Skip to content

fix(release-beat): read every tags page, and pin the checkout in a test (#1220) - #1231

Merged
Birfy merged 1 commit into
ThinkFlowLab:mainfrom
HugoXK:dev2/fix/1220-release-beat-tag-page
Oct 26, 2026
Merged

Birfy merged 1 commit into
ThinkFlowLab:mainfrom
HugoXK:dev2/fix/1220-release-beat-tag-page

Conversation

@HugoXK

@HugoXK HugoXK commented Oct 26, 2026 •

Copy link
Copy Markdown
Contributor

Owner: Dev2
Reviewer: Reviewer

fix(release-beat): read every tags page, and pin the checkout in a test (#1220)

Written-by: Dev-2

Fixes #1220

Tip SHA: a0560bb

What changed

.github/scripts/release-beat.mjs and its own test file — nothing else.

  1. newestTag reads every page. repos/{repo}/tags?per_page=100 was read once. The listing is 100 names to a page in string order, and string order is not version order (v0.2.100 sorts below v0.2.99), so past 100 tags the newest version can sit on page two: the run reads yesterday's tag and files a false Release beat missing: … every day. It now pages to the end, stopping on the first short page; a page that repeats the previous one stops the walk too, so a server that ignores page cannot spin. latestOf's rule is untouched — plain vX.Y.Z only, pre-releases skipped, highest version rather than newest push (A release beat can be missed whole and nobody is told: the 02:00 routine has no catch-up and no alert #1209/Add a release beat watchdog that files one issue a day when the newest v* tag is not today's #1214).
  2. The checkout pin is now watched. .github/workflows/release-beat.yml holds issues: write, so actions/checkout must stay on a full commit. One text assertion (uses: actions/checkout@[0-9a-f]{40}), the audit-merges.test.mjs:260 shape.

Trade-off (pagination vs /releases/latest): pagination, because it answers the question the metric already asks — the highest plain vX.Y.Z tag. /releases/latest answers GitHub's "latest release" flag, which can disagree (a release marked latest, or a tag with no release) and would quietly move the pre-release boundary #1209/#1214 pinned. Cost: one more API call per 100 tags, once a day.

Red then green

Red first, against the old newestTag, with the fixture that is the real shape (page one = v0.2.1 … v0.2.100, page two = v0.2.101 dated today):

not ok 9 - a newest tag past page one is still read: >100 tags must not raise a false miss (#1220)
  error: |-
    the newest tag is dated today, on page two
    'alert' !== 'ok'

After the fix: # tests 22 / # pass 22 / # fail 0.

Knife for the pin — revert uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 to @v4:

not ok 20 - the checkout action stays pinned to a full commit (#1220)
  error: 'actions stay pinned to a commit'

restored, green again.

Verification at the tip

Tip SHA: a0560bb
Ran: TZ=UTC npm run verify on the pushed tree (ef7dc5a, same tree as a0560bb11bc197c7c317059ab7edcf262cf33460) → exit 0: core 1597/1597, social 525/525, tree 125/125, timeline 125/125, .github/scripts 495/495, interop 37/37, live-e2e 24/24; arch-docs: OK (2 changed file(s)); node scripts/ds-bot-patches.mjs check ok.

  • node --test scripts/release-beat.test.mjs → 22/22.
    Not run (and why): the smoke test — no product surface moves, only the release watchdog's own script and its test.

No new dependency, no core/ change, risk:T* left to the controller.

Checkpoint

{
  "pr": 1231,
  "claim": "Dev2",
  "issue": 1220,
  "summary": "The release-beat watchdog read only the first page of the tags listing, so past 100 tags the newest version could sit on page two and the run would file a false missing-release alert every day. newestTag now pages to the end, stopping on a short or repeated page, and leaves the pinned semver and pre-release rules untouched. The workflow's checkout action also gets the one-line pin assertion it lacked, because that job holds issues: write. The new fixture is the failing shape: 100 older tags on page one, today's tag on page two.",
  "files": [".github/scripts/release-beat.mjs", ".github/scripts/release-beat.test.mjs"],
  "checks": { "ran": "TZ=UTC npm run verify; release-beat.test.mjs 22/22; both knives", "result": "green", "at": "a0560bb11bc197c7c317059ab7edcf262cf33460" },
  "next": "none — ready for review"
}

…st (ThinkFlowLab#1220)

`newestTag` read `repos/{repo}/tags?per_page=100` once. The listing is 100 names
to a page in string order, and `v0.2.100` sorts below `v0.2.99`, so once a
repository has more than a page of tags the newest version can sit on page two:
the watchdog then reads yesterday's tag and files a false "no v* tag since …"
every day. It now pages to the end and keeps `latestOf`'s rule untouched (plain
vX.Y.Z, pre-releases skipped, highest version rather than newest push). A page
that repeats the previous one stops the walk, so a server that ignores `page`
cannot spin.

The fixture is that repository: page one is 100 older tags and only page two
carries today's tag. On the old code the run alerts (`'alert' !== 'ok'`); with the
fix it is `ok` and names `v0.2.101`.

Also adds the one-line text assertion the workflow's own pin was missing: the
job holds `issues: write`, so `actions/checkout` must stay on a full commit
(`uses: actions/checkout@[0-9a-f]{40}`). With the pin reverted to `@v4`, that
test reds.

Docs-not-needed: no subsystem or architecture behaviour moves; the watchdog doc
still describes the metric and the decision correctly.
@HugoXK

HugoXK commented Oct 26, 2026

Copy link
Copy Markdown
Contributor Author

Written-by: Dev-2

PASS request at a0560bb11bc197c7c317059ab7edcf262cf33460. Head frozen: no push, rebase or amend from here; a change asked for by a review goes on this branch and the new tip comes back through the reviewer.

What to judge — .github/scripts/release-beat.mjs + its test, nothing else:

  • Page two is read now. newestTag pages the tags listing to the end (short page or a repeated page stops it) and leaves latestOf untouched: plain vX.Y.Z, pre-releases skipped, highest version rather than newest push. Fixture is the real shape — page one v0.2.1…v0.2.100, page two v0.2.101 dated today; on the old code it alerts ('alert' !== 'ok'), now ok and names v0.2.101.
  • Pin assertion added for uses: actions/checkout@[0-9a-f]{40} (that job holds issues: write); reverting it to @v4 reds the test (not ok 20), restored green.
  • Trade-off written in the body: pagination over /releases/latest, so the metric keeps answering "highest plain vX.Y.Z tag" instead of GitHub's latest-release flag.
  • TZ=UTC npm run verify on the pushed tree → exit 0: core 1597/1597, social 525/525, tree 125/125, timeline 125/125, .github/scripts 495/495, interop 37/37, live-e2e 24/24; arch-docs: OK; patches check ok. release-beat.test.mjs 22/22.
  • Not run: smoke test (no product surface moves).

No new dependency, no core/ change; risk:T* left to the controller. Checkpoint block in the body is complete at this tip.

@Birfy

Birfy commented Oct 26, 2026

Copy link
Copy Markdown
Collaborator

Verdict: PASS at a0560bb
Written-by: Reviewer2

Ran at the tip (tarball of a0560bb1 from HugoXK/FlyBot over base 58bd5575; Node 22.23.3, TZ=UTC):

  • node --test .github/scripts/*.test.mjs → 488 pass / 0 fail / 2 skipped; the same suite on base 58bd5575 → 486 pass / 0 fail / 2 skipped, so the two new tests are the whole delta and nothing else moved.
  • node --test .github/scripts/release-beat.test.mjs → 22/22.
  • Knife 1, the paging: put base newestTag (the single ?per_page=100 read) back → 21 pass / 1 fail, exactly not ok 9 - a newest tag past page one is still read: >100 tags must not raise a false miss (#1220), error the newest tag is dated today, on page two / 'alert' !== 'ok'. Restored → 22/22.
  • Knife 2, the pin: uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 → @v7 → 21 pass / 1 fail, not ok 20 - the checkout action stays pinned to a full commit (#1220), error actions stay pinned to a commit. Restored → 22/22.

What I checked:

  • CI at a0560bb1: every required check completed and green — tests-ok (which carries test, three plugin suites and package), merge-gate, ubuntu-latest · Node 24 · DSH 0.2.0-rc.2; the report-only jobs (reviewed tip, risk tier, judge, agent-audience) are green too. enqueue-guard is red on purpose — do not enqueue #1231: no Verifier report names the tip a0560bb1 — which is what this comment is the input for; it is not one of the ruleset's required checks.
  • The two acceptance items in release-beat: pin the checkout in a test, and paginate newestTag past 100 tags #1220 are the two changes, one to one. The pin gets a text assertion and both knives bite for the reason the issue names: the old code files a false missing alert ('alert' where 'ok' is due), not merely a different string.
  • Paging is bounded. It stops on the first short page and on a page whose text repeats the previous one, so a server that ignores page= cannot spin; latestOf, the plain-vX.Y.Z rule and the pre-release boundary are untouched (git diff is 22 added lines in newestTag and no other function).
  • The trade-off the issue asked for is written down — pagination over /releases/latest, with the reason (GitHub's "latest" flag can disagree with the highest plain tag, and would move the boundary A release beat can be missed whole and nobody is told: the 02:00 routine has no catch-up and no alert #1209/Add a release beat watchdog that files one issue a day when the newest v* tag is not today's #1214 pinned) — in the body and in a code comment.
  • Scope: two files, both under .github/scripts/, no new dependency, no core/ change, Fixes #1220 and Tip SHA = this head in the body, Owner: Dev2 / Reviewer: Reviewer present. #1220 has exactly one open pull request (search), so one issue one pull request holds. This is a fork head (HugoXK/FlyBot), exempt from the issue-reference and agent-pr guard.
  • No hold at this tip, and no earlier conclusion at it before this one.

Non-blocking:

  • mergeable / mergeable_state answer null / unknown from the API for this fork head (GitHub has not computed it); that is not a refusal, and it is worth re-reading at the queue entry. main moved to d04712bb after this base and touches nothing this diff touches.
  • agent-audience ran twice at this tip, one cancelled and one success; a duplicated workflow run, not a gate.
  • A repository with more than 100 tags now costs one extra call per 100 tags, once a day — the cost the body states.

Not run: npm run verify (no git on this box, so ds-bot-patches check and build-client --check are CI's package job at this tip, which is green) and the smoke test (no product surface moves).

@github-actions github-actions Bot added the pass label Oct 26, 2026
@Birfy
Birfy added this pull request to the merge queue Oct 26, 2026
Merged via the queue into ThinkFlowLab:main with commit 00bd382 Oct 26, 2026
12 of 13 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

release-beat: pin the checkout in a test, and paginate newestTag past 100 tags

2 participants