diff --git a/.goreleaser.yml b/.goreleaser.yml index 559a9f67..fb2c5a13 100644 --- a/.goreleaser.yml +++ b/.goreleaser.yml @@ -65,12 +65,24 @@ homebrew_casks: token: "{{ .Env.HOMEBREW_TAP_TOKEN }}" homepage: "https://github.com/mnemon-dev/mnemon" description: "Persistent memory and durable agency for LLM agents" - hooks: - post: - install: | - if OS.mac? - system_command "/usr/bin/xattr", args: ["-dr", "com.apple.quarantine", "#{staged_path}/mnemon"] - end + # The binary is ad hoc/linker-signed only (not notarized), so the cask + # download carries com.apple.quarantine and Gatekeeper kills the first + # launch. Strip the attribute from the staged binary so the user needs no + # manual step. + # + # `hooks.post.install` renders a `postflight do ... end` block, which + # Homebrew deprecates in favor of the declarative `postflight_steps` DSL + # (goreleaser/goreleaser#6870). Until GoReleaser ships a steps-aware hook + # (goreleaser/goreleaser#6873), emit the stanza through `custom_block`. + # The `{{ "{{staged_path}}" }}` quoting escapes GoReleaser's own template + # pass so Homebrew's `{{staged_path}}` install-steps token survives into + # the generated cask. + custom_block: | + postflight_steps do + on_macos do + run "/usr/bin/xattr", args: ["-dr", "com.apple.quarantine", "{{ "{{staged_path}}" }}/mnemon"] + end + end release: github: diff --git a/CHANGELOG.md b/CHANGELOG.md index ac722ebd..a620d7a0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -53,6 +53,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/). hook registry, but its current local Agent V2 turn path does not dispatch the user-prompt lifecycle event needed for reliable automatic recall. +### Fixed + +- The generated Homebrew cask no longer emits the deprecated `postflight` + stanza. `brew` commands that load the cask printed "Calling `postflight` is + deprecated! Use `postflight_steps` instead." on every invocation. The + quarantine strip now runs through the declarative `postflight_steps` DSL. + ## [0.2.7] - 2026-09-01 ### Fixed diff --git a/test/mnemond/architecture/release_distribution_test.go b/test/mnemond/architecture/release_distribution_test.go index 6dfde2e9..eaa7a462 100644 --- a/test/mnemond/architecture/release_distribution_test.go +++ b/test/mnemond/architecture/release_distribution_test.go @@ -4,6 +4,7 @@ import ( "os" "path/filepath" "slices" + "strings" "testing" "go.yaml.in/yaml/v3" @@ -68,3 +69,46 @@ func TestReleaseDistributionPublishesWindowsArchives(t *testing.T) { windows.GOOS, windows.Formats) } } + +func TestReleaseCaskEmitsPostflightSteps(t *testing.T) { + root := repositoryRoot(t) + raw, err := os.ReadFile(filepath.Join(root, ".goreleaser.yml")) + if err != nil { + t.Fatal(err) + } + + var config struct { + Casks []struct { + Name string `yaml:"name"` + CustomBlock string `yaml:"custom_block"` + Hooks struct { + Post struct { + Install string `yaml:"install"` + } `yaml:"post"` + } `yaml:"hooks"` + } `yaml:"homebrew_casks"` + } + if err := yaml.Unmarshal(raw, &config); err != nil { + t.Fatalf("parse .goreleaser.yml: %v", err) + } + + if len(config.Casks) != 1 { + t.Fatalf("homebrew casks = %d, want one", len(config.Casks)) + } + cask := config.Casks[0] + + // hooks.post.install renders Homebrew's deprecated `postflight` stanza + // (goreleaser/goreleaser#6870); the quarantine strip must live in + // custom_block as `postflight_steps` until a steps-aware hook ships. + if cask.Hooks.Post.Install != "" { + t.Fatalf("homebrew cask still uses hooks.post.install, which emits the deprecated postflight stanza") + } + for _, want := range []string{"postflight_steps", "on_macos", "/usr/bin/xattr", `{{ "{{staged_path}}" }}`} { + if !strings.Contains(cask.CustomBlock, want) { + t.Fatalf("homebrew cask custom_block is missing %q; got:\n%s", want, cask.CustomBlock) + } + } + if strings.Contains(cask.CustomBlock, "postflight do") { + t.Fatalf("homebrew cask custom_block still emits deprecated postflight:\n%s", cask.CustomBlock) + } +}