From 13ccab980c8fe4e81af10702df496981540218e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=9B=B7=E7=94=B5=E8=8A=BD=E8=A1=A3?= Date: Wed, 22 Jul 2026 19:59:00 -0400 Subject: [PATCH] ci: warm a main-branch build cache so release tag builds aren't cold MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit GitHub Actions cache isolation lets a run restore caches only from its own ref or the default branch. Releases run on tag refs and nothing ever ran on main, so release.yml's rust-cache never restored anything — every release compiled all 62 crates cold on five targets (~50 min, gated by Windows at ~49.5 min). warm-cache.yml builds the same release-dist profile with the same rust-cache key on main (dep-affecting pushes — including each release's version-bump commit — plus a weekly refresh against 7-day eviction and manual dispatch). Tag builds then restore a warm default-branch cache; the remaining cost is workspace-crate compilation + the codegen-units=1 thin-LTO link, which is the deliberate release-hardening tradeoff. --- .github/workflows/warm-cache.yml | 85 ++++++++++++++++++++++++++++++++ 1 file changed, 85 insertions(+) create mode 100644 .github/workflows/warm-cache.yml diff --git a/.github/workflows/warm-cache.yml b/.github/workflows/warm-cache.yml new file mode 100644 index 0000000..35f1809 --- /dev/null +++ b/.github/workflows/warm-cache.yml @@ -0,0 +1,85 @@ +name: Warm build cache + +# Release builds run on TAG refs, and GitHub Actions cache isolation only +# lets a run restore caches created on its OWN ref or the DEFAULT branch. +# No workflow ran on `main`, so every release compiled the whole workspace +# cold on all five targets (~50 min wall clock, gated by Windows). This +# workflow builds the same `release-dist` profile on `main` so tag builds +# restore a warm default-branch cache. +# +# Triggers: dependency-affecting pushes to main (each release's version-bump +# commit warms the cache for the NEXT release), a weekly refresh so the +# cache never hits GitHub's 7-day unused-eviction, and manual dispatch. +# +# The setup steps mirror release.yml's build job (toolchain, target, +# dotslash/protoc, rust-cache key) — keep them in lockstep, or the cache +# key won't match and releases go back to cold builds. + +on: + push: + branches: ["main"] + paths: + - "Cargo.lock" + - "Cargo.toml" + - "rust-toolchain.toml" + - ".github/workflows/warm-cache.yml" + schedule: + - cron: "17 5 * * 1" + workflow_dispatch: + +permissions: + contents: read + +env: + CARGO_TERM_COLOR: always + +concurrency: + group: warm-cache + cancel-in-progress: true + +jobs: + warm: + name: warm (${{ matrix.target }}) + strategy: + fail-fast: false + matrix: + include: + - target: aarch64-apple-darwin + os: macos-14 + - target: x86_64-apple-darwin + os: macos-14 + - target: x86_64-unknown-linux-gnu + os: ubuntu-24.04 + - target: aarch64-unknown-linux-gnu + os: ubuntu-24.04-arm + - target: x86_64-pc-windows-msvc + os: windows-2022 + runs-on: ${{ matrix.os }} + steps: + - uses: actions/checkout@v4 + + - name: Install toolchain (rust-toolchain.toml) + run: rustup show + + - name: Add build target + run: rustup target add ${{ matrix.target }} + + - name: Install dotslash (protoc launcher) + run: cargo install dotslash --locked + + - name: Install protoc (Windows PATH fallback) + if: runner.os == 'Windows' + shell: pwsh + run: | + $url = "https://github.com/protocolbuffers/protobuf/releases/download/v29.3/protoc-29.3-win64.zip" + Invoke-WebRequest -Uri $url -OutFile protoc.zip + Expand-Archive protoc.zip -DestinationPath "$env:USERPROFILE\protoc" + Add-Content $env:GITHUB_PATH "$env:USERPROFILE\protoc\bin" + + # Same key as release.yml so tag builds restore this cache verbatim. + - uses: Swatinem/rust-cache@v2 + with: + key: ${{ matrix.target }} + + - name: Build kigi (release-dist) + run: cargo build --profile release-dist -p kigi-bin --locked --target ${{ matrix.target }}