test: bats coverage for read_rolling_pr_bump_label (FORGEJO_TEST_PR_LABELS hook) #122

Closed
opened 2026-06-26 17:49:40 +02:00 by quartermaster · 0 comments

Why

Surveyor e0c8 flagged at the v0.9.0 sprint approval (#121): read_rolling_pr_bump_label in scripts/release-decide.sh:352 has no direct bats coverage. The function pre-existed the v0.9.0 sprint as untested (Forgejo API path; no test seam yet), but the namespace shift bump:bump/ (closing #107) flipped it from "planned" to "live + load-bearing." The defense-in-depth multi-label fail-loud guard now rests on code-reading + the live exercise, not on a mutation-verified test.

Proposed test seam

Add a FORGEJO_TEST_PR_LABELS env hook, mirroring the existing FORGEJO_TEST_PR_LOOKUP_FILE pattern from forgejo_find_pr_by_merge_sha (Layer 2 tests). When set + the file exists, read_rolling_pr_bump_label reads canned PR-list JSON from the file instead of calling the live Forgejo API.

Test cases

Scenario Expected
Single bump/patch label on rolling PR BUMP_LEVEL=patch, BUMP_SOURCE=rolling_pr_label
Single bump/minor label BUMP_LEVEL=minor
Single bump/major label BUMP_LEVEL=major
No bump/* labels (only other labels) Function returns empty; falls through to auto-detect
Multiple bump/* labels (e.g., bump/patch + bump/minor on same PR) FATAL exit 1 with the multi-label diagnostic message (defense-in-depth guard)
No rolling PR open Function returns empty silently
Non-bump labels with / separator (e.g., priority/high) Function ignores them; falls through
API failure / empty response Function returns empty (graceful degradation)

The multi-label fail-loud case is the most important to mutation-verify per Surveyor's framing — it's the belt-and-suspenders guard if Forgejo's exclusive-label semantics ever surprise us.

Why this came up now

The original read_rolling_pr_bump_label was filed at v0.4.0 era as "planned" — never exercised in production. With #107 (v0.9.0) flipping it to live + load-bearing, the test gap becomes load-bearing too. Surveyor's substrate-state-care discipline: test-coverage should match the load-bearing weight of the code.

Sequencing

  • Now: file this tracker (done)
  • v0.9.x or v0.10.x: implement the test seam + the bats cases above. Small scope (~50 lines of bats + ~5 lines for the test seam in release-decide.sh).
  • Empirical signal worth waiting on: the first live cut that uses the label (operator attaches bump/major to a rolling PR). Surfaces any wiring gaps that static probes can't.

Refs

  • Surfacing: Surveyor e0c8 advisory on PR #121 (v0.9.0 sprint)
  • Function to test: scripts/release-decide.sh:352 read_rolling_pr_bump_label
  • Pattern to mirror: FORGEJO_TEST_PR_LOOKUP_FILE in scripts/lib/forgejo-api.sh:203 (used by Layer-2 tests in tests/release-decide.bats:359)
  • Closed by: #107 — surfaces this test gap
## Why Surveyor e0c8 flagged at the v0.9.0 sprint approval (#121): `read_rolling_pr_bump_label` in `scripts/release-decide.sh:352` has no direct bats coverage. The function pre-existed the v0.9.0 sprint as untested (Forgejo API path; no test seam yet), but the namespace shift `bump:` → `bump/` (closing #107) flipped it from "planned" to "live + load-bearing." The defense-in-depth multi-label fail-loud guard now rests on code-reading + the live exercise, not on a mutation-verified test. ## Proposed test seam Add a `FORGEJO_TEST_PR_LABELS` env hook, mirroring the existing `FORGEJO_TEST_PR_LOOKUP_FILE` pattern from `forgejo_find_pr_by_merge_sha` (Layer 2 tests). When set + the file exists, `read_rolling_pr_bump_label` reads canned PR-list JSON from the file instead of calling the live Forgejo API. ## Test cases | Scenario | Expected | |---|---| | Single `bump/patch` label on rolling PR | `BUMP_LEVEL=patch`, `BUMP_SOURCE=rolling_pr_label` | | Single `bump/minor` label | `BUMP_LEVEL=minor` | | Single `bump/major` label | `BUMP_LEVEL=major` | | No bump/* labels (only other labels) | Function returns empty; falls through to auto-detect | | Multiple `bump/*` labels (e.g., bump/patch + bump/minor on same PR) | **FATAL exit 1** with the multi-label diagnostic message (defense-in-depth guard) | | No rolling PR open | Function returns empty silently | | Non-bump labels with `/` separator (e.g., `priority/high`) | Function ignores them; falls through | | API failure / empty response | Function returns empty (graceful degradation) | The multi-label fail-loud case is the most important to mutation-verify per Surveyor's framing — it's the belt-and-suspenders guard if Forgejo's exclusive-label semantics ever surprise us. ## Why this came up now The original `read_rolling_pr_bump_label` was filed at v0.4.0 era as "planned" — never exercised in production. With #107 (v0.9.0) flipping it to live + load-bearing, the test gap becomes load-bearing too. Surveyor's substrate-state-care discipline: test-coverage should match the load-bearing weight of the code. ## Sequencing - **Now**: file this tracker (done) - **v0.9.x or v0.10.x**: implement the test seam + the bats cases above. Small scope (~50 lines of bats + ~5 lines for the test seam in release-decide.sh). - **Empirical signal worth waiting on**: the first live cut that uses the label (operator attaches `bump/major` to a rolling PR). Surfaces any wiring gaps that static probes can't. ## Refs - **Surfacing**: Surveyor e0c8 advisory on PR #121 (v0.9.0 sprint) - **Function to test**: `scripts/release-decide.sh:352` `read_rolling_pr_bump_label` - **Pattern to mirror**: `FORGEJO_TEST_PR_LOOKUP_FILE` in `scripts/lib/forgejo-api.sh:203` (used by Layer-2 tests in `tests/release-decide.bats:359`) - **Closed by**: [#107](https://git.frankenbit.de/frankenbit/release-toolkit/issues/107) — surfaces this test gap
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
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#122
No description provided.