@@ -11,6 +11,57 @@ concurrency:
1111 cancel-in-progress : true
1212
1313jobs :
14+ # A PR that changes npm-visible files must carry a changeset — without one
15+ # the Release workflow versions nothing and silently ships no release
16+ # (AGENTS.md "Releases"). Docs-site-only and CI-only PRs pass with no
17+ # changeset. An intentional no-release change opts out with
18+ # `npx changeset --empty`. Push builds on main skip the job: there is no
19+ # PR diff to police there, and the changesets already merged.
20+ changeset-guard :
21+ name : Changeset guard
22+ if : github.event_name == 'pull_request'
23+ runs-on : ubuntu-latest
24+ steps :
25+ - uses : actions/checkout@v4
26+ with :
27+ # Full history, so the merge base with the PR's target branch
28+ # exists for the three-dot diff and `changeset status --since`.
29+ fetch-depth : 0
30+
31+ - uses : actions/setup-node@v4
32+ with :
33+ node-version : ' 22'
34+ cache : npm
35+
36+ - name : Require a changeset for npm-visible changes
37+ env :
38+ BASE_REF : ${{ github.base_ref }}
39+ # The path filter runs before `npm ci`, so docs/CI-only PRs pass in
40+ # seconds without an install. `changeset status --since` then also
41+ # parse-validates the changeset files (bad frontmatter or a wrong
42+ # package name fails here instead of in the Release run on main).
43+ run : |
44+ base="origin/$BASE_REF"
45+ changed=$(git diff --name-only "$base...HEAD")
46+ echo "Changed files vs $base:"
47+ echo "$changed"
48+ npm_visible=$(echo "$changed" | grep -E '^(src/|package\.json$|package-lock\.json$|tsup\.config\.ts$|tsconfig\.json$)' || true)
49+ if [ -z "$npm_visible" ]; then
50+ echo "No npm-visible changes; no changeset required."
51+ exit 0
52+ fi
53+ echo "npm-visible changes:"
54+ echo "$npm_visible"
55+ added_changesets=$(echo "$changed" | grep -E '^\.changeset/.+\.md$' | grep -vE 'README\.md$' || true)
56+ if [ -z "$added_changesets" ]; then
57+ echo "::error::This PR changes npm-visible files but contains no changeset. Run 'npx changeset' (or 'npx changeset --empty' for an intentional no-release change) and commit the generated file."
58+ exit 1
59+ fi
60+ echo "Changeset(s) in this PR:"
61+ echo "$added_changesets"
62+ npm ci
63+ npx changeset status --since="$base"
64+
1465 test :
1566 name : Test (Node ${{ matrix.node }})
1667 runs-on : ubuntu-latest
0 commit comments