Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add build flag similar to push flag #17

Closed
garethr opened this issue Mar 22, 2020 · 22 comments
Closed

Add build flag similar to push flag #17

garethr opened this issue Mar 22, 2020 · 22 comments
Milestone

Comments

@garethr
Copy link

garethr commented Mar 22, 2020

At present it's possible to set push to false and just build an image. This is useful when you want to test the image before pushing it. But when you do that, pushing becomes either a matter of doing so manually (potentially with multiple tags), or triggering the full action again, including a build.

It would be useful to run just the push action, maybe by adding a property for build that defaults to true?

@zappy-shu
Copy link
Contributor

Thanks for your feedback @garethr. I've put this suggestion onto the backlog and will discuss it with our PM 👍

@Jtalk
Copy link

Jtalk commented Apr 20, 2020

Implementing this one would help a lot with third party building tools, e.g. sbt's docker:publishLocal. Having your images built automatically by sbt while benefitting from a uniform tagging approach provided by this action would certainly bring it to the next level.

Perhaps a pair of separate actions for Docker push & Docker build?

@shankari
Copy link

@zappy-shu I was planning to volunteer to submit a PR for this, but I am not sure where the source code is. It looks like it uses the https://hub.docker.com/r/docker/github-actions container, but I don't see a dockerfile or source repo for it.

Please tell me that the default github actions are not closed source!

If you have a repo where the code is, I am happy to submit a PR.

@zappy-shu
Copy link
Contributor

zappy-shu commented Apr 23, 2020

@shankari the whole of docker's github action is open-source with the backend image being built from https://github.com/docker/github-actions. It's been separated for a few reasons, the main one being in case we wish to use the image as a backend for other actions. Please feel free to open a PR if you wish to contribute.

One of the big questions is how to deal with tags. The current flow of this action builds the image with all the tags defined in tags, tag_with_sha, and tag_with_ref depending on what the user sets the values to and then pushes all of them. With this the original image will have already been built and tagged by a previous step so we need to consider:

  • How to get the image's current tag?
  • What tags to tag the image with (this will most likely require retagging the image)?
  • What tags to push?

One thing I think is essential is for the action to output what tags it builds and/or pushes with as per #24. Most likely 2 outputs:

  • A version-tags output that is just the end of the tag (e.g. v1,v1.0.1)
  • A fully-qualified-tags output that has the whole tag (e.g. myreg/myorg/myrepo:v1,myreg/myorg/myrepo:v1.0.1)

A simple way to deal with it is to not bother with retagging and just try and push all the tags given. E.g.

# Builds the image and tags it as myorg/myrepo:foo and myorg/myrepo:{ref}
- name: build
  id: build
  uses: docker/build-push-action@v1
  with:
    repository: myorg/myrepo
    tags: foo
    tag_with_ref: true
    push: false

### Do other stuff

# Pushes the image with tags myorg/myrepo:foo and myorg/myrepo:{ref}
- name: push
  uses: docker/build-push-action@v1
  with:
    build: false
    username: ${{ secrets.DOCKER_USERNAME }}
    password: ${{ secrets.DOCKER_PASSWORD }}
    repository: myorg/myrepo
    tags: ${{ steps.build.outputs.version_tags }}

This is relatively simple but doesn't allow retagging between the build and push. Another option is to have some sort of "original image" input that is used simply to find the initial image in the push step which is then retagged and pushed with the new tags. E.g.

# Builds the image and tags it as myorg/myrepo:foo
- name: build
  id: build
  uses: docker/build-push-action@v1
  with:
    repository: myorg/myrepo
    tags: foo
    tag_with_ref: true
    push: false

### Do other stuff

# Pushes the image with tags myorg/myrepo:{ref}
- name: push
  uses: docker/build-push-action@v1
  with:
    username: ${{ secrets.DOCKER_USERNAME }}
    password: ${{ secrets.DOCKER_PASSWORD }}
    repository: myorg/myrepo
    original_image: ${{ steps.build.outputs.full_tags }}
    tag_with_ref: true

As an aside, because of build caching, rebuilding the image shouldn't actually cost that much time unless the steps between the initial build and the build-push break the cache somehow (modifying files or the like).

@nebuk89 any thoughts?

@garethr it'd be great to have your opinion on how you envisage the flow working as well

@khitrenovich
Copy link

The main drawback of rebuilding the image is that is breaks "build-test-promote" concept. In other words, you want to test what you've built before pushing and want to push exactly the image you tested.

@zappy-shu
Copy link
Contributor

@khitrenovich agreed. It's not ideal so was just a side note for those only worried about CI/CD time

@nebuk89
Copy link

nebuk89 commented Apr 23, 2020

We are still considering whether to do a separate build action or just have a build flag in this action (we will start the 'doing' very soon either way!) What do people prefer? 🤔
👍 for flag
🎉 for separate action

@garethr
Copy link
Author

garethr commented Apr 23, 2020

@zappy-shu I like the explicit nature of tags: ${{ steps.build.outputs.tags }}.

I think it's worth considering the various compositions here as well. ie.

  1. Only build
  2. Only push
  3. Build and push

This raises the question of, can you benefit from things like tag_with_ref if you're only pushing, or only building? If the answer is no, then to @nebuk89 point, maybe overloading the action isn't the way to go.

@shankari
Copy link

shankari commented Apr 23, 2020

This is relatively simple but doesn't allow retagging between the build and push. Another option is to have some sort of "original image" input that is used simply to find the initial image in the push step which is then retagged and pushed with the new tags. E.g.

When I volunteered to write the PR, I was planning to have an "original image" output from the build step that would be something like <name>:<sha> and then allow the user to specify additional tags as part of the push step.

@shankari
Copy link

We are still considering whether to do a separate build action or just have a build flag in this action (we will start the 'doing' very soon either way!) What do people prefer? 🤔

Will the "separate action" also have support for multiple repositories (e.g. dockerhub, github packages, etc)?

@Jtalk
Copy link

Jtalk commented Apr 23, 2020

Should we just provide 3 separate actions (push, build, build&push) based on the same underlying docker container (i.e. https://github.com/docker/github-actions)? I doubt it introducing a new input would do any good.

@dungahk
Copy link

dungahk commented Apr 25, 2020

I think having a new input is the way to go, it follows the same principles outlined here https://www.docker.com/blog/first-docker-github-action-is-here/

I do not have anything to add other than what they already said in the article.

sualeh added a commit to schemacrawler/SchemaCrawler that referenced this issue May 1, 2020
@sualeh
Copy link

sualeh commented May 8, 2020

@nebuk89 - do you have a timeline for resolution of this issue?

@ppmathis
Copy link

To add my two cents here, I'd definitely appreciate the option of specifying an original image, which then gets tagged according to the input parameters (e.g. static tags, tag by ref, tag by SHA, ...) and pushed to the repository. I think this is pretty much the second way which @zappy-shu proposed.

This would allow me to build the image myself in an earlier step with an action of my choice (e.g. whoan/docker-build-with-cache-action to save some time and resources) and then still make use of the automated tagging and pushing which this action provides. Currently there is no easy way to do so, especially when leveraging multi-stage builds as they'd require specifying explicit cache-from directives.

@patcon
Copy link

patcon commented May 27, 2020

@zappy-shu: As an aside, because of build caching, rebuilding the image shouldn't actually cost that much time unless the steps between the initial build and the build-push break the cache somehow (modifying files or the like).

When build is done with another tool, e.g. docker-compose, then in order to get a cache hit, the env variables in the tool (like an env_file for docker-compose) might be inconvenient to keep in sync with the env values injected into the github action config.

@crazy-max
Copy link
Member

crazy-max commented Sep 2, 2020

@crazy-max crazy-max added this to the v2 milestone Sep 2, 2020
@crazy-max
Copy link
Member

Version 2 has been merged to the main branch and is therefore available via uses: docker/build-push-action@v2 (mutable tag).

As a reminder, this new version changes drastically and works with 3 new actions (login, setup-buildx and setup-qemu) that we have created. Many usage examples have been added to handle most use cases.

And it should fix this current issue. Don't hesitate if you have any questions.

@kratsg
Copy link

kratsg commented Jul 14, 2022

I've been poring the docs trying to understand how to compose the original point of the issue and the current usage examples. Two of them are relevant but don't quite fully approach the options mentioned in #17 (comment).

The usage of testing before pushing shows an example of testing the image and then re-running build-push-action which uses an "internal cache", but this internal cache can't be used with something like sharing built image between jobs where you're loading it in a different job but not actually using the build-push-action anymore after that, so would re-running actually cause another build to happen?

If so, I don't understand how this resolves the issue where you want to be able to push a previously-built image, unless one is meant to make use of something like copy between registries where you use the tag-push-action to push your tags to different places. Am I misunderstanding the issue or how v2/3 works?

@dhess
Copy link

dhess commented Jul 19, 2022

Agreed — I don't think this issue should have been marked as closed, as there's no way to skip a build and only push.

@LeviPesin
Copy link

Maybe build flag could be introduced with functionality like that build: false, push: true does only image tagging and the push? So it is equivalent to something like this:

while IFS= read -r tag; do
  docker tag ${{ env.IMAGE_NAME }}:${{ env.DUMMY_TAG }} "$tag"
done <<< "${{ needs.metadata.outputs.tags }}"
docker push -a ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}

(where ${{ env.IMAGE_NAME }}:${{ env.DUMMY_TAG }} is loaded by an action's user by a command like docker load --input /tmp/image.tar before)

/ping @crazy-max

@LeviPesin
Copy link

Here is my current workaround:

push:
  if: github.event_name != 'pull_request'
  needs: [metadata]
  name: Push Docker image to the Container registry (GitHub Packages)
  runs-on: ubuntu-latest
  permissions:
    packages: write
  steps:
    - name: Download Docker image
      uses: actions/download-artifact@9782bd6a9848b53b110e712e20e42d89988822b7
      with:
        name: Docker image
        path: /tmp
    - name: Load image
      run: docker load --input /tmp/image.tar
    - name: Log in to the Container registry
      uses: docker/login-action@f4ef78c080cd8ba55a85445d5b36e214a81df20a
      with:
        registry: ${{ env.REGISTRY }}
        username: ${{ github.actor }}
        password: ${{ secrets.GITHUB_TOKEN }}
    - name: Tag Docker image properly
      run: |
        while IFS= read -r tag; do
          echo "Tagging image $tag"
          docker tag ${{ env.IMAGE_NAME }}:test "$tag"
        done <<< "${{ needs.metadata.outputs.tags }}"
    - name: Push Docker image
      run: docker push -a ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}

@LeviPesin
Copy link

@crazy-max Can you please reopen this issue?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests