From 456976c494bc61af5557c973747caeacd41dc695 Mon Sep 17 00:00:00 2001 From: Sharang Parnerkar Date: Sun, 22 Feb 2026 13:34:08 +0100 Subject: [PATCH] build: add sccache for faster local and CI builds - Add .cargo/config.toml with rustc-wrapper = sccache for local caching - Install sccache in CI clippy/test jobs via prebuilt musl binary - Add actions/cache to persist sccache dir across CI runs (keyed by Cargo.lock) - Add BuildKit cache mounts in Dockerfile for sccache across Docker builds - Disable sccache for fmt/audit jobs where it adds no value Local clean-rebuild speedup: 1m58s -> 34s (3.4x) with warm cache. Co-Authored-By: Claude Opus 4.6 --- .cargo/config.toml | 5 +++++ .gitea/workflows/ci.yml | 43 ++++++++++++++++++++++++++++++++++++++++- Dockerfile | 18 ++++++++++++++--- 3 files changed, 62 insertions(+), 4 deletions(-) create mode 100644 .cargo/config.toml diff --git a/.cargo/config.toml b/.cargo/config.toml new file mode 100644 index 0000000..243bd7e --- /dev/null +++ b/.cargo/config.toml @@ -0,0 +1,5 @@ +[build] +# Use sccache as the rustc wrapper for compile caching. +# Falls back gracefully: if sccache is not installed, cargo will warn but +# still compile. Install with: cargo install sccache +rustc-wrapper = "sccache" diff --git a/.gitea/workflows/ci.yml b/.gitea/workflows/ci.yml index 1bbeb87..faf1a3e 100644 --- a/.gitea/workflows/ci.yml +++ b/.gitea/workflows/ci.yml @@ -11,6 +11,10 @@ on: env: CARGO_TERM_COLOR: always RUSTFLAGS: "-D warnings" + # sccache configuration + RUSTC_WRAPPER: /usr/local/bin/sccache + SCCACHE_DIR: /tmp/sccache + SCCACHE_CACHE_SIZE: 2G # Cancel in-progress runs for the same branch/PR concurrency: @@ -34,7 +38,10 @@ jobs: git fetch --depth=1 origin "${GITHUB_SHA}" git checkout FETCH_HEAD - run: rustup component add rustfmt + # Format check does not compile, so sccache is not needed here. - run: cargo fmt --check + env: + RUSTC_WRAPPER: "" clippy: name: Clippy @@ -48,12 +55,27 @@ jobs: git remote add origin "${GITHUB_SERVER_URL}/${GITHUB_REPOSITORY}.git" git fetch --depth=1 origin "${GITHUB_SHA}" git checkout FETCH_HEAD + - name: Install sccache + run: | + curl -fsSL https://github.com/mozilla/sccache/releases/download/v0.9.1/sccache-v0.9.1-x86_64-unknown-linux-musl.tar.gz \ + | tar xz --strip-components=1 -C /usr/local/bin/ sccache-v0.9.1-x86_64-unknown-linux-musl/sccache + chmod +x /usr/local/bin/sccache + - name: Restore sccache cache + uses: https://github.com/actions/cache@v4 + with: + path: /tmp/sccache + key: sccache-clippy-${{ hashFiles('Cargo.lock') }} + restore-keys: | + sccache-clippy- - run: rustup component add clippy # Lint both feature sets independently - name: Clippy (server) run: cargo clippy --features server --no-default-features -- -D warnings - name: Clippy (web) run: cargo clippy --features web --no-default-features -- -D warnings + - name: Show sccache stats + run: sccache --show-stats + if: always() audit: name: Security Audit @@ -69,7 +91,11 @@ jobs: git fetch --depth=1 origin "${GITHUB_SHA}" git checkout FETCH_HEAD - run: cargo install cargo-audit + env: + RUSTC_WRAPPER: "" - run: cargo audit + env: + RUSTC_WRAPPER: "" # --------------------------------------------------------------------------- # Stage 2: Tests (only after all quality checks pass) @@ -87,10 +113,26 @@ jobs: git remote add origin "${GITHUB_SERVER_URL}/${GITHUB_REPOSITORY}.git" git fetch --depth=1 origin "${GITHUB_SHA}" git checkout FETCH_HEAD + - name: Install sccache + run: | + curl -fsSL https://github.com/mozilla/sccache/releases/download/v0.9.1/sccache-v0.9.1-x86_64-unknown-linux-musl.tar.gz \ + | tar xz --strip-components=1 -C /usr/local/bin/ sccache-v0.9.1-x86_64-unknown-linux-musl/sccache + chmod +x /usr/local/bin/sccache + - name: Restore sccache cache + uses: https://github.com/actions/cache@v4 + with: + path: /tmp/sccache + key: sccache-test-${{ hashFiles('Cargo.lock') }} + restore-keys: | + sccache-test- + sccache-clippy- - name: Run tests (server) run: cargo test --features server --no-default-features - name: Run tests (web) run: cargo test --features web --no-default-features + - name: Show sccache stats + run: sccache --show-stats + if: always() # --------------------------------------------------------------------------- # Stage 3: Deploy (only after tests pass, only on main) @@ -108,4 +150,3 @@ jobs: apk add --no-cache curl curl -sf "${{ secrets.COOLIFY_WEBHOOK }}" \ -H "Authorization: Bearer ${{ secrets.COOLIFY_TOKEN }}" - diff --git a/Dockerfile b/Dockerfile index 8c1d477..d4d8e61 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,3 +1,4 @@ +# syntax=docker/dockerfile:1 # Stage 1: Generate dependency recipe for caching FROM rust:1.89-bookworm AS chef RUN cargo install cargo-chef @@ -15,16 +16,26 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ pkg-config libssl-dev curl unzip \ && rm -rf /var/lib/apt/lists/* +# Install sccache for compile caching across Docker builds +RUN curl -fsSL https://github.com/mozilla/sccache/releases/download/v0.9.1/sccache-v0.9.1-x86_64-unknown-linux-musl.tar.gz \ + | tar xz --strip-components=1 -C /usr/local/bin/ sccache-v0.9.1-x86_64-unknown-linux-musl/sccache \ + && chmod +x /usr/local/bin/sccache + +ENV RUSTC_WRAPPER=/usr/local/bin/sccache +ENV SCCACHE_DIR=/tmp/sccache + # Install bun (for Tailwind CSS build step) RUN curl -fsSL https://bun.sh/install | bash ENV PATH="/root/.bun/bin:$PATH" # Install dx CLI from source (binstall binaries require GLIBC >= 2.38) -RUN cargo install dioxus-cli@0.7.3 --locked +RUN --mount=type=cache,target=/tmp/sccache \ + cargo install dioxus-cli@0.7.3 --locked # Cook dependencies from recipe (cached layer) COPY --from=planner /app/recipe.json recipe.json -RUN cargo chef cook --release --recipe-path recipe.json +RUN --mount=type=cache,target=/tmp/sccache \ + cargo chef cook --release --recipe-path recipe.json # Copy source and build COPY . . @@ -33,7 +44,8 @@ COPY . . RUN bun install --frozen-lockfile # Bundle the fullstack application -RUN dx bundle --release --fullstack +RUN --mount=type=cache,target=/tmp/sccache \ + dx bundle --release --fullstack # Stage 3: Minimal runtime image FROM debian:bookworm-slim AS runtime