Skip to content

Commit 0d5f772

Browse files
authored
feat: add autobump workflow for trg formula (#9)
Signed-off-by: Yordis Prieto <yordis.prieto@gmail.com>
1 parent b4f79e7 commit 0d5f772

1 file changed

Lines changed: 244 additions & 0 deletions

File tree

.github/workflows/autobump.yml

Lines changed: 244 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,244 @@
1+
name: Autobump Formulas
2+
3+
on:
4+
schedule:
5+
- cron: "0 */6 * * *"
6+
workflow_dispatch:
7+
inputs:
8+
dry_run:
9+
description: "Dry run: resolve versions and compute SHA256s but do not open PRs"
10+
type: boolean
11+
default: false
12+
13+
jobs:
14+
bump:
15+
name: Bump ${{ matrix.formula }}
16+
runs-on: ubuntu-latest
17+
permissions:
18+
contents: write
19+
pull-requests: write
20+
strategy:
21+
fail-fast: false
22+
matrix:
23+
include:
24+
- formula: trg
25+
formula_file: Formula/trg.rb
26+
upstream_repo: TrogonStack/rusty-monorepo
27+
tag_prefix: trg@v
28+
# {name}-{version}-{arch}.tar.gz
29+
url_style: rust
30+
archs: >-
31+
aarch64-apple-darwin
32+
x86_64-apple-darwin
33+
aarch64-unknown-linux-gnu
34+
x86_64-unknown-linux-gnu
35+
36+
- formula: protoc-gen-elixir-grpc
37+
formula_file: Formula/protoc-gen-elixir-grpc.rb
38+
upstream_repo: TrogonStack/protoc-gen
39+
tag_prefix: protoc-gen-elixir-grpc@v
40+
# {name}@v{version}_{OS}_{arch}.tar.gz
41+
url_style: goreleaser
42+
archs: >-
43+
Darwin_arm64
44+
Darwin_x86_64
45+
Linux_arm64
46+
Linux_x86_64
47+
48+
- formula: protoc-gen-connect-go-servicestruct
49+
formula_file: Formula/protoc-gen-connect-go-servicestruct.rb
50+
upstream_repo: TrogonStack/protoc-gen
51+
tag_prefix: protoc-gen-connect-go-servicestruct@v
52+
url_style: goreleaser
53+
archs: >-
54+
Darwin_arm64
55+
Darwin_x86_64
56+
Linux_arm64
57+
Linux_x86_64
58+
59+
- formula: otel-collector
60+
formula_file: Formula/otel-collector.rb
61+
upstream_repo: open-telemetry/opentelemetry-collector-releases
62+
tag_prefix: "v"
63+
url_style: otelcol
64+
archs: >-
65+
darwin_amd64
66+
67+
steps:
68+
- uses: actions/checkout@v4
69+
70+
- name: Get latest upstream version
71+
id: upstream
72+
run: |
73+
TAG=$(curl -sL \
74+
-H "Authorization: Bearer ${{ secrets.GITHUB_TOKEN }}" \
75+
"https://api.github.com/repos/${{ matrix.upstream_repo }}/releases?per_page=100" \
76+
| jq -r --arg prefix "${{ matrix.tag_prefix }}" \
77+
'[.[] | select(.tag_name | startswith($prefix))] | first | .tag_name | ltrimstr($prefix)')
78+
echo "version=$TAG" >> $GITHUB_OUTPUT
79+
80+
- name: Get current formula version
81+
id: current
82+
run: |
83+
VERSION=$(grep '^ version ' ${{ matrix.formula_file }} | sed 's/.*"\(.*\)"/\1/')
84+
echo "version=$VERSION" >> $GITHUB_OUTPUT
85+
86+
- name: Check if bump needed
87+
id: check
88+
run: |
89+
UPSTREAM="${{ steps.upstream.outputs.version }}"
90+
CURRENT="${{ steps.current.outputs.version }}"
91+
if [ -z "$UPSTREAM" ] || [ "$UPSTREAM" = "null" ]; then
92+
echo "needed=false" >> $GITHUB_OUTPUT
93+
echo "::error::${{ matrix.formula }}: could not resolve upstream version (got '$UPSTREAM'). Check tag_prefix and upstream_repo."
94+
exit 1
95+
elif [ "$UPSTREAM" = "$CURRENT" ]; then
96+
echo "needed=false" >> $GITHUB_OUTPUT
97+
echo "${{ matrix.formula }}: already at $CURRENT, skipping."
98+
else
99+
echo "needed=true" >> $GITHUB_OUTPUT
100+
echo "${{ matrix.formula }}: bumping $CURRENT → $UPSTREAM"
101+
fi
102+
103+
- name: Fetch SHA256 checksums
104+
if: steps.check.outputs.needed == 'true'
105+
id: checksums
106+
run: |
107+
VERSION="${{ steps.upstream.outputs.version }}"
108+
FORMULA="${{ matrix.formula }}"
109+
TAG_PREFIX="${{ matrix.tag_prefix }}"
110+
BASE="https://github.com/${{ matrix.upstream_repo }}/releases/download/${TAG_PREFIX}${VERSION}"
111+
STYLE="${{ matrix.url_style }}"
112+
RESULT=""
113+
114+
for ARCH in ${{ matrix.archs }}; do
115+
if [ "$STYLE" = "rust" ]; then
116+
FILE="${FORMULA}-${VERSION}-${ARCH}.tar.gz"
117+
elif [ "$STYLE" = "goreleaser" ]; then
118+
FILE="${FORMULA}@v${VERSION}_${ARCH}.tar.gz"
119+
elif [ "$STYLE" = "otelcol" ]; then
120+
FILE="otelcol-contrib_${VERSION}_${ARCH}.tar.gz"
121+
fi
122+
123+
URL="${BASE}/${FILE}"
124+
SHA=$(curl -fsSL "$URL" | sha256sum | awk '{print $1}')
125+
if ! echo "$SHA" | grep -qE '^[a-f0-9]{64}$'; then
126+
echo "::error::Failed to fetch or hash $URL (got: '$SHA')"
127+
exit 1
128+
fi
129+
RESULT="${RESULT}${ARCH}=${SHA}\n"
130+
echo "sha_${ARCH//[-.]/_}=$SHA" >> $GITHUB_OUTPUT
131+
done
132+
133+
printf "$RESULT"
134+
135+
- name: Update formula
136+
if: steps.check.outputs.needed == 'true'
137+
run: |
138+
python3 - <<'PYEOF'
139+
import re, os, subprocess
140+
141+
formula_file = os.environ["FORMULA_FILE"]
142+
version = os.environ["NEW_VERSION"]
143+
formula = os.environ["FORMULA_NAME"]
144+
tag_prefix = os.environ["TAG_PREFIX"]
145+
style = os.environ["URL_STYLE"]
146+
repo = os.environ["UPSTREAM_REPO"]
147+
archs_raw = os.environ["ARCHS"].split()
148+
149+
base = f"https://github.com/{repo}/releases/download/{tag_prefix}{version}"
150+
151+
with open(formula_file) as f:
152+
content = f.read()
153+
154+
content = re.sub(r'version "[^"]+"', f'version "{version}"', content)
155+
156+
for arch in archs_raw:
157+
if style == "rust":
158+
new_url = f"{base}/{formula}-{version}-{arch}.tar.gz"
159+
arch_pat = arch.replace("-", r"\-")
160+
content = re.sub(
161+
rf'(url ")[^"]+{arch_pat}\.tar\.gz"',
162+
f'url "{new_url}"',
163+
content
164+
)
165+
elif style == "goreleaser":
166+
new_url = f"{base}/{formula}@v{version}_{arch}.tar.gz"
167+
arch_pat = arch.replace("_", r"\_")
168+
content = re.sub(
169+
rf'(url ")[^"]+{re.escape(arch)}\.tar\.gz"',
170+
f'url "{new_url}"',
171+
content
172+
)
173+
elif style == "otelcol":
174+
new_url = f"{base}/otelcol-contrib_{version}_{arch}.tar.gz"
175+
content = re.sub(
176+
rf'(url ")[^"]+"',
177+
f'url "{new_url}"',
178+
content
179+
)
180+
181+
env_key = "sha_" + arch.replace("-", "_").replace(".", "_")
182+
sha = os.environ.get(env_key, "")
183+
if sha:
184+
if style in ("rust", "goreleaser"):
185+
content = re.sub(
186+
rf'({re.escape(arch)}\.tar\.gz"\n\s+sha256 ")[a-f0-9]+"',
187+
rf'\g<1>{sha}"',
188+
content
189+
)
190+
elif style == "otelcol":
191+
content = re.sub(r'sha256 "[a-f0-9]+"', f'sha256 "{sha}"', content)
192+
193+
with open(formula_file, "w") as f:
194+
f.write(content)
195+
196+
print(content)
197+
PYEOF
198+
env:
199+
FORMULA_FILE: ${{ matrix.formula_file }}
200+
NEW_VERSION: ${{ steps.upstream.outputs.version }}
201+
FORMULA_NAME: ${{ matrix.formula }}
202+
TAG_PREFIX: ${{ matrix.tag_prefix }}
203+
URL_STYLE: ${{ matrix.url_style }}
204+
UPSTREAM_REPO: ${{ matrix.upstream_repo }}
205+
ARCHS: ${{ matrix.archs }}
206+
sha_aarch64_apple_darwin: ${{ steps.checksums.outputs.sha_aarch64_apple_darwin }}
207+
sha_x86_64_apple_darwin: ${{ steps.checksums.outputs.sha_x86_64_apple_darwin }}
208+
sha_aarch64_unknown_linux_gnu: ${{ steps.checksums.outputs.sha_aarch64_unknown_linux_gnu }}
209+
sha_x86_64_unknown_linux_gnu: ${{ steps.checksums.outputs.sha_x86_64_unknown_linux_gnu }}
210+
sha_Darwin_arm64: ${{ steps.checksums.outputs.sha_Darwin_arm64 }}
211+
sha_Darwin_x86_64: ${{ steps.checksums.outputs.sha_Darwin_x86_64 }}
212+
sha_Linux_arm64: ${{ steps.checksums.outputs.sha_Linux_arm64 }}
213+
sha_Linux_x86_64: ${{ steps.checksums.outputs.sha_Linux_x86_64 }}
214+
sha_darwin_amd64: ${{ steps.checksums.outputs.sha_darwin_amd64 }}
215+
216+
- name: Dry run summary
217+
if: steps.check.outputs.needed == 'true' && inputs.dry_run
218+
run: |
219+
echo "### Dry run: ${{ matrix.formula }}" >> $GITHUB_STEP_SUMMARY
220+
echo "- **Current version**: \`${{ steps.current.outputs.version }}\`" >> $GITHUB_STEP_SUMMARY
221+
echo "- **New version**: \`${{ steps.upstream.outputs.version }}\`" >> $GITHUB_STEP_SUMMARY
222+
echo "- **Would open PR**: bump-${{ matrix.formula }}-${{ steps.upstream.outputs.version }}" >> $GITHUB_STEP_SUMMARY
223+
echo "" >> $GITHUB_STEP_SUMMARY
224+
echo "**Updated formula:**" >> $GITHUB_STEP_SUMMARY
225+
echo '```ruby' >> $GITHUB_STEP_SUMMARY
226+
cat ${{ matrix.formula_file }} >> $GITHUB_STEP_SUMMARY
227+
echo '```' >> $GITHUB_STEP_SUMMARY
228+
229+
- name: Open PR
230+
if: steps.check.outputs.needed == 'true' && !inputs.dry_run
231+
uses: peter-evans/create-pull-request@271a8d0340265f705b14b6d32b9829c5e6f51e28 # v7.0.8
232+
with:
233+
token: ${{ secrets.GH_PAT_RELEASE_PLEASE_ACTION }}
234+
commit-message: "chore: bump ${{ matrix.formula }} to ${{ steps.upstream.outputs.version }}"
235+
branch: "bump-${{ matrix.formula }}-${{ steps.upstream.outputs.version }}"
236+
title: "chore: bump ${{ matrix.formula }} to ${{ steps.upstream.outputs.version }}"
237+
body: |
238+
Automated formula bump for `${{ matrix.formula }}`.
239+
240+
- **Previous version**: `${{ steps.current.outputs.version }}`
241+
- **New version**: `${{ steps.upstream.outputs.version }}`
242+
labels: |
243+
bot
244+
bump-formula-pr

0 commit comments

Comments
 (0)