Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 #!/usr/bin/python | |
| 2 | |
| 3 # Copyright (c) 2014 The Chromium Authors. All rights reserved. | |
| 4 # Use of this source code is governed by a BSD-style license that can be | |
| 5 # found in the LICENSE file. | |
| 6 | |
| 7 """Steps to archive dartium, content_shell, and chromedriver from buildbots. | |
| 8 | |
| 9 Imported by buildbot_annotated_steps.py and multivm_archive.py | |
| 10 """ | |
| 11 | |
| 12 import imp | |
| 13 import os | |
| 14 import platform | |
| 15 import re | |
| 16 import subprocess | |
| 17 import sys | |
| 18 | |
| 19 import archive | |
| 20 | |
| 21 BUILDER_NAME = 'BUILDBOT_BUILDERNAME' | |
| 22 REVISION = 'BUILDBOT_REVISION' | |
| 23 BUILDER_PATTERN = (r'^(dartium|multivm)-(mac|lucid64|lucid32|win)' | |
| 24 r'-(full|inc|debug|build)(-ninja)?(-(be|dev|stable|integration))?$') | |
| 25 | |
| 26 if platform.system() == 'Windows': | |
| 27 GSUTIL = 'e:/b/build/scripts/slave/gsutil.bat' | |
| 28 else: | |
| 29 GSUTIL = '/b/build/scripts/slave/gsutil' | |
| 30 ACL = 'public-read' | |
| 31 GS_SITE = 'gs://' | |
| 32 GS_URL = 'https://sandbox.google.com/storage/' | |
| 33 GS_DIR = 'dartium-archive' | |
| 34 LATEST = 'latest' | |
| 35 CONTINUOUS = 'continuous' | |
| 36 | |
| 37 SRC_PATH = os.path.dirname( | |
|
ricow1
2014/05/14 17:28:18
as mentioned elsewhere, this should be in utils I
| |
| 38 os.path.dirname( | |
| 39 os.path.dirname( | |
| 40 os.path.dirname(os.path.abspath(__file__))))) | |
| 41 DART_PATH = os.path.join(SRC_PATH, 'dart') | |
| 42 | |
| 43 bot_utils = imp.load_source('bot_utils', | |
| 44 os.path.join(DART_PATH, 'tools', 'bots', 'bot_utils.py')) | |
| 45 | |
| 46 class BuildInfo(object): | |
| 47 """ | |
| 48 name: A name for the build - the buildbot host if a buildbot. | |
| 49 mode: 'Debug' or 'Release' | |
| 50 arch: target architecture | |
| 51 channel: the channel this build is happening on | |
| 52 is_full: True if this is a full build. | |
| 53 is_incremental: True if this is an incremental build. | |
| 54 is_build: True if this is a builder for the performance testers. | |
| 55 is_win_ninja: True if this is a ninja build on Windows. | |
| 56 | |
| 57 """ | |
| 58 def __init__(self, revision, version): | |
| 59 | |
| 60 self.revision = revision | |
| 61 self.version = version | |
| 62 # Populate via builder environment variables. | |
| 63 self.name = os.environ[BUILDER_NAME] | |
| 64 # Temporary hack, until we rename the FYI bots. | |
| 65 # We should eventually rename all to linux32 and linux64. | |
| 66 self.name = self.name.replace('-linux-', '-lucid64-') | |
| 67 | |
| 68 self.is_incremental = '-inc' in self.name | |
| 69 self.is_win_ninja = 'win-inc-ninja' in self.name | |
| 70 pattern = re.match(BUILDER_PATTERN, self.name) | |
| 71 assert pattern | |
| 72 self.arch = 'x64' if pattern.group(2) == 'lucid64' else 'ia32' | |
| 73 self.mode = 'Debug' if pattern.group(3) == 'debug' else 'Release' | |
| 74 self.is_full = pattern.group(3) == 'full' | |
| 75 self.is_build = pattern.group(3) == 'build' | |
| 76 self.channel = pattern.group(6) if pattern.group(6) else 'be' | |
| 77 | |
| 78 | |
| 79 def ArchiveAndUpload(info, archive_latest=False): | |
| 80 print '@@@BUILD_STEP dartium_generate_archive@@@' | |
| 81 cwd = os.getcwd() | |
| 82 | |
| 83 dartium_bucket = info.name | |
| 84 dartium_bucket = dartium_bucket.replace('multivm', 'multivm-dartium') | |
| 85 drt_bucket = dartium_bucket.replace('dartium', 'drt') | |
| 86 chromedriver_bucket = dartium_bucket.replace('dartium', 'chromedriver') | |
| 87 dartium_archive = dartium_bucket + '-' + info.version | |
| 88 drt_archive = drt_bucket + '-' + info.version | |
| 89 chromedriver_archive = chromedriver_bucket + '-' + info.version | |
| 90 dartium_zip, drt_zip, chromedriver_zip = archive.Archive( | |
| 91 SRC_PATH, | |
| 92 info.mode, | |
| 93 dartium_archive, | |
| 94 drt_archive, | |
| 95 chromedriver_archive, | |
| 96 is_win_ninja=info.is_win_ninja) | |
| 97 | |
| 98 status = 0 | |
| 99 # Upload bleeding-edge builds to old dartium-archive bucket | |
| 100 if info.channel == 'be': | |
|
ricow1
2014/05/14 17:28:18
that is true, we upload bleeding edge to the old b
Bill Hesse
2014/05/15 10:46:37
We also upload bleeding-edge to the new buckets.
| |
| 101 status = (OldUpload('dartium', dartium_bucket, | |
| 102 os.path.abspath(dartium_zip), | |
| 103 archive_latest=archive_latest) | |
| 104 or OldUpload('drt', drt_bucket, | |
| 105 os.path.abspath(drt_zip), | |
| 106 archive_latest=archive_latest) | |
| 107 or OldUpload('chromedriver', chromedriver_bucket, | |
| 108 os.path.abspath(chromedriver_zip), | |
| 109 archive_latest=archive_latest)) | |
| 110 | |
| 111 # Upload to new dart-archive bucket using GCSNamer, but not incremental | |
| 112 # or perf builder builds. | |
| 113 if not info.is_incremental and not info.is_build: | |
| 114 Upload('dartium', os.path.abspath(dartium_zip), | |
| 115 info, archive_latest=archive_latest) | |
| 116 Upload('drt', os.path.abspath(drt_zip), | |
| 117 info, archive_latest=archive_latest) | |
| 118 Upload('chromedriver', os.path.abspath(chromedriver_zip), | |
| 119 info, archive_latest=archive_latest) | |
| 120 | |
| 121 os.chdir(cwd) | |
| 122 if status != 0: | |
| 123 print '@@@STEP_FAILURE@@@' | |
| 124 return status | |
| 125 | |
| 126 | |
| 127 def OldUpload(module, bucket, zip_file, archive_latest=False): | |
| 128 """Upload a zip file to the old bucket gs://dartium-archive/ | |
| 129 """ | |
| 130 # TODO(whesse): Remove the old archiving code (OldUpload, OldUploadFile, | |
| 131 # and constants they use) once everything points to the new location. | |
| 132 status = 0 | |
| 133 _, filename = os.path.split(zip_file) | |
| 134 if not archive_latest: | |
| 135 target = '/'.join([GS_DIR, bucket, filename]) | |
| 136 print '@@@BUILD_STEP %s_upload_archive_old@@@' % module | |
| 137 status = OldUploadFile(zip_file, GS_SITE + target) | |
| 138 print '@@@STEP_LINK@download@' + GS_URL + target + '@@@' | |
| 139 else: | |
| 140 print '@@@BUILD_STEP %s_upload_latest_old@@@' % module | |
| 141 # Clear latest for this build type. | |
| 142 old = '/'.join([GS_DIR, LATEST, bucket + '-*']) | |
| 143 old_archives = ListArchives(GS_SITE + old) | |
| 144 | |
| 145 # Upload the new latest and remove unnecessary old ones. | |
| 146 target = GS_SITE + '/'.join([GS_DIR, LATEST, filename]) | |
| 147 status = OldUploadFile(zip_file, target) | |
| 148 if status == 0: | |
| 149 RemoveArchives( | |
| 150 [iarch for iarch in old_archives if iarch != target]) | |
| 151 else: | |
| 152 print 'Upload failed' | |
| 153 | |
| 154 # Upload unversioned name to continuous site for incremental | |
| 155 # builds. | |
| 156 if '-inc' in bucket: | |
| 157 continuous_name = bucket[:bucket.find('-inc')] | |
| 158 target = GS_SITE + '/'.join([GS_DIR, CONTINUOUS, | |
| 159 continuous_name + '.zip']) | |
| 160 status = OldUploadFile(zip_file, target) | |
| 161 | |
| 162 print ('@@@BUILD_STEP %s_upload_archive is over (status = %s)@@@' % | |
| 163 (module, status)) | |
| 164 return status | |
| 165 | |
| 166 | |
| 167 def Upload(module, zip_file, info, archive_latest=False): | |
| 168 """Upload a zip file to cloud storage bucket gs://dart-archive/ | |
| 169 """ | |
| 170 print '@@@BUILD_STEP %s_upload_archive @@@' % module | |
| 171 revision = 'latest' if archive_latest else info.revision | |
| 172 name = module.replace('drt', 'content_shell') | |
| 173 namer = bot_utils.GCSNamer(info.channel, bot_utils.ReleaseType.RAW) | |
| 174 remote_path = namer.dartium_variant_zipfilepath(revision, | |
| 175 name, | |
| 176 sys.platform, | |
| 177 info.arch, | |
| 178 info.mode.lower()) | |
| 179 UploadFile(zip_file, remote_path, create_md5sum=True) | |
| 180 | |
| 181 print '@@@STEP_LINK@download@' + remote_path + '@@@' | |
| 182 | |
| 183 | |
| 184 def OldUploadFile(source, target): | |
| 185 """Upload an archive zip file to Google storage. | |
| 186 """ | |
| 187 | |
| 188 # Upload file. | |
| 189 cmd = [GSUTIL, 'cp', source, target] | |
| 190 (status, output) = ExecuteCommand(cmd) | |
| 191 if status != 0: | |
| 192 return status | |
| 193 print 'Uploaded: ' + output | |
| 194 | |
| 195 # Set ACL. | |
| 196 if ACL is not None: | |
| 197 cmd = [GSUTIL, 'setacl', ACL, target] | |
| 198 (status, output) = ExecuteCommand(cmd) | |
| 199 return status | |
| 200 | |
| 201 | |
| 202 def UploadFile(local_path, remote_path, create_md5sum=False): | |
| 203 # Copy it to the new unified gs://dart-archive bucket | |
| 204 gsutil = bot_utils.GSUtil() | |
| 205 gsutil.upload(local_path, remote_path, public=True) | |
| 206 if create_md5sum: | |
| 207 # 'local_path' may have a different filename than 'remote_path'. So we need | |
| 208 # to make sure the *.md5sum file contains the correct name. | |
| 209 assert '/' in remote_path and not remote_path.endswith('/') | |
| 210 mangled_filename = remote_path[remote_path.rfind('/') + 1:] | |
| 211 local_md5sum = bot_utils.CreateChecksumFile(local_path, mangled_filename) | |
| 212 gsutil.upload(local_md5sum, remote_path + '.md5sum', public=True) | |
| 213 | |
| 214 | |
| 215 def ExecuteCommand(cmd): | |
| 216 """Execute a command in a subprocess. | |
| 217 """ | |
| 218 print 'Executing: ' + ' '.join(cmd) | |
| 219 try: | |
| 220 pipe = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE) | |
| 221 (output, error) = pipe.communicate() | |
| 222 if pipe.returncode != 0: | |
| 223 print 'Execution failed: ' + str(error) | |
| 224 return (pipe.returncode, output) | |
| 225 except: | |
| 226 import traceback | |
| 227 print 'Execution raised exception:', traceback.format_exc() | |
| 228 return (-1, '') | |
| 229 | |
| 230 | |
| 231 def UploadDartTestsResults(layout_test_results_dir, name, version, | |
| 232 component, checked): | |
| 233 """Uploads test results to google storage. | |
| 234 """ | |
| 235 print ('@@@BUILD_STEP archive %s_layout_%s_tests results@@@' % | |
| 236 (component, checked)) | |
| 237 dir_name = os.path.dirname(layout_test_results_dir) | |
| 238 base_name = os.path.basename(layout_test_results_dir) | |
| 239 cwd = os.getcwd() | |
| 240 os.chdir(dir_name) | |
| 241 | |
| 242 archive_name = 'layout_test_results.zip' | |
| 243 archive.ZipDir(archive_name, base_name) | |
| 244 | |
| 245 target = '/'.join([GS_DIR, 'layout-test-results', name, component + '-' + | |
| 246 checked + '-' + version + '.zip']) | |
| 247 status = OldUploadFile(os.path.abspath(archive_name), GS_SITE + target) | |
| 248 os.remove(archive_name) | |
| 249 if status == 0: | |
| 250 print ('@@@STEP_LINK@download@' + GS_URL + target + '@@@') | |
| 251 else: | |
| 252 print '@@@STEP_FAILURE@@@' | |
| 253 os.chdir(cwd) | |
| 254 | |
| 255 | |
| 256 def ListArchives(pattern): | |
| 257 """List the contents in Google storage matching the file pattern. | |
| 258 """ | |
| 259 cmd = [GSUTIL, 'ls', pattern] | |
| 260 (status, output) = ExecuteCommand(cmd) | |
| 261 if status != 0: | |
| 262 return [] | |
| 263 return output.split(os.linesep) | |
| 264 | |
| 265 | |
| 266 def RemoveArchives(archives): | |
| 267 """Remove the list of archives in Google storage. | |
| 268 """ | |
| 269 for archive in archives: | |
| 270 if archive.find(GS_SITE) == 0: | |
| 271 cmd = [GSUTIL, 'rm', archive.rstrip()] | |
| 272 (status, _) = ExecuteCommand(cmd) | |
| 273 if status != 0: | |
| 274 return status | |
| 275 return 0 | |
| OLD | NEW |