Skip to content

Commit 64533ed

Browse files
committed
ci(release): allow slower qa live canaries
1 parent 7488946 commit 64533ed

5 files changed

Lines changed: 75 additions & 3 deletions

File tree

.github/workflows/openclaw-release-checks.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -669,6 +669,7 @@ jobs:
669669
env:
670670
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
671671
OPENCLAW_QA_REDACT_PUBLIC_METADATA: "1"
672+
OPENCLAW_QA_MATRIX_CANARY_TIMEOUT_MS: "90000"
672673
OPENCLAW_QA_MATRIX_NO_REPLY_WINDOW_MS: "3000"
673674
run: |
674675
set -euo pipefail
@@ -761,6 +762,7 @@ jobs:
761762
OPENCLAW_QA_CONVEX_SECRET_CI: ${{ secrets.OPENCLAW_QA_CONVEX_SECRET_CI }}
762763
OPENCLAW_QA_REDACT_PUBLIC_METADATA: "1"
763764
OPENCLAW_QA_TELEGRAM_CAPTURE_CONTENT: "1"
765+
OPENCLAW_QA_TELEGRAM_CANARY_TIMEOUT_MS: "90000"
764766
run: |
765767
set -euo pipefail
766768

extensions/qa-lab/src/live-transports/telegram/telegram-live.runtime.test.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,20 @@ describe("telegram live qa runtime", () => {
100100
).toBe(true);
101101
});
102102

103+
it("normalizes the Telegram QA canary timeout env", () => {
104+
expect(__testing.resolveTelegramQaCanaryTimeoutMs({})).toBe(30_000);
105+
expect(
106+
__testing.resolveTelegramQaCanaryTimeoutMs({
107+
OPENCLAW_QA_TELEGRAM_CANARY_TIMEOUT_MS: "90000",
108+
}),
109+
).toBe(90_000);
110+
expect(
111+
__testing.resolveTelegramQaCanaryTimeoutMs({
112+
OPENCLAW_QA_TELEGRAM_CANARY_TIMEOUT_MS: "nope",
113+
}),
114+
).toBe(30_000);
115+
});
116+
103117
it("sanitizes and truncates Telegram live progress details", () => {
104118
expect(__testing.sanitizeTelegramQaProgressValue("scenario\nid\tvalue")).toBe(
105119
"scenario id value",

extensions/qa-lab/src/live-transports/telegram/telegram-live.runtime.ts

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,8 @@ type TelegramObservedMessageArtifact = {
9999
mediaKinds: string[];
100100
};
101101

102+
const DEFAULT_TELEGRAM_QA_CANARY_TIMEOUT_MS = 30_000;
103+
102104
type TelegramQaScenarioResult = {
103105
id: string;
104106
title: string;
@@ -350,6 +352,30 @@ function shouldLogTelegramQaLiveProgress(env: NodeJS.ProcessEnv = process.env) {
350352
return parseTelegramQaProgressBooleanEnv(env.CI) === true;
351353
}
352354

355+
function parsePositiveTelegramQaEnvMs(env: NodeJS.ProcessEnv, name: string, fallbackMs: number) {
356+
const raw = env[name];
357+
if (raw === undefined) {
358+
return fallbackMs;
359+
}
360+
const parsed = Number(raw);
361+
if (!Number.isFinite(parsed) || parsed < 1) {
362+
return fallbackMs;
363+
}
364+
return Math.floor(parsed);
365+
}
366+
367+
function resolveTelegramQaCanaryTimeoutMs(env: NodeJS.ProcessEnv = process.env) {
368+
return parsePositiveTelegramQaEnvMs(
369+
env,
370+
"OPENCLAW_QA_TELEGRAM_CANARY_TIMEOUT_MS",
371+
DEFAULT_TELEGRAM_QA_CANARY_TIMEOUT_MS,
372+
);
373+
}
374+
375+
function formatTelegramQaTimeoutSeconds(timeoutMs: number) {
376+
return `${Math.round(timeoutMs / 1_000)}s`;
377+
}
378+
353379
function writeTelegramQaProgress(enabled: boolean, message: string) {
354380
if (!enabled) {
355381
return;
@@ -862,6 +888,7 @@ async function runCanary(params: {
862888
groupId: string;
863889
sutUsername: string;
864890
sutBotId: number;
891+
timeoutMs: number;
865892
observedMessages: TelegramObservedMessage[];
866893
}) {
867894
const offset = await flushTelegramUpdates(params.driverToken);
@@ -880,7 +907,7 @@ async function runCanary(params: {
880907
sutObserved = await waitForObservedMessage({
881908
token: params.driverToken,
882909
initialOffset: offset,
883-
timeoutMs: 30_000,
910+
timeoutMs: params.timeoutMs,
884911
observedMessages: params.observedMessages,
885912
observationScenarioId: "telegram-canary",
886913
observationScenarioTitle: "Telegram canary",
@@ -921,7 +948,7 @@ async function runCanary(params: {
921948
}
922949
throw new TelegramQaCanaryError(
923950
"sut_reply_timeout",
924-
"SUT bot did not send any group reply after the canary command within 30s.",
951+
`SUT bot did not send any group reply after the canary command within ${formatTelegramQaTimeoutSeconds(params.timeoutMs)}.`,
925952
{
926953
groupId: params.groupId,
927954
sutBotId: params.sutBotId,
@@ -1208,6 +1235,7 @@ export async function runTelegramQaLive(params: {
12081235
groupId: runtimeEnv.groupId,
12091236
sutUsername,
12101237
sutBotId: sutIdentity.id,
1238+
timeoutMs: resolveTelegramQaCanaryTimeoutMs(),
12111239
observedMessages,
12121240
});
12131241
scenarioResults.push({
@@ -1481,6 +1509,7 @@ export const __testing = {
14811509
normalizeTelegramObservedMessage,
14821510
parseTelegramQaProgressBooleanEnv,
14831511
parseTelegramQaCredentialPayload,
1512+
resolveTelegramQaCanaryTimeoutMs,
14841513
resolveTelegramQaRuntimeEnv,
14851514
sanitizeTelegramQaProgressValue,
14861515
shouldLogTelegramQaLiveProgress,

extensions/qa-matrix/src/runners/contract/runtime.test.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,24 @@ describe("matrix live qa runtime", () => {
106106
}
107107
});
108108

109+
it("normalizes the Matrix QA canary timeout env", () => {
110+
const previous = process.env.OPENCLAW_QA_MATRIX_CANARY_TIMEOUT_MS;
111+
try {
112+
delete process.env.OPENCLAW_QA_MATRIX_CANARY_TIMEOUT_MS;
113+
expect(liveTesting.resolveMatrixQaCanaryTimeoutMs()).toBe(45_000);
114+
process.env.OPENCLAW_QA_MATRIX_CANARY_TIMEOUT_MS = "90000";
115+
expect(liveTesting.resolveMatrixQaCanaryTimeoutMs()).toBe(90_000);
116+
process.env.OPENCLAW_QA_MATRIX_CANARY_TIMEOUT_MS = "nope";
117+
expect(liveTesting.resolveMatrixQaCanaryTimeoutMs()).toBe(45_000);
118+
} finally {
119+
if (previous === undefined) {
120+
delete process.env.OPENCLAW_QA_MATRIX_CANARY_TIMEOUT_MS;
121+
} else {
122+
process.env.OPENCLAW_QA_MATRIX_CANARY_TIMEOUT_MS = previous;
123+
}
124+
}
125+
});
126+
109127
it("injects a temporary Matrix account into the QA gateway config", () => {
110128
const baseCfg: OpenClawConfig = {
111129
plugins: {

extensions/qa-matrix/src/runners/contract/runtime.ts

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ type MatrixQaGatewayChild = {
5151

5252
const DEFAULT_MATRIX_QA_RUN_TIMEOUT_MS = 30 * 60_000;
5353
const DEFAULT_MATRIX_QA_CLEANUP_TIMEOUT_MS = 90_000;
54+
const DEFAULT_MATRIX_QA_CANARY_TIMEOUT_MS = 45_000;
5455

5556
type MatrixQaLiveLaneGatewayHarness = {
5657
gateway: MatrixQaGatewayChild;
@@ -192,6 +193,13 @@ function createMatrixQaRunDeadline() {
192193
};
193194
}
194195

196+
function resolveMatrixQaCanaryTimeoutMs() {
197+
return parsePositiveMatrixQaEnvMs(
198+
"OPENCLAW_QA_MATRIX_CANARY_TIMEOUT_MS",
199+
DEFAULT_MATRIX_QA_CANARY_TIMEOUT_MS,
200+
);
201+
}
202+
195203
function remainingMatrixQaRunMs(deadline: { deadlineMs: number }) {
196204
return Math.max(1, deadline.deadlineMs - Date.now());
197205
}
@@ -720,7 +728,7 @@ export async function runMatrixQaLive(params: {
720728
syncState,
721729
syncStreams,
722730
sutUserId: provisioning.sut.userId,
723-
timeoutMs: 45_000,
731+
timeoutMs: resolveMatrixQaCanaryTimeoutMs(),
724732
}),
725733
),
726734
);
@@ -1128,6 +1136,7 @@ export const __testing = {
11281136
findMatrixQaScenarios,
11291137
isMatrixAccountReady,
11301138
patchMatrixQaGatewayConfig,
1139+
resolveMatrixQaCanaryTimeoutMs,
11311140
resolveMatrixQaModels,
11321141
shouldWriteMatrixQaProgress,
11331142
summarizeMatrixQaConfigSnapshot,

0 commit comments

Comments
 (0)