| #!/usr/bin/env python2.7 |
| # Copyright 2019 The Fuchsia Authors. All rights reserved. |
| # Use of this source code is governed by a BSD-style license that can be |
| # found in the LICENSE file. |
| |
| ## Roll a new compiler into goma or into Fuchsia |
| |
| ## Usage: See `fx roll-compiler --help` |
| |
| import argparse |
| import json |
| import os |
| import subprocess |
| import sys |
| import tempfile |
| |
| FUCHSIA_DIR = os.path.normpath( |
| os.path.join(__file__, os.pardir, os.pardir, os.pardir, os.pardir)) |
| JIRI_BIN = os.path.join(FUCHSIA_DIR, '.jiri_root', 'bin') |
| CIPD = os.path.join(JIRI_BIN, 'cipd') |
| JIRI = os.path.join(JIRI_BIN, 'jiri') |
| |
| |
| def CallCipd(args): |
| with tempfile.NamedTemporaryFile(mode='r', suffix='.json') as f: |
| cmd = [CIPD] + args + ['-json-output', f.name] |
| with open(os.devnull, 'w') as devnull: |
| subprocess.check_call(cmd, stdout=devnull) |
| return json.load(f)['result'] |
| |
| |
| def ResolvePackage(package, version): |
| return CallCipd(['describe', package, '-version', version]) |
| |
| |
| def main(): |
| parser = argparse.ArgumentParser( |
| 'fx roll-compiler', |
| description='Roll a new compiler into goma or into Fuchsia', |
| epilog=''' |
| With multiple --package switches, all packages must resolve successfully |
| before commands are run for any package. |
| ''') |
| parser.add_argument( |
| 'to', choices=('goma', 'fuchsia'), help='Either "goma" or "fuchsia"') |
| parser.add_argument('version', nargs='?', help='CIPD version to promote') |
| parser.add_argument( |
| '--package', '-p', action='append', help='CIPD package name') |
| parser.add_argument( |
| '--manifest', |
| default=os.path.join( |
| FUCHSIA_DIR, 'integration', 'fuchsia', 'prebuilts'), |
| help='Jiri manifest file to edit') |
| parser.add_argument('--ref', default='goma', help='CIPD ref to publish') |
| parser.add_argument( |
| '--tag', default='git_revision', help='CIPD tag to publish') |
| parser.add_argument( |
| '--platforms', |
| action='append', |
| metavar='PLATFORM', |
| help='CIPD platforms with matching packages') |
| parser.add_argument( |
| '--dry-run', |
| action='store_const', |
| default=False, |
| const=True, |
| help='Only print final command but do not run it') |
| args = parser.parse_args() |
| |
| if args.version is None: |
| # When promoting to Goma (step 1), use the latest package by default. |
| # When promoting to Fuchsia (step 2), use the --ref value, i.e. |
| # the version that was presumably promoted in step 1. |
| args.version = 'latest' if args.to == 'goma' else args.ref |
| |
| if not args.platforms: |
| args.platforms = ['linux-arm64', 'linux-amd64', 'mac-amd64'] |
| |
| if not args.package: |
| args.package = ['fuchsia/third_party/clang'] |
| |
| def PackageTag(package): |
| [tag] = [ |
| tag['tag'] |
| for tag in package['tags'] |
| if tag['tag'].startswith(args.tag + ':') |
| ] |
| return tag |
| |
| def ReifyPackage(package): |
| packages = [ |
| ResolvePackage('%s/%s' % (package, platform), args.version) |
| for platform in args.platforms |
| ] |
| |
| package_tags = { |
| package['pin']['package']: PackageTag(package) |
| for package in packages |
| } |
| tag_set = set(package_tags.itervalues()) |
| if len(tag_set) != 1: |
| sys.stderr.write( |
| 'Not all packages have matching %s tags at version %s:\n' % |
| (args.tag, args.version)) |
| json.dump(package_tags, sys.stderr, sort_keys=True, indent=4) |
| sys.stderr.write('\n') |
| sys.exit(1) |
| [tag] = tag_set |
| |
| print 'Resolved %s (%s) to %s' % (package, args.version, tag) |
| return package, tag |
| |
| def DryRun(args): |
| print args |
| |
| run = DryRun if args.dry_run else subprocess.check_call |
| |
| for package, tag in map(ReifyPackage, args.package): |
| if args.to == 'goma': |
| run( |
| [ |
| CIPD, |
| 'set-ref', |
| package + '/', |
| '-ref', |
| args.ref, |
| '-version', |
| tag, |
| ]) |
| else: |
| run( |
| [ |
| JIRI, |
| 'edit', |
| '-package', |
| '%s/${platform}=%s' % (package, tag), |
| args.manifest, |
| ]) |
| |
| if args.to == 'fuchsia': |
| run([os.path.join(FUCHSIA_DIR, 'integration', 'update-lockfiles.sh')]) |
| |
| return 0 |
| |
| |
| if __name__ == '__main__': |
| sys.exit(main()) |