Publish Docker Images workflow (TilmanGriesel/chipper)
The Publish Docker Images workflow from TilmanGriesel/chipper, explained and optimized by Latchkey.
CI health: C - fair
Point runs-on at Latchkey and get run de-duplication, job timeouts, SHA-pinned actions, self-healing for flaky steps, and up to 58% lower cost, applied automatically.
What it does
This is the Publish Docker Images workflow from the TilmanGriesel/chipper repository, a real project running GitHub Actions. It is shown here with attribution under its MIT license.
Below, Latchkey shows a faster, safer version produced by its optimization engine.
The workflow
name: Publish Docker Images
on:
push:
branches:
- main
tags:
- "v*"
workflow_dispatch:
jobs:
build-and-push:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v3
with:
lfs: true
fetch-depth: 0
- name: Checkout LFS objects
run: git lfs checkout
- name: Determine Version and Build Number
id: version
run: |
echo "BUILD_NUM=${{ github.run_number }}" >> $GITHUB_ENV
if [ "${{ github.ref_type }}" == "tag" ]; then
echo "VERSION=${{ github.ref_name }}.${{ github.run_number }}" >> $GITHUB_ENV
else
echo "VERSION=latest" >> $GITHUB_ENV
fi
- name: Log in to Docker Hub
uses: docker/login-action@v2
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_API_KEY }}
- name: Build and Push API Image
run: |
docker build \
--build-arg VERSION=${{ env.VERSION }} \
--build-arg BUILD_NUM=${{ env.BUILD_NUM }} \
-t ${{ secrets.DOCKER_USERNAME }}/chipper:api-${{ env.VERSION }} \
services/api
docker push ${{ secrets.DOCKER_USERNAME }}/chipper:api-${{ env.VERSION }}
- name: Build and Push Web Image
run: |
docker build \
--build-arg VERSION=${{ env.VERSION }} \
--build-arg BUILD_NUM=${{ env.BUILD_NUM }} \
-t ${{ secrets.DOCKER_USERNAME }}/chipper:web-${{ env.VERSION }} \
services/web
docker push ${{ secrets.DOCKER_USERNAME }}/chipper:web-${{ env.VERSION }}
- name: Build and Push CLI Tool Image
run: |
docker build \
--build-arg VERSION=${{ env.VERSION }} \
--build-arg BUILD_NUM=${{ env.BUILD_NUM }} \
-t ${{ secrets.DOCKER_USERNAME }}/chipper:cli-${{ env.VERSION }} \
tools/cli
docker push ${{ secrets.DOCKER_USERNAME }}/chipper:cli-${{ env.VERSION }}
- name: Build and Push Embed Tool Image
run: |
docker build \
--build-arg VERSION=${{ env.VERSION }} \
--build-arg BUILD_NUM=${{ env.BUILD_NUM }} \
-t ${{ secrets.DOCKER_USERNAME }}/chipper:embed-${{ env.VERSION }} \
tools/embed
docker push ${{ secrets.DOCKER_USERNAME }}/chipper:embed-${{ env.VERSION }}
- name: Build and Push Scrape Tool Image
run: |
docker build \
--build-arg VERSION=${{ env.VERSION }} \
--build-arg BUILD_NUM=${{ env.BUILD_NUM }} \
-t ${{ secrets.DOCKER_USERNAME }}/chipper:scrape-${{ env.VERSION }} \
tools/scrape
docker push ${{ secrets.DOCKER_USERNAME }}/chipper:scrape-${{ env.VERSION }}
The same workflow, on Latchkey
Removes redundant runs and caps runaway jobs. Added and changed lines are highlighted.
name: Publish Docker Images on: push: branches: - main tags: - "v*" workflow_dispatch: concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true jobs: build-and-push: timeout-minutes: 30 runs-on: latchkey-small steps: - name: Checkout code uses: actions/checkout@v3 with: lfs: true fetch-depth: 0 - name: Checkout LFS objects run: git lfs checkout - name: Determine Version and Build Number id: version run: | echo "BUILD_NUM=${{ github.run_number }}" >> $GITHUB_ENV if [ "${{ github.ref_type }}" == "tag" ]; then echo "VERSION=${{ github.ref_name }}.${{ github.run_number }}" >> $GITHUB_ENV else echo "VERSION=latest" >> $GITHUB_ENV fi - name: Log in to Docker Hub uses: docker/login-action@v2 with: username: ${{ secrets.DOCKER_USERNAME }} password: ${{ secrets.DOCKER_API_KEY }} - name: Build and Push API Image run: | docker build \ --build-arg VERSION=${{ env.VERSION }} \ --build-arg BUILD_NUM=${{ env.BUILD_NUM }} \ -t ${{ secrets.DOCKER_USERNAME }}/chipper:api-${{ env.VERSION }} \ services/api docker push ${{ secrets.DOCKER_USERNAME }}/chipper:api-${{ env.VERSION }} - name: Build and Push Web Image run: | docker build \ --build-arg VERSION=${{ env.VERSION }} \ --build-arg BUILD_NUM=${{ env.BUILD_NUM }} \ -t ${{ secrets.DOCKER_USERNAME }}/chipper:web-${{ env.VERSION }} \ services/web docker push ${{ secrets.DOCKER_USERNAME }}/chipper:web-${{ env.VERSION }} - name: Build and Push CLI Tool Image run: | docker build \ --build-arg VERSION=${{ env.VERSION }} \ --build-arg BUILD_NUM=${{ env.BUILD_NUM }} \ -t ${{ secrets.DOCKER_USERNAME }}/chipper:cli-${{ env.VERSION }} \ tools/cli docker push ${{ secrets.DOCKER_USERNAME }}/chipper:cli-${{ env.VERSION }} - name: Build and Push Embed Tool Image run: | docker build \ --build-arg VERSION=${{ env.VERSION }} \ --build-arg BUILD_NUM=${{ env.BUILD_NUM }} \ -t ${{ secrets.DOCKER_USERNAME }}/chipper:embed-${{ env.VERSION }} \ tools/embed docker push ${{ secrets.DOCKER_USERNAME }}/chipper:embed-${{ env.VERSION }} - name: Build and Push Scrape Tool Image run: | docker build \ --build-arg VERSION=${{ env.VERSION }} \ --build-arg BUILD_NUM=${{ env.BUILD_NUM }} \ -t ${{ secrets.DOCKER_USERNAME }}/chipper:scrape-${{ env.VERSION }} \ tools/scrape docker push ${{ secrets.DOCKER_USERNAME }}/chipper:scrape-${{ env.VERSION }}
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. - Cancel superseded runs when a branch or PR gets a newer push.
- Add a job timeout so a hung step cannot burn hours of runner time.
1 third-party action is referenced by a movable tag. Pin it 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.