Skip to content

Fix deprecated postflight stanza in the generated Homebrew cask - #510

Merged
joe4dev merged 1 commit into
mainfrom
devx-1124-homebrew-cask-generated-tap-warning-switch-hookspostinstall
Sep 22, 2026
Merged

joe4dev merged 1 commit into
mainfrom
devx-1124-homebrew-cask-generated-tap-warning-switch-hookspostinstall

Conversation

@joe4dev

@joe4dev joe4dev commented Sep 21, 2026 •

Copy link
Copy Markdown
Member

Motivation

Every brew operation that loads localstack/tap/lstk tells the user to file a bug against our tap:

Warning: Calling `postflight` is deprecated! Use `postflight_steps` instead.
Please report this issue to the localstack/homebrew-tap tap ...
  Casks/lstk.rb:39

Homebrew 7.0 deprecated the raw-Ruby flight blocks (Homebrew/brew#23366), and hooks.post.install renders into one. Reported as localstack/homebrew-tap#7, and still present on the published 1.1.0 cask.

Solution

The replacement option, hooks.post.install_steps, arrives in GoReleaser v2.19 (goreleaser/goreleaser#6873, still open). On the pinned ~> v2 it fails outright:

line 71: field install_steps not found in type config.HomebrewCaskHook

So custom_block writes the stanza instead, escaping {{staged_path}} past GoReleaser's template pass. The step still clears quarantine on the whole staged dir, as #477 made it, so the bundled-extensions binary beside lstk keeps running:

postflight_steps do
  on_macos do
    run "/usr/bin/xattr", args: ["-dr", "com.apple.quarantine", "{{staged_path}}"]
  end
end

On goreleaser v2.18.2 and Homebrew 7.0.4 the cask loads as Cask::Artifact::PostflightSteps, prints no warning, and serializes the step with its on_macos guard.

One cost: custom_block renders first in the cask, so brew style reports 12 Cask/StanzaOrder offences in place of 1 Cask/InstallSteps. Nothing gates on that — the tap has no CI, and brew install never runs rubocop. Moving back under hooks on v2.19 drops both the offences and the escape.

#511 adds a CI guard so this cannot silently regress. It stacks on this branch, since the check fails against main.

Docs

Nothing to document. lstk's commands, flags, env vars and output are unchanged. Users see one difference: brew install --cask localstack/tap/lstk stops printing a deprecation warning. The cask itself is generated and carries a DO-NOT-EDIT header.

Review

Human review advised: this changes the published cask's structure and takes a different route than DEVX-1124 proposed.

Todo

Towards DEVX-1124

🤖 Generated with Claude Code

@joe4dev joe4dev added semver: patch docs: skip Pull request does not require documentation changes labels Sep 21, 2026
@joe4dev
joe4dev force-pushed the devx-1124-homebrew-cask-generated-tap-warning-switch-hookspostinstall branch 2 times, most recently from a26609d to 8eb792c Compare September 21, 2026 16:26
Co-Authored-By: Claude <noreply@anthropic.com>
@joe4dev
joe4dev force-pushed the devx-1124-homebrew-cask-generated-tap-warning-switch-hookspostinstall branch from 8eb792c to e613925 Compare September 21, 2026 16:42
@joe4dev

joe4dev commented Sep 22, 2026

Copy link
Copy Markdown
Member Author

Validation

macOS arm64, goreleaser v2.18.2, Homebrew 7.0.4, quarantine not disabled (HOMEBREW_CASK_OPTS and HOMEBREW_NO_QUARANTINE unset).

The {{staged_path}} escape

The value sits in a | block scalar, so YAML passes it through byte for byte, and GoReleaser evaluates the rendered cask in a second template pass. Three variants through goreleaser release --snapshot:

Arg in .goreleaser.yaml Result
"{{ "{{staged_path}}" }}" (this PR) emits "{{staged_path}}"
"{{staged_path}}" release fails: function "staged_path" not defined
"{{ .StagedPath }}" release fails: map has no entry for key "StagedPath"

Row 2 shows the escape is required, not cosmetic. Row 3 confirms the field #6873 adds does not exist on the pinned ~> v2. Both failures print the pass-2 input containing GoReleaser's own unevaluated desc {{ "…" }}, which is the same escaping trick applied to the same pass.

Generated stanza

cask "lstk" do
  postflight_steps do
    on_macos do
      run "/usr/bin/xattr", args: ["-dr", "com.apple.quarantine", "{{staged_path}}"]
    end
  end

Install

Generated cask pointed at the published v1.1.0 archives — only version and sha256 substituted, and the arm64 sha matches the published tap cask — then installed from a throwaway local tap:

Cask Deprecation warning Quarantine on staged lstk lstk --version
Published (postflight) 3× cleared lstk 1.1.0
Control, hook removed none present (no output — killed)
This PR (postflight_steps) none cleared lstk 1.1.0

The control confirms the step is load-bearing: without it Gatekeeper kills the binary. -dr also recurses as #477 intends — across all 43 staged files the control leaves every one quarantined, and this PR leaves every one clear.

brew style in tap layout: 1 Cask/InstallSteps before, 12 Cask/StanzaOrder after, matching the trade-off described above.

Two follow-ups for #511

  • Assert exactly one postflight_steps. Homebrew silently loads two and runs both, so adding hooks.post.install_steps on v2.19 without dropping custom_block would pass the current check.
  • Pipe the rendered cask through ruby -c. custom_block is unvalidated raw Ruby, so a syntax error would otherwise surface at install time.

@anisaoshafi anisaoshafi left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

🚀

Comment thread .goreleaser.yaml
@joe4dev
joe4dev merged commit a0a8375 into main Sep 22, 2026
19 checks passed
@joe4dev
joe4dev deleted the devx-1124-homebrew-cask-generated-tap-warning-switch-hookspostinstall branch September 22, 2026 10:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

docs: skip Pull request does not require documentation changes semver: patch

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants