Repository navigation
PR preview counts commits merged to main after the PR branched as the PR's own #683
Description
Summary
In advisory standing-pr mode, the PR preview limits the version analysis to the PR's own commits by passing baseRef = pull_request.base.sha (packages/release/src/preview/preview.ts, prBaseSha). That SHA is where the PR last synced with its base, not the base tip. The workflow checks out GitHub's merge ref (refs/pull/N/merge), whose first parent is the base tip. So base.sha..HEAD also contains every commit merged into main since the PR branched, and the preview lists them as changes this PR adds.
A PR that has just merged main in looks right, which makes this easy to miss. The longer a PR goes without syncing, the more of other PRs' changes its preview shows.
Evidence: #672
-
pull_request.base.shais24774c3e(docs(roadmap): tick off shipped LLM-notes work and refresh the enablement note #665), the merge-base of the PR head andmain. ci: skip CodeQL, release preview and title checks on the standing release PR #672 has never mergedmainin. -
Merge ref
22b82a30has parents288a0db5(currentmain) and0eac66e7(PR head). -
The live preview comment on ci: skip CodeQL, release preview and title checks on the standing release PR #672 lists 12 changelog entries. The PR has 2 commits. The other 10 are test: enforce the shared coverage thresholds in every package's unit run #670, chore(biome): flag barrel files outside package entry points #669, chore(turbo): bump to 2.11.10 and opt out of agent guidance #671, docs(version): match the README flag table to the CLI #677, chore(deps): bump anthropics/claude-code-action from 1.0.240 to 1.0.252 #663, chore(biome): enforce block statements #679, chore(deps): update package versions and lockfile #681, chore(biome): make noExplicitAny an error outside specs and mocks #682, docs: add commands and gotchas to AGENTS.md, and drop CLAUDE.md #673 and chore: add .git-blame-ignore-revs for the block-statement sweep #680, all already on
mainand in the standing PR (chore: release v0.42.0 #614). -
Reproduced locally on the merge ref with
runRelease({ dryRun: true, skipNotes: true, …, baseRef }), which is the call the preview makes:baseRefChangelog entries 24774c3e(pull_request.base.sha, what the preview uses)12, the same as the live comment 288a0db5(HEAD^1, the base tip)2, the PR's own
#673 showed the same thing on a smaller scale: after #682 merged, its preview listed #682's commit, because #673 hadn't merged main since.
Impact
- The changelog section shows other PRs' changes.
- The "After merge — predicted release" table can show an escalation this PR doesn't cause. A
feator breaking commit that landed onmainafter the branch point is counted as this PR's. (ci: skip CodeQL, release preview and title checks on the standing release PR #672 didn't show one only because the standing PR is already at 0.42.0.) - Consumers get the same behaviour.
templates/workflows/release-preview.ymluses the default checkout, which is the merge ref.
Also affected: the post-release preview refresh (opt-in)
refreshFeederPreviews (ci.prPreview.refreshAfterRelease) calls runPreview for each open PR from the release job's checkout of main, passing pr.baseSha from the REST API. runPreview doesn't check out the PR. So the range is pr.baseSha..main: main's commits since the PR branched, and none of the PR's own. For #672 today that would be 10 commits, none of them #672's. I found this by reading the code. This repo doesn't enable the option, so I haven't seen it live.
Suggested fix
- Event path: scope to the base branch tip, not
pull_request.base.sha. On the merge ref that'sHEAD^1. More generally,git rev-parse origin/<pull_request.base.ref>works withfetch-depth: 0.<base tip>..HEADlists only the PR's commits whether the checkout is the merge ref or the PR head. - Refresh path: the analysis needs the PR's tree, for example a worktree of
refs/pull/N/mergescoped from its first parent. Otherwise the refresh shouldn't recompute the version analysis. - Test: a preview test where the base branch gains a
featcommit after the PR branches, asserting that only the PR's own commit appears and the predicted bump doesn't escalate.
Activity
goosewobbler commentedon Oct 24, 2026
Decision (maintainer): option B for the post-release refresh. The refresh stops recomputing previews from the release job's checkout. It marks each open feeder PR's preview as stale ("
mainhas moved; this preview updates on the PR's next push") instead. The fix for the event path is unchanged: count only commits after the base branch's tip.This supersedes #797: the refresh will no longer call
runPreview, so its early return can't skip feeder PRs. Carry #797's lesson over:refreshFeederPreviewsunder a standing-PRclosedevent payload, asserting that a feeder PR's preview is marked stale.