Skip to content

ci: drop concurrency group on init_release, use race-tolerant find-or-create#5668

Merged
renecannao merged 1 commit into
v3.0from
v3.0-fix-init-release-race
Apr 24, 2026
Merged

ci: drop concurrency group on init_release, use race-tolerant find-or-create#5668
renecannao merged 1 commit into
v3.0from
v3.0-fix-init-release-race

Conversation

@renecannao

Copy link
Copy Markdown
Contributor

Summary

Fixes a mass-cancellation bug in #5666 that only surfaces when many package workflows are dispatched at once.

Problem observed

After merging #5666 and dispatching all 156 package workflows at the same commit:

Status Count
completed / cancelled 142
in_progress 9
completed / success 6 (and growing)

Only ~15 workflows ever ran to completion. The other 141 were cancelled before their init_release step even started.

Root cause

The init_release job was serialized via:

concurrency:
  group: release-init-${{ github.sha }}
  cancel-in-progress: false

Per GitHub's docs on concurrency groups:

When a concurrent job or workflow is queued, if another job or workflow using the same concurrency group in the repository is in progress, the queued job or workflow will be pending. Any previously pending job or workflow in the concurrency group will be canceled.

So the group holds at most 1 running + 1 pending. Triggering 156 workflows simultaneously caused a rolling cancellation: each new arrival displaced the previously-pending one, cancelling it. Net result: only the first-arrived and last-arrived ever progressed past init.

The Option A design from #5666 was validated with just 2 parallel workflows — at N=2, the 1 running + 1 pending cap fits exactly, so the bug didn't show. At N=156 it's catastrophic.

Fix

Drop the concurrency group entirely. All 156 init_release jobs run in parallel and converge via a race-tolerant find-or-create loop:

sleep $(( RANDOM % 10 ))   # stagger start to soften thundering-herd
for attempt in 1..6:
  IDS=$(find drafts where target_commitish==$SHA AND tag_name==$TAG | sort -n)
  if [ -n "$IDS" ]:
    RELEASE_ID=$(head -1)  # deterministic winner: lowest id
    break
  gh api -X POST releases   # create; races tolerated
  sleep 2-5s

Key properties:

  • Deterministic winner. All workers pick the oldest draft (lowest release id) matching SHA+tag. No matter who queries when, they all agree on the same draft.
  • No deletion during race. A worker doesn't delete "duplicate" drafts it sees, because another worker might just have resolved to upload there. Orphan drafts from the race are left in place and can be swept separately if the list grows (most races produce 0–5 duplicates per burst, not 156).
  • Stagger + retry. Random 0–9s initial sleep and 2–5s inter-attempt sleep spread the load over ~30s, so most workers find an already-created draft on their first query.

Validation

  • Lint: all 156 generated workflows pass structural YAML checks; concurrency key is absent from the init_release job.
  • Full end-to-end can only be done post-merge: dispatch all 156 on the same SHA and confirm (a) all succeed (no cancellations), (b) exactly one canonical draft accumulates every distro × variant × tier asset.

Out of scope

  • Orphan-draft cleanup. If the find-or-create race leaves small numbers of empty drafts behind, they accumulate harmlessly. A future scheduled workflow (e.g. "sweep drafts with 0 assets older than 1d") can mop up.

Test plan

  • Merge to v3.0.
  • Dispatch all 156 CI-package-* workflows on the new HEAD SHA.
  • Confirm: 0 cancellations, 156 init_releases all complete, all uploads land in the same draft release (one name, one target_commitish).
  • Check gh api repos/sysown/proxysql/releases after completion — ideally ≤ 5 duplicate empty drafts (from race), to be cleaned up manually if so.

…find-or-create

The previous design serialized all init_release jobs via
  concurrency:
    group: release-init-${{ github.sha }}
    cancel-in-progress: false
That ran into GitHub's "1 running + 1 pending" rule on concurrency
groups: when a third job tries to enter the group, the currently-
pending one is cancelled in favor of the newer arrival. Triggering all
156 package workflows at once caused ~142 of them to be cancelled
before their init_release even got a chance to run.

Replace serialization with a race-tolerant find-or-create loop that
all 156 init jobs run in parallel:

  - Stagger start 0-9s to reduce thundering-herd on the first query.
  - Up to 6 attempts: look up drafts matching this SHA + tag_name
    (strongest key); use the one with the lowest id (deterministic
    winner).
  - If none exist, POST create; sleep 2-5s; re-query. Multiple creates
    may race during the initial burst, producing a handful of
    duplicate drafts, but every worker converges on the same
    lowest-id draft.
  - Fail hard after 6 attempts.

Duplicates from races are not deleted here (deletion under contention
risks a worker using a just-deleted release). A follow-up can sweep
zero-asset duplicate drafts periodically if the list grows.
@gemini-code-assist

Copy link
Copy Markdown

Note

Gemini is unable to generate a review for this pull request due to the file types involved not being currently supported.

@coderabbitai

coderabbitai Bot commented Apr 24, 2026

Copy link
Copy Markdown

Important

Review skipped

Too many files!

This PR contains 156 files, which is 6 over the limit of 150.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 86434586-0836-4c51-9fa6-089f0a05631d

📥 Commits

Reviewing files that changed from the base of the PR and between 4beb6a8 and ac64389.

📒 Files selected for processing (156)
  • .github/workflows/CI-package-amd64-almalinux10-clang.yml
  • .github/workflows/CI-package-amd64-almalinux10-dbg.yml
  • .github/workflows/CI-package-amd64-almalinux10-genai-clang.yml
  • .github/workflows/CI-package-amd64-almalinux10-genai-dbg.yml
  • .github/workflows/CI-package-amd64-almalinux10-genai.yml
  • .github/workflows/CI-package-amd64-almalinux10-v31-clang.yml
  • .github/workflows/CI-package-amd64-almalinux10-v31-dbg.yml
  • .github/workflows/CI-package-amd64-almalinux10-v31.yml
  • .github/workflows/CI-package-amd64-almalinux10.yml
  • .github/workflows/CI-package-amd64-almalinux8-clang.yml
  • .github/workflows/CI-package-amd64-almalinux8-dbg.yml
  • .github/workflows/CI-package-amd64-almalinux8-genai-clang.yml
  • .github/workflows/CI-package-amd64-almalinux8-genai-dbg.yml
  • .github/workflows/CI-package-amd64-almalinux8-genai.yml
  • .github/workflows/CI-package-amd64-almalinux8-v31-clang.yml
  • .github/workflows/CI-package-amd64-almalinux8-v31-dbg.yml
  • .github/workflows/CI-package-amd64-almalinux8-v31.yml
  • .github/workflows/CI-package-amd64-almalinux8.yml
  • .github/workflows/CI-package-amd64-almalinux9-clang.yml
  • .github/workflows/CI-package-amd64-almalinux9-dbg.yml
  • .github/workflows/CI-package-amd64-almalinux9-genai-clang.yml
  • .github/workflows/CI-package-amd64-almalinux9-genai-dbg.yml
  • .github/workflows/CI-package-amd64-almalinux9-genai.yml
  • .github/workflows/CI-package-amd64-almalinux9-v31-clang.yml
  • .github/workflows/CI-package-amd64-almalinux9-v31-dbg.yml
  • .github/workflows/CI-package-amd64-almalinux9-v31.yml
  • .github/workflows/CI-package-amd64-almalinux9.yml
  • .github/workflows/CI-package-amd64-centos10-clang.yml
  • .github/workflows/CI-package-amd64-centos10-dbg.yml
  • .github/workflows/CI-package-amd64-centos10-genai-clang.yml
  • .github/workflows/CI-package-amd64-centos10-genai-dbg.yml
  • .github/workflows/CI-package-amd64-centos10-genai.yml
  • .github/workflows/CI-package-amd64-centos10-v31-clang.yml
  • .github/workflows/CI-package-amd64-centos10-v31-dbg.yml
  • .github/workflows/CI-package-amd64-centos10-v31.yml
  • .github/workflows/CI-package-amd64-centos10.yml
  • .github/workflows/CI-package-amd64-centos9-clang.yml
  • .github/workflows/CI-package-amd64-centos9-dbg.yml
  • .github/workflows/CI-package-amd64-centos9-genai-clang.yml
  • .github/workflows/CI-package-amd64-centos9-genai-dbg.yml
  • .github/workflows/CI-package-amd64-centos9-genai.yml
  • .github/workflows/CI-package-amd64-centos9-v31-clang.yml
  • .github/workflows/CI-package-amd64-centos9-v31-dbg.yml
  • .github/workflows/CI-package-amd64-centos9-v31.yml
  • .github/workflows/CI-package-amd64-centos9.yml
  • .github/workflows/CI-package-amd64-debian12-clang.yml
  • .github/workflows/CI-package-amd64-debian12-dbg.yml
  • .github/workflows/CI-package-amd64-debian12-genai-clang.yml
  • .github/workflows/CI-package-amd64-debian12-genai-dbg.yml
  • .github/workflows/CI-package-amd64-debian12-genai.yml
  • .github/workflows/CI-package-amd64-debian12-v31-clang.yml
  • .github/workflows/CI-package-amd64-debian12-v31-dbg.yml
  • .github/workflows/CI-package-amd64-debian12-v31.yml
  • .github/workflows/CI-package-amd64-debian12.yml
  • .github/workflows/CI-package-amd64-debian13-clang.yml
  • .github/workflows/CI-package-amd64-debian13-dbg.yml
  • .github/workflows/CI-package-amd64-debian13-genai-clang.yml
  • .github/workflows/CI-package-amd64-debian13-genai-dbg.yml
  • .github/workflows/CI-package-amd64-debian13-genai.yml
  • .github/workflows/CI-package-amd64-debian13-v31-clang.yml
  • .github/workflows/CI-package-amd64-debian13-v31-dbg.yml
  • .github/workflows/CI-package-amd64-debian13-v31.yml
  • .github/workflows/CI-package-amd64-debian13.yml
  • .github/workflows/CI-package-amd64-fedora42-clang.yml
  • .github/workflows/CI-package-amd64-fedora42-dbg.yml
  • .github/workflows/CI-package-amd64-fedora42-genai-clang.yml
  • .github/workflows/CI-package-amd64-fedora42-genai-dbg.yml
  • .github/workflows/CI-package-amd64-fedora42-genai.yml
  • .github/workflows/CI-package-amd64-fedora42-v31-clang.yml
  • .github/workflows/CI-package-amd64-fedora42-v31-dbg.yml
  • .github/workflows/CI-package-amd64-fedora42-v31.yml
  • .github/workflows/CI-package-amd64-fedora42.yml
  • .github/workflows/CI-package-amd64-fedora43-clang.yml
  • .github/workflows/CI-package-amd64-fedora43-dbg.yml
  • .github/workflows/CI-package-amd64-fedora43-genai-clang.yml
  • .github/workflows/CI-package-amd64-fedora43-genai-dbg.yml
  • .github/workflows/CI-package-amd64-fedora43-genai.yml
  • .github/workflows/CI-package-amd64-fedora43-v31-clang.yml
  • .github/workflows/CI-package-amd64-fedora43-v31-dbg.yml
  • .github/workflows/CI-package-amd64-fedora43-v31.yml
  • .github/workflows/CI-package-amd64-fedora43.yml
  • .github/workflows/CI-package-amd64-opensuse15-clang.yml
  • .github/workflows/CI-package-amd64-opensuse15-dbg.yml
  • .github/workflows/CI-package-amd64-opensuse15-genai-clang.yml
  • .github/workflows/CI-package-amd64-opensuse15-genai-dbg.yml
  • .github/workflows/CI-package-amd64-opensuse15-genai.yml
  • .github/workflows/CI-package-amd64-opensuse15-v31-clang.yml
  • .github/workflows/CI-package-amd64-opensuse15-v31-dbg.yml
  • .github/workflows/CI-package-amd64-opensuse15-v31.yml
  • .github/workflows/CI-package-amd64-opensuse15.yml
  • .github/workflows/CI-package-amd64-opensuse16-clang.yml
  • .github/workflows/CI-package-amd64-opensuse16-dbg.yml
  • .github/workflows/CI-package-amd64-opensuse16-genai-clang.yml
  • .github/workflows/CI-package-amd64-opensuse16-genai-dbg.yml
  • .github/workflows/CI-package-amd64-opensuse16-genai.yml
  • .github/workflows/CI-package-amd64-opensuse16-v31-clang.yml
  • .github/workflows/CI-package-amd64-opensuse16-v31-dbg.yml
  • .github/workflows/CI-package-amd64-opensuse16-v31.yml
  • .github/workflows/CI-package-amd64-opensuse16.yml
  • .github/workflows/CI-package-amd64-ubuntu22-clang.yml
  • .github/workflows/CI-package-amd64-ubuntu22-dbg.yml
  • .github/workflows/CI-package-amd64-ubuntu22-genai-clang.yml
  • .github/workflows/CI-package-amd64-ubuntu22-genai-dbg.yml
  • .github/workflows/CI-package-amd64-ubuntu22-genai.yml
  • .github/workflows/CI-package-amd64-ubuntu22-v31-clang.yml
  • .github/workflows/CI-package-amd64-ubuntu22-v31-dbg.yml
  • .github/workflows/CI-package-amd64-ubuntu22-v31.yml
  • .github/workflows/CI-package-amd64-ubuntu22.yml
  • .github/workflows/CI-package-amd64-ubuntu24-clang.yml
  • .github/workflows/CI-package-amd64-ubuntu24-dbg.yml
  • .github/workflows/CI-package-amd64-ubuntu24-genai-clang.yml
  • .github/workflows/CI-package-amd64-ubuntu24-genai-dbg.yml
  • .github/workflows/CI-package-amd64-ubuntu24-genai.yml
  • .github/workflows/CI-package-amd64-ubuntu24-v31-clang.yml
  • .github/workflows/CI-package-amd64-ubuntu24-v31-dbg.yml
  • .github/workflows/CI-package-amd64-ubuntu24-v31.yml
  • .github/workflows/CI-package-amd64-ubuntu24.yml
  • .github/workflows/CI-package-arm64-almalinux10-genai.yml
  • .github/workflows/CI-package-arm64-almalinux10-v31.yml
  • .github/workflows/CI-package-arm64-almalinux10.yml
  • .github/workflows/CI-package-arm64-almalinux8-genai.yml
  • .github/workflows/CI-package-arm64-almalinux8-v31.yml
  • .github/workflows/CI-package-arm64-almalinux8.yml
  • .github/workflows/CI-package-arm64-almalinux9-genai.yml
  • .github/workflows/CI-package-arm64-almalinux9-v31.yml
  • .github/workflows/CI-package-arm64-almalinux9.yml
  • .github/workflows/CI-package-arm64-centos10-genai.yml
  • .github/workflows/CI-package-arm64-centos10-v31.yml
  • .github/workflows/CI-package-arm64-centos10.yml
  • .github/workflows/CI-package-arm64-centos9-genai.yml
  • .github/workflows/CI-package-arm64-centos9-v31.yml
  • .github/workflows/CI-package-arm64-centos9.yml
  • .github/workflows/CI-package-arm64-debian12-genai.yml
  • .github/workflows/CI-package-arm64-debian12-v31.yml
  • .github/workflows/CI-package-arm64-debian12.yml
  • .github/workflows/CI-package-arm64-debian13-genai.yml
  • .github/workflows/CI-package-arm64-debian13-v31.yml
  • .github/workflows/CI-package-arm64-debian13.yml
  • .github/workflows/CI-package-arm64-fedora42-genai.yml
  • .github/workflows/CI-package-arm64-fedora42-v31.yml
  • .github/workflows/CI-package-arm64-fedora42.yml
  • .github/workflows/CI-package-arm64-fedora43-genai.yml
  • .github/workflows/CI-package-arm64-fedora43-v31.yml
  • .github/workflows/CI-package-arm64-fedora43.yml
  • .github/workflows/CI-package-arm64-opensuse15-genai.yml
  • .github/workflows/CI-package-arm64-opensuse15-v31.yml
  • .github/workflows/CI-package-arm64-opensuse15.yml
  • .github/workflows/CI-package-arm64-opensuse16-genai.yml
  • .github/workflows/CI-package-arm64-opensuse16-v31.yml
  • .github/workflows/CI-package-arm64-opensuse16.yml
  • .github/workflows/CI-package-arm64-ubuntu22-genai.yml
  • .github/workflows/CI-package-arm64-ubuntu22-v31.yml
  • .github/workflows/CI-package-arm64-ubuntu22.yml
  • .github/workflows/CI-package-arm64-ubuntu24-genai.yml
  • .github/workflows/CI-package-arm64-ubuntu24-v31.yml
  • .github/workflows/CI-package-arm64-ubuntu24.yml

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch v3.0-fix-init-release-race

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@renecannao
renecannao merged commit 0ef544c into v3.0 Apr 24, 2026
4 checks passed
@sonarqubecloud

Copy link
Copy Markdown

@renecannao
renecannao deleted the v3.0-fix-init-release-race branch June 10, 2026 11:17
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