From a1620579c78dbd147a513b213cd1972409ce38e5 Mon Sep 17 00:00:00 2001 From: "mudler's LocalAI [bot]" <139863280+localai-bot@users.noreply.github.com> Date: Thu, 30 Jul 2026 15:13:53 +0200 Subject: [PATCH] fix(ci): skip the core image and release build on backend-only diffs (#11224) Version-pin bumps dominate PR volume: 48 update/* PRs in the week to 2026-07-30, from 16 pins, each a two-line diff. bump_deps.yaml runs a 28-entry matrix daily and opens one PR per moved pin; CRISPASR and the gallery checksum produced one every day, ik-llama-cpp six in seven days. Almost all of them edit nothing but a single backend/*//Makefile. Neither image-pr.yml nor build-test.yaml can observe such a change. `make build` is `go build ./cmd/local-ai`, GoReleaser builds that plus ./cmd/launcher, and the core image's final stage ships only entrypoint.sh, healthcheck.sh and the binary. The per-backend trees are copied into the builder but nothing in them reaches the output. That is 7 + 3 jobs per bump PR that cannot fail for a reason the diff caused, roughly 410 jobs a week. Add backend/{cpp,go,python}/** to the paths-ignore of those two workflows. The inputs that do reach the binary are deliberately outside those prefixes and so still trigger a full run: backend/backend.proto (protogen-go), go.mod/go.sum (the go mod tidy before-hook), and backend/Dockerfile.* . Not applied to the workflows that genuinely read that tree: test.yml TEST_PATHS names ./backend/go/{cloud-proxy,local-store, valkey-store}/... lint.yml .golangci.yml carries backend/-scoped rules tests-e2e.yml the e2e suite drives real backends over gRPC backend_pr.yml its whole job is rebuilding the changed backend Simulated against the change shapes that occur in this repo. Pin bumps and python requirement bumps skip; backend.proto, go.mod, a core Go edit, a backend/Dockerfile edit and any mixed diff all still run, since paths-ignore skips only when every changed file matches. Assisted-by: Claude:opus-5 [claude-code] Signed-off-by: Ettore Di Giacinto Co-authored-by: Ettore Di Giacinto --- .agents/ci-caching.md | 21 +++++++++++++++++++++ .github/workflows/build-test.yaml | 9 +++++++++ .github/workflows/image-pr.yml | 10 ++++++++++ 3 files changed, 40 insertions(+) diff --git a/.agents/ci-caching.md b/.agents/ci-caching.md index cc0e7c5d0..11f6b6b77 100644 --- a/.agents/ci-caching.md +++ b/.agents/ci-caching.md @@ -160,6 +160,27 @@ The volume is real: 13 gallery-only PRs merged that week with 10 open at once, a | `gallery/**` | Model-gallery metadata, parsed at runtime, never copied into an image | | `docs/**`, `examples/**`, `**/*.md` | Never enter an image or a binary. `lint.yml` already excluded these before gallery was added | +### `backend/{cpp,go,python}/**` on `image-pr.yml` and `build-test.yaml` only + +Version-pin bumps dominate PR volume: 48 `update/*` PRs in the week to 2026-07-30, from 16 pins, each a two-line diff. Most edit nothing but one `backend/*//Makefile`. + +Neither of those two workflows can observe such a change. `make build` is `go build ./cmd/local-ai`, GoReleaser builds the same plus `./cmd/launcher`, and the core image's final stage ships only `entrypoint.sh`, `healthcheck.sh` and that binary. The per-backend trees are copied into the builder but nothing in them reaches the output. + +What still triggers a full run, because none of it lives under those prefixes: + +- `backend/backend.proto` — feeds `protogen-go`, so it does change the binary. +- `go.mod` / `go.sum` — the `go mod tidy` before-hook. +- `backend/Dockerfile.*` and anything else directly under `backend/`. + +Deliberately **not** applied to: + +| Workflow | Why it must keep seeing `backend/**` | +|---|---| +| `test.yml` | `TEST_PATHS` explicitly includes `./backend/go/cloud-proxy/...`, `./backend/go/local-store/...` and `./backend/go/valkey-store/...` | +| `lint.yml` | `.golangci.yml` carries `backend/`-scoped rules, so golangci-lint covers that tree | +| `tests-e2e.yml` | The e2e suite drives real backends over gRPC | +| `backend_pr.yml` | This is the workflow whose entire job is to rebuild the changed backend | + What still runs, and why it has to: | Workflow | Why it keeps running | diff --git a/.github/workflows/build-test.yaml b/.github/workflows/build-test.yaml index 34b41e09f..08fb2d084 100644 --- a/.github/workflows/build-test.yaml +++ b/.github/workflows/build-test.yaml @@ -8,12 +8,21 @@ on: # GoReleaser and the darwin launcher take no gallery, docs or markdown # input, so a diff confined to these paths cannot change either binary. # The darwin job matters here: macOS is the scarcest runner class. + # + # backend/{cpp,go,python}/**: GoReleaser builds ./cmd/local-ai and the + # launcher builds ./cmd/launcher; neither compiles a backend. The + # before-hooks still matter, but their input is backend/backend.proto + # (protogen-go) and go.mod/go.sum (go mod tidy), none of which live under + # these prefixes, so a change to any of those still triggers a full run. # See .agents/ci-caching.md. paths-ignore: - 'gallery/**' - 'docs/**' - 'examples/**' - '**/*.md' + - 'backend/cpp/**' + - 'backend/go/**' + - 'backend/python/**' # Supersede an in-flight run when a PR gets a new push. Keyed on the PR number # so every push to the same PR shares a group; on a master push the key falls diff --git a/.github/workflows/image-pr.yml b/.github/workflows/image-pr.yml index fbf077383..2605c2541 100644 --- a/.github/workflows/image-pr.yml +++ b/.github/workflows/image-pr.yml @@ -8,12 +8,22 @@ # image; docs and markdown never enter one at all. Gallery content is # still checked by yaml-check.yml and by # core/gallery/variants_lint_test.go under 'tests'. + # + # backend/{cpp,go,python}/**: this workflow builds the core image, whose + # only compiled output is `make build` -> `go build ./cmd/local-ai`. The + # per-backend trees are copied into the builder but nothing in them reaches + # the binary or the final stage. backend/backend.proto is deliberately not + # listed: it feeds protogen-go and so does change the binary, and it does + # not live under any of these prefixes, so it still triggers a full run. # See .agents/ci-caching.md. paths-ignore: - 'gallery/**' - 'docs/**' - 'examples/**' - '**/*.md' + - 'backend/cpp/**' + - 'backend/go/**' + - 'backend/python/**' concurrency: group: ci-${{ github.event.pull_request.number || github.sha }}-${{ github.repository }}