skip to Main Content

I’m building a new GitHub workflow (my first), which currently consists of 2 simple jobs:

  1. Build a Docker image for the Django application.
  2. 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


  1. What if you used ghcr.io/YOUR_USERNAME/project-name:latest in your

    tags: ghcr.io/<USERNAME>/project-name:latest
    

    to upload the image to github registry first.

    And then use that to pull down the image in your next build step?

     container:
          image: ghcr.io/<USERNAME>/project-name:latest
    
    Login or Signup to reply.
  2. 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:

    env:
      REGISTRY: ghcr.io
      IMAGE_NAME: ${{ github.repository }}
      IMAGE_TAG: ghcr.io/<USERNAME>/project-name:your-tag
    

    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

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search