Re-usable GitHub Actions workflows

Things you already know about code re-use

  • Enables maintenance of a single thing to improve many things
  • Enables abstraction of unimportant details
    • “Which container registry or registries should I publish to?”

An example workflow

Modified from source

name: "Build and release container image"

# Triggers
on:
  push:
    branches:
      - "main"
  release:
    types:
      - "published"


# A group of steps that occurs in the same run environment
jobs:

  build-and-release-image:
    name: "Build and release container image"
    runs-on: "ubuntu-latest"
    env:
      IMAGE_NAME: "nsidc/usaon-vta-survey"
      # GitHub Actions expressions don't have great conditional support, so
      # writing a ternary expression looks a lot like bash. In Python, this
      # would read as:
      #     github.event.release.tag_name if github.event_name == 'release' else 'latest'
      #     https://docs.github.com/en/actions/learn-github-actions/expressions
      IMAGE_TAG: "${{ github.event_name == 'release' && github.event.release.tag_name || 'latest' }}"
    steps:
      - name: "Check out repository"
        uses: "actions/checkout@v3"

      - name: "Build container image"
        run: |
          docker build -t "${IMAGE_NAME}:${IMAGE_TAG}" .

      - name: "DockerHub login"
        uses: "docker/login-action@v2"
        with:
          username: "${{secrets.DOCKER_USER}}"
          password: "${{secrets.DOCKER_PASS}}"

      - name: "GHCR login"
        uses: "docker/login-action@v2"
        with:
          registry: "ghcr.io"
          username: "${{ github.repository_owner }}"
          password: "${{ secrets.GITHUB_TOKEN }}"

      - name: "Push to DockerHub and GHCR"
        run: |
          docker push "${IMAGE_NAME}:${IMAGE_TAG}"

          docker tag "${IMAGE_NAME}:${IMAGE_TAG}" "ghcr.io/${IMAGE_NAME}:${IMAGE_TAG}"
          docker push "ghcr.io/${IMAGE_NAME}:${IMAGE_TAG}"

Re-using with GitHub Actions

In action

diff

name: "Build and release container image"

on:
  push:
    branches:
      - "main"
    tags:
      - "v[0-9]+.[0-9]+.[0-9]+*"


jobs:

  build-and-release-image:
    uses: "nsidc/.github/.github/workflows/build-and-publish-container-image.yml@main"
    secrets: "inherit"

Re-usable workflow source

source

  • The trigger event is workflow_call, which takes inputs and secrets as args
  • Everything else is nearly identical to the example workflow
  • …except a bit of magic to automatically detect the calling repository’s name:
    • IMAGE_NAME: "nsidc/${{ github.event.repository.name }}"

Starter workflows

  • For “bootstrapping” a new workflow file
  • Enable sharing workflow configuration text within the GitHub GUI
    • “Actions” -> “New workflow”
  • Do not support passing arguments
  • Can be defined at the org level by a combination of a YAML and JSON file in my-org/.github repo’s /workflow-templates directory.

NSIDC’s starter workflows