Skip to content

feat(orchestrate): record per-component seed state and read it on promote - #520

Merged
joshua-temple merged 1 commit into
mainfrom
feat/orchestrate-seed-state
Jul 8, 2026
Merged

joshua-temple merged 1 commit into
mainfrom
feat/orchestrate-seed-state

Conversation

@joshua-temple

Copy link
Copy Markdown
Collaborator

Problem

Per-component promotion writes isolated state, but orchestrate still recorded the built version into the shared flat state.<env>, and promote read its source from there. Two components would overwrite each other's seed, and the independent-promotion scenario had to interleave to avoid it.

Fix (coupled write + read)

  • Write: orchestrate records state.components.<name>.<env>. The generated per-component workflow writes it via its inline state edit (generator.go), and the orchestrate CLI serializes through WriteScopedState when a component is selected (orchestrator.go, command.go). An empty component records flat state.<env>, byte-identical.
  • Read: the promote source read previously consumed the flat seed orchestrate wrote, so scoping the write alone leaves a component's promote with no source deployments. The promote preflight now reads the component's own seed via ReadComponentState and overlays it (statemerge.go, promote.go, command_preflight.go); single-component reads stay flat.

Result: two components orchestrate to the first environment independently, each keeping its own state, with no interleaving.

Verification

go build ./..., go test ./... (2596 pass), go test -race on orchestrate/promote/config (790 pass), golangci-lint run ./... clean; e2e build+vet clean. Single-component byte-identical baseline gate green (the generator state-edit change does not alter single-component output). Concurrent-orchestrate re-apply preserves an unmodeled sibling verbatim (component_seed_test.go). New scenario 52-component-orchestrate-isolation.yaml (two components orchestrate to dev with no interleaving; both state.components.<name>.dev coexist) passes locally in the harness (30.2s); the promotion-isolation (40.5s) and single-component (55.7s) scenarios also pass locally.

Refs #290, #292.

…mote

Orchestrate now records a component's built version at state.components.<name>.<env> instead of the shared flat state.<env>, so two components no longer overwrite each other's seed. The generated per-component workflow writes state.components.<name>.<env> via its inline state edit, and the orchestrate CLI serializes through WriteScopedState when a component is selected; an empty component records flat state.<env> byte-identical. Because the promote source read previously consumed the flat seed that orchestrate wrote, scoping the write alone would leave a component's promote with no source deployments; the promote preflight now reads the component's own seed via ReadComponentState and overlays it, keeping single-component reads flat. Two components can now orchestrate to the first environment independently, each keeping its own state, without interleaving.

Refs #290, #292.

Signed-off-by: Joshua Temple <joshua.temple@stablekernel.com>
@joshua-temple
joshua-temple merged commit 0147f31 into main Jul 8, 2026
20 checks passed
@joshua-temple
joshua-temple deleted the feat/orchestrate-seed-state branch July 8, 2026 07:43
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