Felipe97/llama-cpp-compiled
01.2k
1# This workflow uses actions that are not certified by GitHub.2# They are provided by a third-party and are governed by3# separate terms of service, privacy policy, and support4# documentation.5 6# GitHub recommends pinning actions to a commit SHA.7# To get a newer version, you will need to update the SHA.8# You can also reference a tag or branch, but the action may change without warning.9 10name: Publish Docker image11 12on:13 workflow_dispatch: # allows manual triggering14 inputs:15 skip_s390x:16 description: "Skip the s390x build target (useful for fast test runs that do not need the IBM Z runner)"17 type: boolean18 default: false19 schedule:20 # Rebuild daily rather than on every push because it is expensive21 - cron: '12 4 * * *'22 23concurrency:24 group: ${{ github.workflow }}-${{ github.head_ref && github.ref || github.run_id }}25 cancel-in-progress: true26 27# Fine-grant permission28# https://docs.github.com/en/actions/security-for-github-actions/security-guides/automatic-token-authentication#modifying-the-permissions-for-the-github_token29permissions:30 packages: write31 32jobs:33 create_tag:34 name: Create and push git tag35 runs-on: ubuntu-slim36 permissions:37 contents: write38 outputs:39 source_tag: ${{ steps.srctag.outputs.name }}40 41 steps:42 - name: Clone43 id: checkout44 uses: actions/checkout@v645 with:46 fetch-depth: 047 ssh-key: ${{ secrets.DEPLOY_KEY_RELEASE }}48 49 - name: Determine source tag name50 id: srctag51 uses: ./.github/actions/get-tag-name52 env:53 BRANCH_NAME: ${{ github.head_ref || github.ref_name }}54 55 - name: Create and push git tag56 env:57 GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}58 run: |59 git tag ${{ steps.srctag.outputs.name }} || exit 060 git push origin ${{ steps.srctag.outputs.name }} || exit 061 62 build_ui:63 name: Build UI64 needs: create_tag65 uses: ./.github/workflows/ui-build.yml66 with:67 ui_version: ${{ needs.create_tag.outputs.source_tag }}68 69 prepare_matrices:70 name: Prepare Docker matrices71 runs-on: ubuntu-24.0472 outputs:73 build_matrix: ${{ steps.matrices.outputs.build_matrix }}74 merge_matrix: ${{ steps.matrices.outputs.merge_matrix }}75 76 steps:77 - name: Generate build and merge matrices78 id: matrices79 shell: bash80 env:81 SKIP_S390X: ${{ inputs.skip_s390x || 'false' }}82 run: |83 set -euo pipefail84 85 # Keep all build targets in one place and derive merge targets from it.86 cat > build-matrix.json <<'JSON'87 [88 { "tag": "cpu", "dockerfile": ".devops/cpu.Dockerfile", "platforms": "linux/amd64", "full": true, "light": true, "server": true, "free_disk_space": false, "runs_on": "ubuntu-24.04" },89 { "tag": "cpu", "dockerfile": ".devops/cpu.Dockerfile", "platforms": "linux/arm64", "full": true, "light": true, "server": true, "free_disk_space": false, "runs_on": "ubuntu-24.04-arm" },90 { "tag": "cpu", "dockerfile": ".devops/s390x.Dockerfile", "platforms": "linux/s390x", "full": true, "light": true, "server": true, "free_disk_space": false, "runs_on": "ubuntu-24.04-s390x", "prebuilt_ui": true },91 { "tag": "cuda cuda12", "dockerfile": ".devops/cuda.Dockerfile", "cuda_version": "12.8.1", "platforms": "linux/amd64", "full": true, "light": true, "server": true, "free_disk_space": true, "runs_on": "ubuntu-24.04" },92 { "tag": "cuda cuda12", "dockerfile": ".devops/cuda.Dockerfile", "cuda_version": "12.8.1", "platforms": "linux/arm64", "full": true, "light": true, "server": true, "free_disk_space": true, "runs_on": "ubuntu-24.04-arm" },93 { "tag": "cuda13", "dockerfile": ".devops/cuda.Dockerfile", "cuda_version": "13.3.0", "platforms": "linux/amd64", "full": true, "light": true, "server": true, "free_disk_space": true, "runs_on": "ubuntu-24.04" },94 { "tag": "cuda13", "dockerfile": ".devops/cuda.Dockerfile", "cuda_version": "13.3.0", "platforms": "linux/arm64", "full": true, "light": true, "server": true, "free_disk_space": true, "runs_on": "ubuntu-24.04-arm" },95 { "tag": "musa", "dockerfile": ".devops/musa.Dockerfile", "platforms": "linux/amd64", "full": true, "light": true, "server": true, "free_disk_space": true, "runs_on": "ubuntu-24.04" },96 { "tag": "intel", "dockerfile": ".devops/intel.Dockerfile", "platforms": "linux/amd64", "full": true, "light": true, "server": true, "free_disk_space": true, "runs_on": "ubuntu-24.04" },97 { "tag": "vulkan", "dockerfile": ".devops/vulkan.Dockerfile", "platforms": "linux/amd64", "full": true, "light": true, "server": true, "free_disk_space": false, "runs_on": "ubuntu-24.04" },98 { "tag": "vulkan", "dockerfile": ".devops/vulkan.Dockerfile", "platforms": "linux/arm64", "full": true, "light": true, "server": true, "free_disk_space": false, "runs_on": "ubuntu-24.04-arm" },99 { "tag": "rocm", "dockerfile": ".devops/rocm.Dockerfile", "platforms": "linux/amd64", "full": true, "light": true, "server": true, "free_disk_space": true, "runs_on": "ubuntu-24.04" },100 { "tag": "openvino", "dockerfile": ".devops/openvino.Dockerfile", "platforms": "linux/amd64", "full": true, "light": true, "server": true, "free_disk_space": false, "runs_on": "ubuntu-24.04" }101 ]102 JSON103 104 if [ "${SKIP_S390X}" = "true" ]; then105 jq 'map(select(.platforms != "linux/s390x"))' build-matrix.json > build-matrix.json.tmp106 mv build-matrix.json.tmp build-matrix.json107 fi108 109 BUILD_MATRIX="$(jq -c . build-matrix.json)"110 MERGE_MATRIX="$(jq -c '111 reduce .[] as $entry ({}; .[$entry.tag] |= (112 . // {113 tag: $entry.tag,114 arches: [],115 full: false,116 light: false,117 server: false118 }119 | .full = (.full or ($entry.full // false))120 | .light = (.light or ($entry.light // false))121 | .server = (.server or ($entry.server // false))122 | .arches += [($entry.platforms | sub("^linux/"; ""))]123 ))124 # Backward compatibility: s390x tags are aliases of cpu for the linux/s390x platform.125 | if (has("cpu") and (((.cpu.arches // []) | index("s390x")) != null)) then126 . + {127 s390x: {128 tag: "s390x",129 arches: ["s390x"],130 full: .cpu.full,131 light: .cpu.light,132 server: .cpu.server133 }134 }135 else136 .137 end138 | [.[] | .arches = (.arches | unique | sort | join(" "))]139 ' build-matrix.json)"140 141 echo "build_matrix=$BUILD_MATRIX" >> "$GITHUB_OUTPUT"142 echo "merge_matrix=$MERGE_MATRIX" >> "$GITHUB_OUTPUT"143 144 push_to_registry:145 name: Push Docker image to Docker Registry146 needs: [prepare_matrices, create_tag, build_ui]147 148 runs-on: ${{ matrix.config.runs_on }}149 strategy:150 fail-fast: false151 matrix:152 config: ${{ fromJSON(needs.prepare_matrices.outputs.build_matrix) }}153 steps:154 - name: Check out the repo155 id: checkout156 uses: actions/checkout@v6157 with:158 fetch-depth: 0159 ref: ${{ needs.create_tag.outputs.source_tag }}160 161 - name: Download prebuilt UI162 if: ${{ matrix.config.prebuilt_ui == true }}163 uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8164 with:165 name: llama-ui.zip166 path: tools/ui/dist167 168 - name: Set up QEMU169 if: ${{ contains(matrix.config.platforms, 'linux/amd64') }}170 uses: docker/setup-qemu-action@ce360397dd3f832beb865e1373c09c0e9f86d70a # v4171 with:172 image: tonistiigi/binfmt:qemu-v10.2.1173 174 - name: Set up Docker Buildx175 uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd # v4176 177 - name: Log in to Docker Registry178 uses: docker/login-action@b45d80f862d83dbcd57f89517bcf500b2ab88fb2 # v4179 with:180 registry: ghcr.io181 username: ${{ github.repository_owner }}182 password: ${{ secrets.GITHUB_TOKEN }}183 184 - name: Determine image metadata185 id: meta186 shell: bash187 run: |188 set -euo pipefail189 190 REPO_OWNER="${GITHUB_REPOSITORY_OWNER@L}" # to lower case191 REPO_NAME="${{ github.event.repository.name }}"192 IMAGE_REPO="ghcr.io/${REPO_OWNER}/${REPO_NAME}"193 PREFIX="${IMAGE_REPO}:"194 PLATFORM="${{ matrix.config.platforms }}"195 ARCH_SUFFIX="${PLATFORM#linux/}"196 197 # list all tags possible198 tags="${{ matrix.config.tag }}"199 for tag in $tags; do200 if [[ "$tag" == "cpu" ]]; then201 TYPE=""202 else203 TYPE="-$tag"204 fi205 CACHETAG="${PREFIX}buildcache${TYPE}-${ARCH_SUFFIX}"206 done207 208 SAFE_TAGS="$(echo "$tags" | tr ' ' '_')"209 210 echo "image_repo=$IMAGE_REPO" >> $GITHUB_OUTPUT211 echo "arch_suffix=$ARCH_SUFFIX" >> $GITHUB_OUTPUT212 echo "cache_output_tag=$CACHETAG" >> $GITHUB_OUTPUT213 echo "digest_artifact_suffix=${SAFE_TAGS}-${ARCH_SUFFIX}" >> $GITHUB_OUTPUT214 echo "cache_output_tag=$CACHETAG" # print out for debugging215 env:216 GITHUB_REPOSITORY_OWNER: '${{ github.repository_owner }}'217 218 - name: Get build date219 id: build_date220 run: echo "date=$(date -u +"%Y-%m-%dT%H:%M:%SZ")" >> $GITHUB_OUTPUT221 222 - name: Free Disk Space (Ubuntu)223 if: ${{ matrix.config.free_disk_space == true }}224 uses: ggml-org/free-disk-space@v1.3.1225 with:226 # this might remove tools that are actually needed,227 # if set to "true" but frees about 6 GB228 tool-cache: false229 230 # all of these default to true, but feel free to set to231 # "false" if necessary for your workflow232 android: true233 dotnet: true234 haskell: true235 large-packages: true236 docker-images: true237 swap-storage: true238 239 - name: Build and push Full Docker image by digest240 id: build_full241 if: ${{ (github.event_name == 'push' || github.event_name == 'schedule' || github.event_name == 'workflow_dispatch') && matrix.config.full == true }}242 uses: docker/build-push-action@d08e5c354a6adb9ed34480a06d141179aa583294 # v7243 with:244 context: .245 platforms: ${{ matrix.config.platforms }}246 outputs: type=image,name=${{ steps.meta.outputs.image_repo }},push-by-digest=true,name-canonical=true,push=true,oci-mediatypes=true247 file: ${{ matrix.config.dockerfile }}248 target: full249 provenance: false250 build-args: |251 BUILD_DATE=${{ steps.build_date.outputs.date }}252 APP_VERSION=${{ needs.create_tag.outputs.source_tag }}253 APP_REVISION=${{ steps.checkout.outputs.commit }}254 IMAGE_URL=${{ github.server_url }}/${{ github.repository }}255 IMAGE_SOURCE=${{ github.server_url }}/${{ github.repository }}256 ${{ matrix.config.ubuntu_version && format('UBUNTU_VERSION={0}', matrix.config.ubuntu_version) || '' }}257 ${{ matrix.config.cuda_version && format('CUDA_VERSION={0}', matrix.config.cuda_version) || '' }}258 annotations: |259 manifest:org.opencontainers.image.created=${{ steps.build_date.outputs.date }}260 manifest:org.opencontainers.image.version=${{ needs.create_tag.outputs.source_tag }}261 manifest:org.opencontainers.image.revision=${{ steps.checkout.outputs.commit }}262 manifest:org.opencontainers.image.title=llama.cpp263 manifest:org.opencontainers.image.description=LLM inference in C/C++264 manifest:org.opencontainers.image.url=${{ github.server_url }}/${{ github.repository }}265 manifest:org.opencontainers.image.source=${{ github.server_url }}/${{ github.repository }}266 # using github experimental cache267 #cache-from: type=gha268 #cache-to: type=gha,mode=max269 # return to this if the experimental github cache is having issues270 #cache-to: type=local,dest=/tmp/.buildx-cache271 #cache-from: type=local,src=/tmp/.buildx-cache272 # using registry cache (no storage limit)273 cache-from: type=registry,ref=${{ steps.meta.outputs.cache_output_tag }}274 cache-to: type=registry,ref=${{ steps.meta.outputs.cache_output_tag }},mode=max275 276 - name: Build and push Light Docker image by digest277 id: build_light278 if: ${{ (github.event_name == 'push' || github.event_name == 'schedule' || github.event_name == 'workflow_dispatch') && matrix.config.light == true }}279 uses: docker/build-push-action@d08e5c354a6adb9ed34480a06d141179aa583294 # v7280 with:281 context: .282 platforms: ${{ matrix.config.platforms }}283 outputs: type=image,name=${{ steps.meta.outputs.image_repo }},push-by-digest=true,name-canonical=true,push=true,oci-mediatypes=true284 file: ${{ matrix.config.dockerfile }}285 target: light286 provenance: false287 build-args: |288 BUILD_DATE=${{ steps.build_date.outputs.date }}289 APP_VERSION=${{ needs.create_tag.outputs.source_tag }}290 APP_REVISION=${{ steps.checkout.outputs.commit }}291 IMAGE_URL=${{ github.server_url }}/${{ github.repository }}292 IMAGE_SOURCE=${{ github.server_url }}/${{ github.repository }}293 ${{ matrix.config.ubuntu_version && format('UBUNTU_VERSION={0}', matrix.config.ubuntu_version) || '' }}294 ${{ matrix.config.cuda_version && format('CUDA_VERSION={0}', matrix.config.cuda_version) || '' }}295 annotations: |296 manifest:org.opencontainers.image.created=${{ steps.build_date.outputs.date }}297 manifest:org.opencontainers.image.version=${{ needs.create_tag.outputs.source_tag }}298 manifest:org.opencontainers.image.revision=${{ steps.checkout.outputs.commit }}299 manifest:org.opencontainers.image.title=llama.cpp300 manifest:org.opencontainers.image.description=LLM inference in C/C++301 manifest:org.opencontainers.image.url=${{ github.server_url }}/${{ github.repository }}302 manifest:org.opencontainers.image.source=${{ github.server_url }}/${{ github.repository }}303 # using github experimental cache304 #cache-from: type=gha305 #cache-to: type=gha,mode=max306 # return to this if the experimental github cache is having issues307 #cache-to: type=local,dest=/tmp/.buildx-cache308 #cache-from: type=local,src=/tmp/.buildx-cache309 # using registry cache (no storage limit)310 cache-from: type=registry,ref=${{ steps.meta.outputs.cache_output_tag }}311 cache-to: type=registry,ref=${{ steps.meta.outputs.cache_output_tag }},mode=max312 313 - name: Build and push Server Docker image by digest314 id: build_server315 if: ${{ (github.event_name == 'push' || github.event_name == 'schedule' || github.event_name == 'workflow_dispatch') && matrix.config.server == true }}316 uses: docker/build-push-action@d08e5c354a6adb9ed34480a06d141179aa583294 # v7317 with:318 context: .319 platforms: ${{ matrix.config.platforms }}320 outputs: type=image,name=${{ steps.meta.outputs.image_repo }},push-by-digest=true,name-canonical=true,push=true,oci-mediatypes=true321 file: ${{ matrix.config.dockerfile }}322 target: server323 provenance: false324 build-args: |325 BUILD_DATE=${{ steps.build_date.outputs.date }}326 APP_VERSION=${{ needs.create_tag.outputs.source_tag }}327 APP_REVISION=${{ steps.checkout.outputs.commit }}328 IMAGE_URL=${{ github.server_url }}/${{ github.repository }}329 IMAGE_SOURCE=${{ github.server_url }}/${{ github.repository }}330 ${{ matrix.config.ubuntu_version && format('UBUNTU_VERSION={0}', matrix.config.ubuntu_version) || '' }}331 ${{ matrix.config.cuda_version && format('CUDA_VERSION={0}', matrix.config.cuda_version) || '' }}332 annotations: |333 manifest:org.opencontainers.image.created=${{ steps.build_date.outputs.date }}334 manifest:org.opencontainers.image.version=${{ needs.create_tag.outputs.source_tag }}335 manifest:org.opencontainers.image.revision=${{ steps.checkout.outputs.commit }}336 manifest:org.opencontainers.image.title=llama.cpp337 manifest:org.opencontainers.image.description=LLM inference in C/C++338 manifest:org.opencontainers.image.url=${{ github.server_url }}/${{ github.repository }}339 manifest:org.opencontainers.image.source=${{ github.server_url }}/${{ github.repository }}340 # using github experimental cache341 #cache-from: type=gha342 #cache-to: type=gha,mode=max343 # return to this if the experimental github cache is having issues344 #cache-to: type=local,dest=/tmp/.buildx-cache345 #cache-from: type=local,src=/tmp/.buildx-cache346 # using registry cache (no storage limit)347 cache-from: type=registry,ref=${{ steps.meta.outputs.cache_output_tag }}348 cache-to: type=registry,ref=${{ steps.meta.outputs.cache_output_tag }},mode=max349 350 - name: Export digest metadata351 shell: bash352 run: |353 set -euo pipefail354 355 TAGS="${{ matrix.config.tag }}"356 ARCH_SUFFIX="${{ steps.meta.outputs.arch_suffix }}"357 DIGEST_FILE="/tmp/digests/${{ steps.meta.outputs.digest_artifact_suffix }}.tsv"358 mkdir -p /tmp/digests359 360 add_digest_rows() {361 local image_type="$1"362 local digest="$2"363 364 if [[ -z "$digest" ]]; then365 echo "Missing digest for image_type=${image_type}" >&2366 exit 1367 fi368 369 for tag in $TAGS; do370 printf '%s\t%s\t%s\t%s\n' "$tag" "$ARCH_SUFFIX" "$image_type" "$digest" >> "$DIGEST_FILE"371 done372 }373 374 if [[ "${{ matrix.config.full }}" == "true" ]]; then375 add_digest_rows "full" "${{ steps.build_full.outputs.digest }}"376 fi377 378 if [[ "${{ matrix.config.light }}" == "true" ]]; then379 add_digest_rows "light" "${{ steps.build_light.outputs.digest }}"380 fi381 382 if [[ "${{ matrix.config.server }}" == "true" ]]; then383 add_digest_rows "server" "${{ steps.build_server.outputs.digest }}"384 fi385 386 - name: Upload digest metadata387 uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7388 with:389 name: digests-${{ steps.meta.outputs.digest_artifact_suffix }}390 path: /tmp/digests/${{ steps.meta.outputs.digest_artifact_suffix }}.tsv391 if-no-files-found: error392 393 merge_arch_tags:394 name: Create shared tags from digests395 needs: [prepare_matrices, push_to_registry, create_tag]396 runs-on: ubuntu-24.04397 permissions:398 contents: read399 packages: write400 id-token: write401 attestations: write402 strategy:403 fail-fast: false404 matrix:405 config: ${{ fromJSON(needs.prepare_matrices.outputs.merge_matrix) }}406 407 steps:408 - name: Check out the repo409 id: checkout410 uses: actions/checkout@v6411 with:412 fetch-depth: 0413 414 - name: Get build date415 id: build_date416 run: echo "date=$(date -u +"%Y-%m-%dT%H:%M:%SZ")" >> $GITHUB_OUTPUT417 418 - name: Download digest metadata419 uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8420 with:421 pattern: digests-*422 path: /tmp/digests423 merge-multiple: true424 425 - name: Set up Docker Buildx426 uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd # v4427 428 - name: Log in to Docker Registry429 uses: docker/login-action@b45d80f862d83dbcd57f89517bcf500b2ab88fb2 # v4430 with:431 registry: ghcr.io432 username: ${{ github.repository_owner }}433 password: ${{ secrets.GITHUB_TOKEN }}434 435 - name: Create tags from digests436 id: create_tags437 shell: bash438 run: |439 set -euo pipefail440 441 REPO_OWNER="${GITHUB_REPOSITORY_OWNER@L}" # to lower case442 REPO_NAME="${{ github.event.repository.name }}"443 IMAGE_REPO="ghcr.io/${REPO_OWNER}/${REPO_NAME}"444 PREFIX="${IMAGE_REPO}:"445 SRC_TAG="${{ needs.create_tag.outputs.source_tag }}"446 BUILD_DATE="${{ steps.build_date.outputs.date }}"447 COMMIT_SHA="${{ steps.checkout.outputs.commit }}"448 echo "image_repo=${IMAGE_REPO}" >> "$GITHUB_OUTPUT"449 TAGS="${{ matrix.config.tag }}"450 ARCHES="${{ matrix.config.arches }}"451 DIGEST_GLOB="/tmp/digests/*.tsv"452 453 if ! ls ${DIGEST_GLOB} >/dev/null 2>&1; then454 echo "No digest metadata found in /tmp/digests" >&2455 exit 1456 fi457 458 if [[ -z "$SRC_TAG" ]]; then459 echo "Missing source tag from create_tag" >&2460 exit 1461 fi462 463 find_digest() {464 local tag_name="$1"465 local arch="$2"466 local image_type="$3"467 local digest468 469 digest="$(awk -F '\t' -v t="$tag_name" -v a="$arch" -v i="$image_type" '$1 == t && $2 == a && $3 == i { print $4; exit }' ${DIGEST_GLOB})"470 471 # Backward compatibility: s390x tags are aliases of cpu for the linux/s390x platform.472 if [[ -z "$digest" && "$tag_name" == "s390x" && "$arch" == "s390x" ]]; then473 digest="$(awk -F '\t' -v t="cpu" -v a="$arch" -v i="$image_type" '$1 == t && $2 == a && $3 == i { print $4; exit }' ${DIGEST_GLOB})"474 fi475 476 if [[ -z "$digest" ]]; then477 echo "Missing digest for tag=${tag_name} arch=${arch} image_type=${image_type}" >&2478 exit 1479 fi480 481 echo "$digest"482 }483 484 create_manifest_tags() {485 local image_type="$1"486 local tag_name="$2"487 local suffix="$3"488 489 local merged_tag="${PREFIX}${image_type}${suffix}"490 local merged_versioned_tag="${merged_tag}-${SRC_TAG}"491 492 local refs=()493 494 for arch in $ARCHES; do495 local digest496 digest="$(find_digest "$tag_name" "$arch" "$image_type")"497 refs+=("${IMAGE_REPO}@${digest}")498 done499 500 local annotations=(501 --annotation "index:org.opencontainers.image.created=${BUILD_DATE}"502 --annotation "index:org.opencontainers.image.version=${SRC_TAG}"503 --annotation "index:org.opencontainers.image.revision=${COMMIT_SHA}"504 --annotation "index:org.opencontainers.image.title=llama.cpp"505 --annotation "index:org.opencontainers.image.description=LLM inference in C/C++"506 --annotation "index:org.opencontainers.image.url=${{ github.server_url }}/${{ github.repository }}"507 --annotation "index:org.opencontainers.image.source=${{ github.server_url }}/${{ github.repository }}"508 )509 510 echo "Creating ${merged_tag} from ${refs[*]}"511 docker buildx imagetools create "${annotations[@]}" --tag "${merged_tag}" "${refs[@]}"512 513 echo "Creating ${merged_versioned_tag} from ${refs[*]}"514 docker buildx imagetools create "${annotations[@]}" --tag "${merged_versioned_tag}" "${refs[@]}"515 516 if [[ "$tag_name" == "${TAGS%% *}" ]]; then517 local digest518 digest="$(docker buildx imagetools inspect "${merged_versioned_tag}" --format '{{.Manifest.Digest}}')"519 if [[ ! "$digest" =~ ^sha256:[0-9a-f]{64}$ ]]; then520 echo "Invalid digest for ${merged_versioned_tag}: ${digest}" >&2521 exit 1522 fi523 echo "${image_type}_digest=${digest}" >> "$GITHUB_OUTPUT"524 fi525 }526 527 for tag in $TAGS; do528 if [[ "$tag" == "cpu" ]]; then529 TYPE=""530 else531 TYPE="-$tag"532 fi533 534 if [[ "${{ matrix.config.full }}" == "true" ]]; then535 create_manifest_tags "full" "$tag" "$TYPE"536 fi537 538 if [[ "${{ matrix.config.light }}" == "true" ]]; then539 create_manifest_tags "light" "$tag" "$TYPE"540 fi541 542 if [[ "${{ matrix.config.server }}" == "true" ]]; then543 create_manifest_tags "server" "$tag" "$TYPE"544 fi545 done546 env:547 GITHUB_REPOSITORY_OWNER: '${{ github.repository_owner }}'548 549 - name: Attest full image550 if: ${{ matrix.config.full }}551 uses: actions/attest@v4552 with:553 subject-name: ${{ steps.create_tags.outputs.image_repo }}554 subject-digest: ${{ steps.create_tags.outputs.full_digest }}555 556 - name: Attest light image557 if: ${{ matrix.config.light }}558 uses: actions/attest@v4559 with:560 subject-name: ${{ steps.create_tags.outputs.image_repo }}561 subject-digest: ${{ steps.create_tags.outputs.light_digest }}562 563 - name: Attest server image564 if: ${{ matrix.config.server }}565 uses: actions/attest@v4566 with:567 subject-name: ${{ steps.create_tags.outputs.image_repo }}568 subject-digest: ${{ steps.create_tags.outputs.server_digest }}569 