115 lines
5.6 KiB
YAML
115 lines
5.6 KiB
YAML
name: Build Slint (linux)
|
|
|
|
# Builds the Slint app on a stock GitHub-hosted runner. The wall is the qbz_ui
|
|
# rustc (the generated Slint UI = ONE ~1.6M-line module): its peak memory DEMAND
|
|
# is ~30 GB (measured RSS+Swap, 2026-06) and it is FRONTEND-bound — codegen knobs
|
|
# (codegen-units, opt-level, CARGO_BUILD_JOBS, -Z threads) barely move it (jobs=1
|
|
# only shaved ~3 GB vs cargo defaults). So the build is NOT made to fit by tuning;
|
|
# it is made to fit by giving it enough RAM+SWAP to hold ~30 GB. A stock
|
|
# `ubuntu-24.04` runner has ~16 GB RAM, so this job adds a large swapfile so
|
|
# RAM(16) + swap(~4 base + 18) ≈ 38 GB comfortably exceeds the ~30 GB demand: the
|
|
# resident working set stays near RAM size while cold pages page out (slow but it
|
|
# completes). The MIN-tier rustc env below keeps the resident set as low as
|
|
# possible. rust-cache (added below) makes this heavy compile happen ONCE per
|
|
# qbz_ui change, not on every push — that, not the peak, is the minute saver.
|
|
# Build-only for now (no signing/bundling).
|
|
|
|
on:
|
|
# Manual trigger ONLY (pick the ref in the Actions UI). Repo policy: public
|
|
# workflows fire on release tags, never on plain pushes — a push to main IS
|
|
# a release merge, and the tag that follows immediately fires the real
|
|
# release builds, so an auto-build here would just double-burn ~2h of
|
|
# runner time for nothing.
|
|
workflow_dispatch:
|
|
|
|
# A new push to slint-mvp cancels the older in-flight build — only the latest
|
|
# commit matters, and stacked ~20-min builds are the main minute-burn.
|
|
concurrency:
|
|
group: build-slint-${{ github.ref }}
|
|
cancel-in-progress: true
|
|
|
|
jobs:
|
|
build:
|
|
runs-on: ubuntu-24.04
|
|
timeout-minutes: 180
|
|
steps:
|
|
- uses: actions/checkout@v7
|
|
|
|
- name: Free disk + swap
|
|
run: |
|
|
echo "::group::before"; df -h /; free -h; echo "::endgroup::"
|
|
# On ubuntu-24.04 there is no separate large /mnt disk — everything is
|
|
# on the 72 GB root (~16 GB free after the image). Reclaim the big
|
|
# preinstalled toolchains we don't need (~25-30 GB) so the cargo target
|
|
# fits, then add a modest swap cushion for the qbz-slint rustc peak.
|
|
sudo rm -rf /usr/share/dotnet /opt/ghc /usr/local/lib/android \
|
|
/opt/hostedtoolcache /usr/local/share/boost /usr/share/swift \
|
|
/usr/local/lib/node_modules || true
|
|
sudo docker image prune --all --force || true
|
|
# The runner ships an active /swapfile (~4 GB); add a LARGE extra swap
|
|
# so RAM(16) + swap(~4 + 18) ≈ 38 GB holds the measured ~30 GB qbz_ui
|
|
# demand (frontend-bound; not tunable away). 8 GB was NOT enough
|
|
# (16+4+8 ≈ 28 GB < 30 GB → OOM risk). Guarded so a swap hiccup never
|
|
# fails the job.
|
|
( sudo fallocate -l 18G /swap_extra \
|
|
&& sudo chmod 600 /swap_extra \
|
|
&& sudo mkswap /swap_extra \
|
|
&& sudo swapon /swap_extra ) || echo "extra swap skipped (non-fatal)"
|
|
echo "::group::after"; df -h /; free -h; echo "::endgroup::"
|
|
|
|
- name: System dependencies
|
|
run: |
|
|
sudo apt-get update
|
|
sudo apt-get install -y --no-install-recommends \
|
|
build-essential pkg-config cmake clang libclang-dev mold nasm \
|
|
libasound2-dev libjack-jackd2-dev \
|
|
libfontconfig1-dev libfreetype-dev \
|
|
libxkbcommon-dev libwayland-dev libxcb1-dev \
|
|
libgl1-mesa-dev libegl1-mesa-dev \
|
|
libdbus-1-dev libssl-dev \
|
|
libharfbuzz-dev libjbig2dec0-dev libopenjp2-7-dev \
|
|
libjpeg-dev zlib1g-dev libgumbo-dev
|
|
|
|
- name: Rust toolchain (pinned dated nightly — build uses -Z threads)
|
|
# Pinned (not floating @nightly) so rustc -V is byte-stable across runs:
|
|
# rust-cache embeds the rustc version in its key, and a floating nightly
|
|
# re-keys the cache + invalidates every Cargo fingerprint daily (the
|
|
# from-scratch-every-run waste). Bump this date deliberately when a newer
|
|
# nightly feature is actually needed.
|
|
uses: dtolnay/rust-toolchain@master
|
|
with:
|
|
toolchain: nightly-2026-06-23
|
|
|
|
- name: Cargo cache (Swatinem/rust-cache)
|
|
# THE biggest minute-saver: caches ~/.cargo + crates/target so a push
|
|
# that only touches controllers restores the prebuilt qbz-ui rlib (the
|
|
# ~20 GB / ~20-min compilation unit) instead of recompiling it; only the
|
|
# cheap qbz bin then rebuilds + links. `workspaces` MUST point at crates/
|
|
# (manifest is crates/Cargo.toml, artifacts land in crates/target — not
|
|
# the default `. -> target`). save-if gates cache WRITES to slint-mvp so
|
|
# dispatch/PR runs read but don't churn the 10 GB Actions cache budget.
|
|
uses: Swatinem/rust-cache@v2
|
|
with:
|
|
workspaces: crates -> target
|
|
shared-key: slint-linux
|
|
cache-on-failure: true
|
|
save-if: ${{ github.ref == 'refs/heads/main' || github.ref == 'refs/heads/slint-mvp' }}
|
|
|
|
- name: Build qbz-slint (memory-tuned, MIN tier)
|
|
env:
|
|
CARGO_INCREMENTAL: '0'
|
|
CARGO_BUILD_JOBS: '1'
|
|
CARGO_PROFILE_RELEASE_CODEGEN_UNITS: '256'
|
|
CARGO_PROFILE_RELEASE_OPT_LEVEL: '2'
|
|
RUSTFLAGS: '-C link-arg=-fuse-ld=mold -Z threads=1'
|
|
run: |
|
|
cargo build --release --manifest-path crates/Cargo.toml -p qbz
|
|
echo "::group::result"; ls -lh crates/target/release/qbz; df -h /; free -h; echo "::endgroup::"
|
|
|
|
- name: Upload binary
|
|
uses: actions/upload-artifact@v7
|
|
with:
|
|
name: qbz-linux-x86_64
|
|
path: crates/target/release/qbz
|
|
if-no-files-found: error
|