From 3ff57513ae20375f2b7f639e0823b9e9a7d22d05 Mon Sep 17 00:00:00 2001 From: Amadeus Mader Date: Wed, 4 Mar 2026 12:53:49 +0100 Subject: [PATCH] ci: updated release build --- .github/workflows/docker_release.yml | 181 ++++++++++++++++++++------- 1 file changed, 139 insertions(+), 42 deletions(-) diff --git a/.github/workflows/docker_release.yml b/.github/workflows/docker_release.yml index 0e9224b..81c0915 100644 --- a/.github/workflows/docker_release.yml +++ b/.github/workflows/docker_release.yml @@ -24,25 +24,139 @@ on: types: - published -jobs: - build_and_push_docker: - runs-on: ubuntu-latest - env: - dev_arch: 'linux/amd64' - release_arch: 'linux/amd64,linux/arm64' - permissions: - contents: read - packages: write - steps: - - name: Checkout - uses: actions/checkout@v4 +# Prevent concurrent releases - queue them instead +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: false - - name: Docker meta - id: meta - uses: docker/metadata-action@v5 +env: + REGISTRY: ghcr.io + IMAGE_NAME: ${{ github.repository }} + +permissions: + contents: read + packages: write + +jobs: + # Determine which platforms to build based on trigger type + prepare: + runs-on: ubuntu-latest + outputs: + matrix: ${{ steps.set-matrix.outputs.matrix }} + is_multi_arch: ${{ steps.set-matrix.outputs.is_multi_arch }} + steps: + - name: Determine build matrix + id: set-matrix + run: | + # Release events always build both architectures + # Push to master only builds amd64 (for speed) + # workflow_dispatch uses the selected platforms input + + if [[ "${{ github.event_name }}" == "release" ]]; then + echo 'matrix={"include":[{"platform":"linux/amd64","runner":"ubuntu-latest"},{"platform":"linux/arm64","runner":"ubuntu-24.04-arm"}]}' >> $GITHUB_OUTPUT + echo "is_multi_arch=true" >> $GITHUB_OUTPUT + elif [[ "${{ github.event_name }}" == "workflow_dispatch" ]]; then + PLATFORMS="${{ inputs.platforms }}" + if [[ "$PLATFORMS" == *"arm64"* ]]; then + echo 'matrix={"include":[{"platform":"linux/amd64","runner":"ubuntu-latest"},{"platform":"linux/arm64","runner":"ubuntu-24.04-arm"}]}' >> $GITHUB_OUTPUT + echo "is_multi_arch=true" >> $GITHUB_OUTPUT + else + echo 'matrix={"include":[{"platform":"linux/amd64","runner":"ubuntu-latest"}]}' >> $GITHUB_OUTPUT + echo "is_multi_arch=false" >> $GITHUB_OUTPUT + fi + else + # Push to master - only amd64 for faster dev builds + echo 'matrix={"include":[{"platform":"linux/amd64","runner":"ubuntu-latest"}]}' >> $GITHUB_OUTPUT + echo "is_multi_arch=false" >> $GITHUB_OUTPUT + fi + + build: + needs: prepare + runs-on: ${{ matrix.runner }} + timeout-minutes: 45 + strategy: + fail-fast: false + matrix: ${{ fromJson(needs.prepare.outputs.matrix) }} + steps: + - name: Prepare environment + run: | + platform=${{ matrix.platform }} + echo "PLATFORM_PAIR=${platform//\//-}" >> $GITHUB_ENV + + - name: Checkout + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@b5ca514318bd6ebac0fb2aedd5d36ec1b5c232a2 # v3.10.0 + + - name: Login to GitHub Container Registry + uses: docker/login-action@74a5d142397b4f367a81961eba4e8cd7edddf772 # v3.4.0 with: - images: | - ghcr.io/${{ github.repository }} + registry: ${{ env.REGISTRY }} + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Extract metadata for Docker + id: meta + uses: docker/metadata-action@902fa8ec7d6ecbf8d84d538b9b233a880e428804 # v5.7.0 + with: + images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} + + - name: Build and push by digest + id: build + uses: docker/build-push-action@471d1dc4e07e5cdedd4c2171150001c434f0b7a4 # v6.15.0 + with: + context: . + file: ./docker/selfhosted.Dockerfile + platforms: ${{ matrix.platform }} + labels: ${{ steps.meta.outputs.labels }} + outputs: type=image,name=${{ env.REGISTRY }}/${{ env.IMAGE_NAME }},push-by-digest=true,name-canonical=true,push=true + cache-from: type=gha,scope=build-${{ env.PLATFORM_PAIR }} + cache-to: type=gha,scope=build-${{ env.PLATFORM_PAIR }},mode=max + sbom: true + provenance: true + + - name: Export digest + run: | + mkdir -p /tmp/digests + digest="${{ steps.build.outputs.digest }}" + touch "/tmp/digests/${digest#sha256:}" + + - name: Upload digest + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 + with: + name: digests-${{ env.PLATFORM_PAIR }} + path: /tmp/digests/* + if-no-files-found: error + retention-days: 1 + + merge: + needs: [prepare, build] + runs-on: ubuntu-latest + timeout-minutes: 10 + steps: + - name: Download digests + uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0 + with: + pattern: digests-* + path: /tmp/digests + merge-multiple: true + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@b5ca514318bd6ebac0fb2aedd5d36ec1b5c232a2 # v3.10.0 + + - name: Login to GitHub Container Registry + uses: docker/login-action@74a5d142397b4f367a81961eba4e8cd7edddf772 # v3.4.0 + with: + registry: ${{ env.REGISTRY }} + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Extract metadata for Docker + id: meta + uses: docker/metadata-action@902fa8ec7d6ecbf8d84d538b9b233a880e428804 # v5.7.0 + with: + images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} # All non-release actions will be tagged as `dev` (ie: push, workflow_dispatch) tags: | type=ref,event=tag @@ -51,29 +165,12 @@ jobs: flavor: | latest=auto - - name: Set up QEMU - uses: docker/setup-qemu-action@v3 + - name: Create manifest list and push + working-directory: /tmp/digests + run: | + docker buildx imagetools create $(jq -cr '.tags | map("-t " + .) | join(" ")' <<< "$DOCKER_METADATA_OUTPUT_JSON") \ + $(printf '${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}@sha256:%s ' *) - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v3 - - - name: Login to GitHub Container Registry - uses: docker/login-action@v3 - with: - registry: ghcr.io - username: ${{ github.actor }} - password: ${{ secrets.GITHUB_TOKEN }} - - - name: Build and Push - uses: docker/build-push-action@v6 - with: - context: . - file: ./docker/selfhosted.Dockerfile - # If the event is a release, use the release_arch, otherwise use the - # platforms input if present, falling back to dev_arch - platforms: ${{ github.event_name == 'release' && env.release_arch || (github.event.inputs.platforms || env.dev_arch) }} - push: true - tags: ${{ steps.meta.outputs.tags }} - labels: ${{ steps.meta.outputs.labels }} - cache-from: type=gha - cache-to: type=gha,mode=max + - name: Inspect image + run: | + docker buildx imagetools inspect ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.meta.outputs.version }}