[Adroid v4 API] Add Android Build API V4 REST client and tests#5370
Conversation
| HTTP_TIMEOUT = 60 | ||
|
|
||
| # 20 MB default chunk size for file downloads. | ||
| DEFAULT_CHUNK_SIZE = 20 * 1024 * 1024 |
There was a problem hiding this comment.
220c2da to
b185fc1
Compare
|
I'll let @dylanjew handle this as I'm about to go OOO for a while. |
|
I'm not super familiar with this part of the code, so I'll trust your judgment: is this something we should test on dev? If so, can you provide some evidence that it is working as expected? Same applies for #5371. |
dylanjew
left a comment
There was a problem hiding this comment.
LGTM! just a couple small questions
|
|
||
| @retry.wrap( | ||
| retries=5, delay=1, backoff=2, function='android_build_v4_api._request') | ||
| def _request(self, |
There was a problem hiding this comment.
Actually, thats a good idea, Ill adapt the fetch_url util to accept a bunch of additional params without compromising its behavior
| except (requests.exceptions.RequestException, | ||
| google.auth.exceptions.GoogleAuthError, ValueError) as e: | ||
| logs.error(f'V4 get_artifact_metadata failed for artifact {name}: {e}') | ||
| return None |
There was a problem hiding this comment.
Is there a reason we catch and log instead of just allowing the error to raise? Was this the previous behavior?
There was a problem hiding this comment.
Yes, in the V3 API implementation, all HTTP requests were wrapped in _execute_request_with_retries(request)
When failed, it catched the exception logged an error and then returned None
| self.mock.get.return_value = mock_response | ||
|
|
||
| result = self.api.list_builds('git_main', 'target_name') | ||
| self.assertIsNone(result) |
There was a problem hiding this comment.
this is why it's a bit confusing to swallow the error and return None, we can't tell whether the error was due to an intermittent connection issue or because some assumption about the API has changed and we need to parse the response differently
There was a problem hiding this comment.
True, we can let the exceptions be thrown instead(by encapsulating them) in a custom exception, like we do in the swarming api But for this api use case, we will end up catching the exception and logging an error and returning None(as done previously)
There was a problem hiding this comment.
We can also create another PR that focuses on throwing exceptions instead, WDYT?
There was a problem hiding this comment.
Thanks! I think it's reasonable to preserve the existing behavior to reduce the blast radius of the API change.
@IvanBM18 Can you add your testing to the description? This PR doesn't exercise the new code, but #5371 will. The codepath is Chrome specific. |
Oh, I see that you included it in the script! Could you add a brief summary of what the script tests to the description? e.g. ensures each API returns successfully, the artifacts are downloaded etc. |
javanlacerda
left a comment
There was a problem hiding this comment.
Overall LGTM, but as it changes the fetch_url, it would be great to run it in dev to check any side effects.
Hi @javanlacerda pushed the changes from this pr(and its dependants) to dev and reported the errors found in this description, everything LGTM please check it out :D |
## Overview As per requested, we created a new feature flag to disable definitely the API build use cases(used trough `fetch_artifact.py`), this feature flag is enabled by default, because that's the current API & ClusterFuzz workflow. But can be disabled by adding the feature flag to the DB and marking it as enabled=false. ## Changes - Creates new feature_flag, and enables it by default in `fetch_artifact.py` - Logs warnings when the feature flag is disabled in `fetch_artifact.py` - Safely exists the related methods in `symbols_downloader` and `flash.py` which consume the `fetch_artifact.py` - Moved up the `adb.bad_state_reach()` method from the `fetch_artifact.py` module to its callers, this way we can now handle better the None values and raised errors from the API being turned off by the feature flag. ## Tests After the initial tests in the PR parents, i tested this changes once more in dev(including all 3 prs), looking specifically for `utils.fetch_url` or errors inherent to the return value from this method. Basically since my changes landed in dev the following error groups where seen: <img width="1735" height="1240" alt="image" src="https://github.com/user-attachments/assets/0591fb5c-d728-406a-b888-4f2534b2daab" /> Discarded the errors following this logic: - 403 Errors are expected to appear as per the changes that were previously there to avoid them are no longer in dev - Some error groups only appeared on previous clusterfuzz versions - Other errors are expected(like the queue size limit or bad revision errors) - There are errors from corpus pruning & fuzzer not found, this have been seen for a while now, not related to my changes - Lastly there are some errors in a cron_job, specifically in [this file ](https://github.com/google/clusterfuzz/blob/master/src/clusterfuzz/_internal/cron/load_bigquery_stats.py)but this one doesn't make usage of `fetch_url` and nor does the method that triggered the error #### PR review 1. [**#5370** Add Android Build API V4 REST client and tests ](#5370) 2. [#5371 Migrate fetch_artifact to use new V4 API](#5371) 3. 👉 [#5373 Creates Feature Flag for Android V4 API](#5373) *(This PR)* Please only approve, I'll merge this PR's to avoid any possible merge conflict that can appear in the process :D
## Overview Bug: b/422775458 Our previous implementation of the android builv v4 api was wrong, it failed always because the api no longer worked on discovery service url. In other [PR](#5370) we focused on creating the new api to interact with the v4 requirements. In this PR we focus on using this api class in the `fetch_artifact.py` module, ## Changes - Made private all the methods that were only used internally in `fetch_artifact.py` - Refactors previous usage of the v4 api to now use the current version with minimal changes in the `fetch_artifact.py` script to avoid breaking anything ## Tests performed - Created unit tests for `feth_artifact.py` - Tested this script using [a custom script](https://github.com/google/clusterfuzz/compare/android-build-v4-testing) (test details in [this PR description](#5370) ) #### PR review 1. [**#5370** Add Android Build API V4 REST client and tests ](#5370) 2. 👉 #5371 Migrate fetch_artifact to use new V4 API *(This PR)* 3. [#5373 Creates Feature Flag for Android V4 API](#5373) Please only approve, I'll merge this PR's to avoid any possible merge conflict that can appear in the process :D
Changes
We previously migrated the v3 api to use v4 in fetch_artifact.py but after testing the implementation we discovered that we can't continue the same approach of using a client created by service discovery url , if we want to continue using the android build api we needed to change our strategy and start using raw http requests.
utils.fetch_urlto unify requests and reuse it in this new api while maintaining previous functionalityFor more info in the v4 api see: go/build-api-v4-clients-migration-guide & b/422775458
Tests
Testing script details
The custom script performs various tests that imitate how clusterfuzz would use the
fetch_artifact.pymodule in conjunction with our new api.The script test the following:
Test steps:
Dev verification
After the initial tests ^ i tested this changes once more in dev(including all 3 prs), looking specifically for

utils.fetch_urlor errors inherent to the return value from this method. Basically since my changes landed in dev the following error groups where seen:Discarded the errors following this logic:
fetch_urland nor does the method that triggered the errorNote:
PR review Stack
Please only approve, I'll merge this PR's to avoid any possible merge conflict that can appear in the process :D