3proxy/.github/workflows/docker.yml
Vladimir Dubrovin fa43cafd58 Sign packages, publish checksums, attest before upload, narrow permissions
GPG signing of rpm packages and detached signatures for deb packages and
for the SHA256SUMS files, using GPG_PRIVATE_KEY / GPG_PASSPHRASE secrets.
Checksums are published as release assets.

Build provenance is attested before the assets are uploaded, so a failed
attestation does not leave unattested files published.

Workflow permissions are read-only, write permissions are requested per
job only where they are used.
2026-08-21 11:07:54 +03:00

194 lines
5.6 KiB
YAML

name: Build Docker images
on:
release:
types: [published]
workflow_dispatch:
permissions:
contents: read
env:
DOCKERHUB_IMAGE: docker.io/3proxy/3proxy
GHCR_IMAGE: ghcr.io/3proxy/3proxy
jobs:
build:
name: ${{ matrix.image }} ${{ matrix.platform }}
permissions:
contents: read
packages: write
runs-on: ${{ matrix.runner }}
strategy:
fail-fast: false
matrix:
image: [full, busybox, minimal]
platform: [linux/amd64, linux/arm64, linux/arm/v7]
include:
- platform: linux/amd64
runner: ubuntu-latest
- platform: linux/arm64
runner: ubuntu-24.04-arm
- platform: linux/arm/v7
runner: ubuntu-24.04-arm
steps:
- name: Checkout
uses: actions/checkout@v7
- name: Platform name
id: platform
run: echo "pair=$(echo '${{ matrix.platform }}' | tr / -)" >> "$GITHUB_OUTPUT"
- name: Set up QEMU
if: matrix.platform == 'linux/arm/v7'
uses: docker/setup-qemu-action@v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v4
- name: Login to GHCR
uses: docker/login-action@v4
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Build and push by digest
id: build
uses: docker/build-push-action@v7
with:
context: .
file: Dockerfile.${{ matrix.image }}
platforms: ${{ matrix.platform }}
provenance: false
sbom: false
outputs: type=image,name=${{ env.GHCR_IMAGE }},push-by-digest=true,name-canonical=true,push=true
- name: Export digest
env:
DIGEST: ${{ steps.build.outputs.digest }}
run: |
mkdir -p /tmp/digests
touch "/tmp/digests/${DIGEST#sha256:}"
- name: Upload digest
uses: actions/upload-artifact@v7
with:
name: digests-${{ matrix.image }}-${{ steps.platform.outputs.pair }}
path: /tmp/digests/*
if-no-files-found: error
retention-days: 1
publish:
name: Publish ${{ matrix.image }}
permissions:
contents: read
packages: write
id-token: write
attestations: write
runs-on: ubuntu-latest
needs: build
strategy:
fail-fast: false
matrix:
include:
- image: full
suffix: ''
floating: latest
- image: busybox
suffix: .busybox
floating: busybox
- image: minimal
suffix: .minimal
floating: minimal
steps:
- name: Download digests
uses: actions/download-artifact@v7
with:
path: /tmp/digests
pattern: digests-${{ matrix.image }}-*
merge-multiple: true
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v4
- name: Install cosign
uses: sigstore/cosign-installer@v3
with:
cosign-release: v2.4.3
- name: Login to Docker Hub
uses: docker/login-action@v4
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Login to GHCR
uses: docker/login-action@v4
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Determine tags
id: tags
env:
RELEASE_TAG: ${{ github.event.release.tag_name }}
SUFFIX: ${{ matrix.suffix }}
FLOATING: ${{ matrix.floating }}
run: |
if [[ "$RELEASE_TAG" != "" ]]; then
RELEASE="${RELEASE_TAG#v}"
echo "versioned=${RELEASE}${SUFFIX}" >> "$GITHUB_OUTPUT"
echo "moving=${FLOATING}" >> "$GITHUB_OUTPUT"
else
DATETIME=$(date +%d%m%y%H%M%S)
BRANCH=$(echo "${GITHUB_REF#refs/heads/}" | tr "/" "-")
echo "versioned=${DATETIME}-${BRANCH}${SUFFIX}" >> "$GITHUB_OUTPUT"
echo "moving=${BRANCH}${SUFFIX}" >> "$GITHUB_OUTPUT"
fi
- name: Create manifest list and push
working-directory: /tmp/digests
env:
VERSIONED: ${{ steps.tags.outputs.versioned }}
MOVING: ${{ steps.tags.outputs.moving }}
run: |
docker buildx imagetools create \
-t "${DOCKERHUB_IMAGE}:${VERSIONED}" \
-t "${DOCKERHUB_IMAGE}:${MOVING}" \
-t "${GHCR_IMAGE}:${VERSIONED}" \
-t "${GHCR_IMAGE}:${MOVING}" \
$(printf "${GHCR_IMAGE}@sha256:%s " *)
- name: Get pushed digest
id: digest
env:
VERSIONED: ${{ steps.tags.outputs.versioned }}
run: |
DIGEST=$(docker buildx imagetools inspect "${DOCKERHUB_IMAGE}:${VERSIONED}" \
--format '{{json .Manifest}}' | jq -r .digest)
echo "digest=${DIGEST}" >> "$GITHUB_OUTPUT"
- name: Attest Docker Hub image
uses: actions/attest-build-provenance@v2
with:
subject-name: ${{ env.DOCKERHUB_IMAGE }}
subject-digest: ${{ steps.digest.outputs.digest }}
push-to-registry: false
- name: Attest GHCR image
uses: actions/attest-build-provenance@v2
with:
subject-name: ${{ env.GHCR_IMAGE }}
subject-digest: ${{ steps.digest.outputs.digest }}
push-to-registry: false
- name: Sign images
env:
DIGEST: ${{ steps.digest.outputs.digest }}
run: |
cosign sign --yes "${DOCKERHUB_IMAGE}@${DIGEST}"
cosign sign --yes "${GHCR_IMAGE}@${DIGEST}"