From 3341ade2bfd759cd5fa0b074f1e1cdc30dcb9648 Mon Sep 17 00:00:00 2001 From: Dallin Romney Date: Fri, 17 Jul 2026 15:41:41 -0700 Subject: [PATCH] fix(release): restore frozen validation startup (#110210) * fix(release): restore frozen validation startup Adapt the no-write validation portion of b597a8d364f2849c704b2d0087a9c6c087def2f7 (#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 of c7810fc6972c0152cb5b5c473011bb8d8aefee0b (#99352) that authorizes the canonical extended-stable/YYYY.M.33 workflow branch. --- .github/workflows/install-smoke.yml | 62 +----- .../openclaw-live-and-e2e-checks-reusable.yml | 206 +----------------- .github/workflows/openclaw-release-checks.yml | 4 +- .github/workflows/package-acceptance.yml | 13 +- .../install-smoke-no-push-workflow.test.ts | 39 +--- .../package-acceptance-workflow.test.ts | 3 + test/scripts/release-no-push-workflow.test.ts | 50 ++--- 7 files changed, 44 insertions(+), 333 deletions(-) diff --git a/.github/workflows/install-smoke.yml b/.github/workflows/install-smoke.yml index c180b9ed011a..68254e6e98bb 100644 --- a/.github/workflows/install-smoke.yml +++ b/.github/workflows/install-smoke.yml @@ -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] diff --git a/.github/workflows/openclaw-live-and-e2e-checks-reusable.yml b/.github/workflows/openclaw-live-and-e2e-checks-reusable.yml index b16074804115..b086e620a161 100644 --- a/.github/workflows/openclaw-live-and-e2e-checks-reusable.yml +++ b/.github/workflows/openclaw-live-and-e2e-checks-reusable.yml @@ -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 }}) diff --git a/.github/workflows/openclaw-release-checks.yml b/.github/workflows/openclaw-release-checks.yml index 746054831d67..8a8eed82de01 100644 --- a/.github/workflows/openclaw-release-checks.yml +++ b/.github/workflows/openclaw-release-checks.yml @@ -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/- 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/- ref, or a Tideclaw alpha branch for alpha prereleases." >&2 exit 1 fi diff --git a/.github/workflows/package-acceptance.yml b/.github/workflows/package-acceptance.yml index 76d8b2694472..9b2eabdbe6af 100644 --- a/.github/workflows/package-acceptance.yml +++ b/.github/workflows/package-acceptance.yml @@ -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 diff --git a/test/scripts/install-smoke-no-push-workflow.test.ts b/test/scripts/install-smoke-no-push-workflow.test.ts index 75bd890cfc5c..30f7e537f455 100644 --- a/test/scripts/install-smoke-no-push-workflow.test.ts +++ b/test/scripts/install-smoke-no-push-workflow.test.ts @@ -52,17 +52,17 @@ function step(workflowJob: WorkflowJob, name: string): WorkflowStep { } describe("install smoke no-push root image transport", () => { - it("keeps registry transport as the default and validates the selected mode", () => { + it("defaults every caller to artifact-only transport", () => { const workflow = readWorkflow(INSTALL_SMOKE); const dispatchInput = workflow.on?.workflow_dispatch?.inputs?.root_image_transport; const callInput = workflow.on?.workflow_call?.inputs?.root_image_transport; expect(dispatchInput).toMatchObject({ - default: "registry", - options: ["registry", "no-push-artifact"], + default: "no-push-artifact", + options: ["no-push-artifact"], type: "choice", }); expect(callInput).toMatchObject({ - default: "registry", + default: "no-push-artifact", type: "string", }); expect(workflow.permissions).toMatchObject({ @@ -205,41 +205,18 @@ describe("install smoke no-push root image transport", () => { path: "${{ steps.image_artifact.outputs.artifact_path }}", }); - const registryPublisher = job(workflow, "push_root_dockerfile_image"); - expect(registryPublisher.permissions).toEqual({ - contents: "read", - packages: "write", - }); - expect(registryPublisher.if).toBe( - "needs.preflight.outputs.root_image_transport == 'registry' && needs.root_dockerfile_image.outputs.image_exists != 'true'", - ); - expect(step(registryPublisher, "Checkout CLI").with).toMatchObject({ - ref: "${{ needs.preflight.outputs.target_sha }}", - "persist-credentials": false, - }); - expect(step(registryPublisher, "Log in to GHCR").if).toBeUndefined(); - const registryBuild = step(registryPublisher, "Build and push root Dockerfile smoke image"); - expect(registryBuild.run).toContain("--push"); - expect(registryBuild.run).not.toContain("--load"); - const writeScopedJobs = Object.entries(workflow.jobs) .filter(([, candidate]) => candidate.permissions?.packages === "write") .map(([name]) => name); - expect(writeScopedJobs).toEqual(["push_root_dockerfile_image"]); + expect(writeScopedJobs).toEqual([]); + expect(workflow.jobs.push_root_dockerfile_image).toBeUndefined(); const ready = job(workflow, "root_dockerfile_image_ready"); - expect(ready.needs).toEqual([ - "preflight", - "root_dockerfile_image", - "push_root_dockerfile_image", - ]); + expect(ready.needs).toEqual(["preflight", "root_dockerfile_image"]); expect(ready.if).toContain("always()"); const verify = step(ready, "Verify root Dockerfile image preparation"); expect(verify.run).toContain('if [[ "$PREPARE_RESULT" != "success" ]]'); - expect(verify.run).toContain( - 'if [[ "$ROOT_IMAGE_TRANSPORT" == "registry" && "$IMAGE_EXISTS" != "true" ]]', - ); - expect(verify.run).toContain('elif [[ "$PUSH_RESULT" != "skipped" ]]'); + expect(verify.run).not.toContain("PUSH_RESULT"); }); it("verifies and loads the artifact in every consumer without registry fallback", () => { diff --git a/test/scripts/package-acceptance-workflow.test.ts b/test/scripts/package-acceptance-workflow.test.ts index 6cac0ebccfee..d9178d730996 100644 --- a/test/scripts/package-acceptance-workflow.test.ts +++ b/test/scripts/package-acceptance-workflow.test.ts @@ -650,6 +650,9 @@ describe("package acceptance workflow", () => { ); expect(workflow).toContain("| Child | Result | Minutes | Head SHA | Run |"); expect(releaseChecksWorkflow).toContain("refs/heads/release-ci/[0-9a-f]{12}-[0-9]+"); + expect(releaseChecksWorkflow).toContain( + "refs/heads/extended-stable/[0-9]{4}\\.([1-9]|1[0-2])\\.33", + ); expect(releaseChecksWorkflow).toContain( "source: ${{ (needs.resolve_target.outputs.package_acceptance_package_spec != '' || needs.resolve_target.outputs.release_package_spec != '') && 'npm' || 'artifact' }}", ); diff --git a/test/scripts/release-no-push-workflow.test.ts b/test/scripts/release-no-push-workflow.test.ts index 0a0889779601..f1e8f05c022a 100644 --- a/test/scripts/release-no-push-workflow.test.ts +++ b/test/scripts/release-no-push-workflow.test.ts @@ -273,12 +273,12 @@ describe("release validation no-push transport", () => { const registryAcceptance = job(packageAcceptance, "docker_acceptance_registry"); expect(packageAcceptance.permissions?.packages).toBe("read"); expect(packageAcceptance.on?.workflow_dispatch?.inputs?.shared_image_policy).toMatchObject({ - default: "allow-push", - options: ["allow-push", "existing-only", "no-push-artifact"], + default: "no-push-artifact", + options: ["existing-only", "no-push-artifact"], type: "choice", }); expect(packageAcceptance.on?.workflow_call?.inputs?.shared_image_policy).toMatchObject({ - default: "allow-push", + default: "no-push-artifact", type: "string", }); expect(standardAcceptance.with?.shared_image_policy).toBe("${{ inputs.shared_image_policy }}"); @@ -298,8 +298,8 @@ describe("release validation no-push transport", () => { }); expect(standardAcceptance.if).toContain("shared_image_policy == 'no-push-artifact'"); expectReadOnlyPackagePermission(standardAcceptance); - expect(registryAcceptance.if).toContain("shared_image_policy != 'no-push-artifact'"); - expect(registryAcceptance.permissions?.packages).toBe("write"); + expect(registryAcceptance.if).toContain("shared_image_policy == 'existing-only'"); + expectReadOnlyPackagePermission(registryAcceptance); const pluginDocker = job(pluginPrerelease, "plugin-prerelease-docker-suite"); expectReadOnlyPackagePermission(pluginDocker); @@ -322,10 +322,10 @@ describe("release validation no-push transport", () => { const dispatchPolicy = workflow.on?.workflow_dispatch?.inputs?.shared_image_policy; const callPolicy = workflow.on?.workflow_call?.inputs?.shared_image_policy; expect(dispatchPolicy).toMatchObject({ - default: "allow-push", - options: ["allow-push", "existing-only", "no-push-artifact"], + default: "no-push-artifact", + options: ["existing-only", "no-push-artifact"], }); - expect(callPolicy).toMatchObject({ default: "allow-push", type: "string" }); + expect(callPolicy).toMatchObject({ default: "no-push-artifact", type: "string" }); const validation = job(workflow, "validate_selected_ref"); expect(validation.outputs?.workflow_repository).toBe( @@ -354,28 +354,18 @@ describe("release validation no-push transport", () => { const dockerProducer = job(workflow, "prepare_docker_e2e_image"); const liveProducer = job(workflow, "prepare_live_test_image"); - const dockerPublisher = job(workflow, "push_docker_e2e_images"); - const livePublisher = job(workflow, "push_live_test_image"); expect(workflow.permissions?.actions).toBe("read"); expect(workflow.permissions?.packages).toBe("read"); expectReadOnlyPackagePermission(dockerProducer); expectReadOnlyPackagePermission(liveProducer); - expect(dockerPublisher.permissions?.packages).toBe("write"); - expect(livePublisher.permissions?.packages).toBe("write"); - expect(dockerPublisher.if).toContain("shared_image_policy == 'allow-push'"); - expect(livePublisher.if).toContain("shared_image_policy == 'allow-push'"); + expect(workflow.jobs?.push_docker_e2e_images).toBeUndefined(); + expect(workflow.jobs?.push_live_test_image).toBeUndefined(); expect(job(workflow, "docker_e2e_image_ready").permissions?.packages).toBeUndefined(); expect(job(workflow, "live_test_image_ready").permissions?.packages).toBeUndefined(); const packageWriters = Object.entries(workflow.jobs ?? {}).filter( ([, workflowJob]) => workflowJob.permissions?.packages === "write", ); - expect(packageWriters.map(([name]) => name).sort()).toEqual([ - "push_docker_e2e_images", - "push_live_test_image", - ]); - for (const [, workflowJob] of packageWriters) { - expect(workflowJob.if).toContain("shared_image_policy == 'allow-push'"); - } + expect(packageWriters).toEqual([]); const validateSelectedRef = step( job(workflow, "validate_selected_ref"), "Validate selected ref", @@ -557,13 +547,13 @@ describe("release validation no-push transport", () => { push: false, }); const dockerLoginCondition = step(dockerProducer, "Log in to GHCR").if; - expect(dockerLoginCondition).toContain("shared_image_policy == 'allow-push'"); expect(dockerLoginCondition).toContain("shared_image_policy == 'existing-only'"); + expect(dockerLoginCondition).not.toContain("allow-push"); expect(step(liveProducer, "Log in to GHCR").if).toContain( "shared_image_policy != 'no-push-artifact'", ); expect(step(dockerProducer, "Check existing shared Docker E2E images").if).toContain( - "shared_image_policy == 'allow-push'", + "shared_image_policy == 'existing-only'", ); expect(step(liveProducer, "Check existing shared live-test image").if).toContain( "shared_image_policy != 'no-push-artifact'", @@ -574,19 +564,7 @@ describe("release validation no-push transport", () => { .filter((candidate) => candidate.run?.includes("--push")) .map((candidate) => ({ candidate, jobName })), ); - expect(shellPushSteps.map(({ candidate }) => candidate.name).sort()).toEqual([ - "Build and push bare Docker E2E image", - "Build and push functional Docker E2E image", - ]); - for (const { jobName } of shellPushSteps) { - expect(jobName).toBe("push_docker_e2e_images"); - } - expect(step(livePublisher, "Build and push shared live-test image").with?.push).toBe(true); - expect(step(dockerPublisher, "Download OpenClaw Docker E2E package").with).toMatchObject({ - "artifact-ids": "${{ needs.prepare_docker_e2e_image.outputs.package_artifact_id }}", - "github-token": "${{ github.token }}", - "run-id": "${{ needs.prepare_docker_e2e_image.outputs.package_artifact_run_id }}", - }); + expect(shellPushSteps).toEqual([]); for (const name of [ "validate_docker_e2e",