From ef3bdd3433c11fe8eae00c540c46885d34a80268 Mon Sep 17 00:00:00 2001 From: bherbruck Date: Sat, 17 Oct 2026 06:47:41 +0000 Subject: [PATCH] CI: main and merge-queue runs share the work with the self-hosted runner Clippy, the doc tests and test shards 1-2 of pushes to main and merge-queue groups run on the self-hosted runner, alongside GitHub's runners for everything else. Pull requests, the nightly run and Run workflow stay on GitHub's runners. Clippy and the doc tests keep warm build directories outside the checkout (scripts/ci/warm-target.sh). The test archive is still built on GitHub's runners: the self-hosted machine has a newer glibc, so binaries built there don't start on ubuntu-24.04. Co-Authored-By: Claude Opus 5.5 --- .github/workflows/ci.yml | 27 ++++++++++++++++++++++----- scripts/ci/warm-target.sh | 16 ++++++++++++++++ 2 files changed, 38 insertions(+), 5 deletions(-) create mode 100755 scripts/ci/warm-target.sh diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index be4e28f9..4d1ac13d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -8,6 +8,13 @@ # Tests are built once and run in 4 shards. A few heavy tests (see .config/nextest.toml) are # skipped on pull requests and run on pushes to main and nightly. # Cross-compilation is opt-in through Run workflow; release builds remain in release.yml. +# Pushes to main and merge-queue groups use both pools: Clippy, the doc tests and test shards +# 1-2 run on the self-hosted runner (`self-hosted-fast`, warm build directories via +# scripts/ci/warm-target.sh), everything else on GitHub's runners. The test archive is built on +# GitHub's runners: the self-hosted machine has a newer glibc, so its binaries wouldn't start +# on ubuntu-24.04, while the archive runs there unchanged (same /home/runner/work checkout +# path). Pull requests, the nightly run and Run workflow use GitHub's runners only; the +# self-hosted runner refuses any job that isn't a push to main or a merge-queue group. name: CI on: @@ -134,14 +141,19 @@ jobs: name: Native Linux Clippy needs: changes if: needs.changes.outputs.native == 'true' - runs-on: ubuntu-24.04 + runs-on: ${{ (github.event_name == 'merge_group' || (github.event_name == 'push' && github.ref == 'refs/heads/main')) && 'self-hosted-fast' || 'ubuntu-24.04' }} timeout-minutes: 30 steps: - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + - name: Warm build directory (self-hosted runner) + if: runner.environment == 'self-hosted' + run: scripts/ci/warm-target.sh clippy - uses: dtolnay/rust-toolchain@stable with: components: clippy - - uses: Swatinem/rust-cache@6323deb102c322ba6fcbdcafc7e3dddab59af2b6 # v2.9.2 + # The self-hosted runner keeps its build directory and Cargo home instead. + - if: runner.environment == 'github-hosted' + uses: Swatinem/rust-cache@6323deb102c322ba6fcbdcafc7e3dddab59af2b6 # v2.9.2 with: key: native-clippy - name: Clippy @@ -200,7 +212,7 @@ jobs: tests: name: Native Linux tests (${{ matrix.shard }}/4) needs: [changes, build-tests] - runs-on: ubuntu-24.04 + runs-on: ${{ ((github.event_name == 'merge_group' || (github.event_name == 'push' && github.ref == 'refs/heads/main')) && matrix.shard <= 2) && 'self-hosted-fast' || 'ubuntu-24.04' }} timeout-minutes: 60 strategy: fail-fast: false @@ -356,7 +368,7 @@ jobs: name: Doc tests needs: changes if: needs.changes.outputs.native == 'true' - runs-on: ubuntu-24.04 + runs-on: ${{ (github.event_name == 'merge_group' || (github.event_name == 'push' && github.ref == 'refs/heads/main')) && 'self-hosted-fast' || 'ubuntu-24.04' }} timeout-minutes: 45 env: CARGO_INCREMENTAL: "0" @@ -365,8 +377,13 @@ jobs: SCCACHE_IGNORE_SERVER_IO_ERROR: "1" steps: - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + - name: Warm build directory (self-hosted runner) + if: runner.environment == 'self-hosted' + run: scripts/ci/warm-target.sh doc-tests - uses: dtolnay/rust-toolchain@stable - - uses: Swatinem/rust-cache@6323deb102c322ba6fcbdcafc7e3dddab59af2b6 # v2.9.2 + # The self-hosted runner keeps its build directory and Cargo home instead. + - if: runner.environment == 'github-hosted' + uses: Swatinem/rust-cache@6323deb102c322ba6fcbdcafc7e3dddab59af2b6 # v2.9.2 with: key: doc-tests - name: Set up compiler cache diff --git a/scripts/ci/warm-target.sh b/scripts/ci/warm-target.sh new file mode 100755 index 00000000..6bbb3aed --- /dev/null +++ b/scripts/ci/warm-target.sh @@ -0,0 +1,16 @@ +#!/usr/bin/env bash +# Self-hosted runner only: keep a job's Cargo build directory between runs, outside the +# checkout (actions/checkout's clean would delete it), and point CARGO_TARGET_DIR at it for the +# rest of the job. Usage: warm-target.sh NAME +# Each self-hosted runner has its own /home/runner, so two never share a directory. +set -euo pipefail +name=${1:?usage: warm-target.sh NAME} +dir=/home/runner/work/cargo-target/$name +# Start over when it has grown past 40 GB: old dependency versions pile up. +if [ -d "$dir" ] && [ "$(du -sm "$dir" | cut -f1)" -gt 40000 ]; then + echo "warm-target: $dir is over 40 GB, starting a fresh build" + rm -rf "$dir" +fi +mkdir -p "$dir" +echo "CARGO_TARGET_DIR=$dir" >> "$GITHUB_ENV" +echo "warm-target: $dir ($(du -sh "$dir" | cut -f1))"