blob: ed7e9e35c511babcfc649781e965d109d0557e88 [file] [log] [blame]
#!/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())