Skip to content

chore(ci): switch sccache from local disk to memcached backend#68

Merged
drew merged 23 commits into
mainfrom
sccache-memcached-backend/an
Mar 3, 2026
Merged

chore(ci): switch sccache from local disk to memcached backend#68
drew merged 23 commits into
mainfrom
sccache-memcached-backend/an

Conversation

@drew

@drew drew commented Mar 3, 2026

Copy link
Copy Markdown
Collaborator

Summary

  • Replace SCCACHE_DIR (local disk cache) with SCCACHE_MEMCACHED_ENDPOINT (tcp://memcached.sccache:11211) for shared compilation caching across CI runners
  • Pass the endpoint as a Docker build arg so CI gets shared memcached caching while local builds degrade gracefully
  • Remove sccache disk cache entries from GitHub Actions (actions/cache) and GitLab CI cache config

Changes

File Change
mise.toml SCCACHE_DIRSCCACHE_MEMCACHED_ENDPOINT (with env override)
Dockerfile.server ENV SCCACHE_DIRARG/ENV SCCACHE_MEMCACHED_ENDPOINT; remove sccache cache mounts
Dockerfile.base (sandbox) Same
Dockerfile.python-wheels Same
.github/workflows/checks.yml Add SCCACHE_MEMCACHED_ENDPOINT env; remove disk cache step
.gitlab-ci.yml Add SCCACHE_MEMCACHED_ENDPOINT variable; remove sccache disk cache entry
docker-build-component.sh Forward SCCACHE_MEMCACHED_ENDPOINT as --build-arg
docker-publish-multiarch.sh Forward SCCACHE_MEMCACHED_ENDPOINT as --build-arg
architecture/build-containers.md Update docs to reflect memcached backend

Prerequisites

  • Memcached instance available at tcp://memcached.sccache:11211 from CI runners and Docker build network

Replace SCCACHE_DIR with SCCACHE_MEMCACHED_ENDPOINT (tcp://memcached.sccache:11211)
across CI configs, Dockerfiles, and build scripts. Docker builds receive the
endpoint as a build arg so CI gets shared caching while local builds degrade
gracefully.
@drew drew self-assigned this Mar 3, 2026
@drew drew added the test:e2e Requires end-to-end coverage label Mar 3, 2026
drew added 16 commits March 2, 2026 21:32
Read SCCACHE_MEMCACHED_ENDPOINT from GitHub repository variables instead
of hardcoding the value. Revert GitLab CI changes since that environment
is not configured for memcached yet. Remove the mise.toml default so
local dev without memcached falls back to local sccache storage.
Unset empty SCCACHE_MEMCACHED_ENDPOINT in cross-build.sh so sccache
falls back to local disk cache. Remove the ENV line from Dockerfiles
since the ARG alone is sufficient for RUN layers.
BuildKit cache mounts can retain stale .rmeta files from prior builds
with different dependency versions. If cargo build fails, clean the
target directory and retry once so builds self-heal.
With sccache backed by memcached (CI) or local disk (dev), compilation
caching is handled externally. The BuildKit cargo-target cache mounts
were the sole source of stale .rmeta files that caused build failures
when dependencies changed. Removing them eliminates the staleness
problem entirely and the touch-to-invalidate workarounds they required.
…t mounts

Replace cargo-target BuildKit cache mounts with sccache local disk cache
mounts (/tmp/sccache). This avoids stale .rmeta artifacts that plague
target/ mounts across dependency changes, while still giving local dev
builds fast incremental rebuilds. In CI, sccache uses memcached and
ignores the local disk mount. cross-build.sh defaults SCCACHE_DIR to
/tmp/sccache to align with the Dockerfile mount targets.
Bring back cargo-target BuildKit cache mounts alongside sccache disk
mounts. Without target/, cargo recompiles all dependencies on every
source change since it has no fingerprint state. The target mount gives
true incremental rebuilds locally; sccache provides a second cache layer
that survives target/ invalidation from dep changes. The touch workarounds
are restored to handle stale proto/build.rs artifacts in the target mount.
If cargo build fails (e.g. stale .rmeta in the BuildKit cargo-target
cache mount from a dependency version change), clean the target dir and
retry. The sccache layer still has compiled objects so the clean rebuild
is fast. This self-heals without manual docker builder prune.
Cache target/ directory and cargo registry between CI runs so
unchanged dependencies skip compilation entirely instead of relying
solely on sccache for individual compilation units.
The aqua backend for sccache does not support linux/arm64 despite
arm64 binaries being available on GitHub releases. Switch to the ubi
backend which downloads directly from GitHub releases and correctly
resolves the architecture.

Also add mise install steps to checks workflow to ensure tools are
available when the CI image may not have them pre-installed.
The ubi backend installed a broken sccache binary on linux/amd64 that
did not support RUSTC_WRAPPER mode. The github backend properly extracts
the release tarball and provides the correct binary.
Swatinem/rust-cache runs rustc -vV to compute the cache key, but
rustup has no default toolchain configured in the CI image (mise
manages Rust via shims). Without this, the cache action silently
fails and every run compiles from scratch.
@drew drew force-pushed the sccache-memcached-backend/an branch from 0451b81 to 798d150 Compare March 3, 2026 07:01
drew added 5 commits March 2, 2026 23:09
The previous approach wrote 'export KEY=value' shell syntax directly to
$GITHUB_ENV, which only accepts KEY=value format. This caused PATH not
to be updated, so sccache resolved to the mise shim instead of the
installed binary, failing with 'No version is set for shim: sccache'.

Split activation into:
- mise env --dotenv for env vars (proper KEY=VALUE format)
- GITHUB_PATH for PATH entries (correct GH Actions mechanism)
The mise shim at /opt/mise/shims/sccache cannot resolve the tool version
when cargo spawns it as a subprocess. Use 'mise which sccache' to get the
absolute binary path, bypassing the shim entirely.
mise which sccache fails on amd64 with 'sccache is a mise bin however
it is not currently active'. Run mise use -g to register the tool
globally so both the shim and mise which can resolve it.
The mise shim maps the sccache binary to ubi:mozilla/sccache, but the
tool was installed as github:mozilla/sccache. This backend mismatch
causes the shim to fail with 'No version is set for shim: sccache' on
amd64. The github: backend is deprecated in favor of ubi: in newer mise
versions — switching aligns the tool declaration with what the shim
expects.

Also removes the now-unnecessary 'Activate mise environment' CI step.
ubi:mozilla/sccache picks sccache-dist instead of sccache on x86_64
linux because both release assets match the platform and ubi selects
sccache-dist first alphabetically. The sccache-dist binary is the
distributed build scheduler, not the compiler cache wrapper, causing
RUSTC_WRAPPER to fail with 'unrecognized subcommand'.

Use matching="sccache-v" to filter release assets at download time,
ensuring ubi selects sccache-v0.14.0-* instead of sccache-dist-v0.14.0-*.
The exe option alone is insufficient because ubi partial-matches
sccache-dist containing sccache. arm64 is unaffected since sccache-dist
has no arm64 release asset.
@drew drew force-pushed the sccache-memcached-backend/an branch from e7b2512 to 6219fc6 Compare March 3, 2026 07:54
@drew drew merged commit 12a49e9 into main Mar 3, 2026
15 of 17 checks passed
@drew drew deleted the sccache-memcached-backend/an branch March 3, 2026 08:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

test:e2e Requires end-to-end coverage

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant