• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1#!/usr/bin/env python3
2#
3# Copyright (C) 2019-2020 The Android Open Source Project
4#
5# Licensed under the Apache License, Version 2.0 (the "License");
6# you may not use this file except in compliance with the License.
7# You may obtain a copy of the License at
8#
9#       http://www.apache.org/licenses/LICENSE-2.0
10#
11# Unless required by applicable law or agreed to in writing, software
12# distributed under the License is distributed on an "AS IS" BASIS,
13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14# See the License for the specific language governing permissions and
15# limitations under the License.
16#
17
18import argparse
19import collections
20import functools
21import glob
22import json
23import logging
24import os
25import pathlib
26import re
27import shlex
28import shutil
29import subprocess
30import sys
31import tempfile
32import urllib.request
33
34from concurrent import futures
35from pathlib import Path
36
37BASE_URL = "https://ci.android.com/builds/submitted/{build_id}/{target}/latest/raw"
38SUPPORTED_ARCHS = ["arm64"]
39VARIANTS = ["userdebug"]
40BOOT_PREBUILT_REL_DIR = "packages/modules/BootPrebuilt"
41ANDROID_BUILD_TOP = os.environ["ANDROID_BUILD_TOP"]
42
43logger = logging.getLogger(__name__)
44logging.basicConfig(level=logging.INFO)
45
46def parse_args():
47  parser = argparse.ArgumentParser()
48  parser.add_argument(
49      "build_id",
50      type=int,
51      help="the build id to download the build for, e.g. 6148204")
52  parser.add_argument(
53      "--bug",
54      type=str,
55      default=None,
56      help="optional bug number for git commit.")
57
58  return parser.parse_args()
59
60
61def download_file(url, dest_filename):
62  logger.info("Downloading %s -> %s", url, dest_filename)
63  urllib.request.urlretrieve(url, dest_filename)
64
65
66def get_artifact_download_spec(build_id, device, variant, dest_dir):
67  target = "{}-{}".format(device, variant)
68  url_base = BASE_URL.format(build_id=build_id, target=target)
69  filename = "{}-img-{}.zip".format(device, build_id)
70  url = os.path.join(url_base, filename)
71  dest_filename = os.path.join(dest_dir, filename)
72  return url, dest_filename
73
74
75def update_prebuilt(build_id, boot_prebuilt, ver, arch, variant, bug):
76  device = "aosp_" + arch
77  arch_dir = os.path.join(boot_prebuilt, ver, arch)
78  variant_dir = os.path.join(arch_dir, variant)
79  boot_img_name = "boot-{}.img".format(ver)
80  stored_img_name = "boot-{}.img".format(variant)
81  try:
82    subprocess.check_call(["repo", "start", "boot-prebuilt-{}".format(build_id)], cwd=arch_dir)
83
84    os.makedirs(variant_dir)
85    url, dest_filename = get_artifact_download_spec(build_id, device, variant, variant_dir)
86    download_file(url, dest_filename)
87    args = ["unzip", "-d", variant_dir, dest_filename, boot_img_name]
88    logger.info("Calling: %s", " ".join(args))
89    subprocess.check_call(args)
90    shutil.move(os.path.join(variant_dir, boot_img_name), os.path.join(arch_dir, stored_img_name))
91
92  finally:
93    shutil.rmtree(variant_dir)
94
95    message = """Update prebuilts to {build_id}.
96
97Test: Treehugger
98Bug: {bug}
99""".format(build_id=build_id, bug=bug or "N/A")
100
101    logger.info("Creating commit for %s", arch_dir)
102    subprocess.check_call(["git", "add", "."], cwd=arch_dir)
103    subprocess.check_call(["git", "commit", "-m", message], cwd=arch_dir)
104
105
106def main():
107  args = parse_args()
108  with futures.ThreadPoolExecutor(max_workers=10) as pool:
109    fs = []
110    boot_prebuilt = os.path.join(ANDROID_BUILD_TOP, BOOT_PREBUILT_REL_DIR)
111    for ver in os.listdir(boot_prebuilt):
112      if not re.match(r'\d+[.]\d+', ver):
113        continue
114      for arch in os.listdir(os.path.join(boot_prebuilt, ver)):
115        if arch not in SUPPORTED_ARCHS:
116          continue
117        for variant in VARIANTS:
118          fs.append((ver, arch, pool.submit(update_prebuilt, args.build_id, boot_prebuilt, ver,
119                                            arch, variant, args.bug)))
120
121    futures.wait([f for ver, arch, f in fs])
122    success_dirs = []
123    logger.info("===============")
124    logger.info("Summary:")
125    for ver, arch, future in fs:
126      if future.exception():
127        logger.error("%s/%s: %s", ver, arch, future.exception())
128      else:
129        logger.info("%s/%s: Updated.", ver, arch)
130        success_dirs.append(os.path.join(BOOT_PREBUILT_REL_DIR, ver, arch))
131
132    if success_dirs:
133      args = ["repo", "upload", "--verify", "--hashtag-branch", "--br",
134              "boot-prebuilt-{}".format(args.build_id)] + success_dirs
135      logger.info(" ".join(args))
136      subprocess.check_call(args, cwd=ANDROID_BUILD_TOP)
137
138
139if __name__ == "__main__":
140  sys.exit(main())
141