From dcfc7e58fafa0b25fc7d71a61e611367b855acaf Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Fri, 22 May 2026 22:01:15 +0100 Subject: [PATCH] ci: unblock advisory Tideclaw alpha release checks --- .github/workflows/full-release-validation.yml | 104 +++++++++++++++++- .github/workflows/openclaw-release-checks.yml | 4 +- .../package-acceptance-workflow.test.ts | 7 ++ 3 files changed, 109 insertions(+), 6 deletions(-) diff --git a/.github/workflows/full-release-validation.yml b/.github/workflows/full-release-validation.yml index d91dd8e8f40..75f548d0606 100644 --- a/.github/workflows/full-release-validation.yml +++ b/.github/workflows/full-release-validation.yml @@ -479,7 +479,7 @@ jobs: local workflow="$1" shift - local before_json dispatch_output run_id status conclusion url poll_count + local before_json dispatch_output run_id status conclusion url poll_count run_json before_json="$(gh run list --workflow "$workflow" --event workflow_dispatch --limit 100 --json databaseId --jq '[.[].databaseId]')" dispatch_output="$(gh workflow run "$workflow" --ref "$CHILD_WORKFLOW_REF" "$@" 2>&1)" @@ -511,6 +511,46 @@ jobs: echo "Dispatched ${workflow}: https://github.com/${GITHUB_REPOSITORY}/actions/runs/${run_id}" echo "run_id=${run_id}" >> "$GITHUB_OUTPUT" + release_check_blocking_job() { + case "$1" in + "resolve_target" | \ + "Prepare release package artifact" | \ + "install_smoke_release_checks / "* | \ + "Run package acceptance" | \ + "Run package acceptance / "*) + return 0 + ;; + esac + return 1 + } + + release_checks_advisory_only() { + local run_json="$1" + local verifier_conclusion name saw_advisory failed + + verifier_conclusion="$( + jq -r '.jobs[] | select(.name == "Verify release checks") | .conclusion' <<< "$run_json" | + tail -n 1 + )" + if [[ "$verifier_conclusion" != "success" ]]; then + return 1 + fi + + saw_advisory=0 + failed=0 + while IFS= read -r name; do + [[ -z "${name// }" ]] && continue + if release_check_blocking_job "$name"; then + echo "::error::${name} is a package-safety Tideclaw alpha release-check lane." + failed=1 + else + saw_advisory=1 + fi + done < <(jq -r '.jobs[] | select(.conclusion != "success" and .conclusion != "skipped") | .name' <<< "$run_json") + + [[ "$saw_advisory" == "1" && "$failed" == "0" ]] + } + cancel_child() { if [[ -n "${run_id:-}" ]]; then echo "Cancelling child workflow ${workflow}: ${run_id}" >&2 @@ -534,13 +574,20 @@ jobs: done trap - EXIT INT TERM - conclusion="$(gh run view "$run_id" --json conclusion --jq '.conclusion')" - url="$(gh run view "$run_id" --json url --jq '.url')" + run_json="$(gh run view "$run_id" --json conclusion,url,jobs)" + conclusion="$(jq -r '.conclusion' <<< "$run_json")" + url="$(jq -r '.url' <<< "$run_json")" echo "${workflow} finished with ${conclusion}: ${url}" echo "url=${url}" >> "$GITHUB_OUTPUT" echo "conclusion=${conclusion}" >> "$GITHUB_OUTPUT" if [[ "$conclusion" != "success" ]]; then - gh run view "$run_id" --json jobs --jq '.jobs[] | select(.conclusion != "success" and .conclusion != "skipped") | {name, conclusion, url}' || true + jq '.jobs[] | select(.conclusion != "success" and .conclusion != "skipped") | {name, conclusion, url}' <<< "$run_json" || true + if [[ "$workflow" == "openclaw-release-checks.yml" && "$CHILD_WORKFLOW_REF" =~ ^tideclaw/alpha/[0-9]{4}-[0-9]{2}-[0-9]{2}-[0-9]{4}Z$ ]]; then + if release_checks_advisory_only "$run_json"; then + echo "::warning::${workflow} ended with ${conclusion}, but Verify release checks accepted Tideclaw alpha advisory lanes." + return 0 + fi + fi exit 1 fi } @@ -798,10 +845,51 @@ jobs: run: | set -euo pipefail + release_check_blocking_job() { + case "$1" in + "resolve_target" | \ + "Prepare release package artifact" | \ + "install_smoke_release_checks / "* | \ + "Run package acceptance" | \ + "Run package acceptance / "*) + return 0 + ;; + esac + return 1 + } + + release_checks_advisory_only() { + local run_json="$1" + local verifier_conclusion name saw_advisory failed + + verifier_conclusion="$( + jq -r '.jobs[] | select(.name == "Verify release checks") | .conclusion' <<< "$run_json" | + tail -n 1 + )" + if [[ "$verifier_conclusion" != "success" ]]; then + return 1 + fi + + saw_advisory=0 + failed=0 + while IFS= read -r name; do + [[ -z "${name// }" ]] && continue + if release_check_blocking_job "$name"; then + echo "::error::${name} is a package-safety Tideclaw alpha release-check lane." + failed=1 + else + saw_advisory=1 + fi + done < <(jq -r '.jobs[] | select(.conclusion != "success" and .conclusion != "skipped") | .name' <<< "$run_json") + + [[ "$saw_advisory" == "1" && "$failed" == "0" ]] + } + check_child() { local label="$1" local run_id="$2" local required="$3" + local advisory_ok="${4:-0}" if [[ -z "${run_id// }" ]]; then if [[ "$required" == "0" ]]; then @@ -827,6 +915,12 @@ jobs: fi if [[ "$status" != "completed" || "$conclusion" != "success" ]]; then + if [[ "$advisory_ok" == "1" && "$label" == "release_checks" ]]; then + if release_checks_advisory_only "$run_json"; then + echo "::warning::${label} child run ended with ${status}/${conclusion}, but Verify release checks accepted Tideclaw alpha advisory lanes: ${url}" + return 0 + fi + fi echo "::error::${label} child run ended with ${status}/${conclusion}: ${url}" jq '.jobs[] | select(.conclusion != "success" and .conclusion != "skipped") | {name, status, conclusion, url}' <<< "$run_json" || true return 1 @@ -1016,6 +1110,8 @@ jobs: if [[ "$RELEASE_CHECKS_RESULT" == "skipped" && -z "${RELEASE_CHECKS_RUN_ID// }" ]]; then check_child "release_checks" "" "$release_checks_required" || failed=1 + elif [[ "$CHILD_WORKFLOW_REF" =~ ^tideclaw/alpha/[0-9]{4}-[0-9]{2}-[0-9]{2}-[0-9]{4}Z$ ]]; then + check_child "release_checks" "$RELEASE_CHECKS_RUN_ID" 1 1 || failed=1 else check_child "release_checks" "$RELEASE_CHECKS_RUN_ID" 1 || failed=1 fi diff --git a/.github/workflows/openclaw-release-checks.yml b/.github/workflows/openclaw-release-checks.yml index fd72a8243bc..fa95637a241 100644 --- a/.github/workflows/openclaw-release-checks.yml +++ b/.github/workflows/openclaw-release-checks.yml @@ -670,7 +670,7 @@ jobs: pull-requests: read uses: ./.github/workflows/package-acceptance.yml with: - advisory: ${{ startsWith(github.ref, 'refs/heads/tideclaw/alpha/') }} + advisory: false workflow_ref: ${{ github.ref_name }} source: ${{ (needs.resolve_target.outputs.package_acceptance_package_spec != '' || needs.resolve_target.outputs.release_package_spec != '') && 'npm' || 'artifact' }} package_spec: ${{ needs.resolve_target.outputs.package_acceptance_package_spec || needs.resolve_target.outputs.release_package_spec || 'openclaw@beta' }} @@ -1566,7 +1566,7 @@ jobs: if [[ "$result" != "success" && "$result" != "skipped" ]]; then if [[ "$tideclaw_alpha" == "true" ]]; then case "$name" in - prepare_release_package|install_smoke_release_checks) ;; + prepare_release_package|install_smoke_release_checks|package_acceptance_release_checks) ;; *) echo "::warning::${name} ended with ${result}; Tideclaw alpha treats non-package-safety release-check lanes as advisory." continue diff --git a/test/scripts/package-acceptance-workflow.test.ts b/test/scripts/package-acceptance-workflow.test.ts index a25a5f3b595..c8faf61ea4f 100644 --- a/test/scripts/package-acceptance-workflow.test.ts +++ b/test/scripts/package-acceptance-workflow.test.ts @@ -679,6 +679,7 @@ describe("package artifact reuse", () => { expect(workflow).toContain("rerun_group:"); expect(workflow).toContain("live_suite_filter:"); expect(workflow).toContain("cross_os_suite_filter:"); + expect(workflow).toContain("advisory: false"); expect(workflow).toContain( "suite_filter: ${{ needs.resolve_target.outputs.cross_os_suite_filter }}", ); @@ -823,6 +824,12 @@ describe("package artifact reuse", () => { 'case "$RERUN_GROUP" in', "release-checks|install-smoke|cross-os|live-e2e|package|qa|qa-parity|qa-live)", "cancel-in-progress: ${{ (inputs.ref == 'main' && inputs.rerun_group == 'all') || startsWith(inputs.ref, 'tideclaw/alpha/') }}", + "Verify release checks accepted Tideclaw alpha advisory lanes", + "release_checks_advisory_only", + "release_check_blocking_job", + "is a package-safety Tideclaw alpha release-check lane", + "package_acceptance_release_checks) ;;", + 'check_child "release_checks" "$RELEASE_CHECKS_RUN_ID" 1 1', "gh run cancel", "NORMAL_CI_RESULT: ${{ needs.normal_ci.result }}", ]);