Files
jellytau/.gitea/workflows/build-and-test.yml
T
dtourolle a7365b9511
🏗️ Build and Test JellyTau / Run Tests (push) Successful in 20m10s
Publish Documentation / Build & publish docs to gitea-pages (push) Successful in 5m17s
Traceability Validation / Check Requirement Traces (push) Successful in 15s
Build & Release / Run Tests (push) Successful in 13m59s
🏗️ Build and Test JellyTau / Android Compile Check (push) Successful in 4m13s
Build & Release / Build Linux (push) Failing after 16m29s
Build & Release / Build Android (push) Canceled after 0s
Build & Release / Create Release (push) Canceled after 0s
Build & Release / Build Windows (push) Canceled after 11m6s
fix(ci): cache the cargo registry, not the 16 GB target dir
The runner's 74 GB disk kept filling. Measured on the box: 24 GB of
act cache, 23.18 GB of it created in 20 days -- ~1.15 GB/day against a
30-day-unused / 90-day-used GC, so it could never converge.

Cause: src-tauri/target (16 GB locally: 9.6G debug, 3.2G release, 2.4G
android) was cached under five separate keys, all keyed on
hashFiles('**/Cargo.lock'). The release script stamps the version into
Cargo.lock, so all five invalidated on every chore(release) -- 32
distinct lockfile revisions in three months.

- Cache only registry/index, registry/cache and git/db. registry/src is
  omitted as well: cargo re-extracts it from the 155 MB of .crate
  tarballs rather than storing 1.1 GB extracted.
- Collapse the five per-job keys into one shared cargo-registry key.
  They existed to keep debug/release target artifacts from clobbering
  each other; with target uncached, registry contents are
  target-independent and every job wants the same crates.
- Split cargo-xwin into its own key. It tracks the xwin version in the
  builder image, not our lockfile, so keying it on Cargo.lock was
  re-downloading the whole Windows SDK on every release bump.
- CARGO_INCREMENTAL=0: never reused across runs, 3.5 GB of the debug dir.
- Installer artifact retention 30d -> 7d; tagged releases carry the
  binaries anyway.

Inflow drops from ~5 GB to ~150 MB per lockfile change. Tradeoff: Rust
jobs now compile cold every run (~31min vs ~9min on a cache hit for the
Linux release build). Most runs already paid that, since a release bump
invalidated every key. sccache with a hard size cap is the way back if
it bites.
2026-08-21 11:59:28 +02:00

183 lines
7.2 KiB
YAML

name: '🏗️ Build and Test JellyTau'
on:
push:
branches:
- master
paths-ignore:
- '**/*.md'
pull_request:
branches:
- master
paths-ignore:
- '**/*.md'
workflow_dispatch:
env:
# Incremental state is never reused between CI runs -- pure disk cost.
CARGO_INCREMENTAL: 0
jobs:
test:
name: Run Tests
# A release push triggers build-release.yml on the tag, which runs this exact
# test suite itself — and on a single-slot runner the two ~1h workflows would
# otherwise serialize/contend. Skip the duplicate for chore(release) commits.
# (head_commit is absent on pull_request/workflow_dispatch; startsWith(null,…)
# is false there, so those events still run.)
if: "!startsWith(github.event.head_commit.message, 'chore(release)')"
runs-on: linux/amd64
container:
image: gitea.tourolle.paris/dtourolle/jellytau-builder:latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Cache Rust dependencies
uses: actions/cache@v3
with:
# Registry only -- never src-tauri/target. That directory is ~16 GB and
# was cached under five separate keys, which filled the runner's 74 GB
# disk at ~1.15 GB/day (23 GB in 20 days, measured Aug 2026).
# registry/src is omitted too: cargo re-extracts it for free from
# registry/cache (155 MB of .crate tarballs vs 1.1 GB extracted).
path: |
~/.cargo/registry/index
~/.cargo/registry/cache
~/.cargo/git/db
# One shared key across every job. The old per-job keys existed to stop
# debug/release target artifacts clobbering each other; with target no
# longer cached, registry contents are target-independent, so all jobs
# want the same crates. First job to finish saves; the rest restore.
key: ${{ runner.os }}-cargo-registry-${{ hashFiles('**/Cargo.lock') }}
restore-keys: |
${{ runner.os }}-cargo-registry-
- name: Cache Node dependencies
uses: actions/cache@v3
with:
path: |
~/.bun/install/cache
node_modules
key: ${{ runner.os }}-bun-${{ hashFiles('**/bun.lock') }}
restore-keys: |
${{ runner.os }}-bun-
- name: Install dependencies
run: |
bun install
# Tripwire for domain-taxonomy leaks into the presentation layer (a
# multi-type includeItemTypes query defining a category in the frontend).
# See scripts/check-frontend-boundary.sh and
# docs/specs/scoped-search-boundary.md.
- name: Check frontend/backend boundary
run: bash scripts/check-frontend-boundary.sh
# The docs are the maintained source of truth for architecture and
# process, and they cross-reference each other heavily. A rename that
# misses a link turns a doc into a dead end silently. Pure shell + git —
# no tool is installed at job time.
- name: Check documentation links
run: bash scripts/check-doc-links.sh
- name: Run frontend tests
run: |
bunx svelte-kit sync
bun run test
# CLAUDE.md has required `cargo fmt` + `cargo clippy` before every commit
# for as long as the rule has existed, but nothing in CI checked either,
# so the requirement rested entirely on memory. Both components are baked
# into the builder image (Dockerfile.builder: `rustup component add
# rustfmt clippy`) — nothing is installed at job time.
- name: Check Rust formatting
run: |
cd src-tauri
cargo fmt --all -- --check
# Clippy is a hard gate. It was advisory while the tree carried a warning
# backlog; that backlog is gone (0 warnings on 1.97.1, the pinned
# toolchain), so a warning here is now new breakage rather than old noise.
#
# This only means anything because src-tauri/rust-toolchain.toml pins the
# compiler: clippy's lint set moves between releases, so an unpinned gate
# would fail on whatever the runner happened to install. The pin and this
# flag stand or fall together — if you unpin, drop this back to advisory.
- name: Run clippy
run: |
cd src-tauri
cargo clippy --all-targets -- -D warnings
- name: Run Rust tests
run: |
cd src-tauri
cargo test
cd ..
# Fast per-commit Android compile check. This does NOT build a shippable APK:
# the full signed release APK is built only on tag pushes by build-release.yml
# (which runs sync-android-sources.sh + signing). Running the full bundle here
# too would duplicate a ~15min build and, without the sync step, produced an
# unsigned APK missing our custom sources/icons/proguard rules anyway.
# `cargo check` for the Android target (~1min) catches Android-specific Rust
# breakage without linking, bundling, or signing.
android-check:
name: Android Compile Check
runs-on: linux/amd64
needs: test
container:
image: gitea.tourolle.paris/dtourolle/jellytau-builder:latest
env:
ANDROID_HOME: /opt/android-sdk
ANDROID_SDK_ROOT: /opt/android-sdk
NDK_HOME: /opt/android-sdk/ndk/27.0.11902837
ANDROID_NDK_HOME: /opt/android-sdk/ndk/27.0.11902837
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Cache Rust dependencies
uses: actions/cache@v3
with:
# Registry only -- never src-tauri/target. That directory is ~16 GB and
# was cached under five separate keys, which filled the runner's 74 GB
# disk at ~1.15 GB/day (23 GB in 20 days, measured Aug 2026).
# registry/src is omitted too: cargo re-extracts it for free from
# registry/cache (155 MB of .crate tarballs vs 1.1 GB extracted).
path: |
~/.cargo/registry/index
~/.cargo/registry/cache
~/.cargo/git/db
# One shared key across every job. The old per-job keys existed to stop
# debug/release target artifacts clobbering each other; with target no
# longer cached, registry contents are target-independent, so all jobs
# want the same crates. First job to finish saves; the rest restore.
key: ${{ runner.os }}-cargo-registry-${{ hashFiles('**/Cargo.lock') }}
restore-keys: |
${{ runner.os }}-cargo-registry-
- name: Cache Node dependencies
uses: actions/cache@v3
with:
path: |
~/.bun/install/cache
node_modules
key: ${{ runner.os }}-bun-${{ hashFiles('**/bun.lock') }}
restore-keys: |
${{ runner.os }}-bun-
- name: Install dependencies
run: bun install
- name: Cargo check (aarch64-linux-android)
run: |
TC="$NDK_HOME/toolchains/llvm/prebuilt/linux-x86_64/bin"
export CARGO_TARGET_AARCH64_LINUX_ANDROID_LINKER="$TC/aarch64-linux-android24-clang"
export CC_aarch64_linux_android="$TC/aarch64-linux-android24-clang"
export AR_aarch64_linux_android="$TC/llvm-ar"
cd src-tauri
cargo check --target aarch64-linux-android --lib