blob: 59f489aab8ea32a1876c560a8497d91e85ecacd4 [file] [log] [blame]
David Rileyc0da9d92016-02-01 12:11:01 -08001# Copyright 2016 The Chromium OS Authors. All rights reserved.
2# Use of this source code is governed by a BSD-style license that can be
3# found in the LICENSE file.
4
5"""This module uprevs Android for cbuildbot.
6
7After calling, it prints outs ANDROID_VERSION_ATOM=(version atom string). A
8caller could then use this atom with emerge to build the newly uprevved version
9of Android e.g.
10
Shuhei Takahashi6d02c192017-04-05 14:01:24 +090011./cros_mark_android_as_stable \
12 --android_package=android-container \
13 --android_build_branch=git_mnc-dr-arc-dev \
14 --android_gts_build_branch=git_mnc-dev
15
David Rileyc0da9d92016-02-01 12:11:01 -080016Returns chromeos-base/android-container-2559197
17
18emerge-veyron_minnie-cheets =chromeos-base/android-container-2559197-r1
19"""
20
21from __future__ import print_function
22
23import filecmp
24import glob
25import os
Hidehiko Abe12727dd2016-05-27 23:23:45 +090026import re
David Rileyc0da9d92016-02-01 12:11:01 -080027
Aviv Keshetb7519e12016-10-04 00:50:00 -070028from chromite.lib import constants
David Rileyc0da9d92016-02-01 12:11:01 -080029from chromite.lib import commandline
30from chromite.lib import cros_build_lib
31from chromite.lib import cros_logging as logging
32from chromite.lib import git
33from chromite.lib import gs
34from chromite.lib import portage_util
35from chromite.scripts import cros_mark_as_stable
36
37
38# Dir where all the action happens.
39_OVERLAY_DIR = '%(srcroot)s/private-overlays/project-cheets-private/'
40
Hidehiko Abe4fd94ae2017-01-24 18:59:55 +090041_GIT_COMMIT_MESSAGE = ('Marking latest for %(android_package)s ebuild '
David Rileyc0da9d92016-02-01 12:11:01 -080042 'with version %(android_version)s as stable.')
43
44# URLs that print lists of Android revisions between two build ids.
45_ANDROID_VERSION_URL = ('http://android-build-uber.corp.google.com/repo.html?'
46 'last_bid=%(old)s&bid=%(new)s&branch=%(branch)s')
47
Shuhei Takahashi6d02c192017-04-05 14:01:24 +090048# TODO(nya): Check if this default value can be used for NYC uprevs.
49# I'm afraid it's not, but NYC manual uprev instruction does not mention
50# the flag.
51_DEFAULT_ANDROID_GTS_BUILD_BRANCH = 'git_mnc-dev'
52
David Rileyc0da9d92016-02-01 12:11:01 -080053
Hidehiko Abe1ebc25d2016-07-28 02:24:37 +090054def IsBuildIdValid(bucket_url, build_branch, build_id, targets):
David Rileyc0da9d92016-02-01 12:11:01 -080055 """Checks that a specific build_id is valid.
56
57 Looks for that build_id for all builds. Confirms that the subpath can
58 be found and that the zip file is present in that subdirectory.
59
60 Args:
61 bucket_url: URL of Android build gs bucket
62 build_branch: branch of Android builds
63 build_id: A string. The Android build id number to check.
Hidehiko Abe1ebc25d2016-07-28 02:24:37 +090064 targets: Dict from build key to (targe build suffix, artifact file pattern)
65 pair.
David Rileyc0da9d92016-02-01 12:11:01 -080066
67 Returns:
68 Returns subpaths dictionary if build_id is valid.
69 None if the build_id is not valid.
70 """
71 gs_context = gs.GSContext()
72 subpaths_dict = {}
Hidehiko Abe1ebc25d2016-07-28 02:24:37 +090073 for build, (target, _) in targets.iteritems():
David Rileyc0da9d92016-02-01 12:11:01 -080074 build_dir = '%s-%s' % (build_branch, target)
75 build_id_path = os.path.join(bucket_url, build_dir, build_id)
76
77 # Find name of subpath.
78 try:
79 subpaths = gs_context.List(build_id_path)
80 except gs.GSNoSuchKey:
81 logging.warn(
82 'Directory [%s] does not contain any subpath, ignoring it.',
83 build_id_path)
84 return None
85 if len(subpaths) > 1:
86 logging.warn(
87 'Directory [%s] contains more than one subpath, ignoring it.',
88 build_id_path)
89 return None
90
91 subpath_dir = subpaths[0].url.rstrip('/')
92 subpath_name = os.path.basename(subpath_dir)
93
94 # Look for a zipfile ending in the build_id number.
95 try:
Hidehiko Abe12727dd2016-05-27 23:23:45 +090096 gs_context.List(subpath_dir)
David Rileyc0da9d92016-02-01 12:11:01 -080097 except gs.GSNoSuchKey:
98 logging.warn(
Hidehiko Abe12727dd2016-05-27 23:23:45 +090099 'Did not find a file for build id [%s] in directory [%s].',
David Rileyc0da9d92016-02-01 12:11:01 -0800100 build_id, subpath_dir)
101 return None
102
103 # Record subpath for the build.
104 subpaths_dict[build] = subpath_name
105
106 # If we got here, it means we found an appropriate build for all platforms.
107 return subpaths_dict
108
109
Hidehiko Abe1ebc25d2016-07-28 02:24:37 +0900110def GetLatestBuild(bucket_url, build_branch, targets):
David Rileyc0da9d92016-02-01 12:11:01 -0800111 """Searches the gs bucket for the latest green build.
112
113 Args:
114 bucket_url: URL of Android build gs bucket
115 build_branch: branch of Android builds
Hidehiko Abe1ebc25d2016-07-28 02:24:37 +0900116 targets: Dict from build key to (targe build suffix, artifact file pattern)
117 pair.
David Rileyc0da9d92016-02-01 12:11:01 -0800118
119 Returns:
120 Tuple of (latest version string, subpaths dictionary)
121 If no latest build can be found, returns None, None
122 """
123 gs_context = gs.GSContext()
124 common_build_ids = None
125 # Find builds for each target.
Hidehiko Abe1ebc25d2016-07-28 02:24:37 +0900126 for target, _ in targets.itervalues():
David Rileyc0da9d92016-02-01 12:11:01 -0800127 build_dir = '-'.join((build_branch, target))
128 base_path = os.path.join(bucket_url, build_dir)
129 build_ids = []
130 for gs_result in gs_context.List(base_path):
131 # Remove trailing slashes and get the base name, which is the build_id.
132 build_id = os.path.basename(gs_result.url.rstrip('/'))
133 if not build_id.isdigit():
134 logging.warn('Directory [%s] does not look like a valid build_id.',
135 gs_result.url)
136 continue
137 build_ids.append(build_id)
138
139 # Update current list of builds.
140 if common_build_ids is None:
141 # First run, populate it with the first platform.
142 common_build_ids = set(build_ids)
143 else:
144 # Already populated, find the ones that are common.
145 common_build_ids.intersection_update(build_ids)
146
147 if common_build_ids is None:
148 logging.warn('Did not find a build_id common to all platforms.')
149 return None, None
150
151 # Otherwise, find the most recent one that is valid.
152 for build_id in sorted(common_build_ids, key=int, reverse=True):
Hidehiko Abe1ebc25d2016-07-28 02:24:37 +0900153 subpaths = IsBuildIdValid(bucket_url, build_branch, build_id, targets)
David Rileyc0da9d92016-02-01 12:11:01 -0800154 if subpaths:
155 return build_id, subpaths
156
157 # If not found, no build_id is valid.
158 logging.warn('Did not find a build_id valid on all platforms.')
159 return None, None
160
161
162def FindAndroidCandidates(package_dir):
163 """Return a tuple of Android's unstable ebuild and stable ebuilds.
164
165 Args:
166 package_dir: The path to where the package ebuild is stored.
167
168 Returns:
169 Tuple [unstable_ebuild, stable_ebuilds].
170
171 Raises:
172 Exception: if no unstable ebuild exists for Android.
173 """
174 stable_ebuilds = []
175 unstable_ebuilds = []
176 for path in glob.glob(os.path.join(package_dir, '*.ebuild')):
177 ebuild = portage_util.EBuild(path)
178 if ebuild.version == '9999':
179 unstable_ebuilds.append(ebuild)
180 else:
181 stable_ebuilds.append(ebuild)
182
183 # Apply some sanity checks.
184 if not unstable_ebuilds:
185 raise Exception('Missing 9999 ebuild for %s' % package_dir)
186 if not stable_ebuilds:
187 logging.warning('Missing stable ebuild for %s' % package_dir)
188
189 return portage_util.BestEBuild(unstable_ebuilds), stable_ebuilds
190
191
Nicolas Norvezb08f54d2016-12-05 17:58:54 -0800192def _GetArcBasename(build, basename):
193 """Tweaks filenames between Android bucket and ARC++ bucket.
194
195 Android builders create build artifacts with the same name for -user and
196 -userdebug builds, which breaks the android-container ebuild (b/33072485).
197 When copying the artifacts from the Android bucket to the ARC++ bucket some
198 artifacts will be renamed from the usual pattern
199 *cheets_${ARCH}-target_files-S{VERSION}.zip to
200 cheets_${BUILD_NAME}-target_files-S{VERSION}.zip which will typically look
201 like cheets_(${LABEL})*${ARCH}_userdebug-target_files-S{VERSION}.zip.
202
203 Args:
204 build: the build being mirrored, e.g. 'X86', 'ARM', 'X86_USERDEBUG'.
205 basename: the basename of the artifact to copy.
206
207 Returns:
208 The basename of the destination.
209 """
210 if build not in constants.ARC_BUILDS_NEED_ARTIFACTS_RENAMED:
211 return basename
212 to_discard, sep, to_keep = basename.partition('-')
213 if not sep:
214 logging.error(('Build %s: Could not find separator "-" in artifact'
215 ' basename %s'), build, basename)
216 return basename
217 if 'cheets_' not in to_discard:
218 logging.error('Build %s: Unexpected artifact basename %s',
219 build, basename)
220 return basename
221 return 'cheets_%s-%s' % (build.lower(), to_keep)
222
223
David Riley73f00d92016-02-16 18:54:20 -0800224def CopyToArcBucket(android_bucket_url, build_branch, build_id, subpaths,
Hidehiko Abe1ebc25d2016-07-28 02:24:37 +0900225 targets, arc_bucket_url, acls):
David Riley73f00d92016-02-16 18:54:20 -0800226 """Copies from source Android bucket to ARC++ specific bucket.
227
228 Copies each build to the ARC bucket eliminating the subpath.
229 Applies build specific ACLs for each file.
230
231 Args:
232 android_bucket_url: URL of Android build gs bucket
233 build_branch: branch of Android builds
234 build_id: A string. The Android build id number to check.
235 subpaths: Subpath dictionary for each build to copy.
Hidehiko Abe1ebc25d2016-07-28 02:24:37 +0900236 targets: Dict from build key to (targe build suffix, artifact file pattern)
237 pair.
David Riley73f00d92016-02-16 18:54:20 -0800238 arc_bucket_url: URL of the target ARC build gs bucket
239 acls: ACLs dictionary for each build to copy.
240 """
241 gs_context = gs.GSContext()
242 for build, subpath in subpaths.iteritems():
Hidehiko Abe1ebc25d2016-07-28 02:24:37 +0900243 target, pattern = targets[build]
David Riley73f00d92016-02-16 18:54:20 -0800244 build_dir = '%s-%s' % (build_branch, target)
245 android_dir = os.path.join(android_bucket_url, build_dir, build_id, subpath)
246 arc_dir = os.path.join(arc_bucket_url, build_dir, build_id)
247
Hidehiko Abe12727dd2016-05-27 23:23:45 +0900248 # Copy all target files from android_dir to arc_dir, setting ACLs.
249 for targetfile in gs_context.List(android_dir):
250 if re.search(pattern, targetfile.url):
251 basename = os.path.basename(targetfile.url)
Nicolas Norvezb08f54d2016-12-05 17:58:54 -0800252 arc_path = os.path.join(arc_dir, _GetArcBasename(build, basename))
David Riley73f00d92016-02-16 18:54:20 -0800253 acl = acls[build]
254 needs_copy = True
255
256 # Check a pre-existing file with the original source.
257 if gs_context.Exists(arc_path):
Hidehiko Abe12727dd2016-05-27 23:23:45 +0900258 if (gs_context.Stat(targetfile.url).hash_crc32c !=
Elijah Taylorbfc30692016-04-22 14:05:23 -0700259 gs_context.Stat(arc_path).hash_crc32c):
David Riley73f00d92016-02-16 18:54:20 -0800260 logging.warn('Removing incorrect file %s', arc_path)
261 gs_context.Remove(arc_path)
262 else:
263 logging.info('Skipping already copied file %s', arc_path)
264 needs_copy = False
265
266 # Copy if necessary, and set the ACL unconditionally.
267 # The Stat() call above doesn't verify the ACL is correct and
268 # the ChangeACL should be relatively cheap compared to the copy.
269 # This covers the following caes:
270 # - handling an interrupted copy from a previous run.
271 # - rerunning the copy in case one of the googlestorage_acl_X.txt
272 # files changes (e.g. we add a new variant which reuses a build).
273 if needs_copy:
Hidehiko Abe12727dd2016-05-27 23:23:45 +0900274 logging.info('Copying %s -> %s (acl %s)',
275 targetfile.url, arc_path, acl)
276 gs_context.Copy(targetfile.url, arc_path, version=0)
David Riley73f00d92016-02-16 18:54:20 -0800277 gs_context.ChangeACL(arc_path, acl_args_file=acl)
278
279
Hidehiko Abe1ebc25d2016-07-28 02:24:37 +0900280def MirrorArtifacts(android_bucket_url, android_build_branch, arc_bucket_url,
281 acls, targets, version=None):
282 """Mirrors artifacts from Android bucket to ARC bucket.
283
284 First, this function identifies which build version should be copied,
285 if not given. Please see GetLatestBuild() and IsBuildIdValid() for details.
286
287 On build version identified, then copies target artifacts to the ARC bucket,
288 with setting ACLs.
289
290 Args:
291 android_bucket_url: URL of Android build gs bucket
292 android_build_branch: branch of Android builds
293 arc_bucket_url: URL of the target ARC build gs bucket
294 acls: ACLs dictionary for each build to copy.
295 targets: Dict from build key to (targe build suffix, artifact file pattern)
296 pair.
297 version: (optional) A string. The Android build id number to check.
298 If not passed, detect latest good build version.
299
300 Returns:
301 Mirrored version.
302 """
303 if version:
304 subpaths = IsBuildIdValid(
305 android_bucket_url, android_build_branch, version, targets)
306 if not subpaths:
307 logging.error('Requested build %s is not valid' % version)
308 else:
309 version, subpaths = GetLatestBuild(
310 android_bucket_url, android_build_branch, targets)
311
312 CopyToArcBucket(android_bucket_url, android_build_branch, version, subpaths,
313 targets, arc_bucket_url, acls)
314 return version
315
316
David Riley73f00d92016-02-16 18:54:20 -0800317def MakeAclDict(package_dir):
318 """Creates a dictionary of acl files for each build type.
319
320 Args:
321 package_dir: The path to where the package acl files are stored.
322
323 Returns:
324 Returns acls dictionary.
325 """
326 return dict(
327 (k, os.path.join(package_dir, v))
328 for k, v in constants.ARC_BUCKET_ACLS.items()
329 )
330
331
David Rileyc0da9d92016-02-01 12:11:01 -0800332def GetAndroidRevisionListLink(build_branch, old_android, new_android):
333 """Returns a link to the list of revisions between two Android versions
334
335 Given two AndroidEBuilds, generate a link to a page that prints the
336 Android changes between those two revisions, inclusive.
337
338 Args:
339 build_branch: branch of Android builds
340 old_android: ebuild for the version to diff from
341 new_android: ebuild for the version to which to diff
342
343 Returns:
344 The desired URL.
345 """
346 return _ANDROID_VERSION_URL % {'branch': build_branch,
347 'old': old_android.version,
348 'new': new_android.version}
349
350
Hidehiko Abe4fd94ae2017-01-24 18:59:55 +0900351def MarkAndroidEBuildAsStable(stable_candidate, unstable_ebuild,
352 android_package, android_version, package_dir,
353 build_branch, arc_bucket_url):
David Rileyc0da9d92016-02-01 12:11:01 -0800354 r"""Uprevs the Android ebuild.
355
356 This is the main function that uprevs from a stable candidate
357 to its new version.
358
359 Args:
360 stable_candidate: ebuild that corresponds to the stable ebuild we are
361 revving from. If None, builds the a new ebuild given the version
362 with revision set to 1.
363 unstable_ebuild: ebuild corresponding to the unstable ebuild for Android.
Hidehiko Abe4fd94ae2017-01-24 18:59:55 +0900364 android_package: android package name.
David Rileyc0da9d92016-02-01 12:11:01 -0800365 android_version: The \d+ build id of Android.
David Rileyc0da9d92016-02-01 12:11:01 -0800366 package_dir: Path to the android-container package dir.
David Riley73f00d92016-02-16 18:54:20 -0800367 build_branch: branch of Android builds.
368 arc_bucket_url: URL of the target ARC build gs bucket.
David Rileyc0da9d92016-02-01 12:11:01 -0800369
370 Returns:
371 Full portage version atom (including rc's, etc) that was revved.
372 """
373 def IsTheNewEBuildRedundant(new_ebuild, stable_ebuild):
374 """Returns True if the new ebuild is redundant.
375
376 This is True if there if the current stable ebuild is the exact same copy
377 of the new one.
378 """
379 if not stable_ebuild:
380 return False
381
David Riley676f5402016-02-12 17:24:23 -0800382 if stable_candidate.version_no_rev == new_ebuild.version_no_rev:
David Rileyc0da9d92016-02-01 12:11:01 -0800383 return filecmp.cmp(
384 new_ebuild.ebuild_path, stable_ebuild.ebuild_path, shallow=False)
385
386 # Case where we have the last stable candidate with same version just rev.
David Riley676f5402016-02-12 17:24:23 -0800387 if stable_candidate and stable_candidate.version_no_rev == android_version:
David Rileyc0da9d92016-02-01 12:11:01 -0800388 new_ebuild_path = '%s-r%d.ebuild' % (
389 stable_candidate.ebuild_path_no_revision,
390 stable_candidate.current_revision + 1)
391 else:
Hidehiko Abe4fd94ae2017-01-24 18:59:55 +0900392 pf = '%s-%s-r1' % (android_package, android_version)
David Rileyc0da9d92016-02-01 12:11:01 -0800393 new_ebuild_path = os.path.join(package_dir, '%s.ebuild' % pf)
394
David Riley73f00d92016-02-16 18:54:20 -0800395 variables = {'BASE_URL': arc_bucket_url}
Hidehiko Abe12727dd2016-05-27 23:23:45 +0900396 for build, (target, _) in constants.ANDROID_BUILD_TARGETS.iteritems():
David Riley73f00d92016-02-16 18:54:20 -0800397 variables[build + '_TARGET'] = '%s-%s' % (build_branch, target)
David Rileyc0da9d92016-02-01 12:11:01 -0800398
399 portage_util.EBuild.MarkAsStable(
400 unstable_ebuild.ebuild_path, new_ebuild_path,
401 variables, make_stable=True)
402 new_ebuild = portage_util.EBuild(new_ebuild_path)
403
404 # Determine whether this is ebuild is redundant.
405 if IsTheNewEBuildRedundant(new_ebuild, stable_candidate):
406 msg = 'Previous ebuild with same version found and ebuild is redundant.'
407 logging.info(msg)
408 os.unlink(new_ebuild_path)
409 return None
410
411 if stable_candidate:
412 logging.PrintBuildbotLink('Android revisions',
413 GetAndroidRevisionListLink(build_branch,
414 stable_candidate,
415 new_ebuild))
416
417 git.RunGit(package_dir, ['add', new_ebuild_path])
418 if stable_candidate and not stable_candidate.IsSticky():
419 git.RunGit(package_dir, ['rm', stable_candidate.ebuild_path])
420
421 # Update ebuild manifest and git add it.
422 gen_manifest_cmd = ['ebuild', new_ebuild_path, 'manifest', '--force']
423 cros_build_lib.RunCommand(gen_manifest_cmd,
424 extra_env=None, print_cmd=True)
425 git.RunGit(package_dir, ['add', 'Manifest'])
426
427 portage_util.EBuild.CommitChange(
Hidehiko Abe4fd94ae2017-01-24 18:59:55 +0900428 _GIT_COMMIT_MESSAGE % {'android_package': android_package,
David Rileyc0da9d92016-02-01 12:11:01 -0800429 'android_version': android_version},
430 package_dir)
431
432 return '%s-%s' % (new_ebuild.package, new_ebuild.version)
433
434
435def GetParser():
436 """Creates the argument parser."""
437 parser = commandline.ArgumentParser()
438 parser.add_argument('-b', '--boards')
439 parser.add_argument('--android_bucket_url',
David Riley73f00d92016-02-16 18:54:20 -0800440 default=constants.ANDROID_BUCKET_URL,
441 type='gs_path')
David Rileyc0da9d92016-02-01 12:11:01 -0800442 parser.add_argument('--android_build_branch',
Shuhei Takahashi6d02c192017-04-05 14:01:24 +0900443 required=True,
444 help='Android branch to import from. '
445 'Ex: git_mnc-dr-arc-dev')
Hidehiko Abe1ebc25d2016-07-28 02:24:37 +0900446 parser.add_argument('--android_gts_build_branch',
Shuhei Takahashi6d02c192017-04-05 14:01:24 +0900447 default=_DEFAULT_ANDROID_GTS_BUILD_BRANCH,
448 help='Android GTS branch to copy artifacts from. '
449 'Ex: git_mnc-dev')
Hidehiko Abe4fd94ae2017-01-24 18:59:55 +0900450 parser.add_argument('--android_package',
451 default=constants.ANDROID_PACKAGE_NAME)
David Riley73f00d92016-02-16 18:54:20 -0800452 parser.add_argument('--arc_bucket_url',
453 default=constants.ARC_BUCKET_URL,
454 type='gs_path')
David Rileyc0da9d92016-02-01 12:11:01 -0800455 parser.add_argument('-f', '--force_version',
456 help='Android build id to use')
457 parser.add_argument('-s', '--srcroot',
458 default=os.path.join(os.environ['HOME'], 'trunk', 'src'),
459 help='Path to the src directory')
460 parser.add_argument('-t', '--tracking_branch', default='cros/master',
461 help='Branch we are tracking changes against')
462 return parser
463
464
465def main(argv):
466 parser = GetParser()
467 options = parser.parse_args(argv)
468 options.Freeze()
469
470 overlay_dir = os.path.abspath(_OVERLAY_DIR % {'srcroot': options.srcroot})
Hidehiko Abe4fd94ae2017-01-24 18:59:55 +0900471 android_package_dir = os.path.join(
472 overlay_dir,
473 portage_util.GetFullAndroidPortagePackageName(options.android_package))
David Rileyc0da9d92016-02-01 12:11:01 -0800474 version_to_uprev = None
David Rileyc0da9d92016-02-01 12:11:01 -0800475
476 (unstable_ebuild, stable_ebuilds) = FindAndroidCandidates(android_package_dir)
David Riley73f00d92016-02-16 18:54:20 -0800477 acls = MakeAclDict(android_package_dir)
Hidehiko Abe1ebc25d2016-07-28 02:24:37 +0900478 # Mirror artifacts, i.e., images and some sdk tools (e.g., adb, aapt).
479 version_to_uprev = MirrorArtifacts(options.android_bucket_url,
480 options.android_build_branch,
481 options.arc_bucket_url, acls,
482 constants.ANDROID_BUILD_TARGETS,
483 options.force_version)
484
485 # Mirror GTS.
486 MirrorArtifacts(options.android_bucket_url,
487 options.android_gts_build_branch,
488 options.arc_bucket_url, acls,
489 constants.ANDROID_GTS_BUILD_TARGETS)
David Riley73f00d92016-02-16 18:54:20 -0800490
David Rileyc0da9d92016-02-01 12:11:01 -0800491 stable_candidate = portage_util.BestEBuild(stable_ebuilds)
492
493 if stable_candidate:
David Riley676f5402016-02-12 17:24:23 -0800494 logging.info('Stable candidate found %s' % stable_candidate.version)
David Rileyc0da9d92016-02-01 12:11:01 -0800495 else:
496 logging.info('No stable candidate found.')
497
498 tracking_branch = 'remotes/m/%s' % os.path.basename(options.tracking_branch)
499 existing_branch = git.GetCurrentBranch(android_package_dir)
500 work_branch = cros_mark_as_stable.GitBranch(constants.STABLE_EBUILD_BRANCH,
501 tracking_branch,
502 android_package_dir)
503 work_branch.CreateBranch()
504
505 # In the case of uprevving overlays that have patches applied to them,
506 # include the patched changes in the stabilizing branch.
507 if existing_branch:
508 git.RunGit(overlay_dir, ['rebase', existing_branch])
509
510 android_version_atom = MarkAndroidEBuildAsStable(
Hidehiko Abe4fd94ae2017-01-24 18:59:55 +0900511 stable_candidate, unstable_ebuild, options.android_package,
David Riley73f00d92016-02-16 18:54:20 -0800512 version_to_uprev, android_package_dir,
513 options.android_build_branch, options.arc_bucket_url)
David Rileyc0da9d92016-02-01 12:11:01 -0800514 if android_version_atom:
515 if options.boards:
516 cros_mark_as_stable.CleanStalePackages(options.srcroot,
517 options.boards.split(':'),
518 [android_version_atom])
519
520 # Explicit print to communicate to caller.
521 print('ANDROID_VERSION_ATOM=%s' % android_version_atom)