feat(pipectl)!: remove promote and rollback as delivery operations #2034

Merged
sean merged 1 commit from fix/remove-promote-rollback into trunk 2026-08-12 14:04:21 +00:00
Owner

promote and rollback are removed from the pipeline API. spec.operation now accepts deploy and retry only, and both CLI verbs become tombstones naming pipectl deploy.

Why these two, and only these two. Neither ever had an execution path — no reconciler branched on either value, so a promote submitted the byte-identical workflow a deploy submits. Across their whole lifetime the cluster recorded one promote and one rollback, and the rollback failed. Applying a Release to a more mature Target is a deploy; returning a Target to earlier bytes is a deploy of the earlier version.

retry and consume are deliberately untouched. retry has 16 live records and is the documented recovery when a kernel-roll canary gate expires at 7200s. consume has 55 records and is emitted automatically by the flux deploy template, not typed by hand.

Decision record. This executes PIPELINE-CONTROL-PLANE-OVERHAUL.md ("remove the deployment operation named with the retired 'promotion' term"). It supersedes the R10 sketch in RELEASE-TRAIN-AND-EVENT-TRIGGERS.md, which proposed keeping both values behind --as. That doc now records the decision and its cost: the declared label saying a human meant a deploy as a rollback is no longer captured anywhere. Nothing is inferred, so R10's actual objection is not violated.

Latent bug fixed along the way. usage() printed a hardcoded sed -n '2,22p' range. Deleting two help lines without shrinking it would have made every pipectl help call print set -euo pipefail and the NS=workflows block as if it were help text — affecting all eight call sites, including the surviving verbs.

Kept deliberately (same words, unrelated senses): the release-step promote (build → test → promote) and its four templates, the gitops auto-rollback-on-failure workflow argument, retry.RetryOnConflict, the gpg signing keyset, and rolled-back as a deployment outcome.

Live objects. The two historical records carrying the removed values stay as history. Both are terminal, so the tightened enum cannot strand an in-flight deployment.

Verification

  • tests/check.sh: 129/129 guards pass, including lexicon-retired-verbs, crd-generated-in-sync, check-emittable-templates, and every-guard-has-a-caller.
  • go build ./... and the non-envtest Go tests pass.
  • CRD diff touches only the enum and its doc line; retryOf and both retry CEL rules survive.
  • pipectl help now ends cleanly at trace; both tombstones exit 1 naming the replacement.
  • pipectl-maturity-intents extended: the tombstones must refuse, name the replacement, and create no PipelineDeploy record.
  • Not run locally: the delivery_api_envtest CEL contract — envtest assets are absent on this laptop. It runs in CI.

No CHANGELOG entry: that file is read-only history and release notes come from frozen PipelineChange evidence.

`promote` and `rollback` are removed from the pipeline API. `spec.operation` now accepts `deploy` and `retry` only, and both CLI verbs become tombstones naming `pipectl deploy`. **Why these two, and only these two.** Neither ever had an execution path — no reconciler branched on either value, so a promote submitted the byte-identical workflow a deploy submits. Across their whole lifetime the cluster recorded **one** promote and **one** rollback, and the rollback failed. Applying a Release to a more mature Target is a deploy; returning a Target to earlier bytes is a deploy of the earlier version. **`retry` and `consume` are deliberately untouched.** `retry` has 16 live records and is the documented recovery when a kernel-roll canary gate expires at 7200s. `consume` has 55 records and is emitted automatically by the flux deploy template, not typed by hand. **Decision record.** This executes PIPELINE-CONTROL-PLANE-OVERHAUL.md ("remove the deployment operation named with the retired 'promotion' term"). It supersedes the R10 sketch in RELEASE-TRAIN-AND-EVENT-TRIGGERS.md, which proposed keeping both values behind `--as`. That doc now records the decision **and its cost**: the declared label saying a human meant a deploy as a rollback is no longer captured anywhere. Nothing is inferred, so R10's actual objection is not violated. **Latent bug fixed along the way.** `usage()` printed a hardcoded `sed -n '2,22p'` range. Deleting two help lines without shrinking it would have made every `pipectl` help call print `set -euo pipefail` and the `NS=workflows` block as if it were help text — affecting all eight call sites, including the surviving verbs. **Kept deliberately** (same words, unrelated senses): the release-step `promote` (build → test → promote) and its four templates, the gitops auto-rollback-on-failure workflow argument, `retry.RetryOnConflict`, the gpg signing keyset, and `rolled-back` as a deployment outcome. **Live objects.** The two historical records carrying the removed values stay as history. Both are terminal, so the tightened enum cannot strand an in-flight deployment. ## Verification - `tests/check.sh`: **129/129 guards pass**, including `lexicon-retired-verbs`, `crd-generated-in-sync`, `check-emittable-templates`, and `every-guard-has-a-caller`. - `go build ./...` and the non-envtest Go tests pass. - CRD diff touches only the enum and its doc line; `retryOf` and both retry CEL rules survive. - `pipectl` help now ends cleanly at `trace`; both tombstones exit 1 naming the replacement. - `pipectl-maturity-intents` extended: the tombstones must refuse, name the replacement, and **create no PipelineDeploy record**. - Not run locally: the `delivery_api_envtest` CEL contract — envtest assets are absent on this laptop. It runs in CI. No CHANGELOG entry: that file is read-only history and release notes come from frozen `PipelineChange` evidence.
feat(pipectl)!: remove promote and rollback as delivery operations
All checks were successful
pipeline/ci CI green @ 723329498ce1
723329498c
`promote` and `rollback` are removed from the pipeline API. `spec.operation`
now accepts `deploy` and `retry` only, and both CLI verbs are tombstones that
name `pipectl deploy`.

Neither value ever had an execution path. No reconciler branched on either, so
a promote submitted the byte-identical workflow a deploy submits. In their
whole lifetime the cluster recorded one promote and one rollback, and the
rollback failed. Applying a Release to a more mature Target is a deploy;
returning a Target to earlier bytes is a deploy of the earlier version.

This executes the decision in PIPELINE-CONTROL-PLANE-OVERHAUL.md ("remove the
deployment operation named with the retired 'promotion' term"). It supersedes
the R10 sketch in RELEASE-TRAIN-AND-EVENT-TRIGGERS.md, which proposed keeping
both values behind `--as`. That doc now records the decision and its cost: the
declared label saying a human meant a deploy as a rollback is no longer
captured. Nothing is inferred, so R10's actual objection is not violated.

`retry` and `consume` are deliberately untouched. `retry` is the recovery path
when a kernel-roll canary gate expires, and the flux deploy template emits
consumptions by itself.

Tombstones follow the existing `ship` and `merge` convention, per the overhaul
doc: old commands print a deprecation error naming the replacement rather than
aliasing silently. Both verbs took the same three arguments as `deploy`, so a
silent deletion would have dropped an old invocation into `usage` with no hint.

Also fixes a latent trap: `usage()` printed a hardcoded `sed -n '2,22p'`
range. Deleting two help lines without shrinking it would have made every
pipectl help call print shell internals as help text.

pipectl-maturity-intents now asserts the tombstones refuse, name the
replacement, and create no PipelineDeploy record.

Kept deliberately, all unrelated senses of the same words: the release-step
`promote` (build -> test -> promote) and its templates, the gitops
auto-rollback-on-failure workflow argument, `retry.RetryOnConflict`, the gpg
signing keyset, and `rolled-back` as a deployment outcome.

The two historical records carrying the removed values stay in place as
history. Both are terminal, so the tightened enum cannot strand an in-flight
deployment.
sean merged commit 723329498c into trunk 2026-08-12 14:04:21 +00:00
Sign in to join this conversation.
No reviewers
No labels
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
sean/pipelines!2034
No description provided.