fix(ci): skip CI when PR only changes .changeset/ files#2874
Conversation
PRs that only add/modify files in .changeset/ (changelog entries, config) don't need full CI (build, test, lint, E2E, Cypress). This extends the existing changeset-release/main branch detection to also check changed files via `gh pr diff --name-only`. Fail-safe: if the API call fails or returns empty, CI runs normally. Affects: ci.yml (ci + create-agents-e2e jobs), cypress.yml Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
|
TL;DR — Extends the changeset-detection step in CI and Cypress workflows to also skip pipeline runs when a PR's only changed files live under Key changes
Summary | 2 files | 1 commit | base: File-based changeset detection for all PRs
The new guard runs after the existing branch-name check. It fetches the PR diff via
|
There was a problem hiding this comment.
Low urgency. Logic is correct and fail-safe — API errors or unexpected event types fall through to running CI normally. The three-way duplication is a pre-existing pattern; this PR just extends it consistently. One minor concern flagged inline about CHANGED_FILES and empty-line edge cases with echo.
Claude Opus | 𝕏
| fi | ||
|
|
||
| if [ -n "$CHANGED_FILES" ]; then | ||
| NON_CHANGESET=$(echo "$CHANGED_FILES" | grep -v '^\.changeset/' || true) |
There was a problem hiding this comment.
Nit: echo "$CHANGED_FILES" will produce a trailing empty line if $CHANGED_FILES ends with a newline (it won't, since command substitution strips it — but if gh pr diff ever outputs a trailing blank line, $() strips it). More defensibly, you could use printf '%s' "$CHANGED_FILES" to avoid echo's implicit trailing newline, but in practice this is fine because grep -v on an empty line would produce that empty line in NON_CHANGESET, causing the skip to not trigger (a safe false-negative). No action needed — just calling it out.
| # Check if PR only contains .changeset/ file changes | ||
| if [ "$IS_CHANGESET" = "false" ] && [ "$GITHUB_EVENT_NAME" != "push" ]; then | ||
| if [ "$GITHUB_EVENT_NAME" = "pull_request" ] && [ -n "$PR_NUMBER" ]; then | ||
| CHANGED_FILES=$(gh pr diff "$PR_NUMBER" --name-only --repo "$GITHUB_REPOSITORY" 2>/dev/null || echo "") | ||
| elif [ "$GITHUB_EVENT_NAME" = "merge_group" ] && [ -n "$PR_NUM" ]; then | ||
| CHANGED_FILES=$(gh pr diff "$PR_NUM" --name-only --repo "$GITHUB_REPOSITORY" 2>/dev/null || echo "") | ||
| fi | ||
|
|
||
| if [ -n "$CHANGED_FILES" ]; then | ||
| NON_CHANGESET=$(echo "$CHANGED_FILES" | grep -v '^\.changeset/' || true) | ||
| if [ -z "$NON_CHANGESET" ]; then | ||
| IS_CHANGESET=true | ||
| echo "Only .changeset/ files changed — skipping CI checks" | ||
| fi | ||
| fi | ||
| fi |
There was a problem hiding this comment.
This 16-line block is now copy-pasted in three jobs across two files. Consider extracting it into a composite action or a reusable workflow step that all three jobs call. That would eliminate the maintenance risk of the blocks drifting out of sync over time. Not blocking for this PR, but worth considering as a follow-up.
There was a problem hiding this comment.
Approving. Logic is sound and fail-safe.
Claude Opus | 𝕏
There was a problem hiding this comment.
PR Review Summary
(0) Total Issues | Risk: Low
🟢 No Blocking Issues
The implementation is correct and well-designed:
✅ Correct fail-safe behavior — If the gh pr diff API call fails, CI runs normally (safe default)
✅ Proper shell scripting — Variables are quoted correctly, || true handles grep non-matches, error output is redirected appropriately
✅ Complete event coverage — Handles pull_request, merge_group, and correctly skips the check for push events
✅ Backward compatible — Existing changeset-release/main bot detection is preserved
💭 Consider (1) 💭
Inline Comments:
- 💭 Consider:
.github/workflows/ci.yml:61-76— Extract duplicated changeset detection logic to composite action
📝 Notes
Fork PRs: The github.token has limited permissions for PRs from forks, so changeset-only PRs from forks will still run full CI. This is acceptable fail-safe behavior and doesn't need to be "fixed" — just documenting for awareness.
✅ APPROVE
Summary: Clean implementation with proper fail-safe behavior. The test plan covers the key scenarios. The duplication suggestion is a nice-to-have for future maintainability but doesn't block this PR.
Reviewers (2)
| Reviewer | Returned | Main Findings | Consider | While You're Here | Inline Comments | Pending Recs | Discarded |
|---|---|---|---|---|---|---|---|
pr-review-devops |
4 | 0 | 0 | 0 | 1 | 0 | 3 |
pr-review-standards |
0 | 0 | 0 | 0 | 0 | 0 | 0 |
| Total | 4 | 0 | 0 | 0 | 1 | 0 | 3 |
Discarded (3)
| Location | Issue | Reason Discarded |
|---|---|---|
.github/workflows/ci.yml:62 |
Condition structure regarding PR_NUMBER availability is subtle | Logic is correct as confirmed by both reviewers; clarity is subjective |
.github/workflows/ci.yml:64 |
Fork PRs will run full CI due to token limitations | Acceptable fail-safe behavior, documented in notes above |
.github/workflows/ci.yml:87 |
PR_NUMBER variable correctly added | Positive observation, not an issue |
| # Check if PR only contains .changeset/ file changes | ||
| if [ "$IS_CHANGESET" = "false" ] && [ "$GITHUB_EVENT_NAME" != "push" ]; then | ||
| if [ "$GITHUB_EVENT_NAME" = "pull_request" ] && [ -n "$PR_NUMBER" ]; then | ||
| CHANGED_FILES=$(gh pr diff "$PR_NUMBER" --name-only --repo "$GITHUB_REPOSITORY" 2>/dev/null || echo "") | ||
| elif [ "$GITHUB_EVENT_NAME" = "merge_group" ] && [ -n "$PR_NUM" ]; then | ||
| CHANGED_FILES=$(gh pr diff "$PR_NUM" --name-only --repo "$GITHUB_REPOSITORY" 2>/dev/null || echo "") | ||
| fi | ||
|
|
||
| if [ -n "$CHANGED_FILES" ]; then | ||
| NON_CHANGESET=$(echo "$CHANGED_FILES" | grep -v '^\.changeset/' || true) | ||
| if [ -z "$NON_CHANGESET" ]; then | ||
| IS_CHANGESET=true | ||
| echo "Only .changeset/ files changed — skipping CI checks" | ||
| fi | ||
| fi | ||
| fi |
There was a problem hiding this comment.
💭 Consider: Extract changeset detection to composite action
Issue: This 16-line block is duplicated 3 times across ci.yml (2x) and cypress.yml (1x).
Why: DRY violation makes future changes error-prone — any fix or enhancement must be applied in 3 places. The repo already uses composite actions in .github/composite-actions/ for reusable workflow logic.
Fix: Consider extracting to a composite action (e.g., .github/composite-actions/changeset-check/action.yml) that outputs is_changeset. This is non-blocking since the duplication follows existing patterns in the workflow file, but would improve maintainability for future changes.
Refs:
Summary
ci.ymlandcypress.ymlto also skip CI when a PR's only changes are files in.changeset/(changelog entries, config)changeset-release/mainbot PR was detected — now any PR with changeset-only changes skips the expensive CI pipeline (32GB runners, databases, Playwright, Cypress)gh pr diff --name-onlyto check changed files; fail-safe — if the API call fails, CI runs normallyTest plan
.changeset/*.mdfiles → CI skipped.changeset/*.md+ code changes → CI runschangeset-release/mainbot PR → CI skipped (existing behavior preserved)🤖 Generated with Claude Code