Skip to content

Commit 56ca356

Browse files
committed
ci: use GitHub-hosted release runners
1 parent 3a3e67d commit 56ca356

2 files changed

Lines changed: 49 additions & 104 deletions

File tree

.github/workflows/release-drafter.yml

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,7 @@
66
# `docs/changelog/v<ver>.md` is prefilled.
77
#
88
# Cost: one ubuntu-latest job per relevant PR/push event, single API
9-
# call, no compile, no tests. Zero contention with the self-hosted
10-
# Hetzner runners that release.yml uses.
9+
# call, no compile, no tests.
1110

1211
name: release-drafter
1312

.github/workflows/release.yml

Lines changed: 48 additions & 102 deletions
Original file line numberDiff line numberDiff line change
@@ -31,42 +31,31 @@ permissions:
3131
packages: write
3232

3333
# Runner strategy:
34-
# - Linux + Android + mipsel: self-hosted (mhrv-hetzner-*, Hetzner
35-
# 8-core / 31 GB Ubuntu 24.04 box with
36-
# Rust, Android SDK+NDK, Docker, all
37-
# cross-compile toolchains pre-installed).
38-
# Two runners registered for parallelism.
39-
# - macOS arm64 + amd64, Windows: GitHub-hosted (we don't self-host those
40-
# OSes; the free minutes on a public repo
41-
# are plenty for those two platforms).
34+
# - Linux + Android + mipsel: GitHub-hosted Ubuntu runners.
35+
# - macOS arm64 + amd64, Windows: GitHub-hosted native OS runners.
4236
#
43-
# Why self-hosted: GH-hosted 2-core runners were spending ~13 min cold per
44-
# release; on the Hetzner box a cold linux-amd64 build is 1m9s, and warm
45-
# builds with Swatinem/rust-cache are sub-minute. Keeps the toolchain warm,
46-
# and more importantly keeps target/ warm via the rust-cache action.
37+
# Why hosted: the repo no longer keeps persistent release builders
38+
# registered. Each release job provisions only the tools it needs, while
39+
# Swatinem/rust-cache keeps target/ and cargo registry rebuild cost sane.
4740

4841
jobs:
4942
build:
5043
strategy:
5144
fail-fast: false
5245
matrix:
5346
include:
54-
# Pin to Ubuntu 22.04 GLIBC target (GLIBC 2.35) so the glibc builds
55-
# load on any distro ≥ Ubuntu 22.04 / Debian 12 / Mint 21 / Fedora 36.
56-
# On self-hosted this is a Rust-side choice (cargo target triple),
57-
# not an OS-of-the-runner choice — the runner itself is Ubuntu 24.04
58-
# (GLIBC 2.39), but we link against the 2.35-era glibc via the
59-
# x86_64-unknown-linux-gnu target triple which pins to the oldest
60-
# GLIBC symbol version rustc is willing to emit. Users behind tight
61-
# internet who can't dist-upgrade keep working.
47+
# Pin the runner to Ubuntu 22.04 and use the
48+
# x86_64-unknown-linux-gnu target so glibc builds stay compatible
49+
# with Ubuntu 22.04 / Debian 12 / Mint 21 / Fedora 36 era systems.
50+
# Users behind tight internet who can't dist-upgrade keep working.
6251
- target: x86_64-unknown-linux-gnu
63-
os: [self-hosted, linux, x64, mhrv-build]
52+
os: ubuntu-22.04
6453
name: mhrv-rs-linux-amd64
6554
- target: aarch64-unknown-linux-gnu
66-
os: [self-hosted, linux, x64, mhrv-build]
55+
os: ubuntu-22.04
6756
name: mhrv-rs-linux-arm64
6857
- target: arm-unknown-linux-gnueabihf
69-
os: [self-hosted, linux, x64, mhrv-build]
58+
os: ubuntu-22.04
7059
name: mhrv-rs-raspbian-armhf
7160
- target: x86_64-apple-darwin
7261
os: macos-latest
@@ -89,10 +78,10 @@ jobs:
8978
# x86_64-pc-windows-gnu (windows-amd64) which covers ~99% of
9079
# active Windows installs (incl. all WoA64 emulation).
9180
- target: x86_64-unknown-linux-musl
92-
os: [self-hosted, linux, x64, mhrv-build]
81+
os: ubuntu-22.04
9382
name: mhrv-rs-linux-musl-amd64
9483
- target: aarch64-unknown-linux-musl
95-
os: [self-hosted, linux, x64, mhrv-build]
84+
os: ubuntu-22.04
9685
name: mhrv-rs-linux-musl-arm64
9786
# OpenWRT MT7621 (soft-float mipsel 32-bit). Dozens of cheap
9887
# home routers run this chipset and they *specifically* need
@@ -103,7 +92,7 @@ jobs:
10392
# `continue-on-error: true` so a regression here doesn't block
10493
# the rest of the release. Issue #26.
10594
- target: mipsel-unknown-linux-musl
106-
os: [self-hosted, linux, x64, mhrv-build]
95+
os: ubuntu-22.04
10796
name: mhrv-rs-openwrt-mipsel-softfloat
10897
mipsel_softfloat: true
10998

@@ -114,26 +103,6 @@ jobs:
114103
continue-on-error: ${{ matrix.mipsel_softfloat == true }}
115104

116105
steps:
117-
# Heal any root-owned leftovers from a previous mipsel docker
118-
# build that failed before its post-step chown could run. The
119-
# docker container writes target/ as root, and if cargo errors
120-
# inside the container the outer `sudo chown -R` line never
121-
# executes (bash -e exits on the docker non-zero), leaving root-
122-
# owned files that fail every subsequent `actions/checkout@v4`
123-
# workspace clean with `EACCES: permission denied unlink`. This
124-
# step is a no-op on a clean runner, so cheap to keep always-on.
125-
# Self-hosted only; GitHub-hosted runners get a fresh VM each run.
126-
- name: Pre-checkout — clean root-owned files (self-hosted only)
127-
if: contains(matrix.os, 'self-hosted')
128-
run: |
129-
if [ -d "$GITHUB_WORKSPACE/target" ]; then
130-
sudo rm -rf "$GITHUB_WORKSPACE/target" || true
131-
fi
132-
# Stale .rustc_info.json at the workspace root is the
133-
# specific file `actions/checkout` errors on; nuke any
134-
# other root-owned scraps that may be sitting there too.
135-
sudo find "$GITHUB_WORKSPACE" -maxdepth 2 -uid 0 -exec rm -rf {} + 2>/dev/null || true
136-
137106
- uses: actions/checkout@v4
138107

139108
# Skip the host-level rustup install for mipsel-softfloat — that
@@ -145,10 +114,6 @@ jobs:
145114
# 'mipsel-unknown-linux-musl' is unavailable for download", which
146115
# fails the job before the docker step ever runs.
147116
#
148-
# On self-hosted this action is mostly a no-op: rustup is already
149-
# installed and the standard target triples are pre-added. It
150-
# still verifies the target is present and is cheap enough to keep
151-
# as a safety net.
152117
# Per-matrix-entry toolchain selection. Default is `stable` (latest)
153118
# for every target except where `rust_toolchain` is explicitly pinned
154119
# — currently just i686-pc-windows-msvc, which needs 1.77.2 to keep
@@ -159,19 +124,9 @@ jobs:
159124
toolchain: ${{ matrix.rust_toolchain || 'stable' }}
160125
targets: ${{ matrix.target }}
161126

162-
# Cache target/ + cargo registry across runs — this is the big
163-
# self-hosted speedup. Without it, actions/checkout@v4's default
164-
# `git clean -ffdx` wipes target/ between runs and every build is
165-
# cold. With it, warm builds are sub-minute even for the full
166-
# release profile.
167-
#
168-
# cache-bin: false is MANDATORY on our self-hosted runners. With
169-
# the default (true), rust-cache aggressively prunes $CARGO_HOME/bin
170-
# of binaries it didn't install via `cargo install`, including the
171-
# `rustup` binary that cargo/rustc/etc. are symlinked to. The next
172-
# job then hits "command not found" or a broken-symlink TOML parse
173-
# error from a stale cargo. We want target/ + registry caching, NOT
174-
# bin pruning. rustup is pre-installed on the runners anyway.
127+
# Cache target/ + cargo registry across runs. cache-bin: false keeps
128+
# the cache focused on build artifacts and registry state instead of
129+
# pruning tool binaries installed by setup actions.
175130
- uses: Swatinem/rust-cache@v2
176131
if: matrix.mipsel_softfloat != true
177132
with:
@@ -182,13 +137,11 @@ jobs:
182137
key: ${{ matrix.target }}-${{ matrix.rust_toolchain || 'stable' }}
183138
cache-bin: "false"
184139

185-
# eframe needs a few system libs on Linux for window management, keyboard,
186-
# and OpenGL/X11/Wayland. Gated to GitHub-hosted runners only — the
187-
# self-hosted runners pre-install all of these once at setup time, and
188-
# letting multiple parallel matrix jobs race on `sudo apt-get install`
189-
# fights over /var/lib/apt/lists/lock and fails them all.
140+
# eframe needs a few system libs on Linux for window management,
141+
# keyboard, and OpenGL/X11/Wayland. Only the x86_64 GNU Linux job
142+
# builds the UI on Linux, so the cross and musl jobs skip this.
190143
- name: Install Linux eframe system deps
191-
if: runner.os == 'Linux' && runner.environment == 'github-hosted'
144+
if: matrix.target == 'x86_64-unknown-linux-gnu'
192145
run: |
193146
sudo apt-get update
194147
sudo apt-get install -y \
@@ -198,24 +151,22 @@ jobs:
198151
libx11-dev \
199152
libgl1-mesa-dev libglib2.0-dev libgtk-3-dev
200153
201-
# Cross-compile toolchains. Same story as above — gated to hosted
202-
# runners; self-hosted has gcc-aarch64-linux-gnu + gcc-arm-linux-gnueabihf
203-
# pre-installed, and the linker entries live in
204-
# /home/ghrunner/cargo-{01,02}/config.toml (seeded once at runner
205-
# setup time, picked up via CARGO_HOME env).
154+
# Cross-compile toolchains for hosted Ubuntu runners.
206155
- name: Install aarch64 cross-compile toolchain (Linux only)
207-
if: matrix.target == 'aarch64-unknown-linux-gnu' && runner.environment == 'github-hosted'
156+
if: matrix.target == 'aarch64-unknown-linux-gnu'
208157
run: |
209158
sudo apt-get update
210159
sudo apt-get install -y gcc-aarch64-linux-gnu
160+
mkdir -p ~/.cargo
211161
echo '[target.aarch64-unknown-linux-gnu]' >> ~/.cargo/config.toml
212162
echo 'linker = "aarch64-linux-gnu-gcc"' >> ~/.cargo/config.toml
213163
214164
- name: Install armhf cross-compile toolchain (Linux only)
215-
if: matrix.target == 'arm-unknown-linux-gnueabihf' && runner.environment == 'github-hosted'
165+
if: matrix.target == 'arm-unknown-linux-gnueabihf'
216166
run: |
217167
sudo apt-get update
218168
sudo apt-get install -y gcc-arm-linux-gnueabihf
169+
mkdir -p ~/.cargo
219170
echo '[target.arm-unknown-linux-gnueabihf]' >> ~/.cargo/config.toml
220171
echo 'linker = "arm-linux-gnueabihf-gcc"' >> ~/.cargo/config.toml
221172
@@ -284,11 +235,10 @@ jobs:
284235
# Always chown back, even if docker exits non-zero. The previous
285236
# form (`docker run …; sudo chown …`) ran chown only on success
286237
# because bash -e short-circuits on the docker failure; that
287-
# left target/ root-owned and broke `actions/checkout@v4` on
288-
# every subsequent self-hosted run with EACCES on
289-
# target/.rustc_info.json. The `trap … EXIT` runs the chown
290-
# whether docker succeeded or failed, so a transient mipsel
291-
# compile regression never poisons the runner workspace.
238+
# left target/ root-owned for later steps in the same job. The
239+
# `trap … EXIT` runs the chown whether docker succeeded or failed,
240+
# so a transient mipsel compile regression never poisons the
241+
# workspace.
292242
set +e
293243
trap 'sudo chown -R "$(id -u):$(id -g)" target 2>/dev/null || true' EXIT
294244
docker run --rm -v "$PWD":/src -w /src \
@@ -408,24 +358,21 @@ jobs:
408358
# x86_64, x86) via cargo-ndk and drops the .so files into the Gradle
409359
# project's jniLibs/ tree, which then packages them into a single
410360
# universal APK. Users pick it once, no per-ABI split.
411-
#
412-
# Runs on self-hosted. The runner has Android SDK + NDK r26c + cargo-ndk
413-
# pre-installed under /opt/android-sdk; the env block below points Gradle
414-
# at those paths so we don't re-download ~1 GB of SDK per release.
415361
android:
416-
runs-on: [self-hosted, linux, x64, mhrv-build]
362+
runs-on: ubuntu-latest
417363
env:
418-
ANDROID_SDK_ROOT: /opt/android-sdk
419-
ANDROID_HOME: /opt/android-sdk
420-
ANDROID_NDK_HOME: /opt/android-sdk/ndk/26.2.11394342
421-
ANDROID_NDK_ROOT: /opt/android-sdk/ndk/26.2.11394342
422-
JAVA_HOME: /usr/lib/jvm/java-17-openjdk-amd64
364+
ANDROID_SDK_ROOT: /usr/local/lib/android/sdk
365+
ANDROID_HOME: /usr/local/lib/android/sdk
366+
ANDROID_NDK_HOME: /usr/local/lib/android/sdk/ndk/26.2.11394342
367+
ANDROID_NDK_ROOT: /usr/local/lib/android/sdk/ndk/26.2.11394342
423368
steps:
424369
- uses: actions/checkout@v4
425370

426-
# Rust toolchain: idempotent on self-hosted (targets already present),
427-
# kept here so the workflow still works if we ever run it on a GH-hosted
428-
# fallback.
371+
- uses: actions/setup-java@v4
372+
with:
373+
distribution: temurin
374+
java-version: '17'
375+
429376
- uses: dtolnay/rust-toolchain@stable
430377
with:
431378
targets: aarch64-linux-android,armv7-linux-androideabi,x86_64-linux-android,i686-linux-android
@@ -434,9 +381,6 @@ jobs:
434381
# release builds back-to-back with LTO is where the cold cost comes
435382
# from; rust-cache brings warm runs down to ~3–4 min from ~9 min cold.
436383
# cache-bin: false — see the rationale on the matrix build job above.
437-
# On top of that, `cargo-ndk` lives in /usr/local/bin/ on our runners
438-
# (not $CARGO_HOME/bin), specifically so rust-cache's default bin
439-
# pruning can't delete it.
440384
- uses: Swatinem/rust-cache@v2
441385
with:
442386
key: android-universal
@@ -446,6 +390,11 @@ jobs:
446390
workspaces: |
447391
. -> target
448392
393+
- name: Install Android NDK and cargo-ndk
394+
run: |
395+
yes | "$ANDROID_HOME/cmdline-tools/latest/bin/sdkmanager" "ndk;26.2.11394342"
396+
cargo install cargo-ndk --locked
397+
449398
# `./gradlew :app:assembleRelease` triggers cargoBuildRelease first
450399
# which invokes cargo-ndk with all four targets, then Gradle packages
451400
# the APK (release buildType signed with the committed release.jks —
@@ -583,11 +532,8 @@ jobs:
583532
cache-from: type=gha
584533
cache-to: type=gha,mode=max
585534

586-
# release + telegram: lightweight aggregation jobs kept on GH-hosted
587-
# ubuntu-latest. They only download artifacts and call APIs — no build
588-
# tooling needed, no benefit from moving to self-hosted, and keeping them
589-
# off the self-hosted runners avoids contention with Linux build jobs from
590-
# the next tag if two releases overlap.
535+
# release + telegram: lightweight aggregation jobs on GitHub-hosted
536+
# ubuntu-latest. They only download artifacts and call APIs.
591537
release:
592538
needs: [build, android]
593539
runs-on: ubuntu-latest

0 commit comments

Comments
 (0)