Fallback if GitHub status is stuck as "pending" (#20729)
GitHub's status API is super flaky. Sometimes it reports a job as "pending" even after it completes in CircleCI. If it's still pending when we time out, return the build ID anyway. TODO: The location of the retry loop is a bit weird. We should probably combine this function with the one that downloads the artifacts, and wrap the retry loop around the whole thing.
Andrew Clark committed
Feb 3, 2021 at 17:33 UTC
00e38c80b28fd9b5e99b890d85e080edc2fcc49f
1 file changed
+20
-3
scripts/release/get-build-id-for-commit.js
+20
-3
@@ -2,8 +2,8 @@
2
3
const fetch = require('node-fetch');
4
5
-const POLLING_INTERVAL = 5 * 1000; // 5 seconds
6
-const RETRY_TIMEOUT = 10 * 60 * 1000; // 10 minutes
5
+const POLLING_INTERVAL = 10 * 1000; // 10 seconds
6
+const RETRY_TIMEOUT = 4 * 60 * 1000; // 4 minutes
7
8
function wait(ms) {
9
return new Promise(resolve => {
@@ -11,6 +11,10 @@ function wait(ms) {
11
});
12
}
13
14
+function scrapeBuildIDFromStatus(status) {
15
+ return /\/facebook\/react\/([0-9]+)/.exec(status.target_url)[1];
16
+}
17
+
18
async function getBuildIdForCommit(sha) {
19
const retryLimit = Date.now() + RETRY_TIMEOUT;
20
retry: while (true) {
@@ -30,11 +34,24 @@ async function getBuildIdForCommit(sha) {
34
const status = statuses[i];
35
if (status.context === `ci/circleci: process_artifacts_combined`) {
36
if (status.state === 'success') {
33
- return /\/facebook\/react\/([0-9]+)/.exec(status.target_url)[1];
37
+ return scrapeBuildIDFromStatus(status);
38
}
39
if (status.state === 'failure') {
40
throw new Error(`Build job for commit failed: ${sha}`);
41
}
42
+ if (status.state === 'pending') {
43
+ if (Date.now() < retryLimit) {
44
+ await wait(POLLING_INTERVAL);
45
+ continue retry;
46
+ }
47
+ // GitHub's status API is super flaky. Sometimes it reports a job
48
+ // as "pending" even after it completes in CircleCI. If it's still
49
+ // pending when we time out, return the build ID anyway.
50
+ // TODO: The location of the retry loop is a bit weird. We should
51
+ // probably combine this function with the one that downloads the
52
+ // artifacts, and wrap the retry loop around the whole thing.
53
+ return scrapeBuildIDFromStatus(status);
54
+ }
55
}
56
}
57
if (state === 'pending') {