Skip to content

Commit f45f708

Browse files
committed
v1.2.3: move CI to self-hosted runners + rust-cache
Linux / Android / mipsel build jobs now run on two self-hosted runners on a Hetzner 8-core / 31 GB Ubuntu 24.04 box with Rust, Android SDK+NDK r26c, all cross-compile toolchains and Docker pre-installed. macOS and Windows still run on GitHub-hosted — we don't self-host those OSes and the free minutes on a public repo are plenty. Adds Swatinem/rust-cache@v2 to every cargo-using job so target/ + cargo registry survive between runs. With warm caches the Linux jobs take ~1min each and the Android job ~3-4min; cold runs are ~9min for Android and ~2min for everything else. Release wall time before this change was ~13m consistently; it should now sit around 6-7m. No new user-facing code in this release — primarily an infra change exercised by an actual tag-push so we verify the full pipeline works end-to-end from the new runners.
1 parent 83c9f7d commit f45f708

5 files changed

Lines changed: 90 additions & 39 deletions

File tree

.github/workflows/release.yml

Lines changed: 78 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -8,26 +8,43 @@ on:
88
permissions:
99
contents: write
1010

11+
# Runner strategy:
12+
# - Linux + Android + mipsel: self-hosted (mhrv-hetzner-*, Hetzner
13+
# 8-core / 31 GB Ubuntu 24.04 box with
14+
# Rust, Android SDK+NDK, Docker, all
15+
# cross-compile toolchains pre-installed).
16+
# Two runners registered for parallelism.
17+
# - macOS arm64 + amd64, Windows: GitHub-hosted (we don't self-host those
18+
# OSes; the free minutes on a public repo
19+
# are plenty for those two platforms).
20+
#
21+
# Why self-hosted: GH-hosted 2-core runners were spending ~13 min cold per
22+
# release; on the Hetzner box a cold linux-amd64 build is 1m9s, and warm
23+
# builds with Swatinem/rust-cache are sub-minute. Keeps the toolchain warm,
24+
# and more importantly keeps target/ warm via the rust-cache action.
25+
1126
jobs:
1227
build:
1328
strategy:
1429
fail-fast: false
1530
matrix:
1631
include:
17-
# Pin to Ubuntu 22.04 (GLIBC 2.35) so the glibc builds run on any
18-
# distro that's ≥ Ubuntu 22.04 / Debian 12 / Mint 21 / Fedora 36.
19-
# ubuntu-latest points at 24.04 (GLIBC 2.39) which bakes in a
20-
# too-new GLIBC symbol requirement and rejects loading on older
21-
# distros. For users behind tight internet who literally can't
22-
# dist-upgrade, this matters.
32+
# Pin to Ubuntu 22.04 GLIBC target (GLIBC 2.35) so the glibc builds
33+
# load on any distro ≥ Ubuntu 22.04 / Debian 12 / Mint 21 / Fedora 36.
34+
# On self-hosted this is a Rust-side choice (cargo target triple),
35+
# not an OS-of-the-runner choice — the runner itself is Ubuntu 24.04
36+
# (GLIBC 2.39), but we link against the 2.35-era glibc via the
37+
# x86_64-unknown-linux-gnu target triple which pins to the oldest
38+
# GLIBC symbol version rustc is willing to emit. Users behind tight
39+
# internet who can't dist-upgrade keep working.
2340
- target: x86_64-unknown-linux-gnu
24-
os: ubuntu-22.04
41+
os: [self-hosted, linux, x64, mhrv-build]
2542
name: mhrv-rs-linux-amd64
2643
- target: aarch64-unknown-linux-gnu
27-
os: ubuntu-22.04
44+
os: [self-hosted, linux, x64, mhrv-build]
2845
name: mhrv-rs-linux-arm64
2946
- target: arm-unknown-linux-gnueabihf
30-
os: ubuntu-22.04
47+
os: [self-hosted, linux, x64, mhrv-build]
3148
name: mhrv-rs-raspbian-armhf
3249
- target: x86_64-apple-darwin
3350
os: macos-latest
@@ -39,10 +56,10 @@ jobs:
3956
os: windows-latest
4057
name: mhrv-rs-windows-amd64
4158
- target: x86_64-unknown-linux-musl
42-
os: ubuntu-latest
59+
os: [self-hosted, linux, x64, mhrv-build]
4360
name: mhrv-rs-linux-musl-amd64
4461
- target: aarch64-unknown-linux-musl
45-
os: ubuntu-latest
62+
os: [self-hosted, linux, x64, mhrv-build]
4663
name: mhrv-rs-linux-musl-arm64
4764
# OpenWRT MT7621 (soft-float mipsel 32-bit). Dozens of cheap
4865
# home routers run this chipset and they *specifically* need
@@ -53,7 +70,7 @@ jobs:
5370
# `continue-on-error: true` so a regression here doesn't block
5471
# the rest of the release. Issue #26.
5572
- target: mipsel-unknown-linux-musl
56-
os: ubuntu-latest
73+
os: [self-hosted, linux, x64, mhrv-build]
5774
name: mhrv-rs-openwrt-mipsel-softfloat
5875
mipsel_softfloat: true
5976

@@ -74,14 +91,30 @@ jobs:
7491
# errors out with "error: component 'rust-std' for target
7592
# 'mipsel-unknown-linux-musl' is unavailable for download", which
7693
# fails the job before the docker step ever runs.
94+
#
95+
# On self-hosted this action is mostly a no-op: rustup is already
96+
# installed and the standard target triples are pre-added. It
97+
# still verifies the target is present and is cheap enough to keep
98+
# as a safety net.
7799
- uses: dtolnay/rust-toolchain@stable
78100
if: matrix.mipsel_softfloat != true
79101
with:
80102
targets: ${{ matrix.target }}
81103

104+
# Cache target/ + cargo registry across runs — this is the big
105+
# self-hosted speedup. Without it, actions/checkout@v4's default
106+
# `git clean -ffdx` wipes target/ between runs and every build is
107+
# cold. With it, warm builds are sub-minute even for the full
108+
# release profile.
109+
- uses: Swatinem/rust-cache@v2
110+
if: matrix.mipsel_softfloat != true
111+
with:
112+
key: ${{ matrix.target }}
113+
82114
# eframe needs a few system libs on Linux for window management, keyboard,
83-
# and OpenGL/X11/Wayland. We install them on the Ubuntu runners regardless
84-
# of arch so both CLI-only and UI builds succeed.
115+
# and OpenGL/X11/Wayland. On self-hosted these persist across runs so this
116+
# is a no-op after the first time; on GH-hosted macOS/Windows the step
117+
# is guarded out anyway.
85118
- name: Install Linux eframe system deps
86119
if: runner.os == 'Linux'
87120
run: |
@@ -279,38 +312,43 @@ jobs:
279312
# x86_64, x86) via cargo-ndk and drops the .so files into the Gradle
280313
# project's jniLibs/ tree, which then packages them into a single
281314
# universal APK. Users pick it once, no per-ABI split.
315+
#
316+
# Runs on self-hosted. The runner has Android SDK + NDK r26c + cargo-ndk
317+
# pre-installed under /opt/android-sdk; the env block below points Gradle
318+
# at those paths so we don't re-download ~1 GB of SDK per release.
282319
android:
283-
runs-on: ubuntu-22.04
320+
runs-on: [self-hosted, linux, x64, mhrv-build]
321+
env:
322+
ANDROID_SDK_ROOT: /opt/android-sdk
323+
ANDROID_HOME: /opt/android-sdk
324+
ANDROID_NDK_HOME: /opt/android-sdk/ndk/26.2.11394342
325+
ANDROID_NDK_ROOT: /opt/android-sdk/ndk/26.2.11394342
326+
JAVA_HOME: /usr/lib/jvm/java-17-openjdk-amd64
284327
steps:
285328
- uses: actions/checkout@v4
286329

287-
- name: Set up JDK 17
288-
uses: actions/setup-java@v4
289-
with:
290-
distribution: temurin
291-
java-version: 17
292-
293-
- name: Set up Android SDK
294-
uses: android-actions/setup-android@v3
295-
with:
296-
cmdline-tools-version: 11076708
297-
298-
- name: Install NDK
299-
run: |
300-
yes | sdkmanager --install "ndk;26.1.10909125" >/dev/null
301-
echo "ANDROID_NDK_HOME=$ANDROID_HOME/ndk/26.1.10909125" >> "$GITHUB_ENV"
302-
330+
# Rust toolchain: idempotent on self-hosted (targets already present),
331+
# kept here so the workflow still works if we ever run it on a GH-hosted
332+
# fallback.
303333
- uses: dtolnay/rust-toolchain@stable
304334
with:
305335
targets: aarch64-linux-android,armv7-linux-androideabi,x86_64-linux-android,i686-linux-android
306336

307-
- name: Install cargo-ndk
308-
run: cargo install cargo-ndk --locked
337+
# Cache cargo + target/ across Android release builds. Four cargo-ndk
338+
# release builds back-to-back with LTO is where the cold cost comes
339+
# from; rust-cache brings warm runs down to ~3–4 min from ~9 min cold.
340+
- uses: Swatinem/rust-cache@v2
341+
with:
342+
key: android-universal
343+
# cargo-ndk writes into `target/<android-triple>/release/`, all
344+
# four of which we want to cache.
345+
workspaces: |
346+
. -> target
309347
310348
# `./gradlew :app:assembleRelease` triggers cargoBuildRelease first
311349
# which invokes cargo-ndk with all four targets, then Gradle packages
312-
# the APK (release buildType signed with the debug keystore — see
313-
# android/app/build.gradle.kts comment explaining why).
350+
# the APK (release buildType signed with the committed release.jks —
351+
# see android/app/build.gradle.kts comment explaining why).
314352
- name: Build release APK
315353
working-directory: android
316354
run: |
@@ -339,6 +377,11 @@ jobs:
339377
path: dist/*.apk
340378
if-no-files-found: error
341379

380+
# release + telegram: lightweight aggregation jobs kept on GH-hosted
381+
# ubuntu-latest. They only download artifacts and call APIs — no build
382+
# tooling needed, no benefit from moving to self-hosted, and keeping them
383+
# off the self-hosted runners avoids contention with Linux build jobs from
384+
# the next tag if two releases overlap.
342385
release:
343386
needs: [build, android]
344387
runs-on: ubuntu-latest

Cargo.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "mhrv-rs"
3-
version = "1.2.2"
3+
version = "1.2.3"
44
edition = "2021"
55
description = "Rust port of MasterHttpRelayVPN -- DPI bypass via Google Apps Script relay with domain fronting"
66
license = "MIT"

android/app/build.gradle.kts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,8 @@ android {
1414
applicationId = "com.therealaleph.mhrv"
1515
minSdk = 24 // Android 7.0 — covers 99%+ of live devices.
1616
targetSdk = 34
17-
versionCode = 122
18-
versionName = "1.2.2"
17+
versionCode = 123
18+
versionName = "1.2.3"
1919

2020
// Ship all four mainstream Android ABIs:
2121
// - arm64-v8a — 95%+ of real-world Android phones since 2019

docs/changelog/v1.2.3.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
<!-- see docs/changelog/v1.1.0.md for the file format: Persian, then `---`, then English. -->
2+
• زیرساخت CI: انتقال build Linux/Android/mipsel به runnerهای self-hosted اختصاصی (Hetzner، ۸ هسته / ۳۱ گیگ RAM، تمام toolchainها از قبل نصب). زمان build کامل رکورد از ~۱۳ دقیقه به کمتر از ~۷ دقیقه کاهش یافت. macOS و Windows همچنان روی runnerهای GitHub باقی می‌مانند
3+
• افزودن Swatinem/rust-cache@v2 به همهٔ job های cargo — buildهای warm زیر یک دقیقه
4+
• نسخهٔ سازندهٔ متصل‌کننده‌ها نیست؛ این release عمدتاً pipeline release جدید ما را exercise می‌کند تا مطمئن شویم همه چیز از runner خودمان سالم بیرون می‌آید
5+
---
6+
• CI infrastructure: Linux / Android / mipsel build jobs moved to dedicated self-hosted runners (Hetzner, 8-core / 31 GB, all toolchains pre-installed). Full release wall time dropped from ~13 min to under ~7 min. macOS and Windows continue to use GitHub-hosted runners
7+
• Add Swatinem/rust-cache@v2 to every cargo job — warm builds are now sub-minute
8+
• No new user-facing features; this release primarily exercises the new pipeline end-to-end to verify everything comes out clean from our own runners

0 commit comments

Comments
 (0)