name: Docker Release on: push: branches: - main tags: - "v*" paths-ignore: - "docs/**" - "**/*.md" - "**/*.mdx" - ".agents/**" - "skills/**" concurrency: group: docker-release-${{ github.workflow }}-${{ github.ref }} cancel-in-progress: false env: REGISTRY: ghcr.io IMAGE_NAME: ${{ github.repository }} jobs: # Build amd64 images (default + slim share the build stage cache) build-amd64: runs-on: blacksmith-16vcpu-ubuntu-2404 permissions: packages: write contents: read outputs: digest: ${{ steps.build.outputs.digest }} slim-digest: ${{ steps.build-slim.outputs.digest }} steps: - name: Checkout uses: actions/checkout@v4 - name: Set up Docker Builder uses: useblacksmith/setup-docker-builder@v1 - name: Login to GitHub Container Registry uses: docker/login-action@v3 with: registry: ${{ env.REGISTRY }} username: ${{ github.repository_owner }} password: ${{ secrets.GITHUB_TOKEN }} - name: Resolve image tags (amd64) id: tags shell: bash env: IMAGE: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} run: | set -euo pipefail tags=() slim_tags=() if [[ "${GITHUB_REF}" == "refs/heads/main" ]]; then tags+=("${IMAGE}:main-amd64") slim_tags+=("${IMAGE}:main-slim-amd64") fi if [[ "${GITHUB_REF}" == refs/tags/v* ]]; then version="${GITHUB_REF#refs/tags/v}" tags+=("${IMAGE}:${version}-amd64") slim_tags+=("${IMAGE}:${version}-slim-amd64") fi if [[ ${#tags[@]} -eq 0 ]]; then echo "::error::No amd64 tags resolved for ref ${GITHUB_REF}" exit 1 fi { echo "value<> "$GITHUB_OUTPUT" { echo "slim<> "$GITHUB_OUTPUT" - name: Resolve OCI labels (amd64) id: labels shell: bash run: | set -euo pipefail version="${GITHUB_SHA}" if [[ "${GITHUB_REF}" == "refs/heads/main" ]]; then version="main" fi if [[ "${GITHUB_REF}" == refs/tags/v* ]]; then version="${GITHUB_REF#refs/tags/v}" fi created="$(date -u +%Y-%m-%dT%H:%M:%SZ)" { echo "value<> "$GITHUB_OUTPUT" - name: Build and push amd64 image id: build uses: useblacksmith/build-push-action@v2 with: context: . platforms: linux/amd64 tags: ${{ steps.tags.outputs.value }} labels: ${{ steps.labels.outputs.value }} provenance: false push: true - name: Build and push amd64 slim image id: build-slim uses: useblacksmith/build-push-action@v2 with: context: . platforms: linux/amd64 build-args: | OPENCLAW_VARIANT=slim tags: ${{ steps.tags.outputs.slim }} labels: ${{ steps.labels.outputs.value }} provenance: false push: true # Build arm64 images (default + slim share the build stage cache) build-arm64: runs-on: blacksmith-16vcpu-ubuntu-2404-arm permissions: packages: write contents: read outputs: digest: ${{ steps.build.outputs.digest }} slim-digest: ${{ steps.build-slim.outputs.digest }} steps: - name: Checkout uses: actions/checkout@v4 - name: Set up Docker Builder uses: useblacksmith/setup-docker-builder@v1 - name: Login to GitHub Container Registry uses: docker/login-action@v3 with: registry: ${{ env.REGISTRY }} username: ${{ github.repository_owner }} password: ${{ secrets.GITHUB_TOKEN }} - name: Resolve image tags (arm64) id: tags shell: bash env: IMAGE: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} run: | set -euo pipefail tags=() slim_tags=() if [[ "${GITHUB_REF}" == "refs/heads/main" ]]; then tags+=("${IMAGE}:main-arm64") slim_tags+=("${IMAGE}:main-slim-arm64") fi if [[ "${GITHUB_REF}" == refs/tags/v* ]]; then version="${GITHUB_REF#refs/tags/v}" tags+=("${IMAGE}:${version}-arm64") slim_tags+=("${IMAGE}:${version}-slim-arm64") fi if [[ ${#tags[@]} -eq 0 ]]; then echo "::error::No arm64 tags resolved for ref ${GITHUB_REF}" exit 1 fi { echo "value<> "$GITHUB_OUTPUT" { echo "slim<> "$GITHUB_OUTPUT" - name: Resolve OCI labels (arm64) id: labels shell: bash run: | set -euo pipefail version="${GITHUB_SHA}" if [[ "${GITHUB_REF}" == "refs/heads/main" ]]; then version="main" fi if [[ "${GITHUB_REF}" == refs/tags/v* ]]; then version="${GITHUB_REF#refs/tags/v}" fi created="$(date -u +%Y-%m-%dT%H:%M:%SZ)" { echo "value<> "$GITHUB_OUTPUT" - name: Build and push arm64 image id: build uses: useblacksmith/build-push-action@v2 with: context: . platforms: linux/arm64 tags: ${{ steps.tags.outputs.value }} labels: ${{ steps.labels.outputs.value }} provenance: false push: true - name: Build and push arm64 slim image id: build-slim uses: useblacksmith/build-push-action@v2 with: context: . platforms: linux/arm64 build-args: | OPENCLAW_VARIANT=slim tags: ${{ steps.tags.outputs.slim }} labels: ${{ steps.labels.outputs.value }} provenance: false push: true # Create multi-platform manifests create-manifest: runs-on: blacksmith-16vcpu-ubuntu-2404 permissions: packages: write contents: read needs: [build-amd64, build-arm64] steps: - name: Checkout uses: actions/checkout@v4 - name: Login to GitHub Container Registry uses: docker/login-action@v3 with: registry: ${{ env.REGISTRY }} username: ${{ github.repository_owner }} password: ${{ secrets.GITHUB_TOKEN }} - name: Resolve manifest tags id: tags shell: bash env: IMAGE: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} run: | set -euo pipefail tags=() slim_tags=() if [[ "${GITHUB_REF}" == "refs/heads/main" ]]; then tags+=("${IMAGE}:main") slim_tags+=("${IMAGE}:main-slim") fi if [[ "${GITHUB_REF}" == refs/tags/v* ]]; then version="${GITHUB_REF#refs/tags/v}" tags+=("${IMAGE}:${version}") slim_tags+=("${IMAGE}:${version}-slim") if [[ "$version" =~ ^[0-9]+\.[0-9]+\.[0-9]+(-[0-9]+)?$ ]]; then tags+=("${IMAGE}:latest") slim_tags+=("${IMAGE}:slim") fi fi if [[ ${#tags[@]} -eq 0 ]]; then echo "::error::No manifest tags resolved for ref ${GITHUB_REF}" exit 1 fi { echo "value<> "$GITHUB_OUTPUT" { echo "slim<> "$GITHUB_OUTPUT" - name: Create and push default manifest shell: bash run: | set -euo pipefail mapfile -t tags <<< "${{ steps.tags.outputs.value }}" args=() for tag in "${tags[@]}"; do [ -z "$tag" ] && continue args+=("-t" "$tag") done docker buildx imagetools create "${args[@]}" \ ${{ needs.build-amd64.outputs.digest }} \ ${{ needs.build-arm64.outputs.digest }} - name: Create and push slim manifest shell: bash run: | set -euo pipefail mapfile -t tags <<< "${{ steps.tags.outputs.slim }}" args=() for tag in "${tags[@]}"; do [ -z "$tag" ] && continue args+=("-t" "$tag") done docker buildx imagetools create "${args[@]}" \ ${{ needs.build-amd64.outputs.slim-digest }} \ ${{ needs.build-arm64.outputs.slim-digest }}