pulumi-hugo-cn/scripts/ci/await-in-progress.js
2023-10-26 15:47:47 -07:00

61 lines
2.6 KiB
JavaScript

const { Octokit } = require("@octokit/rest");
// Wait for any in-progress runs of the same workflow on this branch to complete before
// proceeding. In other words, if the current workflow is an instance of the "foo"
// workflow, and there's another "foo" workflow running for a different commit on the same
// branch as this one, wait for that workflow to complete before exiting (in order to
// prevent the current workflow from continuing).
// Inspired by https://github.com/softprops/turnstyle.
async function waitForInProgressRuns() {
// See https://docs.github.com/en/free-pro-team@latest/actions/reference/environment-variables
// for an explanation of each of these variables.
const githubToken = process.env.GITHUB_TOKEN;
const currentRunID = parseInt(process.env.GITHUB_RUN_ID, 10);
const workflowName = process.env.GITHUB_WORKFLOW;
const [owner, repo] = process.env.GITHUB_REPOSITORY.split("/");
const branch = process.env.GITHUB_HEAD_REF || process.env.GITHUB_REF.replace("refs/heads/", "");
const status = "in_progress";
const octokit = new Octokit({
auth: githubToken,
});
// Given the current workflow name, fetch its ID.
const workflows = await octokit.rest.actions.listRepoWorkflows({ owner, repo });
const workflow_id = workflows.data.workflows.find(workflow => workflow.name === workflowName).id;
// Fetch a paginated list of in-progress runs of the current workflow.
const runs = await octokit.paginate(
octokit.rest.actions.listWorkflowRuns.endpoint.merge({
owner,
repo,
branch,
workflow_id,
status,
}),
);
// Sort in-progress runs descendingly, excluding the current one.
const recent = runs.sort((a, b) => b.id - a.id).filter(run => run.id < currentRunID);
console.log(`Found ${recent.length} other ${workflowName} job(s) running on branch ${branch}.`);
if (recent.length > 0) {
const [mostRecent] = recent;
console.log(`Waiting for ${mostRecent.html_url} to complete before continuing.`);
await Promise.resolve(setTimeout(waitForInProgressRuns, 60000)); // One minute.
} else {
console.log("Continuing.");
}
}
// Unhandled errors that happen within Promises yield warnings, but do not (yet) cause the
// process to exit nonzero. Since we want this script to fail loudly when something goes
// wrong, we listen for unhandledRejection events and rethrow, exiting 1.
// https://nodejs.org/api/process.html#process_event_unhandledrejection
process.on("unhandledRejection", error => {
throw error;
});
waitForInProgressRuns();