4848 "gs://android-haiku/target-cuttlefish/stable_build_info.json" )
4949
5050
51+ def _use_v4 ():
52+ """Return True if we should use V4 Android Build API."""
53+ try :
54+ use_v4 = db_config .get_value ('use_android_build_api_v4' ) or False
55+ logs .info (
56+ 'AndroidBuildAPI feature flag status read.' ,
57+ use_android_build_api_v4 = use_v4 )
58+ return use_v4
59+ except Exception as e :
60+ logs .error (
61+ 'AndroidBuildAPI error reading feature flag use_android_build_api_v4. '
62+ 'Defaulting to False.' ,
63+ error = str (e ))
64+ return False
65+
66+
5167def execute_request_with_retries (request ):
5268 """Executes request and retries on failure."""
5369 result = None
@@ -68,24 +84,68 @@ def download_artifact(client, bid, target, attempt_id, name, output_directory,
6884 logs .info ('artifact to download: %s' % name )
6985 logs .info ('output_directory: %s' % output_directory )
7086 logs .info ('output_filename: %s' % output_filename )
71- artifact_query = client .buildartifact ().get (
72- buildId = bid , target = target , attemptId = attempt_id , resourceId = name )
87+
88+ version_tag = 'V4' if _use_v4 () else 'V3'
89+ logs .info (
90+ 'AndroidBuildAPI download_artifact started.' ,
91+ api_version = version_tag ,
92+ operation = 'download_artifact' ,
93+ build_id = bid ,
94+ target = target ,
95+ attempt_id = attempt_id ,
96+ artifact_name = name )
97+
98+ if _use_v4 ():
99+ artifact_query = client .buildartifacts ().get (
100+ buildId = bid , target = target , attemptId = attempt_id , resourceId = name )
101+ else :
102+ artifact_query = client .buildartifact ().get (
103+ buildId = bid , target = target , attemptId = attempt_id , resourceId = name )
73104 artifact = execute_request_with_retries (artifact_query )
74105 if artifact is None :
75- logs .error (f'Artifact unreachable with name { name } , target { target } '
76- f'and build id { bid } .' )
106+ logs .error (
107+ 'AndroidBuildAPI download_artifact failed: artifact metadata '
108+ 'unreachable.' ,
109+ api_version = version_tag ,
110+ operation = 'download_artifact' ,
111+ build_id = bid ,
112+ target = target ,
113+ attempt_id = attempt_id ,
114+ artifact_name = name ,
115+ status = 'failed' )
77116 return None
78117
79118 # Lucky us, we always have the size.
80119 size = int (artifact ['size' ])
120+ logs .info (
121+ 'AndroidBuildAPI download_artifact metadata retrieved successfully.' ,
122+ api_version = version_tag ,
123+ operation = 'download_artifact' ,
124+ build_id = bid ,
125+ target = target ,
126+ attempt_id = attempt_id ,
127+ artifact_name = name ,
128+ size = size )
81129
82130 chunksize = - 1
83131 if size >= DEFAULT_CHUNK_SIZE :
84132 chunksize = DEFAULT_CHUNK_SIZE
85133
86134 # Just like get, except get_media.
87- dl_request = client .buildartifact ().get_media (
88- buildId = bid , target = target , attemptId = attempt_id , resourceId = name )
135+ logs .info (
136+ 'AndroidBuildAPI download_artifact media download started.' ,
137+ api_version = version_tag ,
138+ operation = 'download_artifact_media' ,
139+ build_id = bid ,
140+ target = target ,
141+ attempt_id = attempt_id ,
142+ artifact_name = name )
143+ if _use_v4 ():
144+ dl_request = client .buildartifacts ().get_media (
145+ buildId = bid , target = target , attemptId = attempt_id , resourceId = name )
146+ else :
147+ dl_request = client .buildartifact ().get_media (
148+ buildId = bid , target = target , attemptId = attempt_id , resourceId = name )
89149
90150 if output_filename :
91151 file_name = output_filename
@@ -95,7 +155,16 @@ def download_artifact(client, bid, target, attempt_id, name, output_directory,
95155 output_path = os .path .join (output_directory , file_name )
96156 # If the artifact already exists, then bail out.
97157 if os .path .exists (output_path ) and os .path .getsize (output_path ) == size :
98- logs .info ('Artifact %s already exists, skipping download.' % name )
158+ logs .info (
159+ 'AndroidBuildAPI download_artifact skipped (file already exists).' ,
160+ api_version = version_tag ,
161+ operation = 'download_artifact' ,
162+ build_id = bid ,
163+ target = target ,
164+ attempt_id = attempt_id ,
165+ artifact_name = name ,
166+ output_path = output_path ,
167+ status = 'skipped_exists' )
99168 return output_path
100169
101170 logs .info ('Downloading artifact %s.' % name )
@@ -118,6 +187,16 @@ def download_artifact(client, bid, target, attempt_id, name, output_directory,
118187 percent_completed = (size_completed * 100.0 ) / size
119188 logs .info ('%.1f%% complete.' % percent_completed )
120189
190+ logs .info (
191+ 'AndroidBuildAPI download_artifact completed successfully.' ,
192+ api_version = version_tag ,
193+ operation = 'download_artifact' ,
194+ build_id = bid ,
195+ target = target ,
196+ attempt_id = attempt_id ,
197+ artifact_name = name ,
198+ output_path = output_path ,
199+ status = 'success' )
121200 return output_path
122201
123202
@@ -127,21 +206,44 @@ def get_artifacts_for_build(client,
127206 attempt_id : str = 'latest' ,
128207 regexp : Optional [str ] = None ) -> List [str ]:
129208 """Return list of artifacts for a given build."""
130- if not regexp :
131- request = client .buildartifact ().list (
132- buildId = bid , target = target , attemptId = attempt_id )
209+ version_tag = 'V4' if _use_v4 () else 'V3'
210+ logs .info (
211+ 'AndroidBuildAPI get_artifacts_for_build started.' ,
212+ api_version = version_tag ,
213+ operation = 'get_artifacts_for_build' ,
214+ build_id = bid ,
215+ target = target ,
216+ attempt_id = attempt_id ,
217+ regexp = regexp )
218+
219+ if _use_v4 ():
220+ if not regexp :
221+ request = client .buildartifacts ().list (
222+ buildId = bid , target = target , attemptId = attempt_id )
223+ else :
224+ request = client .buildartifacts ().list (
225+ buildId = bid ,
226+ target = target ,
227+ attemptId = attempt_id ,
228+ nameRegexp = regexp ,
229+ maxResults = 100 )
133230 else :
134- request = client .buildartifact ().list (
135- buildId = bid ,
136- target = target ,
137- attemptId = attempt_id ,
138- nameRegexp = regexp ,
139- maxResults = 100 )
231+ if not regexp :
232+ request = client .buildartifact ().list (
233+ buildId = bid , target = target , attemptId = attempt_id )
234+ else :
235+ request = client .buildartifact ().list (
236+ buildId = bid ,
237+ target = target ,
238+ attemptId = attempt_id ,
239+ nameRegexp = regexp ,
240+ maxResults = 100 )
140241
141242 request_str = (f'{ request .uri } , { request .method } , '
142243 f'{ request .body } , { request .methodId } ' )
143244
144245 artifacts = []
246+
145247 results = []
146248 while request :
147249 result = execute_request_with_retries (request )
@@ -151,7 +253,21 @@ def get_artifacts_for_build(client,
151253 if result and 'artifacts' in result :
152254 for artifact in result ['artifacts' ]:
153255 artifacts .append (artifact )
154- request = client .buildartifact ().list_next (request , result )
256+ if _use_v4 ():
257+ request = client .buildartifacts ().list_next (request , result )
258+ else :
259+ request = client .buildartifact ().list_next (request , result )
260+
261+ logs .info (
262+ 'AndroidBuildAPI get_artifacts_for_build completed.' ,
263+ api_version = version_tag ,
264+ operation = 'get_artifacts_for_build' ,
265+ build_id = bid ,
266+ target = target ,
267+ attempt_id = attempt_id ,
268+ regexp = regexp ,
269+ artifacts_count = len (artifacts ),
270+ status = 'success' if artifacts else 'empty' )
155271
156272 if not artifacts :
157273 logs .error (f'No artifact found for target { target } , build id { bid } .\n '
@@ -174,11 +290,24 @@ def get_client():
174290 credentials = ServiceAccountCredentials .from_json_keyfile_dict (
175291 json .loads (build_apiary_service_account_private_key ),
176292 scopes = 'https://www.googleapis.com/auth/androidbuild.internal' )
177- client = apiclient .discovery .build (
178- 'androidbuildinternal' ,
179- 'v3' ,
180- credentials = credentials ,
181- static_discovery = False )
293+ if _use_v4 ():
294+ logs .info (
295+ 'AndroidBuildAPI client initialization started.' , api_version = 'V4' )
296+ client = apiclient .discovery .build (
297+ 'androidbuildinternal' ,
298+ 'v4' ,
299+ discoveryServiceUrl =
300+ 'https://androidbuild-pa.googleapis.com/$discovery/rest?version=v4' ,
301+ credentials = credentials ,
302+ static_discovery = False )
303+ else :
304+ logs .info (
305+ 'AndroidBuildAPI client initialization started.' , api_version = 'V3' )
306+ client = apiclient .discovery .build (
307+ 'androidbuildinternal' ,
308+ 'v3' ,
309+ credentials = credentials ,
310+ static_discovery = False )
182311
183312 return client
184313
@@ -218,25 +347,59 @@ def get_latest_artifact_info(branch, target, signed=False, stable_build=False):
218347 if 'bid' in build_info and build_info ['bid' ] != '0' :
219348 return build_info
220349
221- request = client .build ().list ( # pylint: disable=no-member
222- buildType = 'submitted' ,
350+ version_tag = 'V4' if _use_v4 () else 'V3'
351+ logs .info (
352+ 'AndroidBuildAPI get_latest_artifact_info started.' ,
353+ api_version = version_tag ,
354+ operation = 'get_latest_artifact_info' ,
223355 branch = branch ,
224356 target = target ,
225- successful = True ,
226- maxResults = 1 ,
227357 signed = signed )
358+ if _use_v4 ():
359+ request = client .builds ().list ( # pylint: disable=no-member
360+ buildType = 'submitted' ,
361+ branch = branch ,
362+ target = target ,
363+ successful = True ,
364+ maxResults = 1 ,
365+ signed = signed )
366+ else :
367+ request = client .build ().list ( # pylint: disable=no-member
368+ buildType = 'submitted' ,
369+ branch = branch ,
370+ target = target ,
371+ successful = True ,
372+ maxResults = 1 ,
373+ signed = signed )
228374 request_str = (f'{ request .uri } , { request .method } , '
229375 f'{ request .body } , { request .methodId } ' )
230376
231377 builds = execute_request_with_retries (request )
232378 if not builds :
233- logs .error (f'No build found for target { target } , branch { branch } , '
234- f'request: { request_str } .' )
379+ logs .error (
380+ 'AndroidBuildAPI get_latest_artifact_info failed: no builds found.' ,
381+ api_version = version_tag ,
382+ operation = 'get_latest_artifact_info' ,
383+ branch = branch ,
384+ target = target ,
385+ signed = signed ,
386+ status = 'failed' ,
387+ request_str = request_str )
235388 return None
236389
237390 build = builds ['builds' ][0 ]
238391 bid = build ['buildId' ]
239392 target = build ['target' ]['name' ]
393+
394+ logs .info (
395+ 'AndroidBuildAPI get_latest_artifact_info completed.' ,
396+ api_version = version_tag ,
397+ operation = 'get_latest_artifact_info' ,
398+ branch = branch ,
399+ target = target ,
400+ signed = signed ,
401+ build_id = bid ,
402+ status = 'success' )
240403 return {'bid' : bid , 'branch' : branch , 'target' : target }
241404
242405
0 commit comments