chore(ci): skip expensive jobs on non-source changes#565
chore(ci): skip expensive jobs on non-source changes#565
Conversation
Add dorny/paths-filter gate so lint, build-check, and both test jobs only run when source-affecting files change (src/, test/, package.json, tsconfigs, Dockerfiles, etc.). Metadata checks (commit-lint, changeset-check) remain unconditional. Also restrict commit-lint to PRs/workflow_dispatch to avoid false positives on squash-merge commits pushed to main, fix post-tests Coveralls parallel-finished to not fire on skipped test runs, and bump actions/checkout + actions/setup-node from v3 to v4.
🦋 Changeset detectedLatest commit: c65405e The changes in this PR will be included in the next version bump. This PR includes changesets to release 0 packagesWhen changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
There was a problem hiding this comment.
Pull request overview
Updates CI to avoid running expensive lint/build/test jobs when a PR only changes non-source files, while keeping required checks satisfied and reducing Coveralls noise.
Changes:
- Add a
changesjob (paths filter) and gatelint,build-check, and test jobs onneeds.changes.outputs.src. - Restrict
commit-linttopull_requestandworkflow_dispatch; guard Coveralls “parallel-finished”. - Bump
actions/checkout/actions/setup-nodetov4and add@changesets/changelog-githubto devDependencies.
Reviewed changes
Copilot reviewed 3 out of 4 changed files in this pull request and generated 5 comments.
| File | Description |
|---|---|
.github/workflows/checks.yml |
Adds changed-path detection and conditions to skip expensive jobs; updates action versions; adjusts Coveralls signaling. |
package.json |
Adds @changesets/changelog-github devDependency; normalizes author string. |
package-lock.json |
Locks dependencies added by @changesets/changelog-github. |
.changeset/proud-pants-cry.md |
Adds a changeset entry for the PR. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| needs.lint.result != 'failure' && | ||
| needs.build-check.result != 'failure' |
There was a problem hiding this comment.
The unit test job condition allows execution when lint/build-check are cancelled (because it only blocks failure). If the intent is to only run tests after those jobs succeed, change the condition to require needs.lint.result == 'success' and needs.build-check.result == 'success'.
| needs.lint.result != 'failure' && | |
| needs.build-check.result != 'failure' | |
| needs.lint.result == 'success' && | |
| needs.build-check.result == 'success' |
| if: | | ||
| always() && | ||
| needs.changes.outputs.src == 'true' && | ||
| needs.lint.result != 'failure' && | ||
| needs.build-check.result != 'failure' |
There was a problem hiding this comment.
Same as the unit test job: the integration test job condition only blocks on failure, so tests may still run if lint/build-check were cancelled. If dependencies must pass, require needs.lint.result == 'success' and needs.build-check.result == 'success' instead.
| - name: Coveralls Finished | ||
| uses: coverallsapp/github-action@master | ||
| if: | | ||
| needs.test-units-and-cover.result != 'skipped' || | ||
| needs.test-integrations-and-cover.result != 'skipped' | ||
| with: | ||
| github-token: ${{ secrets.GITHUB_TOKEN }} | ||
| parallel-finished: true |
There was a problem hiding this comment.
coverallsapp/github-action@master is a floating ref, which is risky for supply-chain security and can introduce unexpected CI changes. Pin this to a stable release tag or (preferably) a commit SHA.
| permissions: | ||
| pull-requests: read | ||
| outputs: | ||
| src: ${{ steps.filter.outputs.src }} | ||
| steps: | ||
| - uses: actions/checkout@v4 |
There was a problem hiding this comment.
The changes job sets a job-level permissions block with only pull-requests: read. When job permissions are set, any unspecified scopes default to none, which can break actions/checkout (it needs contents: read). Add contents: read (and keep pull-requests: read if you want API-based PR file listing).
| outputs: | ||
| src: ${{ steps.filter.outputs.src }} | ||
| steps: | ||
| - uses: actions/checkout@v4 |
There was a problem hiding this comment.
dorny/paths-filter relies on git history for non-PR events (e.g., push), but actions/checkout here uses the default shallow clone. Configure actions/checkout with an appropriate fetch-depth (commonly 0 or at least 2) so the action can diff github.event.before..after reliably.
| - uses: actions/checkout@v4 | |
| - uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 |
Summary
changesjob usingdorny/paths-filter@v3to detect whether source-affecting files changed (src/,test/,package.json,tsconfig*.json,biome.json,.knip.json, Dockerfiles,.nvmrc, and the workflow file itself)lint,build-check, and both test jobs behindneeds.changes.outputs.src == 'true'so they skip on docs/config-only PRscommit-lintfalse positives on squash-merges by restricting it topull_requestandworkflow_dispatchonlypost-testsCoverallsparallel-finishedsignal to only fire when at least one test job ran (prevents spurious 0% coverage reports)actions/checkoutandactions/setup-nodefrom@v3→@v4Why job-level filter instead of trigger-level
paths:GitHub only satisfies required status checks when a job actually runs. A trigger-level
paths:filter skips the entire workflow, leaving required checks unsatisfied and blocking PRs. The job-level approach keeps the workflow running but skips expensive jobs internally.Test plan
.mdfile →lint,build-check,test-units-and-cover,test-integrations-and-covershow as Skipped (green) in Checkssrc/→ all jobs run normallymain→commit-lintis skipped,changesets.ymlruns as beforeworkflow_dispatch→ all jobs run (path-filter returnstruewith no diff)🤖 Generated with Claude Code