Docker Build on Tag workflow (HolmesGPT/holmesgpt)
The Docker Build on Tag workflow from HolmesGPT/holmesgpt, explained and optimized by Latchkey.
CI health: B - good
Point runs-on at Latchkey and get job timeouts, SHA-pinned actions, self-healing for flaky steps, and up to 58% lower cost, applied automatically.
What it does
This is the Docker Build on Tag workflow from the HolmesGPT/holmesgpt repository, a real project running GitHub Actions. It is shown here with attribution under its Apache-2.0 license.
Below, Latchkey shows a faster, safer version produced by its optimization engine.
The workflow
name: Docker Build on Tag
on:
release:
types: [published]
jobs:
build:
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
id-token: write
steps:
- uses: actions/checkout@v4
- uses: google-github-actions/auth@v2
with:
project_id: 'genuine-flight-317411'
workload_identity_provider: 'projects/429189597230/locations/global/workloadIdentityPools/github/providers/robusta-repos' # prod
- name: Set up gcloud CLI
uses: google-github-actions/setup-gcloud@v2
with:
project_id: genuine-flight-317411
- name: Configure Docker Registry
run: gcloud auth configure-docker us-central1-docker.pkg.dev
- name: Update package version
run: |
sed -i 's/__version__ = .*/__version__ = "${{github.ref_name}}"/g' holmes/__init__.py
sed -i 's/0.0.0/${{github.ref_name}}/g' helm/holmes/Chart.yaml helm/holmes/values.yaml
sed -i 's/0.0.1/${{github.ref_name}}/g' helm/holmes/Chart.yaml
- name: Login to Docker Hub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Build and push Holmes Docker images
uses: docker/build-push-action@v6
with:
context: .
file: ./Dockerfile
platforms: linux/arm64,linux/amd64
push: true
tags: |
us-central1-docker.pkg.dev/genuine-flight-317411/devel/holmes:${{ github.ref_name }}
robustadev/holmes:${{ github.ref_name }}
build-args: |
BUILDKIT_INLINE_CACHE=1
- name: Build and push Holmes Operator Docker images
uses: docker/build-push-action@v6
with:
context: .
file: ./Dockerfile.operator
platforms: linux/arm64,linux/amd64
push: true
tags: |
us-central1-docker.pkg.dev/genuine-flight-317411/devel/holmes-operator:${{ github.ref_name }}
robustadev/holmes-operator:${{ github.ref_name }}
build-args: |
BUILDKIT_INLINE_CACHE=1
# Note: this ignores the "Set as latest release" checkbox in the GitHub UI
# it isn't possible to check whether that was set or not
# so if you do not want to override the "latest" tag, you should mark the release as a prerelease or a draft
# for prereleases and drafts we don't tag latest
- name: Tag and push Docker images as latest if applicable
if: ${{ github.event.release.prerelease == false && github.event.release.draft == false }}
run: |
# Tag Holmes as latest (preserves multi-arch manifest)
docker buildx imagetools create \
--tag us-central1-docker.pkg.dev/genuine-flight-317411/devel/holmes:latest \
--tag robustadev/holmes:latest \
us-central1-docker.pkg.dev/genuine-flight-317411/devel/holmes:${{ github.ref_name }}
# Tag Holmes Operator as latest (preserves multi-arch manifest)
docker buildx imagetools create \
--tag us-central1-docker.pkg.dev/genuine-flight-317411/devel/holmes-operator:latest \
--tag robustadev/holmes-operator:latest \
us-central1-docker.pkg.dev/genuine-flight-317411/devel/holmes-operator:${{ github.ref_name }}
- name: Save artifact with helm chart
uses: actions/upload-artifact@v4
with:
name: helm-chart
path: helm/holmes/
- name: Upload helm chart
run: |
cd helm && ./upload_chart.sh
- name: Login to GitHub Container Registry
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Push Helm chart to OCI registry
run: |
helm package helm/holmes
helm push holmes-${{github.ref_name}}.tgz oci://ghcr.io/holmesgpt/charts
The same workflow, on Latchkey
Removes redundant runs and caps runaway jobs. Added and changed lines are highlighted.
name: Docker Build on Tag on: release: types: [published] jobs: build: timeout-minutes: 30 runs-on: latchkey-small permissions: contents: read packages: write id-token: write steps: - uses: actions/checkout@v4 - uses: google-github-actions/auth@v2 with: project_id: 'genuine-flight-317411' workload_identity_provider: 'projects/429189597230/locations/global/workloadIdentityPools/github/providers/robusta-repos' # prod - name: Set up gcloud CLI uses: google-github-actions/setup-gcloud@v2 with: project_id: genuine-flight-317411 - name: Configure Docker Registry run: gcloud auth configure-docker us-central1-docker.pkg.dev - name: Update package version run: | sed -i 's/__version__ = .*/__version__ = "${{github.ref_name}}"/g' holmes/__init__.py sed -i 's/0.0.0/${{github.ref_name}}/g' helm/holmes/Chart.yaml helm/holmes/values.yaml sed -i 's/0.0.1/${{github.ref_name}}/g' helm/holmes/Chart.yaml - name: Login to Docker Hub uses: docker/login-action@v3 with: username: ${{ secrets.DOCKER_USERNAME }} password: ${{ secrets.DOCKER_PASSWORD }} - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3 - name: Build and push Holmes Docker images uses: docker/build-push-action@v6 with: context: . file: ./Dockerfile platforms: linux/arm64,linux/amd64 push: true tags: | us-central1-docker.pkg.dev/genuine-flight-317411/devel/holmes:${{ github.ref_name }} robustadev/holmes:${{ github.ref_name }} build-args: | BUILDKIT_INLINE_CACHE=1 - name: Build and push Holmes Operator Docker images uses: docker/build-push-action@v6 with: context: . file: ./Dockerfile.operator platforms: linux/arm64,linux/amd64 push: true tags: | us-central1-docker.pkg.dev/genuine-flight-317411/devel/holmes-operator:${{ github.ref_name }} robustadev/holmes-operator:${{ github.ref_name }} build-args: | BUILDKIT_INLINE_CACHE=1 # Note: this ignores the "Set as latest release" checkbox in the GitHub UI # it isn't possible to check whether that was set or not # so if you do not want to override the "latest" tag, you should mark the release as a prerelease or a draft # for prereleases and drafts we don't tag latest - name: Tag and push Docker images as latest if applicable if: ${{ github.event.release.prerelease == false && github.event.release.draft == false }} run: | # Tag Holmes as latest (preserves multi-arch manifest) docker buildx imagetools create \ --tag us-central1-docker.pkg.dev/genuine-flight-317411/devel/holmes:latest \ --tag robustadev/holmes:latest \ us-central1-docker.pkg.dev/genuine-flight-317411/devel/holmes:${{ github.ref_name }} # Tag Holmes Operator as latest (preserves multi-arch manifest) docker buildx imagetools create \ --tag us-central1-docker.pkg.dev/genuine-flight-317411/devel/holmes-operator:latest \ --tag robustadev/holmes-operator:latest \ us-central1-docker.pkg.dev/genuine-flight-317411/devel/holmes-operator:${{ github.ref_name }} - name: Save artifact with helm chart uses: actions/upload-artifact@v4 with: name: helm-chart path: helm/holmes/ - name: Upload helm chart run: | cd helm && ./upload_chart.sh - name: Login to GitHub Container Registry uses: docker/login-action@v3 with: registry: ghcr.io username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} - name: Push Helm chart to OCI registry run: | helm package helm/holmes helm push holmes-${{github.ref_name}}.tgz oci://ghcr.io/holmesgpt/charts
What changed
- Run on Latchkey managed runners with one line (
runs-on), which apply the fixes below automatically and self-heal transient failures. This example useslatchkey-small; pick the runner size that fits the job. - Add a job timeout so a hung step cannot burn hours of runner time.
5 third-party actions are referenced by a movable tag. Pin them to the commit SHA (Latchkey resolves and applies this automatically) so a repointed tag cannot change what runs.
What Latchkey heals here
This workflow has steps that commonly fail on transient issues (network, registries, flaky browsers). On Latchkey managed runners they are detected, retried, and self-healed instead of failing your build:
- Container pulls and builds
This workflow runs 1 job per trigger. On Latchkey the same minutes cost up to 58% less than GitHub-hosted, with zero queue time.