From 0e9547cf9c3e0765e5e98dab1f422bd157a50dfc Mon Sep 17 00:00:00 2001 From: david morales <118213696+davidmoralesz@users.noreply.github.com> Date: Fri, 9 Oct 2026 14:08:59 -0600 Subject: [PATCH] fix(workflows): skip runs that cannot change a result Cancel a pull request run when a newer push supersedes it, and skip the PR checks for Dependabot and for edits that touch neither the title nor the base. Both live in the reusable workflows, so every consumer at @v1 inherits them. --- .github/workflows/ci-gitleaks.yml | 7 +++++++ .github/workflows/ci-go.yml | 7 +++++++ .github/workflows/ci-java-gradle.yml | 7 +++++++ .github/workflows/ci-lint.yml | 7 +++++++ .github/workflows/ci-pr.yml | 16 ++++++++++++++++ .github/workflows/ci-pre-commit.yml | 7 +++++++ .github/workflows/ci-workflows.yml | 11 +++++++++++ 7 files changed, 62 insertions(+) diff --git a/.github/workflows/ci-gitleaks.yml b/.github/workflows/ci-gitleaks.yml index d8bc09a..f95ebfa 100644 --- a/.github/workflows/ci-gitleaks.yml +++ b/.github/workflows/ci-gitleaks.yml @@ -37,6 +37,13 @@ jobs: timeout-minutes: 15 permissions: contents: read + # Pushing again to a pull request supersedes the run in flight, so it is cancelled rather + # than billed to the end. Only pull requests cancel: a push to the default branch, a + # merge group and a schedule always finish. `github.workflow` is the caller's name, and + # the library suffix keeps this group distinct from any the caller declares itself. + concurrency: + group: ci-gitleaks-${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: ${{ github.event_name == 'pull_request' }} env: GITLEAKS_VERSION: ${{ inputs.gitleaks-version }} CONFIG_FILE: ${{ inputs.config-file }} diff --git a/.github/workflows/ci-go.yml b/.github/workflows/ci-go.yml index 1fb030a..4c60286 100644 --- a/.github/workflows/ci-go.yml +++ b/.github/workflows/ci-go.yml @@ -79,6 +79,13 @@ jobs: timeout-minutes: ${{ inputs.timeout-minutes }} permissions: contents: read + # Pushing again to a pull request supersedes the run in flight, so it is cancelled rather + # than billed to the end. Only pull requests cancel: a push to the default branch, a + # merge group and a schedule always finish. `github.workflow` is the caller's name, and + # the library suffix keeps this group distinct from any the caller declares itself. + concurrency: + group: ci-go-${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: ${{ github.event_name == 'pull_request' }} defaults: run: working-directory: ${{ inputs.working-directory }} diff --git a/.github/workflows/ci-java-gradle.yml b/.github/workflows/ci-java-gradle.yml index 218975d..0cfab34 100644 --- a/.github/workflows/ci-java-gradle.yml +++ b/.github/workflows/ci-java-gradle.yml @@ -75,6 +75,13 @@ jobs: timeout-minutes: ${{ inputs.timeout-minutes }} permissions: contents: read + # Pushing again to a pull request supersedes the run in flight, so it is cancelled rather + # than billed to the end. Only pull requests cancel: a push to the default branch, a + # merge group and a schedule always finish. `github.workflow` is the caller's name, and + # the library suffix keeps this group distinct from any the caller declares itself. + concurrency: + group: ci-java-gradle-${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: ${{ github.event_name == 'pull_request' }} steps: - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: diff --git a/.github/workflows/ci-lint.yml b/.github/workflows/ci-lint.yml index 2aa84c1..92c1643 100644 --- a/.github/workflows/ci-lint.yml +++ b/.github/workflows/ci-lint.yml @@ -57,6 +57,13 @@ jobs: timeout-minutes: ${{ inputs.timeout-minutes }} permissions: contents: read + # Pushing again to a pull request supersedes the run in flight, so it is cancelled rather + # than billed to the end. Only pull requests cancel: a push to the default branch, a + # merge group and a schedule always finish. `github.workflow` is the caller's name, and + # the library suffix keeps this group distinct from any the caller declares itself. + concurrency: + group: ci-lint-${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: ${{ github.event_name == 'pull_request' }} steps: - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: diff --git a/.github/workflows/ci-pr.yml b/.github/workflows/ci-pr.yml index 9896718..ec205cb 100644 --- a/.github/workflows/ci-pr.yml +++ b/.github/workflows/ci-pr.yml @@ -37,9 +37,25 @@ permissions: {} jobs: pr-checks: name: Title, branch, size, commits + # Skipped here rather than in the caller so the check still reports, as skipped, under + # the name a ruleset requires. Dependabot's pull requests are never linted, so they do + # not need a runner at all. `edited` also fires when only the body or base changes -- + # release-please and Dependabot rewrite theirs on every push -- and nothing checked + # reads the body, so it re-runs only when the title or the base branch changed. + if: >- + ${{ github.actor != 'dependabot[bot]' + && (github.event.action != 'edited' + || github.event.changes.title || github.event.changes.base) }} runs-on: ubuntu-latest permissions: contents: read + # Pushing again to a pull request supersedes the run in flight, so it is cancelled rather + # than billed to the end. Only pull requests cancel: a push to the default branch, a + # merge group and a schedule always finish. `github.workflow` is the caller's name, and + # the library suffix keeps this group distinct from any the caller declares itself. + concurrency: + group: ci-pr-${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: ${{ github.event_name == 'pull_request' }} steps: - name: Check out the pull request uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 diff --git a/.github/workflows/ci-pre-commit.yml b/.github/workflows/ci-pre-commit.yml index 92dba51..1f4f735 100644 --- a/.github/workflows/ci-pre-commit.yml +++ b/.github/workflows/ci-pre-commit.yml @@ -77,6 +77,13 @@ jobs: timeout-minutes: ${{ inputs.timeout-minutes }} permissions: contents: read + # Pushing again to a pull request supersedes the run in flight, so it is cancelled rather + # than billed to the end. Only pull requests cancel: a push to the default branch, a + # merge group and a schedule always finish. `github.workflow` is the caller's name, and + # the library suffix keeps this group distinct from any the caller declares itself. + concurrency: + group: ci-pre-commit-${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: ${{ github.event_name == 'pull_request' }} env: UV_VERSION: ${{ inputs.uv-version }} UV_PROJECT: ${{ inputs.uv-project }} diff --git a/.github/workflows/ci-workflows.yml b/.github/workflows/ci-workflows.yml index 7b2c2c6..f349223 100644 --- a/.github/workflows/ci-workflows.yml +++ b/.github/workflows/ci-workflows.yml @@ -44,6 +44,13 @@ jobs: timeout-minutes: 15 permissions: contents: read + # Pushing again to a pull request supersedes the run in flight, so it is cancelled rather + # than billed to the end. Only pull requests cancel: a push to the default branch, a + # merge group and a schedule always finish. `github.workflow` is the caller's name, and + # the library suffix keeps this group distinct from any the caller declares itself. + concurrency: + group: ci-workflows-actionlint-${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: ${{ github.event_name == 'pull_request' }} env: ACTIONLINT_VERSION: ${{ inputs.actionlint-version }} steps: @@ -73,6 +80,10 @@ jobs: timeout-minutes: 15 permissions: contents: read + # See the actionlint job: a superseded pull request run is cancelled, nothing else is. + concurrency: + group: ci-workflows-zizmor-${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: ${{ github.event_name == 'pull_request' }} env: ZIZMOR_VERSION: ${{ inputs.zizmor-version }} ZIZMOR_PERSONA: ${{ inputs.zizmor-persona }}