From 8b8fc1ac463c70c22728e993200d776378c3df27 Mon Sep 17 00:00:00 2001 From: Adam Moussa Date: Tue, 28 Jul 2026 12:34:17 -0400 Subject: [PATCH] ci: add job-level concurrency to the cd-cdk, cd-sam and iOS deploys cd-dotnet-eb already serialises deploys per environment; the other three deploy reusables had no concurrency group, so back-to-back merges could start overlapping runs against the same target. CloudFormation rejects a concurrent update on the same stack and cd-sam/cd-cdk pre-flight already hard-fails on an in-progress stack, so the symptom is a failed run that needs a manual re-run rather than a corrupted deploy. Grouping makes those deploys queue instead. Each group key names the thing being deployed, so independent targets in one caller repo still deploy in parallel: cd-sam region + stack-name (both always non-empty) cd-cdk region + stacks + stack-name cd-mobile-ios working-directory + fastlane-lane (both default) cd-cdk keys on the stack selector rather than stack-name because seahaven-org-baseline calls it from five jobs in a single run, one per AWS account, and two of those pass no stack-name. Keying on stack-name alone would collapse them into one group and serialise five independent per-account deploys. cancel-in-progress is false on all three, matching cd-dotnet-eb: unlike CI, cancelling a deploy midway can leave infrastructure mid-update. --- .github/workflows/cd-cdk.yaml | 13 +++++++++++++ .github/workflows/cd-mobile-ios.yaml | 9 +++++++++ .github/workflows/cd-sam.yaml | 9 +++++++++ 3 files changed, 31 insertions(+) diff --git a/.github/workflows/cd-cdk.yaml b/.github/workflows/cd-cdk.yaml index 6a12f41..e58214e 100644 --- a/.github/workflows/cd-cdk.yaml +++ b/.github/workflows/cd-cdk.yaml @@ -56,6 +56,19 @@ jobs: deploy: runs-on: ubuntu-latest timeout-minutes: 30 + # Serialise per deploy target so two pushes cannot deploy over each other. + # The target is the stack selector, NOT stack-name: a multi-account app can + # call this workflow from several jobs in one run (seahaven-org-baseline + # runs five, one per AWS account) and stack-name is optional, so keying on + # it alone would collapse the selector-only jobs into one group and + # serialise deploys that are genuinely independent. `stacks` always defaults + # to "--all", so the group is never empty and back-to-back deploys of the + # same target still queue. + # cancel-in-progress is FALSE on purpose: unlike CI, aborting midway can + # leave a stack mid-update. + concurrency: + group: cd-cdk-${{ inputs.region }}-${{ inputs.stacks }}-${{ inputs.stack-name }} + cancel-in-progress: false steps: - uses: actions/checkout@v7 diff --git a/.github/workflows/cd-mobile-ios.yaml b/.github/workflows/cd-mobile-ios.yaml index 56a91ea..39db5c6 100644 --- a/.github/workflows/cd-mobile-ios.yaml +++ b/.github/workflows/cd-mobile-ios.yaml @@ -56,6 +56,15 @@ jobs: deploy-ios: runs-on: macos-26 timeout-minutes: ${{ inputs.timeout-minutes }} + # Serialise per app + lane so two pushes cannot upload over each other. + # There is no app-identifier input: the target is whatever Fastfile lives in + # working-directory, so that plus the lane is what identifies the deploy. + # Both always default ("." and "ios beta"), so the group is never empty. + # cancel-in-progress is FALSE on purpose: unlike CI, aborting midway can + # leave a half-uploaded TestFlight build. + concurrency: + group: cd-mobile-ios-${{ inputs.working-directory }}-${{ inputs.fastlane-lane }} + cancel-in-progress: false defaults: run: working-directory: ${{ inputs.working-directory }} diff --git a/.github/workflows/cd-sam.yaml b/.github/workflows/cd-sam.yaml index 249998b..9dc07af 100644 --- a/.github/workflows/cd-sam.yaml +++ b/.github/workflows/cd-sam.yaml @@ -39,6 +39,15 @@ jobs: deploy: runs-on: ubuntu-latest timeout-minutes: 15 + # Serialise per stack so two pushes cannot deploy over each other. + # stack-name is required and region always defaults, so the group is never + # empty; the pair is exactly what identifies a CloudFormation stack, so + # different stacks in the same caller repo still deploy in parallel. + # cancel-in-progress is FALSE on purpose: unlike CI, aborting midway can + # leave a stack mid-update. + concurrency: + group: cd-sam-${{ inputs.region }}-${{ inputs.stack-name }} + cancel-in-progress: false steps: - uses: actions/checkout@v7