gh-action-pypi-publish icon indicating copy to clipboard operation
gh-action-pypi-publish copied to clipboard

Build Docker image and push to GHCR

Open br3ndonland opened this issue 1 year ago • 15 comments

Description

Closes #58

Up to this point, the project has been set up as a Docker action referencing the Dockerfile.

https://github.com/pypa/gh-action-pypi-publish/blob/3fbcf7ccf443305955ce16db9de8401f7dc1c7dd/action.yml#L86-L88

The downside to using the Dockerfile for the action is that the Docker image must be built every time the action is used (#58).

This PR will set up the project to build the Docker image and push it to GitHub Container Registry (GHCR). This change will speed up user workflows every time the action is used because the workflows will simply pull the Docker image from GHCR instead of building again.

Changes

Build container image with GitHub Actions

This PR will build Docker images with the Docker CLI (docker build). Builds will include inline cache metadata so layers can be reused by future builds.

This PR only proposes to build container images for x86_64 (linux/amd64) because GitHub Actions Linux runners currently only support x86_64 CPU architectures (actions/runner-images#5631), and this project only supports GitHub Actions Linux runners. The README explains:

Since this GitHub Action is docker-based, it can only be used from within GNU/Linux based jobs in GitHub Actions CI/CD workflows. This is by design and is unlikely to change due to a number of considerations we rely on.

Push container image to GHCR

The workflow will log in to GHCR using the built-in GitHub token and push the Docker image. Workflow runs triggered by pull requests will build the Docker image and run the smoke tests but will not push the Docker image.

Update action to pull container image from GHCR

Docker actions support pulling in pre-built Docker images by supplying a registry address to the image: key. The downside to this syntax is that there's no way to specify the correct Docker tag because the GitHub Actions image: and uses: keys don't accept any context. For example, if a user's workflow has uses: pypa/gh-action-pypi-publish@release/v1.8, then the action should pull in a Docker image built from the release/v1.8 ref, something like ghcr.io/pypa/gh-action-pypi-publish:release-v1.8 (Docker tags can't have /).

# this works but the image tag can't be customized
runs:
  using: docker
  image: docker://ghcr.io/pypa/gh-action-pypi-publish:release-v1.8
# this doesn't work because `image:` doesn't support context
runs:
  using: docker
  image: docker://ghcr.io/pypa/gh-action-pypi-publish:${{ github.action_ref }}

The workaround is to switch the top-level action.yml to a composite action that then calls the Docker action, substituting the correct image name and tag.

Related

br3ndonland avatar Apr 19 '24 01:04 br3ndonland

This looks.. intriguing! I don't remember if I ever considered combining composite+docker actions (I did play with having two composites in the same repo in the past, though).

I'll need to take some time to think about it and look through the patch more closely. Please, don't expect an immediate review, however it does look very promising at glance!

Originally I thought that I'd have a workflow where I trigger a release, that release adds a commit that hardcodes an update to action.yml with the "future" version tag, tags that commit and pushes it (post docker publish). It wouldn't be on the main branch, the tags would be on the orphaned leaves.

This looks like a better idea so far. Thanks again!

webknjaz avatar Apr 25 '24 01:04 webknjaz

That sounds great. Take your time. Thanks for your consideration.

If you do decide to accept this change, I'm happy to help maintain the workflows in the future. Feel free to mention me @br3ndonland and I will help address any issues that come up.

br3ndonland avatar Apr 26 '24 23:04 br3ndonland

Thanks! I've hit "rebase" on the UI to get this on top of the recent changes/linting/lockfile bumps but haven't yet looked into it deeper.

webknjaz avatar May 16 '24 15:05 webknjaz

I'm done with the initial review. More is needed, but I'd rather accept what I can through separate PRs to make this one smaller. And the suggested refactoring could be done in parallel. I think that generating the file is a good idea. It should be possible to write the file without bringing in the PyYAML dependency. But it's not that easy for reading it. Can we make use of yq somehow, and convert YAML to JSON this way, maybe?

webknjaz avatar May 16 '24 20:05 webknjaz

@webknjaz thank you for your detailed review. I've addressed most of your comments so far.

br3ndonland avatar May 27 '24 20:05 br3ndonland

Commits like 213c885ac41d769527ac150e2e633bb1ccd886d4 aren't really necessary since Git would automatically absorb changes applied separately. FYI. In fact, this one may have a harmful effect — when the label change is merged into the default branch, and this one rebased on top, Git will keep the removal commit and attempt deleting the label :man_shrugging:

Anyway, we'll address this later on.

webknjaz avatar May 29 '24 14:05 webknjaz

@br3ndonland I'm sure my review is incomplete, but hopefully it gives you enough ideas to try out until the next time.

I think it'd be nice to get this in before #236 if at all possible.

webknjaz avatar May 29 '24 20:05 webknjaz

@br3ndonland could you also rebase this branch locally? The GH button doesn't work, meaning there's going to be some conflicts to resolve.

webknjaz avatar May 29 '24 20:05 webknjaz

@br3ndonland could you also rebase this branch locally? The GH button doesn't work, meaning there's going to be some conflicts to resolve.

No problem. I'm not sure what "the GH button" is (some GitHub Mobile thing?) but I've rebased the branch.

I will address the other comments soon. Looks like there's a small git fetch issue in the smoke test workflow so I will look into that as well.

br3ndonland avatar May 31 '24 01:05 br3ndonland

I was able to get it to work by dumping JSON to a .yml file. The file must have a .yml or .yaml extension (GitHub Actions will raise "Error: Can't find 'action.yml', 'action.yaml' or 'Dockerfile'" on .json files), but the file contents can be JSON.

br3ndonland avatar Jun 01 '24 21:06 br3ndonland

I was able to get it to work by dumping JSON to a .yml file. The file must have a .yml or .yaml extension (GitHub Actions will raise "Error: Can't find 'action.yml', 'action.yaml' or 'Dockerfile'" on .json files), but the file contents can be JSON.

Great! That's what I expected since that JSON is still valid YAML and a YAML parser can read it.

webknjaz avatar Jun 05 '24 19:06 webknjaz

No problem. I'm not sure what "the GH button" is (some GitHub Mobile thing?) but I've rebased the branch.

Oh, it's usually present on the web UI. Might be missing from mobile. Sometimes its presence is conditional. It shows up somewhere right to the “Merge” button in PRs where you have the write privilege.

webknjaz avatar Jun 05 '24 19:06 webknjaz

@webknjaz thanks again for your detailed review so far.

How are things looking to you? Any further suggestions you would like me to look at? You mentioned reusable workflows https://github.com/pypa/gh-action-pypi-publish/pull/230#discussion_r1603922187. Anything else?

If/when you merge this PR, I am willing to switch my projects over to the unstable/v1 branch to verify the action works as expected.

br3ndonland avatar Jun 11 '24 17:06 br3ndonland

@br3ndonland this also needs to be rebased now that the attestations PR is in.

webknjaz avatar Sep 04 '24 13:09 webknjaz