| 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: |
| FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: "true" |
| REGISTRY: ghcr.io |
| IMAGE_NAME: ${{ github.repository }} |
|
|
| jobs: |
| |
| 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@v6 |
|
|
| - name: Set up Docker Builder |
| uses: docker/setup-buildx-action@v4 |
|
|
| - name: Login to GitHub Container Registry |
| uses: docker/login-action@v4 |
| 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<<EOF" |
| printf "%s\n" "${tags[@]}" |
| echo "EOF" |
| } >> "$GITHUB_OUTPUT" |
| { |
| echo "slim<<EOF" |
| printf "%s\n" "${slim_tags[@]}" |
| echo "EOF" |
| } >> "$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<<EOF" |
| echo "org.opencontainers.image.revision=${GITHUB_SHA}" |
| echo "org.opencontainers.image.version=${version}" |
| echo "org.opencontainers.image.created=${created}" |
| echo "EOF" |
| } >> "$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: |
| 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@v6 |
|
|
| - name: Set up Docker Builder |
| uses: docker/setup-buildx-action@v4 |
|
|
| - name: Login to GitHub Container Registry |
| uses: docker/login-action@v4 |
| 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<<EOF" |
| printf "%s\n" "${tags[@]}" |
| echo "EOF" |
| } >> "$GITHUB_OUTPUT" |
| { |
| echo "slim<<EOF" |
| printf "%s\n" "${slim_tags[@]}" |
| echo "EOF" |
| } >> "$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<<EOF" |
| echo "org.opencontainers.image.revision=${GITHUB_SHA}" |
| echo "org.opencontainers.image.version=${version}" |
| echo "org.opencontainers.image.created=${created}" |
| echo "EOF" |
| } >> "$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-manifest: |
| runs-on: blacksmith-16vcpu-ubuntu-2404 |
| permissions: |
| packages: write |
| contents: read |
| needs: [build-amd64, build-arm64] |
| steps: |
| - name: Checkout |
| uses: actions/checkout@v6 |
|
|
| - name: Login to GitHub Container Registry |
| uses: docker/login-action@v4 |
| 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<<EOF" |
| printf "%s\n" "${tags[@]}" |
| echo "EOF" |
| } >> "$GITHUB_OUTPUT" |
| { |
| echo "slim<<EOF" |
| printf "%s\n" "${slim_tags[@]}" |
| echo "EOF" |
| } >> "$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 }} |
| |