This GitHub action can intelligently calculate and output a JSON formatted list of versions associated tags when a SemVer2 compliant tag is pushed go a GitHub repository.
This action can be useful if a git tag like 1.2.3
is pushed to a GitHub repo and you want a GitHub Workflow's job to not only take action with regards to the pushed tag 1.2.3
specifically, but also to related tags like 1.2
, 1
, and latest
assuming the pushed tag's version is new enough to represent those more general tags.
This pattern is often used for tagging containers.
The GitHub action's only output is named tags
and is a JSON formatted list. See the example workflow below for details on how to convert the JSON formatted list to something else. Tags will always be in decreasing order of specificity.
Pushed reference | GitHub repo tags | tags output |
Comment |
---|---|---|---|
... | "[]" |
No git reference associated with the triggering workflow | |
main |
... | "[main]" |
A branch reference get no associated version tags |
1.2.3 |
1.2.0 |
"[1.2.3, 1.2, 1, latest]" |
|
1.2.3 |
1.2.0 , 2.0.0 |
"[1.2.3, 1.2, 1]" |
|
1.2.3 |
1.2.0 , 1.3.0 |
"[1.2.3, 1.2]" |
|
1.2.3 |
1.2.0 , 1.2.5 |
"[1.2.3]" |
|
1.2.3-alpha.1 |
1.2.0 |
"[1.2.3-alpha.1]" |
A pre-release suffix on a version is treated like a branch |
1.2.3a1 |
1.2.0 |
"[1.2.3a1]" |
A pre-release suffix (loose parsing) on a version is treated like a branch |
1.2.3-4 |
1.2.0 , 1.2.3 |
"[1.2.3-4, 1.2.3, 1.2, 1, latest]" |
A build number suffix on a version is treated like the version but even newer |
githubToken
: The GitHub token, required so this action can fetch tags using the GitHub API. If this parameter is not set thendefaultTag
(if set) or an empty list will be returned.
-
prefix
: One or more whitespace or comma delimited prefixes for returned tags.As an example, prefix could be set to
ghcr.io/a/b: quay.io/a/b:
to provide image names with tags for two separate repositories.The string
""
can be used to represent an empty string, and all combinations of prefixes and suffixes are used. -
suffix
: One or more whitespace or comma delimited suffixes for returned tags.As an example, suffix could be set to
"" -debian
to provide a default image variant without suffix next to an image variant referred to with a -debian suffix.The string
""
can be used to represent an empty string, and all combinations of prefixes and suffixes are used. -
defaultTag
: If the tag output would be empty return this tag instead. This can be useful for running a workflow in pull requests where no suitable git references are present.prefix
orsuffix
are not automatically added. -
branchRegex
: If a branch name does not match this regex returndefaultTag
or empty instead.
tags
: A JSON formatted list of calculated tags.
name: Build and publish image to DockerHub
on:
push:
# Uncomment this if you also want a tag created for all pushed branches
# branches:
# - "*"
tags:
- "*"
jobs:
push-images-to-dockerhub:
runs-on: ubuntu-22.04
steps:
- name: Checkout code
uses: actions/checkout@v4
# https://github.com/jupyterhub/action-major-minor-tag-calculator
- name: Get all relevant tags
id: gettags
uses: jupyterhub/action-major-minor-tag-calculator@v3
with:
githubToken: ${{ secrets.GITHUB_TOKEN }}
prefix: "my-username/my-image-name:"
branchRegex: "^[^/]+$"
# https://github.com/docker/login-action
- name: Login to DockerHub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_ACCESS_TOKEN }}
# https://github.com/docker/build-push-action
- name: Build, tag, and push images
uses: docker/build-push-action@v5
with:
push: true
# The tags expression below could with a git reference triggering
# this GitHub workflow evaluate to a string like:
#
# "my-username/my-image:1.2.3,my-username/my-image:1.2,my-username/my-image:1,my-username/my-image:latest"
#
tags: ${{ join(fromJson(steps.gettags.outputs.tags)) }}
This project runs under multiple NodeJS versions, but if you are updating code you must use version 14.x. This is because the contents of the dist/
folder are autogenerated in the packaging step but this depends on the NodeJS version, causing a failure of the CI job that verifies the generated code matches the source.
Install the dependencies:
$ npm install
Build the typescript, run the formatter and linter:
$ npm run build && npm run format && npm run lint
Package the code for distribution (uses ncc):
$ npm run package
Run the tests ✔️
$ npm test
The tests use nock to mock GitHub API responses, no real requests are made so manual testing is still required.
Shortcut:
$ npm run all
Actions are run from GitHub repos so you must checkin the packed dist
folder:
$ npm run all
$ git add dist
$ git commit
$ git push origin main