Skip to content

Commit e2f7018

Browse files
committed
feat: add release workflow with Homebrew bottle support
Release workflow triggered by version tags (v*): - Creates source tarball with submodule baked in - Builds Homebrew bottles for macOS arm64 and x86_64 - Publishes GitHub Release with all artifacts - Updates mavlink/homebrew-tap formula with bottle hashes Requires HOMEBREW_TAP_TOKEN secret for tap repo access.
1 parent c8f2aca commit e2f7018

File tree

2 files changed

+343
-0
lines changed

2 files changed

+343
-0
lines changed

.github/workflows/release.yml

Lines changed: 320 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,320 @@
1+
name: Release
2+
3+
on:
4+
push:
5+
tags:
6+
- 'v*'
7+
8+
permissions:
9+
contents: write
10+
11+
jobs:
12+
# ── Job 1: Create source tarball and draft release ─────────────────────────
13+
source-tarball:
14+
name: Source tarball
15+
runs-on: ubuntu-latest
16+
outputs:
17+
version: ${{ steps.version.outputs.version }}
18+
tarball_sha256: ${{ steps.tarball.outputs.sha256 }}
19+
20+
steps:
21+
- uses: actions/checkout@v4
22+
with:
23+
submodules: true
24+
25+
- name: Extract version from tag
26+
id: version
27+
run: echo "version=${GITHUB_REF#refs/tags/v}" >> "$GITHUB_OUTPUT"
28+
29+
- name: Create source tarball
30+
id: tarball
31+
run: |
32+
VERSION=${{ steps.version.outputs.version }}
33+
tar czf mavsim-viewer-${VERSION}.tar.gz \
34+
--exclude='.git' \
35+
--exclude='tests/fixtures/*.ulg' \
36+
--exclude='build' \
37+
--transform="s,^\.,mavsim-viewer-${VERSION}," \
38+
.
39+
SHA=$(sha256sum mavsim-viewer-${VERSION}.tar.gz | awk '{print $1}')
40+
echo "sha256=${SHA}" >> "$GITHUB_OUTPUT"
41+
echo "Tarball SHA256: ${SHA}"
42+
43+
- name: Create draft release
44+
run: |
45+
gh release create ${{ github.ref_name }} \
46+
--draft \
47+
--title "${{ github.ref_name }}" \
48+
--generate-notes
49+
env:
50+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
51+
52+
- name: Upload source tarball
53+
run: |
54+
VERSION=${{ steps.version.outputs.version }}
55+
gh release upload ${{ github.ref_name }} mavsim-viewer-${VERSION}.tar.gz
56+
env:
57+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
58+
59+
# ── Job 2a: macOS arm64 bottle ─────────────────────────────────────────────
60+
bottle-arm64:
61+
name: Bottle (arm64)
62+
needs: source-tarball
63+
runs-on: macos-14
64+
outputs:
65+
bottle_sha256: ${{ steps.bottle.outputs.sha256 }}
66+
bottle_tag: ${{ steps.bottle.outputs.tag }}
67+
68+
steps:
69+
- name: Set up tap with formula
70+
env:
71+
VERSION: ${{ needs.source-tarball.outputs.version }}
72+
TARBALL_SHA: ${{ needs.source-tarball.outputs.tarball_sha256 }}
73+
TAG: ${{ github.ref_name }}
74+
run: |
75+
FORMULA_DIR="$(brew --repo)/Library/Taps/mavlink/homebrew-tap/Formula"
76+
mkdir -p "$FORMULA_DIR"
77+
python3 -c "
78+
import os
79+
formula = '''class MavsimViewer < Formula
80+
desc \"3D MAVLink vehicle viewer for SITL simulation\"
81+
homepage \"https://github.com/mavlink/mavsim-viewer\"
82+
url \"https://github.com/mavlink/mavsim-viewer/releases/download/{tag}/mavsim-viewer-{version}.tar.gz\"
83+
sha256 \"{sha}\"
84+
license \"BSD-3-Clause\"
85+
86+
depends_on \"cmake\" => :build
87+
88+
def install
89+
system \"cmake\", \"-S\", \".\", \"-B\", \"build\", \"-DCMAKE_BUILD_TYPE=Release\", *std_cmake_args
90+
system \"cmake\", \"--build\", \"build\"
91+
system \"cmake\", \"--install\", \"build\", \"--prefix\", prefix
92+
end
93+
94+
test do
95+
assert_predicate bin/\"mavsim-viewer\", :executable?
96+
end
97+
end
98+
'''.format(
99+
tag=os.environ['TAG'],
100+
version=os.environ['VERSION'],
101+
sha=os.environ['TARBALL_SHA'],
102+
)
103+
with open(os.environ['FORMULA_DIR'] + '/mavsim-viewer.rb', 'w') as f:
104+
f.write(formula)
105+
" FORMULA_DIR="$FORMULA_DIR"
106+
107+
- name: Build bottle
108+
run: brew install --build-bottle mavlink/tap/mavsim-viewer
109+
110+
- name: Package bottle
111+
id: bottle
112+
run: |
113+
TAG=${{ github.ref_name }}
114+
brew bottle \
115+
--json \
116+
--root-url="https://github.com/mavlink/mavsim-viewer/releases/download/${TAG}" \
117+
mavlink/tap/mavsim-viewer
118+
119+
BOTTLE_JSON=$(ls mavsim-viewer--*.bottle.json)
120+
BOTTLE_FILE=$(ls mavsim-viewer--*.bottle.tar.gz)
121+
CLEAN_NAME=$(echo "$BOTTLE_FILE" | sed 's/--/-/')
122+
mv "$BOTTLE_FILE" "$CLEAN_NAME"
123+
124+
BOTTLE_SHA=$(python3 -c "
125+
import json, sys
126+
data = json.load(open(sys.argv[1]))
127+
tags = data['mavsim-viewer']['bottle']['tags']
128+
tag = list(tags.keys())[0]
129+
print(tags[tag]['sha256'])
130+
" "$BOTTLE_JSON")
131+
132+
BOTTLE_TAG=$(python3 -c "
133+
import json, sys
134+
data = json.load(open(sys.argv[1]))
135+
tags = data['mavsim-viewer']['bottle']['tags']
136+
print(list(tags.keys())[0])
137+
" "$BOTTLE_JSON")
138+
139+
echo "sha256=${BOTTLE_SHA}" >> "$GITHUB_OUTPUT"
140+
echo "tag=${BOTTLE_TAG}" >> "$GITHUB_OUTPUT"
141+
echo "file=${CLEAN_NAME}" >> "$GITHUB_OUTPUT"
142+
143+
- name: Upload bottle to release
144+
run: gh release upload ${{ github.ref_name }} ${{ steps.bottle.outputs.file }}
145+
env:
146+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
147+
148+
# ── Job 2b: macOS x86_64 bottle ───────────────────────────────────────────
149+
bottle-x86_64:
150+
name: Bottle (x86_64)
151+
needs: source-tarball
152+
runs-on: macos-13
153+
outputs:
154+
bottle_sha256: ${{ steps.bottle.outputs.sha256 }}
155+
bottle_tag: ${{ steps.bottle.outputs.tag }}
156+
157+
steps:
158+
- name: Set up tap with formula
159+
env:
160+
VERSION: ${{ needs.source-tarball.outputs.version }}
161+
TARBALL_SHA: ${{ needs.source-tarball.outputs.tarball_sha256 }}
162+
TAG: ${{ github.ref_name }}
163+
run: |
164+
FORMULA_DIR="$(brew --repo)/Library/Taps/mavlink/homebrew-tap/Formula"
165+
mkdir -p "$FORMULA_DIR"
166+
python3 -c "
167+
import os
168+
formula = '''class MavsimViewer < Formula
169+
desc \"3D MAVLink vehicle viewer for SITL simulation\"
170+
homepage \"https://github.com/mavlink/mavsim-viewer\"
171+
url \"https://github.com/mavlink/mavsim-viewer/releases/download/{tag}/mavsim-viewer-{version}.tar.gz\"
172+
sha256 \"{sha}\"
173+
license \"BSD-3-Clause\"
174+
175+
depends_on \"cmake\" => :build
176+
177+
def install
178+
system \"cmake\", \"-S\", \".\", \"-B\", \"build\", \"-DCMAKE_BUILD_TYPE=Release\", *std_cmake_args
179+
system \"cmake\", \"--build\", \"build\"
180+
system \"cmake\", \"--install\", \"build\", \"--prefix\", prefix
181+
end
182+
183+
test do
184+
assert_predicate bin/\"mavsim-viewer\", :executable?
185+
end
186+
end
187+
'''.format(
188+
tag=os.environ['TAG'],
189+
version=os.environ['VERSION'],
190+
sha=os.environ['TARBALL_SHA'],
191+
)
192+
with open(os.environ['FORMULA_DIR'] + '/mavsim-viewer.rb', 'w') as f:
193+
f.write(formula)
194+
" FORMULA_DIR="$FORMULA_DIR"
195+
196+
- name: Build bottle
197+
run: brew install --build-bottle mavlink/tap/mavsim-viewer
198+
199+
- name: Package bottle
200+
id: bottle
201+
run: |
202+
TAG=${{ github.ref_name }}
203+
brew bottle \
204+
--json \
205+
--root-url="https://github.com/mavlink/mavsim-viewer/releases/download/${TAG}" \
206+
mavlink/tap/mavsim-viewer
207+
208+
BOTTLE_JSON=$(ls mavsim-viewer--*.bottle.json)
209+
BOTTLE_FILE=$(ls mavsim-viewer--*.bottle.tar.gz)
210+
CLEAN_NAME=$(echo "$BOTTLE_FILE" | sed 's/--/-/')
211+
mv "$BOTTLE_FILE" "$CLEAN_NAME"
212+
213+
BOTTLE_SHA=$(python3 -c "
214+
import json, sys
215+
data = json.load(open(sys.argv[1]))
216+
tags = data['mavsim-viewer']['bottle']['tags']
217+
tag = list(tags.keys())[0]
218+
print(tags[tag]['sha256'])
219+
" "$BOTTLE_JSON")
220+
221+
BOTTLE_TAG=$(python3 -c "
222+
import json, sys
223+
data = json.load(open(sys.argv[1]))
224+
tags = data['mavsim-viewer']['bottle']['tags']
225+
print(list(tags.keys())[0])
226+
" "$BOTTLE_JSON")
227+
228+
echo "sha256=${BOTTLE_SHA}" >> "$GITHUB_OUTPUT"
229+
echo "tag=${BOTTLE_TAG}" >> "$GITHUB_OUTPUT"
230+
echo "file=${CLEAN_NAME}" >> "$GITHUB_OUTPUT"
231+
232+
- name: Upload bottle to release
233+
run: gh release upload ${{ github.ref_name }} ${{ steps.bottle.outputs.file }}
234+
env:
235+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
236+
237+
# ── Job 3: Publish the release ─────────────────────────────────────────────
238+
publish-release:
239+
name: Publish release
240+
needs: [bottle-arm64, bottle-x86_64]
241+
runs-on: ubuntu-latest
242+
243+
steps:
244+
- name: Mark release as published
245+
run: |
246+
gh release edit ${{ github.ref_name }} \
247+
--repo ${{ github.repository }} \
248+
--draft=false
249+
env:
250+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
251+
252+
# ── Job 4: Update Homebrew tap ─────────────────────────────────────────────
253+
update-tap:
254+
name: Update Homebrew tap
255+
needs: [source-tarball, bottle-arm64, bottle-x86_64, publish-release]
256+
runs-on: ubuntu-latest
257+
258+
steps:
259+
- name: Update formula in tap
260+
env:
261+
VERSION: ${{ needs.source-tarball.outputs.version }}
262+
TAG: ${{ github.ref_name }}
263+
TARBALL_SHA: ${{ needs.source-tarball.outputs.tarball_sha256 }}
264+
ARM64_SHA: ${{ needs.bottle-arm64.outputs.bottle_sha256 }}
265+
ARM64_TAG: ${{ needs.bottle-arm64.outputs.bottle_tag }}
266+
X86_SHA: ${{ needs.bottle-x86_64.outputs.bottle_sha256 }}
267+
X86_TAG: ${{ needs.bottle-x86_64.outputs.bottle_tag }}
268+
TAP_TOKEN: ${{ secrets.HOMEBREW_TAP_TOKEN }}
269+
run: |
270+
git clone https://x-access-token:${TAP_TOKEN}@github.com/mavlink/homebrew-tap.git tap
271+
mkdir -p tap/Formula
272+
273+
python3 -c "
274+
import os
275+
formula = '''class MavsimViewer < Formula
276+
desc \"3D MAVLink vehicle viewer for SITL simulation\"
277+
homepage \"https://github.com/mavlink/mavsim-viewer\"
278+
url \"https://github.com/mavlink/mavsim-viewer/releases/download/{tag}/mavsim-viewer-{version}.tar.gz\"
279+
sha256 \"{tarball_sha}\"
280+
license \"BSD-3-Clause\"
281+
282+
bottle do
283+
root_url \"https://github.com/mavlink/mavsim-viewer/releases/download/{tag}\"
284+
sha256 cellar: :any_skip_relocation, {arm64_tag}: \"{arm64_sha}\"
285+
sha256 cellar: :any_skip_relocation, {x86_tag}: \"{x86_sha}\"
286+
end
287+
288+
depends_on \"cmake\" => :build
289+
290+
def install
291+
system \"cmake\", \"-S\", \".\", \"-B\", \"build\",
292+
\"-DCMAKE_BUILD_TYPE=Release\",
293+
*std_cmake_args
294+
system \"cmake\", \"--build\", \"build\"
295+
system \"cmake\", \"--install\", \"build\", \"--prefix\", prefix
296+
end
297+
298+
test do
299+
assert_predicate bin/\"mavsim-viewer\", :executable?
300+
end
301+
end
302+
'''.format(
303+
tag=os.environ['TAG'],
304+
version=os.environ['VERSION'],
305+
tarball_sha=os.environ['TARBALL_SHA'],
306+
arm64_sha=os.environ['ARM64_SHA'],
307+
arm64_tag=os.environ['ARM64_TAG'],
308+
x86_sha=os.environ['X86_SHA'],
309+
x86_tag=os.environ['X86_TAG'],
310+
)
311+
with open('tap/Formula/mavsim-viewer.rb', 'w') as f:
312+
f.write(formula)
313+
"
314+
315+
cd tap
316+
git config user.name "github-actions[bot]"
317+
git config user.email "github-actions[bot]@users.noreply.github.com"
318+
git add Formula/mavsim-viewer.rb
319+
git commit -m "mavsim-viewer ${VERSION}"
320+
git push

Formula/mavsim-viewer.rb

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
# Reference template — the canonical formula lives in mavlink/homebrew-tap
2+
# and is automatically updated by .github/workflows/release.yml on each release.
3+
class MavsimViewer < Formula
4+
desc "3D MAVLink vehicle viewer for SITL simulation"
5+
homepage "https://github.com/mavlink/mavsim-viewer"
6+
url "https://github.com/mavlink/mavsim-viewer/releases/download/vVERSION/mavsim-viewer-VERSION.tar.gz"
7+
sha256 "TODO"
8+
license "BSD-3-Clause"
9+
10+
depends_on "cmake" => :build
11+
12+
def install
13+
system "cmake", "-S", ".", "-B", "build",
14+
"-DCMAKE_BUILD_TYPE=Release",
15+
*std_cmake_args
16+
system "cmake", "--build", "build"
17+
system "cmake", "--install", "build", "--prefix", prefix
18+
end
19+
20+
test do
21+
assert_predicate bin/"mavsim-viewer", :executable?
22+
end
23+
end

0 commit comments

Comments
 (0)