From 9746d75ce5b81d8bf23612188ab741cdc8d6cde9 Mon Sep 17 00:00:00 2001 From: FredApps Date: Wed, 11 Nov 2026 13:44:07 +0100 Subject: [PATCH 1/4] gate: opt-in sccache for the workspace's own crates rust-cache keeps dependencies but not the workspace's crates, so every gate run compiles all of them again. With `sccache: true` the gate wraps rustc in sccache over the GitHub Actions cache. It writes where the dependency cache saves (the default branch, opted-in dispatches) and only reads elsewhere; SCCACHE_GHA_RW_MODE in `env` overrides that. Off by default, so no caller changes. Co-Authored-By: Claude Opus 5.5 --- .github/workflows/gate.yml | 24 ++++++++++++++++++++++++ README.md | 9 +++++++-- 2 files changed, 31 insertions(+), 2 deletions(-) diff --git a/.github/workflows/gate.yml b/.github/workflows/gate.yml index 84a5f75..9c01b9c 100644 --- a/.github/workflows/gate.yml +++ b/.github/workflows/gate.yml @@ -78,6 +78,11 @@ on: type: boolean required: false default: true + sccache: + description: "Also cache the workspace crates' compiled libraries (which rust-cache leaves out) with sccache in the GitHub Actions cache. It writes where the dependency cache is saved (pushes to the default branch, opted-in manual runs); other runs read those entries. SCCACHE_GHA_RW_MODE in `env` overrides that. Test executables are never cached" + type: boolean + required: false + default: false cache-version: description: "Bump to start the dependency cache afresh" type: string @@ -266,6 +271,25 @@ jobs: save-if: ${{ github.event_name != 'pull_request' && (github.ref_name == github.event.repository.default_branch || (inputs.cache-save-on-dispatch && github.event_name == 'workflow_dispatch')) }} cache-on-failure: true + # After rust-cache, so its key does not depend on RUSTC_WRAPPER. + - name: Install sccache + if: inputs.sccache + uses: Mozilla-Actions/sccache-action@fc920bf0ec8de6ee65d409111f7ec508035751ba # v0.0.11 + with: + version: v0.18.0 + + - name: Use sccache + if: inputs.sccache + shell: bash + env: + WRITES: ${{ github.event_name != 'pull_request' && (github.ref_name == github.event.repository.default_branch || (inputs.cache-save-on-dispatch && github.event_name == 'workflow_dispatch')) }} + run: | + echo "SCCACHE_GHA_ENABLED=true" >> "$GITHUB_ENV" + echo "RUSTC_WRAPPER=sccache" >> "$GITHUB_ENV" + if [ -z "${SCCACHE_GHA_RW_MODE:-}" ] && [ "$WRITES" != true ]; then + echo "SCCACHE_GHA_RW_MODE=READ_ONLY" >> "$GITHUB_ENV" + fi + - name: Gate shell: bash env: diff --git a/README.md b/README.md index 80ba23d..fa1b471 100644 --- a/README.md +++ b/README.md @@ -492,7 +492,11 @@ The quality gate for an app's pull requests and pushes to main. It runs `command `cache-save-on-dispatch: true`. The restore prefix includes the canonical root `[profile]` table; dependency, version and comment edits do not discard reusable dependency artifacts. rust-cache still keys on lockfiles, member manifests, toolchain and build environment, and - Cargo validates restored fingerprints. Bump `cache-version` to start afresh. + Cargo validates restored fingerprints. Bump `cache-version` to start afresh; +- with `sccache: true`, sccache (through the GitHub Actions cache) for the workspace's own + library crates, which rust-cache doesn't keep. It writes where the dependency cache saves and + only reads elsewhere; set `SCCACHE_GHA_RW_MODE` in `env` to choose. Test, binary and + proc-macro crates aren't cacheable, so it mainly helps workspaces with many library crates. After the gate, the job fails if `Cargo.lock` changed. Legs run with `fail-fast: false`; each has `timeout-minutes` (default 60). A job only some apps need, such as a web build or a Windows-only @@ -866,7 +870,8 @@ with the rustup `llvm-profdata` and `llvm-cov` tools. Pass `shards: 1` to keep the single `cargo llvm-cov` job. Sharded runs skip doctests, because nextest does not run them. -The scan job frees unused runner SDKs before either Rust coverage path. Sharded +The scan job frees unused runner SDKs before either Rust coverage path. The archive build +frees them in the background, so the build starts at once. Sharded coverage merges and removes raw profiles before extracting the test archive, then releases the compressed archive and temporary binaries as they are consumed. Disk-space snapshots in the logs show headroom before cleanup and aggregation. From f4d0962352caad53dcb198e4ae861e04648c48bf Mon Sep 17 00:00:00 2001 From: FredApps Date: Wed, 11 Nov 2026 13:44:07 +0100 Subject: [PATCH 2/4] sonarcloud: free disk space in the background in the archive build As gate.yml does: the build starts at once and the space is free before it needs it. The scan job's cleanup is unchanged. Co-Authored-By: Claude Opus 5.5 --- .github/workflows/sonarcloud.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/sonarcloud.yml b/.github/workflows/sonarcloud.yml index 13d12d3..af2168e 100644 --- a/.github/workflows/sonarcloud.yml +++ b/.github/workflows/sonarcloud.yml @@ -219,8 +219,10 @@ jobs: run: | echo "CRAFT_FONTS_DIR=$CRAFT_FONTS_PATH" >> "$GITHUB_ENV" echo "CRAFT_FONTS_REQUIRED=1" >> "$GITHUB_ENV" + # In the background, as in gate.yml: the space is free before the build needs it. - name: Free disk space - run: sudo rm -rf /usr/share/dotnet /usr/local/lib/android /opt/ghc /opt/hostedtoolcache/CodeQL + run: | + nohup sudo rm -rf /usr/share/dotnet /usr/local/lib/android /opt/ghc /opt/hostedtoolcache/CodeQL /dev/null 2>&1 & - name: Install Linux build dependencies uses: storytold/craft-common-actions/actions/install-apt-packages@main with: From 89b1e8c6bac2296cdc78184c74deedf15463f1aa Mon Sep 17 00:00:00 2001 From: FredApps Date: Wed, 11 Nov 2026 13:56:50 +0100 Subject: [PATCH 3/4] gate: start sccache's cache afresh when lint settings change sccache v0.18.0 leaves --check-cfg out of its key on purpose, and a cached clippy-driver run doesn't see clippy.toml, so a cached compile replays the warnings it had. The cache's version (SCCACHE_GHA_VERSION) now comes from cache-version and a hash of every Cargo.toml, build.rs and clippy.toml, unless the caller sets it. The README also says what sccache can't see: files a procedural macro reads without rustc tracking them. Co-Authored-By: Claude Opus 5.5 --- .github/workflows/gate.yml | 9 ++++++++- README.md | 6 ++++++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/.github/workflows/gate.yml b/.github/workflows/gate.yml index 9c01b9c..f8f3474 100644 --- a/.github/workflows/gate.yml +++ b/.github/workflows/gate.yml @@ -79,7 +79,7 @@ on: required: false default: true sccache: - description: "Also cache the workspace crates' compiled libraries (which rust-cache leaves out) with sccache in the GitHub Actions cache. It writes where the dependency cache is saved (pushes to the default branch, opted-in manual runs); other runs read those entries. SCCACHE_GHA_RW_MODE in `env` overrides that. Test executables are never cached" + description: "Also cache the workspace crates' compiled libraries (which rust-cache leaves out) with sccache in the GitHub Actions cache. It writes where the dependency cache is saved (pushes to the default branch, opted-in manual runs); other runs read those entries. SCCACHE_GHA_RW_MODE in `env` overrides that. Test executables are never cached. Its cache starts afresh when cache-version or a Cargo.toml, build.rs or clippy.toml changes; bump cache-version when files a procedural macro reads change (see the README)" type: boolean required: false default: false @@ -283,9 +283,16 @@ jobs: shell: bash env: WRITES: ${{ github.event_name != 'pull_request' && (github.ref_name == github.event.repository.default_branch || (inputs.cache-save-on-dispatch && github.event_name == 'workflow_dispatch')) }} + # sccache's key leaves out lint settings that only change diagnostics (`--check-cfg`, + # clippy.toml), so a cached compile would replay its old warnings. A change to the files + # that declare them, or to cache-version, starts a fresh sccache cache instead. + VERSION: ${{ inputs.cache-version }}-${{ hashFiles('**/Cargo.toml', '**/build.rs', '**/clippy.toml', '**/.clippy.toml') }} run: | echo "SCCACHE_GHA_ENABLED=true" >> "$GITHUB_ENV" echo "RUSTC_WRAPPER=sccache" >> "$GITHUB_ENV" + if [ -z "${SCCACHE_GHA_VERSION:-}" ]; then + echo "SCCACHE_GHA_VERSION=$VERSION" >> "$GITHUB_ENV" + fi if [ -z "${SCCACHE_GHA_RW_MODE:-}" ] && [ "$WRITES" != true ]; then echo "SCCACHE_GHA_RW_MODE=READ_ONLY" >> "$GITHUB_ENV" fi diff --git a/README.md b/README.md index fa1b471..8c4fcc3 100644 --- a/README.md +++ b/README.md @@ -497,6 +497,12 @@ The quality gate for an app's pull requests and pushes to main. It runs `command library crates, which rust-cache doesn't keep. It writes where the dependency cache saves and only reads elsewhere; set `SCCACHE_GHA_RW_MODE` in `env` to choose. Test, binary and proc-macro crates aren't cacheable, so it mainly helps workspaces with many library crates. + sccache's cache starts afresh when `cache-version` or any `Cargo.toml`, `build.rs` or + `clippy.toml` changes, because its key leaves out settings that only change diagnostics + (`--check-cfg` declarations, clippy's configuration). It also can't see files a procedural + macro reads without rustc tracking them (some asset-embedding macros): don't opt in while + such files change often, or bump `cache-version` when they do. `SCCACHE_GHA_VERSION` in + `env` sets the cache's version instead; After the gate, the job fails if `Cargo.lock` changed. Legs run with `fail-fast: false`; each has `timeout-minutes` (default 60). A job only some apps need, such as a web build or a Windows-only From e59a0c94ab5b22932ffd9220ea4c035b00942bfb Mon Sep 17 00:00:00 2001 From: FredApps Date: Wed, 11 Nov 2026 13:57:21 +0100 Subject: [PATCH 4/4] gate: key sccache's cache on Cargo.toml and build.rs only clippy records clippy.toml in its dep-info, so sccache already sees it. The one setting sccache leaves out is --check-cfg, declared in Cargo.toml lints and build scripts. Correct the comment and README. Co-Authored-By: Claude Opus 5.5 --- .github/workflows/gate.yml | 11 ++++++----- README.md | 6 +++--- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/.github/workflows/gate.yml b/.github/workflows/gate.yml index f8f3474..3997bf3 100644 --- a/.github/workflows/gate.yml +++ b/.github/workflows/gate.yml @@ -79,7 +79,7 @@ on: required: false default: true sccache: - description: "Also cache the workspace crates' compiled libraries (which rust-cache leaves out) with sccache in the GitHub Actions cache. It writes where the dependency cache is saved (pushes to the default branch, opted-in manual runs); other runs read those entries. SCCACHE_GHA_RW_MODE in `env` overrides that. Test executables are never cached. Its cache starts afresh when cache-version or a Cargo.toml, build.rs or clippy.toml changes; bump cache-version when files a procedural macro reads change (see the README)" + description: "Also cache the workspace crates' compiled libraries (which rust-cache leaves out) with sccache in the GitHub Actions cache. It writes where the dependency cache is saved (pushes to the default branch, opted-in manual runs); other runs read those entries. SCCACHE_GHA_RW_MODE in `env` overrides that. Test executables are never cached. Its cache starts afresh when cache-version, a Cargo.toml or a build.rs changes; bump cache-version when files a procedural macro reads change (see the README)" type: boolean required: false default: false @@ -283,10 +283,11 @@ jobs: shell: bash env: WRITES: ${{ github.event_name != 'pull_request' && (github.ref_name == github.event.repository.default_branch || (inputs.cache-save-on-dispatch && github.event_name == 'workflow_dispatch')) }} - # sccache's key leaves out lint settings that only change diagnostics (`--check-cfg`, - # clippy.toml), so a cached compile would replay its old warnings. A change to the files - # that declare them, or to cache-version, starts a fresh sccache cache instead. - VERSION: ${{ inputs.cache-version }}-${{ hashFiles('**/Cargo.toml', '**/build.rs', '**/clippy.toml', '**/.clippy.toml') }} + # sccache leaves `--check-cfg` out of its key, so after a change to the expected cfgs a + # cached compile would replay its old `unexpected_cfgs` warnings. A change to the files + # that declare them (Cargo.toml lints, build scripts), or to cache-version, starts a + # fresh sccache cache instead. + VERSION: ${{ inputs.cache-version }}-${{ hashFiles('**/Cargo.toml', '**/build.rs') }} run: | echo "SCCACHE_GHA_ENABLED=true" >> "$GITHUB_ENV" echo "RUSTC_WRAPPER=sccache" >> "$GITHUB_ENV" diff --git a/README.md b/README.md index 8c4fcc3..c477398 100644 --- a/README.md +++ b/README.md @@ -497,9 +497,9 @@ The quality gate for an app's pull requests and pushes to main. It runs `command library crates, which rust-cache doesn't keep. It writes where the dependency cache saves and only reads elsewhere; set `SCCACHE_GHA_RW_MODE` in `env` to choose. Test, binary and proc-macro crates aren't cacheable, so it mainly helps workspaces with many library crates. - sccache's cache starts afresh when `cache-version` or any `Cargo.toml`, `build.rs` or - `clippy.toml` changes, because its key leaves out settings that only change diagnostics - (`--check-cfg` declarations, clippy's configuration). It also can't see files a procedural + sccache's cache starts afresh when `cache-version` or any `Cargo.toml` or `build.rs` changes, + because its key leaves out `--check-cfg`: a cached compile would replay its old + `unexpected_cfgs` warnings after the expected cfgs change. It also can't see files a procedural macro reads without rustc tracking them (some asset-embedding macros): don't opt in while such files change often, or bump `cache-version` when they do. `SCCACHE_GHA_VERSION` in `env` sets the cache's version instead;