diff --git a/e2e/scenarios/multi-repo/external-update-deploys-component.yaml b/e2e/scenarios/multi-repo/external-update-deploys-component.yaml index 229b065..15e0716 100644 --- a/e2e/scenarios/multi-repo/external-update-deploys-component.yaml +++ b/e2e/scenarios/multi-repo/external-update-deploys-component.yaml @@ -1,19 +1,19 @@ -# Scenario: external deploy opts in to on_update.deploy and the receiver still -# records new external state, proving the additive on_update config is -# back-compatible with the live record path. +# Scenario: external deploy opts in to on_update.deploy and the receiver records +# new external state while the scoped deploy_cdk job runs live against a local +# reusable deploy workflow. # -# Scope note: the scoped deploy job wiring (a deploy_ job, needs: update, -# if gated on needs.update.result == 'success' && inputs.deploy_name == '', -# uses: the declared workflow, secrets: inherit) is asserted at the generator -# level in internal/generate/external_test.go. A live scoped deploy run needs a -# real reusable deploy workflow plus deploy credentials in the satellite repo, -# which is not reproducible in the gitea + act harness, so the actual deploy run -# is covered by the downstream fleet validation rather than forced here. This -# scenario keeps the live coverage focused on what the harness can prove: that -# adding on_update.deploy does not break the receiver's record path. +# The scenario proves three things end-to-end: +# 1. Adding on_update.deploy does not break the receiver's record path. +# 2. The generated deploy_cdk job fires when deploy_name == 'cdk' and +# calls the local reusable workflow via uses: ./.github/workflows/... +# 3. The local reusable workflow (committed to primary-backend before the +# dispatch) completes successfully so the overall run concludes success. +# +# Note: no actions/checkout inside the reusable workflow - act cannot resolve +# checkout for a reusable callback against the per-scenario gitea instance. name: external-update-deploys-component -description: External deploy declares on_update.deploy; receiver still records new external state +description: External deploy declares on_update.deploy; receiver records state and scoped deploy job runs live repos: primary-backend: @@ -33,7 +33,7 @@ repos: workflow: example/cdk-infra/.github/workflows/deploy.yaml on_update: deploy: - workflow: example/cdk-infra/.github/workflows/deploy.yaml + workflow: .github/workflows/on-update-deploy-cdk.yaml manifest: state: dev: @@ -61,7 +61,39 @@ repos: primary: primary-backend steps: - # Step 1: Commit changes to satellite CDK repo + # Step 1: Commit the local reusable deploy workflow to primary-backend so that + # act can resolve it via uses: ./.github/workflows/on-update-deploy-cdk.yaml + # when the generated deploy_cdk job fires. + - name: seed-local-deploy-workflow + repo: primary-backend + action: commit + commit: + message: "chore: add on-update deploy workflow for cdk" + files: + .github/workflows/on-update-deploy-cdk.yaml: | + name: on-update-deploy-cdk + on: + workflow_call: + inputs: + environment: + required: false + type: string + sha: + required: false + type: string + version: + required: false + type: string + deploy_name: + required: false + type: string + jobs: + cdkdeploy: + runs-on: ubuntu-latest + steps: + - run: echo "on-update deploy ran deploy_name=${{ inputs.deploy_name }} sha=${{ inputs.sha }}" + + # Step 2: Commit changes to satellite CDK repo - name: update-cdk-stack repo: cdk-infra action: commit @@ -77,7 +109,8 @@ steps: } } - # Step 2: Satellite notifies primary after deploy + # Step 3: Satellite notifies primary after deploy; external-update.yaml runs, + # records state, and the scoped deploy_cdk job calls the local reusable workflow. - name: notify-primary repo: cdk-infra action: dispatch diff --git a/internal/generate/external.go b/internal/generate/external.go index fd17e21..6ea3150 100644 --- a/internal/generate/external.go +++ b/internal/generate/external.go @@ -178,6 +178,7 @@ func (g *ExternalUpdateGenerator) writeHeader(sb *strings.Builder) { func (g *ExternalUpdateGenerator) writeWorkflowTrigger(sb *strings.Builder) { sb.WriteString("name: External Update\n\n") + sb.WriteString("run-name: External Update ${{ inputs.deploy_name }} ${{ inputs.sha }}\n\n") sb.WriteString("on:\n") sb.WriteString(" workflow_dispatch:\n") sb.WriteString(" inputs:\n") diff --git a/internal/generate/external_test.go b/internal/generate/external_test.go index 969172f..837bd91 100644 --- a/internal/generate/external_test.go +++ b/internal/generate/external_test.go @@ -1038,3 +1038,29 @@ func TestExternalUpdateGenerator_OnUpdateDeploy_LocalWorkflowPath(t *testing.T) require.NoError(t, err) assert.Contains(t, content, "uses: ./.github/workflows/deploy-cdk.yaml") } + +// TestExternalUpdateGenerator_EmitsRunName verifies that the generated +// external-update workflow includes a run-name line that embeds the +// deploy_name and sha inputs so individual runs are correlatable in the +// GitHub Actions UI. +func TestExternalUpdateGenerator_EmitsRunName(t *testing.T) { + cfg := &config.TrunkConfig{ + TrunkBranch: "master", + Environments: []string{"dev", "test", "prod"}, + External: []config.ExternalRepoConfig{ + { + Repo: "example/cdk-infra", + Ref: "main", + Deploys: []config.ExternalDeployConfig{ + {Name: "cdk", Workflow: "example/cdk-infra/.github/workflows/deploy.yaml"}, + }, + }, + }, + } + + gen := NewExternalUpdateGenerator(cfg, "/tmp") + content, err := gen.Generate() + require.NoError(t, err) + + assert.Contains(t, content, "run-name: External Update ${{ inputs.deploy_name }} ${{ inputs.sha }}") +}