Skip to content

feat: emit environments.json from the manifest#239

Merged
joshua-temple merged 1 commit into
mainfrom
feat/emit-environments-config
Jun 21, 2026
Merged

feat: emit environments.json from the manifest#239
joshua-temple merged 1 commit into
mainfrom
feat/emit-environments-config

Conversation

@joshua-temple

Copy link
Copy Markdown
Collaborator

Problem

GitHub environment protection rules (required reviewers, wait timers, deployment branch and tag policies) and environment-scoped secret and variable names are repository configuration, not workflow YAML. The manifest could not express them, so operators set them by hand with no single source of truth tied to the manifest.

Fix

Add a cascade environments command that emits a deterministic, per-environment environments.json derived from the manifest. The operator applies it out of band (gh api / Terraform); cascade never calls the GitHub API. This is the additive sibling of the branch-protection command (#5).

  • Expand EnvironmentConfig with additive omitempty fields: required_reviewers ([]string slugs), wait_timer (int, 0..43200), branch_policy (protected|custom|all), branch_patterns/tag_patterns ([]string, custom only), secrets/variables ([]string, NAMES only, never values). CurrentSchemaVersion is unchanged.
  • Lenient validation that only fires when a field is present, so no currently-valid manifest is rejected.
  • New internal/environments package mirroring internal/branchprotection: each entry pairs the directly-appliable Environments REST body (wait_timer, deployment_branch_policy) with operator_todo guidance. Reviewers are surfaced as slugs under operator_todo because the REST API needs a numeric id the manifest does not carry; secret and variable names are surfaced for the operator to create with values out of band.
  • Emitted output is deterministic: environments follow manifest order, MarshalIndent, single trailing newline.
  • The file is operator-applied JSON, not a verify-tracked plan file: internal/generate/{plan,marker,verify}.go are untouched and the command is not added to generate.Plan.

Verification

  • go build ./cmd/... ./internal/..., go test ./... (1588 passed), golangci-lint run ./... (no issues), e2e module build/vet/lint clean.
  • New unit tests (payload determinism/drift, names-only, validation range/enum/name-safety, parse-at-current-schema-version), command integration tests (stdout, --output, parity), and e2e scenario 29-environment-config-emit proving the enriched manifest parses and regenerates byte-identically (ran green under Docker).
  • All three manifest.schema.json copies regenerated and byte-identical.

Closes #186.

Signed-off-by: Joshua Temple <joshua.temple@stablekernel.com>
@joshua-temple joshua-temple enabled auto-merge (squash) June 21, 2026 09:44
@joshua-temple joshua-temple merged commit 1135d31 into main Jun 21, 2026
15 checks passed
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.

feat: emit an environments configuration file from the manifest

1 participant