blob: dbcdaae4363da967e4197c6a545a2402c62997fe [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 \
Shao-Chuan Lee9c39e0c2020-04-24 11:40:34 +090013 --android_build_branch=git_pi-arc \
14 --android_package=android-container-pi
Shuhei Takahashi6d02c192017-04-05 14:01:24 +090015
Shao-Chuan Lee9c39e0c2020-04-24 11:40:34 +090016Returns chromeos-base/android-container-pi-6417892-r1
David Rileyc0da9d92016-02-01 12:11:01 -080017
Shao-Chuan Lee9c39e0c2020-04-24 11:40:34 +090018emerge-eve =chromeos-base/android-container-pi-6417892-r1
David Rileyc0da9d92016-02-01 12:11:01 -080019"""
20
21from __future__ import print_function
22
23import filecmp
24import glob
25import os
Hidehiko Abe12727dd2016-05-27 23:23:45 +090026import re
khmel@google.com96c193e2018-05-10 14:00:38 -070027import time
Mike Frysinger00a02292020-04-19 06:28:03 -040028import sys
David Rileyc0da9d92016-02-01 12:11:01 -080029
Aviv Keshetb7519e12016-10-04 00:50:00 -070030from chromite.lib import constants
David Rileyc0da9d92016-02-01 12:11:01 -080031from chromite.lib import commandline
32from chromite.lib import cros_build_lib
33from chromite.lib import cros_logging as logging
34from chromite.lib import git
35from chromite.lib import gs
36from chromite.lib import portage_util
37from chromite.scripts import cros_mark_as_stable
38
39
Mike Frysinger00a02292020-04-19 06:28:03 -040040assert sys.version_info >= (3, 6), 'This module requires Python 3.6+'
41
42
David Rileyc0da9d92016-02-01 12:11:01 -080043# Dir where all the action happens.
44_OVERLAY_DIR = '%(srcroot)s/private-overlays/project-cheets-private/'
45
Junichi Uekawa6d61ab02020-04-15 14:52:28 +090046_GIT_COMMIT_MESSAGE = """Marking latest for %(android_package)s ebuild with \
47version %(android_version)s as stable.
48
49BUG=None
50TEST=CQ
51"""
David Rileyc0da9d92016-02-01 12:11:01 -080052
khmel@chromium.orgd3ec3d72020-04-29 15:57:35 -070053_RUNTIME_ARTIFACTS_BUCKET_URL = 'gs://chromeos-arc-images/runtime_artifacts'
David Rileyc0da9d92016-02-01 12:11:01 -080054
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 = {}
Mike Frysinger0bdbc102019-06-13 15:27:29 -040074 for build, (target, _) in targets.items():
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:
Mike Frysinger968c1142020-05-09 00:37:56 -040082 logging.warning(
David Rileyc0da9d92016-02-01 12:11:01 -080083 'Directory [%s] does not contain any subpath, ignoring it.',
84 build_id_path)
85 return None
86 if len(subpaths) > 1:
Mike Frysinger968c1142020-05-09 00:37:56 -040087 logging.warning(
David Rileyc0da9d92016-02-01 12:11:01 -080088 '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:
Mike Frysinger968c1142020-05-09 00:37:56 -040099 logging.warning(
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.
Mike Frysinger0bdbc102019-06-13 15:27:29 -0400127 for target, _ in targets.values():
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():
Mike Frysinger968c1142020-05-09 00:37:56 -0400135 logging.warning('Directory [%s] does not look like a valid build_id.',
136 gs_result.url)
David Rileyc0da9d92016-02-01 12:11:01 -0800137 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:
Mike Frysinger968c1142020-05-09 00:37:56 -0400149 logging.warning('Did not find a build_id common to all platforms.')
David Rileyc0da9d92016-02-01 12:11:01 -0800150 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.
Mike Frysinger968c1142020-05-09 00:37:56 -0400159 logging.warning('Did not find a build_id valid on all platforms.')
David Rileyc0da9d92016-02-01 12:11:01 -0800160 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:
Lann Martinffb95162018-08-28 12:02:54 -0600188 logging.warning('Missing stable ebuild for %s', package_dir)
David Rileyc0da9d92016-02-01 12:11:01 -0800189
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
David Riley73f00d92016-02-16 18:54:20 -0800229def CopyToArcBucket(android_bucket_url, build_branch, build_id, subpaths,
Hidehiko Abe1ebc25d2016-07-28 02:24:37 +0900230 targets, arc_bucket_url, acls):
David Riley73f00d92016-02-16 18:54:20 -0800231 """Copies from source Android bucket to ARC++ specific bucket.
232
233 Copies each build to the ARC bucket eliminating the subpath.
234 Applies build specific ACLs for each file.
235
236 Args:
237 android_bucket_url: URL of Android build gs bucket
238 build_branch: branch of Android builds
239 build_id: A string. The Android build id number to check.
240 subpaths: Subpath dictionary for each build to copy.
Hidehiko Abe1ebc25d2016-07-28 02:24:37 +0900241 targets: Dict from build key to (targe build suffix, artifact file pattern)
242 pair.
David Riley73f00d92016-02-16 18:54:20 -0800243 arc_bucket_url: URL of the target ARC build gs bucket
244 acls: ACLs dictionary for each build to copy.
245 """
246 gs_context = gs.GSContext()
Mike Frysinger0bdbc102019-06-13 15:27:29 -0400247 for build, subpath in subpaths.items():
Hidehiko Abe1ebc25d2016-07-28 02:24:37 +0900248 target, pattern = targets[build]
David Riley73f00d92016-02-16 18:54:20 -0800249 build_dir = '%s-%s' % (build_branch, target)
250 android_dir = os.path.join(android_bucket_url, build_dir, build_id, subpath)
251 arc_dir = os.path.join(arc_bucket_url, build_dir, build_id)
252
Hidehiko Abe12727dd2016-05-27 23:23:45 +0900253 # Copy all target files from android_dir to arc_dir, setting ACLs.
254 for targetfile in gs_context.List(android_dir):
255 if re.search(pattern, targetfile.url):
256 basename = os.path.basename(targetfile.url)
Nicolas Norvezb08f54d2016-12-05 17:58:54 -0800257 arc_path = os.path.join(arc_dir, _GetArcBasename(build, basename))
David Riley73f00d92016-02-16 18:54:20 -0800258 acl = acls[build]
259 needs_copy = True
khmel@google.com96c193e2018-05-10 14:00:38 -0700260 retry_count = 2
David Riley73f00d92016-02-16 18:54:20 -0800261
khmel@google.com96c193e2018-05-10 14:00:38 -0700262 # Retry in case race condition when several boards trying to copy the
263 # same resource
264 while True:
265 # Check a pre-existing file with the original source.
266 if gs_context.Exists(arc_path):
267 if (gs_context.Stat(targetfile.url).hash_crc32c !=
268 gs_context.Stat(arc_path).hash_crc32c):
Mike Frysinger968c1142020-05-09 00:37:56 -0400269 logging.warning('Removing incorrect file %s', arc_path)
khmel@google.com96c193e2018-05-10 14:00:38 -0700270 gs_context.Remove(arc_path)
271 else:
272 logging.info('Skipping already copied file %s', arc_path)
273 needs_copy = False
David Riley73f00d92016-02-16 18:54:20 -0800274
khmel@google.com96c193e2018-05-10 14:00:38 -0700275 # Copy if necessary, and set the ACL unconditionally.
276 # The Stat() call above doesn't verify the ACL is correct and
277 # the ChangeACL should be relatively cheap compared to the copy.
278 # This covers the following caes:
279 # - handling an interrupted copy from a previous run.
280 # - rerunning the copy in case one of the googlestorage_acl_X.txt
281 # files changes (e.g. we add a new variant which reuses a build).
282 if needs_copy:
283 logging.info('Copying %s -> %s (acl %s)',
284 targetfile.url, arc_path, acl)
285 try:
286 gs_context.Copy(targetfile.url, arc_path, version=0)
287 except gs.GSContextPreconditionFailed as error:
288 if not retry_count:
289 raise error
290 # Retry one more time after a short delay
291 logging.warning('Will retry copying %s -> %s',
292 targetfile.url, arc_path)
293 time.sleep(5)
294 retry_count = retry_count - 1
295 continue
296 gs_context.ChangeACL(arc_path, acl_args_file=acl)
297 break
David Riley73f00d92016-02-16 18:54:20 -0800298
299
Hidehiko Abe1ebc25d2016-07-28 02:24:37 +0900300def MirrorArtifacts(android_bucket_url, android_build_branch, arc_bucket_url,
301 acls, targets, version=None):
302 """Mirrors artifacts from Android bucket to ARC bucket.
303
304 First, this function identifies which build version should be copied,
305 if not given. Please see GetLatestBuild() and IsBuildIdValid() for details.
306
307 On build version identified, then copies target artifacts to the ARC bucket,
308 with setting ACLs.
309
310 Args:
311 android_bucket_url: URL of Android build gs bucket
312 android_build_branch: branch of Android builds
313 arc_bucket_url: URL of the target ARC build gs bucket
314 acls: ACLs dictionary for each build to copy.
315 targets: Dict from build key to (targe build suffix, artifact file pattern)
316 pair.
317 version: (optional) A string. The Android build id number to check.
318 If not passed, detect latest good build version.
319
320 Returns:
321 Mirrored version.
322 """
323 if version:
324 subpaths = IsBuildIdValid(
325 android_bucket_url, android_build_branch, version, targets)
326 if not subpaths:
Lann Martinffb95162018-08-28 12:02:54 -0600327 logging.error('Requested build %s is not valid', version)
Hidehiko Abe1ebc25d2016-07-28 02:24:37 +0900328 else:
329 version, subpaths = GetLatestBuild(
330 android_bucket_url, android_build_branch, targets)
331
332 CopyToArcBucket(android_bucket_url, android_build_branch, version, subpaths,
333 targets, arc_bucket_url, acls)
khmel@google.com778a1cd2018-04-13 11:11:58 -0700334
Hidehiko Abe1ebc25d2016-07-28 02:24:37 +0900335 return version
336
337
David Riley73f00d92016-02-16 18:54:20 -0800338def MakeAclDict(package_dir):
339 """Creates a dictionary of acl files for each build type.
340
341 Args:
342 package_dir: The path to where the package acl files are stored.
343
344 Returns:
345 Returns acls dictionary.
346 """
347 return dict(
348 (k, os.path.join(package_dir, v))
349 for k, v in constants.ARC_BUCKET_ACLS.items()
350 )
351
352
Qijiang Fan6588cc92019-11-20 13:26:04 +0900353def MakeBuildTargetDict(package_name, build_branch):
Nicolas Norvez4bd854f2017-05-23 10:04:45 -0700354 """Creates a dictionary of build targets.
355
Bernie Thompson63ed5612017-08-16 12:27:34 -0700356 Not all targets are common between branches, for example
Nicolas Norvez4bd854f2017-05-23 10:04:45 -0700357 sdk_google_cheets_x86 only exists on N.
358 This generates a dictionary listing the available build targets for a
359 specific branch.
360
361 Args:
Qijiang Fan6588cc92019-11-20 13:26:04 +0900362 package_name: package name of chromeos arc package.
Nicolas Norvez4bd854f2017-05-23 10:04:45 -0700363 build_branch: branch of Android builds.
364
365 Returns:
366 Returns build target dictionary.
367
368 Raises:
369 ValueError: if the Android build branch is invalid.
370 """
Qijiang Fan6588cc92019-11-20 13:26:04 +0900371 if constants.ANDROID_CONTAINER_PACKAGE_KEYWORD in package_name:
Federico 'Morg' Pareschi041ee652020-03-10 15:09:42 +0900372 target_list = {
373 constants.ANDROID_MST_BUILD_BRANCH:
374 constants.ANDROID_MST_BUILD_TARGETS,
Federico 'Morg' Pareschi041ee652020-03-10 15:09:42 +0900375 constants.ANDROID_PI_BUILD_BRANCH:
376 constants.ANDROID_PI_BUILD_TARGETS,
377 constants.ANDROID_QT_BUILD_BRANCH:
378 constants.ANDROID_QT_BUILD_TARGETS,
379 constants.ANDROID_RVC_BUILD_BRANCH:
380 constants.ANDROID_RVC_BUILD_TARGETS,
381 }
Qijiang Fan6588cc92019-11-20 13:26:04 +0900382 elif constants.ANDROID_VM_PACKAGE_KEYWORD in package_name:
Federico 'Morg' Pareschi041ee652020-03-10 15:09:42 +0900383 target_list = {
384 constants.ANDROID_VMPI_BUILD_BRANCH:
385 constants.ANDROID_VMPI_BUILD_TARGETS,
386 constants.ANDROID_VMMST_BUILD_BRANCH:
387 constants.ANDROID_VMMST_BUILD_TARGETS,
388 constants.ANDROID_VMRVC_BUILD_BRANCH:
389 constants.ANDROID_VMRVC_BUILD_TARGETS,
390 }
391 else:
392 raise ValueError('Unknown package: %s' % package_name)
393 target = target_list.get(build_branch)
394 if not target:
Qijiang Fan6588cc92019-11-20 13:26:04 +0900395 raise ValueError('Unknown branch: %s' % build_branch)
Federico 'Morg' Pareschi041ee652020-03-10 15:09:42 +0900396 return target
Nicolas Norvez4bd854f2017-05-23 10:04:45 -0700397
398
Shao-Chuan Lee085e3d72020-05-11 16:00:42 +0900399def PrintUprevMetadata(build_branch, stable_candidate, new_ebuild):
400 """Shows metadata on buildbot page at UprevAndroid step.
David Rileyc0da9d92016-02-01 12:11:01 -0800401
402 Args:
Shao-Chuan Lee085e3d72020-05-11 16:00:42 +0900403 build_branch: The branch of Android builds.
404 stable_candidate: The existing stable ebuild.
405 new_ebuild: The newly written ebuild.
David Rileyc0da9d92016-02-01 12:11:01 -0800406 """
Shao-Chuan Lee085e3d72020-05-11 16:00:42 +0900407 # Examples:
408 # "android-container-pi revved 6461825-r1 -> 6468247-r1"
409 # "android-container-pi revved 6461825-r1 -> 6461825-r2 (ebuild update only)"
410 msg = '%s revved %s -> %s' % (stable_candidate.pkgname,
411 stable_candidate.version,
412 new_ebuild.version)
413
414 old_android = stable_candidate.version_no_rev
415 new_android = new_ebuild.version_no_rev
416
417 if old_android == new_android:
418 msg += ' (ebuild update only)'
419 else:
420 ab_link = ('https://android-build.googleplex.com'
421 '/builds/%s/branches/%s/cls?end=%s'
422 % (new_android, build_branch, old_android))
423 logging.PrintBuildbotLink('Android changelog', ab_link)
424
425 logging.PrintBuildbotStepText(msg)
David Rileyc0da9d92016-02-01 12:11:01 -0800426
427
khmel@chromium.orgd3ec3d72020-04-29 15:57:35 -0700428def UpdateDataCollectorArtifacts(android_version,
429 runtime_artifacts_bucket_url):
430 r"""Finds and includes into variables artifacts from arc.DataCollector.
431
432 Args:
433 android_version: The \d+ build id of Android.
434 runtime_artifacts_bucket_url: root of runtime artifacts
435
436 Returns:
437 dictionary with filled ebuild variables.
438 """
439
440 variables = {}
441 buckets = ['ureadahead_pack', 'gms_core_cache']
442 archs = ['arm', 'arm64', 'x86', 'x86_64']
443 build_types = ['user', 'userdebug']
444
445 version_reference = '${PV}'
446 gs_context = gs.GSContext()
447 for bucket in buckets:
448 for arch in archs:
449 for build_type in build_types:
450 path = (f'{runtime_artifacts_bucket_url}/{bucket}_{arch}_{build_type}_'
Yury Khmele1b74402020-05-18 08:41:35 -0700451 f'{android_version}.tar')
khmel@chromium.orgd3ec3d72020-04-29 15:57:35 -0700452 if gs_context.Exists(path):
453 variables[(f'{arch}_{build_type}_{bucket}').upper()] = (
454 f'{runtime_artifacts_bucket_url}/{bucket}_{arch}_{build_type}_'
455 f'{version_reference}.tar')
456
457 return variables
458
459
Hidehiko Abe4fd94ae2017-01-24 18:59:55 +0900460def MarkAndroidEBuildAsStable(stable_candidate, unstable_ebuild,
461 android_package, android_version, package_dir,
khmel@chromium.orgd3ec3d72020-04-29 15:57:35 -0700462 build_branch, arc_bucket_url,
463 runtime_artifacts_bucket_url,
464 build_targets):
David Rileyc0da9d92016-02-01 12:11:01 -0800465 r"""Uprevs the Android ebuild.
466
467 This is the main function that uprevs from a stable candidate
468 to its new version.
469
470 Args:
471 stable_candidate: ebuild that corresponds to the stable ebuild we are
472 revving from. If None, builds the a new ebuild given the version
473 with revision set to 1.
474 unstable_ebuild: ebuild corresponding to the unstable ebuild for Android.
Hidehiko Abe4fd94ae2017-01-24 18:59:55 +0900475 android_package: android package name.
David Rileyc0da9d92016-02-01 12:11:01 -0800476 android_version: The \d+ build id of Android.
David Rileyc0da9d92016-02-01 12:11:01 -0800477 package_dir: Path to the android-container package dir.
David Riley73f00d92016-02-16 18:54:20 -0800478 build_branch: branch of Android builds.
479 arc_bucket_url: URL of the target ARC build gs bucket.
khmel@chromium.orgd3ec3d72020-04-29 15:57:35 -0700480 runtime_artifacts_bucket_url: root of runtime artifacts
Nicolas Norvez4bd854f2017-05-23 10:04:45 -0700481 build_targets: build targets for this particular Android branch.
David Rileyc0da9d92016-02-01 12:11:01 -0800482
483 Returns:
484 Full portage version atom (including rc's, etc) that was revved.
485 """
486 def IsTheNewEBuildRedundant(new_ebuild, stable_ebuild):
487 """Returns True if the new ebuild is redundant.
488
489 This is True if there if the current stable ebuild is the exact same copy
490 of the new one.
491 """
492 if not stable_ebuild:
493 return False
494
David Riley676f5402016-02-12 17:24:23 -0800495 if stable_candidate.version_no_rev == new_ebuild.version_no_rev:
David Rileyc0da9d92016-02-01 12:11:01 -0800496 return filecmp.cmp(
497 new_ebuild.ebuild_path, stable_ebuild.ebuild_path, shallow=False)
khmel@chromium.orgd3ec3d72020-04-29 15:57:35 -0700498 return False
David Rileyc0da9d92016-02-01 12:11:01 -0800499
500 # Case where we have the last stable candidate with same version just rev.
David Riley676f5402016-02-12 17:24:23 -0800501 if stable_candidate and stable_candidate.version_no_rev == android_version:
David Rileyc0da9d92016-02-01 12:11:01 -0800502 new_ebuild_path = '%s-r%d.ebuild' % (
503 stable_candidate.ebuild_path_no_revision,
504 stable_candidate.current_revision + 1)
505 else:
Hidehiko Abe4fd94ae2017-01-24 18:59:55 +0900506 pf = '%s-%s-r1' % (android_package, android_version)
David Rileyc0da9d92016-02-01 12:11:01 -0800507 new_ebuild_path = os.path.join(package_dir, '%s.ebuild' % pf)
508
David Riley73f00d92016-02-16 18:54:20 -0800509 variables = {'BASE_URL': arc_bucket_url}
Mike Frysinger0bdbc102019-06-13 15:27:29 -0400510 for build, (target, _) in build_targets.items():
David Riley73f00d92016-02-16 18:54:20 -0800511 variables[build + '_TARGET'] = '%s-%s' % (build_branch, target)
David Rileyc0da9d92016-02-01 12:11:01 -0800512
khmel@chromium.orgd3ec3d72020-04-29 15:57:35 -0700513 variables.update(UpdateDataCollectorArtifacts(
514 android_version, runtime_artifacts_bucket_url))
515
David Rileyc0da9d92016-02-01 12:11:01 -0800516 portage_util.EBuild.MarkAsStable(
517 unstable_ebuild.ebuild_path, new_ebuild_path,
518 variables, make_stable=True)
519 new_ebuild = portage_util.EBuild(new_ebuild_path)
520
521 # Determine whether this is ebuild is redundant.
522 if IsTheNewEBuildRedundant(new_ebuild, stable_candidate):
523 msg = 'Previous ebuild with same version found and ebuild is redundant.'
524 logging.info(msg)
Shao-Chuan Lee085e3d72020-05-11 16:00:42 +0900525 logging.PrintBuildbotStepText('%s %s not revved'
526 % (stable_candidate.pkgname,
527 stable_candidate.version))
David Rileyc0da9d92016-02-01 12:11:01 -0800528 os.unlink(new_ebuild_path)
529 return None
530
Shao-Chuan Lee085e3d72020-05-11 16:00:42 +0900531 # PFQ runs should always be able to find a stable candidate.
David Rileyc0da9d92016-02-01 12:11:01 -0800532 if stable_candidate:
Shao-Chuan Lee085e3d72020-05-11 16:00:42 +0900533 PrintUprevMetadata(build_branch, stable_candidate, new_ebuild)
David Rileyc0da9d92016-02-01 12:11:01 -0800534
535 git.RunGit(package_dir, ['add', new_ebuild_path])
536 if stable_candidate and not stable_candidate.IsSticky():
537 git.RunGit(package_dir, ['rm', stable_candidate.ebuild_path])
538
539 # Update ebuild manifest and git add it.
540 gen_manifest_cmd = ['ebuild', new_ebuild_path, 'manifest', '--force']
Mike Frysinger45602c72019-09-22 02:15:11 -0400541 cros_build_lib.run(gen_manifest_cmd, extra_env=None, print_cmd=True)
David Rileyc0da9d92016-02-01 12:11:01 -0800542 git.RunGit(package_dir, ['add', 'Manifest'])
543
544 portage_util.EBuild.CommitChange(
Hidehiko Abe4fd94ae2017-01-24 18:59:55 +0900545 _GIT_COMMIT_MESSAGE % {'android_package': android_package,
David Rileyc0da9d92016-02-01 12:11:01 -0800546 'android_version': android_version},
547 package_dir)
548
549 return '%s-%s' % (new_ebuild.package, new_ebuild.version)
550
551
552def GetParser():
553 """Creates the argument parser."""
554 parser = commandline.ArgumentParser()
555 parser.add_argument('-b', '--boards')
556 parser.add_argument('--android_bucket_url',
David Riley73f00d92016-02-16 18:54:20 -0800557 default=constants.ANDROID_BUCKET_URL,
558 type='gs_path')
David Rileyc0da9d92016-02-01 12:11:01 -0800559 parser.add_argument('--android_build_branch',
Shuhei Takahashi6d02c192017-04-05 14:01:24 +0900560 required=True,
561 help='Android branch to import from. '
562 'Ex: git_mnc-dr-arc-dev')
Hidehiko Abe4fd94ae2017-01-24 18:59:55 +0900563 parser.add_argument('--android_package',
564 default=constants.ANDROID_PACKAGE_NAME)
David Riley73f00d92016-02-16 18:54:20 -0800565 parser.add_argument('--arc_bucket_url',
566 default=constants.ARC_BUCKET_URL,
567 type='gs_path')
David Rileyc0da9d92016-02-01 12:11:01 -0800568 parser.add_argument('-f', '--force_version',
569 help='Android build id to use')
570 parser.add_argument('-s', '--srcroot',
571 default=os.path.join(os.environ['HOME'], 'trunk', 'src'),
572 help='Path to the src directory')
573 parser.add_argument('-t', '--tracking_branch', default='cros/master',
574 help='Branch we are tracking changes against')
khmel@chromium.orgd3ec3d72020-04-29 15:57:35 -0700575 parser.add_argument('--runtime_artifacts_bucket_url',
576 default=_RUNTIME_ARTIFACTS_BUCKET_URL,
577 type='gs_path')
David Rileyc0da9d92016-02-01 12:11:01 -0800578 return parser
579
580
581def main(argv):
Hidehiko Abec9ecf262017-07-05 15:17:41 +0900582 logging.EnableBuildbotMarkers()
David Rileyc0da9d92016-02-01 12:11:01 -0800583 parser = GetParser()
584 options = parser.parse_args(argv)
585 options.Freeze()
586
587 overlay_dir = os.path.abspath(_OVERLAY_DIR % {'srcroot': options.srcroot})
Hidehiko Abe4fd94ae2017-01-24 18:59:55 +0900588 android_package_dir = os.path.join(
589 overlay_dir,
590 portage_util.GetFullAndroidPortagePackageName(options.android_package))
David Rileyc0da9d92016-02-01 12:11:01 -0800591 version_to_uprev = None
David Rileyc0da9d92016-02-01 12:11:01 -0800592
593 (unstable_ebuild, stable_ebuilds) = FindAndroidCandidates(android_package_dir)
David Riley73f00d92016-02-16 18:54:20 -0800594 acls = MakeAclDict(android_package_dir)
Qijiang Fan6588cc92019-11-20 13:26:04 +0900595 build_targets = MakeBuildTargetDict(options.android_package,
596 options.android_build_branch)
Hidehiko Abe1ebc25d2016-07-28 02:24:37 +0900597 # Mirror artifacts, i.e., images and some sdk tools (e.g., adb, aapt).
598 version_to_uprev = MirrorArtifacts(options.android_bucket_url,
599 options.android_build_branch,
600 options.arc_bucket_url, acls,
Nicolas Norvez4bd854f2017-05-23 10:04:45 -0700601 build_targets,
Hidehiko Abe1ebc25d2016-07-28 02:24:37 +0900602 options.force_version)
603
David Rileyc0da9d92016-02-01 12:11:01 -0800604 stable_candidate = portage_util.BestEBuild(stable_ebuilds)
605
606 if stable_candidate:
Lann Martinffb95162018-08-28 12:02:54 -0600607 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,
khmel@chromium.orgd3ec3d72020-04-29 15:57:35 -0700626 options.android_build_branch, options.arc_bucket_url,
627 options.runtime_artifacts_bucket_url, build_targets)
David Rileyc0da9d92016-02-01 12:11:01 -0800628 if android_version_atom:
629 if options.boards:
630 cros_mark_as_stable.CleanStalePackages(options.srcroot,
631 options.boards.split(':'),
632 [android_version_atom])
633
634 # Explicit print to communicate to caller.
635 print('ANDROID_VERSION_ATOM=%s' % android_version_atom)