feat(gallery): publish signed OCI fallbacks (#12182)

* feat(gallery): publish signed OCI fallbacks

Publish both official gallery indexes with their local base configs so
an outage of the HTTP and GitHub sources can fall back to Quay.

Keep artifact signing policies separate from backend image policies,
and expose each moving gallery tag only after its digest is signed.

Assisted-by: Codex:gpt-6

* fix(gallery): confine packaged files to selected roots

Use directory-scoped file access to reject symlink escapes during gallery packaging. Create private bundle files for the publishing runner.

Assisted-by: Codex:GPT-6

---------

Co-authored-by: localai-org-maint-bot <306269227+localai-org-maint-bot@users.noreply.github.com>
This commit is contained in:
localai-org-maint-botandlocalai-org-maint-bot authored and GitHub committed 2026-09-27 21:18:38 +02:00
1 parent f154bd990a
commit 490b952d06
14 files changed
+345 -22

No files matched your search

+78
View File
@@ -0,0 +1,78 @@
name: Publish official OCI galleries
on:
push:
branches: [master]
paths:
- 'gallery/**'
- 'backend/index.yaml'
- 'scripts/build/gallery/**'
- '.github/workflows/gallery_publish.yml'
workflow_dispatch:
permissions:
contents: read
concurrency:
group: publish-official-galleries
cancel-in-progress: false
jobs:
publish:
if: github.repository == 'mudler/LocalAI' && github.ref == 'refs/heads/master'
runs-on: ubuntu-latest
permissions:
contents: read
id-token: write
env:
COSIGN_EXPERIMENTAL: '1'
GALLERY_REPOSITORY: quay.io/go-skynet/local-ai-backends
strategy:
matrix:
include:
- source: gallery
tag: gallery-models
- source: backend
tag: gallery-backends
steps:
- uses: actions/checkout@v7
- uses: actions/setup-go@v6
with:
go-version-file: go.mod
- name: Test and package gallery
env:
GALLERY_SOURCE: ${{ matrix.source }}
run: |
go test ./scripts/build/gallery -count=1
go run ./scripts/build/gallery . "$GALLERY_SOURCE" "$RUNNER_TEMP/gallery"
- uses: oras-project/setup-oras@v1
with:
version: '1.3.0'
- uses: sigstore/cosign-installer@v3
with:
cosign-release: 'v2.6.5'
- name: Login to Quay.io
uses: docker/login-action@v4
with:
registry: quay.io
username: ${{ secrets.LOCALAI_REGISTRY_USERNAME }}
password: ${{ secrets.LOCALAI_REGISTRY_PASSWORD }}
- name: Publish and sign gallery
shell: bash
env:
GALLERY_TAG: ${{ matrix.tag }}
run: |
set -euo pipefail
cd "$RUNNER_TEMP/gallery"
files=()
while IFS= read -r -d '' file; do
files+=("${file#./}:application/yaml")
done < <(find . -type f -print0 | sort -z)
# Publish an immutable revision, then expose latest only after signing.
ref="$GALLERY_REPOSITORY:$GALLERY_TAG-$GITHUB_SHA"
oras push --artifact-type application/vnd.localai.gallery.v1 \
--format json "$ref" "${files[@]}" > "$RUNNER_TEMP/push.json"
digest=$(jq -er '.digest' "$RUNNER_TEMP/push.json")
cosign sign --yes --new-bundle-format \
--registry-referrers-mode=oci-1-1 "$GALLERY_REPOSITORY@$digest"
oras tag "$GALLERY_REPOSITORY@$digest" "$GALLERY_TAG"