Skip to content

fix(brew): link keg-only-on-macOS formulae on Linux - #13108

Merged
jdx merged 3 commits into
jdx:mainfrom
lil-lon:fix/brew-keg-only-linux
Sep 12, 2026
Merged

jdx merged 3 commits into
jdx:mainfrom
lil-lon:fix/brew-keg-only-linux

Conversation

@lil-lon

@lil-lon lil-lon commented Sep 12, 2026 •

Copy link
Copy Markdown
Contributor

Problem

mise bootstrap packages apply reports formulae like brew:zip / brew:unzip
as installed on Linux, but their commands never appear in <prefix>/bin. The
kegs are poured, yet no symlinks are created because the formulae are marked
keg-only β€” even though these formulae are keg-only only because macOS already
provides them
, and brew itself links them normally on Linux.

Cause

mise deserializes only the keg_only bool from the formulae.brew.sh JSON and
ignores the adjacent keg_only_reason object. link_keg then skips prefix
linking whenever the bool is true, with no OS or reason check. Homebrew's own
KegOnlyReason#applicable? returns false outside macOS for the
:provided_by_macos / :shadowed_by_macos reasons, so brew links these
formulae on Linux while mise does not.

Change

  • Parse keg_only_reason and add Formula::keg_only_for_target(), mirroring
    brew's KegOnlyReason#applicable?: macOS-tied reasons do not apply on other
    OSes; :versioned_formula, free-text reasons, and a missing reason stay
    keg-only everywhere.
  • Use it at both link_keg call sites (bottle pour and source build).
    link_keg itself is unchanged; the policy decision moves to the callers.
  • The tap-formula DSL shim now captures the keg_only reason and emits it in
    the same shape as the API JSON, so tapped formulae behave the same way.
  • Docs: note the platform-dependent keg-only behavior.

macOS behavior is unchanged by construction.

Tests

  • Unit tests for the applicability rules (macOS-tied reasons vs. others).
  • The tap metadata test now asserts the extracted reason.
  • e2e (test_system_install_brew_linux): brew:unzip ends up with
    <prefix>/bin/unzip linked, no .mise-keg-only marker, and a runnable
    binary.

Verification

Passing locally:

  • cargo test --all-features system::packages::brew
  • mise run lint
  • cargo clippy --workspace --all-features --all-targets -- -D warnings

Known limitation

Kegs already installed by earlier mise versions keep their .mise-keg-only
marker and stay unlinked; the repair path intentionally does not consult
formula metadata. They are fixed by the next formula version bump via
mise bootstrap packages upgrade, or by removing the keg and re-running
mise bootstrap packages apply.

AI-assisted β€” Tool: Claude Code; model: anthropic/claude-fable-5; version: unavailable.

Summary by CodeRabbit

  • New Features

    • Homebrew formula handling now accounts for platform-specific keg-only rules.
    • macOS-specific keg-only formulae are linked normally on Linux and other applicable platforms.
    • Formula metadata now records keg-only reasons for more accurate installation behavior.
  • Bug Fixes

    • Linux installations correctly link and run formulae that are only keg-only on macOS.
  • Documentation

    • Clarified platform-specific keg-only behavior in the Homebrew documentation.

Mirror brew's KegOnlyReason#applicable?: keg-only reasons tied to macOS (:provided_by_macos, :shadowed_by_macos) do not apply on other OSes, where brew links these formulae into the prefix.
@coderabbitai

coderabbitai Bot commented Sep 12, 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: 7e4ff34a-9c40-4422-aaa5-a158a05c92b3

πŸ“₯ Commits

Reviewing files that changed from the base of the PR and between a3304cd and 3ede283.

πŸ“’ Files selected for processing (7)
  • docs/bootstrap/packages/brew.md
  • e2e/cli/test_system_install_brew_linux
  • src/system/packages/brew/api.rs
  • src/system/packages/brew/pour.rs
  • src/system/packages/brew/source.rs
  • src/system/packages/brew/tap.rs
  • src/system/packages/brew/tap_formula_metadata.rb

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


πŸ“ Walkthrough

Walkthrough

Homebrew metadata now records keg-only reasons. Linking evaluates those reasons for the target platform, including normal Linux linking for macOS-provided formulae. Tests and documentation cover the new behavior.

Changes

Homebrew keg-only linking

Layer / File(s) Summary
Capture keg-only reasons
src/system/packages/brew/tap_formula_metadata.rb, src/system/packages/brew/api.rs
Formula metadata records and deserializes optional keg-only reasons.
Apply target-specific keg status
src/system/packages/brew/api.rs, src/system/packages/brew/pour.rs, src/system/packages/brew/source.rs
macOS-specific reasons apply only on macOS. Pour and source linking use the target-specific keg-only status.
Validate Linux linking behavior
src/system/packages/brew/api.rs, src/system/packages/brew/tap.rs, e2e/cli/test_system_install_brew_linux, docs/bootstrap/packages/brew.md
Tests and documentation cover metadata extraction, platform-specific reasons, and normal Linux linking for unzip.

Priority: ⬇️ Low

Estimated code review effort: 3 (Moderate) | ~20 minutes

Change: Bug fix

Suggested reviewers: jdx

Sequence Diagram(s)

sequenceDiagram
  participant FormulaMetadata
  participant Formula
  participant pour
  participant link_keg
  FormulaMetadata->>Formula: deserialize keg_only_reason
  Formula->>Formula: keg_only_for_target()
  Formula-->>pour: target-specific keg-only status
  pour->>link_keg: link keg with status
Loading

Merge Risk: βšͺ Minimal Β· up to 3ede2

The platform-aware keg-only behavior is applied consistently to both installation paths and is covered for Linux linking, with no concrete unresolved merge risk identified.

πŸš₯ Pre-merge checks | βœ… 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 47.37% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 19 functions across 5 files. (2 skipped: … Write docstrings for the functions missing them to satisfy the coverage threshold.
βœ… Passed checks (4 passed)
Check name Status Explanation
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.
Description Check βœ… Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check βœ… Passed The title clearly and concisely describes the main change: linking formulae that are keg-only on macOS but should be linked on Linux.
Full details: Docstring Coverage

Explanation

Docstring coverage is 47.37% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 19 functions across 5 files. (2 skipped: 2 unsupported.)

  • Fix all pre-merge checks with AI

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 12, 2026

Copy link
Copy Markdown
Contributor

RetriggerConfidence Score: 5/5

The PR appears safe to merge, with consistent policy application across both installation paths and focused regression coverage.

Summary

  • Applies the target-aware policy to bottle and source installations.
  • Captures equivalent metadata when evaluating tapped formulae.
  • Adds unit, tap-metadata, and Linux end-to-end coverage.
  • Documents the platform-dependent linking behavior.

Reviews (1) Β· Last reviewed commit: "Merge branch 'main' into fix/brew-keg-on..."

@jdx
jdx merged commit 95a4cc0 into jdx:main Sep 12, 2026
46 checks passed
@lil-lon
lil-lon deleted the fix/brew-keg-only-linux branch September 12, 2026 12:11
jdx pushed a commit that referenced this pull request Sep 12, 2026
### πŸš€ Features

- **(bootstrap)** declare Dock applications in order by @azohra in
[#13075](#13075)
- **(brew)** implement `mise bootstrap packages where` for keg-only
packages by @himkt in [#13083](#13083)
- **(cli)** add configurable output truncation by @jdx in
[#13112](#13112)
- **(daemons)** manage project daemons and database presets with
pitchfork by @jdx in [#13085](#13085)
- **(doctor)** add project diagnostic checks by @jdx in
[#13062](#13062)
- **(dotfiles)** infer variant sources from dotfiles root by @jdx in
[#13087](#13087)
- **(fmt)** sort lists whose order carries no meaning by @jrandolf in
[#13058](#13058)
- **(vfox)** add backend tool discovery by @jdx in
[#13111](#13111)

### πŸ› Bug Fixes

- **(asdf)** avoid recursive compatibility dispatch by @jdx in
[#13114](#13114)
- **(bootstrap)** explain macos defaults type differences by @jdx in
[#13096](#13096)
- **(bootstrap)** find ssh and tar on Windows for remote bootstrap by
@JamBalaya56562 in [#13117](#13117)
- **(brew)** link keg-only-on-macOS formulae on Linux by @lil-lon in
[#13108](#13108)
- **(config)** merge monorepo settings across overlays by @jdx in
[#13084](#13084)
- **(config)** scope runtime lockfile lookup to effective tool config by
@nettlesh in [#13042](#13042)
- **(doctor)** align project check roots, dir expansion, schema, and
signals by @jdx in [#13089](#13089)
- **(dotfiles)** honor global yes setting when tracking files by
@nettlesh in [#13072](#13072)
- **(dotfiles)** warn when tracking a symlink without its source by @jdx
in [#13095](#13095)
- **(http)** make shared extraction opt-in by @jdx in
[#13059](#13059)
- **(lockfile)** allow packslip to replace legacy provenance by @jdx in
[#13105](#13105)
- **(nushell)** wrap hide-env in try instead of in-env guard by @i-api
in [#13071](#13071)
- **(packslip)** skip unsupported lockfile targets by @jdx in
[#13102](#13102)
- **(schema)** model dotfiles manifests by @risu729 in
[#12741](#12741)
- **(task)** auto-install tools for run task references by @jdx in
[#13086](#13086)
- **(upgrade)** detect letter-suffixed version updates by @jdx in
[#13119](#13119)
- extract structured flight steps from tap casks by @jdx in
[#13060](#13060)

### πŸ“š Documentation

- **(agents)** write PR titles and descriptions for release notes by
@jdx in [#13090](#13090)
- **(task)** organise task-running guidance by @azohra in
[#13077](#13077)
- diagram tracked dotfile synchronization by @jdx in
[#13069](#13069)
- diagram artifact cache execution by @jdx in
[#13068](#13068)
- diagram tool configuration precedence by @jdx in
[#13067](#13067)
- illustrate bootstrap machine resources by @jdx in
[#13066](#13066)
- illustrate project environment switching by @jdx in
[#13065](#13065)
- prevent landing tabs from shifting content by @jdx in
[#13107](#13107)
- prohibit drive-by AI discussion spam by @jdx in
[#13110](#13110)

### ⚑ Performance

- **(lockfile)** avoid scheduling cached generation targets by @jdx in
[#13101](#13101)
- **(lockfile)** skip generation for current warm installs by @jdx in
[#13103](#13103)
- **(oci)** leave same-repository base layers remote during push by @jdx
in [#13055](#13055)
- **(oci)** cache local tool layers across image builds by @jdx in
[#13056](#13056)

### πŸ“¦οΈ Dependency Updates

- update rust crate aube-registry to v2.2.14 by @renovate[bot] in
[#13015](#13015)
- update communique to v1.4.0 by @jdx in
[#13104](#13104)
- update rattler by @renovate[bot] in
[#12966](#12966)
- update rust crate aube to v2.2.14 by @renovate[bot] in
[#13014](#13014)
- update rust crate usage-lib to v6.9.0 by @renovate[bot] in
[#12892](#12892)
- update rust crate usage-cli to v6.9.0 by @renovate[bot] in
[#12891](#12891)

### πŸ“¦ Registry

- add mpv (conda:mpv) by @i-api in
[#13049](#13049)
- use conda for postgres, redis, and mongodb by @jdx in
[#13061](#13061)
- add agent-browser by @3w36zj6 in
[#13088](#13088)
- add himalaya
([github:pimalaya/himalaya](https://github.com/pimalaya/himalaya)) by
@i-api in [#13091](#13091)
- fix editorconfig-checker 4.0.1 by @jdx in
[#13098](#13098)
- fix mc downloads from MinIO releases by @jdx in
[#13113](#13113)

### Chore

- **(ci)** replace actionlint with zizmor by @jdx in
[#13097](#13097)

### Ci

- increase vfox runner memory by @jdx in
[#13118](#13118)

### New Contributors

- @lil-lon made their first contribution in
[#13108](#13108)

## πŸ“¦ Aqua Registry Updates

### New Packages (1)

- [`getgaal/gaal`](https://github.com/getgaal/gaal)

### Updated Packages (1)

- [`yadm-dev/yadm`](https://github.com/yadm-dev/yadm)
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.

2 participants