blob: 7bf9398e80081f40dc18ab6e6ca9b51347c06edc [file] [log] [blame]
Mike Frysingere58c0e22017-10-04 15:43:30 -04001# -*- coding: utf-8 -*-
David Rileyc0da9d92016-02-01 12:11:01 -08002# Copyright 2016 The Chromium OS Authors. All rights reserved.
3# Use of this source code is governed by a BSD-style license that can be
4# found in the LICENSE file.
5
6"""This module uprevs Android for cbuildbot.
7
8After calling, it prints outs ANDROID_VERSION_ATOM=(version atom string). A
9caller could then use this atom with emerge to build the newly uprevved version
10of Android e.g.
11
Shuhei Takahashi6d02c192017-04-05 14:01:24 +090012./cros_mark_android_as_stable \
13 --android_package=android-container \
14 --android_build_branch=git_mnc-dr-arc-dev \
15 --android_gts_build_branch=git_mnc-dev
16
David Rileyc0da9d92016-02-01 12:11:01 -080017Returns chromeos-base/android-container-2559197
18
19emerge-veyron_minnie-cheets =chromeos-base/android-container-2559197-r1
20"""
21
22from __future__ import print_function
23
24import filecmp
khmel@google.com778a1cd2018-04-13 11:11:58 -070025import hashlib
David Rileyc0da9d92016-02-01 12:11:01 -080026import glob
27import os
Hidehiko Abe12727dd2016-05-27 23:23:45 +090028import re
khmel@google.com778a1cd2018-04-13 11:11:58 -070029import shutil
30import tempfile
31import subprocess
32import base64
David Rileyc0da9d92016-02-01 12:11:01 -080033
Aviv Keshetb7519e12016-10-04 00:50:00 -070034from chromite.lib import constants
David Rileyc0da9d92016-02-01 12:11:01 -080035from chromite.lib import commandline
36from chromite.lib import cros_build_lib
37from chromite.lib import cros_logging as logging
38from chromite.lib import git
39from chromite.lib import gs
40from chromite.lib import portage_util
41from chromite.scripts import cros_mark_as_stable
42
43
44# Dir where all the action happens.
45_OVERLAY_DIR = '%(srcroot)s/private-overlays/project-cheets-private/'
46
Hidehiko Abe4fd94ae2017-01-24 18:59:55 +090047_GIT_COMMIT_MESSAGE = ('Marking latest for %(android_package)s ebuild '
David Rileyc0da9d92016-02-01 12:11:01 -080048 'with version %(android_version)s as stable.')
49
50# URLs that print lists of Android revisions between two build ids.
51_ANDROID_VERSION_URL = ('http://android-build-uber.corp.google.com/repo.html?'
52 'last_bid=%(old)s&bid=%(new)s&branch=%(branch)s')
53
54
Hidehiko Abe1ebc25d2016-07-28 02:24:37 +090055def IsBuildIdValid(bucket_url, build_branch, build_id, targets):
David Rileyc0da9d92016-02-01 12:11:01 -080056 """Checks that a specific build_id is valid.
57
58 Looks for that build_id for all builds. Confirms that the subpath can
59 be found and that the zip file is present in that subdirectory.
60
61 Args:
62 bucket_url: URL of Android build gs bucket
63 build_branch: branch of Android builds
64 build_id: A string. The Android build id number to check.
Hidehiko Abe1ebc25d2016-07-28 02:24:37 +090065 targets: Dict from build key to (targe build suffix, artifact file pattern)
66 pair.
David Rileyc0da9d92016-02-01 12:11:01 -080067
68 Returns:
69 Returns subpaths dictionary if build_id is valid.
70 None if the build_id is not valid.
71 """
72 gs_context = gs.GSContext()
73 subpaths_dict = {}
Hidehiko Abe1ebc25d2016-07-28 02:24:37 +090074 for build, (target, _) in targets.iteritems():
David Rileyc0da9d92016-02-01 12:11:01 -080075 build_dir = '%s-%s' % (build_branch, target)
76 build_id_path = os.path.join(bucket_url, build_dir, build_id)
77
78 # Find name of subpath.
79 try:
80 subpaths = gs_context.List(build_id_path)
81 except gs.GSNoSuchKey:
82 logging.warn(
83 'Directory [%s] does not contain any subpath, ignoring it.',
84 build_id_path)
85 return None
86 if len(subpaths) > 1:
87 logging.warn(
88 'Directory [%s] contains more than one subpath, ignoring it.',
89 build_id_path)
90 return None
91
92 subpath_dir = subpaths[0].url.rstrip('/')
93 subpath_name = os.path.basename(subpath_dir)
94
95 # Look for a zipfile ending in the build_id number.
96 try:
Hidehiko Abe12727dd2016-05-27 23:23:45 +090097 gs_context.List(subpath_dir)
David Rileyc0da9d92016-02-01 12:11:01 -080098 except gs.GSNoSuchKey:
99 logging.warn(
Hidehiko Abe12727dd2016-05-27 23:23:45 +0900100 'Did not find a file for build id [%s] in directory [%s].',
David Rileyc0da9d92016-02-01 12:11:01 -0800101 build_id, subpath_dir)
102 return None
103
104 # Record subpath for the build.
105 subpaths_dict[build] = subpath_name
106
107 # If we got here, it means we found an appropriate build for all platforms.
108 return subpaths_dict
109
110
Hidehiko Abe1ebc25d2016-07-28 02:24:37 +0900111def GetLatestBuild(bucket_url, build_branch, targets):
David Rileyc0da9d92016-02-01 12:11:01 -0800112 """Searches the gs bucket for the latest green build.
113
114 Args:
115 bucket_url: URL of Android build gs bucket
116 build_branch: branch of Android builds
Hidehiko Abe1ebc25d2016-07-28 02:24:37 +0900117 targets: Dict from build key to (targe build suffix, artifact file pattern)
118 pair.
David Rileyc0da9d92016-02-01 12:11:01 -0800119
120 Returns:
121 Tuple of (latest version string, subpaths dictionary)
122 If no latest build can be found, returns None, None
123 """
124 gs_context = gs.GSContext()
125 common_build_ids = None
126 # Find builds for each target.
Hidehiko Abe1ebc25d2016-07-28 02:24:37 +0900127 for target, _ in targets.itervalues():
David Rileyc0da9d92016-02-01 12:11:01 -0800128 build_dir = '-'.join((build_branch, target))
129 base_path = os.path.join(bucket_url, build_dir)
130 build_ids = []
131 for gs_result in gs_context.List(base_path):
132 # Remove trailing slashes and get the base name, which is the build_id.
133 build_id = os.path.basename(gs_result.url.rstrip('/'))
134 if not build_id.isdigit():
135 logging.warn('Directory [%s] does not look like a valid build_id.',
136 gs_result.url)
137 continue
138 build_ids.append(build_id)
139
140 # Update current list of builds.
141 if common_build_ids is None:
142 # First run, populate it with the first platform.
143 common_build_ids = set(build_ids)
144 else:
145 # Already populated, find the ones that are common.
146 common_build_ids.intersection_update(build_ids)
147
148 if common_build_ids is None:
149 logging.warn('Did not find a build_id common to all platforms.')
150 return None, None
151
152 # Otherwise, find the most recent one that is valid.
153 for build_id in sorted(common_build_ids, key=int, reverse=True):
Hidehiko Abe1ebc25d2016-07-28 02:24:37 +0900154 subpaths = IsBuildIdValid(bucket_url, build_branch, build_id, targets)
David Rileyc0da9d92016-02-01 12:11:01 -0800155 if subpaths:
156 return build_id, subpaths
157
158 # If not found, no build_id is valid.
159 logging.warn('Did not find a build_id valid on all platforms.')
160 return None, None
161
162
163def FindAndroidCandidates(package_dir):
164 """Return a tuple of Android's unstable ebuild and stable ebuilds.
165
166 Args:
167 package_dir: The path to where the package ebuild is stored.
168
169 Returns:
170 Tuple [unstable_ebuild, stable_ebuilds].
171
172 Raises:
173 Exception: if no unstable ebuild exists for Android.
174 """
175 stable_ebuilds = []
176 unstable_ebuilds = []
177 for path in glob.glob(os.path.join(package_dir, '*.ebuild')):
178 ebuild = portage_util.EBuild(path)
179 if ebuild.version == '9999':
180 unstable_ebuilds.append(ebuild)
181 else:
182 stable_ebuilds.append(ebuild)
183
184 # Apply some sanity checks.
185 if not unstable_ebuilds:
186 raise Exception('Missing 9999 ebuild for %s' % package_dir)
187 if not stable_ebuilds:
188 logging.warning('Missing stable ebuild for %s' % package_dir)
189
190 return portage_util.BestEBuild(unstable_ebuilds), stable_ebuilds
191
192
Nicolas Norvezb08f54d2016-12-05 17:58:54 -0800193def _GetArcBasename(build, basename):
194 """Tweaks filenames between Android bucket and ARC++ bucket.
195
196 Android builders create build artifacts with the same name for -user and
197 -userdebug builds, which breaks the android-container ebuild (b/33072485).
198 When copying the artifacts from the Android bucket to the ARC++ bucket some
199 artifacts will be renamed from the usual pattern
200 *cheets_${ARCH}-target_files-S{VERSION}.zip to
201 cheets_${BUILD_NAME}-target_files-S{VERSION}.zip which will typically look
202 like cheets_(${LABEL})*${ARCH}_userdebug-target_files-S{VERSION}.zip.
203
204 Args:
205 build: the build being mirrored, e.g. 'X86', 'ARM', 'X86_USERDEBUG'.
206 basename: the basename of the artifact to copy.
207
208 Returns:
209 The basename of the destination.
210 """
211 if build not in constants.ARC_BUILDS_NEED_ARTIFACTS_RENAMED:
212 return basename
Yūki Ishiief1ada92018-03-27 15:46:15 +0900213 if basename in constants.ARC_ARTIFACTS_RENAME_NOT_NEEDED:
214 return basename
Nicolas Norvezb08f54d2016-12-05 17:58:54 -0800215 to_discard, sep, to_keep = basename.partition('-')
216 if not sep:
217 logging.error(('Build %s: Could not find separator "-" in artifact'
218 ' basename %s'), build, basename)
219 return basename
Bernie Thompson63ed5612017-08-16 12:27:34 -0700220 if 'cheets_' in to_discard:
221 return 'cheets_%s-%s' % (build.lower(), to_keep)
222 elif 'bertha_' in to_discard:
223 return 'bertha_%s-%s' % (build.lower(), to_keep)
224 logging.error('Build %s: Unexpected artifact basename %s',
225 build, basename)
226 return basename
Nicolas Norvezb08f54d2016-12-05 17:58:54 -0800227
228
khmel@google.com778a1cd2018-04-13 11:11:58 -0700229def PackSdkTools(build_branch, build_id, targets, arc_bucket_url):
230 """Creates static SDK tools pack from ARC++ specific bucket.
231
232 Ebuild needs archives to process binaries natively. This collects static SDK
233 tools and packs them to tbz2 archive which can referenced from Android
234 container ebuild file. Pack is placed into the same bucket where SDK tools
235 exist. If pack already exists and up to date then copying is skipped.
236 Otherwise fresh pack is copied.
237
238 Args:
239 build_branch: branch of Android builds
240 build_id: A string. The Android build id number to check.
241 targets: Dict from build key to (targe build suffix, artifact file pattern)
242 pair.
243 arc_bucket_url: URL of the target ARC build gs bucket
244 """
245
246 if not 'SDK_TOOLS' in targets:
247 return
248
249 gs_context = gs.GSContext()
250 target, pattern = targets['SDK_TOOLS']
251 build_dir = '%s-%s' % (build_branch, target)
252 arc_dir = os.path.join(arc_bucket_url, build_dir, build_id)
253
254 sdk_tools_dir = tempfile.mkdtemp()
255
256 try:
257 sdk_tools_bin_dir = os.path.join(sdk_tools_dir, 'bin')
258 os.mkdir(sdk_tools_bin_dir)
259
260 for tool in gs_context.List(arc_dir):
261 if re.search(pattern, tool.url):
262 local_tool_path = os.path.join(sdk_tools_bin_dir,
263 os.path.basename(tool.url))
264 gs_context.Copy(tool.url, local_tool_path, version=0)
265 file_time = int(gs_context.Stat(tool.url).creation_time.strftime('%s'))
266 os.utime(local_tool_path, (file_time, file_time))
267
268 # Fix ./ times to make tar file stable.
269 os.utime(sdk_tools_bin_dir, (0, 0))
270
271 sdk_tools_file_name = 'sdk_tools_%s.tbz2' % build_id
272 sdk_tools_local_path = os.path.join(sdk_tools_dir, sdk_tools_file_name)
273 sdk_tools_target_path = os.path.join(arc_dir, sdk_tools_file_name)
274 subprocess.call(['tar', '--group=root:0', '--owner=root:0',
275 '--create', '--bzip2', '--sort=name',
276 '--file=%s' % sdk_tools_local_path,
277 '--directory=%s' % sdk_tools_bin_dir, '.'])
278
279 if gs_context.Exists(sdk_tools_target_path):
280 # Calculate local md5
281 md5 = hashlib.md5()
282 with open(sdk_tools_local_path, 'rb') as f:
283 while True:
284 buf = f.read(4096)
285 if not buf:
286 break
287 md5.update(buf)
288 md5_local = md5.digest()
289 # Get target md5
290 md5_target = base64.decodestring(
291 gs_context.Stat(sdk_tools_target_path).hash_md5)
292 if md5_local == md5_target:
293 logging.info('SDK tools pack %s is up to date', sdk_tools_target_path)
294 return
295 logging.warning('SDK tools pack %s invalid, removing',
296 sdk_tools_target_path)
297 gs_context.Remove(sdk_tools_target_path)
298
299 logging.info('Creating SDK tools pack %s', sdk_tools_target_path)
300 gs_context.Copy(sdk_tools_local_path, sdk_tools_target_path, version=0)
301 finally:
302 shutil.rmtree(sdk_tools_dir)
303
304
David Riley73f00d92016-02-16 18:54:20 -0800305def CopyToArcBucket(android_bucket_url, build_branch, build_id, subpaths,
Hidehiko Abe1ebc25d2016-07-28 02:24:37 +0900306 targets, arc_bucket_url, acls):
David Riley73f00d92016-02-16 18:54:20 -0800307 """Copies from source Android bucket to ARC++ specific bucket.
308
309 Copies each build to the ARC bucket eliminating the subpath.
310 Applies build specific ACLs for each file.
311
312 Args:
313 android_bucket_url: URL of Android build gs bucket
314 build_branch: branch of Android builds
315 build_id: A string. The Android build id number to check.
316 subpaths: Subpath dictionary for each build to copy.
Hidehiko Abe1ebc25d2016-07-28 02:24:37 +0900317 targets: Dict from build key to (targe build suffix, artifact file pattern)
318 pair.
David Riley73f00d92016-02-16 18:54:20 -0800319 arc_bucket_url: URL of the target ARC build gs bucket
320 acls: ACLs dictionary for each build to copy.
321 """
322 gs_context = gs.GSContext()
323 for build, subpath in subpaths.iteritems():
Hidehiko Abe1ebc25d2016-07-28 02:24:37 +0900324 target, pattern = targets[build]
David Riley73f00d92016-02-16 18:54:20 -0800325 build_dir = '%s-%s' % (build_branch, target)
326 android_dir = os.path.join(android_bucket_url, build_dir, build_id, subpath)
327 arc_dir = os.path.join(arc_bucket_url, build_dir, build_id)
328
Hidehiko Abe12727dd2016-05-27 23:23:45 +0900329 # Copy all target files from android_dir to arc_dir, setting ACLs.
330 for targetfile in gs_context.List(android_dir):
331 if re.search(pattern, targetfile.url):
332 basename = os.path.basename(targetfile.url)
Nicolas Norvezb08f54d2016-12-05 17:58:54 -0800333 arc_path = os.path.join(arc_dir, _GetArcBasename(build, basename))
David Riley73f00d92016-02-16 18:54:20 -0800334 acl = acls[build]
335 needs_copy = True
336
337 # Check a pre-existing file with the original source.
338 if gs_context.Exists(arc_path):
Hidehiko Abe12727dd2016-05-27 23:23:45 +0900339 if (gs_context.Stat(targetfile.url).hash_crc32c !=
Elijah Taylorbfc30692016-04-22 14:05:23 -0700340 gs_context.Stat(arc_path).hash_crc32c):
David Riley73f00d92016-02-16 18:54:20 -0800341 logging.warn('Removing incorrect file %s', arc_path)
342 gs_context.Remove(arc_path)
343 else:
344 logging.info('Skipping already copied file %s', arc_path)
345 needs_copy = False
346
347 # Copy if necessary, and set the ACL unconditionally.
348 # The Stat() call above doesn't verify the ACL is correct and
349 # the ChangeACL should be relatively cheap compared to the copy.
350 # This covers the following caes:
351 # - handling an interrupted copy from a previous run.
352 # - rerunning the copy in case one of the googlestorage_acl_X.txt
353 # files changes (e.g. we add a new variant which reuses a build).
354 if needs_copy:
Hidehiko Abe12727dd2016-05-27 23:23:45 +0900355 logging.info('Copying %s -> %s (acl %s)',
356 targetfile.url, arc_path, acl)
357 gs_context.Copy(targetfile.url, arc_path, version=0)
David Riley73f00d92016-02-16 18:54:20 -0800358 gs_context.ChangeACL(arc_path, acl_args_file=acl)
359
360
Hidehiko Abe1ebc25d2016-07-28 02:24:37 +0900361def MirrorArtifacts(android_bucket_url, android_build_branch, arc_bucket_url,
362 acls, targets, version=None):
363 """Mirrors artifacts from Android bucket to ARC bucket.
364
365 First, this function identifies which build version should be copied,
366 if not given. Please see GetLatestBuild() and IsBuildIdValid() for details.
367
368 On build version identified, then copies target artifacts to the ARC bucket,
369 with setting ACLs.
370
371 Args:
372 android_bucket_url: URL of Android build gs bucket
373 android_build_branch: branch of Android builds
374 arc_bucket_url: URL of the target ARC build gs bucket
375 acls: ACLs dictionary for each build to copy.
376 targets: Dict from build key to (targe build suffix, artifact file pattern)
377 pair.
378 version: (optional) A string. The Android build id number to check.
379 If not passed, detect latest good build version.
380
381 Returns:
382 Mirrored version.
383 """
384 if version:
385 subpaths = IsBuildIdValid(
386 android_bucket_url, android_build_branch, version, targets)
387 if not subpaths:
388 logging.error('Requested build %s is not valid' % version)
389 else:
390 version, subpaths = GetLatestBuild(
391 android_bucket_url, android_build_branch, targets)
392
393 CopyToArcBucket(android_bucket_url, android_build_branch, version, subpaths,
394 targets, arc_bucket_url, acls)
khmel@google.com778a1cd2018-04-13 11:11:58 -0700395 PackSdkTools(android_build_branch, version, targets, arc_bucket_url)
396
Hidehiko Abe1ebc25d2016-07-28 02:24:37 +0900397 return version
398
399
David Riley73f00d92016-02-16 18:54:20 -0800400def MakeAclDict(package_dir):
401 """Creates a dictionary of acl files for each build type.
402
403 Args:
404 package_dir: The path to where the package acl files are stored.
405
406 Returns:
407 Returns acls dictionary.
408 """
409 return dict(
410 (k, os.path.join(package_dir, v))
411 for k, v in constants.ARC_BUCKET_ACLS.items()
412 )
413
414
Nicolas Norvez4bd854f2017-05-23 10:04:45 -0700415def MakeBuildTargetDict(build_branch):
416 """Creates a dictionary of build targets.
417
Bernie Thompson63ed5612017-08-16 12:27:34 -0700418 Not all targets are common between branches, for example
Nicolas Norvez4bd854f2017-05-23 10:04:45 -0700419 sdk_google_cheets_x86 only exists on N.
420 This generates a dictionary listing the available build targets for a
421 specific branch.
422
423 Args:
424 build_branch: branch of Android builds.
425
426 Returns:
427 Returns build target dictionary.
428
429 Raises:
430 ValueError: if the Android build branch is invalid.
431 """
Bernie Thompson54650022018-01-12 10:03:20 -0800432 if build_branch == constants.ANDROID_MST_BUILD_BRANCH:
433 return constants.ANDROID_MST_BUILD_TARGETS
Nicolas Norvez4bd854f2017-05-23 10:04:45 -0700434 elif build_branch == constants.ANDROID_NYC_BUILD_BRANCH:
Bernie Thompson63ed5612017-08-16 12:27:34 -0700435 return constants.ANDROID_NYC_BUILD_TARGETS
Ben Linb8499402018-03-08 16:54:00 -0800436 elif build_branch == constants.ANDROID_PI_BUILD_BRANCH:
437 return constants.ANDROID_PI_BUILD_TARGETS
Nicolas Norvez4bd854f2017-05-23 10:04:45 -0700438 else:
439 raise ValueError('Unknown branch: %s' % build_branch)
Nicolas Norvez4bd854f2017-05-23 10:04:45 -0700440
441
David Rileyc0da9d92016-02-01 12:11:01 -0800442def GetAndroidRevisionListLink(build_branch, old_android, new_android):
443 """Returns a link to the list of revisions between two Android versions
444
445 Given two AndroidEBuilds, generate a link to a page that prints the
446 Android changes between those two revisions, inclusive.
447
448 Args:
449 build_branch: branch of Android builds
450 old_android: ebuild for the version to diff from
451 new_android: ebuild for the version to which to diff
452
453 Returns:
454 The desired URL.
455 """
456 return _ANDROID_VERSION_URL % {'branch': build_branch,
Hidehiko Abec9ecf262017-07-05 15:17:41 +0900457 'old': old_android.version_no_rev,
458 'new': new_android.version_no_rev}
David Rileyc0da9d92016-02-01 12:11:01 -0800459
460
Hidehiko Abe4fd94ae2017-01-24 18:59:55 +0900461def MarkAndroidEBuildAsStable(stable_candidate, unstable_ebuild,
462 android_package, android_version, package_dir,
Nicolas Norvez4bd854f2017-05-23 10:04:45 -0700463 build_branch, arc_bucket_url, build_targets):
David Rileyc0da9d92016-02-01 12:11:01 -0800464 r"""Uprevs the Android ebuild.
465
466 This is the main function that uprevs from a stable candidate
467 to its new version.
468
469 Args:
470 stable_candidate: ebuild that corresponds to the stable ebuild we are
471 revving from. If None, builds the a new ebuild given the version
472 with revision set to 1.
473 unstable_ebuild: ebuild corresponding to the unstable ebuild for Android.
Hidehiko Abe4fd94ae2017-01-24 18:59:55 +0900474 android_package: android package name.
David Rileyc0da9d92016-02-01 12:11:01 -0800475 android_version: The \d+ build id of Android.
David Rileyc0da9d92016-02-01 12:11:01 -0800476 package_dir: Path to the android-container package dir.
David Riley73f00d92016-02-16 18:54:20 -0800477 build_branch: branch of Android builds.
478 arc_bucket_url: URL of the target ARC build gs bucket.
Nicolas Norvez4bd854f2017-05-23 10:04:45 -0700479 build_targets: build targets for this particular Android branch.
David Rileyc0da9d92016-02-01 12:11:01 -0800480
481 Returns:
482 Full portage version atom (including rc's, etc) that was revved.
483 """
484 def IsTheNewEBuildRedundant(new_ebuild, stable_ebuild):
485 """Returns True if the new ebuild is redundant.
486
487 This is True if there if the current stable ebuild is the exact same copy
488 of the new one.
489 """
490 if not stable_ebuild:
491 return False
492
David Riley676f5402016-02-12 17:24:23 -0800493 if stable_candidate.version_no_rev == new_ebuild.version_no_rev:
David Rileyc0da9d92016-02-01 12:11:01 -0800494 return filecmp.cmp(
495 new_ebuild.ebuild_path, stable_ebuild.ebuild_path, shallow=False)
496
497 # Case where we have the last stable candidate with same version just rev.
David Riley676f5402016-02-12 17:24:23 -0800498 if stable_candidate and stable_candidate.version_no_rev == android_version:
David Rileyc0da9d92016-02-01 12:11:01 -0800499 new_ebuild_path = '%s-r%d.ebuild' % (
500 stable_candidate.ebuild_path_no_revision,
501 stable_candidate.current_revision + 1)
502 else:
Hidehiko Abe4fd94ae2017-01-24 18:59:55 +0900503 pf = '%s-%s-r1' % (android_package, android_version)
David Rileyc0da9d92016-02-01 12:11:01 -0800504 new_ebuild_path = os.path.join(package_dir, '%s.ebuild' % pf)
505
David Riley73f00d92016-02-16 18:54:20 -0800506 variables = {'BASE_URL': arc_bucket_url}
Nicolas Norvez4bd854f2017-05-23 10:04:45 -0700507 for build, (target, _) in build_targets.iteritems():
David Riley73f00d92016-02-16 18:54:20 -0800508 variables[build + '_TARGET'] = '%s-%s' % (build_branch, target)
David Rileyc0da9d92016-02-01 12:11:01 -0800509
510 portage_util.EBuild.MarkAsStable(
511 unstable_ebuild.ebuild_path, new_ebuild_path,
512 variables, make_stable=True)
513 new_ebuild = portage_util.EBuild(new_ebuild_path)
514
515 # Determine whether this is ebuild is redundant.
516 if IsTheNewEBuildRedundant(new_ebuild, stable_candidate):
517 msg = 'Previous ebuild with same version found and ebuild is redundant.'
518 logging.info(msg)
519 os.unlink(new_ebuild_path)
520 return None
521
522 if stable_candidate:
523 logging.PrintBuildbotLink('Android revisions',
524 GetAndroidRevisionListLink(build_branch,
525 stable_candidate,
526 new_ebuild))
527
528 git.RunGit(package_dir, ['add', new_ebuild_path])
529 if stable_candidate and not stable_candidate.IsSticky():
530 git.RunGit(package_dir, ['rm', stable_candidate.ebuild_path])
531
532 # Update ebuild manifest and git add it.
533 gen_manifest_cmd = ['ebuild', new_ebuild_path, 'manifest', '--force']
534 cros_build_lib.RunCommand(gen_manifest_cmd,
535 extra_env=None, print_cmd=True)
536 git.RunGit(package_dir, ['add', 'Manifest'])
537
538 portage_util.EBuild.CommitChange(
Hidehiko Abe4fd94ae2017-01-24 18:59:55 +0900539 _GIT_COMMIT_MESSAGE % {'android_package': android_package,
David Rileyc0da9d92016-02-01 12:11:01 -0800540 'android_version': android_version},
541 package_dir)
542
543 return '%s-%s' % (new_ebuild.package, new_ebuild.version)
544
545
546def GetParser():
547 """Creates the argument parser."""
548 parser = commandline.ArgumentParser()
549 parser.add_argument('-b', '--boards')
550 parser.add_argument('--android_bucket_url',
David Riley73f00d92016-02-16 18:54:20 -0800551 default=constants.ANDROID_BUCKET_URL,
552 type='gs_path')
David Rileyc0da9d92016-02-01 12:11:01 -0800553 parser.add_argument('--android_build_branch',
Shuhei Takahashi6d02c192017-04-05 14:01:24 +0900554 required=True,
555 help='Android branch to import from. '
556 'Ex: git_mnc-dr-arc-dev')
Hidehiko Abe1ebc25d2016-07-28 02:24:37 +0900557 parser.add_argument('--android_gts_build_branch',
Shuhei Takahashi6d02c192017-04-05 14:01:24 +0900558 help='Android GTS branch to copy artifacts from. '
559 'Ex: git_mnc-dev')
Hidehiko Abe4fd94ae2017-01-24 18:59:55 +0900560 parser.add_argument('--android_package',
561 default=constants.ANDROID_PACKAGE_NAME)
David Riley73f00d92016-02-16 18:54:20 -0800562 parser.add_argument('--arc_bucket_url',
563 default=constants.ARC_BUCKET_URL,
564 type='gs_path')
David Rileyc0da9d92016-02-01 12:11:01 -0800565 parser.add_argument('-f', '--force_version',
566 help='Android build id to use')
567 parser.add_argument('-s', '--srcroot',
568 default=os.path.join(os.environ['HOME'], 'trunk', 'src'),
569 help='Path to the src directory')
570 parser.add_argument('-t', '--tracking_branch', default='cros/master',
571 help='Branch we are tracking changes against')
572 return parser
573
574
575def main(argv):
Hidehiko Abec9ecf262017-07-05 15:17:41 +0900576 logging.EnableBuildbotMarkers()
David Rileyc0da9d92016-02-01 12:11:01 -0800577 parser = GetParser()
578 options = parser.parse_args(argv)
579 options.Freeze()
580
581 overlay_dir = os.path.abspath(_OVERLAY_DIR % {'srcroot': options.srcroot})
Hidehiko Abe4fd94ae2017-01-24 18:59:55 +0900582 android_package_dir = os.path.join(
583 overlay_dir,
584 portage_util.GetFullAndroidPortagePackageName(options.android_package))
David Rileyc0da9d92016-02-01 12:11:01 -0800585 version_to_uprev = None
David Rileyc0da9d92016-02-01 12:11:01 -0800586
587 (unstable_ebuild, stable_ebuilds) = FindAndroidCandidates(android_package_dir)
David Riley73f00d92016-02-16 18:54:20 -0800588 acls = MakeAclDict(android_package_dir)
Nicolas Norvez4bd854f2017-05-23 10:04:45 -0700589 build_targets = MakeBuildTargetDict(options.android_build_branch)
Hidehiko Abe1ebc25d2016-07-28 02:24:37 +0900590 # Mirror artifacts, i.e., images and some sdk tools (e.g., adb, aapt).
591 version_to_uprev = MirrorArtifacts(options.android_bucket_url,
592 options.android_build_branch,
593 options.arc_bucket_url, acls,
Nicolas Norvez4bd854f2017-05-23 10:04:45 -0700594 build_targets,
Hidehiko Abe1ebc25d2016-07-28 02:24:37 +0900595 options.force_version)
596
597 # Mirror GTS.
Hidehiko Abee8cd06c2017-05-12 23:32:19 +0900598 if options.android_gts_build_branch:
599 MirrorArtifacts(options.android_bucket_url,
600 options.android_gts_build_branch,
601 options.arc_bucket_url, acls,
602 constants.ANDROID_GTS_BUILD_TARGETS)
David Riley73f00d92016-02-16 18:54:20 -0800603
David Rileyc0da9d92016-02-01 12:11:01 -0800604 stable_candidate = portage_util.BestEBuild(stable_ebuilds)
605
606 if stable_candidate:
David Riley676f5402016-02-12 17:24:23 -0800607 logging.info('Stable candidate found %s' % stable_candidate.version)
David Rileyc0da9d92016-02-01 12:11:01 -0800608 else:
609 logging.info('No stable candidate found.')
610
611 tracking_branch = 'remotes/m/%s' % os.path.basename(options.tracking_branch)
612 existing_branch = git.GetCurrentBranch(android_package_dir)
613 work_branch = cros_mark_as_stable.GitBranch(constants.STABLE_EBUILD_BRANCH,
614 tracking_branch,
615 android_package_dir)
616 work_branch.CreateBranch()
617
618 # In the case of uprevving overlays that have patches applied to them,
619 # include the patched changes in the stabilizing branch.
620 if existing_branch:
621 git.RunGit(overlay_dir, ['rebase', existing_branch])
622
623 android_version_atom = MarkAndroidEBuildAsStable(
Hidehiko Abe4fd94ae2017-01-24 18:59:55 +0900624 stable_candidate, unstable_ebuild, options.android_package,
David Riley73f00d92016-02-16 18:54:20 -0800625 version_to_uprev, android_package_dir,
Nicolas Norvez4bd854f2017-05-23 10:04:45 -0700626 options.android_build_branch, options.arc_bucket_url, build_targets)
David Rileyc0da9d92016-02-01 12:11:01 -0800627 if android_version_atom:
628 if options.boards:
629 cros_mark_as_stable.CleanStalePackages(options.srcroot,
630 options.boards.split(':'),
631 [android_version_atom])
632
633 # Explicit print to communicate to caller.
634 print('ANDROID_VERSION_ATOM=%s' % android_version_atom)