No wrapper for Woodpecker pipeline approval — fork PRs always arrive blocked, the raw call records a human as approver, and pipeline-status renders blocked as pending #990

Open
opened 2026-07-31 08:29:49 +00:00 by Ghost · 0 comments

Summary

The fork-PR flow this fleet now uses requires a Woodpecker pipeline approval, and no wrapper exposes it. tools/woodpecker/ provides pipeline-list, pipeline-status, pipeline-trigger and ci-wait — there is no approve.

Every fork PR arrives with its pipeline blocked, so this is not an edge case; it is on the critical path of the standard delivery shape.

Why it matters more than a missing convenience

1. It forces a raw API call, which is where identity goes wrong. Both approvals on mosaicstack/stack#983 had to be hand-rolled POST /api/repos/{id}/pipelines/{n}/approve. The raw path resolves the shared credential, so the approval is recorded as a human's account:

pipeline 2136  reviewed_by: jason.woltje

That approval was taken by the coordinator agent. Nothing in the record says so. A wrapper that resolved the per-agent identity — as the git wrappers already do — would make the approval record mean what it appears to mean.

2. It hides a real authorization question behind an undocumented verb. The approval gate exists to stop unreviewed foreign code from executing with CI secrets. Who may open that gate is a policy question, and right now the tooling neither expresses nor records an answer — it is whoever happens to hand-roll the call.

3. blocked is invisible from the place people look. The Gitea commit status renders a blocked pipeline as pending, which reads as "CI is running, wait." A pipeline that has never started and a pipeline mid-run are the same string to a reader. Anyone waiting on that status waits forever.

Expected

  1. tools/woodpecker/pipeline-approve.sh, resolving the per-agent identity the way the git wrappers do, so the approval record names the agent that approved.
  2. pipeline-status.sh should distinguish blocked from pending in its own output rather than leaving that to the caller — the two states have opposite meanings for whether waiting will ever terminate.

Related

  • #988 — the same wrapper-family gap (no -F body file on the issue/PR wrappers).
  • #980 / #986 — identity not landing where the caller believes it lands. This is the same class on the CI surface: the acting agent is invisible in the artifact.
## Summary The fork-PR flow this fleet now uses **requires** a Woodpecker pipeline approval, and **no wrapper exposes it.** `tools/woodpecker/` provides `pipeline-list`, `pipeline-status`, `pipeline-trigger` and `ci-wait` — there is no `approve`. Every fork PR arrives with its pipeline `blocked`, so this is not an edge case; it is on the critical path of the standard delivery shape. ## Why it matters more than a missing convenience **1. It forces a raw API call, which is where identity goes wrong.** Both approvals on `mosaicstack/stack#983` had to be hand-rolled `POST /api/repos/{id}/pipelines/{n}/approve`. The raw path resolves the shared credential, so the approval is recorded as a **human's account**: ``` pipeline 2136 reviewed_by: jason.woltje ``` That approval was taken by the coordinator agent. Nothing in the record says so. A wrapper that resolved the per-agent identity — as the git wrappers already do — would make the approval record mean what it appears to mean. **2. It hides a real authorization question behind an undocumented verb.** The approval gate exists to stop **unreviewed foreign code** from executing with CI secrets. Who may open that gate is a policy question, and right now the tooling neither expresses nor records an answer — it is whoever happens to hand-roll the call. **3. `blocked` is invisible from the place people look.** The Gitea commit status renders a blocked pipeline as **`pending`**, which reads as "CI is running, wait." A pipeline that has never started and a pipeline mid-run are the same string to a reader. Anyone waiting on that status waits forever. ## Expected 1. `tools/woodpecker/pipeline-approve.sh`, resolving the per-agent identity the way the git wrappers do, so the approval record names the agent that approved. 2. `pipeline-status.sh` should **distinguish `blocked` from `pending` in its own output** rather than leaving that to the caller — the two states have opposite meanings for whether waiting will ever terminate. ## Related - `#988` — the same wrapper-family gap (no `-F` body file on the issue/PR wrappers). - `#980` / `#986` — identity not landing where the caller believes it lands. This is the same class on the CI surface: the acting agent is invisible in the artifact.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: mosaicstack/stack#990