Build image from specific ref
Description
I would like a ref variable in this Action to allow building an image from a specific ref, that may not be the same as the ref that triggered the Actions workflow.
The problem this would solve is that, in GitHub Actions, you cannot make a scheduled workflow that targets anything but your default branch. And I would like to make a scheduled workflow to rebuild a few image tags that will easily go stale on security patches from the base distro images they use.
Take, for example, the following workflow definition that currently only does not work because this Action forces the build-push step to use the branch that triggered the workflow:
name: Publish docker image
on:
push:
branches:
- main
workflow_dispatch:
schedule:
# Monday at 9am UTC
- cron: '0 9 * * 1'
permissions:
id-token: write
contents: read
packages: write
jobs:
package:
runs-on: ubuntu-latest
timeout-minutes: 15
# Need this matrix because GitHub doesn't support running scheduled workflows against non-default branches
# This checks out each branch listed here, and there are separate docker meta and build steps for each branch in the matrix.
strategy:
matrix:
branch:
- main
- v1.0.x
steps:
- name: Add safe git directory
run: git config --global --add safe.directory "$GITHUB_WORKSPACE"
- uses: actions/checkout@v4
with:
ref: ${{ matrix.branch }}
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Login to GitHub Container Registry
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ github.token }}
- name: Docker meta on main
if: matrix.branch == 'main'
id: meta-main
uses: docker/metadata-action@v5
with:
images: |
ghcr.io/${{ github.repository }}
flavor: |
latest=false
prefix=
suffix=
tags: |
type=raw,value=main,enable={{is_default_branch}}
type=sha,format=long
- name: Build Docker Container on main
if: matrix.branch == 'main'
uses: docker/build-push-action@v5
with:
platforms: "linux/amd64,linux/arm64"
push: true
tags: ${{ steps.meta-main.outputs.tags }}
labels: ${{ steps.meta-main.outputs.labels }}
- name: Docker meta on v1.0.x
if: matrix.branch == 'v1.0.x'
id: meta-v1dot0
uses: docker/metadata-action@v5
with:
images: |
ghcr.io/${{ github.repository }}
flavor: |
latest=false
prefix=
suffix=
tags: |
type=raw,value=1.0
type=sha,format=long
- name: Build Docker Container on v1.0.x
if: matrix.branch == 'v1.0.x'
uses: docker/build-push-action@v5
with:
platforms: "linux/amd64,linux/arm64"
push: true
tags: ${{ steps.meta-v1dot0.outputs.tags }}
labels: ${{ steps.meta-v1dot0.outputs.labels }}
Loosely related to this person's Issue: https://github.com/docker/build-push-action/issues/467
But is not a duplicate. They were apparently fine with the proposed "add the branch to your on-push workflow trigger list" suggestion. That doesn't work for scheduled workflows though. Hopefully Docker recognizes this as a valid pain point, as maintaining images that are based on upstream distro images like alpine:latest will naturally require pulling in OS updates for security patches. And it is not uncommon to have multiple supported versions of the software you distribute that live on different branches.
As far as a proposed solution goes, I think this Action could go one of two ways (besides just ignoring the request and labeling this issue with wont-fix):
- An input that tells the Action which ref to use
- An input that tells the Action to just use the ref already checked out (likely by actions/checkout)
An input that tells the Action to just use the ref already checked out (likely by actions/checkout)
This is already possible using the Git context with context: "{{defaultContext}}#${{ matrix.branch }}", so you don't need to use the actions/checkout:
jobs:
package:
runs-on: ubuntu-latest
timeout-minutes: 15
# Need this matrix because GitHub doesn't support running scheduled workflows against non-default branches
# This checks out each branch listed here, and there are separate docker meta and build steps for each branch in the matrix.
strategy:
matrix:
branch:
- main
- v1.0.x
steps:
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Login to GitHub Container Registry
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ github.token }}
- name: Docker meta on main
if: matrix.branch == 'main'
id: meta-main
uses: docker/metadata-action@v5
with:
images: |
ghcr.io/${{ github.repository }}
flavor: |
latest=false
prefix=
suffix=
tags: |
type=raw,value=main,enable={{is_default_branch}}
type=sha,format=long
- name: Build Docker Container on main
if: matrix.branch == 'main'
uses: docker/build-push-action@v5
with:
context: "{{defaultContext}}#${{ matrix.branch }}"
platforms: "linux/amd64,linux/arm64"
push: true
tags: ${{ steps.meta-main.outputs.tags }}
labels: ${{ steps.meta-main.outputs.labels }}
- name: Docker meta on v1.0.x
if: matrix.branch == 'v1.0.x'
id: meta-v1dot0
uses: docker/metadata-action@v5
with:
images: |
ghcr.io/${{ github.repository }}
flavor: |
latest=false
prefix=
suffix=
tags: |
type=raw,value=1.0
type=sha,format=long
- name: Build Docker Container on v1.0.x
if: matrix.branch == 'v1.0.x'
uses: docker/build-push-action@v5
with:
context: "{{defaultContext}}#${{ matrix.branch }}"
platforms: "linux/amd64,linux/arm64"
push: true
tags: ${{ steps.meta-v1dot0.outputs.tags }}
labels: ${{ steps.meta-v1dot0.outputs.labels }}
Also I'm not sure of the intent of this workflow but that doesn't sound right to me to have sequential builds like this when you're using a matrix. There should be one per-matrix job imo.
Thanks for clueing me in on that bit of config!
Also I'm not sure of the intent of this workflow but that doesn't sound right to me to have sequential builds like this when you're using a matrix. There should be one per-matrix job imo.
The if statements I put in the steps make it so only one of those docker builds run in each of the matrix jobs. I assume you missed that bit in your advice here. I suppose I could maybe have used a matrix variable to consolidate all of those differing step definitions into one, to make it a bit more obvious what I was doing in that job, rather than using the if statements.
But anyway, thank you!