From 70dabb28489a79e72f98015900a43449d92e2327 Mon Sep 17 00:00:00 2001 From: Rian Stockbower Date: Sun, 20 Sep 2026 17:05:04 -0400 Subject: [PATCH] INT-904: Modernize generated Homebrew install steps --- .github/workflows/test-actions.yml | 4 +- actions/homebrew-alias/action.yml | 18 ++++++--- actions/homebrew-alias/modernize.sh | 41 +++++++++++++++++++++ actions/homebrew-alias/test_modernize.sh | 47 ++++++++++++++++++++++++ 4 files changed, 104 insertions(+), 6 deletions(-) create mode 100644 actions/homebrew-alias/modernize.sh create mode 100644 actions/homebrew-alias/test_modernize.sh diff --git a/.github/workflows/test-actions.yml b/.github/workflows/test-actions.yml index de5a2c7..045a954 100644 --- a/.github/workflows/test-actions.yml +++ b/.github/workflows/test-actions.yml @@ -141,11 +141,13 @@ jobs: - run: bash actions/macos-codesign-setup/test_gate.sh shell: bash - # homebrew alias-cask rendering (token rename, verbatim url/checksum copy). + # Homebrew cask modernization and alias rendering. homebrew-alias: runs-on: ubuntu-latest steps: - uses: actions/checkout@fbc6f3992d24b796d5a048ff273f7fcc4a7b6c09 # v5.1.0 + - run: bash actions/homebrew-alias/test_modernize.sh + shell: bash - run: bash actions/homebrew-alias/test_alias.sh shell: bash diff --git a/actions/homebrew-alias/action.yml b/actions/homebrew-alias/action.yml index 533c678..67a4db2 100644 --- a/actions/homebrew-alias/action.yml +++ b/actions/homebrew-alias/action.yml @@ -1,7 +1,7 @@ name: Homebrew tap publish (canonical + aliases) description: > - Publish the goreleaser-rendered canonical cask plus its manifest-declared - alias casks to the Homebrew tap in ONE commit. goreleaser must run with + Modernize and publish the goreleaser-rendered canonical cask plus its + manifest-declared alias casks to the Homebrew tap in ONE commit. goreleaser must run with skip_upload:true for the cask (asserted by the release preflight) so this step is the single writer — canonical and aliases land atomically. inputs: @@ -41,7 +41,9 @@ runs: run: | set -euo pipefail render="$ACTION_PATH/alias.sh" + modernize="$ACTION_PATH/modernize.sh" [ -f "$render" ] || { echo "::error::alias.sh not found at $render"; exit 1; } + [ -f "$modernize" ] || { echo "::error::modernize.sh not found at $modernize"; exit 1; } # pilot item (a): the canonical cask MUST be present in dist/ — a missing # one means goreleaser didn't render it (skip_upload misconfig or build # gap). Hard-fail rather than push a partial tap. @@ -61,12 +63,18 @@ runs: dest="$tmp/tap/$CASK_DIR" mkdir -p "$dest" - # canonical: verbatim copy - cp "$CANONICAL_FILE" "$dest/${CANONICAL_TOKEN}.rb" + # GoReleaser 2.18 still emits deprecated preflight/postflight stanza + # names. Normalize once, then derive both canonical and aliases from + # the same modern cask so a future release cannot restore warnings. + normalized="$tmp/${CANONICAL_TOKEN}.rb" + bash "$modernize" render "$CANONICAL_FILE" > "$normalized" + + # canonical: normalized copy + cp "$normalized" "$dest/${CANONICAL_TOKEN}.rb" echo "rendered canonical: ${CANONICAL_TOKEN}.rb" # aliases: same artifact, only the cask stanza token renamed for a in $ALIAS_TOKENS; do - bash "$render" render "$CANONICAL_FILE" "$CANONICAL_TOKEN" "$a" > "$dest/${a}.rb" + bash "$render" render "$normalized" "$CANONICAL_TOKEN" "$a" > "$dest/${a}.rb" echo "rendered alias: ${a}.rb" done diff --git a/actions/homebrew-alias/modernize.sh b/actions/homebrew-alias/modernize.sh new file mode 100644 index 0000000..1ffcc3b --- /dev/null +++ b/actions/homebrew-alias/modernize.sh @@ -0,0 +1,41 @@ +#!/usr/bin/env bash +# Rewrite GoReleaser's legacy Homebrew install-step stanzas to the current DSL. +# +# Usage: +# modernize.sh render +# Print the cask with only deprecated install-step block declarations +# renamed. Already-modern casks pass through unchanged. +set -euo pipefail + +render() { + local file="$1" + [ -f "$file" ] || { echo "::error::cask not found: $file" >&2; return 1; } + + awk ' + /^[[:space:]]*preflight[[:space:]]+do[[:space:]]*$/ { + sub(/preflight[[:space:]]+do[[:space:]]*$/, "preflight_steps do") + } + /^[[:space:]]*postflight[[:space:]]+do[[:space:]]*$/ { + sub(/postflight[[:space:]]+do[[:space:]]*$/, "postflight_steps do") + } + /^[[:space:]]*uninstall_preflight[[:space:]]+do[[:space:]]*$/ { + sub(/uninstall_preflight[[:space:]]+do[[:space:]]*$/, "uninstall_preflight_steps do") + } + /^[[:space:]]*uninstall_postflight[[:space:]]+do[[:space:]]*$/ { + sub(/uninstall_postflight[[:space:]]+do[[:space:]]*$/, "uninstall_postflight_steps do") + } + /^[[:space:]]*system_command[[:space:]]+/ { + sub(/system_command[[:space:]]+/, "run ") + } + /"#\{staged_path\}\// { + sub(/"#\{staged_path\}\//, "\"") + sub(/\][[:space:]]*$/, "], base: :staged_path") + } + { print } + ' "$file" +} + +case "${1:-}" in + render) render "${2:-}" ;; + *) echo "usage: modernize.sh render " >&2; exit 2 ;; +esac diff --git a/actions/homebrew-alias/test_modernize.sh b/actions/homebrew-alias/test_modernize.sh new file mode 100644 index 0000000..8767f17 --- /dev/null +++ b/actions/homebrew-alias/test_modernize.sh @@ -0,0 +1,47 @@ +#!/usr/bin/env bash +# Portable unit tests for modernize.sh render. +set -uo pipefail +cd "$(dirname "$0")" +tmp=$(mktemp -d); fails=0 +trap 'rm -rf "$tmp"' EXIT +ok() { echo "ok $1"; } +bad() { echo "FAIL $1"; fails=$((fails+1)); } + +cat > "$tmp/legacy.rb" <<'RB' +cask "example" do + preflight do + system_command "prepare" + end + postflight do + system_command "/usr/bin/xattr", args: ["-dr", "com.apple.quarantine", "#{staged_path}/example"] + end + uninstall_preflight do + system_command "unprepare" + end + uninstall_postflight do + system_command "unfinish" + end + # postflight do must not change inside a comment +end +RB + +out=$(bash modernize.sh render "$tmp/legacy.rb") +for stanza in preflight_steps postflight_steps uninstall_preflight_steps uninstall_postflight_steps; do + echo "$out" | grep -q "^ ${stanza} do$" && ok "$stanza rendered" || bad "$stanza rendered" +done +echo "$out" | grep -q '^ # postflight do must not change inside a comment$' \ + && ok "comment preserved" || bad "comment preserved" +echo "$out" | grep -q 'run "/usr/bin/xattr", args: \["-dr", "com.apple.quarantine", "example"\], base: :staged_path' \ + && ok "command converted to install-step DSL" || bad "command converted to install-step DSL" +echo "$out" | grep -q 'system_command' \ + && bad "legacy command should be absent" || ok "legacy command absent" + +printf '%s\n' "$out" > "$tmp/modern.rb" +rerendered=$(bash modernize.sh render "$tmp/modern.rb") +[ "$out" = "$rerendered" ] && ok "render is idempotent" || bad "render is idempotent" + +bash modernize.sh render "$tmp/missing.rb" >/dev/null 2>&1 \ + && bad "missing file should fail" || ok "missing file fails" + +echo "----" +if [ "$fails" -eq 0 ]; then echo "all modernization tests passed"; else echo "$fails failed"; exit 1; fi