How to Skip Duplicate CI Runs
A concurrency group with cancel-in-progress kills the previous run when a newer commit lands, and content-based dedup avoids running the same tree twice.
Two kinds of duplicate work: outdated runs on a branch (solved by concurrency + cancel-in-progress), and the same content built twice across push and PR (solved by a dedup action or careful triggers).
Steps
- Add a top-level
concurrencygroup keyed on workflow and ref. - Set
cancel-in-progress: trueto drop superseded runs. - For content dedup, gate with fkirc/skip-duplicate-actions.
Workflow
.github/workflows/ci.yml
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
pre:
runs-on: ubuntu-latest
outputs:
should_skip: ${{ steps.skip.outputs.should_skip }}
steps:
- id: skip
uses: fkirc/skip-duplicate-actions@v5
build:
needs: pre
if: needs.pre.outputs.should_skip != 'true'
runs-on: ubuntu-latest
steps: [{ run: npm ci && npm test }]Gotchas
- Use
cancel-in-progress: falsefor deploy workflows so a release is never interrupted midway. - Cancelling a run marks it cancelled, not success; a required check may need the newer run to complete before merge.
Related guides
How to Combine a Merge Queue With Incremental CIRun incremental CI safely inside a GitHub merge queue by testing each merge_group against its base, so affect…
How to Trigger CI Only on Changed Paths With paths FiltersLimit when a GitHub Actions workflow even starts using on.push.paths and paths-ignore, so unrelated commits n…
How to Measure Cost Savings From Incremental CIQuantify the minutes and money incremental CI saves by comparing skipped jobs against a full run, so you can…