mirror of
https://github.com/facebook/react.git
synced 2026-02-23 12:13:04 +00:00
* Allow aritfacts download even if CI is broken Adds an option to the download script to disable the CI check and continue downloading the artifacts even if CI is broken. I often rely on this to debug broken build artifacts. I was thinking the sizebot should also use this when downloading the base artifacts from main, since for the purposes of size tracking, it really doesn't matter whether the base commit is broken. * Sizebot should work even if base rev is broken Sizebot works by downloading the build artifacts for the base revision and comparing the fize sizes, but the download script will fail if the base revision has a failing CI job. This happens more often than it should because of flaky cron jobs, but even when it does, we shouldn't let it affect the sizebot — for the purposes of tracking sizes, it doesn't really matter whether the base revision is broken.
76 lines
2.5 KiB
JavaScript
76 lines
2.5 KiB
JavaScript
'use strict';
|
|
|
|
const fetch = require('node-fetch');
|
|
|
|
const POLLING_INTERVAL = 10 * 1000; // 10 seconds
|
|
const RETRY_TIMEOUT = 4 * 60 * 1000; // 4 minutes
|
|
|
|
function wait(ms) {
|
|
return new Promise(resolve => {
|
|
setTimeout(() => resolve(), ms);
|
|
});
|
|
}
|
|
|
|
function scrapeBuildIDFromStatus(status) {
|
|
return /\/facebook\/react\/([0-9]+)/.exec(status.target_url)[1];
|
|
}
|
|
|
|
async function getBuildIdForCommit(sha, allowBrokenCI = false) {
|
|
const retryLimit = Date.now() + RETRY_TIMEOUT;
|
|
retry: while (true) {
|
|
const statusesResponse = await fetch(
|
|
`https://api.github.com/repos/facebook/react/commits/${sha}/status`
|
|
);
|
|
|
|
if (!statusesResponse.ok) {
|
|
if (statusesResponse.status === 404) {
|
|
throw Error('Could not find commit for: ' + sha);
|
|
}
|
|
const {message, documentation_url} = await statusesResponse.json();
|
|
const msg = documentation_url
|
|
? `${message}\n\t${documentation_url}`
|
|
: message;
|
|
throw Error(msg);
|
|
}
|
|
|
|
const {statuses, state} = await statusesResponse.json();
|
|
if (!allowBrokenCI && state === 'failure') {
|
|
throw new Error(`Base commit is broken: ${sha}`);
|
|
}
|
|
for (let i = 0; i < statuses.length; i++) {
|
|
const status = statuses[i];
|
|
if (status.context === `ci/circleci: process_artifacts_combined`) {
|
|
if (status.state === 'success') {
|
|
return scrapeBuildIDFromStatus(status);
|
|
}
|
|
if (status.state === 'failure') {
|
|
throw new Error(`Build job for commit failed: ${sha}`);
|
|
}
|
|
if (status.state === 'pending') {
|
|
if (Date.now() < retryLimit) {
|
|
await wait(POLLING_INTERVAL);
|
|
continue retry;
|
|
}
|
|
// 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.
|
|
return scrapeBuildIDFromStatus(status);
|
|
}
|
|
}
|
|
}
|
|
if (state === 'pending') {
|
|
if (Date.now() < retryLimit) {
|
|
await wait(POLLING_INTERVAL);
|
|
continue retry;
|
|
}
|
|
throw new Error('Exceeded retry limit. Build job is still pending.');
|
|
}
|
|
throw new Error('Could not find build for commit: ' + sha);
|
|
}
|
|
}
|
|
|
|
module.exports = getBuildIdForCommit;
|