Repository navigation
GitHubReleases: group bottle uploads by release - #24416
Conversation
|
No actionable comments were generated in the recent review.
|
| Layer / File(s) | Summary |
|---|---|
Group uploads and validate release sequencing Library/Homebrew/github_releases.rb, Library/Homebrew/test/github_releases_spec.rb |
upload_bottles groups bottles by lower-cased owner and repository plus tag. It uploads each group’s bottles to one release and publishes the release after its uploads. Specs cover shared releases, upload error propagation, and separation by repository and tag. |
Draft asset replacement Library/Homebrew/github_releases.rb, Library/Homebrew/test/github_releases_spec.rb |
For draft releases, matching existing assets are deleted before replacement, after the local file readability check. Specs cover retrying partial uploads, retaining unrelated assets, published-release conflicts, and missing replacement files. |
Merge Risk: 
Minimal · up to 54d58
-
The previously identified grouping and retry failures are addressed. No actionable merge-blocking risk remains after normal checks.
Pre-merge checks: 
4
-
Full details: Title check
-
Explanation
The title names the main change: bottle uploads are grouped by release, which matches the raw summary (grouping by owner, repository and tag) and the objectives (PR
#24416). The title is specific and concise and avoids vague terms. The 'GitHubReleases' prefix matches the changed class.
-
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.
There was a problem hiding this comment.
Actionable comments posted: 1

Review info
-
Run configuration-
- Source mode: Auto
- Repository: Unavailable
- Branch: Unavailable
- File: No configuration file from this repository applied
- Commit: Unavailable
- Layers: Organization UI
- Review profile: CHILL
- Plan: Advanced
- Run ID:
de08e9aa-98f3-4e77-be66-609303450b22
Files selected for processing: 2-
Library/Homebrew/github_releases.rbLibrary/Homebrew/test/github_releases_spec.rb
Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 9 remain after this review.
-
There was a problem hiding this comment.
🟢 Approval recommended
No active review issues are identified, and the change includes regression coverage for shared-release ordering, upload failures, and release separation.
No open issues 🎉
What changed in this PR
Updates GitHub Release bottle uploads to group formulae sharing a release, ensuring all assets are uploaded before the release is published.
Changes:
- Groups bottles by
root_urland processes each release independently. - Uploads all formula assets before publishing the release.
- Preserves separate handling for repositories and release tags.
- Adds regression coverage for shared releases, upload failures, and release separation.
| File | Description |
|---|---|
Library/Homebrew/test/github_releases_spec.rb |
Tests shared-release ordering, draft preservation after failures, and release separation. |
Library/Homebrew/github_releases.rb |
Groups bottle uploads by release URL and publishes each draft after all associated uploads succeed. |
Review effort: Lite
d1a0eec to
bdf27f7
Compare
There was a problem hiding this comment.
Actionable comments posted: 1

Review info
-
Run configuration-
- Source mode: Auto
- Repository: Unavailable
- Branch: Unavailable
- File: No configuration file from this repository applied
- Commit: Unavailable
- Layers: Organization UI
- Review profile: CHILL
- Plan: Advanced
- Run ID:
3f8ac35a-c5ca-4db8-85dc-dc99c71be4fc
Files selected for processing: 2-
Library/Homebrew/github_releases.rbLibrary/Homebrew/test/github_releases_spec.rb
Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 8 remain after this review.
-
- Upload all formulae sharing a release before publishing it, so immutable releases do not reject the remaining bottle assets. - Leave incomplete uploads as drafts and cover separate repositories and tags in regression tests. - Normalise owner and repository names when grouping release URLs, while preserving case-sensitive tags. - Resume draft uploads by replacing only matching bottle assets, after checking that the local replacements are readable.
bdf27f7 to
54d58b7
Compare
There was a problem hiding this comment.
🔵 Needs a closer look
Because it changes production GitHub Release publishing across shared and separate repositories, maintainer validation of live drafts, asset uploads, and immutable-release behavior is still needed beyond the focused mocks.
No open issues 🎉
Review effort: Lite
Summary
When several formulae share a GitHub Release,
upload_bottlespublishes it after the first formula. Immutable releases then reject the remaining assets.Group bottles by parsed owner, repository and tag so every formula's assets reach the release before it is published. Owner and repository names are normalised to lowercase, following GitHub's API contract. Tag case is preserved. An upload failure leaves that release as a draft. Retrying replaces only matching bottle assets in that draft, including empty assets left by failed uploads. Replacement files are checked for readability before removing existing draft assets. Other draft assets are retained. Different repositories and tags retain separate releases.
Follow-up to #24403 for batches where multiple formulae share a release.
Evidence
Run this from the repository root to reproduce without publishing a real release. The GitHub API methods model the immutable-release restriction:
immutable release rejects beta.bottle.tar.gz.create draft → upload alpha.bottle.tar.gz → upload beta.bottle.tar.gz → publish release.Focused regression examples and full checks:
The shared-release regression was verified to fail before the fix and pass afterwards. The full file passes all nine examples, including existing published-release and leftover-draft behaviour. Global typechecking and style checks pass. The shared-release fixture mixes owner/repository case; separate-release coverage also distinguishes
testfromTest. Failure-then-retry coverage includes an unrelated draft asset and an emptystarterasset, with separate guards for published assets and missing local replacements.Merge Danger
Door: Two-way
The implementation can be reverted. Uploads that fail before completion leave the shared release unpublished.
Blast Radius: Publishing
Affects GitHub Release bottle uploads through
brew pr-uploadandbrew pr-pull.brew benchmarkresults.brewcommands to reproduce the bug?brew lgtm(style, typechecking and tests) locally?AI disclosure: OpenAI Codex (GPT-6) helped draft the implementation, tests and PR description. I reviewed the changes and verified them with the regression checks above.