mirror of
https://github.com/openclaw/openclaw.git
synced 2026-08-12 21:53:00 -06:00
148 lines
7.2 KiB
YAML
148 lines
7.2 KiB
YAML
name: Blacksmith Testbox
|
|
on:
|
|
workflow_dispatch:
|
|
inputs:
|
|
testbox_id:
|
|
type: string
|
|
description: "Testbox session ID"
|
|
required: true
|
|
timeout_minutes:
|
|
type: number
|
|
description: "Maximum GitHub job runtime for long Testbox commands"
|
|
default: 120
|
|
pull_request:
|
|
types: [opened, reopened, synchronize, ready_for_review]
|
|
paths:
|
|
- ".github/workflows/**"
|
|
|
|
permissions:
|
|
contents: read
|
|
|
|
concurrency:
|
|
group: ${{ github.event_name == 'pull_request' && format('{0}-pr-v1-{1}', github.workflow, github.event.pull_request.number) || format('{0}-manual-v1-{1}', github.workflow, github.run_id) }}
|
|
cancel-in-progress: ${{ github.event_name == 'pull_request' }}
|
|
|
|
env:
|
|
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: "true"
|
|
PNPM_CONFIG_VERIFY_DEPS_BEFORE_RUN: "false"
|
|
|
|
jobs:
|
|
check:
|
|
if: ${{ github.event_name != 'pull_request' || !github.event.pull_request.draft }}
|
|
permissions:
|
|
contents: read
|
|
name: "check"
|
|
# Pull requests only validate the hydration steps; real Testbox leases arrive via dispatch.
|
|
runs-on: ${{ github.event_name == 'pull_request' && 'ubuntu-24.04' || 'blacksmith-16vcpu-ubuntu-2404' }}
|
|
timeout-minutes: ${{ fromJSON(inputs.timeout_minutes || '120') }}
|
|
steps:
|
|
# Testbox lifecycle actions require Blacksmith VM metadata; PRs validate our setup steps only.
|
|
- name: Begin Testbox
|
|
if: github.event_name == 'workflow_dispatch'
|
|
uses: useblacksmith/begin-testbox@233448af4bfdc6fca509a7f0974411ac6d8a8043
|
|
with:
|
|
testbox_id: ${{ inputs.testbox_id }}
|
|
- name: Checkout
|
|
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
|
|
with:
|
|
# Dispatch hydrates the pinned workflow ref; changed-gate sync later
|
|
# reconstructs its exact base and final tree. PR validation keeps both commits.
|
|
fetch-depth: ${{ github.event_name == 'pull_request' && '2' || '1' }}
|
|
persist-credentials: false
|
|
- name: Setup Node environment
|
|
uses: ./.github/actions/setup-node-env
|
|
with:
|
|
install-bun: "false"
|
|
install-trufflehog: "true"
|
|
# Real Testbox hydration reuses the protected dependency snapshot.
|
|
# Pull-request validation runs on GitHub-hosted runners instead.
|
|
sticky-disk: ${{ github.event_name == 'workflow_dispatch' && 'true' || 'false' }}
|
|
use-actions-cache: ${{ github.event_name == 'workflow_dispatch' && 'false' || 'true' }}
|
|
- name: Ensure Testbox base commit
|
|
if: github.event_name == 'pull_request'
|
|
uses: ./.github/actions/ensure-base-commit
|
|
with:
|
|
base-sha: ${{ github.event.pull_request.base.sha }}
|
|
fetch-ref: ${{ github.event.pull_request.base.ref }}
|
|
- name: Prepare Testbox shell
|
|
uses: ./.github/actions/prepare-testbox-shell
|
|
with:
|
|
base-ref: ${{ github.event_name == 'pull_request' && github.event.pull_request.base.sha || 'HEAD' }}
|
|
|
|
- name: Hydrate Testbox provider env helper
|
|
shell: bash
|
|
env:
|
|
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
|
|
ANTHROPIC_API_KEY_OLD: ${{ secrets.ANTHROPIC_API_KEY_OLD }}
|
|
ANTHROPIC_API_TOKEN: ${{ secrets.ANTHROPIC_API_TOKEN }}
|
|
BYTEPLUS_API_KEY: ${{ secrets.BYTEPLUS_API_KEY }}
|
|
CEREBRAS_API_KEY: ${{ secrets.CEREBRAS_API_KEY }}
|
|
DEEPINFRA_API_KEY: ${{ secrets.DEEPINFRA_API_KEY }}
|
|
DASHSCOPE_API_KEY: ${{ secrets.DASHSCOPE_API_KEY }}
|
|
FACTORY_API_KEY: ${{ secrets.FACTORY_API_KEY }}
|
|
FIREWORKS_API_KEY: ${{ secrets.FIREWORKS_API_KEY }}
|
|
GEMINI_API_KEY: ${{ secrets.GEMINI_API_KEY }}
|
|
GOOGLE_API_KEY: ${{ secrets.GOOGLE_API_KEY }}
|
|
GROQ_API_KEY: ${{ secrets.GROQ_API_KEY }}
|
|
KIMI_API_KEY: ${{ secrets.KIMI_API_KEY }}
|
|
MINIMAX_API_KEY: ${{ secrets.MINIMAX_API_KEY }}
|
|
MODELSTUDIO_API_KEY: ${{ secrets.MODELSTUDIO_API_KEY }}
|
|
MISTRAL_API_KEY: ${{ secrets.MISTRAL_API_KEY }}
|
|
MOONSHOT_API_KEY: ${{ secrets.MOONSHOT_API_KEY }}
|
|
OPENCODE_API_KEY: ${{ secrets.OPENCODE_API_KEY }}
|
|
OPENCODE_ZEN_API_KEY: ${{ secrets.OPENCODE_ZEN_API_KEY }}
|
|
OPENCLAW_LIVE_BROWSER_CDP_URL: ${{ secrets.OPENCLAW_LIVE_BROWSER_CDP_URL }}
|
|
OPENCLAW_LIVE_SETUP_TOKEN: ${{ secrets.OPENCLAW_LIVE_SETUP_TOKEN }}
|
|
OPENCLAW_LIVE_SETUP_TOKEN_MODEL: ${{ secrets.OPENCLAW_LIVE_SETUP_TOKEN_MODEL }}
|
|
OPENCLAW_LIVE_SETUP_TOKEN_PROFILE: ${{ secrets.OPENCLAW_LIVE_SETUP_TOKEN_PROFILE }}
|
|
OPENCLAW_LIVE_SETUP_TOKEN_VALUE: ${{ secrets.OPENCLAW_LIVE_SETUP_TOKEN_VALUE }}
|
|
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
|
|
OPENAI_BASE_URL: ${{ secrets.OPENAI_BASE_URL }}
|
|
OPENROUTER_API_KEY: ${{ secrets.OPENROUTER_API_KEY }}
|
|
QWEN_API_KEY: ${{ secrets.QWEN_API_KEY }}
|
|
FAL_KEY: ${{ secrets.FAL_KEY }}
|
|
RUNWAY_API_KEY: ${{ secrets.RUNWAY_API_KEY }}
|
|
DEEPGRAM_API_KEY: ${{ secrets.DEEPGRAM_API_KEY }}
|
|
TOGETHER_API_KEY: ${{ secrets.TOGETHER_API_KEY }}
|
|
VYDRA_API_KEY: ${{ secrets.VYDRA_API_KEY }}
|
|
XAI_API_KEY: ${{ secrets.XAI_API_KEY }}
|
|
ZAI_API_KEY: ${{ secrets.ZAI_API_KEY }}
|
|
Z_AI_API_KEY: ${{ secrets.Z_AI_API_KEY }}
|
|
BYTEPLUS_ACCESS_KEY_ID: ${{ secrets.BYTEPLUS_ACCESS_KEY_ID }}
|
|
BYTEPLUS_SECRET_ACCESS_KEY: ${{ secrets.BYTEPLUS_SECRET_ACCESS_KEY }}
|
|
CLAUDE_CODE_OAUTH_TOKEN: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}
|
|
OPENCLAW_CODEX_AUTH_JSON: ${{ secrets.OPENCLAW_CODEX_AUTH_JSON }}
|
|
OPENCLAW_CODEX_CONFIG_TOML: ${{ secrets.OPENCLAW_CODEX_CONFIG_TOML }}
|
|
OPENCLAW_CLAUDE_JSON: ${{ secrets.OPENCLAW_CLAUDE_JSON }}
|
|
OPENCLAW_CLAUDE_CREDENTIALS_JSON: ${{ secrets.OPENCLAW_CLAUDE_CREDENTIALS_JSON }}
|
|
OPENCLAW_CLAUDE_SETTINGS_JSON: ${{ secrets.OPENCLAW_CLAUDE_SETTINGS_JSON }}
|
|
OPENCLAW_CLAUDE_SETTINGS_LOCAL_JSON: ${{ secrets.OPENCLAW_CLAUDE_SETTINGS_LOCAL_JSON }}
|
|
OPENCLAW_GEMINI_SETTINGS_JSON: ${{ secrets.OPENCLAW_GEMINI_SETTINGS_JSON }}
|
|
run: bash scripts/ci-hydrate-testbox-env.sh
|
|
|
|
- name: Run Testbox
|
|
uses: useblacksmith/run-testbox@3f60ff9ceb2c10c3feefa87dc0c6490cffae059d
|
|
if: github.event_name == 'workflow_dispatch' && always()
|
|
env:
|
|
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: "true"
|
|
|
|
- name: Close Testbox SSH sessions
|
|
if: github.event_name == 'workflow_dispatch' && always()
|
|
shell: bash
|
|
run: |
|
|
set -euo pipefail
|
|
|
|
# Testbox state stores Blacksmith's external forwarded port. Resolve
|
|
# sshd's VM-local listener because that is the sport visible to ss.
|
|
runner_ssh_local_port="$(sudo sshd -T 2>/dev/null | awk '$1 == "port" { print $2; exit }')"
|
|
if [[ ! "$runner_ssh_local_port" =~ ^[0-9]+$ ]] ||
|
|
(( runner_ssh_local_port < 1 || runner_ssh_local_port > 65535 )); then
|
|
echo "No valid local SSH listener port found; skipping session cleanup"
|
|
exit 0
|
|
fi
|
|
|
|
# run-testbox has no post hook. Close only Testbox client sockets so
|
|
# Blacksmith's runner teardown does not wait for its 290-second grace.
|
|
timeout --signal=KILL 5s sudo ss -K state established \
|
|
"( sport = :${runner_ssh_local_port} )" || true
|