Skip to content

Commit 764e09e

Browse files
authored
chore: migrate Homebrew release flow from GoReleaser brews (#104)
* chore: migrate Homebrew release flow from goreleaser brews * fix review feedback for homebrew workflow scripts
1 parent 44be22f commit 764e09e

6 files changed

Lines changed: 308 additions & 101 deletions

File tree

.github/workflows/release.yml

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,4 +45,35 @@ jobs:
4545
args: release --clean
4646
env:
4747
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
48-
HOMEBREW_TAP_GITHUB_TOKEN: ${{ secrets.HOMEBREW_TAP_GITHUB_TOKEN }}
48+
49+
sync-homebrew-formula:
50+
name: Sync Homebrew Formula Template
51+
runs-on: ubuntu-latest
52+
needs: release
53+
if: ${{ !contains(github.ref_name, '-') }}
54+
steps:
55+
- name: Checkout code
56+
uses: actions/checkout@v4
57+
58+
- name: Sync wtp.rb template to Homebrew tap
59+
run: scripts/sync-homebrew-formula.sh
60+
env:
61+
HOMEBREW_TAP_GITHUB_TOKEN: ${{ secrets.HOMEBREW_TAP_GITHUB_TOKEN }}
62+
TAP_REPO: satococoa/homebrew-tap
63+
FORMULA_FILE: wtp.rb
64+
TARGET_BRANCH: main
65+
66+
bump-homebrew-formula:
67+
name: Bump Homebrew Formula
68+
runs-on: ubuntu-latest
69+
needs: sync-homebrew-formula
70+
if: ${{ !contains(github.ref_name, '-') }}
71+
steps:
72+
- name: Bump Homebrew formula
73+
uses: mislav/bump-homebrew-formula-action@v3
74+
with:
75+
homebrew-tap: satococoa/homebrew-tap
76+
formula-name: wtp
77+
formula-path: wtp.rb
78+
env:
79+
COMMITTER_TOKEN: ${{ secrets.HOMEBREW_TAP_GITHUB_TOKEN }}

.goreleaser.yml

Lines changed: 0 additions & 100 deletions
Original file line numberDiff line numberDiff line change
@@ -68,106 +68,6 @@ changelog:
6868
- title: Others
6969
order: 999
7070

71-
brews:
72-
- name: wtp
73-
repository:
74-
owner: satococoa
75-
name: homebrew-tap
76-
token: "{{ .Env.HOMEBREW_TAP_GITHUB_TOKEN }}"
77-
url_template: "https://github.com/satococoa/wtp/releases/download/{{ .Tag }}/{{ .ArtifactName }}"
78-
download_strategy: CurlDownloadStrategy
79-
commit_author:
80-
name: goreleaserbot
81-
email: bot@goreleaser.com
82-
commit_msg_template: "Brew formula update for {{ .ProjectName }} version {{ .Tag }}"
83-
homepage: "https://github.com/satococoa/wtp"
84-
description: "Worktree Plus - Enhanced worktree management with automated setup and hooks"
85-
license: "MIT"
86-
skip_upload: auto
87-
dependencies:
88-
- name: git
89-
install: |
90-
bin.install "wtp"
91-
92-
(bash_completion/"wtp").write <<~'EOS'
93-
# wtp lazy shell-init for bash (installed via Homebrew)
94-
_wtp_lazy_init() {
95-
if [[ -z "${WTP_SHELL_INIT_DONE:-}" ]]; then
96-
local __wtp_init __wtp_status
97-
__wtp_init="$(command wtp shell-init bash 2>/dev/null)"
98-
__wtp_status=$?
99-
if [[ $__wtp_status -ne 0 || -z "$__wtp_init" ]]; then
100-
__wtp_init="$(command wtp completion bash 2>/dev/null)"
101-
__wtp_status=$?
102-
fi
103-
if [[ $__wtp_status -ne 0 || -z "$__wtp_init" ]]; then
104-
return 124
105-
fi
106-
107-
eval "$__wtp_init"
108-
export WTP_SHELL_INIT_DONE=1
109-
fi
110-
111-
if declare -F __wtp_bash_autocomplete >/dev/null 2>&1; then
112-
__wtp_bash_autocomplete "$@"
113-
elif declare -F _wtp >/dev/null 2>&1; then
114-
_wtp "$@"
115-
fi
116-
}
117-
118-
complete -o bashdefault -o default -o nospace -F _wtp_lazy_init wtp
119-
EOS
120-
121-
(zsh_completion/"_wtp").write <<~'EOS'
122-
#compdef wtp
123-
124-
_wtp_lazy_init() {
125-
if [[ -z ${WTP_SHELL_INIT_DONE-} ]]; then
126-
local __wtp_init __wtp_status
127-
__wtp_init="$(command wtp shell-init zsh 2>/dev/null)"
128-
__wtp_status=$?
129-
if [[ $__wtp_status -ne 0 || -z "$__wtp_init" ]]; then
130-
__wtp_init="$(command wtp completion zsh 2>/dev/null)"
131-
__wtp_status=$?
132-
fi
133-
if [[ $__wtp_status -ne 0 || -z "$__wtp_init" ]]; then
134-
return 1
135-
fi
136-
137-
eval "$__wtp_init"
138-
export WTP_SHELL_INIT_DONE=1
139-
fi
140-
141-
if typeset -f _wtp >/dev/null 2>&1; then
142-
_wtp "$@"
143-
fi
144-
}
145-
146-
compdef _wtp_lazy_init wtp
147-
EOS
148-
149-
(fish_completion/"wtp.fish").write <<~'EOS'
150-
function __wtp_lazy_setup --on-event fish_prompt --description 'Lazy shell-init for wtp (Homebrew)'
151-
functions -e __wtp_lazy_setup
152-
153-
if not set -q WTP_SHELL_INIT_DONE
154-
command wtp shell-init fish ^/dev/null | source
155-
set -l __wtp_status $status
156-
if test $__wtp_status -ne 0
157-
command wtp completion fish ^/dev/null | source
158-
set __wtp_status $status
159-
end
160-
if test $__wtp_status -ne 0
161-
return
162-
end
163-
164-
set -gx WTP_SHELL_INIT_DONE 1
165-
end
166-
end
167-
EOS
168-
test: |
169-
system "#{bin}/wtp", "--help"
170-
17171
release:
17272
github:
17373
owner: satococoa

docs/homebrew-release.md

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
# Homebrew Release Flow
2+
3+
`wtp` Homebrew distribution is managed without GoReleaser `brews`.
4+
5+
## Source of Truth
6+
7+
- Formula template: `packaging/homebrew/wtp.rb.tmpl`
8+
- Render script: `scripts/render-homebrew-formula.sh`
9+
- Sync script: `scripts/sync-homebrew-formula.sh`
10+
11+
## Release Workflow
12+
13+
On tag push (`v*`):
14+
15+
1. GoReleaser publishes release assets and packages.
16+
2. `sync-homebrew-formula.sh` syncs formula structure to `satococoa/homebrew-tap`
17+
while preserving existing `version` and `sha256`.
18+
3. `mislav/bump-homebrew-formula-action@v3` bumps `version` and `sha256`
19+
for stable tags only (tags without `-`).
20+
21+
## Updating Homebrew Install Behavior
22+
23+
When changing install/completion behavior:
24+
25+
1. Update `packaging/homebrew/wtp.rb.tmpl`.
26+
2. Validate template rendering:
27+
- `scripts/render-homebrew-formula.sh --version <version> --sha256 <sha256> --output /tmp/wtp.rb`
28+
3. Let release workflow sync the structure to `homebrew-tap`.

packaging/homebrew/wtp.rb.tmpl

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
class Wtp < Formula
2+
desc "Worktree Plus - Enhanced worktree management with automated setup and hooks"
3+
homepage "https://github.com/satococoa/wtp"
4+
url "https://github.com/satococoa/wtp/archive/refs/tags/v__VERSION__.tar.gz"
5+
version "__VERSION__"
6+
sha256 "__SHA256__"
7+
license "MIT"
8+
9+
depends_on "go" => :build
10+
depends_on "git"
11+
12+
def install
13+
ldflags = "-s -w -X main.version=v#{version}"
14+
system "go", "build", "-trimpath", "-ldflags", ldflags, "-o", "wtp", "./cmd/wtp"
15+
bin.install "wtp"
16+
17+
(bash_completion/"wtp").write <<~'EOS'
18+
# wtp lazy shell-init for bash (installed via Homebrew)
19+
_wtp_lazy_init() {
20+
if [[ -z "${WTP_SHELL_INIT_DONE:-}" ]]; then
21+
local __wtp_init __wtp_status
22+
__wtp_init="$(command wtp shell-init bash 2>/dev/null)"
23+
__wtp_status=$?
24+
if [[ $__wtp_status -ne 0 || -z "$__wtp_init" ]]; then
25+
__wtp_init="$(command wtp completion bash 2>/dev/null)"
26+
__wtp_status=$?
27+
fi
28+
if [[ $__wtp_status -ne 0 || -z "$__wtp_init" ]]; then
29+
return 124
30+
fi
31+
32+
eval "$__wtp_init"
33+
export WTP_SHELL_INIT_DONE=1
34+
fi
35+
36+
if declare -F __wtp_bash_autocomplete >/dev/null 2>&1; then
37+
__wtp_bash_autocomplete "$@"
38+
elif declare -F _wtp >/dev/null 2>&1; then
39+
_wtp "$@"
40+
fi
41+
}
42+
43+
complete -o bashdefault -o default -o nospace -F _wtp_lazy_init wtp
44+
EOS
45+
46+
(zsh_completion/"_wtp").write <<~'EOS'
47+
#compdef wtp
48+
49+
_wtp_lazy_init() {
50+
if [[ -z ${WTP_SHELL_INIT_DONE-} ]]; then
51+
local __wtp_init __wtp_status
52+
__wtp_init="$(command wtp shell-init zsh 2>/dev/null)"
53+
__wtp_status=$?
54+
if [[ $__wtp_status -ne 0 || -z "$__wtp_init" ]]; then
55+
__wtp_init="$(command wtp completion zsh 2>/dev/null)"
56+
__wtp_status=$?
57+
fi
58+
if [[ $__wtp_status -ne 0 || -z "$__wtp_init" ]]; then
59+
return 1
60+
fi
61+
62+
eval "$__wtp_init"
63+
export WTP_SHELL_INIT_DONE=1
64+
fi
65+
66+
if typeset -f _wtp >/dev/null 2>&1; then
67+
_wtp "$@"
68+
fi
69+
}
70+
71+
compdef _wtp_lazy_init wtp
72+
EOS
73+
74+
(fish_completion/"wtp.fish").write <<~'EOS'
75+
function __wtp_lazy_setup --on-event fish_prompt --description 'Lazy shell-init for wtp (Homebrew)'
76+
functions -e __wtp_lazy_setup
77+
78+
if not set -q WTP_SHELL_INIT_DONE
79+
command wtp shell-init fish ^/dev/null | source
80+
set -l __wtp_status $status
81+
if test $__wtp_status -ne 0
82+
command wtp completion fish ^/dev/null | source
83+
set __wtp_status $status
84+
end
85+
if test $__wtp_status -ne 0
86+
return
87+
end
88+
89+
set -gx WTP_SHELL_INIT_DONE 1
90+
end
91+
end
92+
EOS
93+
end
94+
95+
test do
96+
system "#{bin}/wtp", "--help"
97+
end
98+
end

scripts/render-homebrew-formula.sh

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
#!/usr/bin/env bash
2+
set -euo pipefail
3+
4+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
5+
REPO_ROOT="$(cd "${SCRIPT_DIR}/.." && pwd)"
6+
7+
VERSION=""
8+
SHA256=""
9+
TEMPLATE_PATH="${REPO_ROOT}/packaging/homebrew/wtp.rb.tmpl"
10+
OUTPUT_PATH=""
11+
12+
usage() {
13+
cat <<'EOF'
14+
Usage:
15+
scripts/render-homebrew-formula.sh --version <VERSION> --sha256 <SHA256> [--template <PATH>] [--output <PATH>]
16+
17+
Examples:
18+
scripts/render-homebrew-formula.sh --version 2.8.0 --sha256 <sha>
19+
scripts/render-homebrew-formula.sh --version 2.8.0 --sha256 <sha> --output /tmp/wtp.rb
20+
EOF
21+
}
22+
23+
require_option_value() {
24+
local option="$1"
25+
local value="${2:-}"
26+
27+
if [[ -z "${value}" || "${value}" == --* ]]; then
28+
echo "missing value for ${option}" >&2
29+
usage >&2
30+
exit 1
31+
fi
32+
}
33+
34+
while [[ $# -gt 0 ]]; do
35+
case "$1" in
36+
--version)
37+
require_option_value "$1" "${2:-}"
38+
VERSION="$2"
39+
shift 2
40+
;;
41+
--sha256)
42+
require_option_value "$1" "${2:-}"
43+
SHA256="$2"
44+
shift 2
45+
;;
46+
--template)
47+
require_option_value "$1" "${2:-}"
48+
TEMPLATE_PATH="$2"
49+
shift 2
50+
;;
51+
--output)
52+
require_option_value "$1" "${2:-}"
53+
OUTPUT_PATH="$2"
54+
shift 2
55+
;;
56+
-h|--help)
57+
usage
58+
exit 0
59+
;;
60+
*)
61+
echo "unknown option: $1" >&2
62+
usage >&2
63+
exit 1
64+
;;
65+
esac
66+
done
67+
68+
if [[ -z "${VERSION}" || -z "${SHA256}" ]]; then
69+
echo "--version and --sha256 are required" >&2
70+
usage >&2
71+
exit 1
72+
fi
73+
74+
if [[ ! -f "${TEMPLATE_PATH}" ]]; then
75+
echo "template not found: ${TEMPLATE_PATH}" >&2
76+
exit 1
77+
fi
78+
79+
rendered="$(
80+
sed \
81+
-e "s/__VERSION__/${VERSION}/g" \
82+
-e "s/__SHA256__/${SHA256}/g" \
83+
"${TEMPLATE_PATH}"
84+
)"
85+
86+
if grep -q '__VERSION__\|__SHA256__' <<<"${rendered}"; then
87+
echo "render failed: unresolved placeholders in output" >&2
88+
exit 1
89+
fi
90+
91+
if [[ -n "${OUTPUT_PATH}" ]]; then
92+
printf '%s\n' "${rendered}" > "${OUTPUT_PATH}"
93+
else
94+
printf '%s\n' "${rendered}"
95+
fi

0 commit comments

Comments
 (0)