fix(ci): key multi-job reusable concurrency on a literal job id

ci-python-app.yaml and ci-mobile-ios.yaml built their concurrency group
from ${{ github.job }}. In a called workflow that expression evaluates to
the caller's job id, not the job's own id, so every job in the reusable
resolved to the same group. With cancel-in-progress: true they cancelled
each other.

Observed in pr-reviewer after repinning it off a ref that predates the
concurrency blocks: one run, ci / lint cancelled 1s after start by a
sibling, ci / subproject-tests succeeded, and the aggregator failed on the
cancelled dependency.

Replaces the expression with the job id written out literally in all 7
groups, and records the reason at the first block in each file.
This commit is contained in:
Adam Moussa 2026-07-28 17:22:51 -04:00
parent 880ba803d2
commit a394b54f82
No known key found for this signature in database
2 changed files with 21 additions and 9 deletions

View file

@ -122,10 +122,16 @@ jobs:
runs-on: ubuntu-latest
timeout-minutes: ${{ inputs.js-timeout-minutes }}
# cancel-in-progress is TRUE: superseding a push should abandon the older
# CI run, which produces no external side effects. `github.job` is in the
# key so the three jobs here do not serialise against each other.
# CI run, which produces no external side effects.
#
# The trailing segment is the job id written out literally, NOT
# `${{ github.job }}`. In a called workflow that expression evaluates to the
# CALLER's job id, so every job here would resolve to the same group and,
# with cancel-in-progress on, cancel its own siblings. Observed live in
# pr-reviewer: `lint` was cancelled one second in by a sibling and the
# aggregator failed on the cancelled dependency.
concurrency:
group: ci-mobile-ios-${{ github.workflow }}-${{ github.ref }}-${{ inputs.working-directory }}-${{ github.job }}
group: ci-mobile-ios-${{ github.workflow }}-${{ github.ref }}-${{ inputs.working-directory }}-js
cancel-in-progress: true
defaults:
run:
@ -194,7 +200,7 @@ jobs:
runs-on: macos-26
timeout-minutes: ${{ inputs.ios-timeout-minutes }}
concurrency:
group: ci-mobile-ios-${{ github.workflow }}-${{ github.ref }}-${{ inputs.working-directory }}-${{ github.job }}
group: ci-mobile-ios-${{ github.workflow }}-${{ github.ref }}-${{ inputs.working-directory }}-ios-build
cancel-in-progress: true
defaults:
run:
@ -289,7 +295,7 @@ jobs:
if: always()
runs-on: ubuntu-latest
concurrency:
group: ci-mobile-ios-${{ github.workflow }}-${{ github.ref }}-${{ inputs.working-directory }}-${{ github.job }}
group: ci-mobile-ios-${{ github.workflow }}-${{ github.ref }}-${{ inputs.working-directory }}-ci
cancel-in-progress: true
steps:
- name: Require all jobs to have succeeded

View file

@ -50,8 +50,14 @@ jobs:
lint:
runs-on: ubuntu-latest
timeout-minutes: 10
# The trailing segment of every group in this file is the job id written
# out literally, NOT `${{ github.job }}`. In a called workflow that
# expression evaluates to the CALLER's job id, so all four jobs here would
# resolve to one group and, with cancel-in-progress on, cancel each other.
# Observed live in pr-reviewer: `lint` was cancelled one second in by a
# sibling and the aggregator failed on the cancelled dependency.
concurrency:
group: ci-python-app-${{ github.workflow }}-${{ github.ref }}-${{ inputs.source-dirs }}-${{ github.job }}
group: ci-python-app-${{ github.workflow }}-${{ github.ref }}-${{ inputs.source-dirs }}-lint
cancel-in-progress: true
steps:
- uses: actions/checkout@v7
@ -100,7 +106,7 @@ jobs:
runs-on: ubuntu-latest
timeout-minutes: 10
concurrency:
group: ci-python-app-${{ github.workflow }}-${{ github.ref }}-${{ inputs.source-dirs }}-${{ github.job }}
group: ci-python-app-${{ github.workflow }}-${{ github.ref }}-${{ inputs.source-dirs }}-test-collect
cancel-in-progress: true
steps:
- uses: actions/checkout@v7
@ -124,7 +130,7 @@ jobs:
runs-on: ubuntu-latest
timeout-minutes: 10
concurrency:
group: ci-python-app-${{ github.workflow }}-${{ github.ref }}-${{ inputs.source-dirs }}-${{ github.job }}
group: ci-python-app-${{ github.workflow }}-${{ github.ref }}-${{ inputs.source-dirs }}-subproject-tests
cancel-in-progress: true
steps:
- uses: actions/checkout@v7
@ -150,7 +156,7 @@ jobs:
if: always()
runs-on: ubuntu-latest
concurrency:
group: ci-python-app-${{ github.workflow }}-${{ github.ref }}-${{ inputs.source-dirs }}-${{ github.job }}
group: ci-python-app-${{ github.workflow }}-${{ github.ref }}-${{ inputs.source-dirs }}-ci
cancel-in-progress: true
steps:
- name: Require all jobs to have succeeded