Skip to content

release-train: develop -> staging - #233

Merged
tracebloc-release-train[bot] merged 2 commits into
stagingfrom
release-train/to-staging
Aug 12, 2026
Merged

release-train: develop -> staging#233
tracebloc-release-train[bot] merged 2 commits into
stagingfrom
release-train/to-staging

Conversation

@LukasWodka

@LukasWodka LukasWodka commented Aug 12, 2026

Copy link
Copy Markdown
Contributor

Automated promotion by the release train (RFC-0008 D14). Head is the train-managed release-train/to-staging branch (a mirror of develop), so it never collides with a human PR. Merged only when the fr-gate is green.


Note

Medium Risk
The gate’s title/label matching will block merges org-wide once callers ship; false positives would erode trust, though this PR ships zero callers and heavy selftests. Inventory and kanban action pin changes are lower risk but affect conformance checks and board automation.

Overview
Introduces a blocked merge gate for PRs that declare a dependency via the org blocked label or common title markers ([blocked on …], DO NOT MERGE, HOLD until, prefix WIP, etc.). Matching lives in scripts/blocked-marker.py (stdlib only, reads GITHUB_EVENT_PATH—no shell interpolation of titles), with a reusable blocked-gate.yml and path-triggered blocked-gate-selftest.yml weighted toward false-positive cases.

Rollout is staged: repo-inventory.yml registers blocked-gate.yml but exempts every repo with blocked_gate_rollout_pending until callers land in a follow-up PR; no repo wires the gate in this change.

Also bumps actions/add-to-project to v2.0.0 in add-to-kanban.yml, documents that pin in README.md, clears cli’s prior add-to-kanban drift in the inventory, and narrows release-train’s divergent copy note to the header-only difference.

Reviewed by Cursor Bugbot for commit 02d22bf. Bugbot is set up for automated code reviews on this repo. Configure here.

* ci(gate): fail a PR that declares itself blocked (backend#1729)

data-ingestors#468 was titled "... (D10) [blocked on S2]". It collected three
approvals and was merged by its author 105 seconds after S2 merged. The author
waited for the blocker they had written down -- but "S2 merged" was never the
real precondition, and nothing could tell the difference. dev and staging
ingestion broke within hours and stayed broken for a day (backend#1752).

The dependency was recorded as prose, in a place nothing reads. This makes that
sentence a merge gate: a PR whose title or labels say it is blocked fails a
check. Two open PRs carry the shape today -- client#490 ("HOLD until v0.8.0
image") and client-runtime#192 ("DO NOT MERGE").

What it does not do: decide whether the blocker is genuinely resolved. #468's
author satisfied the sentence they wrote and the real precondition was still
unmet. The claim is only that clearing the marker is a deliberate act.

The matching is the entire risk surface, so it lives in a tested script rather
than a YAML heredoc. Precision over recall: `unblocked`, `unblocks`, `blocker`,
`threshold`, `holder` and `wipe` must not fire, or the gate gets called noise
and switched off -- the failure mode house-rules.sh names in its own notes.

No callers in this PR, deliberately. The reusable lands first so the matching
can be reviewed alone; repo-inventory.yml records it `exempt` everywhere with
the rollout named, because this file's own header forbids adding a caller and
flipping it to `required` in one PR. Arming is a briefing decision: two live
PRs go red the moment it is on, which is the gate working.

Verified: marker selftest 22 checks green, including the GITHUB_EVENT_PATH path
the workflow actually uses; both event-path assertions mutation-checked (drop
the title / drop the labels -> each fails). caller-drift selftest 116/0.
load_inventory + check_source_reusables pass on the edited inventory, and fail
as intended when the reusables row is removed. actionlint clean.

* fix(gate): anchor the WIP marker — measurement found a real false positive

Ran the matcher over 588 merged PR titles from ten tracebloc repos rather than
trusting the table I had imagined. It produced exactly one false positive:

    chore(ci): retire the WIP-limit nudge

and it is the worst kind, because "WIP limit" is a domain term in THIS org --
wip-limit-check.yml is one of our own reusables, so the phrase recurs. The
(?<![a-z])/(?![a-z]) guards do not help: the character after "WIP" is a hyphen.

That is precisely the failure this gate cannot afford. A check that fires on a
normal chore PR gets called noise and switched off, and then catches nothing
ever again.

WIP-as-a-marker is a PREFIX convention (`WIP: ...`, `[WIP] ...`); WIP mid-title
is the noun. Anchoring to the start keeps every real marker and drops the false
positive. Over the same 588 titles the matcher now blocks exactly one:
data-ingestors#468 -- the PR this gate exists for.

Both new cases mutation-checked: un-anchoring `wip` fails 2 assertions.

* fix(blocked-gate): fail closed on a payload with no pull_request; minimal perms; label events (Bugbot #229)

- blocked-marker.py: a GITHUB_EVENT_PATH payload with no pull_request object now
  refuses (exit 2) instead of returning an empty title -> 'not blocked' -> exit
  0. A non-PR or malformed event was a silent fail-OPEN; it now fails closed like
  the no-event-path branch. Selftest case added.
- blocked-gate.yml: drop 'pull-requests: read' — the script reads
  GITHUB_EVENT_PATH, never the API, so the wider grant would exceed a minimal
  contents:read caller and fail the reusable at startup.
- Document that callers must trigger on labeled/unlabeled too, or the label half
  of the gate never re-runs until the next synchronize.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
@LukasWodka

Copy link
Copy Markdown
Contributor Author

bugbot run

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Bugbot reviewed your changes and found no new issues!

Comment @cursor review or bugbot run to trigger another review on this PR

Reviewed by Cursor Bugbot for commit fb2d462. Configure here.

@tracebloc-release-train tracebloc-release-train Bot added gate-nudge Toggled by the release train to (re-)fire the fr-gate and removed gate-nudge Toggled by the release train to (re-)fire the fr-gate labels Aug 12, 2026
@LukasWodka

Copy link
Copy Markdown
Contributor Author

bugbot run

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Bugbot reviewed your changes and found no new issues!

Comment @cursor review or bugbot run to trigger another review on this PR

Reviewed by Cursor Bugbot for commit fb2d462. Configure here.

Bumps this repo's own add-to-kanban caller, and flips repo-inventory.yml so
v2.0.0 is the fleet norm rather than the drift.

v1.0.2 declares `using: node20`. Node 20 is deprecated on GitHub-hosted
runners, so GitHub force-runs this action on Node 24 today and prints the
deprecation notice on every run -- including the 542 that succeeded. That
fallback is temporary; when it is withdrawn every repo still on v1.0.2 breaks
at once. v2.0.0 declares node24 and needs no fallback.

Not an outage fix: re-running the reported failed job unchanged on the v1.0.2
pin succeeded, so that failure was a transient TLS condition, not a runtime
incompatibility. cli and release-train have run this exact v2.0.0 pin
successfully (12/12 recent runs). v2.0.0 is input-compatible: it declares
project-url, github-token, labeled and label-operator; our callers pass the
first two.

Inventory changes:
  * cli's add-to-kanban.yml goes divergent -> required. Its copy now matches
    the canonical one byte-for-byte (blob 603751a), and leaving it
    divergent would fail the guard with "marked divergent but now matches".
  * release-train's entry stays divergent -- its header comment still differs
    -- but the half of its reason claiming the v2.0.0 pin is drift is now
    false, so the reason is corrected to name the header alone.
  * stale-backlog.yml's divergent entries and devex-bootstrap's exemption are
    untouched.

README.md told a new repo to pin v1.0.2, which would reintroduce the node20
pin this sweep removes.

This must merge AFTER the other 16 caller PRs: copies are compared by blob id
against the canonical file in the checkout, so until they land the audit
correctly reports 16 drifted copies. Documented awkwardness, fail-closed
direction, resolves itself.

Refs: tracebloc/backend#1816

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
@LukasWodka

Copy link
Copy Markdown
Contributor Author

bugbot run

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Bugbot reviewed your changes and found no new issues!

Comment @cursor review or bugbot run to trigger another review on this PR

Reviewed by Cursor Bugbot for commit 02d22bf. Configure here.

@LukasWodka

Copy link
Copy Markdown
Contributor Author

bugbot run

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Bugbot reviewed your changes and found no new issues!

Comment @cursor review or bugbot run to trigger another review on this PR

Reviewed by Cursor Bugbot for commit 02d22bf. Configure here.

@tracebloc-release-train tracebloc-release-train Bot added gate-nudge Toggled by the release train to (re-)fire the fr-gate and removed gate-nudge Toggled by the release train to (re-)fire the fr-gate labels Aug 12, 2026
@tracebloc-release-train
tracebloc-release-train Bot merged commit f45fc9f into staging Aug 12, 2026
23 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant