Skip to content

feat(release): ship shell completions in the cask#95

Merged
ryanlewis merged 1 commit into
mainfrom
cask-completions
May 30, 2026
Merged

feat(release): ship shell completions in the cask#95
ryanlewis merged 1 commit into
mainfrom
cask-completions

Conversation

@ryanlewis
Copy link
Copy Markdown
Owner

PR 2 of #88 — the release plumbing. Builds on PR 1 (#94), which added the things completions <shell> command.

What

Wire generate_completions_from_executable into the homebrew_casks block so brew install runs things completions bash|zsh|fish at install time and drops the scripts into the Homebrew prefix. No custom executable: — it defaults to the first binary (things), which is correct for our root-level archive layout.

binary "things"
generate_completions_from_executable "things", "completions",
  base_name: "things",
  shell_parameter_format: :arg,
  shells: [:bash, :zsh, :fish]

The non-obvious part: quarantine ordering

Completion generation runs the binary during artifact install, which is before postflight. Our binary is unsigned, so it's Gatekeeper-quarantined on download — that's exactly why the cask already removed the quarantine xattr. But that removal lived in postflight, i.e. after the completion run. Left as-is, generate_completions_from_executable would invoke a still-quarantined binary, Gatekeeper would block it, and zero completion files would be written — silently.

Fix: move the xattr -dr com.apple.quarantine hook from postflightpreflight (hooks.post.installhooks.pre.install). Homebrew runs preflight before artifact install, so the binary is de-quarantined in time. It's strictly safe for runtime too — same removal on the same staged binary, just earlier.

Docs

Flipped the README + internal/skill/SKILL.md wording from "doesn't generate completions yet" to "Homebrew generates these on install." (PR 1 had set the honest interim phrasing.)

Verification

  • goreleaser check passes
  • goreleaser release --snapshot --clean --skip=publish emits Casks/things.rb containing the generate_completions_from_executable block and the preflight de-quarantine
  • go test ./internal/skill/ passes (SKILL.md is embedded)
  • Post-tag (needs a real release): brew install ryanlewis/tap/things (or brew reinstall) writes bash/zsh/fish completion files into the prefix
  • Post-tag: open a fresh shell, things <TAB> shows subcommands

The last two require a published tag, so they're for after merge + /release. The quarantine-ordering fix is the thing to watch in that test — if completions still don't appear, the next lever is no_quarantine or confirming the sandbox can exec the de-quarantined binary.

PR 2 of #88. Wire generate_completions_from_executable into the Homebrew cask
so `brew install` runs `things completions <bash|zsh|fish>` (PR 1) and drops
completion scripts into the Homebrew prefix — zero post-install steps.

Move the quarantine-removal hook from postflight to preflight: completion
generation runs the binary during artifact install, which is *before*
postflight, so the unsigned binary must be de-quarantined first or Gatekeeper
blocks it and no completion files get written. Preflight runs before artifact
install, so the same xattr removal there also keeps runtime `things` working.

Flip the README / SKILL.md wording now that Homebrew generates completions.

Verified: `goreleaser check` passes, and `goreleaser release --snapshot --clean
--skip=publish` emits Casks/things.rb with the generate_completions_from_executable
block (shell_parameter_format: :arg, shells [bash zsh fish]) and a preflight
de-quarantine.

Part of #88
@ryanlewis ryanlewis merged commit 9a59d04 into main May 30, 2026
1 check passed
@ryanlewis ryanlewis deleted the cask-completions branch May 30, 2026 14:52
ryanlewis added a commit that referenced this pull request May 30, 2026
Release notes header for **v0.4.0**, required at the tagged commit by
`.goreleaser.yaml` (`readFile ".github/releases/<tag>.md"`). Merge this,
then the `v0.4.0` tag gets cut.

- Headlines bash/zsh/fish **shell completions** (#94, #95).
- Notes the lipgloss v2 migration (#93) and routine dep updates.
- Folds in the skill-doc changes (#89).

Also removes the orphaned `v0.3.2.md`: v0.3.2 was never tagged and its
only change (#89) is now covered here, so we go straight from v0.3.1 →
v0.4.0.
ryanlewis added a commit that referenced this pull request May 30, 2026
Fixes the completion install broken in v0.4.0. Cuts **v0.4.1**.

## Bug

v0.4.0's cask used `shell_parameter_format: arg`, so Homebrew invoked
`things completions --shell=bash`. But `things completions` takes the
shell as a **positional** arg, so Kong rejected the unknown `--shell`
flag (exit 80) and `brew install` wrote no completion files — with three
"Failed to generate … completions" warnings.

(The preflight quarantine fix from #95 worked — the binary *executed*;
exit 80 is our own arg-parse error, not a Gatekeeper block.)

## Fix

Drop `shell_parameter_format` so Homebrew uses its default: a bare
positional arg, `things completions bash`. The GoReleaser docs claim
`arg` means positional, but Homebrew's `:arg` actually emits
`--shell=<name>`; bare positional is the no-format default.

Generated cask now reads:
```ruby
generate_completions_from_executable "things", "completions",
  base_name: "things",
  shells: [:bash, :zsh, :fish]
```

## Verification

- `goreleaser check` ✅; snapshot cask omits `shell_parameter_format` ✅
- Against the **installed v0.4.0 binary**: `things completions
--shell=bash` → exit 80 (reproduces the failure); `things completions
bash` → exit 0 emitting `complete -C things things`; all of
bash/zsh/fish exit 0 positionally ✅

After v0.4.1 releases: `brew update && brew reinstall
ryanlewis/tap/things` should write the completion files with no
warnings.
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