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}"