Repository navigation
fix(brew): support cask completion stanzas, system_command, and elevated artifact links - #11273
Conversation
…ted artifact links Fixes the remaining failures installing the docker-desktop cask reported in #11168: - The cask lifecycle shim rejected any cask using bash_completion, zsh_completion, fish_completion, or manpage stanzas because they hit method_missing while evaluating the DSL to reach preflight/postflight blocks. These artifacts are linked natively by Rust, so the shim now parses them as no-ops. - Lifecycle hooks calling system_command (e.g. docker-desktop's postflight kubectl symlink) failed for the same reason. The shim now implements system_command with args:/sudo:/env:/must_succeed:/print_stdout:/input:/ chdir: support. Elevation follows mise's sudo policy, passed down from Rust via MISE_BREW_CASK_SUDO (interactive/noninteractive/deny), so it never prompts without a TTY and respects system_packages.sudo. - Linking binary/completion artifacts into root-owned directories (e.g. /usr/local/bin on Apple Silicon, where docker-desktop hardcodes absolute targets) failed with EACCES. Artifact target mutations now retry through the controlled sudo path when they hit a permission error, matching Homebrew's behavior of elevating its cask ln/mkdir/rm/mv calls. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
📝 WalkthroughWalkthroughCask lifecycle hooks now execute system commands with captured results and configurable sudo behavior. Rust cask artifact linking and transaction cleanup retry permission-denied filesystem operations through sudo-aware helpers, with completion and command execution tests expanded. ChangesCask elevation flow
Estimated code review effort: 3 (Moderate) | ~25 minutes Sequence Diagram(s)sequenceDiagram
participant CaskHook
participant CaskContext
participant Open3
participant ArtifactLinkTransaction
CaskHook->>CaskContext: load hook with MISE_BREW_CASK_SUDO
CaskContext->>Open3: execute system_command
Open3-->>CaskContext: return command output and status
CaskHook->>ArtifactLinkTransaction: link and manage cask artifacts
ArtifactLinkTransaction-->>CaskHook: retry denied filesystem mutations with sudo
Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
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. Comment |
Greptile SummaryExtends Homebrew cask installation support.
Confidence Score: 5/5The PR appears safe to merge with no eligible blocking failures identified in this follow-up review. No blocking failure remains. Important Files Changed
Reviews (2): Last reviewed commit: "fix(brew): force argv execution in cask ..." | Re-trigger Greptile |
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@src/system/packages/brew/cask_shim.rb`:
- Around line 326-333: Update the Open3.capture3 invocation in the
system_command execution flow to force argv-based execution when args is empty
and sudo is not applied, passing the executable as separate argv elements rather
than a single command string. Preserve the existing sudo_argv transformation and
option handling for elevated or multi-argument commands.
In `@src/system/sudo.rs`:
- Around line 53-59: Update the elevation-mode logic associated with the
documented helper-subprocess policy to base “interactive” on available stdin or
a controlling password TTY, rather than console::user_attended_stderr() alone.
When prompting is not demonstrably safe, return “noninteractive” so callers use
sudo -n; preserve “deny” when elevation is disabled or sudo is unavailable.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Central YAML (base), Organization UI (inherited)
Review profile: CHILL
Plan: Pro Plus
Run ID: 8010ea77-1e7a-47c8-b763-5f3329ce7fdb
📒 Files selected for processing (3)
src/system/packages/brew/cask.rssrc/system/packages/brew/cask_shim.rbsrc/system/sudo.rs
A single-element argv passed to Open3.capture3 is treated as a shell command line, breaking executables whose path contains spaces and inviting shell interpretation. Pass [argv[0], argv[0]] to force argv execution regardless of argument count. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Hyperfine Performance
|
| Command | Mean [ms] | Min [ms] | Max [ms] | Relative |
|---|---|---|---|---|
mise-2026.7.13 x -- echo |
20.4 ± 1.3 | 18.0 | 28.6 | 1.00 |
mise x -- echo |
22.1 ± 2.2 | 19.6 | 53.1 | 1.08 ± 0.13 |
mise env
| Command | Mean [ms] | Min [ms] | Max [ms] | Relative |
|---|---|---|---|---|
mise-2026.7.13 env |
18.4 ± 1.0 | 16.3 | 27.6 | 1.00 |
mise env |
20.1 ± 1.4 | 17.7 | 30.3 | 1.09 ± 0.10 |
mise hook-env
| Command | Mean [ms] | Min [ms] | Max [ms] | Relative |
|---|---|---|---|---|
mise-2026.7.13 hook-env |
19.6 ± 1.4 | 17.4 | 28.6 | 1.00 |
mise hook-env |
20.7 ± 1.2 | 18.4 | 29.3 | 1.06 ± 0.10 |
mise ls
| Command | Mean [ms] | Min [ms] | Max [ms] | Relative |
|---|---|---|---|---|
mise-2026.7.13 ls |
16.4 ± 0.8 | 14.7 | 22.1 | 1.00 |
mise ls |
17.8 ± 0.9 | 16.0 | 25.6 | 1.08 ± 0.08 |
xtasks/test/perf
| Command | mise-2026.7.13 | mise | Variance |
|---|---|---|---|
| install (cached) | 162ms | 172ms | -5% |
| ls (cached) | 59ms | 61ms | -3% |
| bin-paths (cached) | 60ms | 62ms | -3% |
| task-ls (cached) | 127ms | 130ms | -2% |
Fixes the two remaining failures installing the
docker-desktopcask from #11168 (after #11174 and #11219).1. Cask shim rejected completion stanzas
The lifecycle shim evaluates the entire cask DSL to reach
preflight/postflightblocks, but had no stubs forbash_completion,zsh_completion,fish_completion, ormanpage, so any cask using them died inmethod_missing:These artifacts are linked natively by the Rust side, so the shim now parses them as no-ops (same as
app/binary/pkg).2. Cask shim had no
system_commanddocker-desktop's
postflight(anduninstall_postflight) callsystem_command, e.g.:The shim now implements
system_command(mirroring Homebrew'sSystemCommand.run!) withargs:,sudo:,env:,must_succeed:,print_stdout:/print_stderr:/verbose:,input:, andchdir:; unknown options still fail loudly. Elevation follows mise's sudo policy, passed down from Rust viaMISE_BREW_CASK_SUDO(interactive/noninteractive/deny), so it respectssystem_packages.sudoand never hangs on a password prompt without a TTY.3. Artifact links into root-owned dirs failed with EACCES
docker-desktop hardcodes absolute binary targets under
/usr/local(/usr/local/bin/docker,/usr/local/cli-plugins/docker-compose, …). On Apple Silicon/usr/local/binis typically owned byroot:wheel, so backing up the existing target and creating the new symlink failed:Homebrew elevates its cask
ln/mkdir/rm/mvcalls when the target directory is not writable; mise now does the same: artifact-target mutations (link transaction backups/rollback/commit, binary/completion symlinks, obsolete-link removal) retry through the controlledsudo::runpath on permission errors.Testing
postflight+system_commandsymlink + result object), sudo-denied error path, failed-command error path. Pass under macOS system ruby 2.6 and Homebrew portable-ruby 4.0.6 (the interpreter mise actually selects).mise bootstrap packages apply -y brew-cask:docker-desktopwith the real cask now downloads, extracts, installsDocker.app, and runs the real postflight through portable-ruby 4.0.6 successfully. Binary linking into root-owned/usr/local/bincorrectly escalates; in a non-TTY session it fails cleanly with the copy-pasteable command (sudo mv -f -- /usr/local/bin/docker …) instead of a raw EACCES. On an interactive terminal (the reporter's setup, where the fix(brew): remove protected cask app backups #11219sudo chownprompt already worked via Touch ID) the same path prompts and proceeds.🤖 Generated with Claude Code
Note
Medium Risk
Changes run sudo-backed file mutations and lifecycle hooks on system paths; behavior is gated by system_packages.sudo and TTY policy, but mis-elevation or symlink targets could still affect the host install layout.
Overview
Improves brew-cask installs for casks like docker-desktop by extending the Ruby lifecycle shim and retrying root-owned artifact paths with mise’s existing sudo policy.
The cask shim now treats
bash_completion,zsh_completion,fish_completion, andmanpageas parse-only no-ops (Rust still links completions), and addssystem_commandwith argv execution, optionalsudo:, and elevation driven byMISE_BREW_CASK_SUDO(interactive/noninteractive/deny) from newsudo::subprocess_mode().On the Rust side, binary/completion symlinks and link-transaction mkdir / ln / mv / rm retry through
sudo::runon permission errors, matching Homebrew when targets live under directories such as/usr/local/bin. Unit tests cover completion +system_commandpostflight, denied sudo, and failed commands.Reviewed by Cursor Bugbot for commit bffa4ba. Bugbot is set up for automated code reviews on this repo. Configure here.
Summary by CodeRabbit
New Features
Bug Fixes
Tests