Skip to content

build: replace ccache + GHA cache with sccache backed by Azure Blob Storage#208

Merged
tycho merged 2 commits into
mainfrom
steven/azure-sccache
Jul 15, 2026
Merged

build: replace ccache + GHA cache with sccache backed by Azure Blob Storage#208
tycho merged 2 commits into
mainfrom
steven/azure-sccache

Conversation

@tycho

@tycho tycho commented Jul 14, 2026

Copy link
Copy Markdown
Member

The previous compile cache serialized the whole ccache directory into a single GitHub Actions cache blob per flavor/arch. Those blobs shared the repo-wide 10GB cache budget and were routinely evicted before any build could benefit from them, and the 7-day per-entry TTL needed a scheduled workflow (cache-refresh.yml) whose only job was to keep entries alive.

Switch the compile phase to sccache with Azure Blob Storage as a shared backend (container sccache on the ederasccache storage account). Cache objects are stored and fetched individually, so there is no more monolithic save/restore step, no size cap to prune against, and all builders across all flavors, arches, and runs read and write the same namespace concurrently. Garbage collection is handled service-side by an Azure lifecycle rule that deletes objects unaccessed for 30 days, which lets cache-refresh.yml be deleted outright.

Details:

  • buildenv installs a pinned sccache release (checksum-verified per arch) and populates /usr/lib/sccache with wrapper scripts for the native and cross compilers. Wrappers reference the real compiler by absolute path because /usr/lib/sccache shadows the compiler names in PATH; a bare name would resolve back to the wrapper and recurse.
  • The generated docker.sh passes the SCCACHE_AZURE_* environment through by name only, so the script (which is uploaded as a workflow artifact) never contains credentials.
  • CI selects credentials per trigger: trusted (non-PR) builds get the read-write connection string, pull requests get a read-only token so an untrusted change cannot poison objects later consumed by release builds, and fork PRs (no secrets) fall back to a bind-mounted local disk cache -- the same fallback that keeps local developer builds cached across runs.
  • docker-build-internal.sh prints sccache --show-stats after each compile so hit rates and backend errors are visible in build logs.
  • The Dockerfile packaging targets and build context are renamed ccachebuild -> prebuilt, since what they consume are artifacts compiled out-of-band in the docker run phase, not anything ccache-specific.

@bleggett

Copy link
Copy Markdown
Contributor

xref - should close out: #166

bleggett
bleggett previously approved these changes Jul 14, 2026
Comment thread .github/workflows/matrix.yml
tycho added 2 commits July 14, 2026 15:16
…torage

The previous compile cache serialized the whole ccache directory into a
single GitHub Actions cache blob per flavor/arch. Those blobs shared the
repo-wide 10GB cache budget and were routinely evicted before any build
could benefit from them, and the 7-day per-entry TTL needed a scheduled
workflow (cache-refresh.yml) whose only job was to keep entries alive.

Switch the compile phase to sccache with Azure Blob Storage as a shared
backend (container `sccache` on the `ederasccache` storage account).
Cache objects are stored and fetched individually, so there is no more
monolithic save/restore step, no size cap to prune against, and all
builders across all flavors, arches, and runs read and write the same
namespace concurrently. Garbage collection is handled service-side by an
Azure lifecycle rule that deletes objects unaccessed for 30 days, which
lets cache-refresh.yml be deleted outright.

Details:

- The build environment now comes from the published kernel-buildenv
  image, pinned by digest (see Dockerfile.buildenv and buildenv.yml).
  That image carries the pinned, checksum-verified sccache release and
  the /usr/lib/sccache compiler wrapper scripts, so the Dockerfile's
  inline toolchain construction goes away entirely and the compilers can
  only change through a reviewed digest bump - which matters now that
  cache keys include the compiler binary's hash.
- The generated docker.sh passes the SCCACHE_AZURE_* environment through
  by name only, so the script (which is uploaded as a workflow artifact)
  never contains credentials.
- CI selects credentials from an explicit allowlist of maintainer-gated
  triggers: push, schedule, and workflow_dispatch get the read-write
  connection string, and everything else - pull requests today, any
  trigger added in the future - fails closed to a read-only token, so
  unreviewed code can never poison cache objects later consumed by
  release builds. Fork PRs (no secrets) fall back to a bind-mounted
  local disk cache, the same fallback that keeps local developer builds
  cached across runs.
- docker-build-internal.sh prints `sccache --show-stats` after each
  compile so hit rates and backend errors are visible in build logs.
- The Dockerfile packaging targets and build context are renamed
  ccachebuild -> prebuilt, since what they consume are artifacts
  compiled out-of-band in the docker run phase, not anything
  ccache-specific.

Signed-off-by: Steven Noonan <steven@edera.dev>
…stings

rsync.kernel.org caps concurrent connections (currently 100) and refuses
new sessions with exit code 5 when saturated, and matrix generation made
one rsync connection for the firmware listing plus one per kernel major
series - a connection-slot lottery on every run. Worse, rsync's stderr
was discarded, so CI logs never showed the "@error: max connections"
message; the failure had to be reproduced locally to be diagnosed.

Enumerate releases from git tags instead: `git ls-remote --tags --refs`
against git.kernel.org fetches only the server-side-filtered tag
advertisement (no clone), and git.kernel.org does not impose the rsync
daemon's aggressive connection cap. Release tags map 1:1 to published
artifacts: vX.Y[.Z] in stable/linux.git to linux-X.Y[.Z].tar.xz, and
YYYYMMDD in firmware/linux-firmware.git to
linux-firmware-YYYYMMDD.tar.xz (the live tag sets were verified to match
the rsync directory listings exactly, including the firmware range
20190312..present).

The listing helper retries with exponential backoff and jitter, and
prints the underlying stderr on each failed attempt, so any residual
network failure is both tolerated and visible in CI logs.

One behavioral note: linux.git tags only reach back to v2.6.11 while the
rsync tree lists tarballs to v1.0; nothing anywhere near that old is
buildable from this repo.

Signed-off-by: Steven Noonan <steven@edera.dev>
@tycho tycho force-pushed the steven/azure-sccache branch from bd7c21c to f15fdc2 Compare July 14, 2026 22:16
@tycho tycho marked this pull request as ready for review July 15, 2026 00:23
@tycho tycho merged commit f15fdc2 into main Jul 15, 2026
9 checks passed
@tycho tycho deleted the steven/azure-sccache branch July 15, 2026 14:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants