Repository navigation
Type cask artifact options instead of **options - #24095
Conversation
There was a problem hiding this comment.
Copilot review overview
🔵 Needs a closer look
command_wrapper should default only nil options, so false receives the intended validation error.
Review effort: Lite
Findings: None
What changed in this PR
This PR replaces untyped cask artifact options with explicit typed keywords and strengthens stanza validation.
Changes:
- Types install, uninstall, and zap phase interfaces.
- Validates artifact, installer, and command-wrapper arguments.
- Adds regression tests for invalid arguments.
| File | Summary |
|---|---|
Library/Homebrew/test/cask/artifact/installer_spec.rb |
Tests invalid installer arguments |
Library/Homebrew/test/cask/artifact/generic_artifact_spec.rb |
Tests unknown artifact keys |
Library/Homebrew/test/cask/artifact/command_wrapper_spec.rb |
Tests invalid wrapper options |
Library/Homebrew/cmd/unlink.rb |
Passes explicit uninstall options |
Library/Homebrew/cmd/link.rb |
Passes explicit install options |
Library/Homebrew/cask/installer.rb |
Forwards typed artifact options |
Library/Homebrew/cask/artifact/zap.rb |
Types zap options |
Library/Homebrew/cask/artifact/uninstall.rb |
Types uninstall options |
Library/Homebrew/cask/artifact/symlinked.rb |
Types linking phases |
Library/Homebrew/cask/artifact/relocated.rb |
Validates relocation options |
Library/Homebrew/cask/artifact/qlplugin.rb |
Types Quick Look phases |
Library/Homebrew/cask/artifact/pkg.rb |
Types package options |
Library/Homebrew/cask/artifact/mdimporter.rb |
Types importer installation |
Library/Homebrew/cask/artifact/installer.rb |
Validates installer arguments |
Library/Homebrew/cask/artifact/install_steps.rb |
Types install-step phases |
Library/Homebrew/cask/artifact/generated_script.rb |
Validates generated script options |
Library/Homebrew/cask/artifact/generated_completion.rb |
Types completion phases |
Library/Homebrew/cask/artifact/command_wrapper.rb |
Validates wrapper options |
Library/Homebrew/cask/artifact/binary.rb |
Types binary linking |
Library/Homebrew/cask/artifact/artifact.rb |
Validates generic artifact options |
Library/Homebrew/cask/artifact/abstract_uninstall.rb |
Types uninstall dispatch |
Library/Homebrew/cask/artifact/abstract_flight_block.rb |
Types flight block phases |
💡 Add a code-review agent skill for context-aware, tailored reviews. Learn more in the docs.
- The artifact phase methods took `**options` so that the single `Cask::Installer` call site could pass keywords each artifact ignores. A keyword mistyped there was absorbed by every artifact that splatted, so only the typed `Moved` subclasses caught it. - List the caller's keywords on each `install_phase`, `uninstall_phase`, `post_uninstall_phase` and `zap_phase`, including the ones an artifact does not read: `Library/.rubocop.yml` sets `AllowUnusedKeywordArguments`. - Keep `command` required on the `uninstall` and `zap` phases, which reached it through the splat, so omitting it still raises rather than running the privileged deletions with the default. - Type and forward `dispatch_uninstall_directive`'s keywords. It passed on `verbose` and `skip`, which no `uninstall_*` handler reads, so the handlers keep the `**_kwargs` that `send` dispatches into. - Drop the `options` hashes in `brew link` and `brew unlink` and the conditional `uninstall_options[:quit]`, without which the new signatures are unchecked at those call sites. - Keep `**` where a cask stanza is validated, so that `assert_valid_keys` still names an unknown key, but type its values as `DirectivesType` rather than `T.untyped`. - `Relocated#initialize` passes a target to `super` only when it has one, keeping `to_args` and so the JSON API free of `target: nil`. - `Artifact.from_args` validates and then calls `super` rather than `new`, so the generic `artifact` stanza rejects an unknown key as every other `Relocated` stanza already did. No `artifact` stanza in `homebrew/cask` passes one. - An `installer manual:` that is not a path, and a `command_wrapper` given something other than a hash, now name the stanza argument at fault instead of failing later with `Pathname.new requires a String` or `undefined method 'each_key'`. - An explicit `pkg` `choices: nil` no longer crashes on `nil.empty?`. Any other non-collection value still reaches `installer`, which rejects it as before.
4aa888d to
4e5152d
Compare
|
Copilot's overview note on |
MikeMcQuaid
left a comment
There was a problem hiding this comment.
Thanks, nice work! Should be good to go when 🟢 and a rebase will fix you up (I'll do that for you now).
In general when we fix all these **options uses a RuboCop to prevent them in future would be great ❤️
**optionsin cask artifact phase methods and their callers with explicit keywords sobrew typecheckcatches mistyped options.commandrequired foruninstallandzap.DirectivesTypesoassert_valid_keysstill names unknown keys.artifactkeys like other relocated stanzas and explain invalidinstaller manual:andcommand_wrapperarguments.brew benchmarkresults.brewcommands to reproduce the bug?brew lgtm(style, typechecking and tests) locally?Claude Code with Opus 5, with local review and testing.