Skip to content

ci: scope Quality Gate concurrency to the calling workflow#74

Merged
szjanikowski merged 1 commit into
mainfrom
fix/quality-gate-concurrency-collision
Jun 25, 2026
Merged

ci: scope Quality Gate concurrency to the calling workflow#74
szjanikowski merged 1 commit into
mainfrom
fix/quality-gate-concurrency-collision

Conversation

@szjanikowski

Copy link
Copy Markdown
Contributor

Problem

After a release, main showed a red ✗ at the release commit — looking like CI was failing. It wasn't. The mark was a standalone Quality Gate run with conclusion cancelled (GitHub renders cancelled identically to a failure). The code was healthy: every other gate run on that commit passed all jobs and the release shipped to PyPI.

Root cause (structural, recurs on every release)

publish.yml calls quality-gate.yml as a reusable workflow (uses:). A reusable workflow's concurrency is evaluated in the caller's ref context. When Publish runs on main, its embedded quality-gate joins the same group quality-refs/heads/main as the standalone Quality Gate triggered by the push to main.

The standard release flow — merge release PR to main (push → standalone gate) immediately followed by a tag push / dry-run dispatch (→ Publish, whose embedded gate shares the group) — therefore triggers cancel-in-progress: true, which cancels the older standalone gate. Red ✗.

Fix

Key the concurrency group on github.workflow as well:

group: quality-${{ github.workflow }}-${{ github.ref }}

github.workflow resolves to the caller's workflow name ("Quality Gate" on a direct push/PR, "Publish" when invoked via uses:), so the standalone gate and the publish-embedded gate never share a group — while each still de-dupes among its own runs (the cancellation savings concurrency was added for are preserved). A comment documents the one caveat: this relies on each caller declaring an explicit name: (both do today), else GitHub falls back to the file path and the group silently changes.

Verification

  • YAML parses (quality-gate.yml + publish.yml).
  • This PR's own Quality Gate runs and de-dupes on re-push.
  • After merge: a dry-run gh workflow run publish.yml --ref main immediately after a push to main no longer cancels the standalone Quality Gate (both complete green).

🤖 Generated with Claude Code

@szjanikowski szjanikowski force-pushed the fix/quality-gate-concurrency-collision branch 2 times, most recently from 9861a22 to b83ead7 Compare June 25, 2026 16:26
publish.yml calls quality-gate.yml as a reusable workflow, and a reusable
workflow's concurrency group is evaluated in the caller's ref context. On a
release (merge to main → push, immediately followed by a tag/dry-run Publish),
the publish-embedded gate joined the same `quality-refs/heads/main` group as the
standalone push-triggered gate, and `cancel-in-progress: true` cancelled the
latter — which GitHub renders as a red ✗ on main even though nothing failed.

Key the concurrency group on github.workflow too, so the standalone gate and the
publish-embedded gate never share a group while each still de-dupes among its own
runs. github.workflow resolves to the caller's workflow name ("Quality Gate" vs
"Publish"), which relies on each caller declaring an explicit `name:` (both do);
documented in a comment.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@szjanikowski szjanikowski force-pushed the fix/quality-gate-concurrency-collision branch from b83ead7 to c01970b Compare June 25, 2026 16:34
@szjanikowski szjanikowski merged commit bc583f7 into main Jun 25, 2026
9 checks passed
@szjanikowski szjanikowski deleted the fix/quality-gate-concurrency-collision branch June 25, 2026 16:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant