From 3e4207f333c87c4757f2e23a202b777c6e6dc9b3 Mon Sep 17 00:00:00 2001 From: pos Date: Sun, 6 Sep 2026 08:04:27 +0200 Subject: [PATCH 1/5] M12.1: publish releases to Docker Hub --- .github/workflows/release.yml | 67 +++++++++++++++++++++++++---------- 1 file changed, 49 insertions(+), 18 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index a750503..2a528ec 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -12,7 +12,8 @@ permissions: attestations: write env: - IMAGE_NAME: ghcr.io/ploos-as/soju + GHCR_IMAGE: ghcr.io/ploos-as/soju + DOCKERHUB_IMAGE: ${{ vars.DOCKERHUB_USERNAME }}/soju jobs: publish: @@ -25,6 +26,15 @@ jobs: - name: Verify release tag and commit binding run: sh scripts/verify-release-ref.sh "$GITHUB_REF_NAME" "$GITHUB_SHA" + - name: Validate Docker Hub publication configuration + env: + DOCKERHUB_USERNAME: ${{ vars.DOCKERHUB_USERNAME }} + DOCKERHUB_TOKEN: ${{ secrets.DOCKERHUB_TOKEN }} + run: | + set -eu + test -n "$DOCKERHUB_USERNAME" + test -n "$DOCKERHUB_TOKEN" + - name: Set up QEMU uses: docker/setup-qemu-action@c7c53464625b32c7a7e944ae62b3e17d2b600130 @@ -38,11 +48,19 @@ jobs: username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} + - name: Log in to Docker Hub + uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9 + with: + username: ${{ vars.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_TOKEN }} + - name: Docker metadata id: meta uses: docker/metadata-action@c299e40c65443455700f0fdfc63efafe5b349051 with: - images: ${{ env.IMAGE_NAME }} + images: | + ${{ env.GHCR_IMAGE }} + ${{ env.DOCKERHUB_IMAGE }} flavor: | latest=auto tags: | @@ -74,22 +92,29 @@ jobs: IMAGE_DIGEST: ${{ steps.push.outputs.digest }} run: | set -eu - image_ref="$(sh scripts/verify-exact-digest-runtime.sh "$IMAGE_NAME" "$IMAGE_DIGEST")" - docker pull "$image_ref" - resolved="$(docker image inspect "$image_ref" --format '{{index .RepoDigests 0}}')" - test "$resolved" = "$image_ref" - revision="$(docker image inspect "$image_ref" --format '{{index .Config.Labels "org.opencontainers.image.revision"}}')" - version="$(docker image inspect "$image_ref" --format '{{index .Config.Labels "org.opencontainers.image.version"}}')" + ghcr_ref="$(sh scripts/verify-exact-digest-runtime.sh "$GHCR_IMAGE" "$IMAGE_DIGEST")" + dockerhub_ref="$(sh scripts/verify-exact-digest-runtime.sh "$DOCKERHUB_IMAGE" "$IMAGE_DIGEST")" + + docker pull "$ghcr_ref" + ghcr_resolved="$(docker image inspect "$ghcr_ref" --format '{{index .RepoDigests 0}}')" + test "$ghcr_resolved" = "$ghcr_ref" + + docker pull "$dockerhub_ref" + dockerhub_resolved="$(docker image inspect "$dockerhub_ref" --format '{{range .RepoDigests}}{{println .}}{{end}}' | grep -F "${DOCKERHUB_IMAGE}@${IMAGE_DIGEST}" | head -n 1)" + test "$dockerhub_resolved" = "$dockerhub_ref" + + revision="$(docker image inspect "$ghcr_ref" --format '{{index .Config.Labels "org.opencontainers.image.revision"}}')" + version="$(docker image inspect "$ghcr_ref" --format '{{index .Config.Labels "org.opencontainers.image.version"}}')" test "$revision" = "$GITHUB_SHA" test "$version" = "$GITHUB_REF_NAME" - test "$(docker run --rm --entrypoint id "$image_ref" -u)" = "1000" - test "$(docker run --rm --entrypoint id "$image_ref" -g)" = "1000" + test "$(docker run --rm --entrypoint id "$ghcr_ref" -u)" = "1000" + test "$(docker run --rm --entrypoint id "$ghcr_ref" -g)" = "1000" mkdir -p data-release run-release sudo chown 1000:1000 data-release run-release cid=$(docker run -d --rm \ -v "$PWD/data-release:/var/lib/soju" \ -v "$PWD/run-release:/run/soju" \ - "$image_ref") + "$ghcr_ref") trap 'docker logs "$cid" 2>&1 || true; docker rm -f "$cid" >/dev/null 2>&1 || true' EXIT for i in $(seq 1 30); do if docker ps --filter "id=$cid" --format '{{.ID}}' | grep -q . \ @@ -104,25 +129,26 @@ jobs: docker rm -f "$cid" trap - EXIT - - name: Attest image + - name: Attest GHCR image uses: actions/attest-build-provenance@977bb373ede98d70efdf65b84cb5f73e068dcc2a with: - subject-name: ${{ env.IMAGE_NAME }} + subject-name: ${{ env.GHCR_IMAGE }} subject-digest: ${{ steps.push.outputs.digest }} push-to-registry: true - name: Install Cosign uses: sigstore/cosign-installer@d7543c93d881b35a8faa02e8e3605f69b7a1ce62 - - name: Sign exact release digest with GitHub OIDC + - name: Sign exact release digests with GitHub OIDC env: IMAGE_DIGEST: ${{ steps.push.outputs.digest }} run: | set -eu test -n "$IMAGE_DIGEST" - cosign sign --yes "${IMAGE_NAME}@${IMAGE_DIGEST}" + cosign sign --yes "${GHCR_IMAGE}@${IMAGE_DIGEST}" + cosign sign --yes "${DOCKERHUB_IMAGE}@${IMAGE_DIGEST}" - - name: Verify keyless release signature + - name: Verify keyless release signatures env: IMAGE_DIGEST: ${{ steps.push.outputs.digest }} run: | @@ -131,8 +157,13 @@ jobs: cosign verify \ --certificate-oidc-issuer https://token.actions.githubusercontent.com \ --certificate-identity-regexp '^https://github.com/Ploos-AS/soju/.github/workflows/release.yml@refs/tags/v.*$' \ - "${IMAGE_NAME}@${IMAGE_DIGEST}" > /tmp/cosign-verification.json - test -s /tmp/cosign-verification.json + "${GHCR_IMAGE}@${IMAGE_DIGEST}" > /tmp/cosign-ghcr.json + test -s /tmp/cosign-ghcr.json + cosign verify \ + --certificate-oidc-issuer https://token.actions.githubusercontent.com \ + --certificate-identity-regexp '^https://github.com/Ploos-AS/soju/.github/workflows/release.yml@refs/tags/v.*$' \ + "${DOCKERHUB_IMAGE}@${IMAGE_DIGEST}" > /tmp/cosign-dockerhub.json + test -s /tmp/cosign-dockerhub.json - name: Create GitHub Release env: From c44d8e78fa640b76a44ae3ea4d5764bd72c20d46 Mon Sep 17 00:00:00 2001 From: pos Date: Sun, 6 Sep 2026 08:04:43 +0200 Subject: [PATCH 2/5] M12.1: document Docker Hub publishing --- README.md | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 90abfa7..557d0ff 100644 --- a/README.md +++ b/README.md @@ -2,14 +2,24 @@ Production-oriented OCI packaging for [soju](https://soju.im/), the IRC bouncer maintained at Codeberg. -> Upstream already publishes a container image. This repository is an independent Ploos-AS packaging project focused on reproducible source builds, explicit upstream pinning, non-root operation, multi-architecture GHCR releases, and supply-chain attestations. It is not a fork of soju. +> Upstream already publishes a container image. This repository is an independent Ploos-AS packaging project focused on reproducible source builds, explicit upstream pinning, non-root operation, multi-architecture OCI releases, and supply-chain attestations. It is not a fork of soju. -## Image +## Images + +Primary registry: ```text ghcr.io/ploos-as/soju ``` +Secondary registry: + +```text +/soju +``` + +Release workflows publish the same multi-architecture build to GHCR and Docker Hub. Docker Hub authentication uses the GitHub Actions repository variable `DOCKERHUB_USERNAME` and secret `DOCKERHUB_TOKEN`. + Target platforms: - `linux/amd64` @@ -109,7 +119,7 @@ CI verifies that the container starts as UID/GID 1000, creates its SQLite databa ## Releases -Tags matching `v*` publish semver aliases to GHCR and build both amd64 and arm64 images. Release builds include SBOM and provenance/attestation metadata. +Tags matching `v*` publish semver aliases to both GHCR and Docker Hub and build both amd64 and arm64 images. Release builds include SBOM and provenance/attestation metadata. The exact published digest is runtime-qualified, and keyless Cosign signatures are written and verified for both registry references. ## Upstream From 9040c4c6aee33cc3fa43c7303a94672fcee03dec Mon Sep 17 00:00:00 2001 From: pos Date: Sun, 6 Sep 2026 08:05:14 +0200 Subject: [PATCH 3/5] M12.1: audit Docker Hub release parity --- .github/workflows/post-release-audit.yml | 67 +++++++++++++++++------- 1 file changed, 49 insertions(+), 18 deletions(-) diff --git a/.github/workflows/post-release-audit.yml b/.github/workflows/post-release-audit.yml index 7adc507..ffe872b 100644 --- a/.github/workflows/post-release-audit.yml +++ b/.github/workflows/post-release-audit.yml @@ -17,7 +17,8 @@ permissions: id-token: write env: - IMAGE_NAME: ghcr.io/ploos-as/soju + GHCR_IMAGE: ghcr.io/ploos-as/soju + DOCKERHUB_IMAGE: ${{ vars.DOCKERHUB_USERNAME }}/soju jobs: audit: @@ -66,6 +67,15 @@ jobs: echo "tag=$tag" >> "$GITHUB_OUTPUT" echo "commit=$tag_commit" >> "$GITHUB_OUTPUT" + - name: Validate Docker Hub audit configuration + env: + DOCKERHUB_USERNAME: ${{ vars.DOCKERHUB_USERNAME }} + DOCKERHUB_TOKEN: ${{ secrets.DOCKERHUB_TOKEN }} + run: | + set -eu + test -n "$DOCKERHUB_USERNAME" + test -n "$DOCKERHUB_TOKEN" + - name: Set up QEMU uses: docker/setup-qemu-action@c7c53464625b32c7a7e944ae62b3e17d2b600130 @@ -79,27 +89,42 @@ jobs: username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} - - name: Resolve immutable release digest and verify platforms + - name: Log in to Docker Hub + uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9 + with: + username: ${{ vars.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_TOKEN }} + + - name: Resolve immutable release digest and verify registry parity id: image env: TAG: ${{ steps.release.outputs.tag }} shell: bash run: | set -euo pipefail - image_tag="${IMAGE_NAME}:${TAG#v}" - docker manifest inspect "$image_tag" > /tmp/manifest.json - jq -e 'any(.manifests[]; .platform.os == "linux" and .platform.architecture == "amd64")' /tmp/manifest.json >/dev/null - jq -e 'any(.manifests[]; .platform.os == "linux" and .platform.architecture == "arm64")' /tmp/manifest.json >/dev/null - docker pull --platform linux/amd64 "$image_tag" >/dev/null - repo_digest="$(docker image inspect "$image_tag" --format '{{index .RepoDigests 0}}')" - digest="${repo_digest##*@}" - sh scripts/verify-exact-digest-runtime.sh "$IMAGE_NAME" "$digest" >/dev/null - echo "digest=$digest" >> "$GITHUB_OUTPUT" + ghcr_tag="${GHCR_IMAGE}:${TAG#v}" + dockerhub_tag="${DOCKERHUB_IMAGE}:${TAG#v}" + + docker manifest inspect "$ghcr_tag" > /tmp/ghcr-manifest.json + jq -e 'any(.manifests[]; .platform.os == "linux" and .platform.architecture == "amd64")' /tmp/ghcr-manifest.json >/dev/null + jq -e 'any(.manifests[]; .platform.os == "linux" and .platform.architecture == "arm64")' /tmp/ghcr-manifest.json >/dev/null + + docker manifest inspect "$dockerhub_tag" > /tmp/dockerhub-manifest.json + jq -e 'any(.manifests[]; .platform.os == "linux" and .platform.architecture == "amd64")' /tmp/dockerhub-manifest.json >/dev/null + jq -e 'any(.manifests[]; .platform.os == "linux" and .platform.architecture == "arm64")' /tmp/dockerhub-manifest.json >/dev/null + + ghcr_digest="$(docker buildx imagetools inspect "$ghcr_tag" | awk '/^Digest:/ {print $2; exit}')" + dockerhub_digest="$(docker buildx imagetools inspect "$dockerhub_tag" | awk '/^Digest:/ {print $2; exit}')" + test -n "$ghcr_digest" + test "$dockerhub_digest" = "$ghcr_digest" + sh scripts/verify-exact-digest-runtime.sh "$GHCR_IMAGE" "$ghcr_digest" >/dev/null + sh scripts/verify-exact-digest-runtime.sh "$DOCKERHUB_IMAGE" "$dockerhub_digest" >/dev/null + echo "digest=$ghcr_digest" >> "$GITHUB_OUTPUT" - name: Install Cosign uses: sigstore/cosign-installer@d7543c93d881b35a8faa02e8e3605f69b7a1ce62 - - name: Verify exact-digest signature + - name: Verify exact-digest signatures env: IMAGE_DIGEST: ${{ steps.image.outputs.digest }} shell: bash @@ -108,8 +133,13 @@ jobs: cosign verify \ --certificate-oidc-issuer https://token.actions.githubusercontent.com \ --certificate-identity-regexp '^https://github.com/Ploos-AS/soju/.github/workflows/release.yml@refs/tags/v.*$' \ - "${IMAGE_NAME}@${IMAGE_DIGEST}" > /tmp/cosign-verification.json - jq -e 'length > 0' /tmp/cosign-verification.json >/dev/null + "${GHCR_IMAGE}@${IMAGE_DIGEST}" > /tmp/cosign-ghcr.json + jq -e 'length > 0' /tmp/cosign-ghcr.json >/dev/null + cosign verify \ + --certificate-oidc-issuer https://token.actions.githubusercontent.com \ + --certificate-identity-regexp '^https://github.com/Ploos-AS/soju/.github/workflows/release.yml@refs/tags/v.*$' \ + "${DOCKERHUB_IMAGE}@${IMAGE_DIGEST}" > /tmp/cosign-dockerhub.json + jq -e 'length > 0' /tmp/cosign-dockerhub.json >/dev/null - name: Verify immutable labels and runtime after release env: @@ -119,7 +149,7 @@ jobs: shell: bash run: | set -euo pipefail - image_ref="${IMAGE_NAME}@${IMAGE_DIGEST}" + image_ref="${GHCR_IMAGE}@${IMAGE_DIGEST}" docker pull --platform linux/amd64 "$image_ref" >/dev/null revision="$(docker image inspect "$image_ref" --format '{{index .Config.Labels "org.opencontainers.image.revision"}}')" version="$(docker image inspect "$image_ref" --format '{{index .Config.Labels "org.opencontainers.image.version"}}')" @@ -153,13 +183,14 @@ jobs: IMAGE_DIGEST: ${{ steps.image.outputs.digest }} run: | { - echo '### M11.5 post-release audit' + echo '### M12.1 dual-registry post-release audit' echo echo "- release: $TAG" echo "- immutable digest: $IMAGE_DIGEST" echo '- GitHub Release/tag/commit binding: verified' - echo '- linux/amd64 + linux/arm64 manifest coverage: verified' - echo '- Cosign keyless signature and release workflow OIDC identity: verified' + echo '- GHCR + Docker Hub digest parity: verified' + echo '- linux/amd64 + linux/arm64 manifest coverage in both registries: verified' + echo '- Cosign keyless signatures in both registries: verified' echo '- OCI revision/version labels: verified' echo '- non-root UID/GID 1000: verified' echo '- exact-digest post-publication SQLite + admin-socket runtime: verified' From 543a56e5116a6b56d631bcdd376a00f6548c1759 Mon Sep 17 00:00:00 2001 From: pos Date: Sun, 6 Sep 2026 08:24:04 +0200 Subject: [PATCH 4/5] M12.1: read Docker Hub username from secrets --- .github/workflows/release.yml | 41 +++++++++-------------------------- 1 file changed, 10 insertions(+), 31 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 2a528ec..db47617 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -13,7 +13,7 @@ permissions: env: GHCR_IMAGE: ghcr.io/ploos-as/soju - DOCKERHUB_IMAGE: ${{ vars.DOCKERHUB_USERNAME }}/soju + DOCKERHUB_IMAGE: ${{ secrets.DOCKERHUB_USERNAME }}/soju jobs: publish: @@ -28,7 +28,7 @@ jobs: - name: Validate Docker Hub publication configuration env: - DOCKERHUB_USERNAME: ${{ vars.DOCKERHUB_USERNAME }} + DOCKERHUB_USERNAME: ${{ secrets.DOCKERHUB_USERNAME }} DOCKERHUB_TOKEN: ${{ secrets.DOCKERHUB_TOKEN }} run: | set -eu @@ -51,7 +51,7 @@ jobs: - name: Log in to Docker Hub uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9 with: - username: ${{ vars.DOCKERHUB_USERNAME }} + username: ${{ secrets.DOCKERHUB_USERNAME }} password: ${{ secrets.DOCKERHUB_TOKEN }} - name: Docker metadata @@ -94,15 +94,12 @@ jobs: set -eu ghcr_ref="$(sh scripts/verify-exact-digest-runtime.sh "$GHCR_IMAGE" "$IMAGE_DIGEST")" dockerhub_ref="$(sh scripts/verify-exact-digest-runtime.sh "$DOCKERHUB_IMAGE" "$IMAGE_DIGEST")" - docker pull "$ghcr_ref" ghcr_resolved="$(docker image inspect "$ghcr_ref" --format '{{index .RepoDigests 0}}')" test "$ghcr_resolved" = "$ghcr_ref" - docker pull "$dockerhub_ref" dockerhub_resolved="$(docker image inspect "$dockerhub_ref" --format '{{range .RepoDigests}}{{println .}}{{end}}' | grep -F "${DOCKERHUB_IMAGE}@${IMAGE_DIGEST}" | head -n 1)" test "$dockerhub_resolved" = "$dockerhub_ref" - revision="$(docker image inspect "$ghcr_ref" --format '{{index .Config.Labels "org.opencontainers.image.revision"}}')" version="$(docker image inspect "$ghcr_ref" --format '{{index .Config.Labels "org.opencontainers.image.version"}}')" test "$revision" = "$GITHUB_SHA" @@ -111,18 +108,10 @@ jobs: test "$(docker run --rm --entrypoint id "$ghcr_ref" -g)" = "1000" mkdir -p data-release run-release sudo chown 1000:1000 data-release run-release - cid=$(docker run -d --rm \ - -v "$PWD/data-release:/var/lib/soju" \ - -v "$PWD/run-release:/run/soju" \ - "$ghcr_ref") + cid=$(docker run -d --rm -v "$PWD/data-release:/var/lib/soju" -v "$PWD/run-release:/run/soju" "$ghcr_ref") trap 'docker logs "$cid" 2>&1 || true; docker rm -f "$cid" >/dev/null 2>&1 || true' EXIT for i in $(seq 1 30); do - if docker ps --filter "id=$cid" --format '{{.ID}}' | grep -q . \ - && test -f data-release/main.db \ - && test -S run-release/admin; then - qualified=true - break - fi + if docker ps --filter "id=$cid" --format '{{.ID}}' | grep -q . && test -f data-release/main.db && test -S run-release/admin; then qualified=true; break; fi sleep 1 done test "${qualified:-false}" = true @@ -154,16 +143,10 @@ jobs: run: | set -eu test -n "$IMAGE_DIGEST" - cosign verify \ - --certificate-oidc-issuer https://token.actions.githubusercontent.com \ - --certificate-identity-regexp '^https://github.com/Ploos-AS/soju/.github/workflows/release.yml@refs/tags/v.*$' \ - "${GHCR_IMAGE}@${IMAGE_DIGEST}" > /tmp/cosign-ghcr.json - test -s /tmp/cosign-ghcr.json - cosign verify \ - --certificate-oidc-issuer https://token.actions.githubusercontent.com \ - --certificate-identity-regexp '^https://github.com/Ploos-AS/soju/.github/workflows/release.yml@refs/tags/v.*$' \ - "${DOCKERHUB_IMAGE}@${IMAGE_DIGEST}" > /tmp/cosign-dockerhub.json - test -s /tmp/cosign-dockerhub.json + for image in "$GHCR_IMAGE" "$DOCKERHUB_IMAGE"; do + cosign verify --certificate-oidc-issuer https://token.actions.githubusercontent.com --certificate-identity-regexp '^https://github.com/Ploos-AS/soju/.github/workflows/release.yml@refs/tags/v.*$' "${image}@${IMAGE_DIGEST}" > /tmp/cosign-verification.json + test -s /tmp/cosign-verification.json + done - name: Create GitHub Release env: @@ -173,9 +156,5 @@ jobs: if gh release view "$GITHUB_REF_NAME" --repo "$GITHUB_REPOSITORY" >/dev/null 2>&1; then echo "GitHub Release already exists for $GITHUB_REF_NAME" else - gh release create "$GITHUB_REF_NAME" \ - --repo "$GITHUB_REPOSITORY" \ - --title "soju $GITHUB_REF_NAME" \ - --generate-notes \ - --verify-tag + gh release create "$GITHUB_REF_NAME" --repo "$GITHUB_REPOSITORY" --title "soju $GITHUB_REF_NAME" --generate-notes --verify-tag fi From 2b735f5bf4e2ae90d1d5b029f58d602b4278a068 Mon Sep 17 00:00:00 2001 From: pos Date: Sun, 6 Sep 2026 08:24:45 +0200 Subject: [PATCH 5/5] M12.1: use Docker Hub username secret in audit --- .github/workflows/post-release-audit.yml | 50 ++++++------------------ 1 file changed, 12 insertions(+), 38 deletions(-) diff --git a/.github/workflows/post-release-audit.yml b/.github/workflows/post-release-audit.yml index ffe872b..8306a82 100644 --- a/.github/workflows/post-release-audit.yml +++ b/.github/workflows/post-release-audit.yml @@ -18,7 +18,7 @@ permissions: env: GHCR_IMAGE: ghcr.io/ploos-as/soju - DOCKERHUB_IMAGE: ${{ vars.DOCKERHUB_USERNAME }}/soju + DOCKERHUB_IMAGE: ${{ secrets.DOCKERHUB_USERNAME }}/soju jobs: audit: @@ -46,30 +46,21 @@ jobs: while IFS= read -r candidate; do [[ -n "$candidate" ]] || continue commit="$(git rev-list -n 1 "$candidate" 2>/dev/null || true)" - if [[ "$commit" == "$PRODUCER_SHA" ]]; then - tag="$candidate" - break - fi + if [[ "$commit" == "$PRODUCER_SHA" ]]; then tag="$candidate"; break; fi done < <(gh release list --repo "$GITHUB_REPOSITORY" --limit 100 --json tagName,isDraft --jq '.[] | select(.isDraft == false) | .tagName') fi [[ -n "$tag" ]] tag_commit="$(git rev-list -n 1 "$tag")" - if [[ -n "$INPUT_TAG" ]]; then - sh scripts/verify-release-ref.sh "$tag" "$tag_commit" --allow-head-mismatch-for-audit - else - sh scripts/verify-release-ref.sh "$tag" "$tag_commit" - fi + if [[ -n "$INPUT_TAG" ]]; then sh scripts/verify-release-ref.sh "$tag" "$tag_commit" --allow-head-mismatch-for-audit; else sh scripts/verify-release-ref.sh "$tag" "$tag_commit"; fi release_json="$(gh release view "$tag" --repo "$GITHUB_REPOSITORY" --json tagName,isDraft,isPrerelease)" jq -e --arg tag "$tag" '.tagName == $tag and .isDraft == false' <<<"$release_json" >/dev/null - if [[ -n "$PRODUCER_SHA" ]]; then - test "$tag_commit" = "$PRODUCER_SHA" - fi + if [[ -n "$PRODUCER_SHA" ]]; then test "$tag_commit" = "$PRODUCER_SHA"; fi echo "tag=$tag" >> "$GITHUB_OUTPUT" echo "commit=$tag_commit" >> "$GITHUB_OUTPUT" - name: Validate Docker Hub audit configuration env: - DOCKERHUB_USERNAME: ${{ vars.DOCKERHUB_USERNAME }} + DOCKERHUB_USERNAME: ${{ secrets.DOCKERHUB_USERNAME }} DOCKERHUB_TOKEN: ${{ secrets.DOCKERHUB_TOKEN }} run: | set -eu @@ -92,7 +83,7 @@ jobs: - name: Log in to Docker Hub uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9 with: - username: ${{ vars.DOCKERHUB_USERNAME }} + username: ${{ secrets.DOCKERHUB_USERNAME }} password: ${{ secrets.DOCKERHUB_TOKEN }} - name: Resolve immutable release digest and verify registry parity @@ -104,15 +95,12 @@ jobs: set -euo pipefail ghcr_tag="${GHCR_IMAGE}:${TAG#v}" dockerhub_tag="${DOCKERHUB_IMAGE}:${TAG#v}" - docker manifest inspect "$ghcr_tag" > /tmp/ghcr-manifest.json jq -e 'any(.manifests[]; .platform.os == "linux" and .platform.architecture == "amd64")' /tmp/ghcr-manifest.json >/dev/null jq -e 'any(.manifests[]; .platform.os == "linux" and .platform.architecture == "arm64")' /tmp/ghcr-manifest.json >/dev/null - docker manifest inspect "$dockerhub_tag" > /tmp/dockerhub-manifest.json jq -e 'any(.manifests[]; .platform.os == "linux" and .platform.architecture == "amd64")' /tmp/dockerhub-manifest.json >/dev/null jq -e 'any(.manifests[]; .platform.os == "linux" and .platform.architecture == "arm64")' /tmp/dockerhub-manifest.json >/dev/null - ghcr_digest="$(docker buildx imagetools inspect "$ghcr_tag" | awk '/^Digest:/ {print $2; exit}')" dockerhub_digest="$(docker buildx imagetools inspect "$dockerhub_tag" | awk '/^Digest:/ {print $2; exit}')" test -n "$ghcr_digest" @@ -130,16 +118,10 @@ jobs: shell: bash run: | set -euo pipefail - cosign verify \ - --certificate-oidc-issuer https://token.actions.githubusercontent.com \ - --certificate-identity-regexp '^https://github.com/Ploos-AS/soju/.github/workflows/release.yml@refs/tags/v.*$' \ - "${GHCR_IMAGE}@${IMAGE_DIGEST}" > /tmp/cosign-ghcr.json - jq -e 'length > 0' /tmp/cosign-ghcr.json >/dev/null - cosign verify \ - --certificate-oidc-issuer https://token.actions.githubusercontent.com \ - --certificate-identity-regexp '^https://github.com/Ploos-AS/soju/.github/workflows/release.yml@refs/tags/v.*$' \ - "${DOCKERHUB_IMAGE}@${IMAGE_DIGEST}" > /tmp/cosign-dockerhub.json - jq -e 'length > 0' /tmp/cosign-dockerhub.json >/dev/null + for image in "$GHCR_IMAGE" "$DOCKERHUB_IMAGE"; do + cosign verify --certificate-oidc-issuer https://token.actions.githubusercontent.com --certificate-identity-regexp '^https://github.com/Ploos-AS/soju/.github/workflows/release.yml@refs/tags/v.*$' "${image}@${IMAGE_DIGEST}" > /tmp/cosign-verification.json + jq -e 'length > 0' /tmp/cosign-verification.json >/dev/null + done - name: Verify immutable labels and runtime after release env: @@ -159,18 +141,10 @@ jobs: test "$(docker run --rm --platform linux/amd64 --entrypoint id "$image_ref" -g)" = "1000" mkdir -p data-audit run-audit sudo chown 1000:1000 data-audit run-audit - cid=$(docker run -d --rm --platform linux/amd64 \ - -v "$PWD/data-audit:/var/lib/soju" \ - -v "$PWD/run-audit:/run/soju" \ - "$image_ref") + cid=$(docker run -d --rm --platform linux/amd64 -v "$PWD/data-audit:/var/lib/soju" -v "$PWD/run-audit:/run/soju" "$image_ref") trap 'docker logs "$cid" 2>&1 || true; docker rm -f "$cid" >/dev/null 2>&1 || true' EXIT for i in $(seq 1 30); do - if docker ps --filter "id=$cid" --format '{{.ID}}' | grep -q . \ - && test -f data-audit/main.db \ - && test -S run-audit/admin; then - healthy=true - break - fi + if docker ps --filter "id=$cid" --format '{{.ID}}' | grep -q . && test -f data-audit/main.db && test -S run-audit/admin; then healthy=true; break; fi sleep 1 done test "${healthy:-false}" = true