Skip to content

Release Docker image #4

Release Docker image

Release Docker image #4

Workflow file for this run

name: Release Docker image
# Manual-only: builds the runtime image for every platform in `platforms` and pushes it to Docker Hub
# as one multi-arch manifest per tag, so a single tag serves x86_64 Linux/Windows-WSL2/Intel Mac and
# arm64 (Apple Silicon, Ampere) alike.
#
# It always builds the branch it was dispatched from ("Use workflow from") - there is no ref input, so
# there is no second branch to keep in sync with the one you picked.
on:
workflow_dispatch:
inputs:
image:
description: Docker Hub repository to push to
required: true
default: josefprochazka/actor-runtime-dev
extra_tag:
description: Optional extra tag to publish alongside the branch tags (e.g. v0.1.0)
required: false
default: ''
latest:
description: Also publish this build as :latest
type: boolean
required: false
default: false
platforms:
description: Target platforms for the multi-arch manifest
required: true
default: linux/amd64,linux/arm64
jobs:
release:
name: Build and push ${{ inputs.image }}
runs-on: ubuntu-latest
timeout-minutes: 60
steps:
# No `ref:` - checkout defaults to the commit the workflow was dispatched from, which is
# exactly the branch picked in "Use workflow from".
- uses: actions/checkout@v4
# Fail here rather than three slow build steps later, with the fix named.
- name: Check Docker Hub credentials are configured
env:
DOCKERHUB_USERNAME: ${{ secrets.DOCKERHUB_USERNAME }}
DOCKERHUB_TOKEN: ${{ secrets.DOCKERHUB_TOKEN }}
run: |
if [ -z "$DOCKERHUB_USERNAME" ] || [ -z "$DOCKERHUB_TOKEN" ]; then
echo "::error::Missing DOCKERHUB_USERNAME / DOCKERHUB_TOKEN repository secrets." \
"Create an access token at https://hub.docker.com/settings/security and add both" \
"under Settings -> Secrets and variables -> Actions."
exit 1
fi
# A Docker tag may only contain [A-Za-z0-9_.-] and must start with an alphanumeric, so a
# branch name like `feat/foo` cannot be used as a tag verbatim.
- name: Compute image tags
id: tags
env:
IMAGE: ${{ inputs.image }}
BRANCH: ${{ github.ref_name }}
EXTRA_TAG: ${{ inputs.extra_tag }}
LATEST: ${{ inputs.latest }}
run: |
set -euo pipefail
slug=$(printf '%s' "$BRANCH" | tr -c 'A-Za-z0-9_.-' '-' | sed 's/^[^A-Za-z0-9]*//' | cut -c1-100)
if [ -z "$slug" ]; then
echo "::error::Branch '$BRANCH' contains no characters usable in a Docker tag."
exit 1
fi
sha=$(git rev-parse --short HEAD)
# The `<branch>-<sha>` tag is the immutable one - `<branch>` and `latest` move.
tags="${IMAGE}:${slug}-${sha}"
tags="${tags}"$'\n'"${IMAGE}:${slug}"
if [ -n "$EXTRA_TAG" ]; then
tags="${tags}"$'\n'"${IMAGE}:${EXTRA_TAG}"
fi
if [ "$LATEST" = "true" ]; then
tags="${tags}"$'\n'"${IMAGE}:latest"
fi
{
echo 'tags<<EOF'
echo "$tags"
echo 'EOF'
} >> "$GITHUB_OUTPUT"
echo "revision=$(git rev-parse HEAD)" >> "$GITHUB_OUTPUT"
# Emulation for any target platform the runner isn't. Only the final stage is emulated -
# the Dockerfile's builder stages are pinned to $BUILDPLATFORM and run natively.
- uses: docker/setup-qemu-action@v3
- uses: docker/setup-buildx-action@v3
- uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Build and push
id: build
uses: docker/build-push-action@v6
with:
context: .
platforms: ${{ inputs.platforms }}
push: true
tags: ${{ steps.tags.outputs.tags }}
provenance: mode=max
sbom: true
# One shared scope: a `type=gha` value is itself a comma-separated key=value list,
# so interpolating the (comma-separated) platform list into `scope` would end the
# value early and buildx would reject the leftover as a key. Sharing the scope also
# lets a single-platform run reuse the layers a multi-arch run already cached.
cache-from: type=gha,scope=release
cache-to: type=gha,mode=max,scope=release
labels: |
org.opencontainers.image.title=actor-runtime
org.opencontainers.image.description=A minimal, self-contained local Apify platform in a single Docker image.
org.opencontainers.image.source=${{ github.server_url }}/${{ github.repository }}
org.opencontainers.image.revision=${{ steps.tags.outputs.revision }}
org.opencontainers.image.version=${{ github.ref_name }}
- name: Summary
env:
TAGS: ${{ steps.tags.outputs.tags }}
DIGEST: ${{ steps.build.outputs.digest }}
run: |
{
echo "### Pushed \`${{ inputs.platforms }}\`"
echo
echo "Digest: \`${DIGEST}\`"
echo
echo "$TAGS" | sed 's/^/- `/; s/$/`/'
} >> "$GITHUB_STEP_SUMMARY"