Problem It Solves
The Detect changesets step in publish.yml uses:
git diff --name-only HEAD~1 HEAD \
| grep -E '^.changeset/.*.md$' \
| grep -v 'README.md$' \
| wc -l
This is fragile for several cases:
- Multiple commits in a single PR merge: with
squash merge, HEAD~1 is the previous main commit, but HEAD is the squash-commit. The diff correctly shows the squash-commit files. But with rebase merge or merge commit, HEAD~1 is one of the merge commits, not the overall diff against main.
- CHANGELOG.md updates: a Changesets bump modifies
CHANGELOG.md, which is under packages/fp/, not .changeset/. The current detection ignores this and correctly doesn't double-count — but it also relies on pnpm changeset version having not yet run.
- Changeset
.md files in nested packages: with monorepos and pnpm, a changeset can be at .changeset/*.md at the root OR in a per-package directory depending on config. The grep anchors the root only.
Proposed Solution
Replace the Detect changesets step with a Changesets-native call. Use pnpm changeset status (or equivalent CLI flag depending on Changesets v3 vs v2) to query the Changesets state machine directly. This is the same tool that the release.yml job eventually calls to perform pnpm changeset version, so we know the result is consistent.
Implementation sketch:
- name: Detect changesets
id: detect
run: |
# Tag pushes and manual workflow_dispatch always proceed.
if [ "\${{ github.event_name }}" = "push" ] && \
[ "\${{ github.ref_type }}" = "tag" ]; then
echo "has_changesets=true" >> "$GITHUB_OUTPUT"
echo "Tag push detected — proceeding."
exit 0
fi
if [ "\${{ github.event_name }}" = "workflow_dispatch" ]; then
echo "has_changesets=true" >> "$GITHUB_OUTPUT"
echo "Manual dispatch — proceeding."
exit 0
fi
# PR merge: query Changesets directly.
if pnpm changeset status --since=origin/staging --output=json 2>/dev/null | grep -q '"published": false'; then
echo "has_changesets=true" >> "$GITHUB_OUTPUT"
else
echo "has_changesets=false" >> "$GITHUB_OUTPUT"
fi
Current state
The Detect changesets step in publish.yml uses git diff --name-only HEAD~1 HEAD. Worked on the e2e test of @deessejs/fp@1.1.0 because the merge was a single-commit squash merge. Will break or under-detect on multi-commit merges.
Acceptance criteria
Alternatives Considered
git diff --first-parent HEAD~1 HEAD: keeps the git-based approach but restricts the diff to the first parent of merge commits. Slightly more robust for merge commit strategy but still bypasses Changesets' own state model.
- Continue with current
git diff HEAD~1 HEAD: accept the fragility on multi-commit merges. Not recommended.
Related
- Plan:
docs/engineering/plans/release-pipeline.md §6.2.
🤖 Generated with Claude Code
Problem It Solves
The
Detect changesetsstep inpublish.ymluses:This is fragile for several cases:
squash merge,HEAD~1is the previous main commit, butHEADis the squash-commit. The diff correctly shows the squash-commit files. But withrebase mergeormerge commit,HEAD~1is one of the merge commits, not the overall diff against main.CHANGELOG.md, which is underpackages/fp/, not.changeset/. The current detection ignores this and correctly doesn't double-count — but it also relies onpnpm changeset versionhaving not yet run..mdfiles in nested packages: with monorepos andpnpm, a changeset can be at.changeset/*.mdat the root OR in a per-package directory depending on config. The grep anchors the root only.Proposed Solution
Replace the
Detect changesetsstep with a Changesets-native call. Usepnpm changeset status(or equivalent CLI flag depending on Changesets v3 vs v2) to query the Changesets state machine directly. This is the same tool that therelease.ymljob eventually calls to performpnpm changeset version, so we know the result is consistent.Implementation sketch:
Current state
The
Detect changesetsstep inpublish.ymlusesgit diff --name-only HEAD~1 HEAD. Worked on the e2e test of@deessejs/fp@1.1.0because the merge was a single-commit squash merge. Will break or under-detect on multi-commit merges.Acceptance criteria
git diff HEAD~1 HEADon a single-commit squash merge (no regression)..changeset/*.mdadditions.Detect changesetsstep logs which signal it used.workflow_dispatchand tag push paths are unchanged.Alternatives Considered
git diff --first-parent HEAD~1 HEAD: keeps the git-based approach but restricts the diff to the first parent of merge commits. Slightly more robust formerge commitstrategy but still bypasses Changesets' own state model.git diff HEAD~1 HEAD: accept the fragility on multi-commit merges. Not recommended.Related
docs/engineering/plans/release-pipeline.md§6.2.🤖 Generated with Claude Code