blob: eb94224816117221ea6911c86445d98e1b40c663 [file] [log] [blame]
Peter Kotwicz2b85bd3d2020-10-01 22:29:491#!/usr/bin/env python3
2
Avi Drissman3f1ea442022-09-08 15:42:013# Copyright 2020 The Chromium Authors
Peter Kotwicz2b85bd3d2020-10-01 22:29:494# Use of this source code is governed by a BSD-style license that can be
5# found in the LICENSE file.
6"""A script to generate build.gradle from template and run fetch_all.py
7
8More specifically, to generate build.gradle:
Peter Wen1a004a02025-01-28 23:04:469 - It downloads the index page for the latest androidx snapshot from
10 https://androidx.dev/snapshots/latest/artifacts
Peter Kotwicz2b85bd3d2020-10-01 22:29:4911 - It replaces {{androidx_repository_url}} with the URL for the latest snapshot
Peter Wen1a004a02025-01-28 23:04:4612 - For each dependency, it looks up the version in the index page's HTML and
Peter Kotwicz2b85bd3d2020-10-01 22:29:4913 substitutes the version into {{androidx_dependency_version}}.
Peter Wen2e5944d2025-02-04 17:02:3214
15Extra args after -- are passed directly to fetch_all.py.
Peter Kotwicz2b85bd3d2020-10-01 22:29:4916"""
17
Haiyang Panace500932022-01-26 19:49:0318import argparse
Peter Kotwicz2b85bd3d2020-10-01 22:29:4919import contextlib
Mohamed Heikal811bb642025-02-25 20:03:5320import json
Haiyang Panace500932022-01-26 19:49:0321import logging
Peter Kotwicz2b85bd3d2020-10-01 22:29:4922import os
Andrew Grieveb5255af2024-06-06 17:03:1823import pathlib
Peter Kotwicz2b85bd3d2020-10-01 22:29:4924import re
Peter Kotwicz2b85bd3d2020-10-01 22:29:4925import shutil
Mohamed Heikal864fa342025-01-08 19:15:4526import sys
Peter Kotwicz2b85bd3d2020-10-01 22:29:4927import subprocess
28import tempfile
Peter Kotwicz4676d062020-10-22 06:04:1329from urllib import request
Peter Wenc90bbb72025-02-25 20:41:4430import zipfile
Peter Kotwicz2b85bd3d2020-10-01 22:29:4931
32_ANDROIDX_PATH = os.path.normpath(os.path.join(__file__, '..'))
Andrew Grieved8c97182024-06-28 18:37:3333_CIPD_PATH = os.path.join(_ANDROIDX_PATH, 'cipd')
Mohamed Heikal864fa342025-01-08 19:15:4534_SRC_PATH = os.path.normpath(os.path.join(_ANDROIDX_PATH, '..', '..'))
Mohamed Heikal811bb642025-02-25 20:03:5335_BOM_PATH = os.path.join(_CIPD_PATH, 'bill_of_materials.json')
Mohamed Heikal864fa342025-01-08 19:15:4536
37sys.path.insert(1, os.path.join(_SRC_PATH, 'third_party', 'depot_tools'))
38import gclient_eval
Peter Kotwicz2b85bd3d2020-10-01 22:29:4939
40_FETCH_ALL_PATH = os.path.normpath(
41 os.path.join(_ANDROIDX_PATH, '..', 'android_deps', 'fetch_all.py'))
42
Peter Wen1a004a02025-01-28 23:04:4643# URL to artifacts in latest androidx snapshot.
44_ANDROIDX_LATEST_SNAPSHOT_ARTIFACTS_URL = 'https://androidx.dev/snapshots/latest/artifacts'
Mohamed Heikal864fa342025-01-08 19:15:4545
46# Path to package listed in //DEPS
47_DEPS_PACKAGE = 'src/third_party/androidx/cipd'
48# CIPD package name
49_CIPD_PACKAGE = 'chromium/third_party/androidx'
Peter Kotwicz2b85bd3d2020-10-01 22:29:4950
Peter Kotwicz3fb0070e2021-02-11 07:37:3551# Snapshot repository URL with {{version}} placeholder.
52_SNAPSHOT_REPOSITORY_URL = 'https://androidx.dev/snapshots/builds/{{version}}/artifacts/repository'
53
Peter Wen1a004a02025-01-28 23:04:4654# When androidx roller is breaking, and a fix is not imminent, use this to pin a
Andrew Grieve2515bcbd2022-05-06 03:14:0755# broken library to an old known-working version.
Andrew Grievea03217f2022-05-12 16:05:2756# * The first element of each tuple is the path to the artifact of the latest
57# version of the library. It could change if the version is rev'ed in a new
58# snapshot.
59# * The second element is a URL to replace the file with. Find the URL for older
Peter Wen1a004a02025-01-28 23:04:4660# versions of libraries by looking through the artifacts for the older version
61# (e.g.: https://androidx.dev/snapshots/builds/8545498/artifacts)
Andrew Grieve2515bcbd2022-05-06 03:14:0762_OVERRIDES = [
Andrew Grievea03217f2022-05-12 16:05:2763 # Example:
Andrew Grieve2515bcbd2022-05-06 03:14:0764 #('androidx_core_core/core-1.9.0-SNAPSHOT.aar',
65 # 'https://androidx.dev/snapshots/builds/8545498/artifacts/repository/'
66 # 'androidx/core/core/1.8.0-SNAPSHOT/core-1.8.0-20220505.122105-1.aar'),
67]
68
Peter Wenba01695b2025-03-03 18:29:4669_FILES_TO_COMMIT = [
70 'additional_readme_paths.json',
71 'bill_of_materials.json',
72 'BUILD.gn',
73 'build.gradle',
74]
75_CIPD_DATA_FILES = _FILES_TO_COMMIT + [
76 'VERSION.txt',
77 'to_commit.zip',
78]
79
Peter Wen19a68702025-03-03 20:41:3180_GENERATED_DISCLAIMER = '''\
81// **IMPORTANT**: build.gradle is generated and any changes would be overridden
82// by the autoroller. Please update build.gradle.template
83// instead.
84'''
85
Peter Kotwicz3fb0070e2021-02-11 07:37:3586
87def _build_snapshot_repository_url(version):
88 return _SNAPSHOT_REPOSITORY_URL.replace('{{version}}', version)
89
Peter Kotwicz2b85bd3d2020-10-01 22:29:4990
Mohamed Heikal864fa342025-01-08 19:15:4591def _get_latest_androidx_version():
Peter Wen1a004a02025-01-28 23:04:4692 androidx_artifacts_response = request.urlopen(
93 _ANDROIDX_LATEST_SNAPSHOT_ARTIFACTS_URL)
Mohamed Heikal864fa342025-01-08 19:15:4594 # Get the versioned url from the redirect destination.
Peter Wen1a004a02025-01-28 23:04:4695 androidx_artifacts_url = androidx_artifacts_response.url
96 androidx_artifacts_response.close()
97 logging.info('URL for the latest build info: %s', androidx_artifacts_url)
Mohamed Heikal864fa342025-01-08 19:15:4598 # Strip '/repository' from pattern.
99 resolved_snapshot_repository_url_pattern = (
100 _build_snapshot_repository_url('([0-9]*)').rsplit('/', 1)[0])
Peter Wen1a004a02025-01-28 23:04:46101 match = re.match(resolved_snapshot_repository_url_pattern,
102 androidx_artifacts_url)
103 assert match is not None
104 version = match.group(1)
Mohamed Heikal864fa342025-01-08 19:15:45105 return version
106
107
108def _query_cipd_tags(version):
109 cipd_output = subprocess.check_output(
110 ['cipd', 'describe', _CIPD_PACKAGE, '-version', version],
111 encoding='utf-8')
112 # Output looks like:
113 # Package: chromium/third_party/androidx
114 # Instance ID: gUjEawxv5mQO8yfbuC8W-rx4V3zYE-4LTWggXpZHI4sC
115 # Registered by: user:chromium-cipd-builder@chops-service-accounts.iam.gserviceaccount.com
116 # Registered at: 2025-01-06 17:54:48.034135 +0000 UTC
117 # Refs:
118 # latest
119 # Tags:
120 # details0:version-cr-012873390
121 # version:cr-012873390
122 lines = cipd_output.split('\n')
123 tags = {}
124 parsing_tags = False
125 for line in lines:
126 if not line.strip():
127 continue
128 if line.startswith('Tags:'):
129 parsing_tags = True
130 continue
131 if parsing_tags:
132 tag, value = line.strip().split(':', 1)
133 tags[tag] = value
134 return tags
135
136
137def _get_current_cipd_instance():
138 with open(os.path.join(_SRC_PATH, 'DEPS'), 'rt') as f:
139 gclient_dict = gclient_eval.Exec(f.read())
140 return gclient_eval.GetCIPD(gclient_dict, _DEPS_PACKAGE, _CIPD_PACKAGE)
141
142
143def _get_current_androidx_version():
144 cipd_instance = _get_current_cipd_instance()
145 cipd_tags = _query_cipd_tags(cipd_instance)
146 version_string = cipd_tags['version']
147 version = version_string[len('cr-0'):]
148 return version
149
150
Mohamed Heikal811bb642025-02-25 20:03:53151def _generate_version_map_str(bom_path):
152 bom = []
153 version_lines = []
154 with open(bom_path) as f:
155 bom = json.load(f)
156 for dep in bom:
Mohamed Heikalbe6cc502025-02-26 16:50:00157 line = f"versionCache['{dep['group']}:{dep['name']}'] = '{dep['version']}'"
Mohamed Heikal811bb642025-02-25 20:03:53158 version_lines.append(line)
159 return '\n'.join(sorted(version_lines))
160
161
Peter Wen1ba3d4d2025-02-25 21:46:37162def _process_build_gradle(template_path, output_path, androidx_repository_url,
163 version_overrides_str):
Peter Kotwicz2b85bd3d2020-10-01 22:29:49164 """Generates build.gradle from template.
165
166 Args:
Andrew Grieved8c97182024-06-28 18:37:33167 template_path: Path to build.gradle.template.
168 output_path: Path to build.gradle.
Peter Kotwicz2b85bd3d2020-10-01 22:29:49169 androidx_repository_url: URL of the maven repository.
Peter Wen1ba3d4d2025-02-25 21:46:37170 version_override_str: An optional list of pinned versions.
Peter Kotwicz2b85bd3d2020-10-01 22:29:49171 """
Mohamed Heikal811bb642025-02-25 20:03:53172 content = pathlib.Path(template_path).read_text()
173 content = content.replace('{{androidx_repository_url}}',
174 androidx_repository_url)
175 content = content.replace('{{version_overrides}}', version_overrides_str)
Peter Wen19a68702025-03-03 20:41:31176 content = content.replace('{{generated_disclaimer}}',
177 _GENERATED_DISCLAIMER)
Andrew Grieveb5255af2024-06-06 17:03:18178 # build.gradle is not deleted after script has finished running. The file is in
Peter Kotwicz2b85bd3d2020-10-01 22:29:49179 # .gitignore and thus will be excluded from uploaded CLs.
Mohamed Heikal811bb642025-02-25 20:03:53180 pathlib.Path(output_path).write_text(content)
Peter Kotwicz2b85bd3d2020-10-01 22:29:49181
182
Peter Wen801b2fe2025-02-25 23:02:46183def _write_cipd_yaml(libs_dir,
184 version,
185 cipd_yaml_path,
Peter Wen801b2fe2025-02-25 23:02:46186 experimental=False):
Peter Kotwicza31339a2020-10-20 16:36:23187 """Writes cipd.yaml file at the passed-in path."""
188
189 lib_dirs = os.listdir(libs_dir)
190 if not lib_dirs:
191 raise Exception('No generated libraries in {}'.format(libs_dir))
192
Peter Wenba01695b2025-03-03 18:29:46193 cipd_lib_files = []
Peter Kotwicza31339a2020-10-20 16:36:23194 for lib_dir in lib_dirs:
195 abs_lib_dir = os.path.join(libs_dir, lib_dir)
Andrew Grieved8c97182024-06-28 18:37:33196 androidx_rel_lib_dir = os.path.relpath(abs_lib_dir, _CIPD_PATH)
Peter Kotwicza31339a2020-10-20 16:36:23197 if not os.path.isdir(abs_lib_dir):
198 continue
199 lib_files = os.listdir(abs_lib_dir)
200 if not 'cipd.yaml' in lib_files:
201 continue
202
Peter Kotwicza6b3b9a2021-01-28 21:40:12203 for lib_file in lib_files:
Peter Wen3477b8b2025-02-27 17:40:22204 if lib_file == 'cipd.yaml':
Peter Kotwicza6b3b9a2021-01-28 21:40:12205 continue
Peter Wenba01695b2025-03-03 18:29:46206 cipd_lib_files.append(os.path.join(androidx_rel_lib_dir, lib_file))
Peter Kotwicza31339a2020-10-20 16:36:23207
Andrew Grieve9c7d4ac2f2022-08-24 17:38:59208 if experimental:
209 package = 'experimental/google.com/' + os.getlogin() + '/androidx'
210 else:
211 package = 'chromium/third_party/androidx'
Peter Kotwicza31339a2020-10-20 16:36:23212 contents = [
mark a. foltzf87dfea2023-09-06 23:49:03213 '# Copyright 2021 The Chromium Authors',
Peter Kotwicza31339a2020-10-20 16:36:23214 '# Use of this source code is governed by a BSD-style license that can be',
215 '# found in the LICENSE file.',
Peter Kotwicz92548aa2021-02-18 15:12:58216 '# version: ' + version,
Andrew Grieve9c7d4ac2f2022-08-24 17:38:59217 'package: ' + package,
Peter Kotwicz3fb0070e2021-02-11 07:37:35218 'description: androidx',
219 'data:',
Peter Kotwicza31339a2020-10-20 16:36:23220 ]
Peter Wenba01695b2025-03-03 18:29:46221 contents.extend('- file: ' + f for f in cipd_lib_files + _CIPD_DATA_FILES)
Peter Kotwicza31339a2020-10-20 16:36:23222
223 with open(cipd_yaml_path, 'w') as out:
224 out.write('\n'.join(contents))
225
226
Peter Kotwicz2b85bd3d2020-10-01 22:29:49227def main():
Haiyang Panace500932022-01-26 19:49:03228 parser = argparse.ArgumentParser(description=__doc__)
229 parser.add_argument('-v',
230 '--verbose',
231 dest='verbose_count',
232 default=0,
233 action='count',
234 help='Verbose level (multiple times for more)')
Andrew Grieve10bbd552022-05-05 18:10:26235 parser.add_argument('--local-repo',
236 help='Path to a locally androidx maven repo to use '
237 'instead of fetching the latest.')
Mohamed Heikal864fa342025-01-08 19:15:45238 parser.add_argument(
239 '--no-roll',
240 action='store_true',
241 help='If passed then we will not try rolling the '
242 'latest androidx but use the currently rolled version.')
Peter Wen1ba3d4d2025-02-25 21:46:37243 parser.add_argument(
244 '--use-bom',
245 action='store_true',
246 help='If passed then we will use the existing bill_of_materials.json '
247 'instead of resolving the latest androidx.')
Peter Wen2e5944d2025-02-04 17:02:32248 args, extra_args = parser.parse_known_args()
Haiyang Panace500932022-01-26 19:49:03249
250 logging.basicConfig(
251 level=logging.WARNING - 10 * args.verbose_count,
252 format='%(levelname).1s %(relativeCreated)6d %(message)s')
253
Andrew Grieve10bbd552022-05-05 18:10:26254 if args.local_repo:
255 version = 'local'
Andrew Grieve10bbd552022-05-05 18:10:26256 androidx_snapshot_repository_url = ('file://' +
257 os.path.abspath(args.local_repo))
258 else:
Mohamed Heikal864fa342025-01-08 19:15:45259 if args.no_roll:
260 version = _get_current_androidx_version()
261 logging.info('Resolved current androidx version to %s', version)
262 else:
263 version = _get_latest_androidx_version()
264 logging.info('Resolved latest androidx version to %s', version)
265
Andrew Grieve10bbd552022-05-05 18:10:26266 androidx_snapshot_repository_url = _build_snapshot_repository_url(
267 version)
Andrew Grieve9c7d4ac2f2022-08-24 17:38:59268 # Prepend '0' to version to avoid conflicts with previous version format.
269 version = 'cr-0' + version
270
Peter Wen1ba3d4d2025-02-25 21:46:37271 if args.use_bom:
272 version_map_str = _generate_version_map_str(_BOM_PATH)
273 else:
274 version_map_str = ''
275
Mohamed Heikal864fa342025-01-08 19:15:45276 if os.path.exists(_CIPD_PATH):
277 shutil.rmtree(_CIPD_PATH)
278 os.mkdir(_CIPD_PATH)
279
Andrew Grieved8c97182024-06-28 18:37:33280 _process_build_gradle(
281 os.path.join(_ANDROIDX_PATH, 'build.gradle.template'),
Peter Wen6fcf2d72025-02-12 15:34:26282 os.path.join(_CIPD_PATH, 'build.gradle'),
Peter Wen1ba3d4d2025-02-25 21:46:37283 androidx_snapshot_repository_url, version_map_str)
Peter Wenba01695b2025-03-03 18:29:46284 shutil.copyfile(os.path.join(_ANDROIDX_PATH, 'BUILD.gn'),
Andrew Grieved8c97182024-06-28 18:37:33285 os.path.join(_CIPD_PATH, 'BUILD.gn'))
Peter Kotwicz2b85bd3d2020-10-01 22:29:49286
287 fetch_all_cmd = [
Andrew Grieved8c97182024-06-28 18:37:33288 _FETCH_ALL_PATH, '--android-deps-dir', _CIPD_PATH,
Peter Kotwiczdabb89d072020-10-22 16:30:03289 '--ignore-vulnerabilities'
Andrew Grievee9bccea42023-02-10 19:56:25290 ] + ['-v'] * args.verbose_count
Peter Wen2e5944d2025-02-04 17:02:32291
292 # Filter out -- from the args to pass to fetch_all.py.
293 fetch_all_cmd += [a for a in extra_args if a != '--']
294
Andrew Grieve9c7d4ac2f2022-08-24 17:38:59295 # Overrides do not work with local snapshots since the repository_url is
296 # different.
297 if not args.local_repo:
298 for subpath, url in _OVERRIDES:
299 fetch_all_cmd += ['--override-artifact', f'{subpath}:{url}']
Mohamed Heikal864fa342025-01-08 19:15:45300 env = os.environ.copy()
301 # Silence the --local warning in fetch_all.py that is not applicable here.
302 env['SWARMING_TASK_ID'] = '1'
303 subprocess.run(fetch_all_cmd, check=True, env=env)
Peter Kotwicza31339a2020-10-20 16:36:23304
Mohamed Heikal811bb642025-02-25 20:03:53305 version_map_str = _generate_version_map_str(_BOM_PATH)
306
307 # Regenerate the build.gradle file filling in the the version map so that
308 # runs of the main project do not have to revalutate androidx versions.
309 _process_build_gradle(
310 os.path.join(_ANDROIDX_PATH, 'build.gradle.template'),
311 os.path.join(_CIPD_PATH, 'build.gradle'),
312 androidx_snapshot_repository_url, version_map_str)
313
Andrew Grieved8c97182024-06-28 18:37:33314 version_txt_path = os.path.join(_CIPD_PATH, 'VERSION.txt')
Andrew Grieve9c7d4ac2f2022-08-24 17:38:59315 with open(version_txt_path, 'w') as f:
316 f.write(version)
Peter Kotwicz92548aa2021-02-18 15:12:58317
Andrew Grieved8c97182024-06-28 18:37:33318 libs_dir = os.path.join(_CIPD_PATH, 'libs')
Peter Kotwicz2b85bd3d2020-10-01 22:29:49319
Peter Wenc90bbb72025-02-25 20:41:44320 to_commit_paths = []
321 for root, _, files in os.walk(libs_dir):
322 for file in files:
323 # Avoid committing actual artifacts.
Peter Wen3477b8b2025-02-27 17:40:22324 if file.endswith(('.aar', '.jar', 'cipd.yaml')):
Peter Wenc90bbb72025-02-25 20:41:44325 continue
326 file_path = os.path.join(root, file)
327 file_path_in_committed = os.path.relpath(file_path, _CIPD_PATH)
328 to_commit_paths.append((file_path, file_path_in_committed))
329
Peter Wenba01695b2025-03-03 18:29:46330 for file in _FILES_TO_COMMIT:
Peter Wenc90bbb72025-02-25 20:41:44331 file_path = os.path.join(_CIPD_PATH, file)
332 to_commit_paths.append(
333 (file_path, f'CHROMIUM_SRC/third_party/androidx/{file}'))
334
335 to_commit_zip_path = os.path.join(_CIPD_PATH, 'to_commit.zip')
336 with zipfile.ZipFile(to_commit_zip_path, 'w') as zip_file:
337 for filename, arcname in to_commit_paths:
338 zip_file.write(filename, arcname=arcname)
Peter Kotwicz2b85bd3d2020-10-01 22:29:49339
Peter Wen801b2fe2025-02-25 23:02:46340 yaml_path = os.path.join(_CIPD_PATH, 'cipd.yaml')
341 _write_cipd_yaml(libs_dir,
342 version,
343 yaml_path,
Peter Wen801b2fe2025-02-25 23:02:46344 experimental=bool(args.local_repo))
345
Peter Kotwicz2b85bd3d2020-10-01 22:29:49346if __name__ == '__main__':
347 main()