Skip to content

Instantly share code, notes, and snippets.

@eps1lon
Last active January 13, 2021 05:13
Show Gist options
  • Save eps1lon/9c822429bffb5db5a3f221dd00fea842 to your computer and use it in GitHub Desktop.
Save eps1lon/9c822429bffb5db5a3f221dd00fea842 to your computer and use it in GitHub Desktop.
cancel multiple CI jobs/runs
/* eslint-disable no-restricted-syntax */
const { Octokit } = require('@octokit/rest');
const GITHUB_TOKEN = process.env.GITHUB_TOKEN;
async function main() {
const octokit = new Octokit({
auth: GITHUB_TOKEN,
});
if (typeof octokit.actions.listWorkflowRunsForRepo !== 'function') {
throw new TypeError(
`The used version of '@octokit/rest' is not supported. 'listWorkflowRunsForRepo' is implemented in '@octokit/rest@^18.0.12'.`,
);
}
const workflowRuns = octokit.paginate.iterator(octokit.actions.listWorkflowRunsForRepo, {
owner: 'mui-org',
repo: 'Material-UI',
actor: 'l10nbot',
status: 'queued',
});
for await (const response of workflowRuns) {
const runs = response.data;
for (const run of runs) {
if (run.name === 'CI' || run.name === 'maintenance') {
console.log('Cancelling run #%d', run.id);
octokit.actions
.cancelWorkflowRun({
owner: run.repository.owner.login,
repo: run.repository.name,
run_id: run.id,
})
.then(
() => {
console.log('Cancelled run #%d', run.id);
},
(reason) => {
console.error('Unable to cancel run #%d: %s', run.id, String(reason));
},
);
}
}
}
}
main().catch((error) => {
console.error(error);
process.exit(1);
});
/* eslint-disable @typescript-eslint/naming-convention */
/* eslint-disable no-await-in-loop */
/* eslint-disable no-restricted-syntax */
const fetch = require('cross-fetch');
const CIRCLE_TOKEN = process.env.CIRCLE_TOKEN;
async function* loadWorkflows(pipelineId) {
let pageToken = null;
do {
const url = `https://circleci.com/api/v2/pipeline/${pipelineId}/workflow?${
pageToken ? `page-token=${pageToken}` : ''
}}`;
const response = await fetch(url, { headers: { 'Circle-Token': CIRCLE_TOKEN } });
const json = await response.json();
const { next_page_token, items } = json;
for (const workflow of items) {
yield workflow;
}
pageToken = next_page_token;
} while (pageToken !== null);
}
async function* loadJobs(workflowId) {
let pageToken = null;
do {
const url = `https://circleci.com/api/v2/workflow/${workflowId}/job?${
pageToken ? `page-token=${pageToken}` : ''
}}`;
const response = await fetch(url, { headers: { 'Circle-Token': CIRCLE_TOKEN } });
const json = await response.json();
const { next_page_token, items } = json;
for (const job of items) {
yield job;
}
pageToken = next_page_token;
} while (pageToken !== null);
}
async function* loadJobsByProject(projectSlug, branch) {
let pageToken = null;
do {
const url = `https://circleci.com/api/v2/project/${projectSlug}/pipeline?branch=${branch}&${
pageToken !== null ? `page-token=${pageToken}` : ''
}`;
const response = await fetch(url, { headers: { 'Circle-Token': CIRCLE_TOKEN } });
const { next_page_token, items } = await response.json();
for (const pipeline of items) {
const workflows = await loadWorkflows(pipeline.id);
for await (const workflow of workflows) {
const jobs = await loadJobs(workflow.id);
for await (const job of jobs) {
yield { job, pipeline, workflow };
}
}
}
pageToken = next_page_token;
} while (pageToken !== null);
}
async function cancelJob(projectSlug, jobNumber) {
const url = `https://circleci.com/api/v2/project/${projectSlug}/job/${jobNumber}/cancel`;
const response = await fetch(url, { method: 'POST', headers: { 'Circle-Token': CIRCLE_TOKEN } });
return response.json();
}
async function cancelWorkflow(workflowId) {
const url = `https://circleci.com/api/v2/workflow/${workflowId}/cancel`;
const response = await fetch(url, { method: 'POST', headers: { 'Circle-Token': CIRCLE_TOKEN } });
return response.json();
}
async function main() {
const projectSlug = 'gh/mui-org/material-ui';
const workflows = loadJobsByProject(projectSlug, 'l10n_master');
for await (const { job, pipeline, workflow } of workflows) {
if (workflow.status === 'running') {
console.log(`cancelling workflow ${workflow.id}`);
cancelWorkflow(workflow.id).then(
(result) => {
console.log(workflow.id, result);
},
(error) => {
console.error(error);
console.error(`The above error occured with workflow ${workflow.id}`);
},
);
}
if (job.status === 'not_running') {
console.log(`cancelling job ${job.id}`);
cancelJob(projectSlug, job.job_number).then(
(result) => {
console.log(job.id, result);
},
(error) => {
console.error(error);
console.error(`The above error occured with job ${job.id}`);
},
);
}
}
}
main().catch((error) => {
console.error(error);
process.exit(1);
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment