blob: fac42c56f18bc2dc0be1b7983e34a1b89cd936a3 [file] [log] [blame]
Søren Gjessee6087bf2023-01-17 10:49:29 +01001#!/usr/bin/env python3
2# Copyright (c) 2023, the R8 project authors. Please see the AUTHORS file
3# for details. All rights reserved. Use of this source code is governed by a
4# BSD-style license that can be found in the LICENSE file.
5
6import argparse
7import os
8import re
9try:
Christoffer Quist Adamsen2434a4d2023-10-16 11:29:03 +020010 import resource
Søren Gjessee6087bf2023-01-17 10:49:29 +010011except ImportError:
Christoffer Quist Adamsen2434a4d2023-10-16 11:29:03 +020012 # Not a Unix system. Do what Gandalf tells you not to.
13 pass
Søren Gjessee6087bf2023-01-17 10:49:29 +010014import shutil
15import subprocess
16import sys
17
18import utils
19
20ARCHIVE_BUCKET = 'r8-releases'
21REPO = 'https://github.com/google/smali'
22NO_DRYRUN_OUTPUT = object()
23
Christoffer Quist Adamsen2434a4d2023-10-16 11:29:03 +020024
Søren Gjessee6087bf2023-01-17 10:49:29 +010025def checkout(temp):
Christoffer Quist Adamsen2434a4d2023-10-16 11:29:03 +020026 subprocess.check_call(['git', 'clone', REPO, temp])
27 return temp
28
Søren Gjessee6087bf2023-01-17 10:49:29 +010029
Søren Gjessee6087bf2023-01-17 10:49:29 +010030def parse_options():
Christoffer Quist Adamsen2434a4d2023-10-16 11:29:03 +020031 result = argparse.ArgumentParser(description='Release Smali')
32 result.add_argument('--version',
33 metavar=('<version>'),
34 help='The version of smali to archive.')
35 result.add_argument('--dry-run',
36 '--dry_run',
37 nargs='?',
38 help='Build only, no upload.',
39 metavar='<output directory>',
40 default=None,
41 const=NO_DRYRUN_OUTPUT)
42 result.add_argument('--checkout', help='Use existing checkout.')
43 return result.parse_args()
Søren Gjessee6087bf2023-01-17 10:49:29 +010044
45
46def set_rlimit_to_max():
Christoffer Quist Adamsen2434a4d2023-10-16 11:29:03 +020047 (soft, hard) = resource.getrlimit(resource.RLIMIT_NOFILE)
48 resource.setrlimit(resource.RLIMIT_NOFILE, (hard, hard))
Søren Gjessee6087bf2023-01-17 10:49:29 +010049
50
51def Main():
Christoffer Quist Adamsen2434a4d2023-10-16 11:29:03 +020052 options = parse_options()
53 if not utils.is_bot() and not options.dry_run:
54 raise Exception('You are not a bot, don\'t archive builds. ' +
55 'Use --dry-run to test locally')
56 if options.checkout and not options.dry_run:
57 raise Exception('Using local checkout is only allowed with --dry-run')
58 if not options.checkout and not options.version:
59 raise Exception(
60 'Option --version is required (when not using local checkout)')
Søren Gjessee6087bf2023-01-17 10:49:29 +010061
Christoffer Quist Adamsen2434a4d2023-10-16 11:29:03 +020062 if utils.is_bot() and not utils.IsWindows():
63 set_rlimit_to_max()
Søren Gjessee6087bf2023-01-17 10:49:29 +010064
Christoffer Quist Adamsen2434a4d2023-10-16 11:29:03 +020065 with utils.TempDir() as temp:
66 # Resolve dry run location to support relative directories.
67 dry_run_output = None
68 if options.dry_run and options.dry_run != NO_DRYRUN_OUTPUT:
69 if not os.path.isdir(options.dry_run):
70 os.mkdir(options.dry_run)
71 dry_run_output = os.path.abspath(options.dry_run)
Søren Gjessee6087bf2023-01-17 10:49:29 +010072
Christoffer Quist Adamsen2434a4d2023-10-16 11:29:03 +020073 checkout_dir = options.checkout if options.checkout else checkout(temp)
74 with utils.ChangedWorkingDirectory(checkout_dir):
75 if options.version:
76 output = subprocess.check_output(
77 ['git', 'tag', '-l', options.version])
78 if len(output) == 0:
79 raise Exception(
80 'Repository does not have a release tag for version %s'
81 % options.version)
82 subprocess.check_call(['git', 'checkout', options.version])
Søren Gjessee6087bf2023-01-17 10:49:29 +010083
Christoffer Quist Adamsen2434a4d2023-10-16 11:29:03 +020084 # Find version from `build.gradle`.
85 for line in open(os.path.join('build.gradle'), 'r'):
86 result = re.match(r'^version = \'(\d+)\.(\d+)\.(\d+)\'', line)
87 if result:
88 break
89 version = '%s.%s.%s' % (result.group(1), result.group(2),
90 result.group(3))
91 if options.version and version != options.version:
92 message = 'version %s, expected version %s' % (version,
93 options.version)
94 if (options.checkout):
95 raise Exception('Checkout %s has %s' %
96 (options.checkout, message))
97 else:
98 raise Exception('Tag % has %s' % (options.version, message))
Ian Zerny6e65f712023-02-15 09:46:02 +010099
Christoffer Quist Adamsen2434a4d2023-10-16 11:29:03 +0200100 print('Building version: %s' % version)
Søren Gjessee6087bf2023-01-17 10:49:29 +0100101
Christoffer Quist Adamsen2434a4d2023-10-16 11:29:03 +0200102 # Build release to local Maven repository.
103 m2 = os.path.join(temp, 'm2')
104 os.mkdir(m2)
105 subprocess.check_call([
106 './gradlew',
107 '-Dmaven.repo.local=%s' % m2, 'release', 'test',
108 'publishToMavenLocal'
109 ])
110 base = os.path.join('com', 'android', 'tools', 'smali')
Søren Gjessee6087bf2023-01-17 10:49:29 +0100111
Christoffer Quist Adamsen2434a4d2023-10-16 11:29:03 +0200112 # Check that the local maven repository only has the single version directory in
113 # each artifact directory.
114 for name in [
115 'smali-util', 'smali-dexlib2', 'smali', 'smali-baksmali'
116 ]:
117 dirnames = next(os.walk(os.path.join(m2, base, name)),
118 (None, None, []))[1]
119 if not dirnames or len(dirnames) != 1 or dirnames[0] != version:
120 raise Exception('Found unexpected directory %s in %s' %
121 (dirnames, name))
Søren Gjessee6087bf2023-01-17 10:49:29 +0100122
Christoffer Quist Adamsen2434a4d2023-10-16 11:29:03 +0200123 # Build an archive with the relevant content of the local maven repository.
124 m2_filtered = os.path.join(temp, 'm2_filtered')
125 shutil.copytree(
126 m2,
127 m2_filtered,
128 ignore=shutil.ignore_patterns('maven-metadata-local.xml'))
129 maven_release_archive = shutil.make_archive(
130 'smali-maven-release-%s' % version, 'zip', m2_filtered, base)
Søren Gjessee6087bf2023-01-17 10:49:29 +0100131
Christoffer Quist Adamsen2434a4d2023-10-16 11:29:03 +0200132 # Collect names of the fat jars.
133 fat_jars = list(
134 map(lambda prefix: '%s-%s-fat.jar' % (prefix, version),
135 ['smali/build/libs/smali', 'baksmali/build/libs/baksmali']))
Søren Gjessee6087bf2023-01-17 10:49:29 +0100136
Christoffer Quist Adamsen2434a4d2023-10-16 11:29:03 +0200137 # Copy artifacts.
138 files = [maven_release_archive]
139 files.extend(fat_jars)
140 if options.dry_run:
141 if dry_run_output:
142 print('Dry run, not actually uploading. Copying to %s:' %
143 dry_run_output)
144 for file in files:
145 destination = os.path.join(dry_run_output,
146 os.path.basename(file))
147 shutil.copyfile(file, destination)
148 print(" %s" % destination)
149 else:
150 print('Dry run, not actually uploading. Generated files:')
151 for file in files:
152 print(" %s" % os.path.basename(file))
153 else:
154 destination_prefix = 'gs://%s/smali/%s' % (ARCHIVE_BUCKET,
155 version)
156 if utils.cloud_storage_exists(destination_prefix):
157 raise Exception(
158 'Target archive directory %s already exists' %
159 destination_prefix)
160 for file in files:
161 destination = '%s/%s' % (destination_prefix,
162 os.path.basename(file))
163 if utils.cloud_storage_exists(destination):
164 raise Exception('Target %s already exists' %
165 destination)
166 utils.upload_file_to_cloud_storage(file, destination)
167 public_url = 'https://storage.googleapis.com/%s/smali/%s' % (
168 ARCHIVE_BUCKET, version)
169 print('Artifacts available at: %s' % public_url)
Søren Gjessee6087bf2023-01-17 10:49:29 +0100170
Christoffer Quist Adamsen2434a4d2023-10-16 11:29:03 +0200171 print("Done!")
172
Søren Gjessee6087bf2023-01-17 10:49:29 +0100173
174if __name__ == '__main__':
Christoffer Quist Adamsen2434a4d2023-10-16 11:29:03 +0200175 sys.exit(Main())