Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(153)

Unified Diff: tools/signing_script.py

Issue 23442023: Added tools/signing_script.py, used to automate steps before and after the signing step (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 7 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: tools/signing_script.py
diff --git a/tools/signing_script.py b/tools/signing_script.py
new file mode 100755
index 0000000000000000000000000000000000000000..4d45d7a93f3ece8b3191745e1bd26d63837c0ad5
--- /dev/null
+++ b/tools/signing_script.py
@@ -0,0 +1,286 @@
+#!/usr/bin/env python
+#
+# Copyright (c) 2013, 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.
+
+import hashlib
+import imp
+import optparse
+import os
+import subprocess
+import sys
+
+DART_DIR = os.path.dirname(os.path.dirname(__file__))
+GSUTIL = os.path.join(DART_DIR, 'third_party', 'gsutil', 'gsutil')
+BOT_UTILS = os.path.join(DART_DIR, 'tools', 'bots', 'bot_utils.py')
+BASENAME_PATTERN = 'darteditor-%(system)s-%(bits)s'
+FILENAME_PATTERN = BASENAME_PATTERN + '.zip'
+BUCKET_PATTERN = (
+ 'gs://dart-editor-archive-trunk/%(revision)s/' + FILENAME_PATTERN)
+
+DRY_RUN = False
+
+bot_utils = imp.load_source('bot_utils', BOT_UTILS)
+
+class ChangedWorkingDirectory(object):
+ def __init__(self, working_directory):
+ self._working_directory = working_directory
+
+ def __enter__(self):
+ self._old_cwd = os.getcwd()
+ print "Enter directory = ", self._working_directory
+ if not DRY_RUN:
+ os.chdir(self._working_directory)
+
+ def __exit__(self, *_):
+ print "Enter directory = ", self._old_cwd
+ os.chdir(self._old_cwd)
+
+def GetOptionsParser():
+ parser = optparse.OptionParser("usage: %prog [options]")
+ parser.add_option("--scratch-dir",
+ help="Scratch directory to use.")
+ parser.add_option("--revision", type="int",
+ help="Revision we want to sign.")
+ parser.add_option("--channel", type="string",
+ default=None,
+ help="Channel we want to sign.")
+ parser.add_option("--dry-run", action="store_true", dest="dry_run",
+ default=False,
+ help="Do a dry run and do not execute any commands.")
+ parser.add_option("--prepare", action="store_true", dest="prepare",
+ default=False,
+ help="Prepare the .exe/.zip files to sign.")
+ parser.add_option("--deploy", action="store_true", dest="deploy",
+ default=False,
+ help="Pack the signed .exe/.zip files and deploy.")
+ return parser
+
+def die(msg, withOptions=True):
+ print msg
+ if withOptions:
+ GetOptionsParser().print_usage()
+ sys.exit(1)
+
+def run(command):
+ """We use run() instead of builtin python methods, because not all
+ functionality can easily be done by python and we can support --dry-run"""
+
+ print "Running: ", command
+ if not DRY_RUN:
+ process = subprocess.Popen(command,
+ stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE)
+ (stdout, stderr) = process.communicate()
+ if process.returncode != 0:
+ print "DEBUG: failed to run command '%s'" % command
+ print "DEBUG: stdout = ", stdout
+ print "DEBUG: stderr = ", stderr
+ print "DEBUG: returncode = ", process.returncode
+ raise OSError(process.returncode)
+
+def clean_directory(directory):
+ if os.path.exists(directory):
+ run(['rm', '-r', directory])
+ run(['mkdir', '-p', directory])
+
+def rm_tree(directory):
+ if os.path.exists(directory):
+ run(['rm', '-r', directory])
+
+def copy_tree(from_dir, to_dir):
+ if os.path.exists(to_dir):
+ run(['rm', '-r', to_dir])
+ run(['cp', '-Rp', from_dir, to_dir])
+
+def copy_file(from_file, to_file):
+ if os.path.exists(to_file):
+ run(['rm', to_file])
+ run(['cp', '-p', from_file, to_file])
+
+def copy_and_zip(from_dir, to_dir):
+ rm_tree(to_dir)
+ copy_tree(from_dir, to_dir)
+
+ dirname = os.path.basename(to_dir)
+ with ChangedWorkingDirectory(os.path.dirname(to_dir)):
+ run(['zip', '-r9', dirname + '.zip', dirname])
+
+def unzip_and_copy(extracted_zipfiledir, to_dir):
+ rm_tree(extracted_zipfiledir)
+ run(['unzip', extracted_zipfiledir + '.zip', '-d',
+ os.path.dirname(extracted_zipfiledir)])
+ rm_tree(to_dir)
+ copy_tree(extracted_zipfiledir, to_dir)
+
+def download_from_old_location(config, destination):
+ bucket = BUCKET_PATTERN % config
+ run([GSUTIL, 'cp', bucket, destination])
+
+def upload_to_old_location(config, source_zip):
+ if not DRY_RUN:
+ bot_utils.CreateChecksumFile(
+ source_zip, mangled_filename=os.path.basename(source_zip))
+ md5_zip_file = source_zip + '.md5sum'
+
+ bucket = BUCKET_PATTERN % config
+ run([GSUTIL, 'cp', source_zip, bucket])
+ run([GSUTIL, 'cp', md5_zip_file, bucket + '.md5sum'])
+ run([GSUTIL, 'setacl', 'public-read', bucket])
+ run([GSUTIL, 'setacl', 'public-read', bucket + '.md5sum'])
+
+def download_from_new_location(channel, config, destination):
+ namer = bot_utils.GCSNamer(channel,
+ bot_utils.ReleaseType.RAW)
+ bucket = namer.editor_zipfilepath(config['revision'], config['system'],
+ config['bits'])
+ run([GSUTIL, 'cp', bucket, destination])
+
+def upload_to_new_location(channel, config, source_zip):
+ namer = bot_utils.GCSNamer(channel,
+ bot_utils.ReleaseType.SIGNED)
+ zipfilename = namer.editor_zipfilename(config['system'], config['bits'])
+ bucket = namer.editor_zipfilepath(config['revision'], config['system'],
+ config['bits'])
+
+ if not DRY_RUN:
+ bot_utils.CreateChecksumFile(source_zip, mangled_filename=zipfilename)
+ md5_zip_file = source_zip + '.md5sum'
+
+ run([GSUTIL, 'cp', source_zip, bucket])
+ run([GSUTIL, 'cp', md5_zip_file, bucket + '.md5sum'])
+ run([GSUTIL, 'setacl', 'public-read', bucket])
+ run([GSUTIL, 'setacl', 'public-read', bucket + '.md5sum'])
+
+def main():
+ if sys.platform != 'linux2':
+ print "This script was only tested on linux. Please run it on linux!"
+ sys.exit(1)
+
+ parser = GetOptionsParser()
+ (options, args) = parser.parse_args()
+
+ if not options.scratch_dir:
+ die("No scratch directory given.")
+ if not options.revision:
+ die("No revision given.")
+ if not options.prepare and not options.deploy:
+ die("No prepare/deploy parameter given.")
+ if options.prepare and options.deploy:
+ die("Can't have prepare and deploy parameters at the same time.")
+ if len(args) > 0:
+ die("Invalid additional arguments: %s." % args)
+
+ if options.channel:
+ assert options.channel in bot_utils.Channel.ALL_CHANNELS
+
+ global DRY_RUN
+ DRY_RUN = options.dry_run
+
+ downloads_dir = os.path.join(options.scratch_dir, 'downloads')
+ presign_dir = os.path.join(options.scratch_dir, 'presign')
+ postsign_dir = os.path.join(options.scratch_dir, 'postsign')
+ uploads_dir = os.path.join(options.scratch_dir, 'uploads')
+
+ if options.prepare:
+ # Clean all directories
+ clean_directory(downloads_dir)
+ clean_directory(presign_dir)
+ clean_directory(postsign_dir)
+ clean_directory(uploads_dir)
+ elif options.deploy:
+ clean_directory(uploads_dir)
+
+ # These are the locations where we can find the *.app folders and *.exe files
+ # and the names we use inside the scratch directory.
+ locations = {
+ 'macos' : {
+ 'editor' : os.path.join('dart', 'DartEditor.app'),
+ 'chrome' : os.path.join('dart', 'chromium', 'Chromium.app'),
+ 'content_shell' : os.path.join('dart', 'chromium',
+ 'Content Shell.app'),
+
+ 'editor_scratch' : 'DartEditor%(bits)s.app',
+ 'chrome_scratch' : 'Chromium%(bits)s.app',
+ 'content_shell_scratch' : 'ContentShell%(bits)s.app',
+
+ 'zip' : True,
+ },
+ 'win32' : {
+ 'editor' : os.path.join('dart', 'DartEditor.exe'),
+ 'chrome' : os.path.join('dart', 'chromium', 'chrome.exe'),
+ 'content_shell' : os.path.join('dart', 'chromium',
+ 'content_shell.exe'),
+
+ 'editor_scratch' : 'DartEditor%(bits)s.exe',
+ 'chrome_scratch' : 'chromium%(bits)s.exe',
+ 'content_shell_scratch' : 'content_shell%(bits)s.exe',
+
+ 'zip' : False,
+ },
+ }
+
+ # Desitination of zip files we download
+ for system in ('macos', 'win32'):
+ for bits in ('32', '64'):
+ config = {
+ 'revision' : options.revision,
+ 'system' : system,
+ 'bits' : bits,
+ }
+
+ destination = os.path.join(downloads_dir, FILENAME_PATTERN % config)
+ destination_dir = os.path.join(downloads_dir, BASENAME_PATTERN % config)
+
+ deploy = os.path.join(uploads_dir, FILENAME_PATTERN % config)
+ deploy_dir = os.path.join(uploads_dir, BASENAME_PATTERN % config)
+
+ if options.prepare:
+ # Download *.zip files from GCS buckets
+ if options.channel:
+ download_from_new_location(options.channel, config, destination)
+ else:
+ download_from_old_location(config, destination)
+
+ run(['unzip', destination, '-d', destination_dir])
+
+ for name in ['editor', 'chrome', 'content_shell']:
+ from_path = os.path.join(destination_dir, locations[system][name])
+ to_path = os.path.join(
+ presign_dir, locations[system]['%s_scratch' % name] % config)
+
+ if locations[system]['zip']:
+ # We copy a .app directory directory and zip it
+ copy_and_zip(from_path, to_path)
+ else:
+ # We copy an .exe file
+ copy_file(from_path, to_path)
+ elif options.deploy:
+ copy_tree(destination_dir, deploy_dir)
+
+ for name in ['editor', 'chrome', 'content_shell']:
+ from_path = os.path.join(
+ postsign_dir, locations[system]['%s_scratch' % name] % config)
+ to_path = os.path.join(deploy_dir, locations[system][name])
+
+ if locations[system]['zip']:
+ # We unzip a zip file and copy the resulting signed .app directory
+ unzip_and_copy(from_path, to_path)
+ else:
+ # We copy the signed .exe file
+ copy_file(from_path, to_path)
+
+ deploy_zip_file = os.path.abspath(deploy)
+ with ChangedWorkingDirectory(deploy_dir):
+ run(['zip', '-r9', deploy_zip_file, 'dart'])
+
+ # Upload *.zip/*.zip.md5sum and set 'public-read' ACL
+ if options.channel:
+ upload_to_new_location(options.channel, config, deploy_zip_file)
+ else:
+ upload_to_old_location(config, deploy_zip_file)
+
+if __name__ == '__main__':
+ main()
+
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698