mirror of
https://github.com/dart-lang/sdk
synced 2024-11-02 12:24:24 +00:00
e9c3eebef1
Copy the signed SDK directory to release first (if it exists). Then copy only those unsigned files that have no signed counterparts. * Add --version alias and remove SVN reference from --revision help. * Fix --dry-run. * Add new base_directory to GCS namer. b/139027087 Change-Id: I4163eb56494bfa92ab1e5686cf089136d63881fe Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/115860 Reviewed-by: William Hesse <whesse@google.com>
185 lines
6.4 KiB
Python
185 lines
6.4 KiB
Python
#!/usr/bin/env python
|
|
#
|
|
# Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
|
|
# for details. All rights reserved. Use of this source code is governed by a
|
|
# BSD-style license that can be found in the LICENSE file.
|
|
|
|
# Dart SDK promote tools.
|
|
|
|
import imp
|
|
import optparse
|
|
import os
|
|
import subprocess
|
|
import sys
|
|
import time
|
|
import urllib
|
|
import bots.bot_utils as bot_utils
|
|
|
|
from os.path import join
|
|
|
|
DART_PATH = os.path.abspath(os.path.join(__file__, '..', '..'))
|
|
DRY_RUN = False
|
|
|
|
|
|
def BuildOptions():
|
|
usage = """usage: %prog promote [options]
|
|
where:
|
|
promote - Will promote builds from raw/signed locations to release
|
|
locations.
|
|
|
|
Example: Promote version 2.5.0 on the stable channel:
|
|
python editor/build/promote.py promote --channel=stable --version=2.5.0
|
|
"""
|
|
|
|
result = optparse.OptionParser(usage=usage)
|
|
|
|
group = optparse.OptionGroup(result, 'Promote',
|
|
'options used to promote code')
|
|
group.add_option(
|
|
'--revision',
|
|
'--version',
|
|
help='The version to promote',
|
|
action='store')
|
|
group.add_option(
|
|
'--channel',
|
|
type='string',
|
|
help='The channel to promote.',
|
|
default=None)
|
|
group.add_option(
|
|
"--dry", help='Dry run', default=False, action="store_true")
|
|
result.add_option_group(group)
|
|
|
|
return result
|
|
|
|
|
|
def main():
|
|
parser = BuildOptions()
|
|
(options, args) = parser.parse_args()
|
|
|
|
def die(msg):
|
|
print msg
|
|
parser.print_help()
|
|
sys.exit(1)
|
|
|
|
if not args:
|
|
die('At least one command must be specified')
|
|
|
|
if args[0] == 'promote':
|
|
command = 'promote'
|
|
if options.revision is None:
|
|
die('You must specify a --revision to specify which revision to promote'
|
|
)
|
|
|
|
# Make sure options.channel is a valid
|
|
if not options.channel:
|
|
die('Specify --channel=be/dev/stable')
|
|
if options.channel not in bot_utils.Channel.ALL_CHANNELS:
|
|
die('You must supply a valid channel to --channel to promote')
|
|
else:
|
|
die('Invalid command specified: {0}. See help below'.format(args[0]))
|
|
|
|
if options.dry:
|
|
global DRY_RUN
|
|
DRY_RUN = True
|
|
if command == 'promote':
|
|
_PromoteDartArchiveBuild(options.channel, options.revision)
|
|
|
|
|
|
def UpdateDocs():
|
|
try:
|
|
print 'Updating docs'
|
|
url = "http://api.dartlang.org/docs/releases/latest/?force_reload=true"
|
|
f = urllib.urlopen(url)
|
|
f.read()
|
|
print 'Successfully updated api docs'
|
|
except Exception as e:
|
|
print 'Could not update api docs, please manually update them'
|
|
print 'Failed with: %s' % e
|
|
|
|
|
|
def _PromoteDartArchiveBuild(channel, revision):
|
|
# These namer objects will be used to create GCS object URIs. For the
|
|
# structure we use, please see tools/bots/bot_utils.py:GCSNamer
|
|
raw_namer = bot_utils.GCSNamer(channel, bot_utils.ReleaseType.RAW)
|
|
signed_namer = bot_utils.GCSNamer(channel, bot_utils.ReleaseType.SIGNED)
|
|
release_namer = bot_utils.GCSNamer(channel, bot_utils.ReleaseType.RELEASE)
|
|
|
|
def promote(to_revision):
|
|
|
|
def safety_check_on_gs_path(gs_path, revision, channel):
|
|
if not (revision != None and len(channel) > 0 and
|
|
('%s' % revision) in gs_path and channel in gs_path):
|
|
raise Exception(
|
|
"InternalError: Sanity check failed on GS URI: %s" %
|
|
gs_path)
|
|
|
|
def exists(gs_path):
|
|
(_, _, exit_code) = Gsutil(['ls', gs_path], throw_on_error=False)
|
|
# gsutil will exit 0 if the "directory" exists
|
|
return exit_code == 0
|
|
|
|
# Google cloud storage has read-after-write, read-after-update,
|
|
# and read-after-delete consistency, but not list after delete consistency.
|
|
# Because gsutil uses list to figure out if it should do the unix styly
|
|
# copy to or copy into, this means that if the directory is reported as
|
|
# still being there (after it has been deleted) gsutil will copy
|
|
# into the directory instead of to the directory.
|
|
def wait_for_delete_to_be_consistent_with_list(gs_path):
|
|
if DRY_RUN:
|
|
return
|
|
while exists(gs_path):
|
|
time.sleep(1)
|
|
|
|
def remove_gs_directory(gs_path):
|
|
safety_check_on_gs_path(gs_path, to_revision, channel)
|
|
# Only delete existing directories
|
|
if exists(gs_path):
|
|
Gsutil(['-m', 'rm', '-R', '-f', gs_path])
|
|
wait_for_delete_to_be_consistent_with_list(gs_path)
|
|
|
|
# Copy the signed sdk directory.
|
|
from_loc = signed_namer.sdk_directory(revision)
|
|
to_loc = release_namer.sdk_directory(to_revision)
|
|
remove_gs_directory(to_loc)
|
|
has_signed = exists(from_loc)
|
|
if has_signed:
|
|
Gsutil(['-m', 'cp', '-a', 'public-read', '-R', from_loc, to_loc])
|
|
# Because gsutil copies differently to existing directories, we need
|
|
# to use the base directory for the next recursive copy.
|
|
to_loc = release_namer.base_directory(to_revision)
|
|
|
|
# Copy the unsigned sdk directory without clobbering signed files.
|
|
from_loc = raw_namer.sdk_directory(revision)
|
|
Gsutil(['-m', 'cp', '-n', '-a', 'public-read', '-R', from_loc, to_loc])
|
|
|
|
# Copy api-docs zipfile.
|
|
from_loc = raw_namer.apidocs_zipfilepath(revision)
|
|
to_loc = release_namer.apidocs_zipfilepath(to_revision)
|
|
Gsutil(['-m', 'cp', '-a', 'public-read', from_loc, to_loc])
|
|
|
|
# Copy wheezy linux deb and src packages.
|
|
from_loc = raw_namer.linux_packages_directory(revision)
|
|
to_loc = release_namer.linux_packages_directory(to_revision)
|
|
remove_gs_directory(to_loc)
|
|
Gsutil(['-m', 'cp', '-a', 'public-read', '-R', from_loc, to_loc])
|
|
|
|
# Copy VERSION file.
|
|
from_loc = raw_namer.version_filepath(revision)
|
|
to_loc = release_namer.version_filepath(to_revision)
|
|
Gsutil(['cp', '-a', 'public-read', from_loc, to_loc])
|
|
|
|
promote(revision)
|
|
promote('latest')
|
|
|
|
|
|
def Gsutil(cmd, throw_on_error=True):
|
|
gsutilTool = join(DART_PATH, 'third_party', 'gsutil', 'gsutil')
|
|
command = [sys.executable, gsutilTool] + cmd
|
|
if DRY_RUN:
|
|
print "DRY runnning: %s" % command
|
|
return (None, None, 0)
|
|
return bot_utils.run(command, throw_on_error=throw_on_error)
|
|
|
|
|
|
if __name__ == '__main__':
|
|
sys.exit(main())
|