





















@@ -1260,11 +1260,83 @@ jobs:
12601260provenance: mode=max
12611261push: true
126212621263+prepare_live_test_image:
1264+needs: validate_selected_ref
1265+if: inputs.include_live_suites
1266+runs-on: blacksmith-32vcpu-ubuntu-2404
1267+timeout-minutes: 60
1268+permissions:
1269+contents: read
1270+packages: write
1271+outputs:
1272+live_image: ${{ steps.image.outputs.live_image }}
1273+env:
1274+DOCKER_BUILD_SUMMARY: "false"
1275+DOCKER_BUILD_RECORD_UPLOAD: "false"
1276+steps:
1277+ - name: Checkout selected ref
1278+uses: actions/checkout@v6
1279+with:
1280+ref: ${{ needs.validate_selected_ref.outputs.selected_sha }}
1281+fetch-depth: 1
1282+1283+ - name: Resolve shared live-test image tag
1284+id: image
1285+shell: bash
1286+env:
1287+SELECTED_SHA: ${{ needs.validate_selected_ref.outputs.selected_sha }}
1288+run: |
1289+ set -euo pipefail
1290+ repository="${GITHUB_REPOSITORY,,}"
1291+ live_image="ghcr.io/${repository}-live-test:${SELECTED_SHA}"
1292+ echo "live_image=${live_image}" >> "$GITHUB_OUTPUT"
1293+ echo "Shared live-test image: \`${live_image}\`" >> "$GITHUB_STEP_SUMMARY"
1294+1295+ - name: Log in to GHCR
1296+uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 # v4
1297+with:
1298+registry: ghcr.io
1299+username: ${{ github.actor }}
1300+password: ${{ github.token }}
1301+1302+ - name: Check existing shared live-test image
1303+id: image_exists
1304+shell: bash
1305+run: |
1306+ set -euo pipefail
1307+ if docker manifest inspect "${{ steps.image.outputs.live_image }}" >/dev/null 2>&1; then
1308+ echo "Shared live-test image already exists: ${{ steps.image.outputs.live_image }}"
1309+ echo "exists=1" >> "$GITHUB_OUTPUT"
1310+ else
1311+ echo "exists=0" >> "$GITHUB_OUTPUT"
1312+ fi
1313+1314+ - name: Setup Docker builder
1315+if: steps.image_exists.outputs.exists != '1'
1316+uses: useblacksmith/setup-docker-builder@ac083cc84672d01c60d5e8561d0a939b697de542 # v1
1317+with:
1318+max-cache-size-mb: 800000
1319+1320+ - name: Build and push shared live-test image
1321+if: steps.image_exists.outputs.exists != '1'
1322+uses: useblacksmith/build-push-action@cbd1f60d194a98cb3be5523b15134501eaf0fbf3 # v2
1323+with:
1324+context: .
1325+file: ./Dockerfile
1326+target: build
1327+build-args: |
1328+ OPENCLAW_EXTENSIONS=matrix
1329+ platforms: linux/amd64
1330+tags: ${{ steps.image.outputs.live_image }}
1331+sbom: true
1332+provenance: mode=max
1333+push: true
1334+12631335validate_live_models_docker:
12641336name: Docker live models (${{ matrix.provider_label }})
1265-needs: validate_selected_ref
1337+needs: [validate_selected_ref, prepare_live_test_image]
12661338if: inputs.include_live_suites && inputs.live_model_providers == ''
1267-runs-on: ubuntu-24.04
1339+runs-on: blacksmith-32vcpu-ubuntu-2404
12681340timeout-minutes: 75
12691341strategy:
12701342fail-fast: false
@@ -1332,6 +1404,8 @@ jobs:
13321404OPENCLAW_GEMINI_SETTINGS_JSON: ${{ secrets.OPENCLAW_GEMINI_SETTINGS_JSON }}
13331405FIREWORKS_API_KEY: ${{ secrets.FIREWORKS_API_KEY }}
13341406OPENCLAW_LIVE_PROVIDERS: ${{ matrix.providers }}
1407+OPENCLAW_LIVE_IMAGE: ${{ needs.prepare_live_test_image.outputs.live_image }}
1408+OPENCLAW_SKIP_DOCKER_BUILD: "1"
13351409OPENCLAW_VITEST_MAX_WORKERS: "2"
13361410steps:
13371411 - name: Checkout selected ref
@@ -1361,6 +1435,14 @@ jobs:
13611435if: contains(matrix.profiles, inputs.release_test_profile)
13621436run: bash scripts/ci-hydrate-live-auth.sh
136314371438+ - name: Log in to GHCR
1439+if: contains(matrix.profiles, inputs.release_test_profile)
1440+uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 # v4
1441+with:
1442+registry: ghcr.io
1443+username: ${{ github.actor }}
1444+password: ${{ github.token }}
1445+13641446 - name: Validate provider credential
13651447if: contains(matrix.profiles, inputs.release_test_profile)
13661448shell: bash
@@ -1402,9 +1484,9 @@ jobs:
1402148414031485validate_live_models_docker_targeted:
14041486name: Docker live models (selected providers)
1405-needs: validate_selected_ref
1487+needs: [validate_selected_ref, prepare_live_test_image]
14061488if: inputs.include_live_suites && inputs.live_model_providers != ''
1407-runs-on: ubuntu-24.04
1489+runs-on: blacksmith-32vcpu-ubuntu-2404
14081490timeout-minutes: 75
14091491env:
14101492OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
@@ -1441,6 +1523,8 @@ jobs:
14411523OPENCLAW_GEMINI_SETTINGS_JSON: ${{ secrets.OPENCLAW_GEMINI_SETTINGS_JSON }}
14421524FIREWORKS_API_KEY: ${{ secrets.FIREWORKS_API_KEY }}
14431525REQUESTED_LIVE_MODEL_PROVIDERS: ${{ inputs.live_model_providers }}
1526+OPENCLAW_LIVE_IMAGE: ${{ needs.prepare_live_test_image.outputs.live_image }}
1527+OPENCLAW_SKIP_DOCKER_BUILD: "1"
14441528OPENCLAW_VITEST_MAX_WORKERS: "2"
14451529steps:
14461530 - name: Checkout selected ref
@@ -1525,6 +1609,13 @@ jobs:
15251609 - name: Hydrate live auth/profile inputs
15261610run: bash scripts/ci-hydrate-live-auth.sh
152716111612+ - name: Log in to GHCR
1613+uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 # v4
1614+with:
1615+registry: ghcr.io
1616+username: ${{ github.actor }}
1617+password: ${{ github.token }}
1618+15281619 - name: Validate provider credentials
15291620shell: bash
15301621run: |
@@ -1688,6 +1779,150 @@ jobs:
16881779timeout_minutes: 90
16891780profile_env_only: false
16901781profiles: full
1782+env:
1783+OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
1784+OPENAI_BASE_URL: ${{ secrets.OPENAI_BASE_URL }}
1785+ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
1786+ANTHROPIC_API_TOKEN: ${{ secrets.ANTHROPIC_API_TOKEN }}
1787+ANTHROPIC_API_KEY_OLD: ${{ secrets.ANTHROPIC_API_KEY_OLD }}
1788+BYTEPLUS_API_KEY: ${{ secrets.BYTEPLUS_API_KEY }}
1789+CEREBRAS_API_KEY: ${{ secrets.CEREBRAS_API_KEY }}
1790+DEEPINFRA_API_KEY: ${{ secrets.DEEPINFRA_API_KEY }}
1791+DASHSCOPE_API_KEY: ${{ secrets.DASHSCOPE_API_KEY }}
1792+GROQ_API_KEY: ${{ secrets.GROQ_API_KEY }}
1793+KIMI_API_KEY: ${{ secrets.KIMI_API_KEY }}
1794+MODELSTUDIO_API_KEY: ${{ secrets.MODELSTUDIO_API_KEY }}
1795+MOONSHOT_API_KEY: ${{ secrets.MOONSHOT_API_KEY }}
1796+MISTRAL_API_KEY: ${{ secrets.MISTRAL_API_KEY }}
1797+MINIMAX_API_KEY: ${{ secrets.MINIMAX_API_KEY }}
1798+OPENCODE_API_KEY: ${{ secrets.OPENCODE_API_KEY }}
1799+OPENCODE_ZEN_API_KEY: ${{ secrets.OPENCODE_ZEN_API_KEY }}
1800+OPENCLAW_LIVE_BROWSER_CDP_URL: ${{ secrets.OPENCLAW_LIVE_BROWSER_CDP_URL }}
1801+OPENCLAW_LIVE_SETUP_TOKEN: ${{ secrets.OPENCLAW_LIVE_SETUP_TOKEN }}
1802+OPENCLAW_LIVE_SETUP_TOKEN_MODEL: ${{ secrets.OPENCLAW_LIVE_SETUP_TOKEN_MODEL }}
1803+OPENCLAW_LIVE_SETUP_TOKEN_PROFILE: ${{ secrets.OPENCLAW_LIVE_SETUP_TOKEN_PROFILE }}
1804+OPENCLAW_LIVE_SETUP_TOKEN_VALUE: ${{ secrets.OPENCLAW_LIVE_SETUP_TOKEN_VALUE }}
1805+GEMINI_API_KEY: ${{ secrets.GEMINI_API_KEY }}
1806+GOOGLE_API_KEY: ${{ secrets.GOOGLE_API_KEY }}
1807+OPENROUTER_API_KEY: ${{ secrets.OPENROUTER_API_KEY }}
1808+QWEN_API_KEY: ${{ secrets.QWEN_API_KEY }}
1809+FAL_KEY: ${{ secrets.FAL_KEY }}
1810+RUNWAY_API_KEY: ${{ secrets.RUNWAY_API_KEY }}
1811+DEEPGRAM_API_KEY: ${{ secrets.DEEPGRAM_API_KEY }}
1812+TOGETHER_API_KEY: ${{ secrets.TOGETHER_API_KEY }}
1813+VYDRA_API_KEY: ${{ secrets.VYDRA_API_KEY }}
1814+XAI_API_KEY: ${{ secrets.XAI_API_KEY }}
1815+ZAI_API_KEY: ${{ secrets.ZAI_API_KEY }}
1816+Z_AI_API_KEY: ${{ secrets.Z_AI_API_KEY }}
1817+BYTEPLUS_ACCESS_KEY_ID: ${{ secrets.BYTEPLUS_ACCESS_KEY_ID }}
1818+BYTEPLUS_SECRET_ACCESS_KEY: ${{ secrets.BYTEPLUS_SECRET_ACCESS_KEY }}
1819+CLAUDE_CODE_OAUTH_TOKEN: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}
1820+OPENCLAW_CODEX_AUTH_JSON: ${{ secrets.OPENCLAW_CODEX_AUTH_JSON }}
1821+OPENCLAW_CODEX_CONFIG_TOML: ${{ secrets.OPENCLAW_CODEX_CONFIG_TOML }}
1822+OPENCLAW_CLAUDE_JSON: ${{ secrets.OPENCLAW_CLAUDE_JSON }}
1823+OPENCLAW_CLAUDE_CREDENTIALS_JSON: ${{ secrets.OPENCLAW_CLAUDE_CREDENTIALS_JSON }}
1824+OPENCLAW_CLAUDE_SETTINGS_JSON: ${{ secrets.OPENCLAW_CLAUDE_SETTINGS_JSON }}
1825+OPENCLAW_CLAUDE_SETTINGS_LOCAL_JSON: ${{ secrets.OPENCLAW_CLAUDE_SETTINGS_LOCAL_JSON }}
1826+OPENCLAW_GEMINI_SETTINGS_JSON: ${{ secrets.OPENCLAW_GEMINI_SETTINGS_JSON }}
1827+FIREWORKS_API_KEY: ${{ secrets.FIREWORKS_API_KEY }}
1828+OPENCLAW_LIVE_VIDEO_GENERATION_SKIP_PROVIDERS: ""
1829+OPENCLAW_LIVE_VYDRA_VIDEO: "1"
1830+OPENCLAW_VITEST_MAX_WORKERS: "2"
1831+steps:
1832+ - name: Checkout selected ref
1833+if: contains(matrix.profiles, inputs.release_test_profile)
1834+uses: actions/checkout@v6
1835+with:
1836+ref: ${{ needs.validate_selected_ref.outputs.selected_sha }}
1837+fetch-depth: 1
1838+1839+ - name: Checkout trusted live shard harness
1840+if: contains(matrix.profiles, inputs.release_test_profile)
1841+uses: actions/checkout@v6
1842+with:
1843+ref: ${{ github.sha }}
1844+fetch-depth: 1
1845+path: .release-harness
1846+1847+ - name: Setup Node environment
1848+if: contains(matrix.profiles, inputs.release_test_profile)
1849+uses: ./.github/actions/setup-node-env
1850+with:
1851+node-version: ${{ env.NODE_VERSION }}
1852+pnpm-version: ${{ env.PNPM_VERSION }}
1853+install-bun: "true"
1854+1855+ - name: Hydrate live auth/profile inputs
1856+if: contains(matrix.profiles, inputs.release_test_profile)
1857+run: bash scripts/ci-hydrate-live-auth.sh
1858+1859+ - name: Configure suite-specific env
1860+if: contains(matrix.profiles, inputs.release_test_profile)
1861+shell: bash
1862+run: |
1863+ set -euo pipefail
1864+ if [[ "${{ matrix.profile_env_only }}" == "true" ]]; then
1865+ echo "OPENCLAW_DOCKER_PROFILE_ENV_ONLY=1" >> "$GITHUB_ENV"
1866+ fi
1867+ case "${{ matrix.suite_id }}" in
1868+ live-cli-backend-docker)
1869+ echo "OPENCLAW_LIVE_CLI_BACKEND_MODEL=codex-cli/gpt-5.5" >> "$GITHUB_ENV"
1870+ # Keep the release-blocking CI lane on Codex API-key auth. The
1871+ # staged auth-file path remains supported for local maintainer
1872+ # reruns, but it can hang on stale subscription/session state in
1873+ # an otherwise healthy release run.
1874+ echo "OPENCLAW_LIVE_CLI_BACKEND_AUTH=api-key" >> "$GITHUB_ENV"
1875+ # Replace the staged config.toml with a minimal CI-safe config so
1876+ # the repo stays trusted for MCP/tool use without inheriting
1877+ # maintainer-local provider/profile overrides that do not exist
1878+ # inside CI.
1879+ # Codex's workspace-write sandbox relies on user namespaces that
1880+ # this Docker lane does not provide, so run Codex unsandboxed
1881+ # inside the already-isolated container to keep MCP cron/tool
1882+ # execution representative instead of failing on nested sandbox
1883+ # setup.
1884+ echo 'OPENCLAW_LIVE_CLI_BACKEND_ARGS=["exec","--json","--color","never","--sandbox","danger-full-access","--skip-git-repo-check"]' >> "$GITHUB_ENV"
1885+ echo 'OPENCLAW_LIVE_CLI_BACKEND_RESUME_ARGS=["exec","resume","{sessionId}","-c","sandbox_mode=\"danger-full-access\"","--skip-git-repo-check"]' >> "$GITHUB_ENV"
1886+ echo "OPENCLAW_LIVE_CLI_BACKEND_DEBUG=1" >> "$GITHUB_ENV"
1887+ echo "OPENCLAW_CLI_BACKEND_LOG_OUTPUT=1" >> "$GITHUB_ENV"
1888+ echo "OPENCLAW_TEST_CONSOLE=1" >> "$GITHUB_ENV"
1889+ echo "OPENCLAW_LIVE_CLI_BACKEND_USE_CI_SAFE_CODEX_CONFIG=1" >> "$GITHUB_ENV"
1890+ ;;
1891+ live-codex-harness-docker)
1892+ # Keep CI on the API-key path for now. The staged Codex auth secret
1893+ # is currently stale, but the wrapper still supports codex-auth for
1894+ # local maintainer reruns without changing Peter's flow.
1895+ echo "OPENCLAW_LIVE_CODEX_HARNESS_AUTH=api-key" >> "$GITHUB_ENV"
1896+ echo "OPENCLAW_LIVE_CODEX_HARNESS_DEBUG=1" >> "$GITHUB_ENV"
1897+ echo "OPENCLAW_CLI_BACKEND_LOG_OUTPUT=1" >> "$GITHUB_ENV"
1898+ echo "OPENCLAW_TEST_CONSOLE=1" >> "$GITHUB_ENV"
1899+ ;;
1900+ live-acp-bind-docker)
1901+ if [[ -n "${GEMINI_API_KEY:-}" || -n "${GOOGLE_API_KEY:-}" ]]; then
1902+ echo "OPENCLAW_LIVE_ACP_BIND_AGENTS=claude,codex,gemini" >> "$GITHUB_ENV"
1903+ else
1904+ # The hydrated Gemini settings file only selects Gemini CLI auth
1905+ # mode. CI still needs a usable Gemini or Google API key before
1906+ # ACP bind can initialize a Gemini session.
1907+ echo "OPENCLAW_LIVE_ACP_BIND_AGENTS=claude,codex" >> "$GITHUB_ENV"
1908+ fi
1909+ ;;
1910+ esac
1911+1912+ - name: Run ${{ matrix.label }}
1913+if: contains(matrix.profiles, inputs.release_test_profile)
1914+run: ${{ matrix.command }}
1915+1916+validate_live_docker_provider_suites:
1917+name: Docker live suites (${{ matrix.label }})
1918+needs: [validate_selected_ref, prepare_live_test_image]
1919+if: inputs.include_live_suites && !inputs.live_models_only
1920+runs-on: blacksmith-32vcpu-ubuntu-2404
1921+timeout-minutes: ${{ matrix.timeout_minutes }}
1922+strategy:
1923+fail-fast: false
1924+matrix:
1925+include:
16911926 - suite_id: live-gateway-docker
16921927label: Docker live gateway
16931928command: OPENCLAW_LIVE_DOCKER_REPO_ROOT="$GITHUB_WORKSPACE" bash .release-harness/scripts/test-live-gateway-models-docker.sh
@@ -1758,6 +1993,8 @@ jobs:
17581993OPENCLAW_CLAUDE_SETTINGS_LOCAL_JSON: ${{ secrets.OPENCLAW_CLAUDE_SETTINGS_LOCAL_JSON }}
17591994OPENCLAW_GEMINI_SETTINGS_JSON: ${{ secrets.OPENCLAW_GEMINI_SETTINGS_JSON }}
17601995FIREWORKS_API_KEY: ${{ secrets.FIREWORKS_API_KEY }}
1996+OPENCLAW_LIVE_IMAGE: ${{ needs.prepare_live_test_image.outputs.live_image }}
1997+OPENCLAW_SKIP_DOCKER_BUILD: "1"
17611998OPENCLAW_LIVE_VIDEO_GENERATION_SKIP_PROVIDERS: ""
17621999OPENCLAW_LIVE_VYDRA_VIDEO: "1"
17632000OPENCLAW_VITEST_MAX_WORKERS: "2"
@@ -1789,6 +2026,14 @@ jobs:
17892026if: contains(matrix.profiles, inputs.release_test_profile)
17902027run: bash scripts/ci-hydrate-live-auth.sh
179120282029+ - name: Log in to GHCR
2030+if: contains(matrix.profiles, inputs.release_test_profile)
2031+uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 # v4
2032+with:
2033+registry: ghcr.io
2034+username: ${{ github.actor }}
2035+password: ${{ github.token }}
2036+17922037 - name: Configure suite-specific env
17932038if: contains(matrix.profiles, inputs.release_test_profile)
17942039shell: bash
@@ -1800,20 +2045,7 @@ jobs:
18002045 case "${{ matrix.suite_id }}" in
18012046 live-cli-backend-docker)
18022047 echo "OPENCLAW_LIVE_CLI_BACKEND_MODEL=codex-cli/gpt-5.5" >> "$GITHUB_ENV"
1803- # Keep the release-blocking CI lane on Codex API-key auth. The
1804- # staged auth-file path remains supported for local maintainer
1805- # reruns, but it can hang on stale subscription/session state in
1806- # an otherwise healthy release run.
18072048 echo "OPENCLAW_LIVE_CLI_BACKEND_AUTH=api-key" >> "$GITHUB_ENV"
1808- # Replace the staged config.toml with a minimal CI-safe config so
1809- # the repo stays trusted for MCP/tool use without inheriting
1810- # maintainer-local provider/profile overrides that do not exist
1811- # inside CI.
1812- # Codex's workspace-write sandbox relies on user namespaces that
1813- # this Docker lane does not provide, so run Codex unsandboxed
1814- # inside the already-isolated container to keep MCP cron/tool
1815- # execution representative instead of failing on nested sandbox
1816- # setup.
18172049 echo 'OPENCLAW_LIVE_CLI_BACKEND_ARGS=["exec","--json","--color","never","--sandbox","danger-full-access","--skip-git-repo-check"]' >> "$GITHUB_ENV"
18182050 echo 'OPENCLAW_LIVE_CLI_BACKEND_RESUME_ARGS=["exec","resume","{sessionId}","-c","sandbox_mode=\"danger-full-access\"","--skip-git-repo-check"]' >> "$GITHUB_ENV"
18192051 echo "OPENCLAW_LIVE_CLI_BACKEND_DEBUG=1" >> "$GITHUB_ENV"
@@ -1822,9 +2054,6 @@ jobs:
18222054 echo "OPENCLAW_LIVE_CLI_BACKEND_USE_CI_SAFE_CODEX_CONFIG=1" >> "$GITHUB_ENV"
18232055 ;;
18242056 live-codex-harness-docker)
1825- # Keep CI on the API-key path for now. The staged Codex auth secret
1826- # is currently stale, but the wrapper still supports codex-auth for
1827- # local maintainer reruns without changing Peter's flow.
18282057 echo "OPENCLAW_LIVE_CODEX_HARNESS_AUTH=api-key" >> "$GITHUB_ENV"
18292058 echo "OPENCLAW_LIVE_CODEX_HARNESS_DEBUG=1" >> "$GITHUB_ENV"
18302059 echo "OPENCLAW_CLI_BACKEND_LOG_OUTPUT=1" >> "$GITHUB_ENV"
@@ -1834,9 +2063,6 @@ jobs:
18342063 if [[ -n "${GEMINI_API_KEY:-}" || -n "${GOOGLE_API_KEY:-}" ]]; then
18352064 echo "OPENCLAW_LIVE_ACP_BIND_AGENTS=claude,codex,gemini" >> "$GITHUB_ENV"
18362065 else
1837- # The hydrated Gemini settings file only selects Gemini CLI auth
1838- # mode. CI still needs a usable Gemini or Google API key before
1839- # ACP bind can initialize a Gemini session.
18402066 echo "OPENCLAW_LIVE_ACP_BIND_AGENTS=claude,codex" >> "$GITHUB_ENV"
18412067 fi
18422068 ;;
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。