A GitHub Action that helps track and automate builds of Docker images that wrap official images. This action monitors upstream Docker images for new releases and generates a build matrix for creating corresponding wrapper images.
- π Tracks upstream Docker image tags
- π·οΈ Supports complex tag filtering and mapping
- π Time-based filtering of releases
- π’ Limit number of releases to process
- ποΈ Multi-platform image support
- π·οΈ Flexible tag generation with expressions
- π Intelligent build detection to avoid unnecessary rebuilds
- π Multiple variants support for tracking different upstream images
This action requires regctl
to be available on the runner. You can either:
- Use the
iarekylew00t/regctl-installer@v3
action to install it (recommended) - Ensure
regctl
is already installed on your runner
name: Build Docker Images
on:
schedule:
- cron: '0 */6 * * *' # Run every 6 hours
workflow_dispatch: # Allow manual trigger
jobs:
track:
runs-on: ubuntu-latest
outputs:
matrix: ${{ steps.track.outputs.matrix }}
steps:
- uses: actions/checkout@v4
- name: Install regctl
uses: iarekylew00t/regctl-installer@v3
- name: Track upstream images
id: track
uses: framjet/docker-uptrack-action@v1
with:
config: ./uptrack.json
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
build:
needs: track
if: needs.track.outputs.matrix != '[]'
strategy:
matrix:
include: ${{ fromJson(needs.track.outputs.matrix) }}
runs-on: ubuntu-latest
steps:
- name: Build and push
uses: docker/build-push-action@v5
with:
platforms: ${{ matrix.platform }}
tags: ${{ matrix.tags }}
build-args: ${{ matrix.buildArgs }}
labels: ${{ matrix.labels }}
{
"variants": [
{
"namespace": "framjet",
"name": "nginx",
"platforms": [
"linux/amd64",
"linux/arm64"
],
"upstream": {
"name": "nginx"
},
"filters": {
"oldest_tag_limit": "1year",
"limit_releases": 10,
"tags": [
{
"pattern": "(.*)-alpine$",
"mapped": "$1",
"extraTags": [
{
"expression": "'build-' + now()|formatDateTime('yyyy-MM-dd')"
}
]
}
]
}
},
{
"namespace": "framjet",
"name": "nginx",
"platforms": [
"linux/amd64"
],
"upstream": {
"name": "nginx"
},
"filters": {
"limit_releases": 5,
"tags": [
{
"pattern": "(.*)-slim",
"mapped": "$1",
}
]
}
}
]
}
Name | Description | Required | Default |
---|---|---|---|
config |
Path to the configuration file | Yes | ./uptrack.json |
rev-provider |
Revision provider.git uses git commit hashconfig uses hash of config folder + config.include file list |
No | git |
force |
Force build even if no changes | No | false |
username |
DockerHub username | Yes | ${{ secrets.DOCKERHUB_USERNAME }} |
password |
DockerHub password/token | Yes | ${{ secrets.DOCKERHUB_TOKEN }} |
label-prefix |
Prefix for generated labels | No | org.framjet.uptrack. |
sep-tags |
Separator for tags output | No | \n |
sep-labels |
Separator for labels output | No | \n |
sep-build-args |
Separator for build args output | No | \n |
github-token |
GitHub token for API access | Yes | ${{ github.token }} |
A JSON array containing build information for each image that needs to be built. Each object in the array includes:
platform
: Target platform (e.g., "linux/amd64")tags
: List of tags to applybuildArgs
: Build argumentslabels
: Docker image labels- Additional metadata about the upstream image
The matrix output merges all variants into a single result, making it easy to use in a GitHub Actions matrix strategy.
Each variant in the variants
array supports the following properties:
namespace
: The Docker Hub namespace for the imagename
: The name of the image to buildplatforms
: Array of target platformsupstream
: Configuration for the upstream image to trackfilters
: Tag filters and limitsbuildArgs
: Custom build argumentslabels
: Custom Docker image labelsextraTags
: Additional tags to applyinclude
: Files/folders to include in the revision hash (when usingrev-provider: config
)buildTarget
: Specific build target to use
The action supports several types of tag filters:
-
Simple string match
"tags": ["latest", "1.0.0"]
-
Pattern matching with mapping
{ "pattern": "(\\d+\\.\\d+\\.\\d+)-alpine$", "mapped": "$1-custom" }
-
Expression-based tags
{ "pattern": ".*", "expression": "tag.name + '-' + platform|replace('/', '-')" }
The action uses a powerful expression language (JEXL) that supports:
- String operations
- Date/time formatting
- Mathematical operations
- Conditional logic
- Built-in functions
Example expressions:
'v' + tag.name|upper
now()|formatDateTime('yyyy-MM-dd')
platform|replace('/', '-')
{
"variants": [
{
"namespace": "myorg",
"name": "python",
"platforms": ["linux/amd64", "linux/arm64"],
"upstream": {
"name": "python"
},
"filters": {
"tags": [
{
"pattern": "(\\d+\\.\\d+)-alpine",
"mapped": "$1"
}
]
}
},
{
"namespace": "myorg",
"name": "nginx",
"platforms": ["linux/amd64"],
"upstream": {
"name": "nginx"
},
"filters": {
"tags": ["stable", "latest"]
},
"labels": {
"org.opencontainers.image.title": "Custom Nginx Image"
}
}
]
}
{
"variants": [
{
"namespace": "myorg",
"name": "python",
"platforms": [
"linux/amd64"
],
"upstream": {
"name": "python"
},
"labels": {
"org.opencontainers.image.title": "Custom Python Image",
"org.opencontainers.image.version": {
"expression": "tag.name"
}
},
"filters": {
"tags": [
"3.10",
"3.11"
]
}
}
]
}
This project is licensed under the MIT License - see the LICENSE file for details.