Skip to content

feat: updater tracks all 6 CI-built images (#64) #138

feat: updater tracks all 6 CI-built images (#64)

feat: updater tracks all 6 CI-built images (#64) #138

Workflow file for this run

name: Build & Deploy
on:
workflow_dispatch:
inputs:
tag:
description: 'Image tag override (default: branch-based)'
required: false
type: string
openclaw_version:
description: 'OpenClaw npm version for worker image (default: Dockerfile ARG)'
required: false
type: string
ironclaw_version:
description: 'IronClaw version for worker image (default: Dockerfile ARG)'
required: false
type: string
push:
branches:
- main
tags:
- "v*"
env:
REGISTRY: docker.io
jobs:
build:
name: Build ${{ matrix.name }}
permissions:
contents: read
packages: write
attestations: write
id-token: write
runs-on: ubuntu-latest
strategy:
matrix:
include:
- name: openclaw-nearai-worker
context: worker
dockerfile: worker/Dockerfile
build_script: true
- name: openclaw-compose-api
context: compose-api
dockerfile: compose-api/Dockerfile
build_script: false
- name: openclaw-updater
context: .
dockerfile: updater/Dockerfile
build_script: false
- name: ironclaw-nearai-worker
context: ironclaw-worker
dockerfile: ironclaw-worker/Dockerfile
build_script: false
- name: openclaw-ingress
context: ingress
dockerfile: ingress/Dockerfile
build_script: false
- name: openclaw-ssh-bastion
context: ssh-bastion
dockerfile: ssh-bastion/Dockerfile
build_script: false
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Log in to Docker registry
uses: docker/login-action@65b78e6e13532edd9afa3aa52ac7964289d1a9c1
with:
registry: ${{ env.REGISTRY }}
username: ${{ vars.DOCKER_REGISTRY_USER }}
password: ${{ secrets.DOCKER_REGISTRY_TOKEN }}
- name: Set image repository
run: echo "IMAGE_REPOSITORY=${{ vars.DOCKER_REGISTRY_USER }}/${{ matrix.name }}" >> "$GITHUB_ENV"
- name: Extract image tag from GitHub ref (branch or tag)
run: |
# Use manual input tag if provided via workflow_dispatch
if [[ -n "${{ inputs.tag }}" ]]; then
TAG="${{ inputs.tag }}"
echo "Using '${TAG}' image tag from workflow_dispatch input"
elif [[ "${GITHUB_REF_TYPE}" == 'tag' ]]; then
TAG=${GITHUB_REF_NAME#v}
echo "Using '${TAG}' image tag for ${GITHUB_REF_NAME} tag"
elif [[ "${GITHUB_REF_TYPE}" == 'branch' ]]; then
TAG=$(if [[ "${GITHUB_REF_NAME}" == 'main' ]]; then echo 'latest'; else echo 'dev'; fi)
echo "Using '${TAG}' image tag for ${GITHUB_REF_NAME} branch"
else
echo "Unsupported ref type: ${GITHUB_REF_TYPE}" >&2
exit 1
fi
if [ -z "${TAG}" ]; then
echo "Unable to parse image tag from ${GITHUB_REF_TYPE}: ${GITHUB_REF_NAME}" >&2
exit 1
fi
echo "IMAGE_REFERENCE=${{ env.REGISTRY }}/${IMAGE_REPOSITORY}:${TAG}" >> "$GITHUB_ENV"
- name: Install build dependencies
if: matrix.build_script
run: |
sudo apt-get update
sudo apt-get install -y skopeo jq
# Reproducible build path (worker only — uses build-image.sh)
- name: Build and push reproducible image
if: matrix.build_script
run: |
./deploy/build-image.sh --push "${{ env.IMAGE_REFERENCE }}"
env:
OPENCLAW_VERSION: ${{ inputs.openclaw_version }}
- name: Get image digest (reproducible)
if: matrix.build_script
run: |
DIGEST=$(skopeo inspect oci-archive:./oci.tar | jq -r '.Digest')
if [ -z "${DIGEST}" ]; then
echo "Failed to get image digest from OCI archive" >&2
exit 1
fi
echo "IMAGE_DIGEST=${DIGEST}" >> "$GITHUB_ENV"
# Standard Docker build path (compose-api, updater)
- name: Build and push image
if: ${{ !matrix.build_script }}
uses: docker/build-push-action@v6
id: docker_build
with:
context: ${{ matrix.context }}
file: ${{ matrix.dockerfile }}
push: true
tags: ${{ env.IMAGE_REFERENCE }}
build-args: |
GIT_COMMIT=${{ github.sha }}
${{ inputs.ironclaw_version && format('IRONCLAW_VERSION={0}', inputs.ironclaw_version) || '' }}
- name: Get image digest (standard)
if: ${{ !matrix.build_script }}
run: echo "IMAGE_DIGEST=${{ steps.docker_build.outputs.digest }}" >> "$GITHUB_ENV"
- name: Generate artifact attestation (GitHub)
uses: actions/attest-build-provenance@v3
with:
subject-name: ${{ env.REGISTRY }}/${{ env.IMAGE_REPOSITORY }}
subject-digest: ${{ env.IMAGE_DIGEST }}
push-to-registry: true
- name: Install cosign
uses: sigstore/cosign-installer@v3
- name: Sign image with cosign (keyless)
run: |
cosign sign --yes "${{ env.REGISTRY }}/${{ env.IMAGE_REPOSITORY }}@${{ env.IMAGE_DIGEST }}"
- name: Generate build summary
run: |
{
echo "## ${{ env.IMAGE_REPOSITORY }} docker image"
echo ""
echo "- tag: \`${{ env.IMAGE_REFERENCE }}\`"
echo "- digest: \`${{ env.IMAGE_DIGEST }}\`"
echo "- sigstore: https://search.sigstore.dev/?hash=${{ env.IMAGE_DIGEST }}"
} >> "$GITHUB_STEP_SUMMARY"