From 96c80309301535dd700ff50364d8afebe55f1f2a Mon Sep 17 00:00:00 2001 From: 8666 <1508173+8666@users.noreply.github.com> Date: Tue, 3 Oct 2023 17:21:23 +0200 Subject: [PATCH] Add option `only_status` (#210) Developers sometimes leave the workflows in queued state. This happens when you have a protected environment and deployment is waiting for approval. They sometimes do not approve and just leave the workflow pending waiting for a merge that will start a new workflow run and deploy from there multiple merges at once. We need to cancel the older pending ones if new PR is merged but SKIP canceling workflows that are running as it might be dangerous to interrupt it. To play it safe we introduce `only_status: 'waiting'` in order to avoid canceling runs with status `in_progress` GitHub official implementation also does not support this option and they do not have plans to implement it soon, so we are adding it to this action --------- Co-authored-by: 8666 Co-authored-by: Steven --- README.md | 19 +++++++++++++++++++ action.yml | 5 ++++- dist/index.js | 3 ++- src/index.ts | 3 ++- 4 files changed, 27 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index bf405efc..05d026fc 100644 --- a/README.md +++ b/README.md @@ -145,6 +145,24 @@ jobs: all_but_latest: true ``` +### Advanced: Skip runs that are in progress + +Some workflows may be dangerous to cancel when they are in progress. If you want to play safe and cancel only workflows that are in state `waiting`, most likely waiting for approval to be deployed in a protected environment, use `only_status` to only cancel runs with a specific status. + +```yml +name: Cancel +on: [push] +jobs: + cancel: + name: 'Cancel Previous Runs' + runs-on: ubuntu-latest + timeout-minutes: 3 + steps: + - uses: styfle/cancel-workflow-action + with: + only_status: 'waiting' +``` + ### Advanced: Token Permissions No change to permissions is required by default. The instructions below are for improved control over of those permissions. @@ -174,4 +192,5 @@ _Note_ : This is typical when global access is set to be restrictive. Only this - Run `yarn install` - Edit `./src/index.ts` - Run `yarn build` +- Run `yarn format` - Commit changes including `./dist/index.js` bundle diff --git a/action.yml b/action.yml index 54af1d4d..c1618fef 100644 --- a/action.yml +++ b/action.yml @@ -17,9 +17,12 @@ inputs: default: ${{ github.token }} required: false all_but_latest: - description: "Cancel all actions but the last one" + description: "Optional - Cancel all actions but the most recent one." required: false default: 'false' + only_status: + description: "Optional - Cancel runs with a specific status, such as `waiting`." + required: false runs: using: 'node16' main: 'dist/index.js' diff --git a/dist/index.js b/dist/index.js index 853fcd71..f4730ad8 100644 --- a/dist/index.js +++ b/dist/index.js @@ -9706,6 +9706,7 @@ async function main() { const workflow_id = core.getInput('workflow_id', { required: false }); const ignore_sha = core.getBooleanInput('ignore_sha', { required: false }); const all_but_latest = core.getBooleanInput('all_but_latest', { required: false }); + const only_status = core.getInput('only_status', { required: false }); console.log(`Found token: ${token ? 'yes' : 'no'}`); const workflow_ids = []; const octokit = github.getOctokit(token); @@ -9751,7 +9752,7 @@ async function main() { const runningWorkflows = workflow_runs.filter(run => run.head_repository.id === trigger_repo_id && run.id !== current_run.id && (ignore_sha || run.head_sha !== headSha) && - run.status !== 'completed' && + (only_status ? run.status === only_status : run.status !== 'completed') && new Date(run.created_at) < cancelBefore); if (all_but_latest && new Date(current_run.created_at) < cancelBefore) { runningWorkflows.push(current_run); diff --git a/src/index.ts b/src/index.ts index 93d04dbc..87888e1d 100644 --- a/src/index.ts +++ b/src/index.ts @@ -34,6 +34,7 @@ async function main() { const workflow_id = core.getInput('workflow_id', { required: false }); const ignore_sha = core.getBooleanInput('ignore_sha', { required: false }); const all_but_latest = core.getBooleanInput('all_but_latest', { required: false }); + const only_status = core.getInput('only_status', { required: false }); console.log(`Found token: ${token ? 'yes' : 'no'}`); const workflow_ids: string[] = []; const octokit = github.getOctokit(token); @@ -90,7 +91,7 @@ async function main() { run.head_repository.id === trigger_repo_id && run.id !== current_run.id && (ignore_sha || run.head_sha !== headSha) && - run.status !== 'completed' && + (only_status ? run.status === only_status : run.status !== 'completed') && new Date(run.created_at) < cancelBefore, ); if (all_but_latest && new Date(current_run.created_at) < cancelBefore) {