name: Release web image # Builds ghcr.io/mountain-loop/yaak-web: the browser client and the server that serves it. # One image per architecture on its own native runner (emulating a Rust release build is hours), # joined into one multi-arch tag at the end. on: push: tags: [v*] workflow_dispatch: inputs: version: description: Version to publish, without the v (e.g. 2026.2.0). Empty publishes main and sha tags only. required: false type: string permissions: contents: read packages: write env: IMAGE: ghcr.io/mountain-loop/yaak-web jobs: build: if: github.repository == 'mountain-loop/yaak' name: Build ${{ matrix.platform }} runs-on: ${{ matrix.runner }} strategy: fail-fast: false matrix: include: - platform: linux/amd64 runner: ubuntu-22.04 arch: amd64 - platform: linux/arm64 runner: ubuntu-22.04-arm arch: arm64 steps: - name: Checkout uses: actions/checkout@v4 - name: Set up Buildx uses: docker/setup-buildx-action@v3 - name: Log in to GHCR uses: docker/login-action@v3 with: registry: ghcr.io username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} - name: Build and push by digest id: build uses: docker/build-push-action@v6 with: context: . file: Dockerfile.web platforms: ${{ matrix.platform }} outputs: type=image,name=${{ env.IMAGE }},push-by-digest=true,name-canonical=true,push=true - name: Export digest run: | mkdir -p "${{ runner.temp }}/digests" digest="${{ steps.build.outputs.digest }}" touch "${{ runner.temp }}/digests/${digest#sha256:}" - name: Upload digest uses: actions/upload-artifact@v4 with: name: digest-${{ matrix.arch }} path: ${{ runner.temp }}/digests/* if-no-files-found: error retention-days: 1 publish: name: Publish manifest needs: build runs-on: ubuntu-latest steps: - name: Download digests uses: actions/download-artifact@v4 with: path: ${{ runner.temp }}/digests pattern: digest-* merge-multiple: true - name: Set up Buildx uses: docker/setup-buildx-action@v3 - name: Log in to GHCR uses: docker/login-action@v3 with: registry: ghcr.io username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} # `latest` follows a release tag, and a manual run that names a version — the way to # publish before the first release. A prerelease (v2026.2.1-beta.1) never takes it. - name: Tags id: meta uses: docker/metadata-action@v5 with: images: ${{ env.IMAGE }} flavor: latest=false tags: | type=semver,pattern={{version}} type=raw,value=${{ inputs.version }},enable=${{ inputs.version != '' }} type=raw,value=latest,enable=${{ inputs.version != '' || (github.event_name == 'push' && !contains(github.ref_name, '-')) }} type=ref,event=branch type=sha,format=short - name: Create and push the manifest working-directory: ${{ runner.temp }}/digests run: | docker buildx imagetools create \ $(jq -cr '.tags | map("-t " + .) | join(" ")' <<< "$DOCKER_METADATA_OUTPUT_JSON") \ $(printf '${{ env.IMAGE }}@sha256:%s ' *) - name: Inspect run: docker buildx imagetools inspect ${{ env.IMAGE }}:${{ steps.meta.outputs.version }}