From 47cb1cf4ab295070455b49b40f03195b7822e921 Mon Sep 17 00:00:00 2001 From: Conrad Irwin Date: Tue, 10 Feb 2026 21:36:42 -0700 Subject: [PATCH] Use sccache in CI (#48895) Try sccache in CI to paper over cargo's abyssmal caching Release Notes: - N/A --- .github/workflows/release.yml | 58 +++++++++ .github/workflows/release_nightly.yml | 22 ++++ .github/workflows/run_agent_evals.yml | 9 ++ .github/workflows/run_cron_unit_evals.yml | 9 ++ .github/workflows/run_tests.yml | 76 ++++++++++++ .github/workflows/run_unit_evals.yml | 9 ++ script/setup-sccache | 116 +++++++++++++++++ script/setup-sccache.ps1 | 117 ++++++++++++++++++ .../src/tasks/workflows/run_agent_evals.rs | 6 + .../xtask/src/tasks/workflows/run_tests.rs | 10 +- tooling/xtask/src/tasks/workflows/steps.rs | 20 +++ tooling/xtask/src/tasks/workflows/vars.rs | 3 + 12 files changed, 454 insertions(+), 1 deletion(-) create mode 100755 script/setup-sccache create mode 100644 script/setup-sccache.ps1 diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 7817289f84d3cc78cabc9101a551e6755d350863..5e57f92661e97f17b34bb57441670196f6feec88 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -26,6 +26,13 @@ jobs: with: cache: rust path: ~/.rustup + - name: steps::setup_sccache + run: ./script/setup-sccache + env: + R2_ACCOUNT_ID: ${{ secrets.R2_ACCOUNT_ID }} + R2_ACCESS_KEY_ID: ${{ secrets.R2_ACCESS_KEY_ID }} + R2_SECRET_ACCESS_KEY: ${{ secrets.R2_SECRET_ACCESS_KEY }} + SCCACHE_BUCKET: sccache-zed - name: steps::setup_node uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 with: @@ -36,6 +43,8 @@ jobs: run: ./script/clear-target-dir-if-larger-than 300 - name: steps::cargo_nextest run: cargo nextest run --workspace --no-fail-fast + - name: steps::show_sccache_stats + run: sccache --show-stats || true - name: steps::cleanup_cargo_config if: always() run: | @@ -64,6 +73,13 @@ jobs: run: ./script/install-mold - name: steps::download_wasi_sdk run: ./script/download-wasi-sdk + - name: steps::setup_sccache + run: ./script/setup-sccache + env: + R2_ACCOUNT_ID: ${{ secrets.R2_ACCOUNT_ID }} + R2_ACCESS_KEY_ID: ${{ secrets.R2_ACCESS_KEY_ID }} + R2_SECRET_ACCESS_KEY: ${{ secrets.R2_SECRET_ACCESS_KEY }} + SCCACHE_BUCKET: sccache-zed - name: steps::setup_node uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 with: @@ -74,6 +90,8 @@ jobs: run: ./script/clear-target-dir-if-larger-than 250 - name: steps::cargo_nextest run: cargo nextest run --workspace --no-fail-fast + - name: steps::show_sccache_stats + run: sccache --show-stats || true - name: steps::cleanup_cargo_config if: always() run: | @@ -100,6 +118,14 @@ jobs: New-Item -ItemType Directory -Path "./../.cargo" -Force Copy-Item -Path "./.cargo/ci-config.toml" -Destination "./../.cargo/config.toml" shell: pwsh + - name: steps::setup_sccache + run: ./script/setup-sccache.ps1 + shell: pwsh + env: + R2_ACCOUNT_ID: ${{ secrets.R2_ACCOUNT_ID }} + R2_ACCESS_KEY_ID: ${{ secrets.R2_ACCESS_KEY_ID }} + R2_SECRET_ACCESS_KEY: ${{ secrets.R2_SECRET_ACCESS_KEY }} + SCCACHE_BUCKET: sccache-zed - name: steps::setup_node uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 with: @@ -110,6 +136,9 @@ jobs: - name: steps::cargo_nextest run: cargo nextest run --workspace --no-fail-fast shell: pwsh + - name: steps::show_sccache_stats + run: sccache --show-stats; exit 0 + shell: pwsh - name: steps::cleanup_cargo_config if: always() run: | @@ -133,8 +162,17 @@ jobs: with: cache: rust path: ~/.rustup + - name: steps::setup_sccache + run: ./script/setup-sccache + env: + R2_ACCOUNT_ID: ${{ secrets.R2_ACCOUNT_ID }} + R2_ACCESS_KEY_ID: ${{ secrets.R2_ACCESS_KEY_ID }} + R2_SECRET_ACCESS_KEY: ${{ secrets.R2_SECRET_ACCESS_KEY }} + SCCACHE_BUCKET: sccache-zed - name: steps::clippy run: ./script/clippy + - name: steps::show_sccache_stats + run: sccache --show-stats || true timeout-minutes: 60 clippy_linux: if: (github.repository_owner == 'zed-industries' || github.repository_owner == 'zed-extensions') @@ -159,8 +197,17 @@ jobs: run: ./script/install-mold - name: steps::download_wasi_sdk run: ./script/download-wasi-sdk + - name: steps::setup_sccache + run: ./script/setup-sccache + env: + R2_ACCOUNT_ID: ${{ secrets.R2_ACCOUNT_ID }} + R2_ACCESS_KEY_ID: ${{ secrets.R2_ACCESS_KEY_ID }} + R2_SECRET_ACCESS_KEY: ${{ secrets.R2_SECRET_ACCESS_KEY }} + SCCACHE_BUCKET: sccache-zed - name: steps::clippy run: ./script/clippy + - name: steps::show_sccache_stats + run: sccache --show-stats || true timeout-minutes: 60 clippy_windows: if: (github.repository_owner == 'zed-industries' || github.repository_owner == 'zed-extensions') @@ -175,9 +222,20 @@ jobs: New-Item -ItemType Directory -Path "./../.cargo" -Force Copy-Item -Path "./.cargo/ci-config.toml" -Destination "./../.cargo/config.toml" shell: pwsh + - name: steps::setup_sccache + run: ./script/setup-sccache.ps1 + shell: pwsh + env: + R2_ACCOUNT_ID: ${{ secrets.R2_ACCOUNT_ID }} + R2_ACCESS_KEY_ID: ${{ secrets.R2_ACCESS_KEY_ID }} + R2_SECRET_ACCESS_KEY: ${{ secrets.R2_SECRET_ACCESS_KEY }} + SCCACHE_BUCKET: sccache-zed - name: steps::clippy run: ./script/clippy.ps1 shell: pwsh + - name: steps::show_sccache_stats + run: sccache --show-stats; exit 0 + shell: pwsh timeout-minutes: 60 check_scripts: if: (github.repository_owner == 'zed-industries' || github.repository_owner == 'zed-extensions') diff --git a/.github/workflows/release_nightly.yml b/.github/workflows/release_nightly.yml index 942f39c45266122e5a8919b3daea9e7e5d82c252..1cdc1d38b18fc1996e0c0339b545f4beee137b58 100644 --- a/.github/workflows/release_nightly.yml +++ b/.github/workflows/release_nightly.yml @@ -38,6 +38,14 @@ jobs: New-Item -ItemType Directory -Path "./../.cargo" -Force Copy-Item -Path "./.cargo/ci-config.toml" -Destination "./../.cargo/config.toml" shell: pwsh + - name: steps::setup_sccache + run: ./script/setup-sccache.ps1 + shell: pwsh + env: + R2_ACCOUNT_ID: ${{ secrets.R2_ACCOUNT_ID }} + R2_ACCESS_KEY_ID: ${{ secrets.R2_ACCESS_KEY_ID }} + R2_SECRET_ACCESS_KEY: ${{ secrets.R2_SECRET_ACCESS_KEY }} + SCCACHE_BUCKET: sccache-zed - name: steps::setup_node uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 with: @@ -48,6 +56,9 @@ jobs: - name: steps::cargo_nextest run: cargo nextest run --workspace --no-fail-fast shell: pwsh + - name: steps::show_sccache_stats + run: sccache --show-stats; exit 0 + shell: pwsh - name: steps::cleanup_cargo_config if: always() run: | @@ -67,9 +78,20 @@ jobs: New-Item -ItemType Directory -Path "./../.cargo" -Force Copy-Item -Path "./.cargo/ci-config.toml" -Destination "./../.cargo/config.toml" shell: pwsh + - name: steps::setup_sccache + run: ./script/setup-sccache.ps1 + shell: pwsh + env: + R2_ACCOUNT_ID: ${{ secrets.R2_ACCOUNT_ID }} + R2_ACCESS_KEY_ID: ${{ secrets.R2_ACCESS_KEY_ID }} + R2_SECRET_ACCESS_KEY: ${{ secrets.R2_SECRET_ACCESS_KEY }} + SCCACHE_BUCKET: sccache-zed - name: steps::clippy run: ./script/clippy.ps1 shell: pwsh + - name: steps::show_sccache_stats + run: sccache --show-stats; exit 0 + shell: pwsh timeout-minutes: 60 bundle_linux_aarch64: needs: diff --git a/.github/workflows/run_agent_evals.yml b/.github/workflows/run_agent_evals.yml index 3036b6ffd9b274e406363b1762c133878321f7c9..c506039ce7c1863bd3c60091beb78d5239110bbd 100644 --- a/.github/workflows/run_agent_evals.yml +++ b/.github/workflows/run_agent_evals.yml @@ -42,6 +42,13 @@ jobs: run: | mkdir -p ./../.cargo cp ./.cargo/ci-config.toml ./../.cargo/config.toml + - name: steps::setup_sccache + run: ./script/setup-sccache + env: + R2_ACCOUNT_ID: ${{ secrets.R2_ACCOUNT_ID }} + R2_ACCESS_KEY_ID: ${{ secrets.R2_ACCESS_KEY_ID }} + R2_SECRET_ACCESS_KEY: ${{ secrets.R2_SECRET_ACCESS_KEY }} + SCCACHE_BUCKET: sccache-zed - name: cargo build --package=eval run: cargo build --package=eval - name: run_agent_evals::agent_evals::run_eval @@ -51,6 +58,8 @@ jobs: OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }} GOOGLE_AI_API_KEY: ${{ secrets.GOOGLE_AI_API_KEY }} GOOGLE_CLOUD_PROJECT: ${{ secrets.GOOGLE_CLOUD_PROJECT }} + - name: steps::show_sccache_stats + run: sccache --show-stats || true - name: steps::cleanup_cargo_config if: always() run: | diff --git a/.github/workflows/run_cron_unit_evals.yml b/.github/workflows/run_cron_unit_evals.yml index 9dfda662301539149a7b4d8679c365c12d64327e..9b7d7f8bda981549656916fec0f8e1d6bc52853e 100644 --- a/.github/workflows/run_cron_unit_evals.yml +++ b/.github/workflows/run_cron_unit_evals.yml @@ -39,6 +39,13 @@ jobs: run: ./script/install-mold - name: steps::download_wasi_sdk run: ./script/download-wasi-sdk + - name: steps::setup_sccache + run: ./script/setup-sccache + env: + R2_ACCOUNT_ID: ${{ secrets.R2_ACCOUNT_ID }} + R2_ACCESS_KEY_ID: ${{ secrets.R2_ACCESS_KEY_ID }} + R2_SECRET_ACCESS_KEY: ${{ secrets.R2_SECRET_ACCESS_KEY }} + SCCACHE_BUCKET: sccache-zed - name: steps::cargo_install_nextest uses: taiki-e/install-action@nextest - name: steps::clear_target_dir_if_large @@ -51,6 +58,8 @@ jobs: GOOGLE_AI_API_KEY: ${{ secrets.GOOGLE_AI_API_KEY }} GOOGLE_CLOUD_PROJECT: ${{ secrets.GOOGLE_CLOUD_PROJECT }} ZED_AGENT_MODEL: ${{ matrix.model }} + - name: steps::show_sccache_stats + run: sccache --show-stats || true - name: steps::cleanup_cargo_config if: always() run: | diff --git a/.github/workflows/run_tests.yml b/.github/workflows/run_tests.yml index 936b3e540f65eb4ae6982db471a1da4bd64d5c1c..66bc7f4356a7093089c6a65a8c118f53ce1dd292 100644 --- a/.github/workflows/run_tests.yml +++ b/.github/workflows/run_tests.yml @@ -154,9 +154,20 @@ jobs: New-Item -ItemType Directory -Path "./../.cargo" -Force Copy-Item -Path "./.cargo/ci-config.toml" -Destination "./../.cargo/config.toml" shell: pwsh + - name: steps::setup_sccache + run: ./script/setup-sccache.ps1 + shell: pwsh + env: + R2_ACCOUNT_ID: ${{ secrets.R2_ACCOUNT_ID }} + R2_ACCESS_KEY_ID: ${{ secrets.R2_ACCESS_KEY_ID }} + R2_SECRET_ACCESS_KEY: ${{ secrets.R2_SECRET_ACCESS_KEY }} + SCCACHE_BUCKET: sccache-zed - name: steps::clippy run: ./script/clippy.ps1 shell: pwsh + - name: steps::show_sccache_stats + run: sccache --show-stats; exit 0 + shell: pwsh timeout-minutes: 60 clippy_linux: needs: @@ -183,8 +194,17 @@ jobs: run: ./script/install-mold - name: steps::download_wasi_sdk run: ./script/download-wasi-sdk + - name: steps::setup_sccache + run: ./script/setup-sccache + env: + R2_ACCOUNT_ID: ${{ secrets.R2_ACCOUNT_ID }} + R2_ACCESS_KEY_ID: ${{ secrets.R2_ACCESS_KEY_ID }} + R2_SECRET_ACCESS_KEY: ${{ secrets.R2_SECRET_ACCESS_KEY }} + SCCACHE_BUCKET: sccache-zed - name: steps::clippy run: ./script/clippy + - name: steps::show_sccache_stats + run: sccache --show-stats || true timeout-minutes: 60 clippy_mac: needs: @@ -205,8 +225,17 @@ jobs: with: cache: rust path: ~/.rustup + - name: steps::setup_sccache + run: ./script/setup-sccache + env: + R2_ACCOUNT_ID: ${{ secrets.R2_ACCOUNT_ID }} + R2_ACCESS_KEY_ID: ${{ secrets.R2_ACCESS_KEY_ID }} + R2_SECRET_ACCESS_KEY: ${{ secrets.R2_SECRET_ACCESS_KEY }} + SCCACHE_BUCKET: sccache-zed - name: steps::clippy run: ./script/clippy + - name: steps::show_sccache_stats + run: sccache --show-stats || true timeout-minutes: 60 run_tests_windows: needs: @@ -223,6 +252,14 @@ jobs: New-Item -ItemType Directory -Path "./../.cargo" -Force Copy-Item -Path "./.cargo/ci-config.toml" -Destination "./../.cargo/config.toml" shell: pwsh + - name: steps::setup_sccache + run: ./script/setup-sccache.ps1 + shell: pwsh + env: + R2_ACCOUNT_ID: ${{ secrets.R2_ACCOUNT_ID }} + R2_ACCESS_KEY_ID: ${{ secrets.R2_ACCESS_KEY_ID }} + R2_SECRET_ACCESS_KEY: ${{ secrets.R2_SECRET_ACCESS_KEY }} + SCCACHE_BUCKET: sccache-zed - name: steps::setup_node uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 with: @@ -233,6 +270,9 @@ jobs: - name: steps::cargo_nextest run: cargo nextest run --workspace --no-fail-fast${{ needs.orchestrate.outputs.changed_packages && format(' -E "{0}"', needs.orchestrate.outputs.changed_packages) || '' }} shell: pwsh + - name: steps::show_sccache_stats + run: sccache --show-stats; exit 0 + shell: pwsh - name: steps::cleanup_cargo_config if: always() run: | @@ -264,6 +304,13 @@ jobs: run: ./script/install-mold - name: steps::download_wasi_sdk run: ./script/download-wasi-sdk + - name: steps::setup_sccache + run: ./script/setup-sccache + env: + R2_ACCOUNT_ID: ${{ secrets.R2_ACCOUNT_ID }} + R2_ACCESS_KEY_ID: ${{ secrets.R2_ACCESS_KEY_ID }} + R2_SECRET_ACCESS_KEY: ${{ secrets.R2_SECRET_ACCESS_KEY }} + SCCACHE_BUCKET: sccache-zed - name: steps::setup_node uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 with: @@ -274,6 +321,8 @@ jobs: run: ./script/clear-target-dir-if-larger-than 250 - name: steps::cargo_nextest run: cargo nextest run --workspace --no-fail-fast${{ needs.orchestrate.outputs.changed_packages && format(' -E "{0}"', needs.orchestrate.outputs.changed_packages) || '' }} + - name: steps::show_sccache_stats + run: sccache --show-stats || true - name: steps::cleanup_cargo_config if: always() run: | @@ -306,6 +355,13 @@ jobs: with: cache: rust path: ~/.rustup + - name: steps::setup_sccache + run: ./script/setup-sccache + env: + R2_ACCOUNT_ID: ${{ secrets.R2_ACCOUNT_ID }} + R2_ACCESS_KEY_ID: ${{ secrets.R2_ACCESS_KEY_ID }} + R2_SECRET_ACCESS_KEY: ${{ secrets.R2_SECRET_ACCESS_KEY }} + SCCACHE_BUCKET: sccache-zed - name: steps::setup_node uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 with: @@ -316,6 +372,8 @@ jobs: run: ./script/clear-target-dir-if-larger-than 300 - name: steps::cargo_nextest run: cargo nextest run --workspace --no-fail-fast${{ needs.orchestrate.outputs.changed_packages && format(' -E "{0}"', needs.orchestrate.outputs.changed_packages) || '' }} + - name: steps::show_sccache_stats + run: sccache --show-stats || true - name: steps::cleanup_cargo_config if: always() run: | @@ -346,10 +404,19 @@ jobs: run: | mkdir -p ./../.cargo cp ./.cargo/ci-config.toml ./../.cargo/config.toml + - name: steps::setup_sccache + run: ./script/setup-sccache + env: + R2_ACCOUNT_ID: ${{ secrets.R2_ACCOUNT_ID }} + R2_ACCESS_KEY_ID: ${{ secrets.R2_ACCESS_KEY_ID }} + R2_SECRET_ACCESS_KEY: ${{ secrets.R2_SECRET_ACCESS_KEY }} + SCCACHE_BUCKET: sccache-zed - id: run_doctests name: run_tests::doctests::run_doctests run: | cargo test --workspace --doc --no-fail-fast + - name: steps::show_sccache_stats + run: sccache --show-stats || true - name: steps::cleanup_cargo_config if: always() run: | @@ -380,10 +447,19 @@ jobs: run: ./script/install-mold - name: steps::download_wasi_sdk run: ./script/download-wasi-sdk + - name: steps::setup_sccache + run: ./script/setup-sccache + env: + R2_ACCOUNT_ID: ${{ secrets.R2_ACCOUNT_ID }} + R2_ACCESS_KEY_ID: ${{ secrets.R2_ACCESS_KEY_ID }} + R2_SECRET_ACCESS_KEY: ${{ secrets.R2_SECRET_ACCESS_KEY }} + SCCACHE_BUCKET: sccache-zed - name: cargo build -p collab run: cargo build -p collab - name: cargo build --workspace --bins --examples run: cargo build --workspace --bins --examples + - name: steps::show_sccache_stats + run: sccache --show-stats || true - name: steps::cleanup_cargo_config if: always() run: | diff --git a/.github/workflows/run_unit_evals.yml b/.github/workflows/run_unit_evals.yml index 2678d04bc7a2d872331f805af2ca5c81fae10263..4aa54a525ce2b6d305da6a2562597bf9f3e2c435 100644 --- a/.github/workflows/run_unit_evals.yml +++ b/.github/workflows/run_unit_evals.yml @@ -42,6 +42,13 @@ jobs: run: ./script/install-mold - name: steps::download_wasi_sdk run: ./script/download-wasi-sdk + - name: steps::setup_sccache + run: ./script/setup-sccache + env: + R2_ACCOUNT_ID: ${{ secrets.R2_ACCOUNT_ID }} + R2_ACCESS_KEY_ID: ${{ secrets.R2_ACCESS_KEY_ID }} + R2_SECRET_ACCESS_KEY: ${{ secrets.R2_SECRET_ACCESS_KEY }} + SCCACHE_BUCKET: sccache-zed - name: steps::cargo_install_nextest uses: taiki-e/install-action@nextest - name: steps::clear_target_dir_if_large @@ -54,6 +61,8 @@ jobs: GOOGLE_AI_API_KEY: ${{ secrets.GOOGLE_AI_API_KEY }} GOOGLE_CLOUD_PROJECT: ${{ secrets.GOOGLE_CLOUD_PROJECT }} UNIT_EVAL_COMMIT: ${{ inputs.commit_sha }} + - name: steps::show_sccache_stats + run: sccache --show-stats || true - name: steps::cleanup_cargo_config if: always() run: | diff --git a/script/setup-sccache b/script/setup-sccache new file mode 100755 index 0000000000000000000000000000000000000000..94c17ea64c9229e042eae5bd1aca696993da85f1 --- /dev/null +++ b/script/setup-sccache @@ -0,0 +1,116 @@ +#!/usr/bin/env bash + +set -euo pipefail + +SCCACHE_VERSION="v0.10.0" +SCCACHE_DIR="./target/sccache" + +install_sccache() { + mkdir -p "$SCCACHE_DIR" + + if [[ -x "${SCCACHE_DIR}/sccache" ]]; then + echo "sccache already cached: $("${SCCACHE_DIR}/sccache" --version)" + else + echo "Installing sccache ${SCCACHE_VERSION} from GitHub releases..." + + local os arch archive basename + os="$(uname -s)" + arch="$(uname -m)" + + case "${os}-${arch}" in + Darwin-arm64) + archive="sccache-${SCCACHE_VERSION}-aarch64-apple-darwin.tar.gz" + ;; + Darwin-x86_64) + archive="sccache-${SCCACHE_VERSION}-x86_64-apple-darwin.tar.gz" + ;; + Linux-x86_64) + archive="sccache-${SCCACHE_VERSION}-x86_64-unknown-linux-musl.tar.gz" + ;; + Linux-aarch64) + archive="sccache-${SCCACHE_VERSION}-aarch64-unknown-linux-musl.tar.gz" + ;; + *) + echo "Unsupported platform: ${os}-${arch}" + exit 1 + ;; + esac + + basename="${archive%.tar.gz}" + curl -fsSL "https://github.com/mozilla/sccache/releases/download/${SCCACHE_VERSION}/${archive}" | tar xz + mv "${basename}/sccache" "${SCCACHE_DIR}/" + rm -rf "${basename}" + echo "Installed sccache: $("${SCCACHE_DIR}/sccache" --version)" + fi + + if [[ -n "${GITHUB_PATH:-}" ]]; then + echo "$(pwd)/${SCCACHE_DIR}" >> "$GITHUB_PATH" + fi + export PATH="$(pwd)/${SCCACHE_DIR}:${PATH}" +} + +configure_sccache() { + if [[ -z "${R2_ACCOUNT_ID:-}" ]]; then + echo "R2_ACCOUNT_ID not set, skipping sccache configuration" + return + fi + + echo "Configuring sccache with Cloudflare R2..." + + local bucket="${SCCACHE_BUCKET:-sccache-zed}" + local key_prefix="${SCCACHE_KEY_PREFIX:-sccache/}" + local base_dir="${GITHUB_WORKSPACE:-$(pwd)}" + + # Set in current process + export SCCACHE_ENDPOINT="https://${R2_ACCOUNT_ID}.r2.cloudflarestorage.com" + export SCCACHE_BUCKET="${bucket}" + export SCCACHE_REGION="auto" + export SCCACHE_S3_KEY_PREFIX="${key_prefix}" + export SCCACHE_BASEDIR="${base_dir}" + export AWS_ACCESS_KEY_ID="${R2_ACCESS_KEY_ID}" + export AWS_SECRET_ACCESS_KEY="${R2_SECRET_ACCESS_KEY}" + export RUSTC_WRAPPER="sccache" + + # Also write to GITHUB_ENV for subsequent steps + if [[ -n "${GITHUB_ENV:-}" ]]; then + { + echo "SCCACHE_ENDPOINT=${SCCACHE_ENDPOINT}" + echo "SCCACHE_BUCKET=${SCCACHE_BUCKET}" + echo "SCCACHE_REGION=${SCCACHE_REGION}" + echo "SCCACHE_S3_KEY_PREFIX=${SCCACHE_S3_KEY_PREFIX}" + echo "SCCACHE_BASEDIR=${SCCACHE_BASEDIR}" + echo "AWS_ACCESS_KEY_ID=${AWS_ACCESS_KEY_ID}" + echo "AWS_SECRET_ACCESS_KEY=${AWS_SECRET_ACCESS_KEY}" + echo "RUSTC_WRAPPER=${RUSTC_WRAPPER}" + } >> "$GITHUB_ENV" + fi + + echo "✓ sccache configured with Cloudflare R2 (bucket: ${bucket})" +} + +show_config() { + echo "=== sccache configuration ===" + echo "sccache version: $(sccache --version)" + echo "RUSTC_WRAPPER: ${RUSTC_WRAPPER:-}" + echo "SCCACHE_BUCKET: ${SCCACHE_BUCKET:-}" + echo "SCCACHE_ENDPOINT: ${SCCACHE_ENDPOINT:-}" + echo "SCCACHE_REGION: ${SCCACHE_REGION:-}" + echo "SCCACHE_S3_KEY_PREFIX: ${SCCACHE_S3_KEY_PREFIX:-}" + echo "SCCACHE_BASEDIR: ${SCCACHE_BASEDIR:-}" + if [[ -n "${AWS_ACCESS_KEY_ID:-}" ]]; then + echo "AWS_ACCESS_KEY_ID: " + else + echo "AWS_ACCESS_KEY_ID: " + fi + if [[ -n "${AWS_SECRET_ACCESS_KEY:-}" ]]; then + echo "AWS_SECRET_ACCESS_KEY: " + else + echo "AWS_SECRET_ACCESS_KEY: " + fi + echo "=== sccache stats ===" + sccache --show-stats || true +} + +install_sccache +configure_sccache +show_config diff --git a/script/setup-sccache.ps1 b/script/setup-sccache.ps1 new file mode 100644 index 0000000000000000000000000000000000000000..d9effcecb1a02c4437496d64309fca58705df501 --- /dev/null +++ b/script/setup-sccache.ps1 @@ -0,0 +1,117 @@ +#Requires -Version 5.1 +$ErrorActionPreference = "Stop" + +$SCCACHE_VERSION = "v0.10.0" +$SCCACHE_DIR = "./target/sccache" + +function Install-Sccache { + New-Item -ItemType Directory -Path $SCCACHE_DIR -Force | Out-Null + + $sccachePath = Join-Path $SCCACHE_DIR "sccache.exe" + + if (Test-Path $sccachePath) { + Write-Host "sccache already cached: $(& $sccachePath --version)" + } + else { + Write-Host "Installing sccache ${SCCACHE_VERSION} from GitHub releases..." + + $arch = if ([Environment]::Is64BitOperatingSystem) { "x86_64" } else { "i686" } + $archive = "sccache-${SCCACHE_VERSION}-${arch}-pc-windows-msvc.zip" + $basename = "sccache-${SCCACHE_VERSION}-${arch}-pc-windows-msvc" + $url = "https://github.com/mozilla/sccache/releases/download/${SCCACHE_VERSION}/${archive}" + + $tempDir = Join-Path $env:TEMP "sccache-install" + New-Item -ItemType Directory -Path $tempDir -Force | Out-Null + + try { + $archivePath = Join-Path $tempDir $archive + Invoke-WebRequest -Uri $url -OutFile $archivePath + Expand-Archive -Path $archivePath -DestinationPath $tempDir + + $extractedPath = Join-Path $tempDir $basename "sccache.exe" + Move-Item -Path $extractedPath -Destination $sccachePath -Force + + Write-Host "Installed sccache: $(& $sccachePath --version)" + } + finally { + Remove-Item -Recurse -Force $tempDir -ErrorAction SilentlyContinue + } + } + + $absolutePath = (Resolve-Path $SCCACHE_DIR).Path + if ($env:GITHUB_PATH) { + $absolutePath | Out-File -FilePath $env:GITHUB_PATH -Append -Encoding utf8 + } + $env:PATH = "$absolutePath;$env:PATH" +} + +function Configure-Sccache { + if (-not $env:R2_ACCOUNT_ID) { + Write-Host "R2_ACCOUNT_ID not set, skipping sccache configuration" + return + } + + Write-Host "Configuring sccache with Cloudflare R2..." + + $bucket = if ($env:SCCACHE_BUCKET) { $env:SCCACHE_BUCKET } else { "sccache-zed" } + $keyPrefix = if ($env:SCCACHE_KEY_PREFIX) { $env:SCCACHE_KEY_PREFIX } else { "sccache/" } + $baseDir = if ($env:GITHUB_WORKSPACE) { $env:GITHUB_WORKSPACE } else { (Get-Location).Path } + + # Set in current process + $env:SCCACHE_ENDPOINT = "https://$($env:R2_ACCOUNT_ID).r2.cloudflarestorage.com" + $env:SCCACHE_BUCKET = $bucket + $env:SCCACHE_REGION = "auto" + $env:SCCACHE_S3_KEY_PREFIX = $keyPrefix + $env:SCCACHE_BASEDIR = $baseDir + $env:AWS_ACCESS_KEY_ID = $env:R2_ACCESS_KEY_ID + $env:AWS_SECRET_ACCESS_KEY = $env:R2_SECRET_ACCESS_KEY + $env:RUSTC_WRAPPER = "sccache" + + # Also write to GITHUB_ENV for subsequent steps + if ($env:GITHUB_ENV) { + @( + "SCCACHE_ENDPOINT=$($env:SCCACHE_ENDPOINT)" + "SCCACHE_BUCKET=$($env:SCCACHE_BUCKET)" + "SCCACHE_REGION=$($env:SCCACHE_REGION)" + "SCCACHE_S3_KEY_PREFIX=$($env:SCCACHE_S3_KEY_PREFIX)" + "SCCACHE_BASEDIR=$($env:SCCACHE_BASEDIR)" + "AWS_ACCESS_KEY_ID=$($env:AWS_ACCESS_KEY_ID)" + "AWS_SECRET_ACCESS_KEY=$($env:AWS_SECRET_ACCESS_KEY)" + "RUSTC_WRAPPER=$($env:RUSTC_WRAPPER)" + ) | Out-File -FilePath $env:GITHUB_ENV -Append -Encoding utf8 + } + + Write-Host "✓ sccache configured with Cloudflare R2 (bucket: $bucket)" +} + +function Show-Config { + Write-Host "=== sccache configuration ===" + Write-Host "sccache version: $(sccache --version)" + Write-Host "RUSTC_WRAPPER: $($env:RUSTC_WRAPPER ?? '')" + Write-Host "SCCACHE_BUCKET: $($env:SCCACHE_BUCKET ?? '')" + Write-Host "SCCACHE_ENDPOINT: $($env:SCCACHE_ENDPOINT ?? '')" + Write-Host "SCCACHE_REGION: $($env:SCCACHE_REGION ?? '')" + Write-Host "SCCACHE_S3_KEY_PREFIX: $($env:SCCACHE_S3_KEY_PREFIX ?? '')" + Write-Host "SCCACHE_BASEDIR: $($env:SCCACHE_BASEDIR ?? '')" + + if ($env:AWS_ACCESS_KEY_ID) { + Write-Host "AWS_ACCESS_KEY_ID: " + } + else { + Write-Host "AWS_ACCESS_KEY_ID: " + } + + if ($env:AWS_SECRET_ACCESS_KEY) { + Write-Host "AWS_SECRET_ACCESS_KEY: " + } + else { + Write-Host "AWS_SECRET_ACCESS_KEY: " + } + + Write-Host "=== sccache stats ===" + sccache --show-stats +} + +Install-Sccache +Configure-Sccache +Show-Config diff --git a/tooling/xtask/src/tasks/workflows/run_agent_evals.rs b/tooling/xtask/src/tasks/workflows/run_agent_evals.rs index 67dce0b09913e6ffd03476d541a506b486ad28b8..ac9dddfad18519383da095ec7145653533140fa9 100644 --- a/tooling/xtask/src/tasks/workflows/run_agent_evals.rs +++ b/tooling/xtask/src/tasks/workflows/run_agent_evals.rs @@ -74,8 +74,10 @@ fn agent_evals() -> NamedJob { .add_step(steps::cache_rust_dependencies_namespace()) .map(steps::install_linux_dependencies) .add_step(setup_cargo_config(Platform::Linux)) + .add_step(steps::setup_sccache(Platform::Linux)) .add_step(steps::script("cargo build --package=eval")) .add_step(add_api_keys(run_eval())) + .add_step(steps::show_sccache_stats(Platform::Linux)) .add_step(steps::cleanup_cargo_config(Platform::Linux)), ) } @@ -138,9 +140,11 @@ fn cron_unit_evals_job() -> Job { .add_step(steps::setup_cargo_config(Platform::Linux)) .add_step(steps::cache_rust_dependencies_namespace()) .map(steps::install_linux_dependencies) + .add_step(steps::setup_sccache(Platform::Linux)) .add_step(steps::cargo_install_nextest()) .add_step(steps::clear_target_dir_if_large(Platform::Linux)) .add_step(script_step) + .add_step(steps::show_sccache_stats(Platform::Linux)) .add_step(steps::cleanup_cargo_config(Platform::Linux)) } @@ -153,11 +157,13 @@ fn unit_evals(commit: Option<&WorkflowInput>) -> Job { .add_step(steps::setup_cargo_config(Platform::Linux)) .add_step(steps::cache_rust_dependencies_namespace()) .map(steps::install_linux_dependencies) + .add_step(steps::setup_sccache(Platform::Linux)) .add_step(steps::cargo_install_nextest()) .add_step(steps::clear_target_dir_if_large(Platform::Linux)) .add_step(match commit { Some(commit) => script_step.add_env(("UNIT_EVAL_COMMIT", commit)), None => script_step, }) + .add_step(steps::show_sccache_stats(Platform::Linux)) .add_step(steps::cleanup_cargo_config(Platform::Linux)) } diff --git a/tooling/xtask/src/tasks/workflows/run_tests.rs b/tooling/xtask/src/tasks/workflows/run_tests.rs index b42a3597dd5d957df17a184a86aa082416f13e60..49c4488dc95620c00a6a8f929cfb756d9c4eb6fa 100644 --- a/tooling/xtask/src/tasks/workflows/run_tests.rs +++ b/tooling/xtask/src/tasks/workflows/run_tests.rs @@ -345,8 +345,10 @@ fn check_workspace_binaries() -> NamedJob { .add_step(steps::setup_cargo_config(Platform::Linux)) .add_step(steps::cache_rust_dependencies_namespace()) .map(steps::install_linux_dependencies) + .add_step(steps::setup_sccache(Platform::Linux)) .add_step(steps::script("cargo build -p collab")) .add_step(steps::script("cargo build --workspace --bins --examples")) + .add_step(steps::show_sccache_stats(Platform::Linux)) .add_step(steps::cleanup_cargo_config(Platform::Linux)), ) } @@ -371,7 +373,9 @@ pub(crate) fn clippy(platform: Platform) -> NamedJob { platform == Platform::Linux, steps::install_linux_dependencies, ) - .add_step(steps::clippy(platform)), + .add_step(steps::setup_sccache(platform)) + .add_step(steps::clippy(platform)) + .add_step(steps::show_sccache_stats(platform)), } } @@ -417,6 +421,7 @@ fn run_platform_tests_impl(platform: Platform, filter_packages: bool) -> NamedJo platform == Platform::Linux, steps::install_linux_dependencies, ) + .add_step(steps::setup_sccache(platform)) .add_step(steps::setup_node()) .when( platform == Platform::Linux || platform == Platform::Mac, @@ -431,6 +436,7 @@ fn run_platform_tests_impl(platform: Platform, filter_packages: bool) -> NamedJo .when(!filter_packages, |job| { job.add_step(steps::cargo_nextest(platform)) }) + .add_step(steps::show_sccache_stats(platform)) .add_step(steps::cleanup_cargo_config(platform)), } } @@ -494,7 +500,9 @@ fn doctests() -> NamedJob { .add_step(steps::cache_rust_dependencies_namespace()) .map(steps::install_linux_dependencies) .add_step(steps::setup_cargo_config(Platform::Linux)) + .add_step(steps::setup_sccache(Platform::Linux)) .add_step(run_doctests()) + .add_step(steps::show_sccache_stats(Platform::Linux)) .add_step(steps::cleanup_cargo_config(Platform::Linux)), ) } diff --git a/tooling/xtask/src/tasks/workflows/steps.rs b/tooling/xtask/src/tasks/workflows/steps.rs index c78a762b9f020c68e6c0362f275d095d4c18d249..25348fbc92414a73c4cd00f14122512ce1fa2557 100644 --- a/tooling/xtask/src/tasks/workflows/steps.rs +++ b/tooling/xtask/src/tasks/workflows/steps.rs @@ -2,6 +2,8 @@ use gh_workflow::*; use crate::tasks::workflows::{runners::Platform, vars, vars::StepOutput}; +const SCCACHE_R2_BUCKET: &str = "sccache-zed"; + const BASH_SHELL: &str = "bash -euxo pipefail {0}"; // https://docs.github.com/en/actions/reference/workflows-and-actions/workflow-syntax#jobsjob_idstepsshell pub const PWSH_SHELL: &str = "pwsh"; @@ -155,6 +157,24 @@ pub fn cache_rust_dependencies_namespace() -> Step { .add_with(("path", "~/.rustup")) } +pub fn setup_sccache(platform: Platform) -> Step { + let step = match platform { + Platform::Windows => named::pwsh("./script/setup-sccache.ps1"), + Platform::Linux | Platform::Mac => named::bash("./script/setup-sccache"), + }; + step.add_env(("R2_ACCOUNT_ID", vars::R2_ACCOUNT_ID)) + .add_env(("R2_ACCESS_KEY_ID", vars::R2_ACCESS_KEY_ID)) + .add_env(("R2_SECRET_ACCESS_KEY", vars::R2_SECRET_ACCESS_KEY)) + .add_env(("SCCACHE_BUCKET", SCCACHE_R2_BUCKET)) +} + +pub fn show_sccache_stats(platform: Platform) -> Step { + match platform { + Platform::Windows => named::pwsh("sccache --show-stats; exit 0"), + Platform::Linux | Platform::Mac => named::bash("sccache --show-stats || true"), + } +} + pub fn cache_nix_dependencies_namespace() -> Step { named::uses("namespacelabs", "nscloud-cache-action", "v1").add_with(("cache", "nix")) } diff --git a/tooling/xtask/src/tasks/workflows/vars.rs b/tooling/xtask/src/tasks/workflows/vars.rs index 87e62c2061406017ee7b72fe98323692e964e019..5939ddbffe6e3cc28cf14e424070480e0ffc60c9 100644 --- a/tooling/xtask/src/tasks/workflows/vars.rs +++ b/tooling/xtask/src/tasks/workflows/vars.rs @@ -46,6 +46,9 @@ secret!(DISCORD_WEBHOOK_RELEASE_NOTES); secret!(WINGET_TOKEN); secret!(VERCEL_TOKEN); secret!(SLACK_WEBHOOK_WORKFLOW_FAILURES); +secret!(R2_ACCOUNT_ID); +secret!(R2_ACCESS_KEY_ID); +secret!(R2_SECRET_ACCESS_KEY); // todo(ci) make these secrets too... var!(AZURE_SIGNING_ACCOUNT_NAME);