mirror of
https://github.com/mudler/LocalAI.git
synced 2026-07-07 06:49:49 -04:00
GitHub Actions refuses to instantiate a matrix that would generate more than 256 jobs. It does so silently: the job hangs forever at "Waiting for pending jobs" and the whole run is marked `failure` while every other job stays green. This is exactly what happened on the v4.6.1 tag build (run 28786533892): the single-arch build matrix had grown to 268 entries, so `backend-jobs-singlearch` (and its downstream merge) never produced a single job, and the release build "failed" with no failing job to point at. The single-arch list is the one that grows unbounded as backends are added, so shard it across a fixed number of matrix jobs (SINGLEARCH_SHARDS=4, ~67 entries each today, headroom to ~1020 backends). Each merge shard `needs:` only its matching build shard, preserving the "merge waits only on its own build" property that keeps slow CUDA/ROCm builds from gating multi-arch manifest assembly. changed-backends.js now emits per-shard matrix/has-* outputs and throws loudly if a shard ever reaches the 256 limit (telling the maintainer to bump SINGLEARCH_SHARDS and add matching job blocks) instead of letting GitHub drop the overflow silently. backend.yml and backend_pr.yml define the four build + four merge shard jobs; multi-arch and darwin groups are untouched. Assisted-by: Claude:claude-opus-4-8 [Claude Code] Signed-off-by: Ettore Di Giacinto <mudler@localai.io> Co-authored-by: Ettore Di Giacinto <mudler@localai.io>
295 lines
14 KiB
YAML
295 lines
14 KiB
YAML
name: 'build backend container images (PR-filtered)'
|
|
|
|
on:
|
|
pull_request:
|
|
|
|
concurrency:
|
|
group: ci-backends-pr-${{ github.event.pull_request.number || github.sha }}-${{ github.repository }}
|
|
cancel-in-progress: ${{ github.event_name == 'pull_request' }}
|
|
|
|
jobs:
|
|
generate-matrix:
|
|
runs-on: ubuntu-latest
|
|
outputs:
|
|
matrix-multiarch: ${{ steps.set-matrix.outputs['matrix-multiarch'] }}
|
|
matrix-darwin: ${{ steps.set-matrix.outputs['matrix-darwin'] }}
|
|
merge-matrix-multiarch: ${{ steps.set-matrix.outputs['merge-matrix-multiarch'] }}
|
|
has-backends-multiarch: ${{ steps.set-matrix.outputs['has-backends-multiarch'] }}
|
|
has-backends-darwin: ${{ steps.set-matrix.outputs['has-backends-darwin'] }}
|
|
has-merges-multiarch: ${{ steps.set-matrix.outputs['has-merges-multiarch'] }}
|
|
# Single-arch backends are sharded across SINGLEARCH_SHARDS matrix jobs to
|
|
# stay under GitHub's 256-jobs-per-matrix limit (see changed-backends.js).
|
|
matrix-singlearch-1: ${{ steps.set-matrix.outputs['matrix-singlearch-1'] }}
|
|
merge-matrix-singlearch-1: ${{ steps.set-matrix.outputs['merge-matrix-singlearch-1'] }}
|
|
has-backends-singlearch-1: ${{ steps.set-matrix.outputs['has-backends-singlearch-1'] }}
|
|
has-merges-singlearch-1: ${{ steps.set-matrix.outputs['has-merges-singlearch-1'] }}
|
|
matrix-singlearch-2: ${{ steps.set-matrix.outputs['matrix-singlearch-2'] }}
|
|
merge-matrix-singlearch-2: ${{ steps.set-matrix.outputs['merge-matrix-singlearch-2'] }}
|
|
has-backends-singlearch-2: ${{ steps.set-matrix.outputs['has-backends-singlearch-2'] }}
|
|
has-merges-singlearch-2: ${{ steps.set-matrix.outputs['has-merges-singlearch-2'] }}
|
|
matrix-singlearch-3: ${{ steps.set-matrix.outputs['matrix-singlearch-3'] }}
|
|
merge-matrix-singlearch-3: ${{ steps.set-matrix.outputs['merge-matrix-singlearch-3'] }}
|
|
has-backends-singlearch-3: ${{ steps.set-matrix.outputs['has-backends-singlearch-3'] }}
|
|
has-merges-singlearch-3: ${{ steps.set-matrix.outputs['has-merges-singlearch-3'] }}
|
|
matrix-singlearch-4: ${{ steps.set-matrix.outputs['matrix-singlearch-4'] }}
|
|
merge-matrix-singlearch-4: ${{ steps.set-matrix.outputs['merge-matrix-singlearch-4'] }}
|
|
has-backends-singlearch-4: ${{ steps.set-matrix.outputs['has-backends-singlearch-4'] }}
|
|
has-merges-singlearch-4: ${{ steps.set-matrix.outputs['has-merges-singlearch-4'] }}
|
|
steps:
|
|
- name: Checkout repository
|
|
uses: actions/checkout@v7
|
|
|
|
- name: Setup Bun
|
|
uses: oven-sh/setup-bun@v2
|
|
|
|
- name: Install dependencies
|
|
run: |
|
|
bun add js-yaml
|
|
bun add @octokit/core
|
|
|
|
# filters the matrix in backend.yml; splits into single-arch and
|
|
# multi-arch groups so backend-merge-jobs can `needs:` only the latter
|
|
# (matches backend.yml's structure).
|
|
- name: Filter matrix for changed backends
|
|
id: set-matrix
|
|
env:
|
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
GITHUB_EVENT_PATH: ${{ github.event_path }}
|
|
run: bun run scripts/changed-backends.js
|
|
|
|
backend-jobs-multiarch:
|
|
needs: generate-matrix
|
|
uses: ./.github/workflows/backend_build.yml
|
|
if: needs.generate-matrix.outputs['has-backends-multiarch'] == 'true'
|
|
with:
|
|
tag-latest: ${{ matrix.tag-latest }}
|
|
tag-suffix: ${{ matrix.tag-suffix }}
|
|
build-type: ${{ matrix.build-type }}
|
|
cuda-major-version: ${{ matrix.cuda-major-version }}
|
|
cuda-minor-version: ${{ matrix.cuda-minor-version }}
|
|
platforms: ${{ matrix.platforms }}
|
|
platform-tag: ${{ matrix.platform-tag || '' }}
|
|
runs-on: ${{ matrix.runs-on }}
|
|
builder-base-image: ${{ matrix.builder-base-image || '' }}
|
|
base-image: ${{ matrix.base-image }}
|
|
backend: ${{ matrix.backend }}
|
|
dockerfile: ${{ matrix.dockerfile }}
|
|
skip-drivers: ${{ matrix.skip-drivers }}
|
|
context: ${{ matrix.context }}
|
|
ubuntu-version: ${{ matrix.ubuntu-version }}
|
|
amdgpu-targets: ${{ matrix.amdgpu-targets || 'gfx908,gfx90a,gfx942,gfx950,gfx1030,gfx1100,gfx1101,gfx1102,gfx1151,gfx1200,gfx1201' }}
|
|
secrets:
|
|
quayUsername: ${{ secrets.LOCALAI_REGISTRY_USERNAME }}
|
|
quayPassword: ${{ secrets.LOCALAI_REGISTRY_PASSWORD }}
|
|
strategy:
|
|
fail-fast: true
|
|
max-parallel: 8
|
|
matrix: ${{ fromJson(needs.generate-matrix.outputs['matrix-multiarch']) }}
|
|
backend-jobs-singlearch-1:
|
|
needs: generate-matrix
|
|
if: needs.generate-matrix.outputs['has-backends-singlearch-1'] == 'true'
|
|
uses: ./.github/workflows/backend_build.yml
|
|
with:
|
|
tag-latest: ${{ matrix.tag-latest }}
|
|
tag-suffix: ${{ matrix.tag-suffix }}
|
|
build-type: ${{ matrix.build-type }}
|
|
cuda-major-version: ${{ matrix.cuda-major-version }}
|
|
cuda-minor-version: ${{ matrix.cuda-minor-version }}
|
|
platforms: ${{ matrix.platforms }}
|
|
platform-tag: ${{ matrix.platform-tag || '' }}
|
|
runs-on: ${{ matrix.runs-on }}
|
|
builder-base-image: ${{ matrix.builder-base-image || '' }}
|
|
base-image: ${{ matrix.base-image }}
|
|
backend: ${{ matrix.backend }}
|
|
dockerfile: ${{ matrix.dockerfile }}
|
|
skip-drivers: ${{ matrix.skip-drivers }}
|
|
context: ${{ matrix.context }}
|
|
ubuntu-version: ${{ matrix.ubuntu-version }}
|
|
amdgpu-targets: ${{ matrix.amdgpu-targets || 'gfx908,gfx90a,gfx942,gfx950,gfx1030,gfx1100,gfx1101,gfx1102,gfx1151,gfx1200,gfx1201' }}
|
|
secrets:
|
|
quayUsername: ${{ secrets.LOCALAI_REGISTRY_USERNAME }}
|
|
quayPassword: ${{ secrets.LOCALAI_REGISTRY_PASSWORD }}
|
|
strategy:
|
|
fail-fast: true
|
|
max-parallel: 8
|
|
matrix: ${{ fromJson(needs.generate-matrix.outputs['matrix-singlearch-1']) }}
|
|
|
|
backend-jobs-singlearch-2:
|
|
needs: generate-matrix
|
|
if: needs.generate-matrix.outputs['has-backends-singlearch-2'] == 'true'
|
|
uses: ./.github/workflows/backend_build.yml
|
|
with:
|
|
tag-latest: ${{ matrix.tag-latest }}
|
|
tag-suffix: ${{ matrix.tag-suffix }}
|
|
build-type: ${{ matrix.build-type }}
|
|
cuda-major-version: ${{ matrix.cuda-major-version }}
|
|
cuda-minor-version: ${{ matrix.cuda-minor-version }}
|
|
platforms: ${{ matrix.platforms }}
|
|
platform-tag: ${{ matrix.platform-tag || '' }}
|
|
runs-on: ${{ matrix.runs-on }}
|
|
builder-base-image: ${{ matrix.builder-base-image || '' }}
|
|
base-image: ${{ matrix.base-image }}
|
|
backend: ${{ matrix.backend }}
|
|
dockerfile: ${{ matrix.dockerfile }}
|
|
skip-drivers: ${{ matrix.skip-drivers }}
|
|
context: ${{ matrix.context }}
|
|
ubuntu-version: ${{ matrix.ubuntu-version }}
|
|
amdgpu-targets: ${{ matrix.amdgpu-targets || 'gfx908,gfx90a,gfx942,gfx950,gfx1030,gfx1100,gfx1101,gfx1102,gfx1151,gfx1200,gfx1201' }}
|
|
secrets:
|
|
quayUsername: ${{ secrets.LOCALAI_REGISTRY_USERNAME }}
|
|
quayPassword: ${{ secrets.LOCALAI_REGISTRY_PASSWORD }}
|
|
strategy:
|
|
fail-fast: true
|
|
max-parallel: 8
|
|
matrix: ${{ fromJson(needs.generate-matrix.outputs['matrix-singlearch-2']) }}
|
|
|
|
backend-jobs-singlearch-3:
|
|
needs: generate-matrix
|
|
if: needs.generate-matrix.outputs['has-backends-singlearch-3'] == 'true'
|
|
uses: ./.github/workflows/backend_build.yml
|
|
with:
|
|
tag-latest: ${{ matrix.tag-latest }}
|
|
tag-suffix: ${{ matrix.tag-suffix }}
|
|
build-type: ${{ matrix.build-type }}
|
|
cuda-major-version: ${{ matrix.cuda-major-version }}
|
|
cuda-minor-version: ${{ matrix.cuda-minor-version }}
|
|
platforms: ${{ matrix.platforms }}
|
|
platform-tag: ${{ matrix.platform-tag || '' }}
|
|
runs-on: ${{ matrix.runs-on }}
|
|
builder-base-image: ${{ matrix.builder-base-image || '' }}
|
|
base-image: ${{ matrix.base-image }}
|
|
backend: ${{ matrix.backend }}
|
|
dockerfile: ${{ matrix.dockerfile }}
|
|
skip-drivers: ${{ matrix.skip-drivers }}
|
|
context: ${{ matrix.context }}
|
|
ubuntu-version: ${{ matrix.ubuntu-version }}
|
|
amdgpu-targets: ${{ matrix.amdgpu-targets || 'gfx908,gfx90a,gfx942,gfx950,gfx1030,gfx1100,gfx1101,gfx1102,gfx1151,gfx1200,gfx1201' }}
|
|
secrets:
|
|
quayUsername: ${{ secrets.LOCALAI_REGISTRY_USERNAME }}
|
|
quayPassword: ${{ secrets.LOCALAI_REGISTRY_PASSWORD }}
|
|
strategy:
|
|
fail-fast: true
|
|
max-parallel: 8
|
|
matrix: ${{ fromJson(needs.generate-matrix.outputs['matrix-singlearch-3']) }}
|
|
|
|
backend-jobs-singlearch-4:
|
|
needs: generate-matrix
|
|
if: needs.generate-matrix.outputs['has-backends-singlearch-4'] == 'true'
|
|
uses: ./.github/workflows/backend_build.yml
|
|
with:
|
|
tag-latest: ${{ matrix.tag-latest }}
|
|
tag-suffix: ${{ matrix.tag-suffix }}
|
|
build-type: ${{ matrix.build-type }}
|
|
cuda-major-version: ${{ matrix.cuda-major-version }}
|
|
cuda-minor-version: ${{ matrix.cuda-minor-version }}
|
|
platforms: ${{ matrix.platforms }}
|
|
platform-tag: ${{ matrix.platform-tag || '' }}
|
|
runs-on: ${{ matrix.runs-on }}
|
|
builder-base-image: ${{ matrix.builder-base-image || '' }}
|
|
base-image: ${{ matrix.base-image }}
|
|
backend: ${{ matrix.backend }}
|
|
dockerfile: ${{ matrix.dockerfile }}
|
|
skip-drivers: ${{ matrix.skip-drivers }}
|
|
context: ${{ matrix.context }}
|
|
ubuntu-version: ${{ matrix.ubuntu-version }}
|
|
amdgpu-targets: ${{ matrix.amdgpu-targets || 'gfx908,gfx90a,gfx942,gfx950,gfx1030,gfx1100,gfx1101,gfx1102,gfx1151,gfx1200,gfx1201' }}
|
|
secrets:
|
|
quayUsername: ${{ secrets.LOCALAI_REGISTRY_USERNAME }}
|
|
quayPassword: ${{ secrets.LOCALAI_REGISTRY_PASSWORD }}
|
|
strategy:
|
|
fail-fast: true
|
|
max-parallel: 8
|
|
matrix: ${{ fromJson(needs.generate-matrix.outputs['matrix-singlearch-4']) }}
|
|
backend-merge-jobs-multiarch:
|
|
needs: [generate-matrix, backend-jobs-multiarch]
|
|
# backend_merge.yml's push-side steps are all gated on
|
|
# github.event_name != 'pull_request', so on a PR the merge job would
|
|
# do nothing. Skip it entirely to avoid spinning up an empty runner.
|
|
# !cancelled() lets the merge run even when a few build legs fail —
|
|
# see the matching note in backend.yml.
|
|
if: ${{ !cancelled() && github.event_name != 'pull_request' && needs.generate-matrix.outputs['has-merges-multiarch'] == 'true' }}
|
|
uses: ./.github/workflows/backend_merge.yml
|
|
with:
|
|
tag-latest: ${{ matrix.tag-latest }}
|
|
tag-suffix: ${{ matrix.tag-suffix }}
|
|
secrets:
|
|
quayUsername: ${{ secrets.LOCALAI_REGISTRY_USERNAME }}
|
|
quayPassword: ${{ secrets.LOCALAI_REGISTRY_PASSWORD }}
|
|
strategy:
|
|
fail-fast: false
|
|
matrix: ${{ fromJson(needs.generate-matrix.outputs['merge-matrix-multiarch']) }}
|
|
|
|
backend-merge-jobs-singlearch-1:
|
|
needs: [generate-matrix, backend-jobs-singlearch-1]
|
|
if: ${{ !cancelled() && github.event_name != 'pull_request' && needs.generate-matrix.outputs['has-merges-singlearch-1'] == 'true' }}
|
|
uses: ./.github/workflows/backend_merge.yml
|
|
with:
|
|
tag-latest: ${{ matrix.tag-latest }}
|
|
tag-suffix: ${{ matrix.tag-suffix }}
|
|
secrets:
|
|
quayUsername: ${{ secrets.LOCALAI_REGISTRY_USERNAME }}
|
|
quayPassword: ${{ secrets.LOCALAI_REGISTRY_PASSWORD }}
|
|
strategy:
|
|
fail-fast: false
|
|
matrix: ${{ fromJson(needs.generate-matrix.outputs['merge-matrix-singlearch-1']) }}
|
|
|
|
backend-merge-jobs-singlearch-2:
|
|
needs: [generate-matrix, backend-jobs-singlearch-2]
|
|
if: ${{ !cancelled() && github.event_name != 'pull_request' && needs.generate-matrix.outputs['has-merges-singlearch-2'] == 'true' }}
|
|
uses: ./.github/workflows/backend_merge.yml
|
|
with:
|
|
tag-latest: ${{ matrix.tag-latest }}
|
|
tag-suffix: ${{ matrix.tag-suffix }}
|
|
secrets:
|
|
quayUsername: ${{ secrets.LOCALAI_REGISTRY_USERNAME }}
|
|
quayPassword: ${{ secrets.LOCALAI_REGISTRY_PASSWORD }}
|
|
strategy:
|
|
fail-fast: false
|
|
matrix: ${{ fromJson(needs.generate-matrix.outputs['merge-matrix-singlearch-2']) }}
|
|
|
|
backend-merge-jobs-singlearch-3:
|
|
needs: [generate-matrix, backend-jobs-singlearch-3]
|
|
if: ${{ !cancelled() && github.event_name != 'pull_request' && needs.generate-matrix.outputs['has-merges-singlearch-3'] == 'true' }}
|
|
uses: ./.github/workflows/backend_merge.yml
|
|
with:
|
|
tag-latest: ${{ matrix.tag-latest }}
|
|
tag-suffix: ${{ matrix.tag-suffix }}
|
|
secrets:
|
|
quayUsername: ${{ secrets.LOCALAI_REGISTRY_USERNAME }}
|
|
quayPassword: ${{ secrets.LOCALAI_REGISTRY_PASSWORD }}
|
|
strategy:
|
|
fail-fast: false
|
|
matrix: ${{ fromJson(needs.generate-matrix.outputs['merge-matrix-singlearch-3']) }}
|
|
|
|
backend-merge-jobs-singlearch-4:
|
|
needs: [generate-matrix, backend-jobs-singlearch-4]
|
|
if: ${{ !cancelled() && github.event_name != 'pull_request' && needs.generate-matrix.outputs['has-merges-singlearch-4'] == 'true' }}
|
|
uses: ./.github/workflows/backend_merge.yml
|
|
with:
|
|
tag-latest: ${{ matrix.tag-latest }}
|
|
tag-suffix: ${{ matrix.tag-suffix }}
|
|
secrets:
|
|
quayUsername: ${{ secrets.LOCALAI_REGISTRY_USERNAME }}
|
|
quayPassword: ${{ secrets.LOCALAI_REGISTRY_PASSWORD }}
|
|
strategy:
|
|
fail-fast: false
|
|
matrix: ${{ fromJson(needs.generate-matrix.outputs['merge-matrix-singlearch-4']) }}
|
|
backend-jobs-darwin:
|
|
needs: generate-matrix
|
|
uses: ./.github/workflows/backend_build_darwin.yml
|
|
if: needs.generate-matrix.outputs.has-backends-darwin == 'true'
|
|
with:
|
|
backend: ${{ matrix.backend }}
|
|
build-type: ${{ matrix.build-type }}
|
|
go-version: "1.25.x"
|
|
tag-suffix: ${{ matrix.tag-suffix }}
|
|
lang: ${{ matrix.lang || 'python' }}
|
|
use-pip: ${{ matrix.backend == 'diffusers' }}
|
|
runs-on: "macos-latest"
|
|
secrets:
|
|
quayUsername: ${{ secrets.LOCALAI_REGISTRY_USERNAME }}
|
|
quayPassword: ${{ secrets.LOCALAI_REGISTRY_PASSWORD }}
|
|
strategy:
|
|
fail-fast: true
|
|
matrix: ${{ fromJson(needs.generate-matrix.outputs.matrix-darwin) }}
|