From 37eb08ef43e7f6b1b67ed12eb2ff6564037156a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Strausmann?= Date: Sun, 10 May 2026 20:48:37 +0000 Subject: [PATCH] fix(ci): lowercase image ref before push-by-digest MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit GitHub stores the repo path with the casing the user picked. Our repo is `strausmann/Label-Printer-Hub`, so `${{ github.repository }}` keeps the capital L/P/H. Docker/OCI registry references MUST be all-lowercase, or buildx rejects the push with: ERROR: failed to build: failed to solve: failed to parse ref "ghcr.io/strausmann/Label-Printer-Hub-frontend": invalid reference format: repository name (strausmann/Label-Printer-Hub-frontend) must be lowercase The old workflow accidentally side-stepped this because `docker/metadata-action` lowercases `images:` for its own outputs. The new pipeline pushes by digest via `build-push-action`'s `outputs: name=…` field, which is a raw passthrough — the casing from `${{ github.repository }}` reached buildx unchanged. Both phases (build and merge) now have a `Compute lowercase image ref` step that uses bash's `${VAR,,}` lowercase expansion, and reference that step's output everywhere a registry ref appears. --- .github/workflows/docker-publish.yml | 35 ++++++++++++++++++++++++---- 1 file changed, 30 insertions(+), 5 deletions(-) diff --git a/.github/workflows/docker-publish.yml b/.github/workflows/docker-publish.yml index 00cb50d..47fd6f0 100644 --- a/.github/workflows/docker-publish.yml +++ b/.github/workflows/docker-publish.yml @@ -72,6 +72,20 @@ jobs: - name: Verify Dockerfile exists for ${{ matrix.service }} run: test -f "${{ matrix.service }}/Dockerfile" + # GitHub's repo path retains the user's original capitalisation + # (`strausmann/Label-Printer-Hub`), but Docker/OCI registry refs MUST + # be all-lowercase. `docker/metadata-action` does this implicitly for + # its own outputs, but `build-push-action`'s `outputs: name=…` is a + # raw passthrough — we have to lowercase the path ourselves before + # using it in the digest-push reference and in the merge step. + - name: Compute lowercase image ref + id: image + env: + REPO: ${{ github.repository }} + run: | + repo_lc="${REPO,,}" + echo "ref=${{ env.REGISTRY_GHCR }}/${repo_lc}-${{ matrix.service }}" >> "$GITHUB_OUTPUT" + - name: Set up Docker Buildx uses: docker/setup-buildx-action@v4 @@ -112,7 +126,7 @@ jobs: uses: docker/metadata-action@v6 with: images: | - ${{ env.REGISTRY_GHCR }}/${{ github.repository }}-${{ matrix.service }} + ${{ steps.image.outputs.ref }} labels: | org.opencontainers.image.title=label-printer-hub-${{ matrix.service }} org.opencontainers.image.description=Self-hosted label printer hub for Brother PT/QL series — ${{ matrix.service }} container @@ -139,8 +153,10 @@ jobs: labels: ${{ steps.meta.outputs.labels }} # `push-by-digest=true` skips the tag write and returns digest in # `steps.build.outputs.digest`. `name-canonical=true` makes the - # registry reference the image by its canonical name. - outputs: type=image,name=${{ env.REGISTRY_GHCR }}/${{ github.repository }}-${{ matrix.service }},push-by-digest=true,name-canonical=true,push=true + # registry reference the image by its canonical name. The image + # ref MUST be lowercase — see the `Compute lowercase image ref` + # step above. + outputs: type=image,name=${{ steps.image.outputs.ref }},push-by-digest=true,name-canonical=true,push=true build-args: | VERSION=${{ steps.tag.outputs.tag }} REVISION=${{ github.sha }} @@ -192,6 +208,15 @@ jobs: path: /tmp/digests merge-multiple: true + # Mirror of the build-phase lowercase step (see comment there). + - name: Compute lowercase image ref + id: image + env: + REPO: ${{ github.repository }} + run: | + repo_lc="${REPO,,}" + echo "ref=${{ env.REGISTRY_GHCR }}/${repo_lc}-${{ matrix.service }}" >> "$GITHUB_OUTPUT" + - name: Set up Docker Buildx uses: docker/setup-buildx-action@v4 @@ -231,7 +256,7 @@ jobs: uses: docker/metadata-action@v6 with: images: | - ${{ env.REGISTRY_GHCR }}/${{ github.repository }}-${{ matrix.service }} + ${{ steps.image.outputs.ref }} ${{ secrets.DOCKERHUB_USERNAME && format('docker.io/{0}/label-printer-hub-{1}', secrets.DOCKERHUB_USERNAME, matrix.service) || '' }} # Same tag scheme as before: # 1.0.0 full semver (always) @@ -262,7 +287,7 @@ jobs: - name: Create manifest list and push working-directory: /tmp/digests env: - DIGEST_REPO: ${{ env.REGISTRY_GHCR }}/${{ github.repository }}-${{ matrix.service }} + DIGEST_REPO: ${{ steps.image.outputs.ref }} TAGS: ${{ steps.meta.outputs.tags }} ANNOTATIONS: ${{ steps.meta.outputs.annotations }} run: |