Skip to content

feat(promote): honor a component's environment-ladder subset at runtime - #530

Merged
joshua-temple merged 1 commit into
mainfrom
feat/component-env-subset
Jul 8, 2026
Merged

joshua-temple merged 1 commit into
mainfrom
feat/component-env-subset

Conversation

@joshua-temple

Copy link
Copy Markdown
Collaborator

Problem

A component may declare an environments list shorter than the repo-global ladder. Generation already emitted per-component workflows scoped to the component's resolved envs, but the promotion RUNTIME (NewPromoter, the preflighter) read the global ladder, so a short-ladder component could be advanced toward environments it does not target.

Fix

  • applyComponentLadder narrows the working ladder to the component's resolved environments in NewPromoter and the preflighter, so next-env, is-last-env, and gating all use the subset: the subset's last environment is the terminal publish boundary, and a promotion toward an environment outside the subset is rejected.
  • An empty component, and a state-only component with no components declaration, use the global ladder unchanged, byte-identical. Mirrors how rollback already resolves the component's ladder.

Generation was audited and is already correct (workflows built from resolved.Config); this closes the runtime gap only.

Verification

go build ./..., go test ./... (2661 pass), go test -race on promote+simulate (257 pass), golangci-lint run ./... clean; e2e build+vet clean; single-component byte-identical baseline gate green. Unit tests prove a [dev, staging] component never targets prod, cascade within the subset succeeds, the subset's last env is terminal, and a full-ladder sibling still reaches prod. New e2e scenario 55-component-env-subset.yaml (api narrowed to [dev, staging], web full ladder) passes locally in the harness (42.6s): api dev-to-staging is terminal, api dev-to-prod fails as expected, web reaches prod.

Refs #297.

A component may declare an environments list shorter than the repo-global ladder. Generation already emitted per-component workflows scoped to the component's resolved envs, but the promotion runtime read the global ladder, so a short-ladder component could be advanced toward environments it does not target. applyComponentLadder now narrows the working ladder to the component's resolved environments in NewPromoter and the preflighter, so next-env, is-last-env, and gating all use the subset: the subset's last environment is the terminal publish boundary and a promotion toward an environment outside the subset is rejected. An empty component, and a state-only component with no declaration, use the global ladder unchanged, byte-identical. Mirrors how rollback already resolves the component's ladder.

Refs #297.

Signed-off-by: Joshua Temple <joshua.temple@stablekernel.com>
@joshua-temple
joshua-temple merged commit f9b7329 into main Jul 8, 2026
20 checks passed
@joshua-temple
joshua-temple deleted the feat/component-env-subset branch July 8, 2026 14:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant