Skip to content

feat: emit native GitHub Deployment objects for promotions#241

Merged
joshua-temple merged 2 commits into
mainfrom
feat/native-deployments
Jun 21, 2026
Merged

feat: emit native GitHub Deployment objects for promotions#241
joshua-temple merged 2 commits into
mainfrom
feat/native-deployments

Conversation

@joshua-temple

Copy link
Copy Markdown
Collaborator

Problem

cascade promotes releases through environments but never creates native GitHub Deployment objects. The repository Deployments view, environment URLs, and auto-inactivation do not reflect cascade promotions. GitHub only auto-creates a Deployment when a job carries a literal environment: key, which is forbidden on reusable-workflow caller jobs (every cascade deploy is such a caller), so cascade must create Deployments explicitly from its own steps: jobs.

Fix

Opt-in, additive config (no schema_version bump):

  • environment_url (omitempty) on environment_config.<name>.
  • deployments: { enabled, keep_prior_active } (omitempty) on the trunk config, using the established sibling-pointer toggle pattern. keep_prior_active maps to the Deployments API auto_inactive (default false relies on native auto-inactivation; true keeps prior deployments active).

When enabled, the single finalize seam (orchestrate generator.go and promote.go) emits steps that call the Deployments API via gh api: create a Deployment for the target environment, set in_progress, then a terminal success/failure based on the deploy callbacks' results (finalize already needs: them), attaching environment_url on success when configured.

Status-transition model

A single finalize seam cannot cleanly emit in_progress before the deploy runs, so the model is: create the Deployment, set in_progress, then immediately set the terminal status (success when every deploy callback succeeded, else failure). Documented in code and docs.

act/gitea guard

The Deployments API does not exist on gitea/act. Every deployment step carries the established real-GitHub guard if: ${{ github.server_url == 'https://github.com' }} (reusing appTokenServerGuard). On gitea/act the steps skip and the e2e path is unaffected.

Least-privilege

deployments: write is added to the finalize job permissions only when the toggle is enabled. Disabled output is byte-identical to before.

Verification

  • go build ./cmd/... ./internal/...: clean.
  • go test ./... -count=1: pass except the documented pre-existing TestNormalizeWorkflowPath_ActionlintClean environment flake (actionlint resolving sibling workflow files absent in the worktree); unrelated to this change.
  • New tests pass: TestNativeDeployments_Enabled/Disabled/Deterministic/Actionlint, TestPlan_MatchesGeneratedBytes (OFF-state byte-identical), TestParseDeployments, TestDeploymentsValidatesAtCurrentSchemaVersion (validates at CurrentSchemaVersion, unchanged).
  • golangci-lint run ./...: 0 issues.
  • cd e2e && go build ./... && go vet ./...: clean.
  • All three manifest.schema.json copies regenerated via cascade schema, drift-free and content-identical.

e2e scenario

e2e/scenarios/31-native-deployments.yaml declares deployments.enabled: true, keep_prior_active: true, and an environment_url, then regenerates and asserts drift-free byte stability. A live Deployment object cannot be asserted because gitea/act has no Deployments API and the steps skip under the server_url guard; the scenario asserts the steps are emitted, guarded, and regeneration stays clean.

Closes #185

Signed-off-by: Joshua Temple <joshua.temple@stablekernel.com>
… config

Signed-off-by: Joshua Temple <joshua.temple@stablekernel.com>
@joshua-temple joshua-temple enabled auto-merge (squash) June 21, 2026 12:02
@joshua-temple joshua-temple merged commit e32768a 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 GitHub Deployment objects and statuses for promotions

1 participant