diff --git a/.github/workflows/openclaw-release-checks.yml b/.github/workflows/openclaw-release-checks.yml index 9e977168900..3f3c7c33975 100644 --- a/.github/workflows/openclaw-release-checks.yml +++ b/.github/workflows/openclaw-release-checks.yml @@ -656,6 +656,7 @@ jobs: shell: bash env: OPENCLAW_QA_REDACT_PUBLIC_METADATA: "1" + OPENCLAW_QA_MATRIX_CANARY_TIMEOUT_MS: "90000" OPENCLAW_QA_MATRIX_NO_REPLY_WINDOW_MS: "3000" run: | set -euo pipefail diff --git a/docs/concepts/qa-matrix.md b/docs/concepts/qa-matrix.md index 3e323e333cd..add045f4307 100644 --- a/docs/concepts/qa-matrix.md +++ b/docs/concepts/qa-matrix.md @@ -99,6 +99,7 @@ Pass `--scenario ` (repeatable) to run a hand-picked set; combine with `--pr | Variable | Default | Effect | | --------------------------------------- | ----------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `OPENCLAW_QA_MATRIX_TIMEOUT_MS` | `1800000` (30 min) | Hard upper bound on the entire run. | +| `OPENCLAW_QA_MATRIX_CANARY_TIMEOUT_MS` | `45000` | Bound for the initial canary reply. Release CI raises this on shared runners so a slow first gateway turn does not fail before scenario coverage starts. | | `OPENCLAW_QA_MATRIX_NO_REPLY_WINDOW_MS` | `8000` | Quiet window for negative no-reply assertions. Clamped to `≤` the run timeout. | | `OPENCLAW_QA_MATRIX_CLEANUP_TIMEOUT_MS` | `90000` | Bound for Docker teardown. Failure surfaces include the recovery `docker compose ... down --remove-orphans` command. | | `OPENCLAW_QA_MATRIX_TUWUNEL_IMAGE` | `ghcr.io/matrix-construct/tuwunel:v1.5.1` | Override the homeserver image when validating against a different Tuwunel version. | diff --git a/extensions/qa-matrix/src/runners/contract/runtime.ts b/extensions/qa-matrix/src/runners/contract/runtime.ts index 2d500124348..3427861468f 100644 --- a/extensions/qa-matrix/src/runners/contract/runtime.ts +++ b/extensions/qa-matrix/src/runners/contract/runtime.ts @@ -943,9 +943,8 @@ export async function runMatrixQaLive(params: { } finally { if (gatewayHarness) { try { - const shouldPreserveGatewayDebugArtifacts = scenarioResults.some( - (scenario) => scenario?.status === "fail", - ); + const shouldPreserveGatewayDebugArtifacts = + scenarioResults.some((scenario) => scenario?.status === "fail") || canaryFailed; preservedGatewayDebugDirPath = shouldPreserveGatewayDebugArtifacts ? path.join(outputDir, "gateway-debug") : undefined; diff --git a/src/commands/doctor.runs-legacy-state-migrations-yes-mode-without.e2e.test.ts b/src/commands/doctor.runs-legacy-state-migrations-yes-mode-without.e2e.test.ts index e8d5173dd26..6ea4658bf4f 100644 --- a/src/commands/doctor.runs-legacy-state-migrations-yes-mode-without.e2e.test.ts +++ b/src/commands/doctor.runs-legacy-state-migrations-yes-mode-without.e2e.test.ts @@ -112,7 +112,19 @@ describe("doctor command", () => { }, ]); - await doctorCommand(createDoctorRuntime(), { yes: true }); + const previousConfigWriteSupport = + process.env.OPENCLAW_UPDATE_PARENT_SUPPORTS_DOCTOR_CONFIG_WRITE; + process.env.OPENCLAW_UPDATE_PARENT_SUPPORTS_DOCTOR_CONFIG_WRITE = "1"; + try { + await doctorCommand(createDoctorRuntime(), { yes: true }); + } finally { + if (previousConfigWriteSupport === undefined) { + delete process.env.OPENCLAW_UPDATE_PARENT_SUPPORTS_DOCTOR_CONFIG_WRITE; + } else { + process.env.OPENCLAW_UPDATE_PARENT_SUPPORTS_DOCTOR_CONFIG_WRITE = + previousConfigWriteSupport; + } + } const written = writeConfigFile.mock.calls.at(-1)?.[0] as Record; const profiles = (written.auth as { profiles: Record }).profiles;