From 0adcc3bb571011bff8b91335d0728a82845c421b Mon Sep 17 00:00:00 2001 From: Jeremie Miller Date: Wed, 19 Aug 2026 01:23:52 -0600 Subject: [PATCH] ci : add attestation for signed release artifacts (#25933) --- .github/workflows/docker.yml | 38 +++++++++++++++++++++++++++++++++++ .github/workflows/release.yml | 7 +++++++ 2 files changed, 45 insertions(+) diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index 350811a93..be2f840b1 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -394,6 +394,11 @@ jobs: name: Create shared tags from digests needs: [prepare_matrices, push_to_registry, create_tag] runs-on: ubuntu-24.04 + permissions: + contents: read + packages: write + id-token: write + attestations: write strategy: fail-fast: false matrix: @@ -428,6 +433,7 @@ jobs: password: ${{ secrets.GITHUB_TOKEN }} - name: Create tags from digests + id: create_tags shell: bash run: | set -euo pipefail @@ -439,6 +445,7 @@ jobs: SRC_TAG="${{ needs.create_tag.outputs.source_tag }}" BUILD_DATE="${{ steps.build_date.outputs.date }}" COMMIT_SHA="${{ steps.checkout.outputs.commit }}" + echo "image_repo=${IMAGE_REPO}" >> "$GITHUB_OUTPUT" TAGS="${{ matrix.config.tag }}" ARCHES="${{ matrix.config.arches }}" DIGEST_GLOB="/tmp/digests/*.tsv" @@ -505,6 +512,16 @@ jobs: echo "Creating ${merged_versioned_tag} from ${refs[*]}" docker buildx imagetools create "${annotations[@]}" --tag "${merged_versioned_tag}" "${refs[@]}" + + if [[ "$tag_name" == "${TAGS%% *}" ]]; then + local digest + digest="$(docker buildx imagetools inspect "${merged_versioned_tag}" --format '{{.Manifest.Digest}}')" + if [[ ! "$digest" =~ ^sha256:[0-9a-f]{64}$ ]]; then + echo "Invalid digest for ${merged_versioned_tag}: ${digest}" >&2 + exit 1 + fi + echo "${image_type}_digest=${digest}" >> "$GITHUB_OUTPUT" + fi } for tag in $TAGS; do @@ -528,3 +545,24 @@ jobs: done env: GITHUB_REPOSITORY_OWNER: '${{ github.repository_owner }}' + + - name: Attest full image + if: ${{ matrix.config.full }} + uses: actions/attest@v4 + with: + subject-name: ${{ steps.create_tags.outputs.image_repo }} + subject-digest: ${{ steps.create_tags.outputs.full_digest }} + + - name: Attest light image + if: ${{ matrix.config.light }} + uses: actions/attest@v4 + with: + subject-name: ${{ steps.create_tags.outputs.image_repo }} + subject-digest: ${{ steps.create_tags.outputs.light_digest }} + + - name: Attest server image + if: ${{ matrix.config.server }} + uses: actions/attest@v4 + with: + subject-name: ${{ steps.create_tags.outputs.image_repo }} + subject-digest: ${{ steps.create_tags.outputs.server_digest }} diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 9de593b9c..01de72a8f 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -1569,6 +1569,8 @@ jobs: # https://docs.github.com/en/actions/security-for-github-actions/security-guides/automatic-token-authentication#modifying-the-permissions-for-the-github_token permissions: contents: write # for creating release + id-token: write + attestations: write runs-on: ubuntu-slim @@ -1662,6 +1664,11 @@ jobs: run: | tar -czvf release/llama-${{ steps.tag.outputs.name }}-ui.tar.gz --transform "s,^\.,llama-${{ steps.tag.outputs.name }}," -C ./ui-dist . + - name: Attest release artifacts + uses: actions/attest@v4 + with: + subject-path: 'release/*' + - name: Create and push git tag run: | TAG="${{ steps.tag.outputs.name }}"