name: Build Docker permissions: actions: read contents: read packages: write on: push: branches: - master pull_request: branches: - master paths: - '.github/workflows/docker-release.yml' - 'Dockerfile' release: types: - released # publishing of stable releases # Cancel earlier, unfinished runs of this workflow on the same branch (unless on release) concurrency: group: "${{ github.workflow }} @ ${{ github.ref_name }}" cancel-in-progress: ${{ github.event_name != 'release' }} env: IMAGE_NAME: ghcr.io/cockatrice/servatrice OCI_DESCRIPTION: Server for Cockatrice, a cross-platform virtual tabletop for multiplayer card games OCI_TITLE: Servatrice OCI_URL: https://cockatrice.github.io/ jobs: build: strategy: fail-fast: false matrix: include: - platform: linux/amd64 runner: ubuntu-latest - platform: linux/arm64 runner: ubuntu-24.04-arm name: "Build (${{ matrix.platform }})" if: github.repository_owner == 'Cockatrice' runs-on: ${{ matrix.runner }} steps: - name: "Checkout" uses: actions/checkout@v7 - name: "Set up Docker buildx" uses: docker/setup-buildx-action@v4 - name: "Login to GitHub Container Registry (GHCR)" if: github.event_name == 'release' && github.event.release.prerelease == false id: login uses: docker/login-action@v4 with: password: ${{ github.token }} registry: ghcr.io username: ${{ github.actor }} - name: "Build Docker image and push by digest" if: steps.login.outcome == 'success' id: build uses: docker/build-push-action@v7 with: cache-from: type=gha,scope=servatrice-${{ matrix.platform }} cache-to: type=gha,mode=max,scope=servatrice-${{ matrix.platform }} context: . labels: | org.opencontainers.image.description=${{ env.OCI_DESCRIPTION }} org.opencontainers.image.title=${{ env.OCI_TITLE }} org.opencontainers.image.url=${{ env.OCI_URL }} outputs: type=image,push-by-digest=true,name-canonical=true,push=true platforms: ${{ matrix.platform }} - name: "Build Docker image" if: steps.login.outcome != 'success' uses: docker/build-push-action@v7 with: cache-from: type=gha,scope=servatrice-${{ matrix.platform }} cache-to: type=gha,mode=max,scope=servatrice-${{ matrix.platform }} context: . platforms: ${{ matrix.platform }} push: false - name: Export digest if: steps.login.outcome == 'success' env: DIGEST: ${{ steps.build.outputs.digest }} run: | mkdir -p $RUNNER_TEMP/digests touch "$RUNNER_TEMP/digests/${DIGEST#sha256:}" - uses: actions/upload-artifact@v7 if: steps.login.outcome == 'success' with: name: digest-${{ matrix.platform }} path: $RUNNER_TEMP/digests/* retention-days: 1 merge: needs: build name: "Publish manifest" if: github.repository_owner == 'Cockatrice' && github.event_name == 'release' && github.event.release.prerelease == false runs-on: ubuntu-slim steps: - uses: actions/download-artifact@v4 with: path: $RUNNER_TEMP/digests pattern: digest-* merge-multiple: true - name: "Set up Docker buildx" uses: docker/setup-buildx-action@v4 - name: "Login to GitHub Container Registry (GHCR)" uses: docker/login-action@v4 with: password: ${{ github.token }} registry: ghcr.io username: ${{ github.actor }} - name: "Docker metadata" id: metadata uses: docker/metadata-action@v6 with: images: ${{ env.IMAGE_NAME }} tags: | type=raw,value=latest type=ref,event=tag - name: "Create manifest" env: TAGS: ${{ steps.metadata.outputs.tags }} working-directory: ${{ runner.temp }}/digests run: | TAG_ARGS="" for tag in $TAGS; do TAG_ARGS="$TAG_ARGS -t $tag" done docker buildx imagetools create \ --annotation "index:org.opencontainers.image.description=$OCI_DESCRIPTION" \ --annotation "index:org.opencontainers.image.title=$OCI_TITLE" \ --annotation "index:org.opencontainers.image.url=$OCI_URL" \ $TAG_ARGS \ $(printf '%s@sha256:%s ' "$IMAGE_NAME" *) - name: "Inspect image" run: docker buildx imagetools inspect "$IMAGE_NAME:latest"