blob: 19da90f2588ea8a617122397849de78a8f866f14 [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
48
Hidehiko Abe1ebc25d2016-07-28 02:24:37 +090049def IsBuildIdValid(bucket_url, build_branch, build_id, targets):
David Rileyc0da9d92016-02-01 12:11:01 -080050 """Checks that a specific build_id is valid.
51
52 Looks for that build_id for all builds. Confirms that the subpath can
53 be found and that the zip file is present in that subdirectory.
54
55 Args:
56 bucket_url: URL of Android build gs bucket
57 build_branch: branch of Android builds
58 build_id: A string. The Android build id number to check.
Hidehiko Abe1ebc25d2016-07-28 02:24:37 +090059 targets: Dict from build key to (targe build suffix, artifact file pattern)
60 pair.
David Rileyc0da9d92016-02-01 12:11:01 -080061
62 Returns:
63 Returns subpaths dictionary if build_id is valid.
64 None if the build_id is not valid.
65 """
66 gs_context = gs.GSContext()
67 subpaths_dict = {}
Hidehiko Abe1ebc25d2016-07-28 02:24:37 +090068 for build, (target, _) in targets.iteritems():
David Rileyc0da9d92016-02-01 12:11:01 -080069 build_dir = '%s-%s' % (build_branch, target)
70 build_id_path = os.path.join(bucket_url, build_dir, build_id)
71
72 # Find name of subpath.
73 try:
74 subpaths = gs_context.List(build_id_path)
75 except gs.GSNoSuchKey:
76 logging.warn(
77 'Directory [%s] does not contain any subpath, ignoring it.',
78 build_id_path)
79 return None
80 if len(subpaths) > 1:
81 logging.warn(
82 'Directory [%s] contains more than one subpath, ignoring it.',
83 build_id_path)
84 return None
85
86 subpath_dir = subpaths[0].url.rstrip('/')
87 subpath_name = os.path.basename(subpath_dir)
88
89 # Look for a zipfile ending in the build_id number.
90 try:
Hidehiko Abe12727dd2016-05-27 23:23:45 +090091 gs_context.List(subpath_dir)
David Rileyc0da9d92016-02-01 12:11:01 -080092 except gs.GSNoSuchKey:
93 logging.warn(
Hidehiko Abe12727dd2016-05-27 23:23:45 +090094 'Did not find a file for build id [%s] in directory [%s].',
David Rileyc0da9d92016-02-01 12:11:01 -080095 build_id, subpath_dir)
96 return None
97
98 # Record subpath for the build.
99 subpaths_dict[build] = subpath_name
100
101 # If we got here, it means we found an appropriate build for all platforms.
102 return subpaths_dict
103
104
Hidehiko Abe1ebc25d2016-07-28 02:24:37 +0900105def GetLatestBuild(bucket_url, build_branch, targets):
David Rileyc0da9d92016-02-01 12:11:01 -0800106 """Searches the gs bucket for the latest green build.
107
108 Args:
109 bucket_url: URL of Android build gs bucket
110 build_branch: branch of Android builds
Hidehiko Abe1ebc25d2016-07-28 02:24:37 +0900111 targets: Dict from build key to (targe build suffix, artifact file pattern)
112 pair.
David Rileyc0da9d92016-02-01 12:11:01 -0800113
114 Returns:
115 Tuple of (latest version string, subpaths dictionary)
116 If no latest build can be found, returns None, None
117 """
118 gs_context = gs.GSContext()
119 common_build_ids = None
120 # Find builds for each target.
Hidehiko Abe1ebc25d2016-07-28 02:24:37 +0900121 for target, _ in targets.itervalues():
David Rileyc0da9d92016-02-01 12:11:01 -0800122 build_dir = '-'.join((build_branch, target))
123 base_path = os.path.join(bucket_url, build_dir)
124 build_ids = []
125 for gs_result in gs_context.List(base_path):
126 # Remove trailing slashes and get the base name, which is the build_id.
127 build_id = os.path.basename(gs_result.url.rstrip('/'))
128 if not build_id.isdigit():
129 logging.warn('Directory [%s] does not look like a valid build_id.',
130 gs_result.url)
131 continue
132 build_ids.append(build_id)
133
134 # Update current list of builds.
135 if common_build_ids is None:
136 # First run, populate it with the first platform.
137 common_build_ids = set(build_ids)
138 else:
139 # Already populated, find the ones that are common.
140 common_build_ids.intersection_update(build_ids)
141
142 if common_build_ids is None:
143 logging.warn('Did not find a build_id common to all platforms.')
144 return None, None
145
146 # Otherwise, find the most recent one that is valid.
147 for build_id in sorted(common_build_ids, key=int, reverse=True):
Hidehiko Abe1ebc25d2016-07-28 02:24:37 +0900148 subpaths = IsBuildIdValid(bucket_url, build_branch, build_id, targets)
David Rileyc0da9d92016-02-01 12:11:01 -0800149 if subpaths:
150 return build_id, subpaths
151
152 # If not found, no build_id is valid.
153 logging.warn('Did not find a build_id valid on all platforms.')
154 return None, None
155
156
157def FindAndroidCandidates(package_dir):
158 """Return a tuple of Android's unstable ebuild and stable ebuilds.
159
160 Args:
161 package_dir: The path to where the package ebuild is stored.
162
163 Returns:
164 Tuple [unstable_ebuild, stable_ebuilds].
165
166 Raises:
167 Exception: if no unstable ebuild exists for Android.
168 """
169 stable_ebuilds = []
170 unstable_ebuilds = []
171 for path in glob.glob(os.path.join(package_dir, '*.ebuild')):
172 ebuild = portage_util.EBuild(path)
173 if ebuild.version == '9999':
174 unstable_ebuilds.append(ebuild)
175 else:
176 stable_ebuilds.append(ebuild)
177
178 # Apply some sanity checks.
179 if not unstable_ebuilds:
180 raise Exception('Missing 9999 ebuild for %s' % package_dir)
181 if not stable_ebuilds:
182 logging.warning('Missing stable ebuild for %s' % package_dir)
183
184 return portage_util.BestEBuild(unstable_ebuilds), stable_ebuilds
185
186
Nicolas Norvezb08f54d2016-12-05 17:58:54 -0800187def _GetArcBasename(build, basename):
188 """Tweaks filenames between Android bucket and ARC++ bucket.
189
190 Android builders create build artifacts with the same name for -user and
191 -userdebug builds, which breaks the android-container ebuild (b/33072485).
192 When copying the artifacts from the Android bucket to the ARC++ bucket some
193 artifacts will be renamed from the usual pattern
194 *cheets_${ARCH}-target_files-S{VERSION}.zip to
195 cheets_${BUILD_NAME}-target_files-S{VERSION}.zip which will typically look
196 like cheets_(${LABEL})*${ARCH}_userdebug-target_files-S{VERSION}.zip.
197
198 Args:
199 build: the build being mirrored, e.g. 'X86', 'ARM', 'X86_USERDEBUG'.
200 basename: the basename of the artifact to copy.
201
202 Returns:
203 The basename of the destination.
204 """
205 if build not in constants.ARC_BUILDS_NEED_ARTIFACTS_RENAMED:
206 return basename
207 to_discard, sep, to_keep = basename.partition('-')
208 if not sep:
209 logging.error(('Build %s: Could not find separator "-" in artifact'
210 ' basename %s'), build, basename)
211 return basename
212 if 'cheets_' not in to_discard:
213 logging.error('Build %s: Unexpected artifact basename %s',
214 build, basename)
215 return basename
216 return 'cheets_%s-%s' % (build.lower(), to_keep)
217
218
David Riley73f00d92016-02-16 18:54:20 -0800219def CopyToArcBucket(android_bucket_url, build_branch, build_id, subpaths,
Hidehiko Abe1ebc25d2016-07-28 02:24:37 +0900220 targets, arc_bucket_url, acls):
David Riley73f00d92016-02-16 18:54:20 -0800221 """Copies from source Android bucket to ARC++ specific bucket.
222
223 Copies each build to the ARC bucket eliminating the subpath.
224 Applies build specific ACLs for each file.
225
226 Args:
227 android_bucket_url: URL of Android build gs bucket
228 build_branch: branch of Android builds
229 build_id: A string. The Android build id number to check.
230 subpaths: Subpath dictionary for each build to copy.
Hidehiko Abe1ebc25d2016-07-28 02:24:37 +0900231 targets: Dict from build key to (targe build suffix, artifact file pattern)
232 pair.
David Riley73f00d92016-02-16 18:54:20 -0800233 arc_bucket_url: URL of the target ARC build gs bucket
234 acls: ACLs dictionary for each build to copy.
235 """
236 gs_context = gs.GSContext()
237 for build, subpath in subpaths.iteritems():
Hidehiko Abe1ebc25d2016-07-28 02:24:37 +0900238 target, pattern = targets[build]
David Riley73f00d92016-02-16 18:54:20 -0800239 build_dir = '%s-%s' % (build_branch, target)
240 android_dir = os.path.join(android_bucket_url, build_dir, build_id, subpath)
241 arc_dir = os.path.join(arc_bucket_url, build_dir, build_id)
242
Hidehiko Abe12727dd2016-05-27 23:23:45 +0900243 # Copy all target files from android_dir to arc_dir, setting ACLs.
244 for targetfile in gs_context.List(android_dir):
245 if re.search(pattern, targetfile.url):
246 basename = os.path.basename(targetfile.url)
Nicolas Norvezb08f54d2016-12-05 17:58:54 -0800247 arc_path = os.path.join(arc_dir, _GetArcBasename(build, basename))
David Riley73f00d92016-02-16 18:54:20 -0800248 acl = acls[build]
249 needs_copy = True
250
251 # Check a pre-existing file with the original source.
252 if gs_context.Exists(arc_path):
Hidehiko Abe12727dd2016-05-27 23:23:45 +0900253 if (gs_context.Stat(targetfile.url).hash_crc32c !=
Elijah Taylorbfc30692016-04-22 14:05:23 -0700254 gs_context.Stat(arc_path).hash_crc32c):
David Riley73f00d92016-02-16 18:54:20 -0800255 logging.warn('Removing incorrect file %s', arc_path)
256 gs_context.Remove(arc_path)
257 else:
258 logging.info('Skipping already copied file %s', arc_path)
259 needs_copy = False
260
261 # Copy if necessary, and set the ACL unconditionally.
262 # The Stat() call above doesn't verify the ACL is correct and
263 # the ChangeACL should be relatively cheap compared to the copy.
264 # This covers the following caes:
265 # - handling an interrupted copy from a previous run.
266 # - rerunning the copy in case one of the googlestorage_acl_X.txt
267 # files changes (e.g. we add a new variant which reuses a build).
268 if needs_copy:
Hidehiko Abe12727dd2016-05-27 23:23:45 +0900269 logging.info('Copying %s -> %s (acl %s)',
270 targetfile.url, arc_path, acl)
271 gs_context.Copy(targetfile.url, arc_path, version=0)
David Riley73f00d92016-02-16 18:54:20 -0800272 gs_context.ChangeACL(arc_path, acl_args_file=acl)
273
274
Hidehiko Abe1ebc25d2016-07-28 02:24:37 +0900275def MirrorArtifacts(android_bucket_url, android_build_branch, arc_bucket_url,
276 acls, targets, version=None):
277 """Mirrors artifacts from Android bucket to ARC bucket.
278
279 First, this function identifies which build version should be copied,
280 if not given. Please see GetLatestBuild() and IsBuildIdValid() for details.
281
282 On build version identified, then copies target artifacts to the ARC bucket,
283 with setting ACLs.
284
285 Args:
286 android_bucket_url: URL of Android build gs bucket
287 android_build_branch: branch of Android builds
288 arc_bucket_url: URL of the target ARC build gs bucket
289 acls: ACLs dictionary for each build to copy.
290 targets: Dict from build key to (targe build suffix, artifact file pattern)
291 pair.
292 version: (optional) A string. The Android build id number to check.
293 If not passed, detect latest good build version.
294
295 Returns:
296 Mirrored version.
297 """
298 if version:
299 subpaths = IsBuildIdValid(
300 android_bucket_url, android_build_branch, version, targets)
301 if not subpaths:
302 logging.error('Requested build %s is not valid' % version)
303 else:
304 version, subpaths = GetLatestBuild(
305 android_bucket_url, android_build_branch, targets)
306
307 CopyToArcBucket(android_bucket_url, android_build_branch, version, subpaths,
308 targets, arc_bucket_url, acls)
309 return version
310
311
David Riley73f00d92016-02-16 18:54:20 -0800312def MakeAclDict(package_dir):
313 """Creates a dictionary of acl files for each build type.
314
315 Args:
316 package_dir: The path to where the package acl files are stored.
317
318 Returns:
319 Returns acls dictionary.
320 """
321 return dict(
322 (k, os.path.join(package_dir, v))
323 for k, v in constants.ARC_BUCKET_ACLS.items()
324 )
325
326
Nicolas Norvez4bd854f2017-05-23 10:04:45 -0700327def MakeBuildTargetDict(build_branch):
328 """Creates a dictionary of build targets.
329
330 Not all targets are common between M and N branches, for example
331 sdk_google_cheets_x86 only exists on N.
332 This generates a dictionary listing the available build targets for a
333 specific branch.
334
335 Args:
336 build_branch: branch of Android builds.
337
338 Returns:
339 Returns build target dictionary.
340
341 Raises:
342 ValueError: if the Android build branch is invalid.
343 """
344 d = constants.ANDROID_COMMON_BUILD_TARGETS.copy()
345 if build_branch == constants.ANDROID_MNC_BUILD_BRANCH:
346 d.update(constants.ANDROID_MNC_BUILD_TARGETS)
347 elif build_branch == constants.ANDROID_NYC_BUILD_BRANCH:
348 d.update(constants.ANDROID_NYC_BUILD_TARGETS)
349 else:
350 raise ValueError('Unknown branch: %s' % build_branch)
351 return d
352
353
David Rileyc0da9d92016-02-01 12:11:01 -0800354def GetAndroidRevisionListLink(build_branch, old_android, new_android):
355 """Returns a link to the list of revisions between two Android versions
356
357 Given two AndroidEBuilds, generate a link to a page that prints the
358 Android changes between those two revisions, inclusive.
359
360 Args:
361 build_branch: branch of Android builds
362 old_android: ebuild for the version to diff from
363 new_android: ebuild for the version to which to diff
364
365 Returns:
366 The desired URL.
367 """
368 return _ANDROID_VERSION_URL % {'branch': build_branch,
369 'old': old_android.version,
370 'new': new_android.version}
371
372
Hidehiko Abe4fd94ae2017-01-24 18:59:55 +0900373def MarkAndroidEBuildAsStable(stable_candidate, unstable_ebuild,
374 android_package, android_version, package_dir,
Nicolas Norvez4bd854f2017-05-23 10:04:45 -0700375 build_branch, arc_bucket_url, build_targets):
David Rileyc0da9d92016-02-01 12:11:01 -0800376 r"""Uprevs the Android ebuild.
377
378 This is the main function that uprevs from a stable candidate
379 to its new version.
380
381 Args:
382 stable_candidate: ebuild that corresponds to the stable ebuild we are
383 revving from. If None, builds the a new ebuild given the version
384 with revision set to 1.
385 unstable_ebuild: ebuild corresponding to the unstable ebuild for Android.
Hidehiko Abe4fd94ae2017-01-24 18:59:55 +0900386 android_package: android package name.
David Rileyc0da9d92016-02-01 12:11:01 -0800387 android_version: The \d+ build id of Android.
David Rileyc0da9d92016-02-01 12:11:01 -0800388 package_dir: Path to the android-container package dir.
David Riley73f00d92016-02-16 18:54:20 -0800389 build_branch: branch of Android builds.
390 arc_bucket_url: URL of the target ARC build gs bucket.
Nicolas Norvez4bd854f2017-05-23 10:04:45 -0700391 build_targets: build targets for this particular Android branch.
David Rileyc0da9d92016-02-01 12:11:01 -0800392
393 Returns:
394 Full portage version atom (including rc's, etc) that was revved.
395 """
396 def IsTheNewEBuildRedundant(new_ebuild, stable_ebuild):
397 """Returns True if the new ebuild is redundant.
398
399 This is True if there if the current stable ebuild is the exact same copy
400 of the new one.
401 """
402 if not stable_ebuild:
403 return False
404
David Riley676f5402016-02-12 17:24:23 -0800405 if stable_candidate.version_no_rev == new_ebuild.version_no_rev:
David Rileyc0da9d92016-02-01 12:11:01 -0800406 return filecmp.cmp(
407 new_ebuild.ebuild_path, stable_ebuild.ebuild_path, shallow=False)
408
409 # Case where we have the last stable candidate with same version just rev.
David Riley676f5402016-02-12 17:24:23 -0800410 if stable_candidate and stable_candidate.version_no_rev == android_version:
David Rileyc0da9d92016-02-01 12:11:01 -0800411 new_ebuild_path = '%s-r%d.ebuild' % (
412 stable_candidate.ebuild_path_no_revision,
413 stable_candidate.current_revision + 1)
414 else:
Hidehiko Abe4fd94ae2017-01-24 18:59:55 +0900415 pf = '%s-%s-r1' % (android_package, android_version)
David Rileyc0da9d92016-02-01 12:11:01 -0800416 new_ebuild_path = os.path.join(package_dir, '%s.ebuild' % pf)
417
David Riley73f00d92016-02-16 18:54:20 -0800418 variables = {'BASE_URL': arc_bucket_url}
Nicolas Norvez4bd854f2017-05-23 10:04:45 -0700419 for build, (target, _) in build_targets.iteritems():
David Riley73f00d92016-02-16 18:54:20 -0800420 variables[build + '_TARGET'] = '%s-%s' % (build_branch, target)
David Rileyc0da9d92016-02-01 12:11:01 -0800421
422 portage_util.EBuild.MarkAsStable(
423 unstable_ebuild.ebuild_path, new_ebuild_path,
424 variables, make_stable=True)
425 new_ebuild = portage_util.EBuild(new_ebuild_path)
426
427 # Determine whether this is ebuild is redundant.
428 if IsTheNewEBuildRedundant(new_ebuild, stable_candidate):
429 msg = 'Previous ebuild with same version found and ebuild is redundant.'
430 logging.info(msg)
431 os.unlink(new_ebuild_path)
432 return None
433
434 if stable_candidate:
435 logging.PrintBuildbotLink('Android revisions',
436 GetAndroidRevisionListLink(build_branch,
437 stable_candidate,
438 new_ebuild))
439
440 git.RunGit(package_dir, ['add', new_ebuild_path])
441 if stable_candidate and not stable_candidate.IsSticky():
442 git.RunGit(package_dir, ['rm', stable_candidate.ebuild_path])
443
444 # Update ebuild manifest and git add it.
445 gen_manifest_cmd = ['ebuild', new_ebuild_path, 'manifest', '--force']
446 cros_build_lib.RunCommand(gen_manifest_cmd,
447 extra_env=None, print_cmd=True)
448 git.RunGit(package_dir, ['add', 'Manifest'])
449
450 portage_util.EBuild.CommitChange(
Hidehiko Abe4fd94ae2017-01-24 18:59:55 +0900451 _GIT_COMMIT_MESSAGE % {'android_package': android_package,
David Rileyc0da9d92016-02-01 12:11:01 -0800452 'android_version': android_version},
453 package_dir)
454
455 return '%s-%s' % (new_ebuild.package, new_ebuild.version)
456
457
458def GetParser():
459 """Creates the argument parser."""
460 parser = commandline.ArgumentParser()
461 parser.add_argument('-b', '--boards')
462 parser.add_argument('--android_bucket_url',
David Riley73f00d92016-02-16 18:54:20 -0800463 default=constants.ANDROID_BUCKET_URL,
464 type='gs_path')
David Rileyc0da9d92016-02-01 12:11:01 -0800465 parser.add_argument('--android_build_branch',
Shuhei Takahashi6d02c192017-04-05 14:01:24 +0900466 required=True,
467 help='Android branch to import from. '
468 'Ex: git_mnc-dr-arc-dev')
Hidehiko Abe1ebc25d2016-07-28 02:24:37 +0900469 parser.add_argument('--android_gts_build_branch',
Shuhei Takahashi6d02c192017-04-05 14:01:24 +0900470 help='Android GTS branch to copy artifacts from. '
471 'Ex: git_mnc-dev')
Hidehiko Abe4fd94ae2017-01-24 18:59:55 +0900472 parser.add_argument('--android_package',
473 default=constants.ANDROID_PACKAGE_NAME)
David Riley73f00d92016-02-16 18:54:20 -0800474 parser.add_argument('--arc_bucket_url',
475 default=constants.ARC_BUCKET_URL,
476 type='gs_path')
David Rileyc0da9d92016-02-01 12:11:01 -0800477 parser.add_argument('-f', '--force_version',
478 help='Android build id to use')
479 parser.add_argument('-s', '--srcroot',
480 default=os.path.join(os.environ['HOME'], 'trunk', 'src'),
481 help='Path to the src directory')
482 parser.add_argument('-t', '--tracking_branch', default='cros/master',
483 help='Branch we are tracking changes against')
484 return parser
485
486
487def main(argv):
488 parser = GetParser()
489 options = parser.parse_args(argv)
490 options.Freeze()
491
492 overlay_dir = os.path.abspath(_OVERLAY_DIR % {'srcroot': options.srcroot})
Hidehiko Abe4fd94ae2017-01-24 18:59:55 +0900493 android_package_dir = os.path.join(
494 overlay_dir,
495 portage_util.GetFullAndroidPortagePackageName(options.android_package))
David Rileyc0da9d92016-02-01 12:11:01 -0800496 version_to_uprev = None
David Rileyc0da9d92016-02-01 12:11:01 -0800497
498 (unstable_ebuild, stable_ebuilds) = FindAndroidCandidates(android_package_dir)
David Riley73f00d92016-02-16 18:54:20 -0800499 acls = MakeAclDict(android_package_dir)
Nicolas Norvez4bd854f2017-05-23 10:04:45 -0700500 build_targets = MakeBuildTargetDict(options.android_build_branch)
Hidehiko Abe1ebc25d2016-07-28 02:24:37 +0900501 # Mirror artifacts, i.e., images and some sdk tools (e.g., adb, aapt).
502 version_to_uprev = MirrorArtifacts(options.android_bucket_url,
503 options.android_build_branch,
504 options.arc_bucket_url, acls,
Nicolas Norvez4bd854f2017-05-23 10:04:45 -0700505 build_targets,
Hidehiko Abe1ebc25d2016-07-28 02:24:37 +0900506 options.force_version)
507
508 # Mirror GTS.
Hidehiko Abee8cd06c2017-05-12 23:32:19 +0900509 if options.android_gts_build_branch:
510 MirrorArtifacts(options.android_bucket_url,
511 options.android_gts_build_branch,
512 options.arc_bucket_url, acls,
513 constants.ANDROID_GTS_BUILD_TARGETS)
David Riley73f00d92016-02-16 18:54:20 -0800514
David Rileyc0da9d92016-02-01 12:11:01 -0800515 stable_candidate = portage_util.BestEBuild(stable_ebuilds)
516
517 if stable_candidate:
David Riley676f5402016-02-12 17:24:23 -0800518 logging.info('Stable candidate found %s' % stable_candidate.version)
David Rileyc0da9d92016-02-01 12:11:01 -0800519 else:
520 logging.info('No stable candidate found.')
521
522 tracking_branch = 'remotes/m/%s' % os.path.basename(options.tracking_branch)
523 existing_branch = git.GetCurrentBranch(android_package_dir)
524 work_branch = cros_mark_as_stable.GitBranch(constants.STABLE_EBUILD_BRANCH,
525 tracking_branch,
526 android_package_dir)
527 work_branch.CreateBranch()
528
529 # In the case of uprevving overlays that have patches applied to them,
530 # include the patched changes in the stabilizing branch.
531 if existing_branch:
532 git.RunGit(overlay_dir, ['rebase', existing_branch])
533
534 android_version_atom = MarkAndroidEBuildAsStable(
Hidehiko Abe4fd94ae2017-01-24 18:59:55 +0900535 stable_candidate, unstable_ebuild, options.android_package,
David Riley73f00d92016-02-16 18:54:20 -0800536 version_to_uprev, android_package_dir,
Nicolas Norvez4bd854f2017-05-23 10:04:45 -0700537 options.android_build_branch, options.arc_bucket_url, build_targets)
David Rileyc0da9d92016-02-01 12:11:01 -0800538 if android_version_atom:
539 if options.boards:
540 cros_mark_as_stable.CleanStalePackages(options.srcroot,
541 options.boards.split(':'),
542 [android_version_atom])
543
544 # Explicit print to communicate to caller.
545 print('ANDROID_VERSION_ATOM=%s' % android_version_atom)