blob: b4968bdd5a82edc27c31589c9352ba8bd02f715b [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
213 to_discard, sep, to_keep = basename.partition('-')
214 if not sep:
215 logging.error(('Build %s: Could not find separator "-" in artifact'
216 ' basename %s'), build, basename)
217 return basename
Bernie Thompson63ed5612017-08-16 12:27:34 -0700218 if 'cheets_' in to_discard:
219 return 'cheets_%s-%s' % (build.lower(), to_keep)
220 elif 'bertha_' in to_discard:
221 return 'bertha_%s-%s' % (build.lower(), to_keep)
222 logging.error('Build %s: Unexpected artifact basename %s',
223 build, basename)
224 return basename
Nicolas Norvezb08f54d2016-12-05 17:58:54 -0800225
226
khmel@google.com778a1cd2018-04-13 11:11:58 -0700227def PackSdkTools(build_branch, build_id, targets, arc_bucket_url):
228 """Creates static SDK tools pack from ARC++ specific bucket.
229
230 Ebuild needs archives to process binaries natively. This collects static SDK
231 tools and packs them to tbz2 archive which can referenced from Android
232 container ebuild file. Pack is placed into the same bucket where SDK tools
233 exist. If pack already exists and up to date then copying is skipped.
234 Otherwise fresh pack is copied.
235
236 Args:
237 build_branch: branch of Android builds
238 build_id: A string. The Android build id number to check.
239 targets: Dict from build key to (targe build suffix, artifact file pattern)
240 pair.
241 arc_bucket_url: URL of the target ARC build gs bucket
242 """
243
244 if not 'SDK_TOOLS' in targets:
245 return
246
247 gs_context = gs.GSContext()
248 target, pattern = targets['SDK_TOOLS']
249 build_dir = '%s-%s' % (build_branch, target)
250 arc_dir = os.path.join(arc_bucket_url, build_dir, build_id)
251
252 sdk_tools_dir = tempfile.mkdtemp()
253
254 try:
255 sdk_tools_bin_dir = os.path.join(sdk_tools_dir, 'bin')
256 os.mkdir(sdk_tools_bin_dir)
257
258 for tool in gs_context.List(arc_dir):
259 if re.search(pattern, tool.url):
260 local_tool_path = os.path.join(sdk_tools_bin_dir,
261 os.path.basename(tool.url))
262 gs_context.Copy(tool.url, local_tool_path, version=0)
263 file_time = int(gs_context.Stat(tool.url).creation_time.strftime('%s'))
264 os.utime(local_tool_path, (file_time, file_time))
265
266 # Fix ./ times to make tar file stable.
267 os.utime(sdk_tools_bin_dir, (0, 0))
268
269 sdk_tools_file_name = 'sdk_tools_%s.tbz2' % build_id
270 sdk_tools_local_path = os.path.join(sdk_tools_dir, sdk_tools_file_name)
271 sdk_tools_target_path = os.path.join(arc_dir, sdk_tools_file_name)
272 subprocess.call(['tar', '--group=root:0', '--owner=root:0',
273 '--create', '--bzip2', '--sort=name',
274 '--file=%s' % sdk_tools_local_path,
275 '--directory=%s' % sdk_tools_bin_dir, '.'])
276
277 if gs_context.Exists(sdk_tools_target_path):
278 # Calculate local md5
279 md5 = hashlib.md5()
280 with open(sdk_tools_local_path, 'rb') as f:
281 while True:
282 buf = f.read(4096)
283 if not buf:
284 break
285 md5.update(buf)
286 md5_local = md5.digest()
287 # Get target md5
288 md5_target = base64.decodestring(
289 gs_context.Stat(sdk_tools_target_path).hash_md5)
290 if md5_local == md5_target:
291 logging.info('SDK tools pack %s is up to date', sdk_tools_target_path)
292 return
293 logging.warning('SDK tools pack %s invalid, removing',
294 sdk_tools_target_path)
295 gs_context.Remove(sdk_tools_target_path)
296
297 logging.info('Creating SDK tools pack %s', sdk_tools_target_path)
298 gs_context.Copy(sdk_tools_local_path, sdk_tools_target_path, version=0)
299 finally:
300 shutil.rmtree(sdk_tools_dir)
301
302
David Riley73f00d92016-02-16 18:54:20 -0800303def CopyToArcBucket(android_bucket_url, build_branch, build_id, subpaths,
Hidehiko Abe1ebc25d2016-07-28 02:24:37 +0900304 targets, arc_bucket_url, acls):
David Riley73f00d92016-02-16 18:54:20 -0800305 """Copies from source Android bucket to ARC++ specific bucket.
306
307 Copies each build to the ARC bucket eliminating the subpath.
308 Applies build specific ACLs for each file.
309
310 Args:
311 android_bucket_url: URL of Android build gs bucket
312 build_branch: branch of Android builds
313 build_id: A string. The Android build id number to check.
314 subpaths: Subpath dictionary for each build to copy.
Hidehiko Abe1ebc25d2016-07-28 02:24:37 +0900315 targets: Dict from build key to (targe build suffix, artifact file pattern)
316 pair.
David Riley73f00d92016-02-16 18:54:20 -0800317 arc_bucket_url: URL of the target ARC build gs bucket
318 acls: ACLs dictionary for each build to copy.
319 """
320 gs_context = gs.GSContext()
321 for build, subpath in subpaths.iteritems():
Hidehiko Abe1ebc25d2016-07-28 02:24:37 +0900322 target, pattern = targets[build]
David Riley73f00d92016-02-16 18:54:20 -0800323 build_dir = '%s-%s' % (build_branch, target)
324 android_dir = os.path.join(android_bucket_url, build_dir, build_id, subpath)
325 arc_dir = os.path.join(arc_bucket_url, build_dir, build_id)
326
Hidehiko Abe12727dd2016-05-27 23:23:45 +0900327 # Copy all target files from android_dir to arc_dir, setting ACLs.
328 for targetfile in gs_context.List(android_dir):
329 if re.search(pattern, targetfile.url):
330 basename = os.path.basename(targetfile.url)
Nicolas Norvezb08f54d2016-12-05 17:58:54 -0800331 arc_path = os.path.join(arc_dir, _GetArcBasename(build, basename))
David Riley73f00d92016-02-16 18:54:20 -0800332 acl = acls[build]
333 needs_copy = True
334
335 # Check a pre-existing file with the original source.
336 if gs_context.Exists(arc_path):
Hidehiko Abe12727dd2016-05-27 23:23:45 +0900337 if (gs_context.Stat(targetfile.url).hash_crc32c !=
Elijah Taylorbfc30692016-04-22 14:05:23 -0700338 gs_context.Stat(arc_path).hash_crc32c):
David Riley73f00d92016-02-16 18:54:20 -0800339 logging.warn('Removing incorrect file %s', arc_path)
340 gs_context.Remove(arc_path)
341 else:
342 logging.info('Skipping already copied file %s', arc_path)
343 needs_copy = False
344
345 # Copy if necessary, and set the ACL unconditionally.
346 # The Stat() call above doesn't verify the ACL is correct and
347 # the ChangeACL should be relatively cheap compared to the copy.
348 # This covers the following caes:
349 # - handling an interrupted copy from a previous run.
350 # - rerunning the copy in case one of the googlestorage_acl_X.txt
351 # files changes (e.g. we add a new variant which reuses a build).
352 if needs_copy:
Hidehiko Abe12727dd2016-05-27 23:23:45 +0900353 logging.info('Copying %s -> %s (acl %s)',
354 targetfile.url, arc_path, acl)
355 gs_context.Copy(targetfile.url, arc_path, version=0)
David Riley73f00d92016-02-16 18:54:20 -0800356 gs_context.ChangeACL(arc_path, acl_args_file=acl)
357
358
Hidehiko Abe1ebc25d2016-07-28 02:24:37 +0900359def MirrorArtifacts(android_bucket_url, android_build_branch, arc_bucket_url,
360 acls, targets, version=None):
361 """Mirrors artifacts from Android bucket to ARC bucket.
362
363 First, this function identifies which build version should be copied,
364 if not given. Please see GetLatestBuild() and IsBuildIdValid() for details.
365
366 On build version identified, then copies target artifacts to the ARC bucket,
367 with setting ACLs.
368
369 Args:
370 android_bucket_url: URL of Android build gs bucket
371 android_build_branch: branch of Android builds
372 arc_bucket_url: URL of the target ARC build gs bucket
373 acls: ACLs dictionary for each build to copy.
374 targets: Dict from build key to (targe build suffix, artifact file pattern)
375 pair.
376 version: (optional) A string. The Android build id number to check.
377 If not passed, detect latest good build version.
378
379 Returns:
380 Mirrored version.
381 """
382 if version:
383 subpaths = IsBuildIdValid(
384 android_bucket_url, android_build_branch, version, targets)
385 if not subpaths:
386 logging.error('Requested build %s is not valid' % version)
387 else:
388 version, subpaths = GetLatestBuild(
389 android_bucket_url, android_build_branch, targets)
390
391 CopyToArcBucket(android_bucket_url, android_build_branch, version, subpaths,
392 targets, arc_bucket_url, acls)
khmel@google.com778a1cd2018-04-13 11:11:58 -0700393 PackSdkTools(android_build_branch, version, targets, arc_bucket_url)
394
Hidehiko Abe1ebc25d2016-07-28 02:24:37 +0900395 return version
396
397
David Riley73f00d92016-02-16 18:54:20 -0800398def MakeAclDict(package_dir):
399 """Creates a dictionary of acl files for each build type.
400
401 Args:
402 package_dir: The path to where the package acl files are stored.
403
404 Returns:
405 Returns acls dictionary.
406 """
407 return dict(
408 (k, os.path.join(package_dir, v))
409 for k, v in constants.ARC_BUCKET_ACLS.items()
410 )
411
412
Nicolas Norvez4bd854f2017-05-23 10:04:45 -0700413def MakeBuildTargetDict(build_branch):
414 """Creates a dictionary of build targets.
415
Bernie Thompson63ed5612017-08-16 12:27:34 -0700416 Not all targets are common between branches, for example
Nicolas Norvez4bd854f2017-05-23 10:04:45 -0700417 sdk_google_cheets_x86 only exists on N.
418 This generates a dictionary listing the available build targets for a
419 specific branch.
420
421 Args:
422 build_branch: branch of Android builds.
423
424 Returns:
425 Returns build target dictionary.
426
427 Raises:
428 ValueError: if the Android build branch is invalid.
429 """
Bernie Thompson54650022018-01-12 10:03:20 -0800430 if build_branch == constants.ANDROID_MST_BUILD_BRANCH:
431 return constants.ANDROID_MST_BUILD_TARGETS
Nicolas Norvez4bd854f2017-05-23 10:04:45 -0700432 elif build_branch == constants.ANDROID_NYC_BUILD_BRANCH:
Bernie Thompson63ed5612017-08-16 12:27:34 -0700433 return constants.ANDROID_NYC_BUILD_TARGETS
Ben Linb8499402018-03-08 16:54:00 -0800434 elif build_branch == constants.ANDROID_PI_BUILD_BRANCH:
435 return constants.ANDROID_PI_BUILD_TARGETS
Nicolas Norvez4bd854f2017-05-23 10:04:45 -0700436 else:
437 raise ValueError('Unknown branch: %s' % build_branch)
Nicolas Norvez4bd854f2017-05-23 10:04:45 -0700438
439
David Rileyc0da9d92016-02-01 12:11:01 -0800440def GetAndroidRevisionListLink(build_branch, old_android, new_android):
441 """Returns a link to the list of revisions between two Android versions
442
443 Given two AndroidEBuilds, generate a link to a page that prints the
444 Android changes between those two revisions, inclusive.
445
446 Args:
447 build_branch: branch of Android builds
448 old_android: ebuild for the version to diff from
449 new_android: ebuild for the version to which to diff
450
451 Returns:
452 The desired URL.
453 """
454 return _ANDROID_VERSION_URL % {'branch': build_branch,
Hidehiko Abec9ecf262017-07-05 15:17:41 +0900455 'old': old_android.version_no_rev,
456 'new': new_android.version_no_rev}
David Rileyc0da9d92016-02-01 12:11:01 -0800457
458
Hidehiko Abe4fd94ae2017-01-24 18:59:55 +0900459def MarkAndroidEBuildAsStable(stable_candidate, unstable_ebuild,
460 android_package, android_version, package_dir,
Nicolas Norvez4bd854f2017-05-23 10:04:45 -0700461 build_branch, arc_bucket_url, build_targets):
David Rileyc0da9d92016-02-01 12:11:01 -0800462 r"""Uprevs the Android ebuild.
463
464 This is the main function that uprevs from a stable candidate
465 to its new version.
466
467 Args:
468 stable_candidate: ebuild that corresponds to the stable ebuild we are
469 revving from. If None, builds the a new ebuild given the version
470 with revision set to 1.
471 unstable_ebuild: ebuild corresponding to the unstable ebuild for Android.
Hidehiko Abe4fd94ae2017-01-24 18:59:55 +0900472 android_package: android package name.
David Rileyc0da9d92016-02-01 12:11:01 -0800473 android_version: The \d+ build id of Android.
David Rileyc0da9d92016-02-01 12:11:01 -0800474 package_dir: Path to the android-container package dir.
David Riley73f00d92016-02-16 18:54:20 -0800475 build_branch: branch of Android builds.
476 arc_bucket_url: URL of the target ARC build gs bucket.
Nicolas Norvez4bd854f2017-05-23 10:04:45 -0700477 build_targets: build targets for this particular Android branch.
David Rileyc0da9d92016-02-01 12:11:01 -0800478
479 Returns:
480 Full portage version atom (including rc's, etc) that was revved.
481 """
482 def IsTheNewEBuildRedundant(new_ebuild, stable_ebuild):
483 """Returns True if the new ebuild is redundant.
484
485 This is True if there if the current stable ebuild is the exact same copy
486 of the new one.
487 """
488 if not stable_ebuild:
489 return False
490
David Riley676f5402016-02-12 17:24:23 -0800491 if stable_candidate.version_no_rev == new_ebuild.version_no_rev:
David Rileyc0da9d92016-02-01 12:11:01 -0800492 return filecmp.cmp(
493 new_ebuild.ebuild_path, stable_ebuild.ebuild_path, shallow=False)
494
495 # Case where we have the last stable candidate with same version just rev.
David Riley676f5402016-02-12 17:24:23 -0800496 if stable_candidate and stable_candidate.version_no_rev == android_version:
David Rileyc0da9d92016-02-01 12:11:01 -0800497 new_ebuild_path = '%s-r%d.ebuild' % (
498 stable_candidate.ebuild_path_no_revision,
499 stable_candidate.current_revision + 1)
500 else:
Hidehiko Abe4fd94ae2017-01-24 18:59:55 +0900501 pf = '%s-%s-r1' % (android_package, android_version)
David Rileyc0da9d92016-02-01 12:11:01 -0800502 new_ebuild_path = os.path.join(package_dir, '%s.ebuild' % pf)
503
David Riley73f00d92016-02-16 18:54:20 -0800504 variables = {'BASE_URL': arc_bucket_url}
Nicolas Norvez4bd854f2017-05-23 10:04:45 -0700505 for build, (target, _) in build_targets.iteritems():
David Riley73f00d92016-02-16 18:54:20 -0800506 variables[build + '_TARGET'] = '%s-%s' % (build_branch, target)
David Rileyc0da9d92016-02-01 12:11:01 -0800507
508 portage_util.EBuild.MarkAsStable(
509 unstable_ebuild.ebuild_path, new_ebuild_path,
510 variables, make_stable=True)
511 new_ebuild = portage_util.EBuild(new_ebuild_path)
512
513 # Determine whether this is ebuild is redundant.
514 if IsTheNewEBuildRedundant(new_ebuild, stable_candidate):
515 msg = 'Previous ebuild with same version found and ebuild is redundant.'
516 logging.info(msg)
517 os.unlink(new_ebuild_path)
518 return None
519
520 if stable_candidate:
521 logging.PrintBuildbotLink('Android revisions',
522 GetAndroidRevisionListLink(build_branch,
523 stable_candidate,
524 new_ebuild))
525
526 git.RunGit(package_dir, ['add', new_ebuild_path])
527 if stable_candidate and not stable_candidate.IsSticky():
528 git.RunGit(package_dir, ['rm', stable_candidate.ebuild_path])
529
530 # Update ebuild manifest and git add it.
531 gen_manifest_cmd = ['ebuild', new_ebuild_path, 'manifest', '--force']
532 cros_build_lib.RunCommand(gen_manifest_cmd,
533 extra_env=None, print_cmd=True)
534 git.RunGit(package_dir, ['add', 'Manifest'])
535
536 portage_util.EBuild.CommitChange(
Hidehiko Abe4fd94ae2017-01-24 18:59:55 +0900537 _GIT_COMMIT_MESSAGE % {'android_package': android_package,
David Rileyc0da9d92016-02-01 12:11:01 -0800538 'android_version': android_version},
539 package_dir)
540
541 return '%s-%s' % (new_ebuild.package, new_ebuild.version)
542
543
544def GetParser():
545 """Creates the argument parser."""
546 parser = commandline.ArgumentParser()
547 parser.add_argument('-b', '--boards')
548 parser.add_argument('--android_bucket_url',
David Riley73f00d92016-02-16 18:54:20 -0800549 default=constants.ANDROID_BUCKET_URL,
550 type='gs_path')
David Rileyc0da9d92016-02-01 12:11:01 -0800551 parser.add_argument('--android_build_branch',
Shuhei Takahashi6d02c192017-04-05 14:01:24 +0900552 required=True,
553 help='Android branch to import from. '
554 'Ex: git_mnc-dr-arc-dev')
Hidehiko Abe1ebc25d2016-07-28 02:24:37 +0900555 parser.add_argument('--android_gts_build_branch',
Shuhei Takahashi6d02c192017-04-05 14:01:24 +0900556 help='Android GTS branch to copy artifacts from. '
557 'Ex: git_mnc-dev')
Hidehiko Abe4fd94ae2017-01-24 18:59:55 +0900558 parser.add_argument('--android_package',
559 default=constants.ANDROID_PACKAGE_NAME)
David Riley73f00d92016-02-16 18:54:20 -0800560 parser.add_argument('--arc_bucket_url',
561 default=constants.ARC_BUCKET_URL,
562 type='gs_path')
David Rileyc0da9d92016-02-01 12:11:01 -0800563 parser.add_argument('-f', '--force_version',
564 help='Android build id to use')
565 parser.add_argument('-s', '--srcroot',
566 default=os.path.join(os.environ['HOME'], 'trunk', 'src'),
567 help='Path to the src directory')
568 parser.add_argument('-t', '--tracking_branch', default='cros/master',
569 help='Branch we are tracking changes against')
570 return parser
571
572
573def main(argv):
Hidehiko Abec9ecf262017-07-05 15:17:41 +0900574 logging.EnableBuildbotMarkers()
David Rileyc0da9d92016-02-01 12:11:01 -0800575 parser = GetParser()
576 options = parser.parse_args(argv)
577 options.Freeze()
578
579 overlay_dir = os.path.abspath(_OVERLAY_DIR % {'srcroot': options.srcroot})
Hidehiko Abe4fd94ae2017-01-24 18:59:55 +0900580 android_package_dir = os.path.join(
581 overlay_dir,
582 portage_util.GetFullAndroidPortagePackageName(options.android_package))
David Rileyc0da9d92016-02-01 12:11:01 -0800583 version_to_uprev = None
David Rileyc0da9d92016-02-01 12:11:01 -0800584
585 (unstable_ebuild, stable_ebuilds) = FindAndroidCandidates(android_package_dir)
David Riley73f00d92016-02-16 18:54:20 -0800586 acls = MakeAclDict(android_package_dir)
Nicolas Norvez4bd854f2017-05-23 10:04:45 -0700587 build_targets = MakeBuildTargetDict(options.android_build_branch)
Hidehiko Abe1ebc25d2016-07-28 02:24:37 +0900588 # Mirror artifacts, i.e., images and some sdk tools (e.g., adb, aapt).
589 version_to_uprev = MirrorArtifacts(options.android_bucket_url,
590 options.android_build_branch,
591 options.arc_bucket_url, acls,
Nicolas Norvez4bd854f2017-05-23 10:04:45 -0700592 build_targets,
Hidehiko Abe1ebc25d2016-07-28 02:24:37 +0900593 options.force_version)
594
595 # Mirror GTS.
Hidehiko Abee8cd06c2017-05-12 23:32:19 +0900596 if options.android_gts_build_branch:
597 MirrorArtifacts(options.android_bucket_url,
598 options.android_gts_build_branch,
599 options.arc_bucket_url, acls,
600 constants.ANDROID_GTS_BUILD_TARGETS)
David Riley73f00d92016-02-16 18:54:20 -0800601
David Rileyc0da9d92016-02-01 12:11:01 -0800602 stable_candidate = portage_util.BestEBuild(stable_ebuilds)
603
604 if stable_candidate:
David Riley676f5402016-02-12 17:24:23 -0800605 logging.info('Stable candidate found %s' % stable_candidate.version)
David Rileyc0da9d92016-02-01 12:11:01 -0800606 else:
607 logging.info('No stable candidate found.')
608
609 tracking_branch = 'remotes/m/%s' % os.path.basename(options.tracking_branch)
610 existing_branch = git.GetCurrentBranch(android_package_dir)
611 work_branch = cros_mark_as_stable.GitBranch(constants.STABLE_EBUILD_BRANCH,
612 tracking_branch,
613 android_package_dir)
614 work_branch.CreateBranch()
615
616 # In the case of uprevving overlays that have patches applied to them,
617 # include the patched changes in the stabilizing branch.
618 if existing_branch:
619 git.RunGit(overlay_dir, ['rebase', existing_branch])
620
621 android_version_atom = MarkAndroidEBuildAsStable(
Hidehiko Abe4fd94ae2017-01-24 18:59:55 +0900622 stable_candidate, unstable_ebuild, options.android_package,
David Riley73f00d92016-02-16 18:54:20 -0800623 version_to_uprev, android_package_dir,
Nicolas Norvez4bd854f2017-05-23 10:04:45 -0700624 options.android_build_branch, options.arc_bucket_url, build_targets)
David Rileyc0da9d92016-02-01 12:11:01 -0800625 if android_version_atom:
626 if options.boards:
627 cros_mark_as_stable.CleanStalePackages(options.srcroot,
628 options.boards.split(':'),
629 [android_version_atom])
630
631 # Explicit print to communicate to caller.
632 print('ANDROID_VERSION_ATOM=%s' % android_version_atom)