Vendor OpenClaw source as Adolf fork baseline
Some checks failed
ClawSweeper Dispatch / dispatch (push) Has been cancelled
CodeQL / Security High (actions) (push) Has been cancelled
CodeQL / Security High (channel-runtime-boundary) (push) Has been cancelled
CodeQL / Security High (core-auth-secrets) (push) Has been cancelled
CodeQL / Security High (mcp-process-tool-boundary) (push) Has been cancelled
CodeQL / Security High (network-ssrf-boundary) (push) Has been cancelled
CodeQL / Security High (plugin-trust-boundary) (push) Has been cancelled
CodeQL / Security High (process-exec-boundary) (push) Has been cancelled
Docs Sync Publish Repo / sync-publish-repo (push) Has been cancelled
Docs / docs (push) Has been cancelled
OpenClaw Stable Main Closeout / Resolve stable release closeout inputs (push) Has been cancelled
OpenClaw Stable Main Closeout / Verify stable main closeout (push) Has been cancelled
Workflow Sanity / no-tabs (push) Has been cancelled
Workflow Sanity / actionlint (push) Has been cancelled
Workflow Sanity / generated-doc-baselines (push) Has been cancelled
CI / runner-admission (push) Has been cancelled
CI / preflight (push) Has been cancelled
CI / security-fast (push) Has been cancelled
CI / pnpm-store-warmup (push) Has been cancelled
CI / build-artifacts (push) Has been cancelled
CI / native-i18n (push) Has been cancelled
CI / ${{ matrix.check_name }} (push) Has been cancelled
CI / ${{ matrix.checkName }} (push) Has been cancelled
CI / checks-node-compat-node22 (push) Has been cancelled
CI / check-bundled-channel-config-metadata (push) Has been cancelled
CI / check-dependencies (push) Has been cancelled
CI / check-guards (push) Has been cancelled
CI / check-lint (push) Has been cancelled
CI / check-prod-types (push) Has been cancelled
CI / check-shrinkwrap (push) Has been cancelled
CI / check-test-types (push) Has been cancelled
CI / check-additional-boundaries-a (push) Has been cancelled
CI / check-additional-boundaries-bcd (push) Has been cancelled
CI / check-additional-extension-bundled (push) Has been cancelled
CI / check-additional-extension-channels (push) Has been cancelled
CI / check-additional-extension-package-boundary (push) Has been cancelled
CI / check-additional-runtime-topology-architecture (push) Has been cancelled
CI / check-session-accessor-boundary (push) Has been cancelled
CI / check-session-transcript-reader-boundary (push) Has been cancelled
CI / check-docs (push) Has been cancelled
CI / skills-python (push) Has been cancelled
CI / macos-swift (push) Has been cancelled
CI / ios-build (push) Has been cancelled
CI / ci-timings-summary (push) Has been cancelled
Native App Locale Refresh / Refresh native fa (push) Has been cancelled
Native App Locale Refresh / Refresh native fr (push) Has been cancelled
Native App Locale Refresh / Refresh native hi (push) Has been cancelled
Native App Locale Refresh / Refresh native id (push) Has been cancelled
Native App Locale Refresh / Refresh native it (push) Has been cancelled
Native App Locale Refresh / Refresh native ja-JP (push) Has been cancelled
Control UI Locale Refresh / plan (push) Has been cancelled
Control UI Locale Refresh / Refresh ${{ matrix.locale }} (push) Has been cancelled
Control UI Locale Refresh / Commit control UI locale refresh (push) Has been cancelled
Live Media Runner Image / Build live media runner image (push) Has been cancelled
Native App Locale Refresh / Refresh native ar (push) Has been cancelled
Native App Locale Refresh / Refresh native de (push) Has been cancelled
Native App Locale Refresh / Refresh native es (push) Has been cancelled
Native App Locale Refresh / Refresh native ko (push) Has been cancelled
Native App Locale Refresh / Refresh native nl (push) Has been cancelled
Native App Locale Refresh / Refresh native pl (push) Has been cancelled
Native App Locale Refresh / Refresh native pt-BR (push) Has been cancelled
Native App Locale Refresh / Refresh native ru (push) Has been cancelled
Native App Locale Refresh / Refresh native sv (push) Has been cancelled
Native App Locale Refresh / Refresh native th (push) Has been cancelled
Native App Locale Refresh / Refresh native tr (push) Has been cancelled
Native App Locale Refresh / Refresh native uk (push) Has been cancelled
Native App Locale Refresh / Refresh native vi (push) Has been cancelled
Native App Locale Refresh / Refresh native zh-CN (push) Has been cancelled
Native App Locale Refresh / Refresh native zh-TW (push) Has been cancelled
Native App Locale Refresh / Commit native locale refresh (push) Has been cancelled
Plugin Init Scaffold Validation / Validate provider scaffold (push) Has been cancelled
Plugin NPM Release / preview_plugins_npm (push) Has been cancelled
Plugin NPM Release / Validate release publish approval (push) Has been cancelled
Plugin NPM Release / preview_plugin_pack (push) Has been cancelled
Plugin NPM Release / publish_plugins_npm (push) Has been cancelled
Sandbox Common Smoke / sandbox-common-smoke (push) Has been cancelled
Website Installer Sync / static (push) Has been cancelled
Website Installer Sync / linux-docker (push) Has been cancelled
Website Installer Sync / macos-installer (push) Has been cancelled
Website Installer Sync / windows-installer (push) Has been cancelled
Website Installer Sync / sync-website (push) Has been cancelled
Some checks failed
ClawSweeper Dispatch / dispatch (push) Has been cancelled
CodeQL / Security High (actions) (push) Has been cancelled
CodeQL / Security High (channel-runtime-boundary) (push) Has been cancelled
CodeQL / Security High (core-auth-secrets) (push) Has been cancelled
CodeQL / Security High (mcp-process-tool-boundary) (push) Has been cancelled
CodeQL / Security High (network-ssrf-boundary) (push) Has been cancelled
CodeQL / Security High (plugin-trust-boundary) (push) Has been cancelled
CodeQL / Security High (process-exec-boundary) (push) Has been cancelled
Docs Sync Publish Repo / sync-publish-repo (push) Has been cancelled
Docs / docs (push) Has been cancelled
OpenClaw Stable Main Closeout / Resolve stable release closeout inputs (push) Has been cancelled
OpenClaw Stable Main Closeout / Verify stable main closeout (push) Has been cancelled
Workflow Sanity / no-tabs (push) Has been cancelled
Workflow Sanity / actionlint (push) Has been cancelled
Workflow Sanity / generated-doc-baselines (push) Has been cancelled
CI / runner-admission (push) Has been cancelled
CI / preflight (push) Has been cancelled
CI / security-fast (push) Has been cancelled
CI / pnpm-store-warmup (push) Has been cancelled
CI / build-artifacts (push) Has been cancelled
CI / native-i18n (push) Has been cancelled
CI / ${{ matrix.check_name }} (push) Has been cancelled
CI / ${{ matrix.checkName }} (push) Has been cancelled
CI / checks-node-compat-node22 (push) Has been cancelled
CI / check-bundled-channel-config-metadata (push) Has been cancelled
CI / check-dependencies (push) Has been cancelled
CI / check-guards (push) Has been cancelled
CI / check-lint (push) Has been cancelled
CI / check-prod-types (push) Has been cancelled
CI / check-shrinkwrap (push) Has been cancelled
CI / check-test-types (push) Has been cancelled
CI / check-additional-boundaries-a (push) Has been cancelled
CI / check-additional-boundaries-bcd (push) Has been cancelled
CI / check-additional-extension-bundled (push) Has been cancelled
CI / check-additional-extension-channels (push) Has been cancelled
CI / check-additional-extension-package-boundary (push) Has been cancelled
CI / check-additional-runtime-topology-architecture (push) Has been cancelled
CI / check-session-accessor-boundary (push) Has been cancelled
CI / check-session-transcript-reader-boundary (push) Has been cancelled
CI / check-docs (push) Has been cancelled
CI / skills-python (push) Has been cancelled
CI / macos-swift (push) Has been cancelled
CI / ios-build (push) Has been cancelled
CI / ci-timings-summary (push) Has been cancelled
Native App Locale Refresh / Refresh native fa (push) Has been cancelled
Native App Locale Refresh / Refresh native fr (push) Has been cancelled
Native App Locale Refresh / Refresh native hi (push) Has been cancelled
Native App Locale Refresh / Refresh native id (push) Has been cancelled
Native App Locale Refresh / Refresh native it (push) Has been cancelled
Native App Locale Refresh / Refresh native ja-JP (push) Has been cancelled
Control UI Locale Refresh / plan (push) Has been cancelled
Control UI Locale Refresh / Refresh ${{ matrix.locale }} (push) Has been cancelled
Control UI Locale Refresh / Commit control UI locale refresh (push) Has been cancelled
Live Media Runner Image / Build live media runner image (push) Has been cancelled
Native App Locale Refresh / Refresh native ar (push) Has been cancelled
Native App Locale Refresh / Refresh native de (push) Has been cancelled
Native App Locale Refresh / Refresh native es (push) Has been cancelled
Native App Locale Refresh / Refresh native ko (push) Has been cancelled
Native App Locale Refresh / Refresh native nl (push) Has been cancelled
Native App Locale Refresh / Refresh native pl (push) Has been cancelled
Native App Locale Refresh / Refresh native pt-BR (push) Has been cancelled
Native App Locale Refresh / Refresh native ru (push) Has been cancelled
Native App Locale Refresh / Refresh native sv (push) Has been cancelled
Native App Locale Refresh / Refresh native th (push) Has been cancelled
Native App Locale Refresh / Refresh native tr (push) Has been cancelled
Native App Locale Refresh / Refresh native uk (push) Has been cancelled
Native App Locale Refresh / Refresh native vi (push) Has been cancelled
Native App Locale Refresh / Refresh native zh-CN (push) Has been cancelled
Native App Locale Refresh / Refresh native zh-TW (push) Has been cancelled
Native App Locale Refresh / Commit native locale refresh (push) Has been cancelled
Plugin Init Scaffold Validation / Validate provider scaffold (push) Has been cancelled
Plugin NPM Release / preview_plugins_npm (push) Has been cancelled
Plugin NPM Release / Validate release publish approval (push) Has been cancelled
Plugin NPM Release / preview_plugin_pack (push) Has been cancelled
Plugin NPM Release / publish_plugins_npm (push) Has been cancelled
Sandbox Common Smoke / sandbox-common-smoke (push) Has been cancelled
Website Installer Sync / static (push) Has been cancelled
Website Installer Sync / linux-docker (push) Has been cancelled
Website Installer Sync / macos-installer (push) Has been cancelled
Website Installer Sync / windows-installer (push) Has been cancelled
Website Installer Sync / sync-website (push) Has been cancelled
Adolf is a fork/vendored clone of github.com/openclaw/openclaw (v2026.6.11), free to diverge. Tree copied sans upstream .git; upstream remote added for future syncs. Node pinned to 24 (.nvmrc); engines already require >=22.19. Preserves docs/ARCHITECTURE.md. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LeqyaxJF2nbRXJtae2kNB2
This commit is contained in:
820
.github/workflows/docker-release.yml
vendored
Normal file
820
.github/workflows/docker-release.yml
vendored
Normal file
@@ -0,0 +1,820 @@
|
||||
name: Docker Release
|
||||
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- "v*"
|
||||
- "!v*-alpha.*"
|
||||
paths-ignore:
|
||||
- "docs/**"
|
||||
- "**/*.md"
|
||||
- "**/*.mdx"
|
||||
- ".agents/**"
|
||||
- "skills/**"
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
tag:
|
||||
description: Existing stable or beta release tag to backfill (for example v2026.3.22 or v2026.3.22-beta.1)
|
||||
required: true
|
||||
type: string
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.event_name == 'workflow_dispatch' && format('docker-release-manual-{0}', inputs.tag) || format('docker-release-push-{0}', github.run_id) }}
|
||||
cancel-in-progress: false
|
||||
|
||||
env:
|
||||
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: "true"
|
||||
REGISTRY: ghcr.io
|
||||
IMAGE_NAME: ${{ github.repository }}
|
||||
DOCKERHUB_REGISTRY: docker.io
|
||||
DOCKERHUB_IMAGE_NAME: openclaw/openclaw
|
||||
|
||||
jobs:
|
||||
validate_manual_backfill:
|
||||
if: github.event_name == 'workflow_dispatch'
|
||||
runs-on: ubuntu-24.04
|
||||
permissions:
|
||||
contents: read
|
||||
steps:
|
||||
- name: Validate tag input format
|
||||
env:
|
||||
RELEASE_TAG: ${{ inputs.tag }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
if [[ "${RELEASE_TAG}" == *"-alpha."* ]]; then
|
||||
echo "Docker alpha image publishing is disabled."
|
||||
exit 1
|
||||
fi
|
||||
if [[ ! "${RELEASE_TAG}" =~ ^v[0-9]{4}\.[1-9][0-9]*\.[1-9][0-9]*(-beta\.[1-9][0-9]*)?$ ]]; then
|
||||
echo "Invalid release tag: ${RELEASE_TAG}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
- name: Checkout selected tag
|
||||
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
|
||||
with:
|
||||
ref: refs/tags/${{ inputs.tag }}
|
||||
fetch-depth: 0
|
||||
|
||||
approve_manual_backfill:
|
||||
if: github.event_name == 'workflow_dispatch'
|
||||
needs: validate_manual_backfill
|
||||
# WARNING: KEEP MANUAL BACKFILLS GATED BY THE docker-release ENVIRONMENT.
|
||||
runs-on: ubuntu-24.04
|
||||
environment: docker-release
|
||||
permissions: {}
|
||||
steps:
|
||||
- name: Approve Docker backfill
|
||||
env:
|
||||
RELEASE_TAG: ${{ inputs.tag }}
|
||||
run: echo "Approved Docker backfill for $RELEASE_TAG"
|
||||
|
||||
validate_publish_config:
|
||||
runs-on: ubuntu-24.04
|
||||
permissions:
|
||||
contents: read
|
||||
steps:
|
||||
- name: Validate Docker Hub publish credentials
|
||||
env:
|
||||
DOCKERHUB_USERNAME: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||
DOCKERHUB_TOKEN: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
DOCKERHUB_IMAGE: ${{ env.DOCKERHUB_REGISTRY }}/${{ env.DOCKERHUB_IMAGE_NAME }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
if [[ -z "${DOCKERHUB_USERNAME}" || -z "${DOCKERHUB_TOKEN}" ]]; then
|
||||
echo "::error::Docker Hub publishing requires DOCKERHUB_USERNAME and DOCKERHUB_TOKEN secrets."
|
||||
exit 1
|
||||
fi
|
||||
echo "Docker Hub publishing configured for ${DOCKERHUB_IMAGE}."
|
||||
|
||||
# KEEP THIS WORKFLOW ON GITHUB-HOSTED RUNNERS.
|
||||
# DO NOT MOVE IT BACK TO BLACKSMITH WITHOUT RE-VALIDATING TAG BUILDS AND BACKFILLS.
|
||||
# Build amd64 image. Default and slim tags point to the same slim runtime.
|
||||
build-amd64:
|
||||
needs: [approve_manual_backfill, validate_publish_config]
|
||||
if: ${{ always() && needs.validate_publish_config.result == 'success' && (github.event_name != 'workflow_dispatch' || needs.approve_manual_backfill.result == 'success') }}
|
||||
# WARNING: DO NOT REVERT THIS TO A BLACKSMITH RUNNER WITHOUT RE-VALIDATING TAG BACKFILLS.
|
||||
runs-on: ubuntu-24.04
|
||||
permissions:
|
||||
packages: write
|
||||
contents: read
|
||||
outputs:
|
||||
digest: ${{ steps.build.outputs.digest }}
|
||||
browser_digest: ${{ steps.build-browser.outputs.digest }}
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
|
||||
with:
|
||||
ref: ${{ github.event_name == 'workflow_dispatch' && format('refs/tags/{0}', inputs.tag) || github.ref }}
|
||||
fetch-depth: 0
|
||||
|
||||
- &buildkit_prepull_step
|
||||
name: Pre-pull BuildKit image
|
||||
shell: bash
|
||||
env:
|
||||
BUILDKIT_IMAGE: moby/buildkit:buildx-stable-1
|
||||
run: |
|
||||
set -euo pipefail
|
||||
for attempt in 1 2 3 4; do
|
||||
if docker pull "${BUILDKIT_IMAGE}"; then
|
||||
exit 0
|
||||
fi
|
||||
if [[ "${attempt}" == "4" ]]; then
|
||||
echo "::error::Failed to pull ${BUILDKIT_IMAGE} after ${attempt} attempts"
|
||||
exit 1
|
||||
fi
|
||||
sleep_seconds=$((attempt * 10))
|
||||
echo "BuildKit image pull failed; retrying in ${sleep_seconds}s (${attempt}/4)."
|
||||
sleep "${sleep_seconds}"
|
||||
done
|
||||
|
||||
- name: Set up Docker Builder
|
||||
uses: docker/setup-buildx-action@d7f5e7f509e45cec5c76c4d5afdd7de93d0b3df5 # v4
|
||||
|
||||
- name: Login to GitHub Container Registry
|
||||
uses: docker/login-action@650006c6eb7dba73a995cc03b0b2d7f5ca915bee # v4
|
||||
with:
|
||||
registry: ${{ env.REGISTRY }}
|
||||
username: ${{ github.repository_owner }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Login to Docker Hub
|
||||
uses: docker/login-action@650006c6eb7dba73a995cc03b0b2d7f5ca915bee # v4
|
||||
with:
|
||||
registry: ${{ env.DOCKERHUB_REGISTRY }}
|
||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
|
||||
- name: Resolve image tags (amd64)
|
||||
id: tags
|
||||
shell: bash
|
||||
env:
|
||||
GHCR_IMAGE: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
|
||||
DOCKERHUB_IMAGE: ${{ env.DOCKERHUB_REGISTRY }}/${{ env.DOCKERHUB_IMAGE_NAME }}
|
||||
SOURCE_REF: ${{ github.event_name == 'workflow_dispatch' && format('refs/tags/{0}', inputs.tag) || github.ref }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
tags=()
|
||||
slim_tags=()
|
||||
browser_tags=()
|
||||
images=("${GHCR_IMAGE}" "${DOCKERHUB_IMAGE}")
|
||||
browser_supported=0
|
||||
if grep -q '^ARG OPENCLAW_INSTALL_BROWSER' Dockerfile; then
|
||||
browser_supported=1
|
||||
fi
|
||||
if [[ "${SOURCE_REF}" == refs/tags/v* ]]; then
|
||||
version="${SOURCE_REF#refs/tags/v}"
|
||||
for image in "${images[@]}"; do
|
||||
tags+=("${image}:${version}-amd64")
|
||||
slim_tags+=("${image}:${version}-slim-amd64")
|
||||
if [[ "${browser_supported}" == "1" ]]; then
|
||||
browser_tags+=("${image}:${version}-browser-amd64")
|
||||
fi
|
||||
done
|
||||
fi
|
||||
if [[ ${#tags[@]} -eq 0 ]]; then
|
||||
echo "::error::No amd64 tags resolved for ref ${SOURCE_REF}"
|
||||
exit 1
|
||||
fi
|
||||
{
|
||||
echo "value<<EOF"
|
||||
printf "%s\n" "${tags[@]}" "${slim_tags[@]}"
|
||||
echo "EOF"
|
||||
echo "browser<<EOF"
|
||||
printf "%s\n" "${browser_tags[@]}"
|
||||
echo "EOF"
|
||||
} >> "$GITHUB_OUTPUT"
|
||||
|
||||
- name: Resolve OCI labels (amd64)
|
||||
id: labels
|
||||
shell: bash
|
||||
env:
|
||||
SOURCE_REF: ${{ github.event_name == 'workflow_dispatch' && format('refs/tags/{0}', inputs.tag) || github.ref }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
source_sha="$(git rev-parse HEAD)"
|
||||
version="${source_sha}"
|
||||
if [[ "${SOURCE_REF}" == "refs/heads/main" ]]; then
|
||||
version="main"
|
||||
fi
|
||||
if [[ "${SOURCE_REF}" == refs/tags/v* ]]; then
|
||||
version="${SOURCE_REF#refs/tags/v}"
|
||||
fi
|
||||
created="$(date -u +%Y-%m-%dT%H:%M:%SZ)"
|
||||
{
|
||||
echo "value<<EOF"
|
||||
echo "org.opencontainers.image.revision=${source_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
|
||||
# WARNING: KEEP THE OFFICIAL DOCKER ACTION HERE; DO NOT SWITCH THIS BACK TO BLACKSMITH BLINDLY.
|
||||
uses: docker/build-push-action@f9f3042f7e2789586610d6e8b85c8f03e5195baf # v7.2.0
|
||||
with:
|
||||
context: .
|
||||
platforms: linux/amd64
|
||||
cache-from: type=gha,scope=docker-release-amd64
|
||||
cache-to: type=gha,mode=max,scope=docker-release-amd64
|
||||
build-args: |
|
||||
OPENCLAW_EXTENSIONS=diagnostics-otel,codex
|
||||
tags: ${{ steps.tags.outputs.value }}
|
||||
labels: ${{ steps.labels.outputs.value }}
|
||||
sbom: true
|
||||
provenance: mode=max
|
||||
push: true
|
||||
|
||||
- name: Build and push amd64 browser image
|
||||
id: build-browser
|
||||
if: steps.tags.outputs.browser != ''
|
||||
# WARNING: KEEP THE OFFICIAL DOCKER ACTION HERE; DO NOT SWITCH THIS BACK TO BLACKSMITH BLINDLY.
|
||||
uses: docker/build-push-action@f9f3042f7e2789586610d6e8b85c8f03e5195baf # v7.2.0
|
||||
with:
|
||||
context: .
|
||||
platforms: linux/amd64
|
||||
cache-from: |
|
||||
type=gha,scope=docker-release-amd64
|
||||
type=gha,scope=docker-release-browser-amd64
|
||||
cache-to: type=gha,mode=max,scope=docker-release-browser-amd64
|
||||
build-args: |
|
||||
OPENCLAW_EXTENSIONS=diagnostics-otel,codex
|
||||
OPENCLAW_INSTALL_BROWSER=1
|
||||
tags: ${{ steps.tags.outputs.browser }}
|
||||
labels: ${{ steps.labels.outputs.value }}
|
||||
sbom: true
|
||||
provenance: mode=max
|
||||
push: true
|
||||
|
||||
- name: Smoke test amd64 runtime workspace templates
|
||||
shell: bash
|
||||
env:
|
||||
IMAGE_REFS: ${{ steps.tags.outputs.value }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
mapfile -t image_refs <<< "${IMAGE_REFS}"
|
||||
image_ref="${image_refs[0]}"
|
||||
if [[ -z "${image_ref}" ]]; then
|
||||
echo "::error::No amd64 image ref resolved for runtime template smoke"
|
||||
exit 1
|
||||
fi
|
||||
docker run --rm --entrypoint /bin/sh "${image_ref}" -lc '
|
||||
set -eu
|
||||
test -f /app/src/agents/templates/HEARTBEAT.md
|
||||
temp_root="$(mktemp -d)"
|
||||
trap "rm -rf \"${temp_root}\"" EXIT
|
||||
mkdir -p "${temp_root}/home" "${temp_root}/cwd"
|
||||
cd "${temp_root}/cwd"
|
||||
set +e
|
||||
HOME="${temp_root}/home" \
|
||||
USERPROFILE="${temp_root}/home" \
|
||||
OPENCLAW_HOME="${temp_root}/home" \
|
||||
OPENCLAW_NO_ONBOARD=1 \
|
||||
OPENCLAW_SUPPRESS_NOTES=1 \
|
||||
OPENCLAW_DISABLE_BUNDLED_PLUGINS=1 \
|
||||
OPENCLAW_DISABLE_BUNDLED_ENTRY_SOURCE_FALLBACK=1 \
|
||||
AWS_EC2_METADATA_DISABLED=true \
|
||||
AWS_SHARED_CREDENTIALS_FILE="${temp_root}/home/.aws/credentials" \
|
||||
AWS_CONFIG_FILE="${temp_root}/home/.aws/config" \
|
||||
node /app/openclaw.mjs agent --message "workspace bootstrap smoke" --session-id "workspace-bootstrap-smoke" --local --timeout 1 --json \
|
||||
>"${temp_root}/out.log" 2>&1
|
||||
status="$?"
|
||||
set -e
|
||||
if grep -F "Missing workspace template:" "${temp_root}/out.log"; then
|
||||
cat "${temp_root}/out.log"
|
||||
exit 1
|
||||
fi
|
||||
test -f "${temp_root}/home/.openclaw/workspace/HEARTBEAT.md"
|
||||
if [ "${status}" -ne 0 ]; then
|
||||
cat "${temp_root}/out.log"
|
||||
fi
|
||||
'
|
||||
|
||||
- name: Smoke test amd64 browser image
|
||||
if: steps.tags.outputs.browser != ''
|
||||
shell: bash
|
||||
env:
|
||||
IMAGE_REFS: ${{ steps.tags.outputs.browser }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
mapfile -t image_refs <<< "${IMAGE_REFS}"
|
||||
image_ref="${image_refs[0]}"
|
||||
if [[ -z "${image_ref}" ]]; then
|
||||
echo "::error::No amd64 browser image ref resolved"
|
||||
exit 1
|
||||
fi
|
||||
docker run --rm --entrypoint /bin/sh "${image_ref}" -lc '
|
||||
set -eu
|
||||
browser="$(find /home/node/.cache/ms-playwright -maxdepth 5 -type f \( -name chrome -o -name chromium -o -name chrome-headless-shell \) -print | head -1)"
|
||||
test -n "${browser}"
|
||||
"${browser}" --version
|
||||
'
|
||||
|
||||
# Build arm64 image. Default and slim tags point to the same slim runtime.
|
||||
build-arm64:
|
||||
needs: [approve_manual_backfill, validate_publish_config]
|
||||
if: ${{ always() && needs.validate_publish_config.result == 'success' && (github.event_name != 'workflow_dispatch' || needs.approve_manual_backfill.result == 'success') }}
|
||||
# WARNING: DO NOT REVERT THIS TO A BLACKSMITH RUNNER WITHOUT RE-VALIDATING TAG BACKFILLS.
|
||||
runs-on: ubuntu-24.04-arm
|
||||
permissions:
|
||||
packages: write
|
||||
contents: read
|
||||
outputs:
|
||||
digest: ${{ steps.build.outputs.digest }}
|
||||
browser_digest: ${{ steps.build-browser.outputs.digest }}
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
|
||||
with:
|
||||
ref: ${{ github.event_name == 'workflow_dispatch' && format('refs/tags/{0}', inputs.tag) || github.ref }}
|
||||
fetch-depth: 0
|
||||
|
||||
- *buildkit_prepull_step
|
||||
- name: Set up Docker Builder
|
||||
uses: docker/setup-buildx-action@d7f5e7f509e45cec5c76c4d5afdd7de93d0b3df5 # v4
|
||||
|
||||
- name: Login to GitHub Container Registry
|
||||
uses: docker/login-action@650006c6eb7dba73a995cc03b0b2d7f5ca915bee # v4
|
||||
with:
|
||||
registry: ${{ env.REGISTRY }}
|
||||
username: ${{ github.repository_owner }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Login to Docker Hub
|
||||
uses: docker/login-action@650006c6eb7dba73a995cc03b0b2d7f5ca915bee # v4
|
||||
with:
|
||||
registry: ${{ env.DOCKERHUB_REGISTRY }}
|
||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
|
||||
- name: Resolve image tags (arm64)
|
||||
id: tags
|
||||
shell: bash
|
||||
env:
|
||||
GHCR_IMAGE: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
|
||||
DOCKERHUB_IMAGE: ${{ env.DOCKERHUB_REGISTRY }}/${{ env.DOCKERHUB_IMAGE_NAME }}
|
||||
SOURCE_REF: ${{ github.event_name == 'workflow_dispatch' && format('refs/tags/{0}', inputs.tag) || github.ref }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
tags=()
|
||||
slim_tags=()
|
||||
browser_tags=()
|
||||
images=("${GHCR_IMAGE}" "${DOCKERHUB_IMAGE}")
|
||||
browser_supported=0
|
||||
if grep -q '^ARG OPENCLAW_INSTALL_BROWSER' Dockerfile; then
|
||||
browser_supported=1
|
||||
fi
|
||||
if [[ "${SOURCE_REF}" == refs/tags/v* ]]; then
|
||||
version="${SOURCE_REF#refs/tags/v}"
|
||||
for image in "${images[@]}"; do
|
||||
tags+=("${image}:${version}-arm64")
|
||||
slim_tags+=("${image}:${version}-slim-arm64")
|
||||
if [[ "${browser_supported}" == "1" ]]; then
|
||||
browser_tags+=("${image}:${version}-browser-arm64")
|
||||
fi
|
||||
done
|
||||
fi
|
||||
if [[ ${#tags[@]} -eq 0 ]]; then
|
||||
echo "::error::No arm64 tags resolved for ref ${SOURCE_REF}"
|
||||
exit 1
|
||||
fi
|
||||
{
|
||||
echo "value<<EOF"
|
||||
printf "%s\n" "${tags[@]}" "${slim_tags[@]}"
|
||||
echo "EOF"
|
||||
echo "browser<<EOF"
|
||||
printf "%s\n" "${browser_tags[@]}"
|
||||
echo "EOF"
|
||||
} >> "$GITHUB_OUTPUT"
|
||||
|
||||
- name: Resolve OCI labels (arm64)
|
||||
id: labels
|
||||
shell: bash
|
||||
env:
|
||||
SOURCE_REF: ${{ github.event_name == 'workflow_dispatch' && format('refs/tags/{0}', inputs.tag) || github.ref }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
source_sha="$(git rev-parse HEAD)"
|
||||
version="${source_sha}"
|
||||
if [[ "${SOURCE_REF}" == "refs/heads/main" ]]; then
|
||||
version="main"
|
||||
fi
|
||||
if [[ "${SOURCE_REF}" == refs/tags/v* ]]; then
|
||||
version="${SOURCE_REF#refs/tags/v}"
|
||||
fi
|
||||
created="$(date -u +%Y-%m-%dT%H:%M:%SZ)"
|
||||
{
|
||||
echo "value<<EOF"
|
||||
echo "org.opencontainers.image.revision=${source_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
|
||||
# WARNING: KEEP THE OFFICIAL DOCKER ACTION HERE; DO NOT SWITCH THIS BACK TO BLACKSMITH BLINDLY.
|
||||
uses: docker/build-push-action@f9f3042f7e2789586610d6e8b85c8f03e5195baf # v7.2.0
|
||||
with:
|
||||
context: .
|
||||
platforms: linux/arm64
|
||||
cache-from: type=gha,scope=docker-release-arm64
|
||||
cache-to: type=gha,mode=max,scope=docker-release-arm64
|
||||
build-args: |
|
||||
OPENCLAW_EXTENSIONS=diagnostics-otel,codex
|
||||
tags: ${{ steps.tags.outputs.value }}
|
||||
labels: ${{ steps.labels.outputs.value }}
|
||||
sbom: true
|
||||
provenance: mode=max
|
||||
push: true
|
||||
|
||||
- name: Build and push arm64 browser image
|
||||
id: build-browser
|
||||
if: steps.tags.outputs.browser != ''
|
||||
# WARNING: KEEP THE OFFICIAL DOCKER ACTION HERE; DO NOT SWITCH THIS BACK TO BLACKSMITH BLINDLY.
|
||||
uses: docker/build-push-action@f9f3042f7e2789586610d6e8b85c8f03e5195baf # v7.2.0
|
||||
with:
|
||||
context: .
|
||||
platforms: linux/arm64
|
||||
cache-from: |
|
||||
type=gha,scope=docker-release-arm64
|
||||
type=gha,scope=docker-release-browser-arm64
|
||||
cache-to: type=gha,mode=max,scope=docker-release-browser-arm64
|
||||
build-args: |
|
||||
OPENCLAW_EXTENSIONS=diagnostics-otel,codex
|
||||
OPENCLAW_INSTALL_BROWSER=1
|
||||
tags: ${{ steps.tags.outputs.browser }}
|
||||
labels: ${{ steps.labels.outputs.value }}
|
||||
sbom: true
|
||||
provenance: mode=max
|
||||
push: true
|
||||
|
||||
- name: Smoke test arm64 runtime workspace templates
|
||||
shell: bash
|
||||
env:
|
||||
IMAGE_REFS: ${{ steps.tags.outputs.value }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
mapfile -t image_refs <<< "${IMAGE_REFS}"
|
||||
image_ref="${image_refs[0]}"
|
||||
if [[ -z "${image_ref}" ]]; then
|
||||
echo "::error::No arm64 image ref resolved for runtime template smoke"
|
||||
exit 1
|
||||
fi
|
||||
docker run --rm --entrypoint /bin/sh "${image_ref}" -lc '
|
||||
set -eu
|
||||
test -f /app/src/agents/templates/HEARTBEAT.md
|
||||
temp_root="$(mktemp -d)"
|
||||
trap "rm -rf \"${temp_root}\"" EXIT
|
||||
mkdir -p "${temp_root}/home" "${temp_root}/cwd"
|
||||
cd "${temp_root}/cwd"
|
||||
set +e
|
||||
HOME="${temp_root}/home" \
|
||||
USERPROFILE="${temp_root}/home" \
|
||||
OPENCLAW_HOME="${temp_root}/home" \
|
||||
OPENCLAW_NO_ONBOARD=1 \
|
||||
OPENCLAW_SUPPRESS_NOTES=1 \
|
||||
OPENCLAW_DISABLE_BUNDLED_PLUGINS=1 \
|
||||
OPENCLAW_DISABLE_BUNDLED_ENTRY_SOURCE_FALLBACK=1 \
|
||||
AWS_EC2_METADATA_DISABLED=true \
|
||||
AWS_SHARED_CREDENTIALS_FILE="${temp_root}/home/.aws/credentials" \
|
||||
AWS_CONFIG_FILE="${temp_root}/home/.aws/config" \
|
||||
node /app/openclaw.mjs agent --message "workspace bootstrap smoke" --session-id "workspace-bootstrap-smoke" --local --timeout 1 --json \
|
||||
>"${temp_root}/out.log" 2>&1
|
||||
status="$?"
|
||||
set -e
|
||||
if grep -F "Missing workspace template:" "${temp_root}/out.log"; then
|
||||
cat "${temp_root}/out.log"
|
||||
exit 1
|
||||
fi
|
||||
test -f "${temp_root}/home/.openclaw/workspace/HEARTBEAT.md"
|
||||
if [ "${status}" -ne 0 ]; then
|
||||
cat "${temp_root}/out.log"
|
||||
fi
|
||||
'
|
||||
|
||||
- name: Smoke test arm64 browser image
|
||||
if: steps.tags.outputs.browser != ''
|
||||
shell: bash
|
||||
env:
|
||||
IMAGE_REFS: ${{ steps.tags.outputs.browser }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
mapfile -t image_refs <<< "${IMAGE_REFS}"
|
||||
image_ref="${image_refs[0]}"
|
||||
if [[ -z "${image_ref}" ]]; then
|
||||
echo "::error::No arm64 browser image ref resolved"
|
||||
exit 1
|
||||
fi
|
||||
docker run --rm --entrypoint /bin/sh "${image_ref}" -lc '
|
||||
set -eu
|
||||
browser="$(find /home/node/.cache/ms-playwright -maxdepth 5 -type f \( -name chrome -o -name chromium -o -name chrome-headless-shell \) -print | head -1)"
|
||||
test -n "${browser}"
|
||||
"${browser}" --version
|
||||
'
|
||||
|
||||
# Create multi-platform manifests
|
||||
create-manifest:
|
||||
needs: [approve_manual_backfill, validate_publish_config, build-amd64, build-arm64]
|
||||
if: ${{ always() && needs.validate_publish_config.result == 'success' && needs.build-amd64.result == 'success' && needs.build-arm64.result == 'success' && (github.event_name != 'workflow_dispatch' || needs.approve_manual_backfill.result == 'success') }}
|
||||
# WARNING: DO NOT REVERT THIS TO A BLACKSMITH RUNNER WITHOUT RE-VALIDATING TAG BACKFILLS.
|
||||
runs-on: ubuntu-24.04
|
||||
permissions:
|
||||
packages: write
|
||||
contents: read
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
|
||||
with:
|
||||
ref: ${{ github.event_name == 'workflow_dispatch' && format('refs/tags/{0}', inputs.tag) || github.ref }}
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Login to GitHub Container Registry
|
||||
uses: docker/login-action@650006c6eb7dba73a995cc03b0b2d7f5ca915bee # v4
|
||||
with:
|
||||
registry: ${{ env.REGISTRY }}
|
||||
username: ${{ github.repository_owner }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Login to Docker Hub
|
||||
uses: docker/login-action@650006c6eb7dba73a995cc03b0b2d7f5ca915bee # v4
|
||||
with:
|
||||
registry: ${{ env.DOCKERHUB_REGISTRY }}
|
||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
|
||||
- name: Resolve manifest tags
|
||||
id: tags
|
||||
shell: bash
|
||||
env:
|
||||
GHCR_IMAGE: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
|
||||
DOCKERHUB_IMAGE: ${{ env.DOCKERHUB_REGISTRY }}/${{ env.DOCKERHUB_IMAGE_NAME }}
|
||||
SOURCE_REF: ${{ github.event_name == 'workflow_dispatch' && format('refs/tags/{0}', inputs.tag) || github.ref }}
|
||||
IS_MANUAL_BACKFILL: ${{ github.event_name == 'workflow_dispatch' && '1' || '0' }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
tags=()
|
||||
slim_tags=()
|
||||
browser_tags=()
|
||||
dockerhub_tags=()
|
||||
dockerhub_slim_tags=()
|
||||
dockerhub_browser_tags=()
|
||||
browser_supported=0
|
||||
if grep -q '^ARG OPENCLAW_INSTALL_BROWSER' Dockerfile; then
|
||||
browser_supported=1
|
||||
fi
|
||||
if [[ "${SOURCE_REF}" == refs/tags/v* ]]; then
|
||||
version="${SOURCE_REF#refs/tags/v}"
|
||||
tags+=("${GHCR_IMAGE}:${version}")
|
||||
slim_tags+=("${GHCR_IMAGE}:${version}-slim")
|
||||
dockerhub_tags+=("${DOCKERHUB_IMAGE}:${version}")
|
||||
dockerhub_slim_tags+=("${DOCKERHUB_IMAGE}:${version}-slim")
|
||||
if [[ "${browser_supported}" == "1" ]]; then
|
||||
browser_tags+=("${GHCR_IMAGE}:${version}-browser")
|
||||
dockerhub_browser_tags+=("${DOCKERHUB_IMAGE}:${version}-browser")
|
||||
fi
|
||||
# Beta releases and manual backfills publish only immutable version tags;
|
||||
# do not advance latest/main aliases from those flows.
|
||||
if [[ "${IS_MANUAL_BACKFILL}" != "1" && "$version" =~ ^[0-9]+\.[0-9]+\.[0-9]+(-[0-9]+)?$ ]]; then
|
||||
tags+=("${GHCR_IMAGE}:latest" "${GHCR_IMAGE}:main")
|
||||
slim_tags+=("${GHCR_IMAGE}:slim" "${GHCR_IMAGE}:main-slim")
|
||||
dockerhub_tags+=("${DOCKERHUB_IMAGE}:latest" "${DOCKERHUB_IMAGE}:main")
|
||||
dockerhub_slim_tags+=("${DOCKERHUB_IMAGE}:slim" "${DOCKERHUB_IMAGE}:main-slim")
|
||||
if [[ "${browser_supported}" == "1" ]]; then
|
||||
browser_tags+=("${GHCR_IMAGE}:latest-browser" "${GHCR_IMAGE}:main-browser")
|
||||
dockerhub_browser_tags+=("${DOCKERHUB_IMAGE}:latest-browser" "${DOCKERHUB_IMAGE}:main-browser")
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
if [[ ${#tags[@]} -eq 0 ]]; then
|
||||
echo "::error::No manifest tags resolved for ref ${SOURCE_REF}"
|
||||
exit 1
|
||||
fi
|
||||
{
|
||||
echo "value<<EOF"
|
||||
printf "%s\n" "${tags[@]}" "${slim_tags[@]}"
|
||||
echo "EOF"
|
||||
echo "browser<<EOF"
|
||||
printf "%s\n" "${browser_tags[@]}"
|
||||
echo "EOF"
|
||||
echo "dockerhub<<EOF"
|
||||
printf "%s\n" "${dockerhub_tags[@]}" "${dockerhub_slim_tags[@]}"
|
||||
echo "EOF"
|
||||
echo "dockerhub_browser<<EOF"
|
||||
printf "%s\n" "${dockerhub_browser_tags[@]}"
|
||||
echo "EOF"
|
||||
} >> "$GITHUB_OUTPUT"
|
||||
|
||||
- name: Create and push manifest
|
||||
shell: bash
|
||||
env:
|
||||
DOCKERHUB_IMAGE: ${{ env.DOCKERHUB_REGISTRY }}/${{ env.DOCKERHUB_IMAGE_NAME }}
|
||||
SOURCE_REF: ${{ github.event_name == 'workflow_dispatch' && format('refs/tags/{0}', inputs.tag) || github.ref }}
|
||||
TAGS: ${{ steps.tags.outputs.value }}
|
||||
BROWSER_TAGS: ${{ steps.tags.outputs.browser }}
|
||||
DOCKERHUB_TAGS: ${{ steps.tags.outputs.dockerhub }}
|
||||
DOCKERHUB_BROWSER_TAGS: ${{ steps.tags.outputs.dockerhub_browser }}
|
||||
AMD64_DIGEST: ${{ needs.build-amd64.outputs.digest }}
|
||||
ARM64_DIGEST: ${{ needs.build-arm64.outputs.digest }}
|
||||
AMD64_BROWSER_DIGEST: ${{ needs.build-amd64.outputs.browser_digest }}
|
||||
ARM64_BROWSER_DIGEST: ${{ needs.build-arm64.outputs.browser_digest }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
mapfile -t tags <<< "${TAGS}"
|
||||
mapfile -t browser_tags <<< "${BROWSER_TAGS}"
|
||||
mapfile -t dockerhub_tags <<< "${DOCKERHUB_TAGS}"
|
||||
mapfile -t dockerhub_browser_tags <<< "${DOCKERHUB_BROWSER_TAGS}"
|
||||
create_manifest() {
|
||||
local amd64_digest="$1"
|
||||
local arm64_digest="$2"
|
||||
shift 2
|
||||
local args=()
|
||||
for tag in "$@"; do
|
||||
[ -z "$tag" ] && continue
|
||||
args+=("-t" "$tag")
|
||||
done
|
||||
docker buildx imagetools create "${args[@]}" "$amd64_digest" "$arm64_digest"
|
||||
}
|
||||
create_manifest "${AMD64_DIGEST}" "${ARM64_DIGEST}" "${tags[@]}"
|
||||
if [[ "${SOURCE_REF}" != refs/tags/v* ]]; then
|
||||
echo "::error::No Docker Hub source refs resolved for ref ${SOURCE_REF}"
|
||||
exit 1
|
||||
fi
|
||||
version="${SOURCE_REF#refs/tags/v}"
|
||||
create_manifest "${DOCKERHUB_IMAGE}:${version}-amd64" "${DOCKERHUB_IMAGE}:${version}-arm64" "${dockerhub_tags[@]}"
|
||||
if [[ -n "${BROWSER_TAGS}" ]]; then
|
||||
create_manifest "${AMD64_BROWSER_DIGEST}" "${ARM64_BROWSER_DIGEST}" "${browser_tags[@]}"
|
||||
fi
|
||||
if [[ -n "${DOCKERHUB_BROWSER_TAGS}" ]]; then
|
||||
create_manifest \
|
||||
"${DOCKERHUB_IMAGE}:${version}-browser-amd64" \
|
||||
"${DOCKERHUB_IMAGE}:${version}-browser-arm64" \
|
||||
"${dockerhub_browser_tags[@]}"
|
||||
fi
|
||||
|
||||
verify-attestations:
|
||||
needs: [create-manifest]
|
||||
if: ${{ always() && needs.create-manifest.result == 'success' }}
|
||||
runs-on: ubuntu-24.04
|
||||
permissions:
|
||||
contents: read
|
||||
packages: read
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
|
||||
with:
|
||||
fetch-depth: 1
|
||||
|
||||
- *buildkit_prepull_step
|
||||
- name: Set up Docker Builder
|
||||
uses: docker/setup-buildx-action@d7f5e7f509e45cec5c76c4d5afdd7de93d0b3df5 # v4
|
||||
|
||||
- name: Login to GitHub Container Registry
|
||||
uses: docker/login-action@650006c6eb7dba73a995cc03b0b2d7f5ca915bee # v4
|
||||
with:
|
||||
registry: ${{ env.REGISTRY }}
|
||||
username: ${{ github.repository_owner }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Login to Docker Hub
|
||||
uses: docker/login-action@650006c6eb7dba73a995cc03b0b2d7f5ca915bee # v4
|
||||
with:
|
||||
registry: ${{ env.DOCKERHUB_REGISTRY }}
|
||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
|
||||
- name: Resolve image refs
|
||||
id: refs
|
||||
shell: bash
|
||||
env:
|
||||
GHCR_IMAGE: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
|
||||
DOCKERHUB_IMAGE: ${{ env.DOCKERHUB_REGISTRY }}/${{ env.DOCKERHUB_IMAGE_NAME }}
|
||||
SOURCE_REF: ${{ github.event_name == 'workflow_dispatch' && format('refs/tags/{0}', inputs.tag) || github.ref }}
|
||||
IS_MANUAL_BACKFILL: ${{ github.event_name == 'workflow_dispatch' && '1' || '0' }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
multi_refs=()
|
||||
slim_multi_refs=()
|
||||
amd64_refs=()
|
||||
arm64_refs=()
|
||||
dockerhub_multi_refs=()
|
||||
dockerhub_slim_multi_refs=()
|
||||
dockerhub_amd64_refs=()
|
||||
dockerhub_arm64_refs=()
|
||||
browser_supported=0
|
||||
if [[ "${SOURCE_REF}" == refs/tags/v* ]]; then
|
||||
tag="${SOURCE_REF#refs/tags/}"
|
||||
git fetch --depth=1 origin "refs/tags/${tag}:refs/tags/${tag}"
|
||||
if git show "${SOURCE_REF}:Dockerfile" | grep -q '^ARG OPENCLAW_INSTALL_BROWSER'; then
|
||||
browser_supported=1
|
||||
fi
|
||||
elif grep -q '^ARG OPENCLAW_INSTALL_BROWSER' Dockerfile; then
|
||||
browser_supported=1
|
||||
fi
|
||||
if [[ "${SOURCE_REF}" == refs/tags/v* ]]; then
|
||||
version="${SOURCE_REF#refs/tags/v}"
|
||||
multi_refs+=("${GHCR_IMAGE}:${version}")
|
||||
slim_multi_refs+=("${GHCR_IMAGE}:${version}-slim")
|
||||
dockerhub_multi_refs+=("${DOCKERHUB_IMAGE}:${version}")
|
||||
dockerhub_slim_multi_refs+=("${DOCKERHUB_IMAGE}:${version}-slim")
|
||||
amd64_refs+=(
|
||||
"${GHCR_IMAGE}:${version}-amd64"
|
||||
"${GHCR_IMAGE}:${version}-slim-amd64"
|
||||
)
|
||||
dockerhub_amd64_refs+=(
|
||||
"${DOCKERHUB_IMAGE}:${version}-amd64"
|
||||
"${DOCKERHUB_IMAGE}:${version}-slim-amd64"
|
||||
)
|
||||
arm64_refs+=(
|
||||
"${GHCR_IMAGE}:${version}-arm64"
|
||||
"${GHCR_IMAGE}:${version}-slim-arm64"
|
||||
)
|
||||
dockerhub_arm64_refs+=(
|
||||
"${DOCKERHUB_IMAGE}:${version}-arm64"
|
||||
"${DOCKERHUB_IMAGE}:${version}-slim-arm64"
|
||||
)
|
||||
if [[ "${browser_supported}" == "1" ]]; then
|
||||
multi_refs+=("${GHCR_IMAGE}:${version}-browser")
|
||||
dockerhub_multi_refs+=("${DOCKERHUB_IMAGE}:${version}-browser")
|
||||
amd64_refs+=("${GHCR_IMAGE}:${version}-browser-amd64")
|
||||
dockerhub_amd64_refs+=("${DOCKERHUB_IMAGE}:${version}-browser-amd64")
|
||||
arm64_refs+=("${GHCR_IMAGE}:${version}-browser-arm64")
|
||||
dockerhub_arm64_refs+=("${DOCKERHUB_IMAGE}:${version}-browser-arm64")
|
||||
fi
|
||||
# Beta releases and manual backfills publish only immutable version tags;
|
||||
# do not advance latest/main aliases from those flows.
|
||||
if [[ "${IS_MANUAL_BACKFILL}" != "1" && "$version" =~ ^[0-9]+\.[0-9]+\.[0-9]+(-[0-9]+)?$ ]]; then
|
||||
multi_refs+=("${GHCR_IMAGE}:latest" "${GHCR_IMAGE}:main")
|
||||
slim_multi_refs+=("${GHCR_IMAGE}:slim" "${GHCR_IMAGE}:main-slim")
|
||||
dockerhub_multi_refs+=("${DOCKERHUB_IMAGE}:latest" "${DOCKERHUB_IMAGE}:main")
|
||||
dockerhub_slim_multi_refs+=("${DOCKERHUB_IMAGE}:slim" "${DOCKERHUB_IMAGE}:main-slim")
|
||||
if [[ "${browser_supported}" == "1" ]]; then
|
||||
multi_refs+=("${GHCR_IMAGE}:latest-browser" "${GHCR_IMAGE}:main-browser")
|
||||
dockerhub_multi_refs+=("${DOCKERHUB_IMAGE}:latest-browser" "${DOCKERHUB_IMAGE}:main-browser")
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
if [[ ${#multi_refs[@]} -eq 0 || ${#amd64_refs[@]} -eq 0 || ${#arm64_refs[@]} -eq 0 || ${#dockerhub_multi_refs[@]} -eq 0 || ${#dockerhub_amd64_refs[@]} -eq 0 || ${#dockerhub_arm64_refs[@]} -eq 0 ]]; then
|
||||
echo "::error::No Docker image refs resolved for ref ${SOURCE_REF}"
|
||||
exit 1
|
||||
fi
|
||||
{
|
||||
echo "multi<<EOF"
|
||||
printf "%s\n" "${multi_refs[@]}" "${slim_multi_refs[@]}"
|
||||
echo "EOF"
|
||||
echo "amd64<<EOF"
|
||||
printf "%s\n" "${amd64_refs[@]}"
|
||||
echo "EOF"
|
||||
echo "arm64<<EOF"
|
||||
printf "%s\n" "${arm64_refs[@]}"
|
||||
echo "EOF"
|
||||
echo "dockerhub_multi<<EOF"
|
||||
printf "%s\n" "${dockerhub_multi_refs[@]}" "${dockerhub_slim_multi_refs[@]}"
|
||||
echo "EOF"
|
||||
echo "dockerhub_amd64<<EOF"
|
||||
printf "%s\n" "${dockerhub_amd64_refs[@]}"
|
||||
echo "EOF"
|
||||
echo "dockerhub_arm64<<EOF"
|
||||
printf "%s\n" "${dockerhub_arm64_refs[@]}"
|
||||
echo "EOF"
|
||||
} >> "$GITHUB_OUTPUT"
|
||||
|
||||
- name: Verify Docker attestations
|
||||
shell: bash
|
||||
env:
|
||||
MULTI_REFS: ${{ steps.refs.outputs.multi }}
|
||||
AMD64_REFS: ${{ steps.refs.outputs.amd64 }}
|
||||
ARM64_REFS: ${{ steps.refs.outputs.arm64 }}
|
||||
DOCKERHUB_MULTI_REFS: ${{ steps.refs.outputs.dockerhub_multi }}
|
||||
DOCKERHUB_AMD64_REFS: ${{ steps.refs.outputs.dockerhub_amd64 }}
|
||||
DOCKERHUB_ARM64_REFS: ${{ steps.refs.outputs.dockerhub_arm64 }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
mapfile -t multi_refs <<< "${MULTI_REFS}"
|
||||
mapfile -t amd64_refs <<< "${AMD64_REFS}"
|
||||
mapfile -t arm64_refs <<< "${ARM64_REFS}"
|
||||
mapfile -t dockerhub_multi_refs <<< "${DOCKERHUB_MULTI_REFS}"
|
||||
mapfile -t dockerhub_amd64_refs <<< "${DOCKERHUB_AMD64_REFS}"
|
||||
mapfile -t dockerhub_arm64_refs <<< "${DOCKERHUB_ARM64_REFS}"
|
||||
|
||||
node scripts/verify-docker-attestations.mjs \
|
||||
--platform linux/amd64 \
|
||||
--platform linux/arm64 \
|
||||
"${multi_refs[@]}"
|
||||
node scripts/verify-docker-attestations.mjs \
|
||||
--platform linux/amd64 \
|
||||
"${amd64_refs[@]}"
|
||||
node scripts/verify-docker-attestations.mjs \
|
||||
--platform linux/arm64 \
|
||||
"${arm64_refs[@]}"
|
||||
node scripts/verify-docker-attestations.mjs \
|
||||
--platform linux/amd64 \
|
||||
--platform linux/arm64 \
|
||||
"${dockerhub_multi_refs[@]}"
|
||||
node scripts/verify-docker-attestations.mjs \
|
||||
--platform linux/amd64 \
|
||||
"${dockerhub_amd64_refs[@]}"
|
||||
node scripts/verify-docker-attestations.mjs \
|
||||
--platform linux/arm64 \
|
||||
"${dockerhub_arm64_refs[@]}"
|
||||
Reference in New Issue
Block a user