Last active
January 13, 2021 05:13
-
-
Save eps1lon/9c822429bffb5db5a3f221dd00fea842 to your computer and use it in GitHub Desktop.
cancel multiple CI jobs/runs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* 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); | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* 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