Søren Gjesse | e6087bf | 2023-01-17 10:49:29 +0100 | [diff] [blame] | 1 | #!/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 | |
| 6 | import argparse |
| 7 | import os |
| 8 | import re |
| 9 | try: |
Christoffer Quist Adamsen | 2434a4d | 2023-10-16 11:29:03 +0200 | [diff] [blame] | 10 | import resource |
Søren Gjesse | e6087bf | 2023-01-17 10:49:29 +0100 | [diff] [blame] | 11 | except ImportError: |
Christoffer Quist Adamsen | 2434a4d | 2023-10-16 11:29:03 +0200 | [diff] [blame] | 12 | # Not a Unix system. Do what Gandalf tells you not to. |
| 13 | pass |
Søren Gjesse | e6087bf | 2023-01-17 10:49:29 +0100 | [diff] [blame] | 14 | import shutil |
| 15 | import subprocess |
| 16 | import sys |
| 17 | |
Søren Gjesse | 246b11c | 2024-02-07 14:33:27 +0100 | [diff] [blame] | 18 | import jdk |
Søren Gjesse | e6087bf | 2023-01-17 10:49:29 +0100 | [diff] [blame] | 19 | import utils |
| 20 | |
| 21 | ARCHIVE_BUCKET = 'r8-releases' |
| 22 | REPO = 'https://github.com/google/smali' |
| 23 | NO_DRYRUN_OUTPUT = object() |
| 24 | |
Christoffer Quist Adamsen | 2434a4d | 2023-10-16 11:29:03 +0200 | [diff] [blame] | 25 | |
Søren Gjesse | e6087bf | 2023-01-17 10:49:29 +0100 | [diff] [blame] | 26 | def checkout(temp): |
Christoffer Quist Adamsen | 2434a4d | 2023-10-16 11:29:03 +0200 | [diff] [blame] | 27 | subprocess.check_call(['git', 'clone', REPO, temp]) |
| 28 | return temp |
| 29 | |
Søren Gjesse | e6087bf | 2023-01-17 10:49:29 +0100 | [diff] [blame] | 30 | |
Søren Gjesse | e6087bf | 2023-01-17 10:49:29 +0100 | [diff] [blame] | 31 | def parse_options(): |
Christoffer Quist Adamsen | 2434a4d | 2023-10-16 11:29:03 +0200 | [diff] [blame] | 32 | result = argparse.ArgumentParser(description='Release Smali') |
| 33 | result.add_argument('--version', |
| 34 | metavar=('<version>'), |
| 35 | help='The version of smali to archive.') |
| 36 | result.add_argument('--dry-run', |
| 37 | '--dry_run', |
| 38 | nargs='?', |
| 39 | help='Build only, no upload.', |
| 40 | metavar='<output directory>', |
| 41 | default=None, |
| 42 | const=NO_DRYRUN_OUTPUT) |
| 43 | result.add_argument('--checkout', help='Use existing checkout.') |
| 44 | return result.parse_args() |
Søren Gjesse | e6087bf | 2023-01-17 10:49:29 +0100 | [diff] [blame] | 45 | |
| 46 | |
| 47 | def set_rlimit_to_max(): |
Christoffer Quist Adamsen | 2434a4d | 2023-10-16 11:29:03 +0200 | [diff] [blame] | 48 | (soft, hard) = resource.getrlimit(resource.RLIMIT_NOFILE) |
| 49 | resource.setrlimit(resource.RLIMIT_NOFILE, (hard, hard)) |
Søren Gjesse | e6087bf | 2023-01-17 10:49:29 +0100 | [diff] [blame] | 50 | |
| 51 | |
| 52 | def Main(): |
Christoffer Quist Adamsen | 2434a4d | 2023-10-16 11:29:03 +0200 | [diff] [blame] | 53 | options = parse_options() |
| 54 | if not utils.is_bot() and not options.dry_run: |
| 55 | raise Exception('You are not a bot, don\'t archive builds. ' + |
| 56 | 'Use --dry-run to test locally') |
| 57 | if options.checkout and not options.dry_run: |
| 58 | raise Exception('Using local checkout is only allowed with --dry-run') |
| 59 | if not options.checkout and not options.version: |
| 60 | raise Exception( |
| 61 | 'Option --version is required (when not using local checkout)') |
Søren Gjesse | e6087bf | 2023-01-17 10:49:29 +0100 | [diff] [blame] | 62 | |
Christoffer Quist Adamsen | 2434a4d | 2023-10-16 11:29:03 +0200 | [diff] [blame] | 63 | if utils.is_bot() and not utils.IsWindows(): |
| 64 | set_rlimit_to_max() |
Søren Gjesse | e6087bf | 2023-01-17 10:49:29 +0100 | [diff] [blame] | 65 | |
Søren Gjesse | d052837 | 2024-09-13 13:54:28 +0200 | [diff] [blame] | 66 | utils.DownloadFromGoogleCloudStorage(utils.JAVA11_SHA_FILE) |
Christoffer Quist Adamsen | 2434a4d | 2023-10-16 11:29:03 +0200 | [diff] [blame] | 67 | with utils.TempDir() as temp: |
| 68 | # Resolve dry run location to support relative directories. |
| 69 | dry_run_output = None |
| 70 | if options.dry_run and options.dry_run != NO_DRYRUN_OUTPUT: |
| 71 | if not os.path.isdir(options.dry_run): |
| 72 | os.mkdir(options.dry_run) |
| 73 | dry_run_output = os.path.abspath(options.dry_run) |
Søren Gjesse | e6087bf | 2023-01-17 10:49:29 +0100 | [diff] [blame] | 74 | |
Christoffer Quist Adamsen | 2434a4d | 2023-10-16 11:29:03 +0200 | [diff] [blame] | 75 | checkout_dir = options.checkout if options.checkout else checkout(temp) |
| 76 | with utils.ChangedWorkingDirectory(checkout_dir): |
| 77 | if options.version: |
| 78 | output = subprocess.check_output( |
| 79 | ['git', 'tag', '-l', options.version]) |
| 80 | if len(output) == 0: |
| 81 | raise Exception( |
| 82 | 'Repository does not have a release tag for version %s' |
| 83 | % options.version) |
| 84 | subprocess.check_call(['git', 'checkout', options.version]) |
Søren Gjesse | e6087bf | 2023-01-17 10:49:29 +0100 | [diff] [blame] | 85 | |
Christoffer Quist Adamsen | 2434a4d | 2023-10-16 11:29:03 +0200 | [diff] [blame] | 86 | # Find version from `build.gradle`. |
| 87 | for line in open(os.path.join('build.gradle'), 'r'): |
| 88 | result = re.match(r'^version = \'(\d+)\.(\d+)\.(\d+)\'', line) |
| 89 | if result: |
| 90 | break |
| 91 | version = '%s.%s.%s' % (result.group(1), result.group(2), |
| 92 | result.group(3)) |
| 93 | if options.version and version != options.version: |
| 94 | message = 'version %s, expected version %s' % (version, |
| 95 | options.version) |
| 96 | if (options.checkout): |
| 97 | raise Exception('Checkout %s has %s' % |
| 98 | (options.checkout, message)) |
| 99 | else: |
| 100 | raise Exception('Tag % has %s' % (options.version, message)) |
Ian Zerny | 6e65f71 | 2023-02-15 09:46:02 +0100 | [diff] [blame] | 101 | |
Christoffer Quist Adamsen | 2434a4d | 2023-10-16 11:29:03 +0200 | [diff] [blame] | 102 | print('Building version: %s' % version) |
Søren Gjesse | e6087bf | 2023-01-17 10:49:29 +0100 | [diff] [blame] | 103 | |
Søren Gjesse | d052837 | 2024-09-13 13:54:28 +0200 | [diff] [blame] | 104 | # Build release to local Maven repository compiling with JDK-11. |
Christoffer Quist Adamsen | 2434a4d | 2023-10-16 11:29:03 +0200 | [diff] [blame] | 105 | m2 = os.path.join(temp, 'm2') |
| 106 | os.mkdir(m2) |
| 107 | subprocess.check_call([ |
| 108 | './gradlew', |
Søren Gjesse | 740f37d | 2024-12-20 11:06:47 +0100 | [diff] [blame] | 109 | '-Dorg.gradle.java.home=%s' % jdk.GetJdk11Home(), |
Christoffer Quist Adamsen | 2434a4d | 2023-10-16 11:29:03 +0200 | [diff] [blame] | 110 | '-Dmaven.repo.local=%s' % m2, 'release', 'test', |
Søren Gjesse | 246b11c | 2024-02-07 14:33:27 +0100 | [diff] [blame] | 111 | 'publishToMavenLocal', |
Søren Gjesse | 740f37d | 2024-12-20 11:06:47 +0100 | [diff] [blame] | 112 | ]) |
Christoffer Quist Adamsen | 2434a4d | 2023-10-16 11:29:03 +0200 | [diff] [blame] | 113 | base = os.path.join('com', 'android', 'tools', 'smali') |
Søren Gjesse | e6087bf | 2023-01-17 10:49:29 +0100 | [diff] [blame] | 114 | |
Christoffer Quist Adamsen | 2434a4d | 2023-10-16 11:29:03 +0200 | [diff] [blame] | 115 | # Check that the local maven repository only has the single version directory in |
| 116 | # each artifact directory. |
| 117 | for name in [ |
| 118 | 'smali-util', 'smali-dexlib2', 'smali', 'smali-baksmali' |
| 119 | ]: |
| 120 | dirnames = next(os.walk(os.path.join(m2, base, name)), |
| 121 | (None, None, []))[1] |
| 122 | if not dirnames or len(dirnames) != 1 or dirnames[0] != version: |
| 123 | raise Exception('Found unexpected directory %s in %s' % |
| 124 | (dirnames, name)) |
Søren Gjesse | e6087bf | 2023-01-17 10:49:29 +0100 | [diff] [blame] | 125 | |
Christoffer Quist Adamsen | 2434a4d | 2023-10-16 11:29:03 +0200 | [diff] [blame] | 126 | # Build an archive with the relevant content of the local maven repository. |
| 127 | m2_filtered = os.path.join(temp, 'm2_filtered') |
| 128 | shutil.copytree( |
| 129 | m2, |
| 130 | m2_filtered, |
| 131 | ignore=shutil.ignore_patterns('maven-metadata-local.xml')) |
| 132 | maven_release_archive = shutil.make_archive( |
| 133 | 'smali-maven-release-%s' % version, 'zip', m2_filtered, base) |
Søren Gjesse | e6087bf | 2023-01-17 10:49:29 +0100 | [diff] [blame] | 134 | |
Christoffer Quist Adamsen | 2434a4d | 2023-10-16 11:29:03 +0200 | [diff] [blame] | 135 | # Collect names of the fat jars. |
| 136 | fat_jars = list( |
| 137 | map(lambda prefix: '%s-%s-fat.jar' % (prefix, version), |
| 138 | ['smali/build/libs/smali', 'baksmali/build/libs/baksmali'])) |
Søren Gjesse | e6087bf | 2023-01-17 10:49:29 +0100 | [diff] [blame] | 139 | |
Christoffer Quist Adamsen | 2434a4d | 2023-10-16 11:29:03 +0200 | [diff] [blame] | 140 | # Copy artifacts. |
| 141 | files = [maven_release_archive] |
| 142 | files.extend(fat_jars) |
| 143 | if options.dry_run: |
| 144 | if dry_run_output: |
| 145 | print('Dry run, not actually uploading. Copying to %s:' % |
| 146 | dry_run_output) |
| 147 | for file in files: |
| 148 | destination = os.path.join(dry_run_output, |
| 149 | os.path.basename(file)) |
| 150 | shutil.copyfile(file, destination) |
| 151 | print(" %s" % destination) |
| 152 | else: |
| 153 | print('Dry run, not actually uploading. Generated files:') |
| 154 | for file in files: |
| 155 | print(" %s" % os.path.basename(file)) |
| 156 | else: |
| 157 | destination_prefix = 'gs://%s/smali/%s' % (ARCHIVE_BUCKET, |
| 158 | version) |
| 159 | if utils.cloud_storage_exists(destination_prefix): |
| 160 | raise Exception( |
| 161 | 'Target archive directory %s already exists' % |
| 162 | destination_prefix) |
| 163 | for file in files: |
| 164 | destination = '%s/%s' % (destination_prefix, |
| 165 | os.path.basename(file)) |
| 166 | if utils.cloud_storage_exists(destination): |
| 167 | raise Exception('Target %s already exists' % |
| 168 | destination) |
| 169 | utils.upload_file_to_cloud_storage(file, destination) |
| 170 | public_url = 'https://storage.googleapis.com/%s/smali/%s' % ( |
| 171 | ARCHIVE_BUCKET, version) |
| 172 | print('Artifacts available at: %s' % public_url) |
Søren Gjesse | e6087bf | 2023-01-17 10:49:29 +0100 | [diff] [blame] | 173 | |
Christoffer Quist Adamsen | 2434a4d | 2023-10-16 11:29:03 +0200 | [diff] [blame] | 174 | print("Done!") |
| 175 | |
Søren Gjesse | e6087bf | 2023-01-17 10:49:29 +0100 | [diff] [blame] | 176 | |
| 177 | if __name__ == '__main__': |
Christoffer Quist Adamsen | 2434a4d | 2023-10-16 11:29:03 +0200 | [diff] [blame] | 178 | sys.exit(Main()) |