diff --git a/.agents/ci-caching.md b/.agents/ci-caching.md index 77b87467e..490bac2d2 100644 --- a/.agents/ci-caching.md +++ b/.agents/ci-caching.md @@ -259,10 +259,20 @@ Eviction is rarely needed in normal operation — `DEPS_REFRESH` handles weekly ## What the cache does **not** cover -- The `free-disk-space` and `setup-build-disk` composite actions run on every job — these reclaim runner-state, not Docker layers, so BuildKit caches don't apply. +- The `free-disk-space` and `setup-build-disk` composite actions run on every job — these reclaim runner-state, not Docker layers, so BuildKit caches don't apply. `test.yml` deliberately does **not** use `free-disk-space`: it runs no buildx step, and the multi-GB fixture downloads that once justified it left `make test` in the test-suite reorg. - Intermediate artifacts of `Build (PR)` are not pushed anywhere — PRs only build for verification. - Darwin builds (see below) — macOS runners have no Docker daemon, so the registry-backed BuildKit cache cannot apply. +### The Linux Go workflows set `cache: false` on purpose + +`test.yml`, `lint.yml`, `tests-e2e.yml` and friends pass `cache: false` to `actions/setup-go@v5`, unlike the darwin jobs. This looks like an oversight and is not. + +Measured over the week to 2026-07-30, the `Set up Go` step has a **median of 11 seconds** on these runners. There is essentially nothing to win: the module download is not where the time goes. The expensive steps are compilation and test execution (`Test (with coverage gate)` at ~18.6min, `Test Backend E2E` at ~14.5min), and Go's build cache would have to survive across runners to touch those. + +Enabling it also has a real cost. GitHub caps Actions cache at **10 GB per repo and the repo already sits at that ceiling** (31 entries), so every `setup-go` entry written by a branch with a distinct `go.sum` (222-375 MB on Linux, up to 1.4 GB on macOS) evicts something else. See the darwin cache budget below. + +Before re-enabling this, measure `Set up Go` again and confirm it has actually become slow. If room is needed in the 10 GB budget, the cheapest evictions are the `docker.io--tonistiigi--binfmt` entries (~30 MB each, trivially re-fetched). + ## Darwin native caches `backend_build_darwin.yml` runs natively on `macOS-14` GitHub-hosted runners — there is no Docker, no BuildKit, no cross-job registry cache. Instead, the reusable workflow uses `actions/cache@v4` for four native caches that mirror the spirit of the Linux cache (warm by default, weekly refresh for unpinned Python deps, PRs read-only). diff --git a/.github/workflows/build-test.yaml b/.github/workflows/build-test.yaml index 23d61d0f5..34b41e09f 100644 --- a/.github/workflows/build-test.yaml +++ b/.github/workflows/build-test.yaml @@ -35,9 +35,15 @@ jobs: uses: actions/setup-go@v5 with: go-version: 1.25 + # A PR builds only the host target. The three-platform cross-compile + # (linux/amd64, linux/arm64, darwin/arm64) is the bulk of this job's + # ~6.6min median and no PR consumes the resulting binaries. The + # before-hooks (protogen-go, react-ui, go mod tidy) run either way, so the + # "is the release build broken" signal is unchanged. master and tags still + # build everything. - name: Run GoReleaser run: | - make dev-dist + make ${{ github.event_name == 'pull_request' && 'dev-dist-single' || 'dev-dist' }} launcher-build-darwin: runs-on: macos-latest steps: diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 7e702a7dd..7081d630c 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -24,8 +24,13 @@ jobs: uses: actions/checkout@v7 with: submodules: true - - name: Free disk space - uses: ./.github/actions/free-disk-space + # No free-disk-space step here on purpose. That action exists to make room + # for docker buildx layers, and this job runs no buildx step. It was also + # sized for a `make test` that downloaded multi-GB GGUF/whisper fixtures + # and built llama-cpp/whisper/stablediffusion-ggml; after the test-suite + # reorg it does neither (see the Makefile test target). It cost ~3min of + # every run, and its tool-cache:true wipe also forced setup-go and + # setup-node to re-download toolchains that ship preinstalled. - name: Setup Go ${{ matrix.go-version }} uses: actions/setup-go@v5 with: diff --git a/Makefile b/Makefile index af40ee7cf..699c6fd61 100644 --- a/Makefile +++ b/Makefile @@ -172,6 +172,15 @@ build-dev: ## Run LocalAI in dev mode with live reload dev-dist: $(GORELEASER) build --snapshot --clean +## PR-time variant of dev-dist: builds only the host platform instead of all +## three release targets (linux/amd64, linux/arm64, darwin/arm64). The point of +## running goreleaser on a PR is to catch a broken config or a broken +## before-hook (protogen-go, react-ui, go mod tidy), and --single-target still +## exercises every one of those. Nothing consumes a PR's cross-compiled +## binaries. master pushes and tags still run the full dev-dist/dist. +dev-dist-single: + $(GORELEASER) build --snapshot --clean --single-target + dist: $(GORELEASER) build --clean