feat(train): PipelineReleasePolicy — automatic release intake, disabled (R8) #2041
Loading…
Reference in a new issue
No description provided.
Delete branch "fix/r11-propose-only"
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?
Decision 1 promised an AUTOMATIC intake mode where every green Build starts a release. Nothing implemented it — the enum offered the mode and no code read it. This is that code, and it is inert: no project has a policy.
Modeled field-for-field on
PipelineDeliveryPolicyper the design. The reconciler watches Build and Release and creates oneintegrateAllGreenRelease when the project's open changes are all green and none is already running. ReleaseSubmitter still owns the train, the version claim, and execution.Two decisions the sketch left open (asked and settled before building):
ChangesNotGreen— not a fault.maxAttempts, default 3). Unbounded, every Build event mints another attempt and burns a version; zdns/zerotea sat on a broken release leg for six days and this would have released into it hundreds of times. The budget is keyed on a hash of the sorted open change numbers, so a NEW green change forms a new set and restores it. Exhaustion reportsAttemptsExhausted.The SubjectAccessReview is the load-bearing part.
serviceAccountNameis an unverified string; without it, creating a policy would mint release intent attributed to ANY identity — and a release publishes signed artifacts and movesmain, so the forged actor lands on the provenance. "May create a release policy" must not silently mean "may release as anyone".7 envtest specs: disabled is inert · non-release-gated refused · a red change holds the set · all-green mints exactly one with correct attribution · a second pass while running does not stack another (coalescing) · the budget stops a failing set · a new change restores it · an ungranted actor refused. 132/132 controller specs pass, 129/129 guards.
Also in this branch: R11 (previous commit, already reviewed in #2040 — this branch was reused after that merged, so the diff here is R8 only).
The CRD is registered in
config/crd/kustomization.yaml— a CRD that exists but is never applied is exactly the pruning trapcrd-generated-in-syncguards.