feat(merge): require explicit e2e scope on merge_pull_request, enforce per-target policy #13
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Problem
E2E behavior on deploy is driven by a free-form token in the merge commit message (
[skip e2e]/[e2e: <pattern>]), parsed by theparse-selectorsjob in flow.ravendeploy-{staging,prod}.yml. Both deploy workflows are opt-out: E2E runs by default unless[skip e2e]is present.The recurring failure is behavioral: the agent forgets the token or emits the wrong scope. Consequences:
staging-stack/prod-stackconcurrency lock (cancel-in-progress: false) and stall the next deploy → routine manual cancels.[skip e2e]on a master merge can silently skip the prod gate.Flipping the workflow default (opt-out → opt-in) was considered and rejected: it only reroutes what "forgetting" defaults to, it does not force an intentional decision. The fix must force the decision where the agent actually makes it — the tool.
Fix — force the decision at the tool boundary
Per CLAUDE.md §7 (never commit directly to dev/master), every deploy-triggering push originates from a
merge_pull_requestcall. That is the chokepoint. Add a required, no-defaulte2eparameter tomerge_pull_request:[e2e:auth]vs[e2e: auth]typos).Per-target policy (by PR base branch)
e2evaluesdev(staging)skip·smoke·full·scoped:<pattern>master(prod)full·scoped:<pattern>skip(tool rejects with a clear error)Rationale: fast iteration on staging (skip allowed, smoke default), clean gate on prod (no skip possible; full or scoped only).
Coupled change in flow.raven (must land together)
The commit-message token vocabulary is a shared contract between this tool (emitter) and
parse-selectors(parser). The parser +run-e2ecomposite action currently understand[skip e2e]and[e2e: <pattern>], and deploy-staging hardcodessuite: smoke. To supportfullon staging,parse-selectorsneeds to treat a reserved token (proposal:[e2e: full]→suite=all) as a suite override. The implementer must read.forgejo/actions/run-e2e/action.yml+ both deploy workflows first and pin the exact token↔behavior mapping before wiring, then open the matching flow.raven PR.Proposed token mapping (verify against run-e2e semantics before committing):
e2e=skip→ append[skip e2e](dev only)e2e=smoke→ no token (staging default suite is smoke)e2e=full→ dev:[e2e: full](reserved → suite=all); master: no token (prod default is already suite=all — do NOT emit[e2e: full], it would settests=fulland grep-match zero specs)e2e=scoped:<pat>→[e2e: <pat>]Defense-in-depth (not the primary mechanism)
Keep the workflows opt-out as a backstop, and add a pre-push git hook in flow.raven that hard-rejects a raw
git pushto dev/master without an explicit E2E token — covers the one path this tool can't see (a forbidden-but-possible direct push). Track the hook in the flow.raven PR.Acceptance criteria
merge_pull_requestrejects the call whene2eis absent (no default).e2e=skipon amaster-based PR is rejected with an actionable error.run-e2e/action.yml+ deploy-{staging,prod}.yml; documented in the tool's help text.parse-selectorsunderstands thefull-on-staging reserved token; pre-push hook backstop added.e2e=smokeruns smoke;e2e=fullruns the full suite on staging; a master merge withe2e=fullruns the full prod suite;e2e=skipon master is impossible.References
deploy-staging.yml/deploy-prod.ymlparse-selectors+e2ejobs (bothif: skip != 'true').Philflow/flow.raven-deployment#267).#14(this repo) — the v16 Actions REST tools work.Philflow/flow.raven-deployment#295will later migrate the composite action this touches into a reusable workflow — keep the token vocabulary migration-safe (see coupling comment below).Coupling note — the composite action you edit gets replaced later (
Philflow/flow.raven-deployment#295)The flow.raven side of this work modifies
parse-selectors+ the stagingsuitewiring under the current composite shape (.forgejo/actions/run-e2e/action.yml). Be aware thatPhilflow/flow.raven-deployment#295(blocked on the Forgejo v16 upgradePhilflow/flow.raven-deployment#267) will later delete that composite action and move it to a reusable workflow.forgejo/workflows/_e2e.yml.Implications:
[skip e2e],[e2e: full]→suite=all,[e2e: <pattern>], default) expressed in a way that's straightforward to carry into the reusable-workflow rewrite — ideally concentrated inparse-selectors+ a cleansuite/testsoutput contract, not scattered inline in the composite.Philflow/flow.raven-deployment#295has been annotated to preserve this vocabulary post-migration, but the cleaner your output contract here, the safer that migration is.#13—#13ships first, under the composite shape. Just don't design the token handling in a way that only works inside the composite.