Skip to content

fix(brew): infer formula version from the GitHub release tag path - #13327

Draft
waynehoover wants to merge 3 commits into
jdx:mainfrom
waynehoover:fix/formula-version-from-url-path
Draft

waynehoover wants to merge 3 commits into
jdx:mainfrom
waynehoover:fix/formula-version-from-url-path

Conversation

@waynehoover

@waynehoover waynehoover commented Sep 17, 2026

Copy link
Copy Markdown
Contributor

The problem

The tap formula shim infers a version from the basename of the stable URL only. A GitHub release asset is routinely named for its platform rather than its version, so those formulae fail outright:

could not infer formula version; add an explicit version declaration (RuntimeError)

goku is the case I hit. Its stable URL is:

https://github.com/yqrashawn/GokuRakuJoudo/releases/download/v0.8.0/goku-arm.zip

File.basename gives goku-arm, which contains no version. The version is in the tag path segment immediately before it.

The fix

Port Homebrew's GitHub releases URL parser and try it before the basename pattern, which is the order Homebrew itself uses:

# Library/Homebrew/version.rb, VERSION_PARSERS
# e.g. `https://github.com/foo/bar/releases/download/v1.2/foo-1.2.0.tar.gz`
UrlParser.new(%r{github\.com/.+/releases/download/(?:[rvV]_?)?(#{NUMERIC_WITH_DOTS})/}),

The ordering is not incidental. It also fixes a second, quieter bug: when a filename carries a partial version followed by a platform suffix, the basename pattern over-captures the suffix. apfel-1.10.0-arm64-macos.tar.gz was yielding 1.10.0-arm64-macos as the version string. Those formulae did not error, they just installed under a wrong version.

Verification

Ran the shim against all 253 tap formulae installed on this machine, before and after:

count
unchanged 244
newly resolving (goku) 1
version corrected 8
newly broken 0

The 8 corrected are apfel, apfel-gui, apfel-run, apfel-tag, auge, bgbgone, ohr, translate, each going from <version>-arm64-macos to <version>.

All 9 changed formulae were then cross-checked against Homebrew's own Version.detect on the same URL, and every one now agrees exactly. Cases covered include bare tags with no prefix, v/V/r prefixes, plain tarballs, and /archive/refs/tags/ URLs (both unchanged), plus a URL with no version anywhere (still nil, still raises).

Deliberately not covered

This ports one of Homebrew's parsers, not all of them. hid_bootloader_cli still cannot be inferred because its tag is LUFA-210130, which is not numeric-with-dots, and it needs a different parser.

The other remaining failures in that sweep are unrelated to version inference. They are two separate shim gaps, in the same family as #13053 and #13163:

  • uninitialized constant Language from include Language::Python::Virtualenv (qmk, apfel-mcp)
  • uninitialized constant CurlDownloadStrategy and require "download_strategy" (acli, ecctl, and the kodehealth tap)

To be explicit, since these are easy to conflate: this PR does not fix qmk. I am happy to send the Language::* shim as a follow-up.

Summary by CodeRabbit

  • Bug Fixes
    • Improved version detection for software downloaded from GitHub release URLs.
    • Correctly identifies versions when filenames omit the version or include only a partial version before platform details.
    • Recognizes versions from GitHub release tag paths, including common r and v prefixes.
    • Preserves explicit version declarations when provided.
    • Retains filename-based detection for other download sources, improving package metadata accuracy without affecting unrelated formats.

The tap formula shim inferred a version from the download URL's
basename only, so a release asset named for its platform rather than
its version failed outright:

    could not infer formula version; add an explicit version declaration

goku is the reported case. Its stable URL ends in goku-arm.zip, which
carries no version at all, while the tag segment immediately before it
does.

Port Homebrew's GitHub releases URL parser and try it before the
basename pattern, which is also the order Homebrew uses in
VERSION_PARSERS (Library/Homebrew/version.rb). The order matters
independently of the missing-version case: when a filename carries a
partial version followed by a platform suffix, the basename pattern
over-captures it, so apfel-1.10.0-arm64-macos.tar.gz was yielding
1.10.0-arm64-macos as the version.

Verified against the 253 tap formulae installed locally: 244 unchanged,
goku newly resolves, 8 formulae corrected from a platform-suffixed
version string to the bare version, 0 regressions. All 9 now agree
exactly with Homebrew's own Version.detect on the same URL.
@coderabbitai

coderabbitai Bot commented Sep 17, 2026

Copy link
Copy Markdown
Contributor

Review Change StackReview Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository YAML (base), Central YAML (inherited), Organization UI (inherited)

Review profile: CHILL

Plan: Advanced

Run ID: 03837381-49c1-494b-a507-82146710ec19

📥 Commits

Reviewing files that changed from the base of the PR and between 6a04725 and d39a3a5.

📒 Files selected for processing (1)
  • src/system/packages/brew/tap.rs
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/system/packages/brew/tap.rs

Included review availability: Your plan provides up to 10 included reviews per hour; 4 remain after this review.


📝 Walkthrough

Walkthrough

Changes

GitHub release version inference

Layer / File(s) Summary
Release URL version extraction
src/system/packages/brew/tap_formula_metadata.rb
inferred_version checks GitHub release URL paths before archive basenames. It retains basename extraction as the fallback.
Version inference validation
src/system/packages/brew/tap.rs
Tests cover release tag prefixes, platform and partial filename suffixes, non-release URL fallback, and explicit version precedence. A metadata shim helper supports these tests.

Priority: ⬇️ Low

Estimated code review effort: 2 (Simple) | ~10 minutes

Change: Bug fix

Merge Risk: ⚪ Minimal · up to d39a3

The version inference change preserves explicit versions and fallback behavior while covering release-tag versions absent from asset names. No actionable merge-blocking risk remains.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the main change: inferring Brew formula versions from GitHub release tag paths.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 8 functions across 2 files.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

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.

@greptile-apps

greptile-apps Bot commented Sep 17, 2026

Copy link
Copy Markdown
Contributor

RetriggerConfidence Score: 5/5

The PR appears safe to merge, with the previously requested regression coverage now present and no new issues introduced since the prior review.

Findings

  1. P2 New inference lacks tests

Summary

The PR aligns formula version inference with Homebrew by preferring numeric GitHub release tags over asset filenames.

  • Adds GitHub release-tag path parsing with support for bare, r, v, and V prefixes.
  • Preserves basename inference for non-release URLs and explicit formula versions.
  • Adds regression coverage for platform-named assets, suffix precedence, prefixes, fallbacks, and explicit overrides.
  • Changes since the previous review only reformat two test expressions.

Reviews (3) · Last reviewed commit: "style: cargo fmt"

Comment thread src/system/packages/brew/tap_formula_metadata.rb
Comment on lines +240 to +252
def version_from_url_path(url)
match = url.to_s.match(GITHUB_RELEASE_URL)
match && match[1]
end

def version_from_basename(url)
basename = File.basename(url.to_s).sub(/\.(tar\.(gz|xz|bz2|zst)|tgz|txz|zip|gz)\z/i, "")
match = basename.match(/(?:^|[-_v])([0-9]+(?:\.[0-9A-Za-z]+)+(?:[-_.][0-9A-Za-z]+)*)/)
match && match[1]
end

def inferred_version(url)
version_from_url_path(url) || version_from_basename(url)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 New inference lacks tests

The existing metadata test declares an explicit version, so it bypasses this new path parser and its precedence over basename inference. Without focused cases for platform-only filenames, supported tag prefixes, and meaningful filename suffixes, later regex changes could silently reintroduce incorrect version inference. Adding regression coverage would protect the behavior introduced here.

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed, and done. Pushed infers_version_from_github_release_tag_path in tap.rs, which uses the same shim-invocation path as the existing extracts_formula_metadata_without_homebrew test but with formulae that declare no version, so the URL heuristics are actually exercised.

Covered: a platform-named asset with no version in the filename, a filename carrying a partial version plus a platform suffix, a filename with a trailing -1, the bare/r/v/V tag prefixes, a non-release URL still reading the filename, and an explicit version still winning over both. Every expectation matches what Homebrew's own Version.detect returns for the same URL.

@jdx
jdx marked this pull request as draft September 17, 2026 20:46
The existing metadata test declares an explicit version, so it never
exercises either URL heuristic. Add cases that pin them directly:

  - a platform-named asset whose filename has no version at all
  - a filename carrying a partial version plus a platform suffix,
    where reading the basename yields "1.10.0-arm64-macos"
  - a filename with a trailing "-1", which Homebrew also discards once
    a numeric tag is present
  - the bare, r, v and V tag prefixes
  - a non-release URL, which still reads the filename
  - an explicit version, which still wins over both

Every expectation matches what Homebrew's own Version.detect returns
for the same URL.
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