Skip to content

feat: populate per-environment deploy-history ring - #157

Merged
joshua-temple merged 1 commit into
mainfrom
feat/state-history-ring
Jun 14, 2026
Merged

joshua-temple merged 1 commit into
mainfrom
feat/state-history-ring

Conversation

@joshua-temple

Copy link
Copy Markdown
Collaborator

Problem

EnvState.Previous []EnvStateSnapshot is a reserved-shape ring that was declared but never populated on the promote and rollback state-write paths. Only an environment's current SHA/Version was retained, so resolving a prior version for arbitrary-depth manual rollback had no in-state target list and depended on git archaeology.

Fix

Populate the ring at every point an environment's state pointer transitions to a new SHA, capturing the outgoing {SHA, Version, CommittedAt, CommittedBy} snapshot on the front (newest first) before the pointer advances.

  • New shared helper EnvState.PushPreviousSnapshot(newSHA) in internal/config/history.go, bounded by the named const MaxPreviousSnapshots = 10. It skips no-op transitions (same SHA) and the initial write (no prior SHA), and caps the ring at N by dropping the oldest entries.
  • Wired into the three state-transition write paths:
    • promote finalize updateState (before the env pointer is overwritten)
    • rollback Apply (env-scoped branch only)
    • hotfix finalize Finalize (converted from an unbounded manual prepend to the shared bounded helper)

Purely additive: existing readers ignore Previous; it is now simply populated. Bounded retention prevents unbounded manifest growth. No new struct fields, no manifest schema change.

Verification

  • go build ./..., go test ./... (1251 pass), golangci-lint run ./... (clean)
  • go test -race on config/promote/rollback/hotfix (437 pass)
  • The ring is populated by CLI-runtime Go logic, not by any emitted workflow step, so generated workflows are unchanged: generate-workflow --config .github/manifest.yaml --force produces no .github/workflows / .github/actions drift.
  • e2e module: go build ./... + go vet ./... clean.
  • YAML marshal/unmarshal round-trip of a multi-entry ring is covered by a unit test.

Scope note

This is the history-ring population only. The manual rollback-that-deploys path, divergence-marking of a rolled-back env, and an end-to-end scenario asserting accumulated ring contents are a follow-up: the e2e harness assertion surface does not yet expose ring-contents checks, and adding that belongs with the manual-rollback scenario in the follow-up. Coverage here is unit and integration across all three write paths, including bounded-ring and round-trip tests.

Signed-off-by: Joshua Temple <joshua.temple@stablekernel.com>
@joshua-temple
joshua-temple merged commit df50416 into main Jun 14, 2026
7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant