This is an automated email from the ASF dual-hosted git repository. potiuk pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/airflow-cancel-workflow-runs.git
commit 0acb1c01f6740dfbca6eab6e21a5b5066e8bafb3 Author: Jarek Potiuk <[email protected]> AuthorDate: Tue Oct 20 08:14:31 2020 +0200 Adds cancelling workflows by name (#8) --- README.md | 282 ++++++++++++++++++++++++++++++++-------------------------- action.yml | 5 ++ dist/index.js | 34 ++++--- src/main.ts | 55 ++++++------ 4 files changed, 210 insertions(+), 166 deletions(-) diff --git a/README.md b/README.md index 5354a8e..90c9a22 100644 --- a/README.md +++ b/README.md @@ -15,11 +15,6 @@ - [Inputs](#inputs) - [Outputs](#outputs) - [Examples](#examples) - - [Repositories that do not use Pull Requests from forks](#repositories-that-do-not-use-pull-requests-from-forks) - - [Cancel duplicate runs for "self" workflow](#cancel-duplicate-runs-for-self-workflow) - - [Cancel "self" workflow run](#cancel-self-workflow-run) - - [Fail-fast workflow runs with failed jobs](#fail-fast-workflow-runs-with-failed-jobs) - - [Cancel all runs with named jobs](#cancel-all-runs-with-named-jobs) - [Repositories that use Pull Requests from forks](#repositories-that-use-pull-requests-from-forks) - [Cancel duplicate runs for the source workflow](#cancel-duplicate-runs-for-the-source-workflow) - [Cancel duplicate jobs for triggered workflow](#cancel-duplicate-jobs-for-triggered-workflow) @@ -28,6 +23,12 @@ - [Fail-fast source workflow runs with failed jobs](#fail-fast-source-workflow-runs-with-failed-jobs) - [Fail-fast source workflow runs with failed jobs and corresponding triggered runs](#fail-fast-source-workflow-runs-with-failed-jobs-and-corresponding-triggered-runs) - [Fail-fast for triggered workflow runs with failed jobs](#fail-fast-for-triggered-workflow-runs-with-failed-jobs) + - [Cancel another workflow run](#cancel-another-workflow-run) + - [Repositories that do not use Pull Requests from forks](#repositories-that-do-not-use-pull-requests-from-forks) + - [Cancel duplicate runs for "self" workflow](#cancel-duplicate-runs-for-self-workflow) + - [Cancel "self" workflow run](#cancel-self-workflow-run) + - [Fail-fast workflow runs with failed jobs](#fail-fast-workflow-runs-with-failed-jobs) + - [Cancel all runs with named jobs](#cancel-all-runs-with-named-jobs) - [Development environment](#development-environment) - [License](#license) @@ -114,7 +115,8 @@ and `schedule` events are no longer needed. | `notifyPRCancelMessage` | no | | Optional cancel message to use instead of the default one when notifyPRCancel is true. It is only used in 'self' cancelling mode. | | `notifyPRMessageStart` | no | | Only for workflow_run events triggered by the PRs. If not empty, it notifies those PRs with the message specified at the start of the workflow - adding the link to the triggered workflow_run. | | `jobNameRegexps` | no | | An array of job name regexps. Only runs containing any job name matching any of of the regexp in this array are considered for cancelling in `failedJobs` and `namedJobs` cancel modes. | -| `skipEventTypes` | no | | Array of event names that should be skipped when cancelling (JSON-encoded string). This might be used in order to skip direct pushes or scheduled events.. | +| `skipEventTypes` | no | | Array of event names that should be skipped when cancelling (JSON-encoded string). This might be used in order to skip direct pushes or scheduled events. | +| `workflowFileName` | no | | Name of the workflow file. It can be used if you want to cancel a different workflow than yours. | The job cancel modes work as follows: @@ -145,127 +147,6 @@ The job cancel modes work as follows: Note that you can combine the steps below in several steps of the same job. The examples here are showing one step per case for clarity. -## Repositories that do not use Pull Requests from forks - -Note that examples in this chapter only work if you do not have Pull Requests coming from forks (so for -example if you only work in a private repository). When those action runs within the usual `pull_request` -triggered runs coming from a fork, they have not enough permissions to cancel running workflows. - -If you want to cancel `pull_requests` from forks, you need to use `workflow_run` triggered runs - see the -[Repositories that use Pull Requests from fork](#repositories-that-use-pull-requests-from-forks) chapter. - -Note that in case you configure the separate `workflow_run` Cancelling workflow, there is no need to add -the action to the "source" workflows. The "Canceling workflow" pattern handles well not only Pull Requests -from the forks, but also all other cases - including cancelling Pull Requests for the same repository -and canceling scheduled runs. - -### Cancel duplicate runs for "self" workflow - -Cancels past runs for the same workflow (with the same branch). - -In the case below, any of the direct "push" events will cancel all past runs for the same branch as the -one being pushed. However, it can be configured for "pull_request" (in the same repository) or "schedule" -type of events as well. It will also notify the PR with the comment containining why it has been -cancelled. - -```yaml -name: CI -on: push -jobs: - cancel-duplicate-workflow-runs: - name: "Cancel duplicate workflow runs" - runs-on: ubuntu-latest - steps: - - uses: potiuk/cancel-workflow-runs@v2 - name: "Cancel duplicate workflow runs" - with: - cancelMode: duplicates - notifyPRCancel: true -``` - -### Cancel "self" workflow run - -This is useful in case you decide to cancel "self" run. - -In the case below - own workflow will be cancelled immediately. It can be configured for "push", -"pull_request" (from the same repository) or "schedule" type of events. - -```yaml -name: CI -on: push -jobs: - cancel-self-run: - name: "Cancel the self workflow run" - runs-on: ubuntu-latest - steps: - - name: "Cancel the self workflow run" - uses: potiuk/cancel-workflow-runs@v2 - with: - cancelMode: self - token: ${{ secrets.GITHUB_TOKEN }} - notifyPRCancel: true -``` - -### Fail-fast workflow runs with failed jobs - -Cancels all runs (including self run!) if they have failed jobs matching any of the regular expressions. -Note that it does not take into account the branch of the running jobs. It will cancel all runs with failed -jobs, no matter what branch originated it. - -In the case below, if any of the own workflow runs have failed jobs matching any of the -`^Static checks$` and `^Build docs^` or `^Build prod image .*` regexp, this workflow will cancel the runs. - -```yaml -name: CI -on: - push: - -jobs: - cancel-self-failed-runs: - name: "Cancel failed runs" - runs-on: ubuntu-latest - steps: - - uses: potiuk/cancel-workflow-runs@v2 - name: "Cancel failed runs" - with: - cancelMode: failedJobs - token: ${{ secrets.GITHUB_TOKEN }} - jobNameRegexps: '["^Static checks$", "^Build docs$", "^Build prod image.*"]' - notifyPRCancel: true -``` - -### Cancel all runs with named jobs - -Cancels all runs (including self run!) if any of the job names match any of the regular -expressions. Note that it does not take into account the branch of the runs. It will cancel all runs with -matching jobs, no matter what branch originated it. - -This is useful in case of job names generated dynamically. - -In the case below, if any of the "self" workflow runs has job names that matches any of the -`^Static checks$` and `^Build docs^` or `^Build prod image .*` regexp, this workflow will cancel the runs. - -```yaml -on: - push: - workflow_run: - workflows: ['CI'] - types: ['requested'] - -jobs: - cancel-self-failed-runs: - name: "Cancel the self workflow run" - runs-on: ubuntu-latest - steps: - - uses: potiuk/cancel-workflow-runs@v2 - name: "Cancel past CI runs" - with: - cancelMode: namedJobs - token: ${{ secrets.GITHUB_TOKEN }} - jobNameRegexps: '["^Static checks$", "^Build docs$", "^Build prod image.*"]' - notifyPRCancel: true -``` - ## Repositories that use Pull Requests from forks Note that in case you implement separate "Canceling workflow", following the examples below, you do not @@ -611,6 +492,153 @@ jobs: jobNameRegexps: '["^Static checks$", "^Build docs$", "^Build prod image.*"]' ``` +### Cancel another workflow run + +This is useful in case you decide to cancel the *source run* that triggered the *triggered run*. +In the case below, the step cancels the `CI` workflow that triggered the `Cancelling` run. + +```yaml +name: Cancelling +on: + workflow_run: + workflows: ['CI'] + types: ['requested'] + + cancel-other-workflow-run: + name: "Cancel the self CI workflow run" + runs-on: ubuntu-latest + steps: + - name: "Cancel the self CI workflow run" + uses: potiuk/cancel-workflow-runs@v2 + with: + cancelMode: duplicates + token: ${{ secrets.GITHUB_TOKEN }} + workflowFileName: other_workflow.yml +``` + + + +## Repositories that do not use Pull Requests from forks + +Note that examples in this chapter only work if you do not have Pull Requests coming from forks (so for +example if you only work in a private repository). When those action runs within the usual `pull_request` +triggered runs coming from a fork, they have not enough permissions to cancel running workflows. + +If you want to cancel `pull_requests` from forks, you need to use `workflow_run` triggered runs - see the +[Repositories that use Pull Requests from fork](#repositories-that-use-pull-requests-from-forks) chapter. + +Note that in case you configure the separate `workflow_run` Cancelling workflow, there is no need to add +the action to the "source" workflows. The "Canceling workflow" pattern handles well not only Pull Requests +from the forks, but also all other cases - including cancelling Pull Requests for the same repository +and canceling scheduled runs. + +### Cancel duplicate runs for "self" workflow + +Cancels past runs for the same workflow (with the same branch). + +In the case below, any of the direct "push" events will cancel all past runs for the same branch as the +one being pushed. However, it can be configured for "pull_request" (in the same repository) or "schedule" +type of events as well. It will also notify the PR with the comment containining why it has been +cancelled. + +```yaml +name: CI +on: push +jobs: + cancel-duplicate-workflow-runs: + name: "Cancel duplicate workflow runs" + runs-on: ubuntu-latest + steps: + - uses: potiuk/cancel-workflow-runs@v2 + name: "Cancel duplicate workflow runs" + with: + cancelMode: duplicates + notifyPRCancel: true +``` + +### Cancel "self" workflow run + +This is useful in case you decide to cancel "self" run. + +In the case below - own workflow will be cancelled immediately. It can be configured for "push", +"pull_request" (from the same repository) or "schedule" type of events. + +```yaml +name: CI +on: push +jobs: + cancel-self-run: + name: "Cancel the self workflow run" + runs-on: ubuntu-latest + steps: + - name: "Cancel the self workflow run" + uses: potiuk/cancel-workflow-runs@v2 + with: + cancelMode: self + token: ${{ secrets.GITHUB_TOKEN }} + notifyPRCancel: true +``` + +### Fail-fast workflow runs with failed jobs + +Cancels all runs (including self run!) if they have failed jobs matching any of the regular expressions. +Note that it does not take into account the branch of the running jobs. It will cancel all runs with failed +jobs, no matter what branch originated it. + +In the case below, if any of the own workflow runs have failed jobs matching any of the +`^Static checks$` and `^Build docs^` or `^Build prod image .*` regexp, this workflow will cancel the runs. + +```yaml +name: CI +on: + push: + +jobs: + cancel-self-failed-runs: + name: "Cancel failed runs" + runs-on: ubuntu-latest + steps: + - uses: potiuk/cancel-workflow-runs@v2 + name: "Cancel failed runs" + with: + cancelMode: failedJobs + token: ${{ secrets.GITHUB_TOKEN }} + jobNameRegexps: '["^Static checks$", "^Build docs$", "^Build prod image.*"]' + notifyPRCancel: true +``` + +### Cancel all runs with named jobs + +Cancels all runs (including self run!) if any of the job names match any of the regular +expressions. Note that it does not take into account the branch of the runs. It will cancel all runs with +matching jobs, no matter what branch originated it. + +This is useful in case of job names generated dynamically. + +In the case below, if any of the "self" workflow runs has job names that matches any of the +`^Static checks$` and `^Build docs^` or `^Build prod image .*` regexp, this workflow will cancel the runs. + +```yaml +on: + push: + workflow_run: + workflows: ['CI'] + types: ['requested'] + +jobs: + cancel-self-failed-runs: + name: "Cancel the self workflow run" + runs-on: ubuntu-latest + steps: + - uses: potiuk/cancel-workflow-runs@v2 + name: "Cancel past CI runs" + with: + cancelMode: namedJobs + token: ${{ secrets.GITHUB_TOKEN }} + jobNameRegexps: '["^Static checks$", "^Build docs$", "^Build prod image.*"]' + notifyPRCancel: true +``` + ## Development environment diff --git a/action.yml b/action.yml index 8fc9087..103d4e4 100644 --- a/action.yml +++ b/action.yml @@ -46,6 +46,11 @@ inputs: Array of event names that should be skipped when cancelling (JSON-encoded string). This might be used in order to skip direct pushes or scheduled events. required: false + workflowFileName: + description: | + Name of the workflow file. It can be used if you want to cancel a different workflow than yours. + required: false + runs: using: 'node12' main: 'dist/index.js' diff --git a/dist/index.js b/dist/index.js index 53c47fc..a347a2c 100644 --- a/dist/index.js +++ b/dist/index.js @@ -1894,30 +1894,38 @@ function run() { const skipEventTypes = skipEventTypesString ? JSON.parse(skipEventTypesString) : []; + const workflowFileName = core.getInput('workflowFileName'); const [owner, repo] = repository.split('/'); core.info(`\nGetting workflow id for source run id: ${sourceRunId}, owner: ${owner}, repo: ${repo},` + ` skipEventTypes: ${skipEventTypes}\n`); - const sourceWorkflowId = yield getWorkflowId(octokit, sourceRunId, owner, repo); + let sourceWorkflowId; + if (workflowFileName) { + sourceWorkflowId = workflowFileName; + core.info(`\nFinding runs for another workflow found by ${workflowFileName} name: ${sourceWorkflowId}\n`); + } + else { + sourceWorkflowId = yield getWorkflowId(octokit, sourceRunId, owner, repo); + if (sourceRunId === selfRunId) { + core.info(`\nFinding runs for my own workflow ${sourceWorkflowId}\n`); + } + else { + core.info(`\nFinding runs for source workflow ${sourceWorkflowId}\n`); + } + if (eventName === 'workflow_run' && sourceRunId === selfRunId) { + if (cancelMode === CancelMode.DUPLICATES) + throw Error(`You cannot run "workflow_run" in ${cancelMode} cancelMode without "sourceId" input.` + + 'It will likely not work as you intended - it will cancel runs which are not duplicates!' + + 'See the docs for details.'); + } + } core.info(`Repository: ${repository}, Owner: ${owner}, Repo: ${repo}, ` + `Event name: ${eventName}, CancelMode: ${cancelMode}, ` + `sourceWorkflowId: ${sourceWorkflowId}, sourceRunId: ${sourceRunId}, selfRunId: ${selfRunId}, ` + `jobNames: ${jobNameRegexps}`); - if (sourceRunId === selfRunId) { - core.info(`\nFinding runs for my own workflow ${sourceWorkflowId}\n`); - } - else { - core.info(`\nFinding runs for source workflow ${sourceWorkflowId}\n`); - } if (jobNameRegexps.length > 0 && [CancelMode.DUPLICATES, CancelMode.SELF].includes(cancelMode)) { throw Error(`You cannot specify jobNames on ${cancelMode} cancelMode.`); } - if (eventName === 'workflow_run' && sourceRunId === selfRunId) { - if (cancelMode === CancelMode.DUPLICATES) - throw Error(`You cannot run "workflow_run" in ${cancelMode} cancelMode without "sourceId" input.` + - 'It will likely not work as you intended - it will cancel runs which are not duplicates!' + - 'See the docs for details.'); - } const [headRepo, headBranch, sourceEventName, headSha, mergeCommitSha, pullRequest] = yield getOrigin(octokit, sourceRunId, owner, repo); verboseOutput('sourceHeadRepo', headRepo); verboseOutput('sourceHeadBranch', headBranch); diff --git a/src/main.ts b/src/main.ts index e7bcbe8..9f60f3d 100644 --- a/src/main.ts +++ b/src/main.ts @@ -23,7 +23,7 @@ function createListRunsQueryOtherRuns( owner: string, repo: string, status: string, - workflowId: number, + workflowId: number | string, headBranch: string, eventName: string ): rest.RequestOptions { @@ -44,7 +44,7 @@ function createListRunsQueryMyOwnRun( owner: string, repo: string, status: string, - workflowId: number, + workflowId: number | string, runId: number ): rest.RequestOptions { const request = { @@ -64,7 +64,7 @@ function createListRunsQueryAllRuns( owner: string, repo: string, status: string, - workflowId: number + workflowId: number | string ): rest.RequestOptions { const request = { owner, @@ -330,7 +330,7 @@ async function cancelRun( async function findAndCancelRuns( octokit: github.GitHub, selfRunId: number, - sourceWorkflowId: number, + sourceWorkflowId: number | string, sourceRunId: number, owner: string, repo: string, @@ -569,7 +569,7 @@ async function getOrigin( async function performCancelJob( octokit: github.GitHub, selfRunId: number, - sourceWorkflowId: number, + sourceWorkflowId: number | string, sourceRunId: number, owner: string, repo: string, @@ -670,6 +670,7 @@ async function run(): Promise<void> { const skipEventTypes = skipEventTypesString ? JSON.parse(skipEventTypesString) : [] + const workflowFileName = core.getInput('workflowFileName') const [owner, repo] = repository.split('/') @@ -677,12 +678,29 @@ async function run(): Promise<void> { `\nGetting workflow id for source run id: ${sourceRunId}, owner: ${owner}, repo: ${repo},` + ` skipEventTypes: ${skipEventTypes}\n` ) - const sourceWorkflowId = await getWorkflowId( - octokit, - sourceRunId, - owner, - repo - ) + let sourceWorkflowId + + if (workflowFileName) { + sourceWorkflowId = workflowFileName + core.info( + `\nFinding runs for another workflow found by ${workflowFileName} name: ${sourceWorkflowId}\n` + ) + } else { + sourceWorkflowId = await getWorkflowId(octokit, sourceRunId, owner, repo) + if (sourceRunId === selfRunId) { + core.info(`\nFinding runs for my own workflow ${sourceWorkflowId}\n`) + } else { + core.info(`\nFinding runs for source workflow ${sourceWorkflowId}\n`) + } + if (eventName === 'workflow_run' && sourceRunId === selfRunId) { + if (cancelMode === CancelMode.DUPLICATES) + throw Error( + `You cannot run "workflow_run" in ${cancelMode} cancelMode without "sourceId" input.` + + 'It will likely not work as you intended - it will cancel runs which are not duplicates!' + + 'See the docs for details.' + ) + } + } core.info( `Repository: ${repository}, Owner: ${owner}, Repo: ${repo}, ` + `Event name: ${eventName}, CancelMode: ${cancelMode}, ` + @@ -690,12 +708,6 @@ async function run(): Promise<void> { `jobNames: ${jobNameRegexps}` ) - if (sourceRunId === selfRunId) { - core.info(`\nFinding runs for my own workflow ${sourceWorkflowId}\n`) - } else { - core.info(`\nFinding runs for source workflow ${sourceWorkflowId}\n`) - } - if ( jobNameRegexps.length > 0 && [CancelMode.DUPLICATES, CancelMode.SELF].includes(cancelMode) @@ -703,15 +715,6 @@ async function run(): Promise<void> { throw Error(`You cannot specify jobNames on ${cancelMode} cancelMode.`) } - if (eventName === 'workflow_run' && sourceRunId === selfRunId) { - if (cancelMode === CancelMode.DUPLICATES) - throw Error( - `You cannot run "workflow_run" in ${cancelMode} cancelMode without "sourceId" input.` + - 'It will likely not work as you intended - it will cancel runs which are not duplicates!' + - 'See the docs for details.' - ) - } - const [ headRepo, headBranch,
