I’m building a new GitHub workflow (my first), which currently consists of 2 simple jobs:
- Build a Docker image for the Django application.
- Run our Django tests inside the Docker image that was just build.
But I’ve run into a problem referencing the image from the first job correctly in the second job.
My workflow.yml
file looks like this:
# Inspired by:
# <https://docs.github.com/en/actions/publishing-packages/publishing-docker-images>
# and the "Django test" workflow template from GitHub.
name: Build and test
on:
push:
branches:
- master
- development
- "feature/**"
env:
REGISTRY: ghcr.io
IMAGE_NAME: ${{ github.repository }}
jobs:
build-and-push-docker-image:
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
steps:
- name: Checkout repository
uses: actions/checkout@v2
- name: Log in to the Container registry
uses: docker/login-action@f054a8b539a109f9f41c372932f1ae047eff08c9
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Extract metadata for Docker image
id: meta
uses: docker/metadata-action@98669ae865ea3cffbcbaa878cf57c20bbf1c6c38
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
- name: Build and push Docker image
uses: docker/build-push-action@ad44023a93711e3deb337508980b4b5e9bcdc5dc
with:
context: .
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
env:
IMAGE_TAG: ${{ steps.meta.outputs.tags }}
run-django-tests:
needs: build-and-push-docker-image
runs-on: ubuntu-latest
container:
image: ${{ FULL_IMAGE_NAME_HERE }}
steps:
- uses: actions/checkout@v2
- name: Run tests
run: python ./manage.py test
And it’s the ${{ FULL_IMAGE_NAME_HERE }}
part that I’m currently stuck at.
I’ve tried using the same steps.meta.outputs.*
variables as used in the first job, but (obviously) they are not available in the second job.
I also tried defining a new env
variable in the first job (I don’t know if this is even possible), containing the image tag, to be used in later jobs (over time more jobs will be added that will use the same image). But I can’t access the env
context in the container
section of my second job definition.
It seems the env
variable has recently been added to the container
section context. But I still get an error when my workflow.yml
is parsed:
The workflow is not valid. .github/workflows/workflow.yml (Line: 58, Col: 14): Unrecognized named-value: ‘env’.
This above error references jobs.run-django-tests.container.image
and is thrown when it has a value of, say, ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
.
The overall idea is to have a workflow (in the general meaning of that word, not the GitHub workflow sense) where we push feature branches, have the Docker image built for the branch, run tests and such on that branch specific image and if everything passes, the branch can be merged.
Feature branches follow a naming convention of feature/<my-feature>
. But as we have a slash in there, the resulting tags and labels used for images are converted to hyphenated variants, feature-<my-feature>
, resulting in images being pushed to the registry as <image-name>/feature-<my-feature>
. I’m cool with that, but I need a way to be able to reference that exact image, including the tag. And I can’t just use the git branch name, as the slashes are converted to hyphens in the image naming.
Yes, the easy solution would be to start using hyphens instead of slashes in our branch names, but I’m sure there’s a better way around this 🙂
Another option would be to use the git commit hash instead of branch name. I could live with that, but I still need to reference the REGISTRY
and IMAGE_NAME
variables from the env
context, which raises the exception if I try.
I also realise that I can use artifacts to store and pass on the Docker image. This would definitely work for me (and might even be the solution). But I kinda like the idea of using the GitHub Container Registry for this, making it easier to also run branch specific images externally (e.g. on a test or staging server).
2
Answers
What if you used ghcr.io/YOUR_USERNAME/project-name:latest in your
to upload the image to github registry first.
And then use that to pull down the image in your next build step?
The two jobs create two different worker nodes (machines) so the content in the first is not available in the next one.
You can create another env at the top like:
and then use IMAGE_TAG to push and pull the image (mostly "your-tag" is the branch name).
In the second Job, you need to pull an image from the GitHub registry using the IMAGE_TAG env as documented Working with container registry