feat(release): auto-assign manifest follow-up PR to the user who merged the rolling PR #113

Closed
opened 2026-06-26 14:33:12 +02:00 by quartermaster · 0 comments

Why

The manifest follow-up PR (chore(manifest): post-cut bookkeeping for vX.Y.Z) currently opens with no assignee. Under path-α option (3) (required_approvals > 0), this PR sits open waiting for someone to merge it — but nothing in the substrate signals WHO is responsible. The PR just sits.

Auto-assigning it to the user who merged the rolling PR (the operator who clicked Gate-1) makes the responsibility-chain visible at the substrate level: "you clicked Gate-1; you're on the hook for the post-cut follow-up." It also surfaces the PR in that operator's Forgejo notifications + assigned-to-me view, which is where they'd naturally look.

Especially useful when:

  • Multiple operators share Gate-1 duty (the PR routes to whoever clicked, not to a generic mailbox)
  • Path-α option (3) is in use (the PR sits open until someone clicks; auto-assign tells them WHICH someone)
  • The operator switches contexts between Gate-1 click and the follow-up click (the assignment is the breadcrumb)

Less useful but still harmless under option (2) (zero-touch — the manifest PR auto-merges; assignee just becomes a record-keeping detail).

Implementation surface

Small change in .forgejo/workflows/_release.yml's manifest-PR creation step:

  1. Identify the rolling PR: after mode=cut fires, use forgejo_find_pr_by_merge_sha (already in lib/forgejo-api.sh, used by Layer 2) to look up the rolling PR whose merge_commit_sha matches $GITHUB_SHA.
  2. Read .merged_by.login: from the rolling PR JSON.
  3. Pass assignees in the manifest PR create: extend forgejo_create_pr to accept assignees, OR call mcp__forgejo__edit_issue after PR creation to set assignees.

Fallback paths (substrate-state-care per §8 Axis A)

The merger-lookup can fail in edge cases. Each path should fall back cleanly:

Edge case Fallback
forgejo_find_pr_by_merge_sha returns empty (race or direct-push-to-main) Open manifest PR with no assignee (current behavior)
.merged_by.login is empty (unusual, but possible on direct push) No assignee
Merger is release-bot itself (path-α option (2) scenario) Skip assignment — manifest PR is about to auto-merge anyway; assignee is moot
API call fails No assignee (don't block manifest PR creation on a UX-nice-to-have)

The whole feature is BEST-EFFORT — never blocks the cut path.

What this PR (when implemented) does NOT do

  • Does NOT change the manifest PR title or body — that's settled (Herald β-refined naming)
  • Does NOT change the auto-merge logic — that's a separate question (review-gate tradeoff #112)
  • Does NOT change the assignee after the PR is open — one-shot at creation time

Test coverage needed

  • New bats tests in tests/release-decide.bats (or wherever the manifest-PR-creation tests live) for:
    • happy path: rolling PR has .merged_by.login → manifest PR gets assignee
    • forgejo_find_pr_by_merge_sha returns empty: manifest PR opens with no assignee
    • merger is release-bot: no assignee (skip)
    • API failure during merger-lookup: manifest PR opens with no assignee (graceful degradation)

Sequencing

Lightweight feature; can land any time. Composes with #112 (review-gate tradeoff docs) — that issue documents WHEN this feature is most useful (option (3) scenario).

Suggested target: v0.7.x or v0.8.x as part of the pre-v1.0 readiness sweep (#106) — the kind of consumer-UX polish that adoption is likely to surface.

Refs

  • Operator framing 2026-06-26: "would it be appropriate to auto-assign the follow-up PR to the user who merged the cut PR?"
  • Sibling tracker: #112 — review-gate tradeoff docs (this feature's main use case)
  • Substrate primitive: forgejo_find_pr_by_merge_sha in scripts/lib/forgejo-api.sh (already exists, used by Layer 2)
  • Forgejo API: PATCH /repos/{owner}/{repo}/issues/{index} accepts assignees: ["username"]
## Why The manifest follow-up PR (`chore(manifest): post-cut bookkeeping for vX.Y.Z`) currently opens with no assignee. Under path-α option (3) (`required_approvals > 0`), this PR sits open waiting for someone to merge it — but nothing in the substrate signals WHO is responsible. The PR just sits. Auto-assigning it to the user who merged the rolling PR (the operator who clicked Gate-1) makes the responsibility-chain visible at the substrate level: *"you clicked Gate-1; you're on the hook for the post-cut follow-up."* It also surfaces the PR in that operator's Forgejo notifications + assigned-to-me view, which is where they'd naturally look. Especially useful when: - Multiple operators share Gate-1 duty (the PR routes to whoever clicked, not to a generic mailbox) - Path-α option (3) is in use (the PR sits open until someone clicks; auto-assign tells them WHICH someone) - The operator switches contexts between Gate-1 click and the follow-up click (the assignment is the breadcrumb) Less useful but still harmless under option (2) (zero-touch — the manifest PR auto-merges; assignee just becomes a record-keeping detail). ## Implementation surface Small change in `.forgejo/workflows/_release.yml`'s manifest-PR creation step: 1. **Identify the rolling PR**: after `mode=cut` fires, use `forgejo_find_pr_by_merge_sha` (already in `lib/forgejo-api.sh`, used by Layer 2) to look up the rolling PR whose merge_commit_sha matches `$GITHUB_SHA`. 2. **Read `.merged_by.login`**: from the rolling PR JSON. 3. **Pass `assignees` in the manifest PR create**: extend `forgejo_create_pr` to accept assignees, OR call `mcp__forgejo__edit_issue` after PR creation to set assignees. ## Fallback paths (substrate-state-care per §8 Axis A) The merger-lookup can fail in edge cases. Each path should fall back cleanly: | Edge case | Fallback | |---|---| | `forgejo_find_pr_by_merge_sha` returns empty (race or direct-push-to-main) | Open manifest PR with no assignee (current behavior) | | `.merged_by.login` is empty (unusual, but possible on direct push) | No assignee | | Merger is `release-bot` itself (path-α option (2) scenario) | Skip assignment — manifest PR is about to auto-merge anyway; assignee is moot | | API call fails | No assignee (don't block manifest PR creation on a UX-nice-to-have) | The whole feature is BEST-EFFORT — never blocks the cut path. ## What this PR (when implemented) does NOT do - Does NOT change the manifest PR title or body — that's settled (Herald β-refined naming) - Does NOT change the auto-merge logic — that's a separate question (review-gate tradeoff #112) - Does NOT change the assignee after the PR is open — one-shot at creation time ## Test coverage needed - New bats tests in `tests/release-decide.bats` (or wherever the manifest-PR-creation tests live) for: - **happy path**: rolling PR has `.merged_by.login` → manifest PR gets assignee - **forgejo_find_pr_by_merge_sha returns empty**: manifest PR opens with no assignee - **merger is release-bot**: no assignee (skip) - **API failure during merger-lookup**: manifest PR opens with no assignee (graceful degradation) ## Sequencing Lightweight feature; can land any time. Composes with #112 (review-gate tradeoff docs) — that issue documents WHEN this feature is most useful (option (3) scenario). Suggested target: v0.7.x or v0.8.x as part of the pre-v1.0 readiness sweep (#106) — the kind of consumer-UX polish that adoption is likely to surface. ## Refs - **Operator framing 2026-06-26**: "would it be appropriate to auto-assign the follow-up PR to the user who merged the cut PR?" - **Sibling tracker**: [#112](https://git.frankenbit.de/frankenbit/release-toolkit/issues/112) — review-gate tradeoff docs (this feature's main use case) - **Substrate primitive**: `forgejo_find_pr_by_merge_sha` in `scripts/lib/forgejo-api.sh` (already exists, used by Layer 2) - **Forgejo API**: `PATCH /repos/{owner}/{repo}/issues/{index}` accepts `assignees: ["username"]`
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#113
No description provided.