Skip to content

Where people and agents ship software together. The open-source git platform for the whole job: issues, agents, checks and deploys to the edge.

The runner base image has what Tauri builds against on Linux, so CI's desktop job installs nothing #288

Mergedsyntaqx merged worktree-agent-a0eb712dcd50c1528 into main
syntaqxopened this pull request

Follows #245, which baked sccache, worker-build and the musl target into the runner's base. This does the same for the per-run install that still costs the most: Tauri's Linux system packages in CI's Desktop app job.

What it does

  • services/runner/base/Dockerfile: a new layer after Java, .NET and Ruby (before the Rust build tools) installs libwebkit2gtk-4.1-dev libxdo-dev libayatana-appindicator3-dev librsvg2-dev, without Recommends. The rest of scripts/apt-install.sh tauri (build-essential, curl, wget, file, libssl-dev) was in the base already. base.json gains a webkit2gtk version (scripts/deploy/image.mjs).
  • scripts/apt-install.sh installs nothing when every package of the set is installed already, and --check writes installed=true|false to the step's output.
  • ci.yml (Desktop app), desktop-release.yml (Linux), caches.yml (desktop-linux): a --check step first. When the image has the packages, the apt cache restore and the install are both skipped. Otherwise (a self-hosted runner, or an older image) they run as before.
  • scripts/deploy/deploy.test.mjs: fails when the script's tauri set has a package the base doesn't install. Without this test, a package added to the script alone would be skipped on g1t's machines.
  • Docs: the actions guide says the Tauri packages are there, and the CONTRIBUTING cache table notes the apt-tauri- entry is only used where the image lacks them.

Measured (before)

These are the last 30 CI runs' Desktop app job (g1t run view):

StepMedianRange
What Tauri needs on Linux57.7 s26 to 136 s
Cache apt's downloads9.8 s5 to 69 s
Desktop app job, whole143 s65 to 367 s

Expected after: both steps are skipped, and the --check step takes well under a second (0.01 s in the image). That saves about 68 s per run at the median and up to about 3.4 minutes at the worst, so the Desktop job drops to around 75 s. A cold apt cache can no longer cause the 30-minute timeout. The desktop release's Linux build and the Caches workflow's desktop-linux job save the same minute each time they run.

Image size

The new layer is 0.97 GB unpacked (by base.json's size_bytes measure; docker history shows 743 MB), so the base grows from 4.68 GB to about 5.65 GB (+21%). With Recommends the layer would be 1.58 GB: the extra 207 packages are GStreamer plugins, FFmpeg, VA/VDPAU/Vulkan drivers, fonts and pocketsphinx, none of which a build loads, so they're left out. The biggest required pieces are libllvm15 (mesa), libwebkit2gtk-4.1-0 and libicu-dev.

Verified

  • In a test image (the current base plus this layer): apt-install.sh tauri --check → installed=true, and apt-install.sh tauri skips in 0.01 s. On the current base, --check → installed=false and the install runs as before.
  • In that image, with nothing else installed, the desktop app's tests pass (cargo test --manifest-path apps/desktop/src-tauri/Cargo.toml: 55 passed, 3 ignored). tauri build --bundles deb,rpm,appimage also makes all three bundles, so leaving out Recommends doesn't break the release's AppImage.
  • cargo test -p g1t-actions --test repository_workflows passes (20). The new deploy test passes.

Not baked in, and why

  • The tauri-windows set (clang, LLVM, lld, NSIS), cargo-xwin, zig and cargo-zigbuild: only the releases' cross builds and the Caches workflow use them, and Caches runs those jobs only when an entry is missing (none ran in the last 60 runs). LLVM and clang alone would add more than half a GB.
  • worker-build's own downloads (wasm-bindgen, esbuild, wasm-opt, restored from worker-build-tools-… in 7 to 12 s per Rust build job): wasm-bindgen's version follows Cargo.lock, so a baked copy would go stale on the next bump. This is a possible follow-up.
  • cargo-nextest: nothing uses it, and switching the test runner is out of scope.
  • worker-build, sccache and the wasm32/musl targets are already in the base (#245). Their steps take 1 to 2 s.

Rollout

The base is built and pushed by hand (or by runner-base.yml once a self-hosted docker runner is registered and RUNNER_BASE_SELF_HOSTED is set):

  1. On a machine with Docker that's logged in to Cloudflare's registry, on this branch: node scripts/deploy.mjs build-base. It builds on the previous base's layers (only this layer and the ones after it are new), pushes g1t-runner:base-<date>-<hash>, and rewrites services/runner/base.json.
  2. Commit services/runner/base.json to this branch. Until then, CI's TypeScript job fails on "services/runner/base.json records the base its folder builds". That guard is intended: a deploy would refuse to build the runner's image on a stale base.json too.
  3. Merge. The deploy's runner-image stage (node scripts/deploy.mjs image) builds the runner's image on the new base, and every hosted job after that starts from it.
  4. Check on the next CI run that "Is what Tauri needs on Linux installed" prints installed=true and the two steps after it are skipped.

Don't merge before step 2. With the Dockerfile changed and base.json not, the runner's deploy stops: "services/runner/base has changed since base.json was written". The workflow and script changes on their own are safe on the old image, which installs as before.

syntaqxcommented

Checked against the real base: on this branch, node scripts/deploy.mjs build-base --no-push built base-20261021-ac4b2283607a at 5,636,446,773 bytes, against 4,678,542,046 now (+0.96 GB), with webkit2gtk 2.50.6. In it, as the job's user, apt-install.sh tauri --check says installed=true, and worker-build 0.8.7 and sccache 0.18.0 are still there. The rebuild also picked up Rust 1.99.1 and Docker 29.9.2. Nothing was pushed, base.json wasn't committed, and the image has been removed. CI's TypeScript failure is the intended base.json guard (rollout step 2). Rust (3) failed in gitedge::a_fetch_for_what_the_mirror_lacks_is_behind (a log assertion, in a test from #279; this PR changes no Rust), and that job is being rerun.

syntaqxmerged this·

All checks have passed

2 passed · on d1da66d

Workflows

CI / pull_request — CI passedDetails
Dependency review — No dependency changesDetails

Merged and closed: the branch can be deleted safely

Everything on it is in its base now.

Sign in to comment.