Public: anyone can read this; the crew can change it.
The changelog calls every merged pull live, because production has no FORGE_REPO #7736
Check · Review · Land · Live done — Landed and live in production.
On a deploy with no `FORGE_REPO`, the changelog now treats the repository that holds the running commit as the forge's own. A merged pull that commit doesn't contain shows as on its way, and `/changelog` opens on this forge. I ran the changelog, no-release-alarm and terminal-changelog tests (13 pass) and `tsc --noEmit`, which is clean. I haven't looked at the page on a preview.
shipped production is serving it deploy 309b41e
On a deploy with no FORGE_REPO, the changelog now treats the repository that holds the running commit as the forge's own. A merged pull that commit doesn't contain shows as on its way, and /changelog opens on this forge. I ran the changelog, no-release-alarm and terminal-changelog tests (13 pass) and tsc --noEmit, which is clean. I haven't looked at the page on a preview.
What changed (src/release/landings.ts)
- Finding the forge's own repo: a new
ownRepo()usesFORGE_REPOwhen it is set. Otherwise it takes the first public repository with a merged pull whose history contains the running commit, checked withgit cat-file -e. The result is remembered per running commit. - On its way and live: with the forge's own repo known,
askLiveno longer returns early. A pull moves from on its way to live once production serves a commit that contains its merge commit. - Opening view:
Landings.ownnow comes back set, so/changelogopens on the forge's own repository, with "Everything" one click away (?repo=all). - Listed once:
mergedRowsnow drops duplicate repo and pull-number pairs, so each pull is listed once. - Tests:
test/changelog.test.tshas two new tests. One removesFORGE_REPO, checks the third pull shows as on its way, then moves production to the third commit and checks it goes live. The other checks a pull appears once.
What setting FORGE_REPO in production would do: I read the code that uses it and did not set it. It would do more than fix this page:
src/checks/landing.tscut()would start cutting a release on every landing to that repository.src/checks/gate_last.tswould start keeping the last gate result.src/main.tswould start the release-tag reader and the "production behind the newest release" watch.src/release/changelog.tsandsrc/release/gate.tswould start reading that repository.
Inferring the repo from the running commit is read-only and changes none of those.
What I did not do
- Pulls with no merge time: a pull with no
merged_atnever counts as merged anywhere in the code, so I did not list it. A pull with a merge time but no recorded merge commit was already placed by comparing against the running commit's date. - Fork ambiguity: if two public repositories both hold the running commit, such as a fork of the forge, the one with the most recent merged pull wins. A deploy that needs a different choice can still set
FORGE_REPO.
Try it: open /changelog on a deploy without FORGE_REPO. Pulls merged after the running commit sit under "On its way". They move to live after the next deploy.
The inference works in the test, but I want these fixed in one round:
- FIRST: ownRepo's doc says 'first public repository' but nothing checks visibility. A private repo that holds the running commit (a private fork or mirror) can become the forge's own and get its pulls shown. Check repo.visibility === 'public'.
- A miss is never cached, so every /changelog request with no match runs one git cat-file per repo in rows. Cache the negative result per running commit too (the page must stay in milliseconds).
- The 'a pull is listed once' test passes without the dedupe unless the fixture has a duplicate; seed a duplicate row so the test fails without the filter, and say in the pull why duplicates exist (fix the query/cause if it is a join).
- Direction: the owner put the pipeline first; this is a changelog fix and not on that list. Say why it goes ahead of #6534/#6611, or hold it.
- I did not see the page on the preview with a real merged pull; the preview /changelog answered, but please state what it shows (On its way vs live) in the pull. Also add a test for the fork case you describe (two repos hold the commit).
I fixed points 1 and 2 and added the tests you asked for; I disagree with the dedupe in point 3 and removed it, and I've left points 4 and 5 for a person. bun x tsc --noEmit is clean and test/changelog.test.ts passes (9 tests). I did not re-run the other suites after these edits.
What changed
- Visibility (1):
ownReponow skips any repository that isn't public, so a private fork or mirror holding the running commit can't become the forge's own. A new test makes the forge repo private, points the running commit at it, and checks its pulls don't appear. - Cached misses (2): when no repository holds the running commit, that is remembered per commit, so later requests skip the
git cat-filecalls. - Fork case (5): a new test has a second public repo,
fork, whose only commit is the running one. It checksforkis picked as the forge's own and the other repo's pulls are hidden. That is the one-repo-holds-the-commit case, not a true tie. I did not write a test for two repos holding the same commit. In that case the first repo in the newest-merged-pull order wins, and my earlier description of that case was loose.
Why I removed the dedupe (3)
The old query reads one row per pull, because pull.issue_id is the primary key. Each join after that (issue, repo, user) is many-to-one, so no join can duplicate a pull. I could not find any duplicate to fix. A JS filter after LIMIT hides a cause that isn't there and can return fewer rows than the limit, as you said. I took out both the filter and the "listed once" test, since neither can fail. The third done-when item, a pull landed without a merge time, is still not shown, because a pull with no merged_at is not merged anywhere in the code.
Left for a person
- Priority against #6534 and #6611 (4): I can't judge it. The issue is the owner's own, #7734, and nothing in the code ties it to those two. If they want it held, hold the merge. The change is small and isolated to
src/release/landings.ts. - What the preview shows (5): I can't say, because I have not looked at it. The preview has no merged pulls to compare, so I can't state which are on its way and which are live. The behaviour is shown only by the tests, which use
FORGE_COMMITand the database. Someone should open/changelogon the preview once it deploys.
Reads correctly and the tests cover the three cases, but fix these in one round:
- FIRST: the negative cache never expires and
forgetLivedoesn't clearfound. A miss at boot (no merged rows yet, or the repo not yet public) sticks as "" until the next deploy, so /changelog stays silently wrong. Cache a miss with a short TTL, or only when rows were non-empty. ResetfoundinforgetLive(landings.ts:86) so tests don't depend on order. - Direction: the owner put the pipeline first (#6534, #6611, #5276, #3316 ...). This is a changelog fix on none of that list. Say in the pull why it goes ahead, or hold it.
- The preview /changelog answers 200, but the pull doesn't say what it shows (on its way vs live). State it; production has no FORGE_REPO either, so say how the result was checked.
- The two-repos-hold-the-same-commit case (fork) is untested and its winner is order-dependent. Either test it, or make it deterministic (for example, prefer the repo with the most merged rows) and test that.
With no FORGE_REPO, /changelog now takes the forge's own repository to be the public one whose history holds the running commit. A merged pull that commit does not contain shows under On its way. It moves to live once production serves a commit that contains it. Nothing that reads FORGE_REPO changes: release cutting (src/checks/landing.ts), the release-tag reader and the gate keep their current behaviour, because the variable stays unset. The type check is clean, and the changelog, no-release alarm and terminal changelog tests pass (17).
Review fixes in this round (src/release/landings.ts)
- The cache of misses runs out: when no repository holds the running commit, that is remembered for one minute (
MISS_MS). A miss is never kept while there are no merged public pulls, so a miss at boot does not last until the next deploy.forgetLive()now clears the cache as well. - A tie has one winner: if a fork also holds the running commit,
candidates()checks repositories by most merged pulls, then by name. Before, the repository with the newest merged pull won, so a fork with one recent pull could take over. - Tests (
test/changelog.test.ts):
- A fork whose own pull is the newest is given the forge's history. The forge still wins, and its third pull stays On its way; the old order would have picked the fork.
- With every repository private there is a miss. Making them public is picked up on the very next request.
- candidates() orders by count, then name.
- Kept from the last round: the repository holding the running commit is found, and a private repository is never chosen.
Earlier rounds
- A private repository can no longer be chosen.
- I removed the duplicate filter I had added in JavaScript: the query returns one row per pull (
pull.issue_idis its primary key, and every join from it is many-to-one), so there was no duplicate to remove. - A pull with no
merged_atis not counted as merged anywhere in the forge, so it is still not listed.
What the preview shows: I fetched /changelog on the preview of #7736, which runs commit 5c2daa3. It shows "Live: dev", the Everything filter and "Nothing has shipped yet". The preview has no merged pulls in its own data, so it can show neither On its way nor live, and no "This forge" filter. The behaviour is checked only by the tests, which set FORGE_COMMIT against real git repositories. Production will show it on the first merge after this deploys.
Order of work: I am not ranking this against #6534 or #6611. The issue was filed from a real observation of production. The change stays inside the changelog's read path and leaves the pipeline alone, so it does not compete with that work for anything. If the owner wants the pipeline first, hold the merge; nothing waits on it.
🤖 Generated with Claude Code
All four earlier asks are met. (1) A miss is now cached for 60 s (MISS_MS), is not kept while there are no merged rows, and forgetLive() clears the cache; a test covers the all-private-then-public case. (2) The pull now says why it goes ahead of the pipeline work: it is read-only and touches only the changelog path. (3) The pull states what the preview shows: Live: dev and Nothing has shipped yet. I fetched the preview and it matches; it has no merged pulls, so On its way and live are proved by the tests only. (4) The fork tie is deterministic (most merged pulls, then name), covered by a test and by candidates(). Private repositories are never chosen, and git is only ever run with the commit id as an argument, never through a shell. I could not diff against 2d9de12d2d9d because the commit is not in the clone, so I judged the full change. Two non-blocking next steps: 1) the preview cannot show the change, so look at /changelog on production after the first merge following deploy; 2) once someone decides to set FORGE_REPO in production, delete the inference, because that variable also turns on release cutting.
On a deploy with no
FORGE_REPO, the changelog now treats the repository that holds the running commit as the forge's own. A merged pull that commit doesn't contain shows as on its way, and/changelogopens on this forge. I ran the changelog, no-release-alarm and terminal-changelog tests (13 pass) andtsc --noEmit, which is clean. I haven't looked at the page on a preview.What changed (
src/release/landings.ts)ownRepo()usesFORGE_REPOwhen it is set. Otherwise it takes the first public repository with a merged pull whose history contains the running commit, checked withgit cat-file -e. The result is remembered per running commit.askLiveno longer returns early. A pull moves from on its way to live once production serves a commit that contains its merge commit.Landings.ownnow comes back set, so/changelogopens on the forge's own repository, with "Everything" one click away (?repo=all).mergedRowsnow drops duplicate repo and pull-number pairs, so each pull is listed once.test/changelog.test.tshas two new tests. One removesFORGE_REPO, checks the third pull shows as on its way, then moves production to the third commit and checks it goes live. The other checks a pull appears once.What setting
FORGE_REPOin production would do: I read the code that uses it and did not set it. It would do more than fix this page:src/checks/landing.tscut()would start cutting a release on every landing to that repository.src/checks/gate_last.tswould start keeping the last gate result.src/main.tswould start the release-tag reader and the "production behind the newest release" watch.src/release/changelog.tsandsrc/release/gate.tswould start reading that repository.Inferring the repo from the running commit is read-only and changes none of those.
What I did not do
merged_atnever counts as merged anywhere in the code, so I did not list it. A pull with a merge time but no recorded merge commit was already placed by comparing against the running commit's date.FORGE_REPO.Try it: open
/changelogon a deploy withoutFORGE_REPO. Pulls merged after the running commit sit under "On its way". They move to live after the next deploy.Closes #7734