1#!/usr/bin/python3 2 3import os 4import subprocess 5import zipfile 6 7from utils import print_e, mv 8 9# See go/fetch_artifact for details on this script. 10FETCH_ARTIFACT = '/google/data/ro/projects/android/fetch_artifact' 11FETCH_ARTIFACT_BEYOND_CORP = '/usr/bin/fetch_artifact' 12 13 14class BuildId(object): 15 def __init__(self, url_id, fs_id): 16 # id when used in build server urls 17 self.url_id = url_id 18 # id when used in build commands 19 self.fs_id = fs_id 20 21 22def fetch_artifact(target, build_id, artifact_path, beyond_corp): 23 download_to = os.path.join('.', os.path.dirname(artifact_path)) 24 print(f'Fetching {artifact_path} from {target}...') 25 if not os.path.exists(download_to): 26 os.makedirs(download_to) 27 if beyond_corp: 28 fetch_cmd = [FETCH_ARTIFACT_BEYOND_CORP, '--use_oauth2', 29 '--bid', str(build_id), '--target', target, artifact_path, download_to] 30 else: 31 fetch_cmd = [FETCH_ARTIFACT, 32 '--bid', str(build_id), '--target', target, artifact_path, download_to] 33 print('Running: ' + ' '.join(fetch_cmd)) 34 try: 35 subprocess.check_output(fetch_cmd, stderr=subprocess.STDOUT) 36 except subprocess.CalledProcessError: 37 print_e(f'FAIL: Unable to retrieve {artifact_path} artifact for build ID {build_id}') 38 print_e('Please make sure you are authenticated for build server access!') 39 return None 40 return artifact_path 41 42 43def fetch_artifacts(target, build_id, artifact_dict, beyond_corp): 44 for artifact, target_path in artifact_dict.items(): 45 artifact_path = fetch_artifact(target, build_id.url_id, artifact, beyond_corp) 46 if not artifact_path: 47 return False 48 mv(artifact_path, target_path) 49 return True 50 51 52def extract_artifact(artifact_path): 53 # Unzip the repo archive into a separate directory. 54 repo_dir = os.path.splitext(artifact_path)[0] 55 with zipfile.ZipFile(artifact_path) as zipFile: 56 zipFile.extractall(repo_dir) 57 return repo_dir 58 59 60def fetch_and_extract(target, build_id, file, beyond_corp, artifact_path=None): 61 if not artifact_path: 62 artifact_path = fetch_artifact(target, build_id, file, beyond_corp) 63 if not artifact_path: 64 return None 65 return extract_artifact(artifact_path) 66 67 68def parse_build_id(source): 69 # must be in the format 12345 or P12345 70 number_text = source 71 presubmit = False 72 if number_text.startswith('P'): 73 presubmit = True 74 number_text = number_text[1:] 75 if not number_text.isnumeric(): 76 return None 77 url_id = source 78 fs_id = url_id 79 if presubmit: 80 fs_id = '0' 81 return BuildId(url_id, fs_id) 82