feat: emit native GitHub Deployment objects for promotions#241
Merged
Conversation
Signed-off-by: Joshua Temple <joshua.temple@stablekernel.com>
… config Signed-off-by: Joshua Temple <joshua.temple@stablekernel.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
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 ownsteps:jobs.Fix
Opt-in, additive config (no
schema_versionbump):environment_url(omitempty) onenvironment_config.<name>.deployments: { enabled, keep_prior_active }(omitempty) on the trunk config, using the established sibling-pointer toggle pattern.keep_prior_activemaps to the Deployments APIauto_inactive(default false relies on native auto-inactivation; true keeps prior deployments active).When enabled, the single finalize seam (orchestrate
generator.goandpromote.go) emits steps that call the Deployments API viagh api: create a Deployment for the target environment, setin_progress, then a terminalsuccess/failurebased on the deploy callbacks' results (finalize alreadyneeds:them), attachingenvironment_urlon success when configured.Status-transition model
A single finalize seam cannot cleanly emit
in_progressbefore the deploy runs, so the model is: create the Deployment, setin_progress, then immediately set the terminal status (successwhen every deploy callback succeeded, elsefailure). 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' }}(reusingappTokenServerGuard). On gitea/act the steps skip and the e2e path is unaffected.Least-privilege
deployments: writeis 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-existingTestNormalizeWorkflowPath_ActionlintCleanenvironment flake (actionlint resolving sibling workflow files absent in the worktree); unrelated to this change.TestNativeDeployments_Enabled/Disabled/Deterministic/Actionlint,TestPlan_MatchesGeneratedBytes(OFF-state byte-identical),TestParseDeployments,TestDeploymentsValidatesAtCurrentSchemaVersion(validates atCurrentSchemaVersion, unchanged).golangci-lint run ./...: 0 issues.cd e2e && go build ./... && go vet ./...: clean.manifest.schema.jsoncopies regenerated viacascade schema, drift-free and content-identical.e2e scenario
e2e/scenarios/31-native-deployments.yamldeclaresdeployments.enabled: true,keep_prior_active: true, and anenvironment_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