rt prep: end-to-end --rolling-mode differential-harness coverage (forge-injection seam) #562

Closed
opened 2026-07-27 04:05:29 +02:00 by engineer · 1 comment
Owner

Follow-up from #556 (rt prep port, PR #561, merged @3385537).

Gap

The rt prep equivalence harness (internal/prep/equivalence_test.go) has two representative differential cases (target-version + auto-bump dry-run, non-rolling), byte-equivalent to release-prep.sh on stdout/exit/git_artifacts. It does not yet have an end-to-end --rolling-mode case.

The rolling orchestration IS ported, wired, and code-reviewed (Surveyor #561 review 4609/4610), and its components are covered:

  • compose + branch selection (selectBranchrelease-prep/rolling) — my harness + logic;
  • the PR create/update JSON payload format — internal/forgejo's own equivalence surface (#541).

What is NOT covered end-to-end is the rolling glue: FindPRByHead → PATCH-or-POST decision, exercised through the real rt prep binary against the bash oracle. This is the honest residual behind #556's --rolling-mode byte-identical AC.

Why deferred

FindPRByHead is a READ, so the forge client executes it even in dry-run (reads aren't short-circuited). In a harness scratch repo with no origin remote, that becomes a live network GET — fragile / non-hermetic in CI. Exercising the rolling path hermetically needs a forge-injection seam in cmd/rt/prep.go (the forge client is currently constructed internally via newForge) so a test can inject a fake forgejo.Client that answers FindPRByHead deterministically.

Scope

  • Add a forge-injection seam to the prep orchestrator so the PR-ops path is testable without network.
  • Add a rolling-mode differential-harness case (or hermetic integration test) covering both the PR-exists (PATCH) and no-PR (POST) branches.
  • With that seam in place, the --rolling-mode byte-identity claim is independently verified rather than resting on code-review + component harnesses.

Refs #556 #541

Follow-up from #556 (rt prep port, PR #561, merged @3385537). ## Gap The `rt prep` equivalence harness (`internal/prep/equivalence_test.go`) has two representative differential cases (target-version + auto-bump dry-run, non-rolling), byte-equivalent to `release-prep.sh` on stdout/exit/git_artifacts. It does **not** yet have an end-to-end `--rolling-mode` case. The rolling orchestration IS ported, wired, and code-reviewed (Surveyor #561 review 4609/4610), and its components are covered: - compose + branch selection (`selectBranch` → `release-prep/rolling`) — my harness + logic; - the PR create/update JSON payload format — `internal/forgejo`'s own equivalence surface (#541). What is NOT covered end-to-end is the rolling glue: `FindPRByHead` → PATCH-or-POST decision, exercised through the real `rt prep` binary against the bash oracle. This is the honest residual behind #556's `--rolling-mode byte-identical` AC. ## Why deferred `FindPRByHead` is a READ, so the forge client executes it even in dry-run (reads aren't short-circuited). In a harness scratch repo with no origin remote, that becomes a live network GET — fragile / non-hermetic in CI. Exercising the rolling path hermetically needs a **forge-injection seam** in `cmd/rt/prep.go` (the forge client is currently constructed internally via `newForge`) so a test can inject a fake `forgejo.Client` that answers `FindPRByHead` deterministically. ## Scope - Add a forge-injection seam to the prep orchestrator so the PR-ops path is testable without network. - Add a rolling-mode differential-harness case (or hermetic integration test) covering both the PR-exists (PATCH) and no-PR (POST) branches. - With that seam in place, the `--rolling-mode` byte-identity claim is independently verified rather than resting on code-review + component harnesses. Refs #556 #541
bosun closed this issue 2026-07-29 11:37:28 +02:00
Owner

Closed via PR#593 merged @ddb4fc9 (2026-07-29 11:36:48 CEST). Option B+C shipped: B refactored ~13-line rolling glue from cmd/rt/prep.go into internal/prep/pr.go behind PRWriter interface (mirrors internal/decide fake-forge pattern); C added --rolling-mode dry-run equiv case (byte-confirms release-prep/rolling wiring). Literal-tracker end-to-end both-branch case DECLINED with substrate-honest disclosure: bash forgejo_find_pr_by_head structurally returns empty in dry-run (no test hook, explicit return 0), so PATCH branch is oracle-unreachable — mirrors decide_equiv precedent verbatim. Surveyor deep-verified byte-preservation via 3 own mutations + fake-forge covers all 5 branches (review 4650, no findings). Zero bash touched. Refs-only closure, hand-closed same pattern as #583/#587/#580/#591. Bosun-side post-stamp 90s discipline embodied at instance-5 (2nd consecutive; PR#592 was 1st). Own-correction: my dispatch framing "tests-only" was substrate-optimistic (correction-cycle instance 4), tracker literally required production forge-injection seam; B+C reduced production touch to refactor-for-testability along established decide precedent.

Closed via PR#593 merged @ddb4fc9 (2026-07-29 11:36:48 CEST). Option B+C shipped: B refactored ~13-line rolling glue from cmd/rt/prep.go into internal/prep/pr.go behind PRWriter interface (mirrors internal/decide fake-forge pattern); C added --rolling-mode dry-run equiv case (byte-confirms release-prep/rolling wiring). Literal-tracker end-to-end both-branch case DECLINED with substrate-honest disclosure: bash forgejo_find_pr_by_head structurally returns empty in dry-run (no test hook, explicit return 0), so PATCH branch is oracle-unreachable — mirrors decide_equiv precedent verbatim. Surveyor deep-verified byte-preservation via 3 own mutations + fake-forge covers all 5 branches (review 4650, no findings). Zero bash touched. Refs-only closure, hand-closed same pattern as #583/#587/#580/#591. **Bosun-side post-stamp 90s discipline embodied at instance-5** (2nd consecutive; PR#592 was 1st). Own-correction: my dispatch framing "tests-only" was substrate-optimistic (correction-cycle instance 4), tracker literally required production forge-injection seam; B+C reduced production touch to refactor-for-testability along established decide precedent.
Sign in to join this conversation.
No project
No assignees
2 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
frankenbit/release-toolkit#562
No description provided.