docker / build-push-action

GitHub Action to build and push Docker images with Buildx
https://github.com/marketplace/actions/build-and-push-docker-images
Apache License 2.0
4.28k stars 548 forks source link

Errors while building such as "`ERROR: failed to parse source "conversions\"", valid sources are digests, references and descriptors: invalid reference format`" #1200

Open jimisola opened 1 month ago

jimisola commented 1 month ago

Contributing guidelines

I've found a bug, and:

Description

I recently did a few changes to https://github.com/unoconv/unoserver-docker such as as:

I think I have reverted all changes but the upgrade of build-push-action but still get errors in the workflow:

  1. ERROR: failed to parse source "LibreOffice", valid sources are digests, references and descriptors: invalid reference format: repository name (library/LibreOffice) must be lowercase
  2. ERROR: "failed to parse source "conversions\"", valid sources are digests, references and descriptors: invalid reference format" possibly after upgrading

The LibreOffice seems be related to this:

outputs: type=image,name=${{ env.REGISTRY }}/${{ env.IMAGE_NAME }},push-by-digest=true,name-canonical=true,annotation-index.org.opencontainers.image.description=Container image that contains unoserver and LibreOffice incl a large set of fonts for file format conversions

That is, "LibreOffice" in the description! I removed that and error 1 goes away.

However, I'm unable to figure out error #2 regarding conversions.

Any ideas on what can be causing this error, this worked before (to my knowledge) and I've used the github example from the official docker manual.

Expected behaviour

The build is successful generating two images.

Actual behaviour

The build fails during Create manifest list and push with:

ERROR: failed to parse source "conversions\"", valid sources are digests, references and descriptors: invalid reference format

Repository URL

https://github.com/unoconv/unoserver-docker

Workflow run URL

https://github.com/unoconv/unoserver-docker/blob/main/.github/workflows/publish-containers.yml

YAML workflow

name: Publish container image to GHCR

on:
  release:
    types:
      - created

env:
  REGISTRY: ghcr.io
  IMAGE_NAME: ${{ github.repository }}

jobs:
  build-n-push-digest:
    runs-on: ubuntu-latest
    permissions:
      contents: read
      packages: write
      id-token: write

    strategy:
      fail-fast: false
      matrix:
        platform:
          - linux/arm64
          - linux/amd64

    steps:
      - name: Prepare
        run: |
          platform=${{ matrix.platform }}
          echo "PLATFORM_PAIR=${platform//\//-}" >> $GITHUB_ENV

      - name: Checkout repository
        uses: actions/checkout@v4

      - name: Extract container metadata
        id: meta
        uses: docker/metadata-action@v5
        with:
          images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
          tags: |
            type=schedule
            type=ref,event=branch
            type=ref,event=pr
            type=semver,pattern={{version}}
        env:
          DOCKER_METADATA_ANNOTATIONS_LEVELS: manifest,index

      - name: Set up QEMU
        uses: docker/setup-qemu-action@v3

      - name: Setup Docker buildx
        uses: docker/setup-buildx-action@v3

      - name: Login to image registry ${{ env.REGISTRY }}
        uses: docker/login-action@v3
        with:
          registry: ${{ env.REGISTRY }}
          username: ${{ github.actor }}
          password: ${{ secrets.GITHUB_TOKEN }}

      - name: Build and push by digest
        id: build
        uses: docker/build-push-action@v6
        with:
          context: .
          push: true
          platforms: ${{ matrix.platform }}
          labels: ${{ steps.meta.outputs.labels }}
          annotations: ${{ steps.meta.outputs.annotations }}
          provenance: mode=max
          sbom: true
          outputs: type=image,name=${{ env.REGISTRY }}/${{ env.IMAGE_NAME }},push-by-digest=true,name-canonical=true,annotation-index.org.opencontainers.image.description=Container image that contains unoserver and libreoffice incl a large set of fonts for file format conversions
        env:
          DOCKER_METADATA_ANNOTATIONS_LEVELS: manifest,index

      - 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@v4
        with:
          name: digests-${{ env.PLATFORM_PAIR }}
          path: /tmp/digests/*
          if-no-files-found: error
          retention-days: 1

  merge:
    runs-on: ubuntu-latest
    needs:
      - build-n-push-digest
    steps:
      - name: Download digests
        uses: actions/download-artifact@v4
        with:
          path: /tmp/digests
          pattern: digests-*
          merge-multiple: true

      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v3

      - name: Docker meta
        id: meta
        uses: docker/metadata-action@v5
        with:
          images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
          tags: |
            type=schedule
            type=ref,event=branch
            type=ref,event=pr
            type=semver,pattern={{version}}
          annotations: |
            org.opencontainers.image.description=Container image that contains unoserver and libreoffice including large set of fonts for file format conversions
            org.opencontainers.image.licenses=MIT
            org.opencontainers.image.source=https://github.com/unoconv/unoserver-docker
        env:
          DOCKER_METADATA_ANNOTATIONS_LEVELS: manifest,index

      - name: Login to image registry ${{ env.REGISTRY }}
        uses: docker/login-action@v3
        with:
          registry: ${{ env.REGISTRY }}
          username: ${{ github.actor }}
          password: ${{ secrets.GITHUB_TOKEN }}

      - name: Debug info 1
        working-directory: /tmp/digests
        run: ls -la

      - name: Debug info 2
        working-directory: /tmp/digests
        run: |
          echo "Listing files in the directory and outputting their contents:"

          # Define the directory path
          DIRECTORY_PATH=.

          # List files in the directory and save to file_list.txt
          ls -la $DIRECTORY_PATH > file_list.txt

          # Output content of each file and save to output.txt
          for file in $(ls $DIRECTORY_PATH); do
            echo "Contents of $DIRECTORY_PATH/$file:" >> output.txt
            echo "$DIRECTORY_PATH/$file:" >> output.txt
            cat $DIRECTORY_PATH/$file >> output.txt
            echo "\n\n" >> output.txt
          done

      - name: Create manifest list and push
        working-directory: /tmp/digests
        run: |
          docker buildx imagetools create \
            $(echo $DOCKER_METADATA_OUTPUT_JSON | jq -cr '.tags | map("-t " + .) | join(" ")') \
            $(echo $DOCKER_METADATA_OUTPUT_JSON | jq -r '.annotations | map("--annotation \"" + . + "\"") | join(" ")') \
            $(printf '${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}@sha256:%s ' *)

      - name: Inspect image
        run: |
          docker buildx imagetools inspect ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.meta.outputs.version }}
yaml

Workflow logs

logs_26787841608.zip

BuildKit logs

Post job cleanup.
BuildKit container logs
  /usr/bin/docker logs buildx_buildkit_builder-7a5587eb-1e2a-4771-9d78-eb611f6bbc570
  time="2024-08-05T00:10:12Z" level=info msg="auto snapshotter: using overlayfs"
  time="2024-08-05T00:10:12Z" level=warning msg="using host network as the default"
  time="2024-08-05T00:10:12Z" level=info msg="found worker \"kzyb9ltwy9wmxjvqg0injjsyb\", labels=map[org.mobyproject.buildkit.worker.executor:oci org.mobyproject.buildkit.worker.hostname:5cfb69ae1535 org.mobyproject.buildkit.worker.network:host org.mobyproject.buildkit.worker.oci.process-mode:sandbox org.mobyproject.buildkit.worker.selinux.enabled:false org.mobyproject.buildkit.worker.snapshotter:overlayfs], platforms=[linux/amd64 linux/amd64/v2 linux/amd64/v3 linux/386]"
  time="2024-08-05T00:10:12Z" level=warning msg="skipping containerd worker, as \"/run/containerd/containerd.sock\" does not exist"
  time="2024-08-05T00:10:12Z" level=info msg="found 1 workers, default=\"kzyb9ltwy9wmxjvqg0injjsyb\""
  time="2024-08-05T00:10:12Z" level=warning msg="currently, only the default worker can be used."
  time="2024-08-05T00:10:12Z" level=info msg="running server on /run/buildkit/buildkitd.sock"
Removing builder
Cleaning up certificates
Post cache


### Additional info

_No response_
crazy-max commented 1 month ago

Similar to https://github.com/docker/build-push-action/issues/1201#issuecomment-2269611346

You should put quotes to set the annotation because here spaces are not escaped:

outputs: type=image,name=${{ env.REGISTRY }}/${{ env.IMAGE_NAME }},push-by-digest=true,name-canonical=true,"annotation-index.org.opencontainers.image.description=Container image that contains unoserver and libreoffice incl a large set of fonts for file format conversions"
jimisola commented 1 month ago

@crazy-max Thanks for the quick response. I've tried that before and it didn't work then and, sadly, didn't work now.

I just changed back to that again but the pipeline failed with the same error (unless I made a mistake there).

I'll try with quotation in the metadata action as well: https://github.com/unoconv/unoserver-docker/blob/main/.github/workflows/publish-containers.yml#L119

And the docker buildx imagetools create command is correctly escaped?

crazy-max commented 1 month ago

I just changed back to that again but the pipeline failed with the same error (unless I made a mistake there).

Ok it looks good for build-push-action step: https://github.com/unoconv/unoserver-docker/actions/runs/10253836683/job/28367364042#step:8:233

But fails for imagetools create: https://github.com/unoconv/unoserver-docker/actions/runs/10253836683/job/28367431409#step:8:2

Can you make this change in "Create manifest list and push" step:

      - name: Create manifest list and push
        working-directory: /tmp/digests
        run: |
          set +ex
          docker buildx imagetools create \
            $(echo $DOCKER_METADATA_OUTPUT_JSON | jq -cr '.tags | map("-t " + .) | join(" ")') \
            $(echo $DOCKER_METADATA_OUTPUT_JSON | jq -r '.annotations | map("--annotation \"" + . + "\"") | join(" ")') \
            $(printf '${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}@sha256:%s ' *)
jimisola commented 1 month ago

Ok it looks good for build-push-action step: https://github.com/unoconv/unoserver-docker/actions/runs/10253836683/job/28367364042#step:8:233

Good. However, the buildx build has arguments like

"--annotation manifest:org.opencontainers.image.description=Docker files for a dockerized unoserver "

Does not these descriptions needs to be in quotation as well?

But fails for imagetools create: https://github.com/unoconv/unoserver-docker/actions/runs/10253836683/job/28367431409#step:8:2

Can you make this change in "Create manifest list and push" step:

      - name: Create manifest list and push
        working-directory: /tmp/digests
        run: |
          set +ex
          docker buildx imagetools create \
            $(echo $DOCKER_METADATA_OUTPUT_JSON | jq -cr '.tags | map("-t " + .) | join(" ")') \
            $(echo $DOCKER_METADATA_OUTPUT_JSON | jq -r '.annotations | map("--annotation \"" + . + "\"") | join(" ")') \
            $(printf '${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}@sha256:%s ' *)

Of course, here is the log.

The description now contains LibreOffice in capital letters as it should be.

What are we looking after btw? I reckon there is something wrong with the quotation and escaping \" or?

"org.opencontainers.image.version":"0.4.0-rc15"},"annotations":["manifest:org.opencontainers.image.created=2024-08-06T07:58:47.672Z","manifest:org.opencontainers.image.description=\"Container image that contains unoserver and LibreOffice including large set of fonts for file format conversions\""

First time I created this I spent hours getting this to work due to qoutation issues. It seems as if this pattern (multi platform) is used by many. A composite github action would probably come in handy.

crazy-max commented 1 month ago

Good. However, the buildx build has arguments like

"--annotation manifest:org.opencontainers.image.description=Docker files for a dockerized unoserver "

Quotes are not shown here because it displays list of args being joined. You can enable debug in your workflow to see the list of inputs to make sure of it by setting ACTIONS_STEP_DEBUG to true as action secret: https://docs.github.com/en/actions/monitoring-and-troubleshooting-workflows/troubleshooting-workflows/enabling-debug-logging#enabling-step-debug-logging

You should see this specific log: https://github.com/docker/build-push-action/blob/a8d35412fb758de9162fd63e3fa3f0942bdedb4d/src/main.ts#L96

Of course, here is the log.

Wrong syntax my bad, should be:

      - name: Create manifest list and push
        working-directory: /tmp/digests
        run: |
          set -ex
          docker buildx imagetools create \
            $(echo $DOCKER_METADATA_OUTPUT_JSON | jq -cr '.tags | map("-t " + .) | join(" ")') \
            $(echo $DOCKER_METADATA_OUTPUT_JSON | jq -r '.annotations | map("--annotation \"" + . + "\"") | join(" ")') \
            $(printf '${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}@sha256:%s ' *)
jimisola commented 1 month ago

I've enabled log create manifest list and push.

Changed the syntax with latest log here

jimisola commented 1 month ago

--annotation '"manifest:org.opencontainers.image.description="Container' image that contains unoserver and LibreOffice including large set of fonts for file format 'conversions""'

The quotation is way off here.

  1. There is a single quotation mark ' that start after --annotation ends efter ="Container. Is that the source of our problems?

  2. There 2 x double quotation marks. i. The whole string "manifest[...]conversions" ii. The description text "Container[...]conversions"

crazy-max commented 1 month ago

--annotation '"manifest:org.opencontainers.image.description="Container' image that contains unoserver and LibreOffice including large set of fonts for file format 'conversions""'

The quotation is way off here.

1. There is a single quotation mark `'` that start after _--annotation_ ends efter `="Container`. Is that the source of our problems?

2. There 2 x double quotation marks.
   i. The whole string "manifest[...]conversions"
   ii. The description text "Container[...]conversions"

Yes looks like it:

image

jimisola commented 1 month ago

Is this an issue/bug with docker actions or something I can do in the workflow?

crazy-max commented 1 month ago

I don't think that's an issue with the action or buildx but within your workflow with command in "Create manifest list and push" step. I think it needs some changes in jq syntax but not sure what atm.

jimisola commented 1 month ago

Ok. I'm thinking that this is quite common use-case since it's in the official docs with the exception then of the annotations which is needed for github to present it correctly under Releases. So, I'm wondering how others got this working.

That said, I'm not entirely sure that the issue is with the jq command - it could be that as well, but I think that there is a bug already when creating the DOCKER_METADATA_OUTPUT_JSON.

from the log:

+ docker buildx imagetools create -t ghcr.io/unoconv/unoserver-docker:0.4.0-rc17 --annotation '"manifest:org.opencontainers.image.created=2024-08-06T09:13:07.118Z"' --annotation '"manifest:org.opencontainers.image.description="Container' image that contains unoserver and LibreOffice including large set of fonts for file format 'conversions""' --annotation '"manifest:org.opencontainers.image.licenses=MIT"' --annotation '"manifest:org.opencontainers.image.revision=f5002ca8d75a2827ca57bd545a10e26208481b5a"' --annotation '"manifest:org.opencontainers.image.source=https://github.com/unoconv/unoserver-docker"' --annotation '"manifest:org.opencontainers.image.title=unoserver-docker"' --annotation '"manifest:org.opencontainers.image.url=https://github.com/unoconv/unoserver-docker"' --annotation '"manifest:org.opencontainers.image.version=0.4.0-rc17"' --annotation '"index:org.opencontainers.image.created=2024-08-06T09:13:07.118Z"' --annotation '"index:org.opencontainers.image.description="Container' image that contains unoserver and LibreOffice including large set of fonts for file format 'conversions""' --annotation '"index:org.opencontainers.image.licenses=MIT"' --annotation '"index:org.opencontainers.image.revision=f5002ca8d75a2827ca57bd545a10e26208481b5a"' --annotation '"index:org.opencontainers.image.source=https://github.com/unoconv/unoserver-docker"' --annotation '"index:org.opencontainers.image.title=unoserver-docker"' --annotation '"index:org.opencontainers.image.url=https://github.com/unoconv/unoserver-docker"' --annotation '"index:org.opencontainers.image.version=0.4.0-rc17"' ghcr.io/unoconv/unoserver-docker@sha256:18bbabd9a1721fdd2fcfd356e8961f073e9bbcd056ab8de38e59ca2b8de9d76c ghcr.io/unoconv/unoserver-docker@sha256:86fa6b1bc57bc7573787372b359fc33bfc4be4fc55cefe87a3b62e32aabdc0fb ghcr.io/unoconv/unoserver-docker@sha256:file_list.txt ghcr.io/unoconv/unoserver-docker@sha256:output.txt

we can conclude that --annotations have double qoutation, both single and double, e.g.

a. --annotation '"manifest:org.opencontainers.image.created=2024-08-06T09:13:07.118Z"'

and as mentioned in my previous comment:

b. --annotation '"manifest:org.opencontainers.image.description="Container' image that contains unoserver and LibreOffice including large set of fonts for file format 'conversions""'

My questions are:

  1. Why are there double quotations as in a?
  2. Why is the single quotation in b directly after Container and not at EOL?
  3. Could it be that we that value in DOCKER_METADATA_OUTPUT_JSON should not have the description escaped since the whole value, i.e.

image

more importantly this escaping of the property value (=Container...:

image

is not made by the option with.outputs for docker/build-push-action@v6. It however, seems to be created by that action and it's not clear to me why. That is, docker/build-push-action@v6 does not handle the quotation in outputs currently but adds extra escaping that then causes issues further down the flow.

DOCKER_METADATA_OUTPUT_JSON: {"tags":["ghcr.io/unoconv/unoserver-docker:0.4.0-rc17"],"labels":{"org.opencontainers.image.created":"2024-08-06T09:13:07.118Z","org.opencontainers.image.description":"Docker files for a dockerized unoserver","org.opencontainers.image.licenses":"MIT","org.opencontainers.image.revision":"f5002ca8d75a2827ca57bd545a10e26208481b5a","org.opencontainers.image.source":"https://github.com/unoconv/unoserver-docker","org.opencontainers.image.title":"unoserver-docker","org.opencontainers.image.url":"https://github.com/unoconv/unoserver-docker","org.opencontainers.image.version":"0.4.0-rc17"},"annotations":["manifest:org.opencontainers.image.created=2024-08-06T09:13:07.118Z","manifest:org.opencontainers.image.description=\"Container image that contains unoserver and LibreOffice including large set of fonts for file format conversions\"","manifest:org.opencontainers.image.licenses=MIT","manifest:org.opencontainers.image.revision=f5002ca8d75a2827ca57bd545a10e26208481b5a","manifest:org.opencontainers.image.source=https://github.com/unoconv/unoserver-docker","manifest:org.opencontainers.image.title=unoserver-docker","manifest:org.opencontainers.image.url=https://github.com/unoconv/unoserver-docker","manifest:org.opencontainers.image.version=0.4.0-rc17","index:org.opencontainers.image.created=2024-08-06T09:13:07.118Z","index:org.opencontainers.image.description=\"Container image that contains unoserver and LibreOffice including large set of fonts for file format conversions\"","index:org.opencontainers.image.licenses=MIT","index:org.opencontainers.image.revision=f5002ca8d75a2827ca57bd545a10e26208481b5a","index:org.opencontainers.image.source=https://github.com/unoconv/unoserver-docker","index:org.opencontainers.image.title=unoserver-docker","index:org.opencontainers.image.url=https://github.com/unoconv/unoserver-docker","index:org.opencontainers.image.version=0.4.0-rc17"]}

One workaround might be to remove \" in DOCKER_METADATA_OUTPUT_JSON and only allow one occurrence of quotation?

jimisola commented 1 month ago

@crazy-max Will you be able to continue co-operation on finding the issue? Not only would I like to solve it I would also like to document it for others since it's a quite common use-case.