|
29 | 29 | types: [completed] |
30 | 30 | workflow_dispatch: {} |
31 | 31 |
|
32 | | -# Only one integ run at a time against the shared account — overlapping deploys |
33 | | -# would collide on the single hardcoded `backgroundagent-integ` stack name. |
| 32 | +# Only one integ run at a time against the shared account. Stack names are now |
| 33 | +# run-unique (`int-<sha>`, see the integ job) so this is no longer a correctness |
| 34 | +# requirement — it bounds shared-account cost/parallelism rather than preventing |
| 35 | +# a name collision. |
34 | 36 | concurrency: |
35 | 37 | group: cdk-integ |
36 | 38 | cancel-in-progress: false |
@@ -217,30 +219,36 @@ jobs: |
217 | 219 | - name: Install dependencies |
218 | 220 | run: yarn install --immutable |
219 | 221 |
|
220 | | - - name: Run integ tests (deploy → assert → destroy) |
221 | | - run: mise //cdk:integ |
222 | | - |
223 | | - # Safety net: integ-runner forces teardown on success and failure, but if |
224 | | - # the run is cancelled or crashes mid-deploy the stack can be stranded in |
225 | | - # the shared account. Delete it directly via CloudFormation so we never |
226 | | - # leak billable resources. |
| 222 | + # Teardown: integ-runner forces `cdk destroy` on success and failure (via |
| 223 | + # the CDK bootstrap roles, which hold the CloudFormation permissions). No |
| 224 | + # raw-CLI safety net here: the GitHub OIDC role has no |
| 225 | + # cloudformation:DeleteStack/DescribeStacks, so such a step can only fail |
| 226 | + # (#566). If a cancelled/crashed run strands the stack, reclaim is the |
| 227 | + # stranded-stack cleanup owned by #400/#72 — and the run-unique name below |
| 228 | + # means a stranded stack never blocks a later run. |
227 | 229 | # |
228 | | - # NOTE: `cdk destroy backgroundagent-integ` would NOT work here — it |
229 | | - # synthesizes the main app (src/main.ts), which does not contain the integ |
230 | | - # stack, so it exits 0 having deleted nothing. Target the stack by its |
231 | | - # literal CloudFormation name instead. delete-stack is idempotent (no-op if |
232 | | - # already gone), so `|| true` only guards transient API errors. |
233 | | - - name: Ensure stack torn down |
234 | | - if: always() |
| 230 | + # INTEG_STACK_NAME maps the stack to the commit under test plus the run |
| 231 | + # number (`int-<sha>-<run>`), replacing the single fixed |
| 232 | + # `backgroundagent-integ` name. The run number makes same-commit re-runs |
| 233 | + # distinct; the `int-` prefix marks it ephemeral for #72's sweep. HEAD_SHA |
| 234 | + # is the resolved PR head (or dispatched ref) and RUN_NUMBER is a positive |
| 235 | + # integer, so both are already lowercase-alphanumeric — no sanitizing |
| 236 | + # needed to stay CloudFormation-valid. |
| 237 | + - name: Run integ tests (deploy → assert → destroy) |
235 | 238 | env: |
236 | | - AWS_REGION: ${{ vars.AWS_REGION || 'us-east-1' }} |
237 | | - AWS_DEFAULT_REGION: ${{ vars.AWS_REGION || 'us-east-1' }} |
| 239 | + HEAD_SHA: ${{ needs.resolve.outputs.head_sha }} |
| 240 | + RUN_NUMBER: ${{ github.run_number }} |
238 | 241 | run: | |
239 | 242 | set -euo pipefail |
240 | | - aws cloudformation delete-stack --stack-name backgroundagent-integ || true |
241 | | - # No `|| true` on the wait: a DELETE_FAILED must surface loudly so we |
242 | | - # never silently leak billable resources in the shared account. |
243 | | - aws cloudformation wait stack-delete-complete --stack-name backgroundagent-integ |
| 243 | + export INTEG_STACK_NAME="int-${HEAD_SHA:0:12}-${RUN_NUMBER}" |
| 244 | + echo "Integ stack name: $INTEG_STACK_NAME" |
| 245 | + mise //cdk:integ -- --all --require-approval never \ |
| 246 | + -c stackName="integ-${{ github.run_id }}-${{ github.run_attempt }}" \ |
| 247 | + -c github:sha="$(git rev-parse HEAD)" \ |
| 248 | + -c github:ref="$(git branch --show-current || echo "detached")" \ |
| 249 | + -c github:actor="${{ github.triggering_actor }}" \ |
| 250 | + -c github:repository="$(gh repo view --json nameWithOwner --jq .nameWithOwner)" \ |
| 251 | + -c github:clean="$([ -z "$(git status --porcelain)" ] && echo true || echo false)" |
244 | 252 |
|
245 | 253 | # Post the final integ-smoke status back to the PR head so the check flips from |
246 | 254 | # pending to success/failure. Skipped for workflow_dispatch (no PR to gate). |
|
0 commit comments