blob: 714a188a64d66093d760ddb7d385671c738a6794 [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
Junichi Uekawad21f94d2020-07-27 15:50:05 +090025import json
David Rileyc0da9d92016-02-01 12:11:01 -080026import os
Hidehiko Abe12727dd2016-05-27 23:23:45 +090027import re
khmel@google.com96c193e2018-05-10 14:00:38 -070028import time
Mike Frysinger00a02292020-04-19 06:28:03 -040029import sys
David Rileyc0da9d92016-02-01 12:11:01 -080030
Aviv Keshetb7519e12016-10-04 00:50:00 -070031from chromite.lib import constants
David Rileyc0da9d92016-02-01 12:11:01 -080032from chromite.lib import commandline
33from chromite.lib import cros_build_lib
34from chromite.lib import cros_logging as logging
35from chromite.lib import git
36from chromite.lib import gs
37from chromite.lib import portage_util
38from chromite.scripts import cros_mark_as_stable
39
40
Mike Frysinger00a02292020-04-19 06:28:03 -040041assert sys.version_info >= (3, 6), 'This module requires Python 3.6+'
42
43
David Rileyc0da9d92016-02-01 12:11:01 -080044# Dir where all the action happens.
45_OVERLAY_DIR = '%(srcroot)s/private-overlays/project-cheets-private/'
46
Junichi Uekawa6d61ab02020-04-15 14:52:28 +090047_GIT_COMMIT_MESSAGE = """Marking latest for %(android_package)s ebuild with \
48version %(android_version)s as stable.
49
50BUG=None
51TEST=CQ
52"""
David Rileyc0da9d92016-02-01 12:11:01 -080053
khmel@chromium.orgd3ec3d72020-04-29 15:57:35 -070054_RUNTIME_ARTIFACTS_BUCKET_URL = 'gs://chromeos-arc-images/runtime_artifacts'
David Rileyc0da9d92016-02-01 12:11:01 -080055
Hidehiko Abe1ebc25d2016-07-28 02:24:37 +090056def IsBuildIdValid(bucket_url, build_branch, build_id, targets):
David Rileyc0da9d92016-02-01 12:11:01 -080057 """Checks that a specific build_id is valid.
58
59 Looks for that build_id for all builds. Confirms that the subpath can
60 be found and that the zip file is present in that subdirectory.
61
62 Args:
63 bucket_url: URL of Android build gs bucket
64 build_branch: branch of Android builds
65 build_id: A string. The Android build id number to check.
Hidehiko Abe1ebc25d2016-07-28 02:24:37 +090066 targets: Dict from build key to (targe build suffix, artifact file pattern)
67 pair.
David Rileyc0da9d92016-02-01 12:11:01 -080068
69 Returns:
70 Returns subpaths dictionary if build_id is valid.
71 None if the build_id is not valid.
72 """
73 gs_context = gs.GSContext()
74 subpaths_dict = {}
Mike Frysinger0bdbc102019-06-13 15:27:29 -040075 for build, (target, _) in targets.items():
David Rileyc0da9d92016-02-01 12:11:01 -080076 build_dir = '%s-%s' % (build_branch, target)
77 build_id_path = os.path.join(bucket_url, build_dir, build_id)
78
79 # Find name of subpath.
80 try:
81 subpaths = gs_context.List(build_id_path)
82 except gs.GSNoSuchKey:
Mike Frysinger968c1142020-05-09 00:37:56 -040083 logging.warning(
David Rileyc0da9d92016-02-01 12:11:01 -080084 'Directory [%s] does not contain any subpath, ignoring it.',
85 build_id_path)
86 return None
87 if len(subpaths) > 1:
Mike Frysinger968c1142020-05-09 00:37:56 -040088 logging.warning(
David Rileyc0da9d92016-02-01 12:11:01 -080089 'Directory [%s] contains more than one subpath, ignoring it.',
90 build_id_path)
91 return None
92
93 subpath_dir = subpaths[0].url.rstrip('/')
94 subpath_name = os.path.basename(subpath_dir)
95
96 # Look for a zipfile ending in the build_id number.
97 try:
Hidehiko Abe12727dd2016-05-27 23:23:45 +090098 gs_context.List(subpath_dir)
David Rileyc0da9d92016-02-01 12:11:01 -080099 except gs.GSNoSuchKey:
Mike Frysinger968c1142020-05-09 00:37:56 -0400100 logging.warning(
Hidehiko Abe12727dd2016-05-27 23:23:45 +0900101 'Did not find a file for build id [%s] in directory [%s].',
David Rileyc0da9d92016-02-01 12:11:01 -0800102 build_id, subpath_dir)
103 return None
104
105 # Record subpath for the build.
106 subpaths_dict[build] = subpath_name
107
108 # If we got here, it means we found an appropriate build for all platforms.
109 return subpaths_dict
110
111
Hidehiko Abe1ebc25d2016-07-28 02:24:37 +0900112def GetLatestBuild(bucket_url, build_branch, targets):
David Rileyc0da9d92016-02-01 12:11:01 -0800113 """Searches the gs bucket for the latest green build.
114
115 Args:
116 bucket_url: URL of Android build gs bucket
117 build_branch: branch of Android builds
Hidehiko Abe1ebc25d2016-07-28 02:24:37 +0900118 targets: Dict from build key to (targe build suffix, artifact file pattern)
119 pair.
David Rileyc0da9d92016-02-01 12:11:01 -0800120
121 Returns:
122 Tuple of (latest version string, subpaths dictionary)
123 If no latest build can be found, returns None, None
124 """
125 gs_context = gs.GSContext()
126 common_build_ids = None
127 # Find builds for each target.
Mike Frysinger0bdbc102019-06-13 15:27:29 -0400128 for target, _ in targets.values():
David Rileyc0da9d92016-02-01 12:11:01 -0800129 build_dir = '-'.join((build_branch, target))
130 base_path = os.path.join(bucket_url, build_dir)
131 build_ids = []
132 for gs_result in gs_context.List(base_path):
133 # Remove trailing slashes and get the base name, which is the build_id.
134 build_id = os.path.basename(gs_result.url.rstrip('/'))
135 if not build_id.isdigit():
Mike Frysinger968c1142020-05-09 00:37:56 -0400136 logging.warning('Directory [%s] does not look like a valid build_id.',
137 gs_result.url)
David Rileyc0da9d92016-02-01 12:11:01 -0800138 continue
139 build_ids.append(build_id)
140
141 # Update current list of builds.
142 if common_build_ids is None:
143 # First run, populate it with the first platform.
144 common_build_ids = set(build_ids)
145 else:
146 # Already populated, find the ones that are common.
147 common_build_ids.intersection_update(build_ids)
148
149 if common_build_ids is None:
Mike Frysinger968c1142020-05-09 00:37:56 -0400150 logging.warning('Did not find a build_id common to all platforms.')
David Rileyc0da9d92016-02-01 12:11:01 -0800151 return None, None
152
153 # Otherwise, find the most recent one that is valid.
154 for build_id in sorted(common_build_ids, key=int, reverse=True):
Hidehiko Abe1ebc25d2016-07-28 02:24:37 +0900155 subpaths = IsBuildIdValid(bucket_url, build_branch, build_id, targets)
David Rileyc0da9d92016-02-01 12:11:01 -0800156 if subpaths:
157 return build_id, subpaths
158
159 # If not found, no build_id is valid.
Mike Frysinger968c1142020-05-09 00:37:56 -0400160 logging.warning('Did not find a build_id valid on all platforms.')
David Rileyc0da9d92016-02-01 12:11:01 -0800161 return None, None
162
163
164def FindAndroidCandidates(package_dir):
165 """Return a tuple of Android's unstable ebuild and stable ebuilds.
166
167 Args:
168 package_dir: The path to where the package ebuild is stored.
169
170 Returns:
171 Tuple [unstable_ebuild, stable_ebuilds].
172
173 Raises:
174 Exception: if no unstable ebuild exists for Android.
175 """
176 stable_ebuilds = []
177 unstable_ebuilds = []
178 for path in glob.glob(os.path.join(package_dir, '*.ebuild')):
179 ebuild = portage_util.EBuild(path)
180 if ebuild.version == '9999':
181 unstable_ebuilds.append(ebuild)
182 else:
183 stable_ebuilds.append(ebuild)
184
185 # Apply some sanity checks.
186 if not unstable_ebuilds:
187 raise Exception('Missing 9999 ebuild for %s' % package_dir)
188 if not stable_ebuilds:
Lann Martinffb95162018-08-28 12:02:54 -0600189 logging.warning('Missing stable ebuild for %s', package_dir)
David Rileyc0da9d92016-02-01 12:11:01 -0800190
191 return portage_util.BestEBuild(unstable_ebuilds), stable_ebuilds
192
193
Nicolas Norvezb08f54d2016-12-05 17:58:54 -0800194def _GetArcBasename(build, basename):
195 """Tweaks filenames between Android bucket and ARC++ bucket.
196
197 Android builders create build artifacts with the same name for -user and
198 -userdebug builds, which breaks the android-container ebuild (b/33072485).
199 When copying the artifacts from the Android bucket to the ARC++ bucket some
200 artifacts will be renamed from the usual pattern
201 *cheets_${ARCH}-target_files-S{VERSION}.zip to
202 cheets_${BUILD_NAME}-target_files-S{VERSION}.zip which will typically look
203 like cheets_(${LABEL})*${ARCH}_userdebug-target_files-S{VERSION}.zip.
204
205 Args:
206 build: the build being mirrored, e.g. 'X86', 'ARM', 'X86_USERDEBUG'.
207 basename: the basename of the artifact to copy.
208
209 Returns:
210 The basename of the destination.
211 """
212 if build not in constants.ARC_BUILDS_NEED_ARTIFACTS_RENAMED:
213 return basename
Yūki Ishiief1ada92018-03-27 15:46:15 +0900214 if basename in constants.ARC_ARTIFACTS_RENAME_NOT_NEEDED:
215 return basename
Nicolas Norvezb08f54d2016-12-05 17:58:54 -0800216 to_discard, sep, to_keep = basename.partition('-')
217 if not sep:
218 logging.error(('Build %s: Could not find separator "-" in artifact'
219 ' basename %s'), build, basename)
220 return basename
Bernie Thompson63ed5612017-08-16 12:27:34 -0700221 if 'cheets_' in to_discard:
222 return 'cheets_%s-%s' % (build.lower(), to_keep)
223 elif 'bertha_' in to_discard:
224 return 'bertha_%s-%s' % (build.lower(), to_keep)
225 logging.error('Build %s: Unexpected artifact basename %s',
226 build, basename)
227 return basename
Nicolas Norvezb08f54d2016-12-05 17:58:54 -0800228
229
David Riley73f00d92016-02-16 18:54:20 -0800230def CopyToArcBucket(android_bucket_url, build_branch, build_id, subpaths,
Hidehiko Abe1ebc25d2016-07-28 02:24:37 +0900231 targets, arc_bucket_url, acls):
David Riley73f00d92016-02-16 18:54:20 -0800232 """Copies from source Android bucket to ARC++ specific bucket.
233
234 Copies each build to the ARC bucket eliminating the subpath.
235 Applies build specific ACLs for each file.
236
237 Args:
238 android_bucket_url: URL of Android build gs bucket
239 build_branch: branch of Android builds
240 build_id: A string. The Android build id number to check.
241 subpaths: Subpath dictionary for each build to copy.
Hidehiko Abe1ebc25d2016-07-28 02:24:37 +0900242 targets: Dict from build key to (targe build suffix, artifact file pattern)
243 pair.
David Riley73f00d92016-02-16 18:54:20 -0800244 arc_bucket_url: URL of the target ARC build gs bucket
245 acls: ACLs dictionary for each build to copy.
246 """
247 gs_context = gs.GSContext()
Mike Frysinger0bdbc102019-06-13 15:27:29 -0400248 for build, subpath in subpaths.items():
Hidehiko Abe1ebc25d2016-07-28 02:24:37 +0900249 target, pattern = targets[build]
David Riley73f00d92016-02-16 18:54:20 -0800250 build_dir = '%s-%s' % (build_branch, target)
251 android_dir = os.path.join(android_bucket_url, build_dir, build_id, subpath)
252 arc_dir = os.path.join(arc_bucket_url, build_dir, build_id)
253
Hidehiko Abe12727dd2016-05-27 23:23:45 +0900254 # Copy all target files from android_dir to arc_dir, setting ACLs.
255 for targetfile in gs_context.List(android_dir):
256 if re.search(pattern, targetfile.url):
257 basename = os.path.basename(targetfile.url)
Nicolas Norvezb08f54d2016-12-05 17:58:54 -0800258 arc_path = os.path.join(arc_dir, _GetArcBasename(build, basename))
David Riley73f00d92016-02-16 18:54:20 -0800259 acl = acls[build]
260 needs_copy = True
khmel@google.com96c193e2018-05-10 14:00:38 -0700261 retry_count = 2
David Riley73f00d92016-02-16 18:54:20 -0800262
khmel@google.com96c193e2018-05-10 14:00:38 -0700263 # Retry in case race condition when several boards trying to copy the
264 # same resource
265 while True:
266 # Check a pre-existing file with the original source.
267 if gs_context.Exists(arc_path):
268 if (gs_context.Stat(targetfile.url).hash_crc32c !=
269 gs_context.Stat(arc_path).hash_crc32c):
Mike Frysinger968c1142020-05-09 00:37:56 -0400270 logging.warning('Removing incorrect file %s', arc_path)
khmel@google.com96c193e2018-05-10 14:00:38 -0700271 gs_context.Remove(arc_path)
272 else:
273 logging.info('Skipping already copied file %s', arc_path)
274 needs_copy = False
David Riley73f00d92016-02-16 18:54:20 -0800275
khmel@google.com96c193e2018-05-10 14:00:38 -0700276 # Copy if necessary, and set the ACL unconditionally.
277 # The Stat() call above doesn't verify the ACL is correct and
278 # the ChangeACL should be relatively cheap compared to the copy.
279 # This covers the following caes:
280 # - handling an interrupted copy from a previous run.
281 # - rerunning the copy in case one of the googlestorage_acl_X.txt
282 # files changes (e.g. we add a new variant which reuses a build).
283 if needs_copy:
284 logging.info('Copying %s -> %s (acl %s)',
285 targetfile.url, arc_path, acl)
286 try:
287 gs_context.Copy(targetfile.url, arc_path, version=0)
288 except gs.GSContextPreconditionFailed as error:
289 if not retry_count:
290 raise error
291 # Retry one more time after a short delay
292 logging.warning('Will retry copying %s -> %s',
293 targetfile.url, arc_path)
294 time.sleep(5)
295 retry_count = retry_count - 1
296 continue
297 gs_context.ChangeACL(arc_path, acl_args_file=acl)
298 break
David Riley73f00d92016-02-16 18:54:20 -0800299
300
Hidehiko Abe1ebc25d2016-07-28 02:24:37 +0900301def MirrorArtifacts(android_bucket_url, android_build_branch, arc_bucket_url,
302 acls, targets, version=None):
303 """Mirrors artifacts from Android bucket to ARC bucket.
304
305 First, this function identifies which build version should be copied,
306 if not given. Please see GetLatestBuild() and IsBuildIdValid() for details.
307
308 On build version identified, then copies target artifacts to the ARC bucket,
309 with setting ACLs.
310
311 Args:
312 android_bucket_url: URL of Android build gs bucket
313 android_build_branch: branch of Android builds
314 arc_bucket_url: URL of the target ARC build gs bucket
315 acls: ACLs dictionary for each build to copy.
316 targets: Dict from build key to (targe build suffix, artifact file pattern)
317 pair.
318 version: (optional) A string. The Android build id number to check.
319 If not passed, detect latest good build version.
320
321 Returns:
322 Mirrored version.
323 """
324 if version:
325 subpaths = IsBuildIdValid(
326 android_bucket_url, android_build_branch, version, targets)
327 if not subpaths:
Lann Martinffb95162018-08-28 12:02:54 -0600328 logging.error('Requested build %s is not valid', version)
Hidehiko Abe1ebc25d2016-07-28 02:24:37 +0900329 else:
330 version, subpaths = GetLatestBuild(
331 android_bucket_url, android_build_branch, targets)
332
333 CopyToArcBucket(android_bucket_url, android_build_branch, version, subpaths,
334 targets, arc_bucket_url, acls)
khmel@google.com778a1cd2018-04-13 11:11:58 -0700335
Hidehiko Abe1ebc25d2016-07-28 02:24:37 +0900336 return version
337
338
David Riley73f00d92016-02-16 18:54:20 -0800339def MakeAclDict(package_dir):
340 """Creates a dictionary of acl files for each build type.
341
342 Args:
343 package_dir: The path to where the package acl files are stored.
344
345 Returns:
346 Returns acls dictionary.
347 """
348 return dict(
349 (k, os.path.join(package_dir, v))
350 for k, v in constants.ARC_BUCKET_ACLS.items()
351 )
352
353
Qijiang Fan6588cc92019-11-20 13:26:04 +0900354def MakeBuildTargetDict(package_name, build_branch):
Nicolas Norvez4bd854f2017-05-23 10:04:45 -0700355 """Creates a dictionary of build targets.
356
Bernie Thompson63ed5612017-08-16 12:27:34 -0700357 Not all targets are common between branches, for example
Nicolas Norvez4bd854f2017-05-23 10:04:45 -0700358 sdk_google_cheets_x86 only exists on N.
359 This generates a dictionary listing the available build targets for a
360 specific branch.
361
362 Args:
Qijiang Fan6588cc92019-11-20 13:26:04 +0900363 package_name: package name of chromeos arc package.
Nicolas Norvez4bd854f2017-05-23 10:04:45 -0700364 build_branch: branch of Android builds.
365
366 Returns:
367 Returns build target dictionary.
368
369 Raises:
370 ValueError: if the Android build branch is invalid.
371 """
Qijiang Fan6588cc92019-11-20 13:26:04 +0900372 if constants.ANDROID_CONTAINER_PACKAGE_KEYWORD in package_name:
Federico 'Morg' Pareschi041ee652020-03-10 15:09:42 +0900373 target_list = {
Federico 'Morg' Pareschi041ee652020-03-10 15:09:42 +0900374 constants.ANDROID_PI_BUILD_BRANCH:
375 constants.ANDROID_PI_BUILD_TARGETS,
Federico 'Morg' Pareschi041ee652020-03-10 15:09:42 +0900376 }
Qijiang Fan6588cc92019-11-20 13:26:04 +0900377 elif constants.ANDROID_VM_PACKAGE_KEYWORD in package_name:
Federico 'Morg' Pareschi041ee652020-03-10 15:09:42 +0900378 target_list = {
Federico 'Morg' Pareschi041ee652020-03-10 15:09:42 +0900379 constants.ANDROID_VMMST_BUILD_BRANCH:
380 constants.ANDROID_VMMST_BUILD_TARGETS,
381 constants.ANDROID_VMRVC_BUILD_BRANCH:
382 constants.ANDROID_VMRVC_BUILD_TARGETS,
383 }
384 else:
385 raise ValueError('Unknown package: %s' % package_name)
386 target = target_list.get(build_branch)
387 if not target:
Qijiang Fan6588cc92019-11-20 13:26:04 +0900388 raise ValueError('Unknown branch: %s' % build_branch)
Federico 'Morg' Pareschi041ee652020-03-10 15:09:42 +0900389 return target
Nicolas Norvez4bd854f2017-05-23 10:04:45 -0700390
391
Shao-Chuan Lee085e3d72020-05-11 16:00:42 +0900392def PrintUprevMetadata(build_branch, stable_candidate, new_ebuild):
393 """Shows metadata on buildbot page at UprevAndroid step.
David Rileyc0da9d92016-02-01 12:11:01 -0800394
395 Args:
Shao-Chuan Lee085e3d72020-05-11 16:00:42 +0900396 build_branch: The branch of Android builds.
397 stable_candidate: The existing stable ebuild.
398 new_ebuild: The newly written ebuild.
David Rileyc0da9d92016-02-01 12:11:01 -0800399 """
Shao-Chuan Lee085e3d72020-05-11 16:00:42 +0900400 # Examples:
401 # "android-container-pi revved 6461825-r1 -> 6468247-r1"
402 # "android-container-pi revved 6461825-r1 -> 6461825-r2 (ebuild update only)"
403 msg = '%s revved %s -> %s' % (stable_candidate.pkgname,
404 stable_candidate.version,
405 new_ebuild.version)
406
407 old_android = stable_candidate.version_no_rev
408 new_android = new_ebuild.version_no_rev
409
410 if old_android == new_android:
411 msg += ' (ebuild update only)'
412 else:
413 ab_link = ('https://android-build.googleplex.com'
414 '/builds/%s/branches/%s/cls?end=%s'
415 % (new_android, build_branch, old_android))
416 logging.PrintBuildbotLink('Android changelog', ab_link)
417
418 logging.PrintBuildbotStepText(msg)
Junichi Uekawad21f94d2020-07-27 15:50:05 +0900419 logging.PrintKitchenSetBuildProperty('android_uprev', json.dumps({
420 'branch': build_branch,
421 'new': new_ebuild.version,
422 'old': stable_candidate.version,
423 'pkgname': stable_candidate.pkgname,
424 }))
David Rileyc0da9d92016-02-01 12:11:01 -0800425
426
khmel@chromium.orgd3ec3d72020-04-29 15:57:35 -0700427def UpdateDataCollectorArtifacts(android_version,
428 runtime_artifacts_bucket_url):
429 r"""Finds and includes into variables artifacts from arc.DataCollector.
430
431 Args:
432 android_version: The \d+ build id of Android.
433 runtime_artifacts_bucket_url: root of runtime artifacts
434
435 Returns:
436 dictionary with filled ebuild variables.
437 """
438
439 variables = {}
440 buckets = ['ureadahead_pack', 'gms_core_cache']
441 archs = ['arm', 'arm64', 'x86', 'x86_64']
442 build_types = ['user', 'userdebug']
443
444 version_reference = '${PV}'
445 gs_context = gs.GSContext()
446 for bucket in buckets:
447 for arch in archs:
448 for build_type in build_types:
449 path = (f'{runtime_artifacts_bucket_url}/{bucket}_{arch}_{build_type}_'
Yury Khmele1b74402020-05-18 08:41:35 -0700450 f'{android_version}.tar')
khmel@chromium.orgd3ec3d72020-04-29 15:57:35 -0700451 if gs_context.Exists(path):
452 variables[(f'{arch}_{build_type}_{bucket}').upper()] = (
453 f'{runtime_artifacts_bucket_url}/{bucket}_{arch}_{build_type}_'
454 f'{version_reference}.tar')
455
456 return variables
457
458
Hidehiko Abe4fd94ae2017-01-24 18:59:55 +0900459def MarkAndroidEBuildAsStable(stable_candidate, unstable_ebuild,
460 android_package, android_version, package_dir,
khmel@chromium.orgd3ec3d72020-04-29 15:57:35 -0700461 build_branch, arc_bucket_url,
462 runtime_artifacts_bucket_url,
463 build_targets):
David Rileyc0da9d92016-02-01 12:11:01 -0800464 r"""Uprevs the Android ebuild.
465
466 This is the main function that uprevs from a stable candidate
467 to its new version.
468
469 Args:
470 stable_candidate: ebuild that corresponds to the stable ebuild we are
471 revving from. If None, builds the a new ebuild given the version
472 with revision set to 1.
473 unstable_ebuild: ebuild corresponding to the unstable ebuild for Android.
Hidehiko Abe4fd94ae2017-01-24 18:59:55 +0900474 android_package: android package name.
David Rileyc0da9d92016-02-01 12:11:01 -0800475 android_version: The \d+ build id of Android.
David Rileyc0da9d92016-02-01 12:11:01 -0800476 package_dir: Path to the android-container package dir.
David Riley73f00d92016-02-16 18:54:20 -0800477 build_branch: branch of Android builds.
478 arc_bucket_url: URL of the target ARC build gs bucket.
khmel@chromium.orgd3ec3d72020-04-29 15:57:35 -0700479 runtime_artifacts_bucket_url: root of runtime artifacts
Nicolas Norvez4bd854f2017-05-23 10:04:45 -0700480 build_targets: build targets for this particular Android branch.
David Rileyc0da9d92016-02-01 12:11:01 -0800481
482 Returns:
483 Full portage version atom (including rc's, etc) that was revved.
484 """
485 def IsTheNewEBuildRedundant(new_ebuild, stable_ebuild):
486 """Returns True if the new ebuild is redundant.
487
488 This is True if there if the current stable ebuild is the exact same copy
489 of the new one.
490 """
491 if not stable_ebuild:
492 return False
493
David Riley676f5402016-02-12 17:24:23 -0800494 if stable_candidate.version_no_rev == new_ebuild.version_no_rev:
David Rileyc0da9d92016-02-01 12:11:01 -0800495 return filecmp.cmp(
496 new_ebuild.ebuild_path, stable_ebuild.ebuild_path, shallow=False)
khmel@chromium.orgd3ec3d72020-04-29 15:57:35 -0700497 return False
David Rileyc0da9d92016-02-01 12:11:01 -0800498
499 # Case where we have the last stable candidate with same version just rev.
David Riley676f5402016-02-12 17:24:23 -0800500 if stable_candidate and stable_candidate.version_no_rev == android_version:
David Rileyc0da9d92016-02-01 12:11:01 -0800501 new_ebuild_path = '%s-r%d.ebuild' % (
502 stable_candidate.ebuild_path_no_revision,
503 stable_candidate.current_revision + 1)
504 else:
Hidehiko Abe4fd94ae2017-01-24 18:59:55 +0900505 pf = '%s-%s-r1' % (android_package, android_version)
David Rileyc0da9d92016-02-01 12:11:01 -0800506 new_ebuild_path = os.path.join(package_dir, '%s.ebuild' % pf)
507
David Riley73f00d92016-02-16 18:54:20 -0800508 variables = {'BASE_URL': arc_bucket_url}
Mike Frysinger0bdbc102019-06-13 15:27:29 -0400509 for build, (target, _) in build_targets.items():
David Riley73f00d92016-02-16 18:54:20 -0800510 variables[build + '_TARGET'] = '%s-%s' % (build_branch, target)
David Rileyc0da9d92016-02-01 12:11:01 -0800511
khmel@chromium.orgd3ec3d72020-04-29 15:57:35 -0700512 variables.update(UpdateDataCollectorArtifacts(
513 android_version, runtime_artifacts_bucket_url))
514
David Rileyc0da9d92016-02-01 12:11:01 -0800515 portage_util.EBuild.MarkAsStable(
516 unstable_ebuild.ebuild_path, new_ebuild_path,
517 variables, make_stable=True)
518 new_ebuild = portage_util.EBuild(new_ebuild_path)
519
520 # Determine whether this is ebuild is redundant.
521 if IsTheNewEBuildRedundant(new_ebuild, stable_candidate):
522 msg = 'Previous ebuild with same version found and ebuild is redundant.'
523 logging.info(msg)
Shao-Chuan Lee085e3d72020-05-11 16:00:42 +0900524 logging.PrintBuildbotStepText('%s %s not revved'
525 % (stable_candidate.pkgname,
526 stable_candidate.version))
David Rileyc0da9d92016-02-01 12:11:01 -0800527 os.unlink(new_ebuild_path)
528 return None
529
Shao-Chuan Lee085e3d72020-05-11 16:00:42 +0900530 # PFQ runs should always be able to find a stable candidate.
David Rileyc0da9d92016-02-01 12:11:01 -0800531 if stable_candidate:
Shao-Chuan Lee085e3d72020-05-11 16:00:42 +0900532 PrintUprevMetadata(build_branch, stable_candidate, new_ebuild)
David Rileyc0da9d92016-02-01 12:11:01 -0800533
534 git.RunGit(package_dir, ['add', new_ebuild_path])
535 if stable_candidate and not stable_candidate.IsSticky():
536 git.RunGit(package_dir, ['rm', stable_candidate.ebuild_path])
537
538 # Update ebuild manifest and git add it.
539 gen_manifest_cmd = ['ebuild', new_ebuild_path, 'manifest', '--force']
Mike Frysinger45602c72019-09-22 02:15:11 -0400540 cros_build_lib.run(gen_manifest_cmd, extra_env=None, print_cmd=True)
David Rileyc0da9d92016-02-01 12:11:01 -0800541 git.RunGit(package_dir, ['add', 'Manifest'])
542
543 portage_util.EBuild.CommitChange(
Hidehiko Abe4fd94ae2017-01-24 18:59:55 +0900544 _GIT_COMMIT_MESSAGE % {'android_package': android_package,
David Rileyc0da9d92016-02-01 12:11:01 -0800545 'android_version': android_version},
546 package_dir)
547
548 return '%s-%s' % (new_ebuild.package, new_ebuild.version)
549
550
551def GetParser():
552 """Creates the argument parser."""
553 parser = commandline.ArgumentParser()
554 parser.add_argument('-b', '--boards')
555 parser.add_argument('--android_bucket_url',
David Riley73f00d92016-02-16 18:54:20 -0800556 default=constants.ANDROID_BUCKET_URL,
557 type='gs_path')
David Rileyc0da9d92016-02-01 12:11:01 -0800558 parser.add_argument('--android_build_branch',
Shuhei Takahashi6d02c192017-04-05 14:01:24 +0900559 required=True,
560 help='Android branch to import from. '
561 'Ex: git_mnc-dr-arc-dev')
Hidehiko Abe4fd94ae2017-01-24 18:59:55 +0900562 parser.add_argument('--android_package',
563 default=constants.ANDROID_PACKAGE_NAME)
David Riley73f00d92016-02-16 18:54:20 -0800564 parser.add_argument('--arc_bucket_url',
565 default=constants.ARC_BUCKET_URL,
566 type='gs_path')
David Rileyc0da9d92016-02-01 12:11:01 -0800567 parser.add_argument('-f', '--force_version',
568 help='Android build id to use')
569 parser.add_argument('-s', '--srcroot',
570 default=os.path.join(os.environ['HOME'], 'trunk', 'src'),
571 help='Path to the src directory')
572 parser.add_argument('-t', '--tracking_branch', default='cros/master',
573 help='Branch we are tracking changes against')
khmel@chromium.orgd3ec3d72020-04-29 15:57:35 -0700574 parser.add_argument('--runtime_artifacts_bucket_url',
575 default=_RUNTIME_ARTIFACTS_BUCKET_URL,
576 type='gs_path')
David Rileyc0da9d92016-02-01 12:11:01 -0800577 return parser
578
579
580def main(argv):
Hidehiko Abec9ecf262017-07-05 15:17:41 +0900581 logging.EnableBuildbotMarkers()
David Rileyc0da9d92016-02-01 12:11:01 -0800582 parser = GetParser()
583 options = parser.parse_args(argv)
584 options.Freeze()
585
586 overlay_dir = os.path.abspath(_OVERLAY_DIR % {'srcroot': options.srcroot})
Hidehiko Abe4fd94ae2017-01-24 18:59:55 +0900587 android_package_dir = os.path.join(
588 overlay_dir,
589 portage_util.GetFullAndroidPortagePackageName(options.android_package))
David Rileyc0da9d92016-02-01 12:11:01 -0800590 version_to_uprev = None
David Rileyc0da9d92016-02-01 12:11:01 -0800591
592 (unstable_ebuild, stable_ebuilds) = FindAndroidCandidates(android_package_dir)
David Riley73f00d92016-02-16 18:54:20 -0800593 acls = MakeAclDict(android_package_dir)
Qijiang Fan6588cc92019-11-20 13:26:04 +0900594 build_targets = MakeBuildTargetDict(options.android_package,
595 options.android_build_branch)
Hidehiko Abe1ebc25d2016-07-28 02:24:37 +0900596 # Mirror artifacts, i.e., images and some sdk tools (e.g., adb, aapt).
597 version_to_uprev = MirrorArtifacts(options.android_bucket_url,
598 options.android_build_branch,
599 options.arc_bucket_url, acls,
Nicolas Norvez4bd854f2017-05-23 10:04:45 -0700600 build_targets,
Hidehiko Abe1ebc25d2016-07-28 02:24:37 +0900601 options.force_version)
602
David Rileyc0da9d92016-02-01 12:11:01 -0800603 stable_candidate = portage_util.BestEBuild(stable_ebuilds)
604
605 if stable_candidate:
Lann Martinffb95162018-08-28 12:02:54 -0600606 logging.info('Stable candidate found %s', stable_candidate.version)
David Rileyc0da9d92016-02-01 12:11:01 -0800607 else:
608 logging.info('No stable candidate found.')
609
610 tracking_branch = 'remotes/m/%s' % os.path.basename(options.tracking_branch)
611 existing_branch = git.GetCurrentBranch(android_package_dir)
612 work_branch = cros_mark_as_stable.GitBranch(constants.STABLE_EBUILD_BRANCH,
613 tracking_branch,
614 android_package_dir)
615 work_branch.CreateBranch()
616
617 # In the case of uprevving overlays that have patches applied to them,
618 # include the patched changes in the stabilizing branch.
619 if existing_branch:
620 git.RunGit(overlay_dir, ['rebase', existing_branch])
621
622 android_version_atom = MarkAndroidEBuildAsStable(
Hidehiko Abe4fd94ae2017-01-24 18:59:55 +0900623 stable_candidate, unstable_ebuild, options.android_package,
David Riley73f00d92016-02-16 18:54:20 -0800624 version_to_uprev, android_package_dir,
khmel@chromium.orgd3ec3d72020-04-29 15:57:35 -0700625 options.android_build_branch, options.arc_bucket_url,
626 options.runtime_artifacts_bucket_url, build_targets)
David Rileyc0da9d92016-02-01 12:11:01 -0800627 if android_version_atom:
628 if options.boards:
629 cros_mark_as_stable.CleanStalePackages(options.srcroot,
630 options.boards.split(':'),
631 [android_version_atom])
632
633 # Explicit print to communicate to caller.
634 print('ANDROID_VERSION_ATOM=%s' % android_version_atom)