Skip to content

fix(release): stop the Homebrew cask's postflight deprecation warning - #27

Merged
ftarasenko merged 2 commits into
masterfrom
claude/sweet-brahmagupta-zfz3zv
Sep 21, 2026
Merged

ftarasenko merged 2 commits into
masterfrom
claude/sweet-brahmagupta-zfz3zv

Conversation

@ftarasenko

Copy link
Copy Markdown
Owner

Every brew command touching the cask printed:

Warning: Calling `postflight` is deprecated! Use `postflight_steps` instead.

The stanza is the cask's quarantine strip, which the unsigned binary needs in order to launch on macOS, so it cannot simply be dropped — and Homebrew deprecations become hard errors a few releases later.

What changed

GoReleaser renders homebrew_casks.hooks.post.install as postflight do … end and cannot emit the *_steps stanzas yet (goreleaser/goreleaser#6870, PR #6873, milestone v2.19.0). It also has no way to emit both spellings, so .goreleaser.yaml now writes the stanza itself through custom_block, and the cask picks one at load time:

steps_dsl = defined?(Homebrew::InstallSteps::DSL) && Homebrew::InstallSteps::DSL
if steps_dsl && steps_dsl.method_defined?(:run) && steps_dsl.method_defined?(:on_macos)
  postflight_steps do
    on_macos do
      run "/usr/bin/xattr",
          args: ["-dr", "com.apple.quarantine", "{{staged_path}}/koc"]
    end
  end
else
  postflight do
    if OS.mac?
      system_command "/usr/bin/xattr",
        args: ["-dr", "com.apple.quarantine", "#{staged_path}/koc"]
    end
  end
end

The cask installs on every Homebrew version and prints a deprecation warning on none.

Why the probe is what it is

Three Homebrew releases matter, and they are not the same one:

Homebrew change
6.0.0 postflight_steps stanza lands
6.0.13 steps DSL gains run / on_macos — the steps this block calls
6.0.16 postflight deprecated (the warning)

So the probe asks Homebrew::InstallSteps::DSL.method_defined?(:run) rather than respond_to?(:postflight_steps): the latter is true on 6.0.0–6.0.12, where the block body would then die. (Cask::DSL#respond_to_missing? returns false, so respond_to? is a sound probe in principle — it just answers the wrong question here.)

Two more details, both spelled out next to the block in .goreleaser.yaml:

  • {{staged_path}} is written escaped as {{ "{{staged_path}}" }} because GoReleaser runs the whole generated cask through its own template engine as a final pass. The legacy branch spells the same path #{staged_path}, since the steps DSL has no Ruby interpolation — that was the point of deprecating postflight.
  • custom_block is injected right after cask "koc" do, so the generated file's stanza order is unconventional. It is still correct: Homebrew orders artifacts by class (Binary before PostflightSteps, per Cask::Artifact::AbstractArtifact.sort_order), never by file position.

Verification

  • goreleaser check clean; cask regenerated with GoReleaser built from source (main, since no released version carries the fix) via a snapshot release — both branches render, {{staged_path}} and #{staged_path} each survive the template pass, ruby -c clean.
  • The emitted block was evaluated against stub DSLs for all three Homebrew generations:
pre-6.0 (no InstallSteps)    picked=postflight         PASS
6.0.0-6.0.12 (no run step)   picked=postflight         PASS
6.0.13+ (run + on_macos)     picked=postflight_steps   PASS
                             run -> ["/usr/bin/xattr", ["-dr", "com.apple.quarantine", "{{staged_path}}/koc"]]

No Go code changes, so the command surface is unchanged and docs/coverage.md needs no update. README and AGENTS.md record the version boundaries and the reasoning.

The tap keeps serving the v0.32.0 cask until a new tag is cut.

🤖 Generated with Claude Code

https://claude.ai/code/session_0122vGrcATX7433WuQ91iLm9


Generated by Claude Code

Homebrew 7.0 deprecated the `postflight` stanza in favour of the
declarative `postflight_steps`, so every `brew` command touching the cask
printed

  Warning: Calling `postflight` is deprecated! Use `postflight_steps` instead.

and Homebrew deprecations become hard errors a few releases later. The
stanza is the cask's quarantine strip, which the unsigned binary needs to
launch on macOS, so it cannot simply be dropped.

GoReleaser generates `postflight` from `homebrew_casks.hooks.post.install`
and cannot emit the `*_steps` stanzas yet (goreleaser/goreleaser#6870,
PR #6873, milestone v2.19.0), so write the stanza directly through
`custom_block` instead. Two details are load-bearing and documented next
to the block: the Homebrew path token is escaped as `{{ "{{staged_path}}" }}`
because GoReleaser runs the whole generated cask through its template
engine as a final pass, and the steps DSL has no Ruby interpolation, so
`run` takes the expanded token as an argument. Placement right after
`cask "koc" do` is safe because Homebrew orders artifacts by class
(Binary before PostflightSteps), not by file position.

Verified by building GoReleaser from source and running a snapshot
release: the generated cask carries `postflight_steps`, the literal
`{{staged_path}}` token survives the template pass, and the file is valid
Ruby.

The cask now requires Homebrew >= 7.0, which README and AGENTS.md note.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0122vGrcATX7433WuQ91iLm9
The previous commit moved the quarantine strip to `postflight_steps`
unconditionally, which silences the deprecation warning but raises on any
Homebrew that predates the stanza. Pick the spelling at load time instead:
`postflight_steps` where it works, the original `postflight` block below
that. The cask now installs on every Homebrew and warns on none.

Three versions matter, and they are three releases apart, which is why the
obvious probe is wrong:

  6.0.0   the postflight_steps stanza lands
  6.0.13  the steps DSL gains the run/on_macos steps the block calls
  6.0.16  postflight is deprecated

So the probe is `Homebrew::InstallSteps::DSL.method_defined?(:run)` rather
than `respond_to?(:postflight_steps)` — the latter is true on 6.0.0–6.0.12,
where the block body would then die. That also corrects the floor the last
commit documented: it is 6.0.13, not 7.0.

Verified by regenerating the cask with GoReleaser built from source (both
branches render, `{{staged_path}}` and `#{staged_path}` each survive the
template pass, `ruby -c` clean) and by evaluating the emitted block against
stub DSLs for all three generations: pre-6.0 and 6.0.0–6.0.12 pick
`postflight`, 6.0.13+ picks `postflight_steps` and reaches `run` with the
expected argv.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0122vGrcATX7433WuQ91iLm9
@ftarasenko
ftarasenko merged commit 8f0507c into master Sep 21, 2026
26 checks passed
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.

2 participants