name: Publish Docker Image on: push: branches: - master - multi-runner-docker tags: - v** workflow_dispatch: env: REGISTRY: ghcr.io IMAGE: ${{ github.repository }} jobs: gen-versions: name: Generate tags runs-on: ubuntu-24.04 outputs: DOCKER_IMAGE_TAG_JSON: ${{ steps.variables.outputs.DOCKER_IMAGE_TAG_JSON }} DOCKER_IMAGE_TAG: ${{ steps.variables.outputs.DOCKER_IMAGE_TAG }} steps: - name: Setup variables id: variables run: | # docker/build-push-action supports comma separated tags DOCKER_IMAGE_TAG_BASE="$REGISTRY/$IMAGE" DOCKER_IMAGE_TAG_JSON="$( ( # Every line echoed inside of these parenthesis will result in a version echo dev GH_REF="${{ github.ref }}" # if this is a versioned release, github.ref will start with 'refs/tags/v' # cut off 'refs/tags/v' if [[ $GH_REF == "refs/tags/v"* ]]; then VERSION=$(echo $GH_REF | cut -c 12-) echo latest echo $VERSION fi ) | sed -e 's|.*|'"$DOCKER_IMAGE_TAG_BASE"':\0|' | jq -R -s -c 'split("\n") | map(select (. != "" ))')" echo "DOCKER_IMAGE_TAG_JSON=$DOCKER_IMAGE_TAG_JSON" >> "$GITHUB_OUTPUT" echo "DOCKER_IMAGE_TAG=$(echo "$DOCKER_IMAGE_TAG_JSON" | jq -r 'join(",")')" >> "$GITHUB_OUTPUT" publish-base: name: Publish ${{ matrix.arch }} image strategy: matrix: include: - arch: arm64 os: ubuntu-24.04-arm - arch: amd64 os: ubuntu-24.04 runs-on: ${{ matrix.os }} needs: - gen-versions env: ARCH: ${{matrix.arch}} permissions: packages: write steps: - name: Check out the repo uses: actions/checkout@v4 - name: Log in to ghcr.io uses: docker/login-action@v3 with: registry: ghcr.io username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} - name: Enhance tags id: variables run: | echo "DOCKER_IMAGE_TAG=$(echo "$TAG" | jq -r 'map(. + "-${{ matrix.arch }}") | join(",")')" >>"$GITHUB_OUTPUT" env: TAG: ${{ needs.gen-versions.outputs.DOCKER_IMAGE_TAG_JSON }} - name: Set up Docker Buildx # Even if we don't directly invoke buildx it should set up github action caches, which is nice uses: docker/setup-buildx-action@v3 - name: Build and push Docker Image uses: docker/build-push-action@v6 id: upload-docker-image with: context: . push: true tags: ${{ steps.variables.outputs.DOCKER_IMAGE_TAG }} cache-from: type=gha cache-to: type=gha,mode=max - name: Write digest run: | digest="${{ steps.upload-docker-image.outputs.digest }}" mkdir -p digests touch "digests/${digest#sha256:}" - name: Upload docker image digest uses: actions/upload-artifact@v4 with: if-no-files-found: error name: digests-${{ matrix.arch }} path: digests/* publish-multiarch: name: Publish multi-arch image needs: - publish-base - gen-versions runs-on: ubuntu-24.04 permissions: packages: write steps: - name: Download digests uses: actions/download-artifact@v4 with: path: digests pattern: digests-* merge-multiple: true - name: Log in to ghcr.io uses: docker/login-action@v3 with: registry: ghcr.io username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3 - name: Create manifest list run: | cd digests docker buildx imagetools create \ `# A -t {tag} for each tag in DOCKER_IMAGE_TAGS` \ $(echo '${{ needs.gen-versions.outputs.DOCKER_IMAGE_TAG }}'| tr ',' '\n' | sed -e 's|.*|-t \0|') \ `# Then a reference for each of the arches. This uses the fact that printf repeats its format string if it has too many arguments.` \ $(printf '${{env.REGISTRY}}/${{ env.IMAGE }}@sha256:%s ' *)