| #!/usr/bin/env python |
| # |
| # Copyright (c) 2015, 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 os |
| import os.path |
| import shutil |
| import sys |
| import subprocess |
| |
| import bot |
| import bot_utils |
| |
| utils = bot_utils.GetUtils() |
| |
| BUILD_OS = utils.GuessOS() |
| |
| (bot_name, _) = bot.GetBotName() |
| CHANNEL = bot_utils.GetChannelFromName(bot_name) |
| |
| def BuildSDK(): |
| with bot.BuildStep('Build SDK'): |
| if BUILD_OS == 'linux': |
| sysroot_env = dict(os.environ) |
| sysroot_env['DART_USE_WHEEZY'] = '1' |
| Run([sys.executable, './tools/generate_buildfiles.py'], env=sysroot_env) |
| Run([sys.executable, './tools/build.py', '--mode=release', |
| '--arch=ia32', 'create_sdk']) |
| Run([sys.executable, './tools/build.py', '--mode=release', |
| '--arch=x64', 'create_sdk']) |
| |
| def BuildDartdocAPIDocs(dirname): |
| dart_sdk = os.path.join(bot_utils.DART_DIR, |
| utils.GetBuildRoot(BUILD_OS, 'release', 'ia32'), |
| 'dart-sdk') |
| dart_exe = os.path.join(dart_sdk, 'bin', 'dart') |
| dartdoc_dart = os.path.join(bot_utils.DART_DIR, |
| 'third_party', 'pkg' , 'dartdoc' , 'bin' , |
| 'dartdoc.dart') |
| footer_file = os.path.join(bot_utils.DART_DIR, |
| 'tools', 'bots', 'dartdoc_footer.html') |
| url = 'https://api.dartlang.org/stable' |
| with bot.BuildStep('Build API docs by dartdoc'): |
| bot_utils.run([dart_exe, dartdoc_dart, |
| '--sdk-docs','--output', dirname, '--footer' , footer_file, |
| '--rel-canonical-prefix=' + url]) |
| |
| def CreateUploadVersionFile(): |
| file_path = os.path.join(bot_utils.DART_DIR, |
| utils.GetBuildRoot(BUILD_OS, 'release', 'ia32'), |
| 'VERSION') |
| with open(file_path, 'w') as fd: |
| fd.write(utils.GetVersionFileContent()) |
| DartArchiveUploadVersionFile(file_path) |
| |
| def DartArchiveUploadVersionFile(version_file): |
| namer = bot_utils.GCSNamer(CHANNEL, bot_utils.ReleaseType.RAW) |
| revision = utils.GetArchiveVersion() |
| for revision in [revision, 'latest']: |
| destination = namer.version_filepath(revision) |
| DartArchiveFile(version_file, destination, checksum_files=False) |
| |
| def CreateUploadSDKZips(): |
| with bot.BuildStep('Create and upload sdk zips'): |
| sdk32_path = os.path.join(bot_utils.DART_DIR, |
| utils.GetBuildRoot(BUILD_OS, 'release', 'ia32'), |
| 'dart-sdk') |
| sdk64_path = os.path.join(bot_utils.DART_DIR, |
| utils.GetBuildRoot(BUILD_OS, 'release', 'x64'), |
| 'dart-sdk') |
| |
| sdk32_zip = os.path.join(bot_utils.DART_DIR, |
| utils.GetBuildRoot(BUILD_OS, 'release', 'ia32'), |
| 'dartsdk-%s-32.zip' % BUILD_OS) |
| sdk64_zip = os.path.join(bot_utils.DART_DIR, |
| utils.GetBuildRoot(BUILD_OS, 'release', 'x64'), |
| 'dartsdk-%s-64.zip' % BUILD_OS) |
| FileDelete(sdk32_zip) |
| FileDelete(sdk64_zip) |
| CreateZip(sdk32_path, sdk32_zip) |
| CreateZip(sdk64_path, sdk64_zip) |
| DartArchiveUploadSDKs(BUILD_OS, sdk32_zip, sdk64_zip) |
| |
| def DartArchiveUploadSDKs(system, sdk32_zip, sdk64_zip): |
| namer = bot_utils.GCSNamer(CHANNEL, bot_utils.ReleaseType.RAW) |
| git_number = utils.GetArchiveVersion() |
| git_hash = 'hash/%s' % utils.GetGitRevision() |
| for revision in [git_number, git_hash, 'latest']: |
| path32 = namer.sdk_zipfilepath(revision, system, 'ia32', 'release') |
| path64 = namer.sdk_zipfilepath(revision, system, 'x64', 'release') |
| DartArchiveFile(sdk32_zip, path32, checksum_files=True) |
| DartArchiveFile(sdk64_zip, path64, checksum_files=True) |
| |
| def DartArchiveUnstrippedBinaries(): |
| namer = bot_utils.GCSNamer(CHANNEL, bot_utils.ReleaseType.RAW) |
| revision = utils.GetArchiveVersion() |
| binary = namer.unstripped_filename(BUILD_OS) |
| ia32_binary = os.path.join(bot_utils.DART_DIR, |
| utils.GetBuildRoot(BUILD_OS, 'release', 'ia32'), |
| binary) |
| x64_binary = os.path.join(bot_utils.DART_DIR, |
| utils.GetBuildRoot(BUILD_OS, 'release', 'x64'), |
| binary) |
| gs_ia32_path = namer.unstripped_filepath(revision, BUILD_OS, 'ia32') |
| gs_x64_path = namer.unstripped_filepath(revision, BUILD_OS, 'x64') |
| DartArchiveFile(ia32_binary, gs_ia32_path) |
| DartArchiveFile(x64_binary, gs_x64_path) |
| |
| def CreateUploadSDK(): |
| BuildSDK() |
| CreateUploadSDKZips() |
| DartArchiveUnstrippedBinaries() |
| |
| def CreateUploadAPIDocs(): |
| dartdoc_dir = os.path.join(bot_utils.DART_DIR, |
| utils.GetBuildRoot(BUILD_OS, 'release', 'ia32'), |
| 'gen-dartdocs') |
| dartdoc_zip = os.path.join(bot_utils.DART_DIR, |
| utils.GetBuildRoot(BUILD_OS, 'release', 'ia32'), |
| 'dartdocs-api.zip') |
| if CHANNEL == 'try': |
| BuildDartdocAPIDocs(dartdoc_dir) |
| else: |
| UploadApiLatestFile() |
| BuildDartdocAPIDocs(dartdoc_dir) |
| UploadDartdocApiDocs(dartdoc_dir) |
| CreateZip(dartdoc_dir, dartdoc_zip) |
| DartArchiveUploadDartdocAPIDocs(dartdoc_zip) |
| |
| def DartArchiveUploadDartdocAPIDocs(api_zip): |
| namer = bot_utils.GCSNamer(CHANNEL, bot_utils.ReleaseType.RAW) |
| revision = utils.GetArchiveVersion() |
| for revision in [revision, 'latest']: |
| destination = (namer.apidocs_directory(revision) + '/' + |
| namer.dartdocs_zipfilename()) |
| DartArchiveFile(api_zip, destination, checksum_files=False) |
| |
| def UploadDartdocApiDocs(dir_name): |
| apidocs_namer = bot_utils.GCSNamerApiDocs(CHANNEL) |
| revision = utils.GetArchiveVersion() |
| dartdocs_destination_gcsdir = apidocs_namer.dartdocs_dirpath(revision) |
| |
| # Return early if the documents have already been uploaded. |
| # This can happen if a build was forced, or a commit had no changes in the |
| # dart repository (e.g. DEPS file update). |
| if GsutilExists(dartdocs_destination_gcsdir): |
| print ("Not uploading api docs, since %s is already present." |
| % dartdocs_destination_gcsdir) |
| return |
| |
| # Upload everything inside the built apidocs directory. |
| gsutil = bot_utils.GSUtil() |
| gsutil.upload(dir_name, dartdocs_destination_gcsdir, recursive=True, |
| public=True, multithread=True) |
| |
| def UploadApiLatestFile(): |
| apidocs_namer = bot_utils.GCSNamerApiDocs(CHANNEL) |
| revision = utils.GetArchiveVersion() |
| apidocs_destination_latestfile = apidocs_namer.docs_latestpath(revision) |
| # Update latest.txt to contain the newest revision. |
| with utils.TempDir('latest_file') as temp_dir: |
| latest_file = os.path.join(temp_dir, 'latest.txt') |
| with open(latest_file, 'w') as f: |
| f.write('%s' % revision) |
| DartArchiveFile(latest_file, apidocs_destination_latestfile) |
| |
| def GsutilExists(gsu_path): |
| # This is a little hackish, but it is basically a one off doing very |
| # specialized check that we don't use elsewhere. |
| gsutilTool = os.path.join(bot_utils.DART_DIR, |
| 'third_party', 'gsutil', 'gsutil') |
| (_, stderr, returncode) = bot_utils.run( |
| [gsutilTool, 'ls', gsu_path], |
| throw_on_error=False) |
| # If the returncode is nonzero and we can find a specific error message, |
| # we know there are no objects with a prefix of [gsu_path]. |
| missing = (returncode and 'CommandException: No such object' in stderr) |
| # Either the returncode has to be zero or the object must be missing, |
| # otherwise throw an exception. |
| if not missing and returncode: |
| raise Exception("Failed to determine whether %s exists" % gsu_path) |
| return not missing |
| |
| |
| def CreateZip(directory, target_file): |
| if 'win' in BUILD_OS: |
| CreateZipWindows(directory, target_file) |
| else: |
| CreateZipPosix(directory, target_file) |
| |
| def CreateZipPosix(directory, target_file): |
| with utils.ChangedWorkingDirectory(os.path.dirname(directory)): |
| command = ['zip', '-yrq9', target_file, os.path.basename(directory)] |
| Run(command) |
| |
| def CreateZipWindows(directory, target_file): |
| with utils.ChangedWorkingDirectory(os.path.dirname(directory)): |
| zip_win = os.path.join(bot_utils.DART_DIR, 'third_party', '7zip', '7za') |
| command = [zip_win, 'a', '-tzip', target_file, os.path.basename(directory)] |
| Run(command) |
| |
| def FileDelete(f): |
| if os.path.exists(f): |
| os.remove(f) |
| |
| def DartArchiveFile(local_path, remote_path, checksum_files=False): |
| gsutil = bot_utils.GSUtil() |
| gsutil.upload(local_path, remote_path, public=True) |
| if checksum_files: |
| # 'local_path' may have a different filename than 'remote_path'. So we need |
| # to make sure the *.md5sum file contains the correct name. |
| assert '/' in remote_path and not remote_path.endswith('/') |
| |
| mangled_filename = remote_path[remote_path.rfind('/') + 1:] |
| local_md5sum = bot_utils.CreateMD5ChecksumFile(local_path, |
| mangled_filename) |
| gsutil.upload(local_md5sum, remote_path + '.md5sum', public=True) |
| local_sha256 = bot_utils.CreateSha256ChecksumFile(local_path, |
| mangled_filename) |
| gsutil.upload(local_sha256, remote_path + '.sha256sum', public=True) |
| |
| def Run(command, env=None): |
| print "Running %s" % ' '.join(command) |
| print "Environment %s" % env |
| return bot.RunProcess(command, env=env) |
| |
| if __name__ == '__main__': |
| if len(sys.argv) > 1 and sys.argv[1] == 'api_docs': |
| if BUILD_OS == 'linux': |
| CreateUploadAPIDocs() |
| else: |
| # We always clobber the bot, to make sure releases are build from scratch |
| force = CHANNEL != bot_utils.Channel.BLEEDING_EDGE |
| bot.Clobber(force=force) |
| |
| CreateUploadSDK() |
| if BUILD_OS == 'linux': |
| CreateUploadVersionFile() |