mirror of
https://github.com/mudler/LocalAI.git
synced 2026-10-10 15:52:29 -04:00
* fix(schema): preserve SystemOne image inputs Assisted-by: OpenAI * test(schema): follow Ginkgo conventions for decision inputs Assisted-by: OpenAI * feat(llama-cpp): dispatch native decisions through Score Upgrade the stock dependency and reconcile Score/TTS patches. Reuse native decision parsing, tasks, formatting and response-reader cleanup; preserve ordinary scoring admission and guard older dependencies. Assisted-by: OpenAI * refactor(systemone): share request and model validation Assisted-by: OpenAI:gpt-5 * fix(systemone): preserve HTTP wire-byte validation limit Keep structural validation separate from the serialized internal request bound so HTML escaping cannot reject valid HTTP payloads. Assisted-by: OpenAI:gpt-5 * feat(systemone): bound images and account native decisions Preserve public wire limits independently from router serialization. Reject unsupported NER images, map native request/capability errors, and stamp explicit usage once. Advertise decisions for stock llama-cpp. Assisted-by: OpenAI * fix(systemone): record usage on registered native route Exercise real registration and billing with a mock native backend. Reject empty native responses, malformed image URLs, trailing JSON, and wire overflow including whitespace. Assisted-by: OpenAI * feat(router): add lazy native decision transport Bind named models through internal ModelSystemOne calls with shared validation and bounded abandoned operations. Remove request and echoed-error contents from decision traces. Assisted-by: OpenAI:gpt-5 * feat(router): classify overlapping policies with native decisions Ask independent noul questions, validate probabilities and preserve first-superset routing. Wire the central factory with config-sensitive invalidation and cancellation-safe resolution. Document native framing and bounded operation limits. Assisted-by: OpenAI:gpt-5 * feat(gallery): add pinned Julia-1 native decision model Add a separate text-only llama-cpp Q8 entry with pinned Apache-2.0 source provenance and checksum. Installed using the gallery installer and exercised choice, score and noul on CPU. Assisted-by: OpenAI * test(router): verify native decisions through central factory Add an opt-in real-model Ginkgo integration covering the native Go loader and C++ transport, token usage, independent overlapping labels, and candidate selection. Document owned-server execution and the intentionally non-quality threshold. Assisted-by: Codex:gpt-5 * fix(llama-cpp): align upstream pin and preserve decision signatures Advance to bed0a856 without losing the automated upstream bump. Detect full-request fill_task support at compile time and forward every question for Nimble framing while retaining the earlier native signature. Preserve reconciled SCORE/TTS patches; add standalone compatibility coverage. Assisted-by: Codex:gpt-5 * feat(gallery): add native decision family defaults Pin Laya, Kev-4B, lev, OpenJev and Nimble artifacts. Verify Laya/Kev/lev gallery installs and CPU contracts on both native pins; clearly mark OpenJev/Nimble runtime validation pending and their noncommercial licenses. Assisted-by: OpenAI * docs(decisions): clarify integrated Nimble prerequisite Record the exact combined backend pin while retaining pending OpenJev and Nimble installation/runtime validation status. Assisted-by: Codex:gpt-5 * fix(gallery): indent native decision model sequences Match repository yamllint indentation for Laya, Kev, lev and OpenJev list fields. Parsed gallery data is unchanged; reproduce CI gallery lint failure before the whitespace-only fix and pass the same command afterward. Assisted-by: Codex:gpt-5 * docs(decisions): record OpenJev and Nimble CPU validation Record gallery installation, checksum/metadata verification and multiquestion native smoke results on bed0a856. Retain noncommercial and text-only limitations without accuracy or deterministic-output claims. Assisted-by: OpenAI * fix(ui): expose native Decisions router classifiers Select classifier models using metadata-driven capability routing, retain tuned thresholds, and validate native decision selections before saving. Cover both native backends and create/save/reopen in the real React editor. Assisted-by: Codex:gpt-5 * fix(router): exclude aliases from native decision discovery Check the originally named config before advertising native Decisions eligibility. Retain target capability inheritance for ordinary generation aliases. Exercise the actual capabilities endpoint with native models on both backends, aliases, and disabled models. Assisted-by: Codex:gpt-5 * feat(systemone): share bounded multimodal input validation Preserve text wire limits while admitting bounded PNG/JPEG decision input. Share collection and header validation across internal and public callers and keep the native runner response budget independent. Assisted-by: OpenAI:API-assistant * fix(systemone): bound admission lifetimes and validate complete images Retain shared admission leases through actual work completion, including abandoned internal operations. Decode bounded image pixels, cap public native responses before usage stamping, and preserve oversized malformed text status precedence. Assisted-by: OpenAI:API-assistant * fix(router): classify images before media fetching Preserve ordered structured probes for native decisions. Defer OpenAI media preparation until routing selects the served model, so rejected decision URLs cannot trigger downloads before shared validation. Guard direct image collection with context-aware shared admission. Keep text classifiers and embedding caches from discarding image input. Retain fail-closed classifier configuration and runtime fallback policy. Add middleware, typed-content, admission, cancellation and cache tests. Assisted-by: OpenAI:API-assistant * fix(router): bound extraction before serialization Check probe budgets before copying text or marshaling message state. Count JSON escaping so oversized internal inputs fail before allocation. Preserve typed Anthropic blocks through selected-model conversion and fallback. Keep retry coverage in Ginkgo without global test registration. Assisted-by: OpenAI * fix(router): bound supported probe serialization Arbitrary structs can bypass the probe budget through pointer marshalers, string tags, and promoted fields. Accept concrete chat schema types and plain JSON values instead of emulating arbitrary struct serialization. Budget escaped direct prompts before marshaling so raw length cannot hide serialized expansion. Preserve runtime fallback and reject oversized input before invoking the decision runner. Add Ginkgo allocation, boundary, and marshaler invocation regressions. Six-package tests, three-package race tests, and full-T2 delta lint pass. Assisted-by: OpenAI:GPT-5 golangci-lint * feat(decisions): enable bounded OpenJev images Validate native decision images before permissive media parsing and pixel allocation. Require both decision image support and a vision projector; missing or audio-only projectors cannot silently become text decisions. Pin the OpenJev Q8 projector and document its license and disk footprint. Add native safety tests, canonical limit parity, gallery and load-option checks, and a reproducible CPU direct-RPC contrasting-image smoke. Assisted-by: OpenAI:GPT-5 * fix(decisions): reject incomplete image streams stb accepts corrupt PNG Adler checksums and truncated JPEG scans. Use bounded zlib validation and strict libjpeg decoding before parsing. Keep dimension and aggregate pixel checks ahead of decoder allocations. Wire decoder dependencies into native builds and runtime packaging. Add regressions for appended EOI and embedded marker bypasses. Assisted-by: OpenAI:GPT-5 * fix(ci): gate native decision image validation Run the decoder security tests outside the stdlib-only native suite. Fetch vendor headers at the backend pin and provision decoder dependencies. Gate Go limit parity and production CMake wiring without model downloads. Assisted-by: OpenAI:GPT-5 * test(decisions): cover multimodal public API paths Exercise shared image contracts through the registered HTTP routes and external mock backend. Add opt-in cached gallery installation and real OpenJev image decisions through SystemOne and both routing APIs. Assisted-by: Codex:gpt-5 * test(decisions): assert isolation and cache bypass Observe external RPC calls and compare complete classifier history. Winner-only and cache-miss checks could hide dropped history or cache use. Give real inference its own application and model directory so shared backend mappings and loaded processes cannot affect mixed suite order. Assisted-by: OpenAI:ChatGPT * test(decisions): isolate fixture globals Disable optional global services in the isolated HTTP fixture and register cleanup before setup assertions. Verify meter provider identity survives fixture creation and destruction. Snapshot observed usage before assertions so failures cannot retain the mutex. Require a successful usage stamp before checking error responses. Assisted-by: Codex:gpt-5 golangci-lint * fix(application): honor optional telemetry controls Skip failover gauge registration when metrics are disabled. Register against the application meter rather than looking up the global provider. Allow embedders to retain the bounded routing log without billing stats. Keep the existing default when stats are disabled. The isolated HTTP fixture uses this option without losing its native router assertions. Assisted-by: Codex:gpt-5 golangci-lint --------- Co-authored-by: Ettore Di Giacinto <mudler@localai.io>
354 lines
15 KiB
YAML
354 lines
15 KiB
YAML
---
|
|
name: 'build darwin python backend container images (reusable)'
|
|
|
|
on:
|
|
workflow_call:
|
|
inputs:
|
|
backend:
|
|
description: 'Backend to build'
|
|
required: true
|
|
type: string
|
|
build-type:
|
|
description: 'Build type (e.g., mps)'
|
|
default: ''
|
|
type: string
|
|
use-pip:
|
|
description: 'Use pip to install dependencies'
|
|
default: false
|
|
type: boolean
|
|
lang:
|
|
description: 'Programming language (e.g. go)'
|
|
default: 'python'
|
|
type: string
|
|
go-version:
|
|
description: 'Go version to use'
|
|
# Go 1.27 stamps pure-Go hosts with SDK metadata that supports modern Metal APIs.
|
|
default: '1.27.x'
|
|
type: string
|
|
tag-suffix:
|
|
description: 'Tag suffix for the built image'
|
|
required: true
|
|
type: string
|
|
runs-on:
|
|
description: 'Runner to use'
|
|
default: 'macOS-14'
|
|
type: string
|
|
secrets:
|
|
dockerUsername:
|
|
required: false
|
|
dockerPassword:
|
|
required: false
|
|
quayUsername:
|
|
required: true
|
|
quayPassword:
|
|
required: true
|
|
|
|
jobs:
|
|
darwin-backend-build:
|
|
runs-on: ${{ inputs.runs-on }}
|
|
strategy:
|
|
matrix:
|
|
go-version: ['${{ inputs.go-version }}']
|
|
env:
|
|
# Keep the brew Cellar stable across cache restores. Without these,
|
|
# `brew install` would auto-update brew itself and re-link formulas,
|
|
# mutating the very paths the cache just restored.
|
|
HOMEBREW_NO_AUTO_UPDATE: '1'
|
|
HOMEBREW_NO_INSTALL_CLEANUP: '1'
|
|
HOMEBREW_NO_ANALYTICS: '1'
|
|
steps:
|
|
- name: Clone
|
|
uses: actions/checkout@v7
|
|
with:
|
|
submodules: true
|
|
|
|
- name: Setup Go ${{ matrix.go-version }}
|
|
uses: actions/setup-go@v5
|
|
with:
|
|
go-version: ${{ matrix.go-version }}
|
|
# Caches ~/go/pkg/mod and ~/Library/Caches/go-build keyed on go.sum.
|
|
# Shared across every darwin matrix entry — first job in a run warms
|
|
# it, the rest hit warm.
|
|
cache: true
|
|
|
|
# You can test your matrix by printing the current Go version
|
|
- name: Display Go version
|
|
run: go version
|
|
|
|
# ---- Homebrew cache ----
|
|
# macOS runners have no Docker daemon, so the BuildKit registry cache used
|
|
# for Linux backend images (see .agents/ci-caching.md) doesn't apply here.
|
|
# We cache the brew downloads + Cellar entries for the formulas we install
|
|
# below. Read on every run, write only on master/tag pushes — same policy
|
|
# as the Linux registry cache.
|
|
- name: Restore Homebrew cache
|
|
id: brew-cache
|
|
uses: actions/cache/restore@v6
|
|
with:
|
|
path: |
|
|
~/Library/Caches/Homebrew/downloads
|
|
/opt/homebrew/Cellar/protobuf
|
|
/opt/homebrew/Cellar/grpc
|
|
/opt/homebrew/Cellar/protoc-gen-go
|
|
/opt/homebrew/Cellar/protoc-gen-go-grpc
|
|
/opt/homebrew/Cellar/libomp
|
|
/opt/homebrew/Cellar/llvm
|
|
/opt/homebrew/Cellar/ccache
|
|
/opt/homebrew/Cellar/blake3
|
|
/opt/homebrew/Cellar/fmt
|
|
/opt/homebrew/Cellar/hiredis
|
|
/opt/homebrew/Cellar/xxhash
|
|
/opt/homebrew/Cellar/zstd
|
|
/opt/homebrew/Cellar/nlohmann-json
|
|
/opt/homebrew/Cellar/opus
|
|
key: brew-${{ runner.os }}-${{ runner.arch }}-v1-${{ hashFiles('.github/workflows/backend_build_darwin.yml') }}
|
|
|
|
- name: Dependencies
|
|
run: |
|
|
# ccache is always installed (used by the llama-cpp variant build) so
|
|
# the brew cache content stays stable across every backend in the
|
|
# matrix — they all share one cache key.
|
|
# blake3, fmt, hiredis, xxhash, zstd are ccache's runtime dylib deps.
|
|
# Without explicitly installing them, a brew cache-hit run restores
|
|
# ccache's Cellar dir but skips installing those transitive deps,
|
|
# and ccache fails at runtime with `dyld: Library not loaded`.
|
|
# nlohmann-json is header-only and required by the ds4 backend
|
|
# (dsml_renderer.cpp includes <nlohmann/json.hpp>); on Linux it comes
|
|
# from the apt-installed nlohmann-json3-dev in the build image.
|
|
# opus + pkg-config are required by the opus go backend: its
|
|
# Makefile/package.sh call `pkg-config --cflags/--libs opus` to build
|
|
# libopusshim.dylib and to locate libopus.dylib for bundling. brew's
|
|
# pkg-config defaults its search path to the Homebrew prefix so the
|
|
# opus.pc is found.
|
|
brew install protobuf grpc make protoc-gen-go protoc-gen-go-grpc libomp llvm ccache blake3 fmt hiredis xxhash zstd nlohmann-json opus pkg-config jpeg-turbo zlib
|
|
# Force-reinstall ccache so brew re-validates its full runtime-dep
|
|
# closure on every run. This is the durable fix: when the upstream
|
|
# ccache formula gains a new transitive dep (as it has multiple times
|
|
# already), we don't have to chase missing dylibs one at a time.
|
|
# The downloads cache makes the reinstall fast (~5s on a hit).
|
|
brew reinstall ccache
|
|
# Same pattern for grpc: its CMake config (used by the llama-cpp
|
|
# `grpc-server` target) does find_package(absl). The cache restores
|
|
# /opt/homebrew/Cellar/grpc so brew above no-ops the install, but
|
|
# abseil isn't in our Cellar cache list and never gets installed
|
|
# alongside, leaving grpc's CMake unable to resolve it. Reinstalling
|
|
# grpc re-validates and pulls abseil in, mirroring the ccache fix.
|
|
brew reinstall grpc
|
|
# The brew cache restores the Cellar dirs but NOT the bin symlinks
|
|
# at /opt/homebrew/bin/*. brew install above sees the Cellar present
|
|
# and decides "already installed" without re-linking, so on a cache-
|
|
# hit run the formulas aren't on PATH. Force-link them; --overwrite
|
|
# tolerates pre-existing symlinks from earlier installs.
|
|
brew link --overwrite protobuf grpc make protoc-gen-go protoc-gen-go-grpc libomp llvm ccache blake3 fmt hiredis xxhash zstd nlohmann-json opus pkg-config jpeg-turbo zlib 2>/dev/null || true
|
|
|
|
- name: Save Homebrew cache
|
|
if: github.event_name != 'pull_request' && steps.brew-cache.outputs.cache-hit != 'true'
|
|
uses: actions/cache/save@v6
|
|
with:
|
|
path: |
|
|
~/Library/Caches/Homebrew/downloads
|
|
/opt/homebrew/Cellar/protobuf
|
|
/opt/homebrew/Cellar/grpc
|
|
/opt/homebrew/Cellar/protoc-gen-go
|
|
/opt/homebrew/Cellar/protoc-gen-go-grpc
|
|
/opt/homebrew/Cellar/libomp
|
|
/opt/homebrew/Cellar/llvm
|
|
/opt/homebrew/Cellar/ccache
|
|
/opt/homebrew/Cellar/blake3
|
|
/opt/homebrew/Cellar/fmt
|
|
/opt/homebrew/Cellar/hiredis
|
|
/opt/homebrew/Cellar/xxhash
|
|
/opt/homebrew/Cellar/zstd
|
|
/opt/homebrew/Cellar/nlohmann-json
|
|
/opt/homebrew/Cellar/opus
|
|
key: brew-${{ runner.os }}-${{ runner.arch }}-v1-${{ hashFiles('.github/workflows/backend_build_darwin.yml') }}
|
|
|
|
# ---- ccache for llama.cpp CMake builds ----
|
|
# Three CMake variants (fallback, grpc, rpc-server) compile the same
|
|
# llama.cpp source tree with overlapping flags — ccache dedupes object
|
|
# files across them. Key on the pinned LLAMA_VERSION so a pin bump
|
|
# invalidates cleanly; restore-keys fall back to the latest entry for the
|
|
# same pin so unchanged TUs stay warm even when the cache is fresh.
|
|
- name: Compute llama.cpp version
|
|
if: inputs.backend == 'llama-cpp'
|
|
id: llama-version
|
|
run: |
|
|
version=$(grep '^LLAMA_VERSION' backend/cpp/llama-cpp/Makefile | head -1 | cut -d= -f2 | cut -d'?' -f1 | tr -d ' ')
|
|
echo "version=${version}" >> "$GITHUB_OUTPUT"
|
|
|
|
- name: Restore ccache
|
|
if: inputs.backend == 'llama-cpp'
|
|
id: ccache-cache
|
|
uses: actions/cache/restore@v6
|
|
with:
|
|
path: ~/Library/Caches/ccache
|
|
key: ccache-llama-${{ runner.arch }}-${{ steps.llama-version.outputs.version }}-${{ github.run_id }}
|
|
restore-keys: |
|
|
ccache-llama-${{ runner.arch }}-${{ steps.llama-version.outputs.version }}-
|
|
|
|
- name: Configure ccache
|
|
if: inputs.backend == 'llama-cpp'
|
|
run: |
|
|
mkdir -p "$HOME/Library/Caches/ccache"
|
|
ccache -M 2G
|
|
ccache -z
|
|
# llama-cpp-darwin.sh reads CMAKE_ARGS / CCACHE_DIR from env.
|
|
{
|
|
echo "CMAKE_ARGS=${CMAKE_ARGS:-} -DCMAKE_C_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_COMPILER_LAUNCHER=ccache"
|
|
echo "CCACHE_DIR=$HOME/Library/Caches/ccache"
|
|
} >> "$GITHUB_ENV"
|
|
|
|
# ---- Python wheel cache (uv + pip) ----
|
|
# Mirrors the Linux DEPS_REFRESH cadence (see .agents/ci-caching.md): the
|
|
# ISO-week segment of the cache key forces at most one cold rebuild per
|
|
# backend per week, automatically picking up newer wheels for unpinned
|
|
# deps (torch, mlx, diffusers, …). Restore-keys fall back to the most
|
|
# recent build of the same backend so off-week PRs still hit warm.
|
|
- name: Compute weekly cache bucket
|
|
if: inputs.lang == 'python'
|
|
id: weekly
|
|
run: echo "bucket=$(date -u +%Y-W%V)" >> "$GITHUB_OUTPUT"
|
|
|
|
- name: Restore Python wheel cache
|
|
if: inputs.lang == 'python'
|
|
id: pyenv-cache
|
|
uses: actions/cache/restore@v6
|
|
with:
|
|
path: |
|
|
~/Library/Caches/pip
|
|
~/Library/Caches/uv
|
|
key: pyenv-darwin-${{ inputs.backend }}-${{ steps.weekly.outputs.bucket }}-${{ hashFiles(format('backend/python/{0}/requirements*.txt', inputs.backend)) }}
|
|
restore-keys: |
|
|
pyenv-darwin-${{ inputs.backend }}-
|
|
|
|
# llama-cpp on Darwin uses a bespoke build script (scripts/build/llama-cpp-darwin.sh)
|
|
# that compiles three CMake variants from backend/cpp/llama-cpp and bundles dylibs
|
|
# via otool — it doesn't fit the build-darwin-go-backend / build-darwin-python-backend
|
|
# mold. Drive it via its dedicated `backends/llama-cpp-darwin` make target instead.
|
|
- name: Build ${{ inputs.backend }}-darwin (llama-cpp)
|
|
if: inputs.backend == 'llama-cpp'
|
|
run: |
|
|
make protogen-go
|
|
make backends/llama-cpp-darwin
|
|
|
|
- name: Build ds4 backend (Darwin Metal)
|
|
if: inputs.backend == 'ds4'
|
|
run: |
|
|
make backends/ds4-darwin
|
|
|
|
# privacy-filter is a C++/ggml backend like ds4 - a single grpc-server with
|
|
# otool dylib bundling - so it gets its own bespoke darwin script rather than
|
|
# the generic build-darwin-go-backend path.
|
|
- name: Build privacy-filter backend (Darwin Metal)
|
|
if: inputs.backend == 'privacy-filter'
|
|
run: |
|
|
make protogen-go
|
|
make backends/privacy-filter-darwin
|
|
|
|
# audio-cpp is a C++/ggml backend like ds4 and privacy-filter - a single
|
|
# grpc-server with otool dylib bundling, plus bundled VAD assets - so it
|
|
# gets its own bespoke darwin script rather than the generic
|
|
# build-darwin-go-backend path, which would look for a backend/go/audio-cpp
|
|
# that does not exist. Keep this set in sync with DARWIN_BESPOKE_BUILDERS
|
|
# in scripts/lib/backend-filter.mjs.
|
|
- name: Build audio-cpp backend (Darwin Metal)
|
|
if: inputs.backend == 'audio-cpp'
|
|
run: |
|
|
make backends/audio-cpp-darwin
|
|
|
|
- name: Build ${{ inputs.backend }}-darwin
|
|
if: inputs.backend != 'llama-cpp' && inputs.backend != 'ds4' && inputs.backend != 'privacy-filter' && inputs.backend != 'audio-cpp'
|
|
run: |
|
|
make protogen-go
|
|
BACKEND=${{ inputs.backend }} BUILD_TYPE=${{ inputs.build-type }} USE_PIP=${{ inputs.use-pip }} make build-darwin-${{ inputs.lang }}-backend
|
|
|
|
- name: ccache stats
|
|
if: inputs.backend == 'llama-cpp'
|
|
run: ccache -s
|
|
|
|
- name: Save ccache
|
|
if: inputs.backend == 'llama-cpp' && github.event_name != 'pull_request'
|
|
uses: actions/cache/save@v6
|
|
with:
|
|
path: ~/Library/Caches/ccache
|
|
key: ccache-llama-${{ runner.arch }}-${{ steps.llama-version.outputs.version }}-${{ github.run_id }}
|
|
|
|
- name: Save Python wheel cache
|
|
if: inputs.lang == 'python' && github.event_name != 'pull_request' && steps.pyenv-cache.outputs.cache-hit != 'true'
|
|
uses: actions/cache/save@v6
|
|
with:
|
|
path: |
|
|
~/Library/Caches/pip
|
|
~/Library/Caches/uv
|
|
key: pyenv-darwin-${{ inputs.backend }}-${{ steps.weekly.outputs.bucket }}-${{ hashFiles(format('backend/python/{0}/requirements*.txt', inputs.backend)) }}
|
|
|
|
- name: Upload ${{ inputs.backend }}.tar
|
|
uses: actions/upload-artifact@v7
|
|
with:
|
|
name: ${{ inputs.backend }}-tar
|
|
path: backend-images/${{ inputs.backend }}.tar
|
|
|
|
darwin-backend-publish:
|
|
needs: darwin-backend-build
|
|
if: github.event_name != 'pull_request'
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- name: Download ${{ inputs.backend }}.tar
|
|
uses: actions/download-artifact@v8
|
|
with:
|
|
name: ${{ inputs.backend }}-tar
|
|
path: .
|
|
|
|
- name: Install crane
|
|
run: |
|
|
curl -L https://github.com/google/go-containerregistry/releases/latest/download/go-containerregistry_Linux_x86_64.tar.gz | tar -xz
|
|
sudo mv crane /usr/local/bin/
|
|
|
|
- name: Log in to DockerHub
|
|
run: |
|
|
echo "${{ secrets.dockerPassword }}" | crane auth login docker.io -u "${{ secrets.dockerUsername }}" --password-stdin
|
|
|
|
- name: Log in to quay.io
|
|
run: |
|
|
echo "${{ secrets.quayPassword }}" | crane auth login quay.io -u "${{ secrets.quayUsername }}" --password-stdin
|
|
|
|
- name: Docker meta
|
|
id: meta
|
|
uses: docker/metadata-action@v6
|
|
with:
|
|
images: |
|
|
localai/localai-backends
|
|
tags: |
|
|
type=ref,event=branch
|
|
type=semver,pattern={{raw}}
|
|
type=sha
|
|
flavor: |
|
|
latest=auto
|
|
suffix=${{ inputs.tag-suffix }},onlatest=true
|
|
|
|
- name: Docker meta
|
|
id: quaymeta
|
|
uses: docker/metadata-action@v6
|
|
with:
|
|
images: |
|
|
quay.io/go-skynet/local-ai-backends
|
|
tags: |
|
|
type=ref,event=branch
|
|
type=semver,pattern={{raw}}
|
|
type=sha
|
|
flavor: |
|
|
latest=auto
|
|
suffix=${{ inputs.tag-suffix }},onlatest=true
|
|
|
|
- name: Push Docker image (DockerHub)
|
|
run: |
|
|
for tag in $(echo "${{ steps.meta.outputs.tags }}" | tr ',' '\n'); do
|
|
crane push ${{ inputs.backend }}.tar $tag
|
|
done
|
|
|
|
- name: Push Docker image (Quay)
|
|
run: |
|
|
for tag in $(echo "${{ steps.quaymeta.outputs.tags }}" | tr ',' '\n'); do
|
|
crane push ${{ inputs.backend }}.tar $tag
|
|
done
|