Filter workflows by path in GitHub Actions
Add `paths` or `paths-ignore` to expensive workflows so a docs-only or unrelated change doesn't trigger the full test suite.
Do this
Expensive workflows (E2E, full integration suites) declare a paths filter listing the source directories that can actually affect them, or a paths-ignore list for docs and markdown. A README change no longer spins up the entire suite.12
on:
pull_request:
paths:
- "src/**"
- "package.json"
- "pnpm-lock.yaml"
- ".github/workflows/e2e.yml" # re-run if the workflow itself changesAvoid this
A docs-only change spins up the full suite, spending wall-clock and runner minutes for nothing.
on:
pull_request: # a one-word README fix triggers the full E2E suiteWhy it matters
Running an expensive suite on changes that can't affect it is pure waste, both wall-clock the developer waits on and runner-minutes you pay for. Path filters are a high-impact, low-risk trigger fix. The one thing to watch: if a *required* status check is path-filtered, a skipped run never reports its status, and GitHub has no branch-protection setting that treats a missing check as passed, so the PR waits forever. Either don't make the path-filtered workflow a required check, or gate the work with a job-level if: condition instead of a workflow-level paths filter: GitHub reports a job skipped by a conditional as Success, which satisfies the required check, whereas a skipped workflow reports nothing at all.
When to use
Use it when
Workflows with several jobs and a clear set of source paths that gate them, especially E2E and integration suites.
Be careful when
Be careful path-filtering a *required* status check: a filtered-out workflow never reports, and GitHub can't treat a missing check as satisfied, so the PR stays blocked. Prefer path-filtering non-required expensive workflows. If the check must stay required, gate the work with a job-level if: condition instead: a job skipped by a conditional reports Success and satisfies the check, unlike a workflow skipped by paths.
Verify on your repo
Hand this prompt to your coding agent (Claude Code, Cursor, and the like) to audit and fix this practice in your own repo.
Inspect this repo's .github/workflows for expensive workflows (E2E, integration suites) that trigger on every change with no path scoping. For each, look at the `on:` block for `paths:` or `paths-ignore:` and flag multi-job workflows that have neither. Add a `paths` allowlist of the source directories that can actually affect the workflow (include the workflow file itself) so a docs-only change does not spin up the full suite. Important: do not path-filter a *required* status check, since a skipped workflow never reports and blocks the PR forever, so instead gate the expensive work with a job-level `if:` condition (a job skipped by a conditional reports Success). Show me the diff and open a PR rather than applying it blindly.Prefer to check by hand?
Look at the
on:block of each expensive workflow forpaths:orpaths-ignore:.Flag workflows with several jobs and no path filtering at all.
For any *required* check, don't path-filter the whole workflow: either drop it from the required list, or gate the expensive work with a job-level
if:(a job skipped by a conditional reportsSuccess), so PRs aren't blocked waiting on a check that never runs.
More best practices for GitHub Actions
Where to go next in the CI best-practices catalog.
- Trigger Scope
Cancel superseded runs with concurrency groups
Add a GitHub Actions
concurrencygroup scoped to the ref withcancel-in-progress: true, so a new push cancels the now-obsolete run instead of leaving both to occupy runners. - Parallelization
Build and test only what changed in GitHub Actions
Scope your slowest build/test job to only the packages a PR actually changed, using your monorepo tool's affected mode, with a mandatory full-run fallback so a resolution error never silently skips work.
FAQ
Should I use paths or paths-ignore?
paths is an allowlist (run only when these change) and is safest for a suite with a well-defined source set. paths-ignore is a denylist (skip when only these change) and fits when you mainly want to exclude docs and markdown. Don't set both on the same event.
Will a path filter break a required status check?
It can. When a workflow is skipped by a paths filter, its check context never reports, and branch protection waits for it forever, GitHub has no setting that counts a missing check as passed. The safe fix: don't require a path-filtered workflow, or gate the expensive job with a job-level if: condition instead. GitHub reports a job skipped by a conditional as Success (which satisfies the required check), whereas a skipped workflow reports nothing.
Sources
1GitHub Actions · paths / paths-ignore filters (opens in new tab)
2GitHub · troubleshooting required status checks (opens in new tab)
Last updated 2026-07-06
Don't run the full suite on a docs change.
One line to install. Faster runs on day one, and agents that open reviewable PRs to keep your pipeline following practices like this one.