mirror of
https://github.com/mudler/LocalAI.git
synced 2026-07-30 18:09:05 -04:00
fix(ci): rebuild Go backends on linked pkg/ changes and on matrix entry edits (#10988)
PR #10975 taught the backend matrix filter about shared build inputs, but left two paths that still rebuild nothing. Go backends link code from the main tree. `go list -deps ./backend/go/...` resolves to exactly six pkg subtrees (audio, grpc incl. base/grpcerrors/proto, httpclient, sound, store, utils), identical for GOOS/GOARCH in {linux,darwin} x {amd64,arm64}. Editing any of them changes the shipped binary, but they sit outside every backend directory so the prefix match never saw them. Enumerating those six rather than taking all of pkg/ is the point: all of pkg/ changes in ~8.6% of commits, these six in 2.0% — the same order as the already accepted scripts/build/ rule (1.9%). Blast radius 199/417 Linux, 26/56 Darwin; the ~21 core-server-only pkg subtrees still rebuild nothing, and neither do _test.go files. .github/backend-matrix.yml was excluded wholesale because matching its path would rebuild all 417 entries on every new-backend PR. That hid a real hole: editing an existing entry's base-image, build-type or cuda version changes the image it produces while touching no file the filter can see. Since the change is within a structured file, compare it against the base revision and rebuild only the entries whose fields actually differ — 1 entry for a base-image edit, 0 for a comment or whitespace edit, and all 417 only when the previous revision cannot be resolved. This also closes a third hole: a new matrix entry for an existing backend (a new CUDA variant, say) touches nothing under that backend's directory and previously rebuilt nothing. changed-backends.js fetches the base revision via the contents API, and only when the changed-file list actually names the matrix file, so the common path costs no extra request. Assisted-by: Claude Code:claude-opus-4-8[1m] [Read] [Edit] [Bash] Signed-off-by: Ettore Di Giacinto <mudler@localai.io> Co-authored-by: Ettore Di Giacinto <mudler@localai.io>
This commit is contained in:
committed by
GitHub
parent
65bdbc4ee3
commit
a784cf669f
@@ -5,13 +5,14 @@ import { Octokit } from "@octokit/core";
|
||||
import {
|
||||
getAllBackendPaths,
|
||||
filterMatrix,
|
||||
BACKEND_MATRIX_FILE,
|
||||
} from "./lib/backend-filter.mjs";
|
||||
|
||||
// Matrix data lives in a small data-only YAML so both backend.yml (master push)
|
||||
// and backend_pr.yml (pull_request) can use a dynamic `matrix: ${{ fromJson(...) }}`
|
||||
// for the live job, while this script remains the single source of truth for
|
||||
// "what backends does the project know about".
|
||||
const matrixYml = yaml.load(fs.readFileSync(".github/backend-matrix.yml", "utf8"));
|
||||
const matrixYml = yaml.load(fs.readFileSync(BACKEND_MATRIX_FILE, "utf8"));
|
||||
const includes = matrixYml.include;
|
||||
const includesDarwin = matrixYml.includeDarwin;
|
||||
|
||||
@@ -76,6 +77,45 @@ async function getChangedFilesForPush(event) {
|
||||
return res.data.files.map(f => f.filename);
|
||||
}
|
||||
|
||||
// The matrix file's contents at the base revision, so filterMatrix can rebuild
|
||||
// only the entries whose fields actually changed instead of all 417 (or, as
|
||||
// before, none of them). Returns null when the previous revision cannot be
|
||||
// resolved, which filterMatrix treats as "rebuild everything".
|
||||
//
|
||||
// Only called when the changed-file list actually names the matrix file, so the
|
||||
// common path costs no extra API request.
|
||||
async function getPreviousMatrix(event) {
|
||||
const ref = event.pull_request ? event.pull_request.base.sha : event.before;
|
||||
if (!ref || /^0+$/.test(ref)) return null;
|
||||
const owner = event.repository.owner.login;
|
||||
const repo = event.repository.name;
|
||||
try {
|
||||
const res = await octokit.request('GET /repos/{owner}/{repo}/contents/{path}', {
|
||||
owner,
|
||||
repo,
|
||||
path: BACKEND_MATRIX_FILE,
|
||||
ref,
|
||||
mediaType: { format: 'raw' },
|
||||
});
|
||||
// `format: raw` yields a string; fall back to the JSON representation in
|
||||
// case a proxy or a future Octokit version ignores the media type.
|
||||
const raw = typeof res.data === 'string'
|
||||
? res.data
|
||||
: Buffer.from(res.data.content, 'base64').toString('utf8');
|
||||
const previous = yaml.load(raw);
|
||||
return {
|
||||
include: previous.include || [],
|
||||
includeDarwin: previous.includeDarwin || [],
|
||||
};
|
||||
} catch (err) {
|
||||
console.log(
|
||||
`could not read ${BACKEND_MATRIX_FILE} at ${ref}, falling back to run-all:`,
|
||||
err.message
|
||||
);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// Group matrix entries by tag-suffix and emit a merge-matrix entry per group.
|
||||
// Both multi-leg groups (per-arch fan-out) and singletons get one entry each:
|
||||
// the build job pushes by digest only with no tags applied, so every backend
|
||||
@@ -200,13 +240,14 @@ function emitFullMatrix() {
|
||||
}
|
||||
}
|
||||
|
||||
function emitFilteredMatrix(changedFiles) {
|
||||
function emitFilteredMatrix(changedFiles, previousMatrix) {
|
||||
console.log("Changed files:", changedFiles);
|
||||
|
||||
const { filtered, filteredDarwin, changedBackends } = filterMatrix({
|
||||
includes,
|
||||
includesDarwin,
|
||||
changedFiles,
|
||||
previousMatrix,
|
||||
});
|
||||
|
||||
console.log("Filtered files:", filtered);
|
||||
@@ -260,5 +301,10 @@ function emitFilteredMatrix(changedFiles) {
|
||||
emitFullMatrix();
|
||||
return;
|
||||
}
|
||||
emitFilteredMatrix(changedFiles);
|
||||
|
||||
const previousMatrix = changedFiles.includes(BACKEND_MATRIX_FILE)
|
||||
? await getPreviousMatrix(event)
|
||||
: null;
|
||||
|
||||
emitFilteredMatrix(changedFiles, previousMatrix);
|
||||
})();
|
||||
|
||||
Reference in New Issue
Block a user