blob: ca2e1efc62b40cf203c052b1eaa0ead6b25ef191 [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
Yury Khmelb009aeb2020-08-19 19:40:00 -0700427def FindDataCollectorArtifacts(gs_context,
428 android_version,
429 runtime_artifacts_bucket_url,
430 version_reference):
khmel@chromium.orgd3ec3d72020-04-29 15:57:35 -0700431 r"""Finds and includes into variables artifacts from arc.DataCollector.
432
Yury Khmelb009aeb2020-08-19 19:40:00 -0700433 This is used from UpdateDataCollectorArtifacts in order to check the
434 particular version.
435
khmel@chromium.orgd3ec3d72020-04-29 15:57:35 -0700436 Args:
Yury Khmelb009aeb2020-08-19 19:40:00 -0700437 gs_context: context to execute gsutil
khmel@chromium.orgd3ec3d72020-04-29 15:57:35 -0700438 android_version: The \d+ build id of Android.
439 runtime_artifacts_bucket_url: root of runtime artifacts
Yury Khmelb009aeb2020-08-19 19:40:00 -0700440 build_branch: build branch. Used to determine the pinned version if exists.
441 version_reference: which version to use as a reference. Could be '${PV}' in
442 case version of data collector artifacts matches the
443 Android version or direct version in case of override.
khmel@chromium.orgd3ec3d72020-04-29 15:57:35 -0700444
445 Returns:
Yury Khmelb009aeb2020-08-19 19:40:00 -0700446 dictionary with filled ebuild variables. This dictionary is empty in case
447 no artificats are found.
khmel@chromium.orgd3ec3d72020-04-29 15:57:35 -0700448 """
khmel@chromium.orgd3ec3d72020-04-29 15:57:35 -0700449 variables = {}
Yury Khmelb009aeb2020-08-19 19:40:00 -0700450
khmel@chromium.orgd3ec3d72020-04-29 15:57:35 -0700451 buckets = ['ureadahead_pack', 'gms_core_cache']
452 archs = ['arm', 'arm64', 'x86', 'x86_64']
453 build_types = ['user', 'userdebug']
454
khmel@chromium.orgd3ec3d72020-04-29 15:57:35 -0700455 for bucket in buckets:
456 for arch in archs:
457 for build_type in build_types:
458 path = (f'{runtime_artifacts_bucket_url}/{bucket}_{arch}_{build_type}_'
Yury Khmele1b74402020-05-18 08:41:35 -0700459 f'{android_version}.tar')
khmel@chromium.orgd3ec3d72020-04-29 15:57:35 -0700460 if gs_context.Exists(path):
461 variables[(f'{arch}_{build_type}_{bucket}').upper()] = (
462 f'{runtime_artifacts_bucket_url}/{bucket}_{arch}_{build_type}_'
463 f'{version_reference}.tar')
464
465 return variables
466
467
Yury Khmelb009aeb2020-08-19 19:40:00 -0700468def UpdateDataCollectorArtifacts(android_version,
469 runtime_artifacts_bucket_url,
470 build_branch):
471 r"""Finds and includes into variables artifacts from arc.DataCollector.
472
473 This verifies default android version. In case artificts are not found for
474 default Android version it tries to find artifacts for pinned version. If
475 pinned version is provided, it is required artifacts exist for the pinned
476 version.
477
478 Args:
479 android_version: The \d+ build id of Android.
480 runtime_artifacts_bucket_url: root of runtime artifacts
481 build_branch: build branch. Used to determine the pinned version if exists.
482
483 Returns:
484 dictionary with filled ebuild variables.
485 """
486
487 gs_context = gs.GSContext()
488 # Check the existing version. If we find any artifacts, use them.
489 variables = FindDataCollectorArtifacts(gs_context,
490 android_version,
491 runtime_artifacts_bucket_url,
492 '${PV}')
493 if variables:
494 # Data artificts were found.
495 return variables
496
497 # Check pinned version for the current branch.
498 pin_path = (f'{runtime_artifacts_bucket_url}/{build_branch}_pin_version')
499 if not gs_context.Exists(pin_path):
500 # No pinned version.
501 logging.warning(
502 'No data collector artifacts were found for %s',
503 android_version)
504 return variables
505
506 pin_version = gs_context.Cat(pin_path, encoding='utf-8').rstrip()
507 logging.info('Pinned version %s overrides %s',
508 pin_version, android_version)
509 variables = FindDataCollectorArtifacts(gs_context,
510 pin_version,
511 runtime_artifacts_bucket_url,
512 pin_version)
513 if not variables:
514 # If pin version set it must contain data.
515 raise Exception('Pinned version %s:%s does not contain artificats' % (
516 build_branch, pin_version))
517
518 return variables
519
520
Hidehiko Abe4fd94ae2017-01-24 18:59:55 +0900521def MarkAndroidEBuildAsStable(stable_candidate, unstable_ebuild,
522 android_package, android_version, package_dir,
khmel@chromium.orgd3ec3d72020-04-29 15:57:35 -0700523 build_branch, arc_bucket_url,
524 runtime_artifacts_bucket_url,
525 build_targets):
David Rileyc0da9d92016-02-01 12:11:01 -0800526 r"""Uprevs the Android ebuild.
527
528 This is the main function that uprevs from a stable candidate
529 to its new version.
530
531 Args:
532 stable_candidate: ebuild that corresponds to the stable ebuild we are
533 revving from. If None, builds the a new ebuild given the version
534 with revision set to 1.
535 unstable_ebuild: ebuild corresponding to the unstable ebuild for Android.
Hidehiko Abe4fd94ae2017-01-24 18:59:55 +0900536 android_package: android package name.
David Rileyc0da9d92016-02-01 12:11:01 -0800537 android_version: The \d+ build id of Android.
David Rileyc0da9d92016-02-01 12:11:01 -0800538 package_dir: Path to the android-container package dir.
David Riley73f00d92016-02-16 18:54:20 -0800539 build_branch: branch of Android builds.
540 arc_bucket_url: URL of the target ARC build gs bucket.
khmel@chromium.orgd3ec3d72020-04-29 15:57:35 -0700541 runtime_artifacts_bucket_url: root of runtime artifacts
Nicolas Norvez4bd854f2017-05-23 10:04:45 -0700542 build_targets: build targets for this particular Android branch.
David Rileyc0da9d92016-02-01 12:11:01 -0800543
544 Returns:
545 Full portage version atom (including rc's, etc) that was revved.
546 """
547 def IsTheNewEBuildRedundant(new_ebuild, stable_ebuild):
548 """Returns True if the new ebuild is redundant.
549
550 This is True if there if the current stable ebuild is the exact same copy
551 of the new one.
552 """
553 if not stable_ebuild:
554 return False
555
David Riley676f5402016-02-12 17:24:23 -0800556 if stable_candidate.version_no_rev == new_ebuild.version_no_rev:
David Rileyc0da9d92016-02-01 12:11:01 -0800557 return filecmp.cmp(
558 new_ebuild.ebuild_path, stable_ebuild.ebuild_path, shallow=False)
khmel@chromium.orgd3ec3d72020-04-29 15:57:35 -0700559 return False
David Rileyc0da9d92016-02-01 12:11:01 -0800560
561 # Case where we have the last stable candidate with same version just rev.
David Riley676f5402016-02-12 17:24:23 -0800562 if stable_candidate and stable_candidate.version_no_rev == android_version:
David Rileyc0da9d92016-02-01 12:11:01 -0800563 new_ebuild_path = '%s-r%d.ebuild' % (
564 stable_candidate.ebuild_path_no_revision,
565 stable_candidate.current_revision + 1)
566 else:
Hidehiko Abe4fd94ae2017-01-24 18:59:55 +0900567 pf = '%s-%s-r1' % (android_package, android_version)
David Rileyc0da9d92016-02-01 12:11:01 -0800568 new_ebuild_path = os.path.join(package_dir, '%s.ebuild' % pf)
569
David Riley73f00d92016-02-16 18:54:20 -0800570 variables = {'BASE_URL': arc_bucket_url}
Mike Frysinger0bdbc102019-06-13 15:27:29 -0400571 for build, (target, _) in build_targets.items():
David Riley73f00d92016-02-16 18:54:20 -0800572 variables[build + '_TARGET'] = '%s-%s' % (build_branch, target)
David Rileyc0da9d92016-02-01 12:11:01 -0800573
khmel@chromium.orgd3ec3d72020-04-29 15:57:35 -0700574 variables.update(UpdateDataCollectorArtifacts(
Yury Khmelb009aeb2020-08-19 19:40:00 -0700575 android_version, runtime_artifacts_bucket_url, build_branch))
khmel@chromium.orgd3ec3d72020-04-29 15:57:35 -0700576
David Rileyc0da9d92016-02-01 12:11:01 -0800577 portage_util.EBuild.MarkAsStable(
578 unstable_ebuild.ebuild_path, new_ebuild_path,
579 variables, make_stable=True)
580 new_ebuild = portage_util.EBuild(new_ebuild_path)
581
582 # Determine whether this is ebuild is redundant.
583 if IsTheNewEBuildRedundant(new_ebuild, stable_candidate):
584 msg = 'Previous ebuild with same version found and ebuild is redundant.'
585 logging.info(msg)
Shao-Chuan Lee085e3d72020-05-11 16:00:42 +0900586 logging.PrintBuildbotStepText('%s %s not revved'
587 % (stable_candidate.pkgname,
588 stable_candidate.version))
David Rileyc0da9d92016-02-01 12:11:01 -0800589 os.unlink(new_ebuild_path)
590 return None
591
Shao-Chuan Lee085e3d72020-05-11 16:00:42 +0900592 # PFQ runs should always be able to find a stable candidate.
David Rileyc0da9d92016-02-01 12:11:01 -0800593 if stable_candidate:
Shao-Chuan Lee085e3d72020-05-11 16:00:42 +0900594 PrintUprevMetadata(build_branch, stable_candidate, new_ebuild)
David Rileyc0da9d92016-02-01 12:11:01 -0800595
596 git.RunGit(package_dir, ['add', new_ebuild_path])
597 if stable_candidate and not stable_candidate.IsSticky():
598 git.RunGit(package_dir, ['rm', stable_candidate.ebuild_path])
599
600 # Update ebuild manifest and git add it.
601 gen_manifest_cmd = ['ebuild', new_ebuild_path, 'manifest', '--force']
Mike Frysinger45602c72019-09-22 02:15:11 -0400602 cros_build_lib.run(gen_manifest_cmd, extra_env=None, print_cmd=True)
David Rileyc0da9d92016-02-01 12:11:01 -0800603 git.RunGit(package_dir, ['add', 'Manifest'])
604
605 portage_util.EBuild.CommitChange(
Hidehiko Abe4fd94ae2017-01-24 18:59:55 +0900606 _GIT_COMMIT_MESSAGE % {'android_package': android_package,
David Rileyc0da9d92016-02-01 12:11:01 -0800607 'android_version': android_version},
608 package_dir)
609
610 return '%s-%s' % (new_ebuild.package, new_ebuild.version)
611
612
613def GetParser():
614 """Creates the argument parser."""
615 parser = commandline.ArgumentParser()
616 parser.add_argument('-b', '--boards')
617 parser.add_argument('--android_bucket_url',
David Riley73f00d92016-02-16 18:54:20 -0800618 default=constants.ANDROID_BUCKET_URL,
619 type='gs_path')
David Rileyc0da9d92016-02-01 12:11:01 -0800620 parser.add_argument('--android_build_branch',
Shuhei Takahashi6d02c192017-04-05 14:01:24 +0900621 required=True,
622 help='Android branch to import from. '
623 'Ex: git_mnc-dr-arc-dev')
Hidehiko Abe4fd94ae2017-01-24 18:59:55 +0900624 parser.add_argument('--android_package',
625 default=constants.ANDROID_PACKAGE_NAME)
David Riley73f00d92016-02-16 18:54:20 -0800626 parser.add_argument('--arc_bucket_url',
627 default=constants.ARC_BUCKET_URL,
628 type='gs_path')
David Rileyc0da9d92016-02-01 12:11:01 -0800629 parser.add_argument('-f', '--force_version',
630 help='Android build id to use')
631 parser.add_argument('-s', '--srcroot',
632 default=os.path.join(os.environ['HOME'], 'trunk', 'src'),
633 help='Path to the src directory')
634 parser.add_argument('-t', '--tracking_branch', default='cros/master',
635 help='Branch we are tracking changes against')
khmel@chromium.orgd3ec3d72020-04-29 15:57:35 -0700636 parser.add_argument('--runtime_artifacts_bucket_url',
637 default=_RUNTIME_ARTIFACTS_BUCKET_URL,
638 type='gs_path')
David Rileyc0da9d92016-02-01 12:11:01 -0800639 return parser
640
641
642def main(argv):
Hidehiko Abec9ecf262017-07-05 15:17:41 +0900643 logging.EnableBuildbotMarkers()
David Rileyc0da9d92016-02-01 12:11:01 -0800644 parser = GetParser()
645 options = parser.parse_args(argv)
646 options.Freeze()
647
648 overlay_dir = os.path.abspath(_OVERLAY_DIR % {'srcroot': options.srcroot})
Hidehiko Abe4fd94ae2017-01-24 18:59:55 +0900649 android_package_dir = os.path.join(
650 overlay_dir,
651 portage_util.GetFullAndroidPortagePackageName(options.android_package))
David Rileyc0da9d92016-02-01 12:11:01 -0800652 version_to_uprev = None
David Rileyc0da9d92016-02-01 12:11:01 -0800653
654 (unstable_ebuild, stable_ebuilds) = FindAndroidCandidates(android_package_dir)
David Riley73f00d92016-02-16 18:54:20 -0800655 acls = MakeAclDict(android_package_dir)
Qijiang Fan6588cc92019-11-20 13:26:04 +0900656 build_targets = MakeBuildTargetDict(options.android_package,
657 options.android_build_branch)
Hidehiko Abe1ebc25d2016-07-28 02:24:37 +0900658 # Mirror artifacts, i.e., images and some sdk tools (e.g., adb, aapt).
659 version_to_uprev = MirrorArtifacts(options.android_bucket_url,
660 options.android_build_branch,
661 options.arc_bucket_url, acls,
Nicolas Norvez4bd854f2017-05-23 10:04:45 -0700662 build_targets,
Hidehiko Abe1ebc25d2016-07-28 02:24:37 +0900663 options.force_version)
664
David Rileyc0da9d92016-02-01 12:11:01 -0800665 stable_candidate = portage_util.BestEBuild(stable_ebuilds)
666
667 if stable_candidate:
Lann Martinffb95162018-08-28 12:02:54 -0600668 logging.info('Stable candidate found %s', stable_candidate.version)
David Rileyc0da9d92016-02-01 12:11:01 -0800669 else:
670 logging.info('No stable candidate found.')
671
672 tracking_branch = 'remotes/m/%s' % os.path.basename(options.tracking_branch)
LaMont Jones62c48972021-01-08 16:20:55 -0700673 existing_branch = git.GetCurrentBranchOrId(android_package_dir)
David Rileyc0da9d92016-02-01 12:11:01 -0800674 work_branch = cros_mark_as_stable.GitBranch(constants.STABLE_EBUILD_BRANCH,
675 tracking_branch,
676 android_package_dir)
677 work_branch.CreateBranch()
678
679 # In the case of uprevving overlays that have patches applied to them,
680 # include the patched changes in the stabilizing branch.
681 if existing_branch:
682 git.RunGit(overlay_dir, ['rebase', existing_branch])
683
684 android_version_atom = MarkAndroidEBuildAsStable(
Hidehiko Abe4fd94ae2017-01-24 18:59:55 +0900685 stable_candidate, unstable_ebuild, options.android_package,
David Riley73f00d92016-02-16 18:54:20 -0800686 version_to_uprev, android_package_dir,
khmel@chromium.orgd3ec3d72020-04-29 15:57:35 -0700687 options.android_build_branch, options.arc_bucket_url,
688 options.runtime_artifacts_bucket_url, build_targets)
David Rileyc0da9d92016-02-01 12:11:01 -0800689 if android_version_atom:
690 if options.boards:
691 cros_mark_as_stable.CleanStalePackages(options.srcroot,
692 options.boards.split(':'),
693 [android_version_atom])
694
695 # Explicit print to communicate to caller.
696 print('ANDROID_VERSION_ATOM=%s' % android_version_atom)