mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-06 10:20:42 +00:00
340 lines
12 KiB
YAML
340 lines
12 KiB
YAML
name: Full Release Validation
|
|
|
|
on:
|
|
workflow_dispatch:
|
|
inputs:
|
|
ref:
|
|
description: Branch, tag, or full commit SHA to validate
|
|
required: true
|
|
default: main
|
|
type: string
|
|
workflow_ref:
|
|
description: Trusted workflow ref used to run child workflows
|
|
required: false
|
|
default: main
|
|
type: string
|
|
provider:
|
|
description: Provider lane for cross-OS onboarding and the end-to-end agent turn
|
|
required: false
|
|
default: openai
|
|
type: choice
|
|
options:
|
|
- openai
|
|
- anthropic
|
|
- minimax
|
|
mode:
|
|
description: Which cross-OS release lanes to run
|
|
required: false
|
|
default: both
|
|
type: choice
|
|
options:
|
|
- fresh
|
|
- upgrade
|
|
- both
|
|
npm_telegram_package_spec:
|
|
description: Optional published package spec for the post-publish Telegram E2E lane
|
|
required: false
|
|
default: ""
|
|
type: string
|
|
npm_telegram_provider_mode:
|
|
description: Provider mode for the optional post-publish Telegram E2E lane
|
|
required: false
|
|
default: mock-openai
|
|
type: choice
|
|
options:
|
|
- mock-openai
|
|
- live-frontier
|
|
npm_telegram_scenario:
|
|
description: Optional comma-separated Telegram scenario ids for the post-publish lane
|
|
required: false
|
|
default: ""
|
|
type: string
|
|
|
|
permissions:
|
|
actions: write
|
|
contents: read
|
|
|
|
concurrency:
|
|
group: full-release-validation-${{ inputs.ref }}
|
|
cancel-in-progress: false
|
|
|
|
env:
|
|
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: "true"
|
|
|
|
jobs:
|
|
resolve_target:
|
|
name: Resolve target ref
|
|
runs-on: ubuntu-24.04
|
|
timeout-minutes: 10
|
|
outputs:
|
|
sha: ${{ steps.resolve.outputs.sha }}
|
|
steps:
|
|
- name: Checkout target ref
|
|
uses: actions/checkout@v6
|
|
with:
|
|
ref: ${{ inputs.ref }}
|
|
fetch-depth: 0
|
|
persist-credentials: false
|
|
submodules: false
|
|
|
|
- name: Resolve target SHA
|
|
id: resolve
|
|
run: echo "sha=$(git rev-parse HEAD)" >> "$GITHUB_OUTPUT"
|
|
|
|
- name: Summarize target
|
|
env:
|
|
TARGET_REF: ${{ inputs.ref }}
|
|
TARGET_SHA: ${{ steps.resolve.outputs.sha }}
|
|
WORKFLOW_REF: ${{ inputs.workflow_ref }}
|
|
NPM_TELEGRAM_PACKAGE_SPEC: ${{ inputs.npm_telegram_package_spec }}
|
|
run: |
|
|
{
|
|
echo "## Full release validation"
|
|
echo
|
|
echo "- Target ref: \`${TARGET_REF}\`"
|
|
echo "- Target SHA: \`${TARGET_SHA}\`"
|
|
echo "- Child workflow ref: \`${WORKFLOW_REF}\`"
|
|
echo "- Normal CI: \`CI\` with \`target_ref=${TARGET_REF}\`"
|
|
echo "- Release/live/Docker/QA: \`OpenClaw Release Checks\`"
|
|
if [[ -n "${NPM_TELEGRAM_PACKAGE_SPEC// }" ]]; then
|
|
echo "- Post-publish Telegram E2E: \`${NPM_TELEGRAM_PACKAGE_SPEC}\`"
|
|
else
|
|
echo "- Post-publish Telegram E2E: skipped because no published package spec was provided"
|
|
fi
|
|
} >> "$GITHUB_STEP_SUMMARY"
|
|
|
|
normal_ci:
|
|
name: Run normal full CI
|
|
needs: [resolve_target]
|
|
runs-on: ubuntu-24.04
|
|
timeout-minutes: 240
|
|
steps:
|
|
- name: Dispatch and monitor CI
|
|
env:
|
|
GH_TOKEN: ${{ github.token }}
|
|
TARGET_REF: ${{ inputs.ref }}
|
|
TARGET_SHA: ${{ needs.resolve_target.outputs.sha }}
|
|
WORKFLOW_REF: ${{ inputs.workflow_ref }}
|
|
run: |
|
|
set -euo pipefail
|
|
|
|
dispatch_and_wait() {
|
|
local workflow="$1"
|
|
local workflow_ref="$2"
|
|
shift 2
|
|
|
|
local before_json run_id status conclusion url
|
|
before_json="$(gh run list --workflow "$workflow" --event workflow_dispatch --limit 100 --json databaseId --jq '[.[].databaseId]')"
|
|
|
|
gh workflow run "$workflow" --ref "$workflow_ref" "$@"
|
|
|
|
for _ in $(seq 1 60); do
|
|
run_id="$(
|
|
BEFORE_IDS="$before_json" gh run list --workflow "$workflow" --event workflow_dispatch --limit 50 --json databaseId,createdAt \
|
|
--jq 'map(select(.databaseId as $id | (env.BEFORE_IDS | fromjson | index($id) | not))) | sort_by(.createdAt) | reverse | .[0].databaseId // empty'
|
|
)"
|
|
if [[ -n "$run_id" ]]; then
|
|
break
|
|
fi
|
|
sleep 5
|
|
done
|
|
|
|
if [[ -z "${run_id:-}" ]]; then
|
|
echo "Could not find dispatched run for ${workflow}." >&2
|
|
exit 1
|
|
fi
|
|
|
|
echo "Dispatched ${workflow}: https://github.com/${GITHUB_REPOSITORY}/actions/runs/${run_id}"
|
|
|
|
while true; do
|
|
status="$(gh run view "$run_id" --json status --jq '.status')"
|
|
if [[ "$status" == "completed" ]]; then
|
|
break
|
|
fi
|
|
sleep 30
|
|
done
|
|
|
|
conclusion="$(gh run view "$run_id" --json conclusion --jq '.conclusion')"
|
|
url="$(gh run view "$run_id" --json url --jq '.url')"
|
|
echo "${workflow} finished with ${conclusion}: ${url}"
|
|
if [[ "$conclusion" != "success" ]]; then
|
|
gh run view "$run_id" --json jobs --jq '.jobs[] | select(.conclusion != "success" and .conclusion != "skipped") | {name, conclusion, url}'
|
|
exit 1
|
|
fi
|
|
}
|
|
|
|
{
|
|
echo "### Normal CI"
|
|
echo
|
|
echo "- Target ref: \`${TARGET_REF}\`"
|
|
echo "- Target SHA: \`${TARGET_SHA}\`"
|
|
} >> "$GITHUB_STEP_SUMMARY"
|
|
|
|
dispatch_and_wait ci.yml "$WORKFLOW_REF" -f target_ref="$TARGET_REF"
|
|
|
|
release_checks:
|
|
name: Run release/live/Docker/QA validation
|
|
needs: [resolve_target]
|
|
runs-on: ubuntu-24.04
|
|
timeout-minutes: 720
|
|
steps:
|
|
- name: Dispatch and monitor release checks
|
|
env:
|
|
GH_TOKEN: ${{ github.token }}
|
|
TARGET_REF: ${{ inputs.ref }}
|
|
TARGET_SHA: ${{ needs.resolve_target.outputs.sha }}
|
|
WORKFLOW_REF: ${{ inputs.workflow_ref }}
|
|
PROVIDER: ${{ inputs.provider }}
|
|
MODE: ${{ inputs.mode }}
|
|
run: |
|
|
set -euo pipefail
|
|
|
|
dispatch_and_wait() {
|
|
local workflow="$1"
|
|
local workflow_ref="$2"
|
|
shift 2
|
|
|
|
local before_json run_id status conclusion url
|
|
before_json="$(gh run list --workflow "$workflow" --event workflow_dispatch --limit 100 --json databaseId --jq '[.[].databaseId]')"
|
|
|
|
gh workflow run "$workflow" --ref "$workflow_ref" "$@"
|
|
|
|
for _ in $(seq 1 60); do
|
|
run_id="$(
|
|
BEFORE_IDS="$before_json" gh run list --workflow "$workflow" --event workflow_dispatch --limit 50 --json databaseId,createdAt \
|
|
--jq 'map(select(.databaseId as $id | (env.BEFORE_IDS | fromjson | index($id) | not))) | sort_by(.createdAt) | reverse | .[0].databaseId // empty'
|
|
)"
|
|
if [[ -n "$run_id" ]]; then
|
|
break
|
|
fi
|
|
sleep 5
|
|
done
|
|
|
|
if [[ -z "${run_id:-}" ]]; then
|
|
echo "Could not find dispatched run for ${workflow}." >&2
|
|
exit 1
|
|
fi
|
|
|
|
echo "Dispatched ${workflow}: https://github.com/${GITHUB_REPOSITORY}/actions/runs/${run_id}"
|
|
|
|
while true; do
|
|
status="$(gh run view "$run_id" --json status --jq '.status')"
|
|
if [[ "$status" == "completed" ]]; then
|
|
break
|
|
fi
|
|
sleep 60
|
|
done
|
|
|
|
conclusion="$(gh run view "$run_id" --json conclusion --jq '.conclusion')"
|
|
url="$(gh run view "$run_id" --json url --jq '.url')"
|
|
echo "${workflow} finished with ${conclusion}: ${url}"
|
|
if [[ "$conclusion" != "success" ]]; then
|
|
gh run view "$run_id" --json jobs --jq '.jobs[] | select(.conclusion != "success" and .conclusion != "skipped") | {name, conclusion, url}'
|
|
exit 1
|
|
fi
|
|
}
|
|
|
|
{
|
|
echo "### Release/live/Docker/QA validation"
|
|
echo
|
|
echo "- Target ref: \`${TARGET_REF}\`"
|
|
echo "- Target SHA: \`${TARGET_SHA}\`"
|
|
echo "- Provider: \`${PROVIDER}\`"
|
|
echo "- Cross-OS mode: \`${MODE}\`"
|
|
} >> "$GITHUB_STEP_SUMMARY"
|
|
|
|
dispatch_and_wait openclaw-release-checks.yml "$WORKFLOW_REF" \
|
|
-f ref="$TARGET_REF" \
|
|
-f provider="$PROVIDER" \
|
|
-f mode="$MODE"
|
|
|
|
npm_telegram:
|
|
name: Run post-publish Telegram E2E
|
|
needs: [resolve_target]
|
|
if: inputs.npm_telegram_package_spec != ''
|
|
runs-on: ubuntu-24.04
|
|
timeout-minutes: 120
|
|
steps:
|
|
- name: Dispatch and monitor npm Telegram E2E
|
|
env:
|
|
GH_TOKEN: ${{ github.token }}
|
|
WORKFLOW_REF: ${{ inputs.workflow_ref }}
|
|
PACKAGE_SPEC: ${{ inputs.npm_telegram_package_spec }}
|
|
PROVIDER_MODE: ${{ inputs.npm_telegram_provider_mode }}
|
|
SCENARIO: ${{ inputs.npm_telegram_scenario }}
|
|
run: |
|
|
set -euo pipefail
|
|
|
|
before_json="$(gh run list --workflow npm-telegram-beta-e2e.yml --event workflow_dispatch --limit 100 --json databaseId --jq '[.[].databaseId]')"
|
|
|
|
args=(-f package_spec="$PACKAGE_SPEC" -f provider_mode="$PROVIDER_MODE")
|
|
if [[ -n "${SCENARIO// }" ]]; then
|
|
args+=(-f scenario="$SCENARIO")
|
|
fi
|
|
|
|
gh workflow run npm-telegram-beta-e2e.yml --ref "$WORKFLOW_REF" "${args[@]}"
|
|
|
|
run_id=""
|
|
for _ in $(seq 1 60); do
|
|
run_id="$(
|
|
BEFORE_IDS="$before_json" gh run list --workflow npm-telegram-beta-e2e.yml --event workflow_dispatch --limit 50 --json databaseId,createdAt \
|
|
--jq 'map(select(.databaseId as $id | (env.BEFORE_IDS | fromjson | index($id) | not))) | sort_by(.createdAt) | reverse | .[0].databaseId // empty'
|
|
)"
|
|
if [[ -n "$run_id" ]]; then
|
|
break
|
|
fi
|
|
sleep 5
|
|
done
|
|
|
|
if [[ -z "$run_id" ]]; then
|
|
echo "Could not find dispatched run for npm-telegram-beta-e2e.yml." >&2
|
|
exit 1
|
|
fi
|
|
|
|
echo "Dispatched npm-telegram-beta-e2e.yml: https://github.com/${GITHUB_REPOSITORY}/actions/runs/${run_id}"
|
|
|
|
while true; do
|
|
status="$(gh run view "$run_id" --json status --jq '.status')"
|
|
if [[ "$status" == "completed" ]]; then
|
|
break
|
|
fi
|
|
sleep 60
|
|
done
|
|
|
|
conclusion="$(gh run view "$run_id" --json conclusion --jq '.conclusion')"
|
|
url="$(gh run view "$run_id" --json url --jq '.url')"
|
|
echo "npm-telegram-beta-e2e.yml finished with ${conclusion}: ${url}"
|
|
if [[ "$conclusion" != "success" ]]; then
|
|
gh run view "$run_id" --json jobs --jq '.jobs[] | select(.conclusion != "success" and .conclusion != "skipped") | {name, conclusion, url}'
|
|
exit 1
|
|
fi
|
|
|
|
summary:
|
|
name: Verify full validation
|
|
needs: [normal_ci, release_checks, npm_telegram]
|
|
if: always()
|
|
runs-on: ubuntu-24.04
|
|
timeout-minutes: 5
|
|
steps:
|
|
- name: Verify child workflow results
|
|
env:
|
|
NORMAL_CI_RESULT: ${{ needs.normal_ci.result }}
|
|
RELEASE_CHECKS_RESULT: ${{ needs.release_checks.result }}
|
|
NPM_TELEGRAM_RESULT: ${{ needs.npm_telegram.result }}
|
|
run: |
|
|
set -euo pipefail
|
|
failed=0
|
|
for item in \
|
|
"normal_ci=${NORMAL_CI_RESULT}" \
|
|
"release_checks=${RELEASE_CHECKS_RESULT}" \
|
|
"npm_telegram=${NPM_TELEGRAM_RESULT}"
|
|
do
|
|
name="${item%%=*}"
|
|
result="${item#*=}"
|
|
if [[ "$result" != "success" && "$result" != "skipped" ]]; then
|
|
echo "::error::${name} ended with ${result}"
|
|
failed=1
|
|
fi
|
|
done
|
|
exit "$failed"
|