Skip to content

Type cask artifact options instead of **options - #24095

Merged
MikeMcQuaid merged 1 commit into
mainfrom
cask-artifact-typed-options
Sep 26, 2026
Merged

MikeMcQuaid merged 1 commit into
mainfrom
cask-artifact-typed-options

Conversation

@dduugg

@dduugg dduugg commented Sep 25, 2026 •

Copy link
Copy Markdown
Member
  • Replace **options in cask artifact phase methods and their callers with explicit keywords so brew typecheck catches mistyped options.
  • Forward typed keywords to uninstall directives and keep command required for uninstall and zap.
  • Type validated stanza options as DirectivesType so assert_valid_keys still names unknown keys.
  • Validate generic artifact keys like other relocated stanzas and explain invalid installer manual: and command_wrapper arguments.

  • Have you followed our Contributing guidelines?
  • Have you checked for other open Pull Requests for the same change?
  • Have you explained what your changes do? Performance claims (e.g. "this is faster") must include brew benchmark results.
  • Have you explained why you'd like these changes included, not just what they do?
  • For bug fixes, have you given step-by-step brew commands to reproduce the bug?
  • Have you written new tests (excluding integration tests)? Here's an example.
  • Have you successfully run brew lgtm (style, typechecking and tests) locally?

  • I did not use AI/LLM to create this PR, or I disclosed the tool/model below and reviewed its output; I did not attribute commits to AI and will answer maintainer questions and review comments myself without AI/LLM.

Claude Code with Opus 5, with local review and testing.


@dduugg
dduugg marked this pull request as ready for review September 25, 2026 22:07
Copilot AI lite review requested due to automatic review settings September 25, 2026 22:07

Copilot AI left a comment

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.

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/鈥婬omebrew/鈥媡est/鈥媍ask/鈥媋rtifact/鈥媔nstaller_spec.rb Tests invalid installer arguments
Library/鈥婬omebrew/鈥媡est/鈥媍ask/鈥媋rtifact/鈥媑eneric_artifact_spec.rb Tests unknown artifact keys
Library/鈥婬omebrew/鈥媡est/鈥媍ask/鈥媋rtifact/鈥媍ommand_wrapper_spec.rb Tests invalid wrapper options
Library/鈥婬omebrew/鈥媍md/鈥媢nlink.rb Passes explicit uninstall options
Library/鈥婬omebrew/鈥媍md/鈥媗ink.rb Passes explicit install options
Library/鈥婬omebrew/鈥媍ask/鈥媔nstaller.rb Forwards typed artifact options
Library/鈥婬omebrew/鈥媍ask/鈥媋rtifact/鈥媧ap.rb Types zap options
Library/鈥婬omebrew/鈥媍ask/鈥媋rtifact/鈥媢ninstall.rb Types uninstall options
Library/鈥婬omebrew/鈥媍ask/鈥媋rtifact/鈥媠ymlinked.rb Types linking phases
Library/鈥婬omebrew/鈥媍ask/鈥媋rtifact/鈥媟elocated.rb Validates relocation options
Library/鈥婬omebrew/鈥媍ask/鈥媋rtifact/鈥媞lplugin.rb Types Quick Look phases
Library/鈥婬omebrew/鈥媍ask/鈥媋rtifact/鈥媝kg.rb Types package options
Library/鈥婬omebrew/鈥媍ask/鈥媋rtifact/鈥媘dimporter.rb Types importer installation
Library/鈥婬omebrew/鈥媍ask/鈥媋rtifact/鈥媔nstaller.rb Validates installer arguments
Library/鈥婬omebrew/鈥媍ask/鈥媋rtifact/鈥媔nstall_steps.rb Types install-step phases
Library/鈥婬omebrew/鈥媍ask/鈥媋rtifact/鈥媑enerated_script.rb Validates generated script options
Library/鈥婬omebrew/鈥媍ask/鈥媋rtifact/鈥媑enerated_completion.rb Types completion phases
Library/鈥婬omebrew/鈥媍ask/鈥媋rtifact/鈥媍ommand_wrapper.rb Validates wrapper options
Library/鈥婬omebrew/鈥媍ask/鈥媋rtifact/鈥媌inary.rb Types binary linking
Library/鈥婬omebrew/鈥媍ask/鈥媋rtifact/鈥媋rtifact.rb Validates generic artifact options
Library/鈥婬omebrew/鈥媍ask/鈥媋rtifact/鈥媋bstract_uninstall.rb Types uninstall dispatch
Library/鈥婬omebrew/鈥媍ask/鈥媋rtifact/鈥媋bstract_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.
@dduugg
dduugg force-pushed the cask-artifact-typed-options branch from 4aa888d to 4e5152d Compare September 25, 2026 22:48
@dduugg

dduugg commented Sep 25, 2026

Copy link
Copy Markdown
Member Author

Copilot's overview note on command_wrapper defaulting false options: fixed in 4e5152d. CommandWrapper.from_args now defaults only nil to {}, so command_wrapper "x", false reaches the requires a hash of options error, and a new spec covers it.

Copilot AI left a comment

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.

Copilot review overview

馃煝 Approval recommended

The explicit keyword contracts align with their callers and the validation changes include focused regression coverage.

Review effort: Balanced
Findings: None

@MikeMcQuaid MikeMcQuaid left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

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 鉂わ笍

@MikeMcQuaid
MikeMcQuaid added this pull request to the merge queue Sep 26, 2026
Merged via the queue into main with commit 827627e Sep 26, 2026
55 of 56 checks passed
@MikeMcQuaid
MikeMcQuaid deleted the cask-artifact-typed-options branch September 26, 2026 00:54
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.

3 participants