Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to make GitHub cancel all associated actions when a PR is closed?

Our workflow is configured to run when the following conditions are met:

name: '[apps] deploy'
on:
  pull_request:
    types:
      - opened
      - synchronize
      - reopened
      - ready_for_review

The problem I am seeing is that if the PR gets closed, the actions that have already started are allowed to continue.

As an example:

enter image description here

In this picture we can see that the PR was closed 19 minutes ago, but then 13 minutes ago (6 minutes later) one of the workers reported an error.

How do I ensure that the moment the PR is closed, all actions are cancelled?

like image 688
Gajus Avatar asked Nov 29 '25 17:11

Gajus


1 Answers

I thought this is going to be a question with an obvious answer that I just overlooked, but turns out it isn't.

The most basic way to do this is using actions/github-script, e.g.

jobs:
  comment:
    permissions:
      actions: write
      contents: read
    runs-on: ubuntu-latest
    if: ${{ github.event.pull_request.merged != true }}
    steps:
      - uses: actions/github-script@v7
        with:
          script: |
            const workflowIds = [
              '.github/workflows/deploy_review.yaml',
              '.github/workflows/packages.yaml',
            ];

            for (const workflowId of workflowIds) {
              const workflowRuns = await github.rest.actions.listWorkflowRuns({
                owner: context.repo.owner,
                repo: context.repo.repo,
                workflow_id: workflowId,
                per_page: 100,
                event: 'pull_request',
                branch: context.payload.pull_request.head.ref,
              });
            
              const activeRuns = workflowRuns.data.workflow_runs.filter((workflowRun) => {
                return workflowRun.status === 'queued' || workflowRun.status === 'in_progress';
              });
            
              for (const activeRun of activeRuns) {
                await github.rest.actions.cancelWorkflowRun({
                  owner: context.repo.owner,
                  repo: context.repo.repo,
                  run_id: activeRun.id,
                });
              }
            }
name: Cancel workflows on PR close
on:
  pull_request:
    types:
      - closed

This workflow will be triggered when a PR is closed, and it will cancel workflows associated with the head branch.

This works, but it has a gotcha – this workflow will be queued just like any other workflow, so there are no guarantees that it will execute immediately.

Therefore, what we ended up doing is setting up a webhook that informs us of action = closed and triggers the same logic as above from the webhook handler.

I also want to mention that if you are using if: always() in your workflow, it cannot be cancelled. Consider replacing it with if: success() || failure().

like image 191
Gajus Avatar answered Dec 02 '25 07:12

Gajus



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!