mirror of
https://github.com/openclaw/openclaw.git
synced 2026-08-25 11:55:47 -06:00
fix(release): restore frozen validation startup (#110210)
* fix(release): restore frozen validation startup Adapt the no-write validation portion ofb597a8d364(#103834) for the 6.x extended-stable workflow set. Remove validation-owned image publisher jobs instead of granting write permissions; Docker publication remains out of scope. * fix(release): allow canonical extended-stable checks Restore the openclaw-release-checks.yml portion ofc7810fc697(#99352) that authorizes the canonical extended-stable/YYYY.M.33 workflow branch.
This commit is contained in:
@@ -18,10 +18,9 @@ on:
|
||||
root_image_transport:
|
||||
description: Root Dockerfile image transport
|
||||
required: false
|
||||
default: registry
|
||||
default: no-push-artifact
|
||||
type: choice
|
||||
options:
|
||||
- registry
|
||||
- no-push-artifact
|
||||
workflow_call:
|
||||
inputs:
|
||||
@@ -42,7 +41,7 @@ on:
|
||||
root_image_transport:
|
||||
description: Root Dockerfile image transport
|
||||
required: false
|
||||
default: registry
|
||||
default: no-push-artifact
|
||||
type: string
|
||||
|
||||
permissions:
|
||||
@@ -409,51 +408,8 @@ jobs:
|
||||
fi
|
||||
} >> "$GITHUB_STEP_SUMMARY"
|
||||
|
||||
push_root_dockerfile_image:
|
||||
needs: [preflight, root_dockerfile_image]
|
||||
if: needs.preflight.outputs.root_image_transport == 'registry' && needs.root_dockerfile_image.outputs.image_exists != 'true'
|
||||
runs-on: ubuntu-24.04
|
||||
permissions:
|
||||
contents: read
|
||||
packages: write
|
||||
env:
|
||||
DOCKER_BUILD_SUMMARY: "false"
|
||||
DOCKER_BUILD_RECORD_UPLOAD: "false"
|
||||
steps:
|
||||
- name: Checkout CLI
|
||||
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
|
||||
with:
|
||||
ref: ${{ needs.preflight.outputs.target_sha }}
|
||||
persist-credentials: false
|
||||
|
||||
- name: Log in to GHCR
|
||||
uses: docker/login-action@650006c6eb7dba73a995cc03b0b2d7f5ca915bee # v4
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ github.token }}
|
||||
|
||||
- name: Set up Blacksmith Docker Builder
|
||||
uses: useblacksmith/setup-docker-builder@ab5c1da94f53f5cd75c1038092aa276dddfccbba # v1
|
||||
with:
|
||||
max-cache-size-mb: 800000
|
||||
|
||||
# The registry path publishes one matrix-extension image by target SHA.
|
||||
# A direct buildx command keeps progress visible and fails on timeout.
|
||||
- name: Build and push root Dockerfile smoke image
|
||||
env:
|
||||
IMAGE_REF: ${{ needs.root_dockerfile_image.outputs.image_ref }}
|
||||
run: |
|
||||
timeout --kill-after=30s 45m docker buildx build \
|
||||
--progress=plain \
|
||||
--push \
|
||||
--build-arg OPENCLAW_EXTENSIONS=matrix \
|
||||
-t "$IMAGE_REF" \
|
||||
-f ./Dockerfile \
|
||||
.
|
||||
|
||||
root_dockerfile_image_ready:
|
||||
needs: [preflight, root_dockerfile_image, push_root_dockerfile_image]
|
||||
needs: [preflight, root_dockerfile_image]
|
||||
if: always() && needs.preflight.result == 'success' && needs.preflight.outputs.run_full_install_smoke == 'true'
|
||||
runs-on: ubuntu-24.04
|
||||
permissions:
|
||||
@@ -461,25 +417,13 @@ jobs:
|
||||
steps:
|
||||
- name: Verify root Dockerfile image preparation
|
||||
env:
|
||||
IMAGE_EXISTS: ${{ needs.root_dockerfile_image.outputs.image_exists }}
|
||||
PREPARE_RESULT: ${{ needs.root_dockerfile_image.result }}
|
||||
PUSH_RESULT: ${{ needs.push_root_dockerfile_image.result }}
|
||||
ROOT_IMAGE_TRANSPORT: ${{ needs.preflight.outputs.root_image_transport }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
if [[ "$PREPARE_RESULT" != "success" ]]; then
|
||||
echo "Root Dockerfile image preparation ended with ${PREPARE_RESULT}." >&2
|
||||
exit 1
|
||||
fi
|
||||
if [[ "$ROOT_IMAGE_TRANSPORT" == "registry" && "$IMAGE_EXISTS" != "true" ]]; then
|
||||
if [[ "$PUSH_RESULT" != "success" ]]; then
|
||||
echo "Root Dockerfile registry image publication ended with ${PUSH_RESULT}." >&2
|
||||
exit 1
|
||||
fi
|
||||
elif [[ "$PUSH_RESULT" != "skipped" ]]; then
|
||||
echo "Unexpected root Dockerfile registry publication result: ${PUSH_RESULT}." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
qr_package_install_smoke:
|
||||
needs: [preflight]
|
||||
|
||||
@@ -51,10 +51,9 @@ on:
|
||||
shared_image_policy:
|
||||
description: Shared Docker image transport
|
||||
required: true
|
||||
default: allow-push
|
||||
default: no-push-artifact
|
||||
type: choice
|
||||
options:
|
||||
- allow-push
|
||||
- existing-only
|
||||
- no-push-artifact
|
||||
shared_image_artifact_namespace:
|
||||
@@ -213,9 +212,9 @@ on:
|
||||
default: ""
|
||||
type: string
|
||||
shared_image_policy:
|
||||
description: "Shared Docker image transport: allow-push, existing-only, or no-push-artifact"
|
||||
description: "Shared Docker image transport: existing-only or no-push-artifact"
|
||||
required: false
|
||||
default: allow-push
|
||||
default: no-push-artifact
|
||||
type: string
|
||||
shared_image_artifact_namespace:
|
||||
description: Safe unique artifact namespace when shared_image_policy=no-push-artifact
|
||||
@@ -496,8 +495,6 @@ jobs:
|
||||
fi
|
||||
|
||||
case "$SHARED_IMAGE_POLICY" in
|
||||
allow-push)
|
||||
;;
|
||||
existing-only)
|
||||
if [[ -z "${PROVIDED_BARE_IMAGE// }" && -z "${PROVIDED_FUNCTIONAL_IMAGE// }" ]]; then
|
||||
echo "shared_image_policy=existing-only requires explicit shared image refs." >&2
|
||||
@@ -519,7 +516,7 @@ jobs:
|
||||
}
|
||||
;;
|
||||
*)
|
||||
echo "shared_image_policy must be allow-push, existing-only, or no-push-artifact." >&2
|
||||
echo "shared_image_policy must be existing-only or no-push-artifact." >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
@@ -1964,7 +1961,7 @@ jobs:
|
||||
echo "Shared Docker E2E functional image: \`$functional_image\`" >> "$GITHUB_STEP_SUMMARY"
|
||||
|
||||
- name: Log in to GHCR
|
||||
if: steps.plan.outputs.needs_e2e_image == '1' && (inputs.shared_image_policy == 'allow-push' || inputs.shared_image_policy == 'existing-only')
|
||||
if: steps.plan.outputs.needs_e2e_image == '1' && inputs.shared_image_policy == 'existing-only'
|
||||
run: bash .release-harness/scripts/ci-docker-login-ghcr.sh
|
||||
env:
|
||||
GHCR_USERNAME: ${{ github.actor }}
|
||||
@@ -1972,7 +1969,7 @@ jobs:
|
||||
|
||||
- name: Check existing shared Docker E2E images
|
||||
id: image_exists
|
||||
if: steps.plan.outputs.needs_e2e_image == '1' && (inputs.shared_image_policy == 'allow-push' || inputs.shared_image_policy == 'existing-only')
|
||||
if: steps.plan.outputs.needs_e2e_image == '1' && inputs.shared_image_policy == 'existing-only'
|
||||
shell: bash
|
||||
env:
|
||||
PROVIDED_BARE_IMAGE: ${{ inputs.docker_e2e_bare_image }}
|
||||
@@ -2104,126 +2101,8 @@ jobs:
|
||||
compression-level: 0
|
||||
retention-days: 7
|
||||
|
||||
push_docker_e2e_images:
|
||||
needs: [validate_selected_ref, prepare_docker_e2e_image]
|
||||
if: inputs.shared_image_policy == 'allow-push' && needs.prepare_docker_e2e_image.outputs.needs_registry_build == '1'
|
||||
runs-on: ${{ inputs.use_github_hosted_runners && 'ubuntu-24.04' || 'blacksmith-32vcpu-ubuntu-2404' }}
|
||||
timeout-minutes: ${{ inputs.release_test_profile == 'full' && 90 || 60 }}
|
||||
permissions:
|
||||
actions: read
|
||||
contents: read
|
||||
packages: write
|
||||
env:
|
||||
DOCKER_BUILD_SUMMARY: "false"
|
||||
DOCKER_BUILD_RECORD_UPLOAD: "false"
|
||||
steps:
|
||||
- name: Checkout selected ref
|
||||
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
|
||||
with:
|
||||
ref: ${{ needs.validate_selected_ref.outputs.selected_sha }}
|
||||
fetch-depth: 1
|
||||
persist-credentials: false
|
||||
|
||||
- name: Download OpenClaw Docker E2E package
|
||||
if: needs.prepare_docker_e2e_image.outputs.needs_functional_image == '1' && needs.prepare_docker_e2e_image.outputs.functional_exists != '1'
|
||||
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8
|
||||
with:
|
||||
artifact-ids: ${{ needs.prepare_docker_e2e_image.outputs.package_artifact_id }}
|
||||
path: .artifacts/docker-e2e-package
|
||||
run-id: ${{ needs.prepare_docker_e2e_image.outputs.package_artifact_run_id }}
|
||||
github-token: ${{ github.token }}
|
||||
|
||||
- name: Normalize OpenClaw Docker E2E package
|
||||
if: needs.prepare_docker_e2e_image.outputs.needs_functional_image == '1' && needs.prepare_docker_e2e_image.outputs.functional_exists != '1'
|
||||
shell: bash
|
||||
run: |
|
||||
set -euo pipefail
|
||||
target=".artifacts/docker-e2e-package/openclaw-current.tgz"
|
||||
if [[ ! -f "$target" ]]; then
|
||||
mapfile -t tgzs < <(find .artifacts/docker-e2e-package -type f -name '*.tgz' | sort)
|
||||
if [[ "${#tgzs[@]}" -ne 1 ]]; then
|
||||
echo "Expected exactly one package tarball for the registry image build; found ${#tgzs[@]}." >&2
|
||||
exit 1
|
||||
fi
|
||||
cp "${tgzs[0]}" "$target"
|
||||
fi
|
||||
|
||||
- name: Log in to GHCR
|
||||
run: bash scripts/ci-docker-login-ghcr.sh
|
||||
env:
|
||||
GHCR_USERNAME: ${{ github.actor }}
|
||||
GITHUB_TOKEN: ${{ github.token }}
|
||||
|
||||
- name: Setup Docker builder
|
||||
uses: useblacksmith/setup-docker-builder@ab5c1da94f53f5cd75c1038092aa276dddfccbba # v1
|
||||
with:
|
||||
max-cache-size-mb: 800000
|
||||
|
||||
- name: Build and push bare Docker E2E image
|
||||
if: needs.prepare_docker_e2e_image.outputs.needs_bare_image == '1' && needs.prepare_docker_e2e_image.outputs.bare_exists != '1'
|
||||
shell: bash
|
||||
env:
|
||||
IMAGE_REF: ${{ needs.prepare_docker_e2e_image.outputs.bare_image }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
build_cmd=(
|
||||
docker buildx build
|
||||
--file ./scripts/e2e/Dockerfile
|
||||
--target bare
|
||||
--platform linux/amd64
|
||||
--tag "$IMAGE_REF"
|
||||
--sbom=true
|
||||
--provenance=mode=max
|
||||
--push
|
||||
.
|
||||
)
|
||||
for attempt in 1 2 3 4; do
|
||||
if "${build_cmd[@]}"; then
|
||||
exit 0
|
||||
fi
|
||||
if [[ "$attempt" == "4" ]]; then
|
||||
echo "::error::Failed to build Docker E2E bare image after ${attempt} attempts"
|
||||
exit 1
|
||||
fi
|
||||
sleep_seconds=$((attempt * 20))
|
||||
echo "Docker E2E bare image build failed; retrying in ${sleep_seconds}s (${attempt}/4)."
|
||||
sleep "$sleep_seconds"
|
||||
done
|
||||
|
||||
- name: Build and push functional Docker E2E image
|
||||
if: needs.prepare_docker_e2e_image.outputs.needs_functional_image == '1' && needs.prepare_docker_e2e_image.outputs.functional_exists != '1'
|
||||
shell: bash
|
||||
env:
|
||||
IMAGE_REF: ${{ needs.prepare_docker_e2e_image.outputs.functional_image }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
build_cmd=(
|
||||
docker buildx build
|
||||
--file ./scripts/e2e/Dockerfile
|
||||
--target functional
|
||||
--build-context openclaw_package=.artifacts/docker-e2e-package
|
||||
--platform linux/amd64
|
||||
--tag "$IMAGE_REF"
|
||||
--sbom=true
|
||||
--provenance=mode=max
|
||||
--push
|
||||
.
|
||||
)
|
||||
for attempt in 1 2 3 4; do
|
||||
if "${build_cmd[@]}"; then
|
||||
exit 0
|
||||
fi
|
||||
if [[ "$attempt" == "4" ]]; then
|
||||
echo "::error::Failed to build Docker E2E functional image after ${attempt} attempts"
|
||||
exit 1
|
||||
fi
|
||||
sleep_seconds=$((attempt * 20))
|
||||
echo "Docker E2E functional image build failed; retrying in ${sleep_seconds}s (${attempt}/4)."
|
||||
sleep "$sleep_seconds"
|
||||
done
|
||||
|
||||
docker_e2e_image_ready:
|
||||
needs: [prepare_docker_e2e_image, push_docker_e2e_images]
|
||||
needs: prepare_docker_e2e_image
|
||||
if: always() && needs.prepare_docker_e2e_image.result != 'skipped'
|
||||
runs-on: ubuntu-24.04
|
||||
timeout-minutes: 5
|
||||
@@ -2233,9 +2112,6 @@ jobs:
|
||||
- name: Verify Docker E2E image preparation
|
||||
env:
|
||||
PREPARE_RESULT: ${{ needs.prepare_docker_e2e_image.result }}
|
||||
PUSH_RESULT: ${{ needs.push_docker_e2e_images.result }}
|
||||
NEEDS_REGISTRY_BUILD: ${{ needs.prepare_docker_e2e_image.outputs.needs_registry_build }}
|
||||
SHARED_IMAGE_POLICY: ${{ inputs.shared_image_policy }}
|
||||
shell: bash
|
||||
run: |
|
||||
set -euo pipefail
|
||||
@@ -2243,15 +2119,6 @@ jobs:
|
||||
echo "Docker E2E image preparation ended with ${PREPARE_RESULT}." >&2
|
||||
exit 1
|
||||
fi
|
||||
if [[ "$SHARED_IMAGE_POLICY" == "allow-push" && "$NEEDS_REGISTRY_BUILD" == "1" ]]; then
|
||||
if [[ "$PUSH_RESULT" != "success" ]]; then
|
||||
echo "Docker E2E registry image publication ended with ${PUSH_RESULT}." >&2
|
||||
exit 1
|
||||
fi
|
||||
elif [[ "$PUSH_RESULT" != "skipped" ]]; then
|
||||
echo "Unexpected Docker E2E registry publication result: ${PUSH_RESULT}." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
prepare_live_test_image:
|
||||
needs: validate_selected_ref
|
||||
@@ -2393,53 +2260,8 @@ jobs:
|
||||
compression-level: 0
|
||||
retention-days: 7
|
||||
|
||||
push_live_test_image:
|
||||
needs: [validate_selected_ref, prepare_live_test_image]
|
||||
if: inputs.shared_image_policy == 'allow-push' && needs.prepare_live_test_image.outputs.image_exists != '1'
|
||||
runs-on: ${{ inputs.use_github_hosted_runners && 'ubuntu-24.04' || 'blacksmith-32vcpu-ubuntu-2404' }}
|
||||
timeout-minutes: 60
|
||||
permissions:
|
||||
contents: read
|
||||
packages: write
|
||||
env:
|
||||
DOCKER_BUILD_SUMMARY: "false"
|
||||
DOCKER_BUILD_RECORD_UPLOAD: "false"
|
||||
steps:
|
||||
- name: Checkout selected ref
|
||||
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
|
||||
with:
|
||||
ref: ${{ needs.validate_selected_ref.outputs.selected_sha }}
|
||||
fetch-depth: 1
|
||||
persist-credentials: false
|
||||
|
||||
- name: Log in to GHCR
|
||||
run: bash scripts/ci-docker-login-ghcr.sh
|
||||
env:
|
||||
GHCR_USERNAME: ${{ github.actor }}
|
||||
GITHUB_TOKEN: ${{ github.token }}
|
||||
|
||||
- name: Setup Docker builder
|
||||
uses: useblacksmith/setup-docker-builder@ab5c1da94f53f5cd75c1038092aa276dddfccbba # v1
|
||||
with:
|
||||
max-cache-size-mb: 800000
|
||||
|
||||
- name: Build and push shared live-test image
|
||||
uses: useblacksmith/build-push-action@fb9e3e6a9299c78462bfadd0d93352c316adc9b8 # v2
|
||||
with:
|
||||
context: .
|
||||
file: ./Dockerfile
|
||||
target: build
|
||||
build-args: |
|
||||
OPENCLAW_EXTENSIONS=matrix,acpx
|
||||
platforms: linux/amd64
|
||||
tags: ${{ needs.prepare_live_test_image.outputs.live_image }}
|
||||
sbom: true
|
||||
provenance: mode=max
|
||||
load: false
|
||||
push: true
|
||||
|
||||
live_test_image_ready:
|
||||
needs: [prepare_live_test_image, push_live_test_image]
|
||||
needs: prepare_live_test_image
|
||||
if: always() && needs.prepare_live_test_image.result != 'skipped'
|
||||
runs-on: ubuntu-24.04
|
||||
timeout-minutes: 5
|
||||
@@ -2448,10 +2270,7 @@ jobs:
|
||||
steps:
|
||||
- name: Verify live-test image preparation
|
||||
env:
|
||||
IMAGE_EXISTS: ${{ needs.prepare_live_test_image.outputs.image_exists }}
|
||||
PREPARE_RESULT: ${{ needs.prepare_live_test_image.result }}
|
||||
PUSH_RESULT: ${{ needs.push_live_test_image.result }}
|
||||
SHARED_IMAGE_POLICY: ${{ inputs.shared_image_policy }}
|
||||
shell: bash
|
||||
run: |
|
||||
set -euo pipefail
|
||||
@@ -2459,15 +2278,6 @@ jobs:
|
||||
echo "Live-test image preparation ended with ${PREPARE_RESULT}." >&2
|
||||
exit 1
|
||||
fi
|
||||
if [[ "$SHARED_IMAGE_POLICY" == "allow-push" && "$IMAGE_EXISTS" != "1" ]]; then
|
||||
if [[ "$PUSH_RESULT" != "success" ]]; then
|
||||
echo "Live-test registry image publication ended with ${PUSH_RESULT}." >&2
|
||||
exit 1
|
||||
fi
|
||||
elif [[ "$PUSH_RESULT" != "skipped" ]]; then
|
||||
echo "Unexpected live-test registry publication result: ${PUSH_RESULT}." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
validate_live_models_docker:
|
||||
name: Docker live models (${{ matrix.provider_label }})
|
||||
|
||||
@@ -144,8 +144,8 @@ jobs:
|
||||
tideclaw_alpha_check=true
|
||||
fi
|
||||
fi
|
||||
if [[ "${WORKFLOW_REF}" != "refs/heads/main" ]] && [[ ! "${WORKFLOW_REF}" =~ ^refs/heads/release/[0-9]{4}\.[1-9][0-9]*\.[1-9][0-9]*$ ]] && [[ ! "${WORKFLOW_REF}" =~ ^refs/heads/release-ci/[0-9a-f]{12}-[0-9]+$ ]] && [[ "${tideclaw_alpha_check}" != "true" ]]; then
|
||||
echo "Release checks must be dispatched from main, release/YYYY.M.PATCH, a Full Release Validation release-ci/<sha>-<timestamp> ref, or a Tideclaw alpha branch for alpha prereleases." >&2
|
||||
if [[ "${WORKFLOW_REF}" != "refs/heads/main" ]] && [[ ! "${WORKFLOW_REF}" =~ ^refs/heads/release/[0-9]{4}\.[1-9][0-9]*\.[1-9][0-9]*$ ]] && [[ ! "${WORKFLOW_REF}" =~ ^refs/heads/release-ci/[0-9a-f]{12}-[0-9]+$ ]] && [[ ! "${WORKFLOW_REF}" =~ ^refs/heads/extended-stable/[0-9]{4}\.([1-9]|1[0-2])\.33$ ]] && [[ "${tideclaw_alpha_check}" != "true" ]]; then
|
||||
echo "Release checks must be dispatched from main, release/YYYY.M.PATCH, extended-stable/YYYY.M.33, a Full Release Validation release-ci/<sha>-<timestamp> ref, or a Tideclaw alpha branch for alpha prereleases." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
|
||||
@@ -87,10 +87,9 @@ on:
|
||||
shared_image_policy:
|
||||
description: Shared Docker image transport for package acceptance
|
||||
required: true
|
||||
default: allow-push
|
||||
default: no-push-artifact
|
||||
type: choice
|
||||
options:
|
||||
- allow-push
|
||||
- existing-only
|
||||
- no-push-artifact
|
||||
shared_image_artifact_namespace:
|
||||
@@ -230,9 +229,9 @@ on:
|
||||
default: ""
|
||||
type: string
|
||||
shared_image_policy:
|
||||
description: "Shared Docker image transport: allow-push, existing-only, or no-push-artifact"
|
||||
description: "Shared Docker image transport: existing-only or no-push-artifact"
|
||||
required: false
|
||||
default: allow-push
|
||||
default: no-push-artifact
|
||||
type: string
|
||||
shared_image_artifact_namespace:
|
||||
description: Unique artifact namespace when shared_image_policy=no-push-artifact
|
||||
@@ -864,13 +863,13 @@ jobs:
|
||||
FIREWORKS_API_KEY: ${{ secrets.FIREWORKS_API_KEY }}
|
||||
|
||||
docker_acceptance_registry:
|
||||
name: Docker product acceptance (registry)
|
||||
name: Docker product acceptance (existing registry images)
|
||||
needs: [resolve_package, package_integrity]
|
||||
if: inputs.shared_image_policy != 'no-push-artifact'
|
||||
if: inputs.shared_image_policy == 'existing-only'
|
||||
permissions:
|
||||
actions: read
|
||||
contents: read
|
||||
packages: write
|
||||
packages: read
|
||||
pull-requests: read
|
||||
uses: ./.github/workflows/openclaw-live-and-e2e-checks-reusable.yml
|
||||
with: *docker_acceptance_inputs
|
||||
|
||||
Reference in New Issue
Block a user