-
Notifications
You must be signed in to change notification settings - Fork 9
fix(#111): replace deprecated Homebrew cask postflight stanza #112
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
236b653
58f82f4
199159d
5f0e27f
7d47ecf
65eda5b
d585147
d021604
bd186e2
f3798f8
648e48e
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -57,12 +57,14 @@ homebrew_casks: | |
| homepage: "https://github.com/unbound-force/replicator" | ||
| directory: Casks | ||
| skip_upload: true | ||
| hooks: | ||
| post: | ||
| install: | | ||
| if OS.mac? | ||
| system_command "/usr/bin/xattr", args: ["-dr", "com.apple.quarantine", "#{staged_path}/replicator"] | ||
| end | ||
| # custom_block: native postflight_steps not yet supported by GoReleaser DSL; | ||
| # migrate when available (tracking: goreleaser/goreleaser#6873) | ||
| custom_block: | | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [low] future-maintenance custom_block bypasses GoReleaser native DSL validation for cask stanzas. If GoReleaser later introduces a first-class postflight_steps key, the custom_block will need another migration. There is no current GoReleaser release with native postflight_steps support, so this is the correct approach now, but it should be noted as a maintenance touchpoint. Suggested fix: Add a comment above the custom_block stanza in .goreleaser.yaml (e.g., # custom_block: native postflight_steps not yet supported by GoReleaser DSL; migrate when available) so future maintainers understand the reason for the escape hatch. |
||
| postflight_steps do | ||
| on_macos do | ||
| run "/usr/bin/xattr", args: ["-dr", "com.apple.quarantine", "#{staged_path}/replicator"] | ||
| end | ||
| end | ||
| repository: | ||
| owner: unbound-force | ||
| name: homebrew-tap | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,88 @@ | ||
| ## Context | ||
|
|
||
| Homebrew 7.0 deprecated the `postflight do ... end` cask stanza in favor | ||
| of the declarative `postflight_steps` DSL. The deprecation will become a | ||
| hard error after 2027-12-11. | ||
|
|
||
| GoReleaser generates the Homebrew cask from `.goreleaser.yaml`. The | ||
| `hooks.post.install` key maps to the deprecated `postflight do` block. | ||
| GoReleaser does not yet support native `postflight_steps` generation | ||
| (tracking: goreleaser/goreleaser#6873), but the `custom_block` key injects | ||
| arbitrary Ruby verbatim into the generated cask. | ||
|
|
||
| The existing test infrastructure (`patch-homebrew-cask_test.sh`) validates | ||
| SHA patching logic and fixture integrity but does not exercise the | ||
| goreleaser configuration's cask stanza content. A reversion of the | ||
| `custom_block` to legacy `hooks.post.install` would pass all existing | ||
| tests. | ||
|
|
||
| ## Goals / Non-Goals | ||
|
|
||
| ### Goals | ||
| - Replace `hooks.post.install` with `custom_block` containing | ||
| `postflight_steps` DSL | ||
| - Update the test fixture to match the new DSL | ||
| - Add a deterministic regression test that validates the `custom_block` | ||
| content against three invariants: `postflight_steps do` present, legacy | ||
| `postflight do` absent, `#{staged_path}` Ruby interpolation intact | ||
| - All tests pass without network access or goreleaser binary | ||
|
|
||
| ### Non-Goals | ||
| - Native GoReleaser `postflight_steps` support (blocked on upstream) | ||
| - Changes to quarantine removal behavior | ||
| - Changes to Go source code | ||
| - Changes to the job graph, permissions, or secrets | ||
|
|
||
| ## Decisions | ||
|
|
||
| **D1: Use `custom_block` as the migration vehicle.** GoReleaser's | ||
| `custom_block` injects content verbatim into the generated cask. This is | ||
| the documented escape hatch for DSL features that GoReleaser does not yet | ||
| model natively. A comment above the stanza tracks the upstream issue for | ||
| future migration when native support ships. | ||
|
|
||
| **D2: Validate both the GoReleaser configuration and rendered cask.** The | ||
| configuration assertions fail quickly for accidental DSL changes. CI also | ||
| renders a snapshot with a pinned GoReleaser version and passes the generated | ||
| cask to the regression suite. This verifies that GoReleaser preserves the | ||
| custom block when it produces the release artifact. | ||
|
|
||
| **D3: Use awk for `custom_block` extraction.** The `custom_block` value in | ||
| `.goreleaser.yaml` is a YAML literal block scalar (`|`). Its content starts | ||
| on the line after `custom_block: |` and continues while lines are indented | ||
| deeper than the `custom_block` key. Awk can reliably extract this without | ||
| a YAML parser, avoiding new dependencies. The extraction is validated by | ||
| the assertions that follow it. | ||
|
|
||
| **D4: Three-invariant assertion set.** The regression test checks: | ||
| 1. `postflight_steps do` is present (new DSL adopted) | ||
| 2. `postflight do` without `_steps` is absent (legacy form removed) | ||
| 3. `#{staged_path}` is present (Ruby interpolation, not Go template | ||
| `{{staged_path}}` or literal text) | ||
|
|
||
| These three checks cover the complete DSL transition. If any is violated, | ||
| the cask will either emit deprecation warnings, fail on Homebrew 7.0+, | ||
| or target a nonexistent path at install time. | ||
|
|
||
| **D5: Add to existing test file.** The rendered-cask test is added to | ||
| `patch-homebrew-cask_test.sh` as a separate section. It validates the | ||
| goreleaser config that feeds the patcher's fixture, keeping all cask | ||
| integrity tests in one file and one CI step. | ||
|
|
||
| ## Risks / Trade-offs | ||
|
|
||
| **Risk: `custom_block` extraction relies on YAML indentation.** The awk | ||
| extractor assumes the literal block scalar follows standard YAML | ||
| indentation rules. If `.goreleaser.yaml` is reformatted with non-standard | ||
| indentation, the extraction may fail. This is mitigated by the subsequent | ||
| assertions: if extraction produces garbage, the assertions fail. | ||
|
|
||
| **Risk: GoReleaser changes `custom_block` semantics.** A pinned GoReleaser | ||
| version renders the cask in every pull request, so CI fails if its output no | ||
| longer contains the required DSL. The tracking comment and upstream issue | ||
| reference (goreleaser/goreleaser#6873) flag this for future migration. | ||
|
|
||
| **Trade-off: awk over YAML parser.** A YAML parser would be more robust | ||
| but would require a new dependency (Python/PyYAML in CI or a Go YAML | ||
| library). The awk approach is dependency-free and sufficient for the | ||
| literal block scalar pattern used here. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,101 @@ | ||
| ## Why | ||
|
|
||
| `brew install unbound-force/tap/replicator` emits repeated deprecation | ||
| warnings on Homebrew 7.0+: | ||
|
|
||
| ``` | ||
| Warning: Calling `postflight` is deprecated! Use `postflight_steps` instead. | ||
| ``` | ||
|
|
||
| The `postflight` stanza will become a hard error after 2027-12-11, at which | ||
| point the cask will fail to install entirely. | ||
|
|
||
| The root cause is `.goreleaser.yaml`: the `hooks.post.install` key emits a | ||
| `postflight do` block in the generated cask. Homebrew 7.0 replaced | ||
| `postflight` with the declarative `postflight_steps` DSL. | ||
|
|
||
| GoReleaser does not yet have native `postflight_steps` support (tracking: | ||
| goreleaser/goreleaser#6873). The `custom_block` escape hatch is available | ||
| and injects content verbatim into the generated cask. | ||
|
|
||
| Fixes: https://github.com/unbound-force/replicator/issues/111 | ||
|
|
||
| ## What Changes | ||
|
|
||
| Two changes to the release configuration and one to the test fixture: | ||
|
|
||
| 1. **Replace deprecated hooks.** Remove `hooks.post.install` from | ||
| `.goreleaser.yaml` and replace it with a `custom_block` containing the | ||
| `postflight_steps` DSL (`on_macos do`, `run`, `#{staged_path}`). | ||
| 2. **Update test fixture.** Update | ||
| `.github/scripts/testdata/replicator-v0.5.0.rb` to use | ||
| `postflight_steps do`, `on_macos do`, `run`, and `#{staged_path}`. | ||
| 3. **Add rendered-cask regression test.** Add a deterministic test case | ||
| that extracts the `custom_block` from `.goreleaser.yaml` and verifies | ||
| `postflight_steps do` is present, legacy `postflight do` is absent, | ||
| and `#{staged_path}` remains valid Ruby interpolation. | ||
|
|
||
| ## Capabilities | ||
|
|
||
| ### New Capabilities | ||
| - `postflight_steps cask stanza`: Homebrew cask uses the new declarative | ||
| `postflight_steps` DSL instead of the deprecated `postflight` block. | ||
| - `rendered-cask regression test`: Deterministic test that validates the | ||
| goreleaser configuration emits correct Homebrew syntax without network | ||
| access. | ||
|
|
||
| ### Modified Capabilities | ||
| - `quarantine removal`: Unchanged behavior (still removes | ||
| `com.apple.quarantine` from the replicator binary on macOS); only the | ||
| Homebrew DSL syntax changes. | ||
|
|
||
| ### Removed Capabilities | ||
| - None | ||
|
|
||
| ## Impact | ||
|
|
||
| - **Files**: `.goreleaser.yaml` (replace `hooks.post.install` with | ||
| `custom_block`), `.github/scripts/testdata/replicator-v0.5.0.rb` | ||
| (update fixture stanza syntax), | ||
| `.github/scripts/patch-homebrew-cask_test.sh` (add rendered-cask | ||
| regression test). | ||
| - **Users**: No functional change to quarantine removal behavior. | ||
| Deprecation warnings disappear on Homebrew 7.0+. Future-proofs | ||
| against 2027-12-11 hard error. | ||
| - **No Go source code changes.** Only release configuration and CI test | ||
| infrastructure are affected. | ||
|
|
||
| ## Constitution Alignment | ||
|
|
||
| ### I. Autonomous Collaboration | ||
|
|
||
| **Assessment**: N/A | ||
|
|
||
| No MCP tools, tool output shapes, or inter-agent communication paths are | ||
| affected. This change modifies release configuration only. | ||
|
|
||
| ### II. Composability First | ||
|
|
||
| **Assessment**: PASS | ||
|
|
||
| Replicator MUST be independently installable via Homebrew. A deprecated | ||
| stanza that will become a hard error blocks the distribution channel. | ||
| This change restores clean installation on Homebrew 7.0+ and prevents | ||
| future breakage. | ||
|
|
||
| ### III. Observable Quality | ||
|
|
||
| **Assessment**: PASS | ||
|
|
||
| The regression test deterministically validates the goreleaser | ||
| configuration emits correct Homebrew syntax. If the `custom_block` is | ||
| reverted to legacy `postflight`, the test catches it in pull-request CI. | ||
|
|
||
| ### IV. Testability | ||
|
|
||
| **Assessment**: PASS | ||
|
|
||
| The rendered-cask test extracts the `custom_block` from `.goreleaser.yaml` | ||
| at test time, requires no network access, no goreleaser binary, and no | ||
| Ruby interpreter. It verifies the DSL transition and Ruby interpolation | ||
| syntax deterministically. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[low] code-organization
The
grep -q '#{staged_path}'assertion is technically redundant with thecmp -sfixture comparison above it: if the patched cask is byte-identical to the expected fixture, the grep will always pass. This was deliberately added per the spec's coverage strategy (task 3.2) as a self-documenting canary for the#{staged_path}invariant.