mirror of
https://github.com/mudler/LocalAI.git
synced 2026-10-10 07:47:29 -04:00
Large release runs exceed the artifact API limit of 1,000 items. Use authenticated public API pagination and set its limit from the run artifact count so manifest jobs can find their existing digests. Assisted-by: Codex:gpt-6 Co-authored-by: localai-org-maint-bot <306269227+localai-org-maint-bot@users.noreply.github.com>
163 lines
6.2 KiB
YAML
163 lines
6.2 KiB
YAML
---
|
|
name: 'merge LocalAI image manifest list (reusable)'
|
|
|
|
# Reusable workflow that joins per-arch digest artifacts (uploaded by
|
|
# image_build.yml when called with platform-tag) into a single tagged
|
|
# multi-arch manifest list.
|
|
|
|
on:
|
|
workflow_call:
|
|
inputs:
|
|
tag-latest:
|
|
description: 'Whether the manifest list should also be tagged latest (auto/false/true)'
|
|
required: false
|
|
type: string
|
|
default: ''
|
|
tag-suffix:
|
|
description: 'Image tag suffix (empty for core image). Used in artifact pattern with a -core placeholder for empty.'
|
|
required: true
|
|
type: string
|
|
secrets:
|
|
dockerUsername:
|
|
required: false
|
|
dockerPassword:
|
|
required: false
|
|
quayUsername:
|
|
required: true
|
|
quayPassword:
|
|
required: true
|
|
|
|
jobs:
|
|
merge:
|
|
runs-on: ubuntu-latest
|
|
permissions:
|
|
actions: read
|
|
contents: read
|
|
env:
|
|
quay_username: ${{ secrets.quayUsername }}
|
|
steps:
|
|
# Sparse checkout: needed for .github/scripts/ (the keepalive cleanup
|
|
# script). Skips the rest of the source tree.
|
|
- name: Checkout (.github/scripts only)
|
|
uses: actions/checkout@v7
|
|
with:
|
|
sparse-checkout: |
|
|
.github/scripts
|
|
sparse-checkout-cone-mode: false
|
|
|
|
# The internal artifact API truncates large release runs at 1,000 items.
|
|
# Use the paginated public API with a limit taken from this run.
|
|
- name: Count run artifacts
|
|
id: artifacts
|
|
env:
|
|
GH_TOKEN: ${{ github.token }}
|
|
run: |
|
|
count=$(gh api "repos/$GITHUB_REPOSITORY/actions/runs/$GITHUB_RUN_ID/artifacts?per_page=1" --jq .total_count)
|
|
echo "count=$count" >> "$GITHUB_OUTPUT"
|
|
|
|
- name: Download digests
|
|
uses: actions/download-artifact@v8
|
|
env:
|
|
ACTIONS_ARTIFACT_MAX_ARTIFACT_COUNT: ${{ steps.artifacts.outputs.count }}
|
|
with:
|
|
github-token: ${{ github.token }}
|
|
# `--` separator anchors the glob so we don't over-match sibling
|
|
# tag-suffixes (e.g. -nvidia-l4t-arm64 vs -nvidia-l4t-arm64-cuda-13).
|
|
# Must stay in sync with image_build.yml's upload-artifact name.
|
|
pattern: digests-localai${{ inputs.tag-suffix == '' && '-core' || inputs.tag-suffix }}--*
|
|
merge-multiple: true
|
|
path: /tmp/digests
|
|
|
|
- name: Set up Docker Buildx
|
|
uses: docker/setup-buildx-action@master
|
|
|
|
- name: Login to DockerHub
|
|
if: github.event_name != 'pull_request'
|
|
uses: docker/login-action@v4
|
|
with:
|
|
username: ${{ secrets.dockerUsername }}
|
|
password: ${{ secrets.dockerPassword }}
|
|
|
|
- name: Login to Quay.io
|
|
uses: docker/login-action@v4
|
|
with:
|
|
registry: quay.io
|
|
username: ${{ secrets.quayUsername }}
|
|
password: ${{ secrets.quayPassword }}
|
|
|
|
- name: Docker meta
|
|
id: meta
|
|
uses: docker/metadata-action@v6
|
|
with:
|
|
images: |
|
|
quay.io/go-skynet/local-ai
|
|
localai/localai
|
|
tags: |
|
|
type=ref,event=branch
|
|
type=semver,pattern={{raw}}
|
|
type=sha
|
|
type=raw,value={{branch}}-{{date 'X'}}-{{sha}},enable={{is_default_branch}}
|
|
flavor: |
|
|
latest=${{ inputs.tag-latest }}
|
|
suffix=${{ inputs.tag-suffix }},onlatest=true
|
|
|
|
# Source from ci-cache, not local-ai. See backend_merge.yml for the
|
|
# detailed rationale — quay's manifest GC is per-repository, so the
|
|
# untagged digest in local-ai gets reaped while the same content lives
|
|
# tagged under ci-cache (anchored by image_build.yml). buildx imagetools
|
|
# create copies the manifest into local-ai (blobs already cross-mounted)
|
|
# and publishes the manifest list with user-facing tags. End state in
|
|
# local-ai is self-contained; no embedded reference to ci-cache.
|
|
- name: Create manifest list and push (quay)
|
|
working-directory: /tmp/digests
|
|
run: |
|
|
set -euo pipefail
|
|
tags=$(jq -cr '.tags | map(select(startswith("quay.io/"))) | map("-t " + .) | join(" ")' <<< "$DOCKER_METADATA_OUTPUT_JSON")
|
|
if [ -z "$tags" ]; then
|
|
echo "No quay.io tags from docker/metadata-action; skipping quay merge"
|
|
else
|
|
# shellcheck disable=SC2086
|
|
docker buildx imagetools create $tags \
|
|
$(printf 'quay.io/go-skynet/ci-cache@sha256:%s ' *)
|
|
fi
|
|
|
|
- name: Create manifest list and push (dockerhub)
|
|
if: github.event_name != 'pull_request'
|
|
working-directory: /tmp/digests
|
|
run: |
|
|
set -euo pipefail
|
|
tags=$(jq -cr '.tags | map(select(startswith("localai/"))) | map("-t " + .) | join(" ")' <<< "$DOCKER_METADATA_OUTPUT_JSON")
|
|
if [ -z "$tags" ]; then
|
|
echo "No dockerhub tags from docker/metadata-action; skipping dockerhub merge"
|
|
else
|
|
# shellcheck disable=SC2086
|
|
docker buildx imagetools create $tags \
|
|
$(printf 'localai/localai@sha256:%s ' *)
|
|
fi
|
|
|
|
- name: Inspect manifest
|
|
run: |
|
|
set -euo pipefail
|
|
first_tag=$(jq -cr '.tags[0]' <<< "$DOCKER_METADATA_OUTPUT_JSON")
|
|
if [ -n "$first_tag" ] && [ "$first_tag" != "null" ]; then
|
|
docker buildx imagetools inspect "$first_tag"
|
|
fi
|
|
|
|
# See .github/scripts/cleanup-keepalive-tags.sh for the best-effort
|
|
# semantics — fails soft when the registry credential isn't OAuth-scoped.
|
|
- name: Cleanup keepalive tags in ci-cache
|
|
if: github.event_name != 'pull_request' && success()
|
|
env:
|
|
TAG_SUFFIX: ${{ inputs.tag-suffix == '' && '-core' || inputs.tag-suffix }}
|
|
QUAY_TOKEN: ${{ secrets.quayPassword }}
|
|
run: .github/scripts/cleanup-keepalive-tags.sh
|
|
|
|
- name: Job summary
|
|
run: |
|
|
set -euo pipefail
|
|
echo "Merged manifest tags:" >> "$GITHUB_STEP_SUMMARY"
|
|
jq -r '.tags[]' <<< "$DOCKER_METADATA_OUTPUT_JSON" | sed 's/^/- /' >> "$GITHUB_STEP_SUMMARY"
|
|
echo >> "$GITHUB_STEP_SUMMARY"
|
|
echo "Per-arch digests:" >> "$GITHUB_STEP_SUMMARY"
|
|
ls -1 /tmp/digests | sed 's/^/- sha256:/' >> "$GITHUB_STEP_SUMMARY"
|