Mutable tags and the dependency-review v5 branch executed inside every consumer, including OIDC deploy jobs. SHA pins with version comments match the policy scanner and let Renovate advance them.
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.
release.yaml is workflow_call-only. It normalises and validates a `version`
input against MAJOR.MINOR.PATCH, skips every mutating step when the tag or a
Release for it already exists, creates an annotated tag with `git tag -a` and
publishes a GitHub Release with `gh release create --verify-tag`. Top-level
permissions grant `contents: write` only; no id-token is requested. The
previous-tag lookup and `--generate-notes` both work in a repo with no tags.
ci-mobile-ios.yaml is workflow_call-only and pairs with cd-mobile-ios.yaml,
reusing its node-version, ruby-version, working-directory,
cache-dependency-path and fastlane-lane input names. Job `js` runs npm ci,
typecheck, optional lint and optional tests on ubuntu-latest. Job `ios-build`
runs pod install and `xcodebuild build` on macos-26 with
CODE_SIGNING_ALLOWED=NO, CODE_SIGNING_REQUIRED=NO and CODE_SIGN_IDENTITY="";
it declares no secrets and performs no upload. Job `ci` aggregates both via
`needs` so a caller job keyed `ci` reports `ci / ci`. All three jobs carry
job-level concurrency with cancel-in-progress: true. Top-level permissions are
`contents: read`.
The Fastlane branch carries a per-line `# shellcheck disable=SC2086` because
fastlane requires the platform and lane as two argv entries.