-
Notifications
You must be signed in to change notification settings - Fork 2
247 lines (217 loc) · 10.4 KB
/
Copy pathrelease.yml
File metadata and controls
247 lines (217 loc) · 10.4 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
name: Release
# Builds the installable artifacts and attaches them to a GitHub Release.
#
# Nothing here embeds Line 6 data — the packages ship the binaries only, and the app imports the
# reference data from the user's own HX Edit installation on first run.
#
# Built on the oldest supported Ubuntu runner on purpose: glibc compatibility runs forward, not
# back, so a binary linked against an older glibc runs on newer distros but not the reverse.
on:
push:
tags: ["v*"]
workflow_dispatch: # lets you produce artifacts without cutting a tag
env:
CARGO_TERM_COLOR: always
# Creating a Release and attaching assets needs write access to repository contents. The default
# GITHUB_TOKEN is read-only, which fails with "Resource not accessible by integration".
permissions:
contents: write
jobs:
bundles:
name: deb / rpm / AppImage
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v5
# WebKitGTK and a C toolchain: what the *-sys crates in the GUI's tree need to link.
# (Users installing the .deb don't need any of this — apt pulls the runtime libs in.)
- name: System dependencies
run: |
sudo apt-get update
sudo apt-get install -y --no-install-recommends \
build-essential pkg-config libwebkit2gtk-4.1-dev \
libfuse2 file # libfuse2 + file: AppImage packaging
- uses: dtolnay/rust-toolchain@stable
- uses: Swatinem/rust-cache@v2
with:
workspaces: ". -> target"
- uses: actions/setup-node@v5
with:
node-version: 20
cache: npm
cache-dependency-path: crates/fretwire-tauri/ui/package-lock.json
# The Rust crate embeds ./dist at compile time and dist/ isn't in git, so this must run first.
- name: Build the frontend
working-directory: crates/fretwire-tauri/ui
run: |
npm ci
npm run build
# The .deb/.rpm ship the CLI alongside the GUI (see bundle.linux.*.files in tauri.conf.json),
# so it has to exist before the bundler runs.
- name: Build the CLI
run: cargo build --release --locked -p fretwire-cli
- name: Bundle
working-directory: crates/fretwire-tauri
run: ./ui/node_modules/.bin/tauri build --bundles deb,rpm,appimage
- name: Collect artifacts
run: |
mkdir -p dist
find target/release/bundle -type f \
\( -name '*.deb' -o -name '*.rpm' -o -name '*.AppImage' \) -exec cp {} dist/ \;
ls -la dist
- uses: actions/upload-artifact@v5
with:
name: linux-bundles
path: dist/*
- name: Attach to the release
if: startsWith(github.ref, 'refs/tags/v')
uses: softprops/action-gh-release@v2
with:
files: dist/*
fail_on_unmatched_files: true
# The release body comes from a file in the tree, so it is reviewable in a diff and the
# published notes cannot drift from the tag. Every job points at the same file: whichever
# finishes first creates the release, the others update it with identical text. A tag
# with no matching file fails the step rather than publishing an empty release.
body_path: docs/release-notes/${{ github.ref_name }}.md
cli:
name: static binaries (musl, ${{ matrix.arch }})
runs-on: ${{ matrix.runner }}
strategy:
matrix:
include:
# arm64 is a native build on GitHub's free arm runner (public repos), so it needs no
# cross toolchain — apt's musl-tools provides the right musl-gcc on each. The arm64
# binary has never been run on ARM hardware here; say so in the release notes until
# someone confirms it (the target use is a headless Raspberry Pi — see ROADMAP Phase 8).
- { arch: x86_64, runner: ubuntu-22.04, target: x86_64-unknown-linux-musl }
- { arch: aarch64, runner: ubuntu-24.04-arm, target: aarch64-unknown-linux-musl }
steps:
- uses: actions/checkout@v5
- uses: dtolnay/rust-toolchain@stable
with:
targets: ${{ matrix.target }}
- uses: Swatinem/rust-cache@v2
- uses: actions/setup-node@v5
with:
node-version: 20
cache: npm
cache-dependency-path: crates/fretwire-tauri/ui/package-lock.json
# fretwire-serve embeds the built frontend (a release build is one file to scp onto a Pi),
# and its build.rs refuses to compile without it.
- name: Build the frontend
working-directory: crates/fretwire-tauri/ui
run: |
npm ci
npm run build
# `nusb` is pure Rust with no libusb to link, so these build fully static — one binary per
# arch that runs on any distro, no matter its glibc. The one C in the tree is `ring` (TLS
# for the update check), which apt's musl-gcc compiles. The daemon and the MCP server ride
# along because the headless Pi is where they run.
- name: Build
run: |
sudo apt-get update && sudo apt-get install -y musl-tools
cargo build --release --locked --target ${{ matrix.target }} \
-p fretwire-cli -p fretwire-serve -p fretwire-mcp
- name: Package
run: |
mkdir -p dist
bin=target/${{ matrix.target }}/release
tar -czf dist/fretwire-cli-${{ matrix.arch }}-linux-musl.tar.gz \
-C "$bin" fretwire \
-C "$GITHUB_WORKSPACE" packaging/70-hxstomp.rules README.md LICENSE-MIT LICENSE-APACHE
tar -czf dist/fretwire-serve-${{ matrix.arch }}-linux-musl.tar.gz \
-C "$bin" fretwire-serve \
-C "$GITHUB_WORKSPACE" packaging/70-hxstomp.rules docs/serve-mode.md LICENSE-MIT LICENSE-APACHE
tar -czf dist/fretwire-mcp-${{ matrix.arch }}-linux-musl.tar.gz \
-C "$bin" fretwire-mcp \
-C "$GITHUB_WORKSPACE" LICENSE-MIT LICENSE-APACHE
ls -la dist
- uses: actions/upload-artifact@v5
with:
name: cli-musl-${{ matrix.arch }}
path: dist/*
- name: Attach to the release
if: startsWith(github.ref, 'refs/tags/v')
uses: softprops/action-gh-release@v2
with:
files: dist/*
fail_on_unmatched_files: true
# The release body comes from a file in the tree, so it is reviewable in a diff and the
# published notes cannot drift from the tag. Every job points at the same file: whichever
# finishes first creates the release, the others update it with identical text. A tag
# with no matching file fails the step rather than publishing an empty release.
body_path: docs/release-notes/${{ github.ref_name }}.md
arch:
name: Arch package (makepkg)
runs-on: ubuntu-24.04
# makepkg is Arch's own tool, so this runs inside an Arch container. Besides producing the
# `.pkg.tar.zst` an Arch user installs with `pacman -U`, it is the check that
# `packaging/PKGBUILD` still builds at all — the file sat unbuilt for six weeks once (ROADMAP
# Phase 8), and it is what goes to the AUR once an account exists. The plain image builds with
# Arch's generic x86-64 flags; a package built on a CachyOS box would carry `-march=native`.
container: archlinux:base-devel
steps:
# git before checkout: without it actions/checkout falls back to a tarball with no `.git`,
# and the tarball step below needs `git archive`.
- name: System dependencies
run: |
pacman -Sy --noconfirm archlinux-keyring
pacman -Su --noconfirm --needed git sudo rustup npm webkit2gtk-4.1 gtk3 pkgconf
- uses: actions/checkout@v5
- name: Build with makepkg
run: |
set -eu
pkgver=$(sed -n 's/^pkgver=//p' packaging/PKGBUILD)
case "$GITHUB_REF" in
refs/tags/v*)
tag=${GITHUB_REF_NAME#v}
if [ "$pkgver" != "$tag" ]; then
echo "::error::packaging/PKGBUILD says pkgver=$pkgver but the tag is v$tag — bump it"
exit 1
fi ;;
esac
# makepkg refuses to run as root, so the build happens as a throwaway user with its own
# home (rustup installs the toolchain there) and its own build directory.
useradd -m builder
build=/home/builder/build
mkdir -p "$build"
cp packaging/PKGBUILD "$build/"
# The PKGBUILD's source is the tag's tarball on GitHub, which does not exist until the
# tag is pushed — and whose bytes differ from what `git archive` produces here anyway.
# So build from this checkout: a tarball under the filename makepkg expects (it then
# skips the download) with the checksum skipped, since that hash belongs to the
# published tarball. The AUR copy keeps the real hash (`updpkgsums` after the tag).
git config --global --add safe.directory "$GITHUB_WORKSPACE"
git archive --format=tar.gz --prefix="fretwire-$pkgver/" \
-o "$build/fretwire-$pkgver.tar.gz" HEAD
chown -R builder:builder "$build"
echo 'PACKAGER="John Baxter <john-baxter-dev@proton.me>"' >> /etc/makepkg.conf
sudo -H -u builder rustup default stable
cd "$build"
sudo -H -u builder makepkg --noconfirm --skipchecksums
# Only the package itself: Arch's default `debug` option also splits off a
# `fretwire-debug` package, which is nothing a release needs to carry.
mkdir -p "$GITHUB_WORKSPACE/dist"
cp ./fretwire-[0-9]*.pkg.tar.zst "$GITHUB_WORKSPACE/dist/"
ls -la "$GITHUB_WORKSPACE/dist"
# Install it the way a user would and check what landed: both binaries, the udev rule, the
# desktop entry, and a GUI that resolves every shared library on a stock Arch.
- name: Install and smoke-test
run: |
set -eu
pacman -U --noconfirm dist/*.pkg.tar.zst
fretwire --version
test -f /usr/lib/udev/rules.d/70-hxstomp.rules
test -f /usr/share/applications/fretwire.desktop
! ldd /usr/bin/fretwire-gui | grep "not found"
- uses: actions/upload-artifact@v5
with:
name: arch-package
path: dist/*
- name: Attach to the release
if: startsWith(github.ref, 'refs/tags/v')
uses: softprops/action-gh-release@v2
with:
files: dist/*
fail_on_unmatched_files: true
body_path: docs/release-notes/${{ github.ref_name }}.md