test(release): support convex npm telegram credentials

This commit is contained in:
Ayaan Zaidi
2026-04-24 10:49:26 +05:30
parent b7fba2100f
commit bd1b8448a5
5 changed files with 110 additions and 11 deletions

View File

@@ -112,7 +112,13 @@ runs the same lanes before release approval.
live Telegram QA lane with that installed package as the SUT Gateway.
- Defaults to `OPENCLAW_NPM_TELEGRAM_PACKAGE_SPEC=openclaw@beta`.
- Uses the same Telegram env credentials or Convex credential source as
`pnpm openclaw qa telegram`.
`pnpm openclaw qa telegram`. For CI/release automation, set
`OPENCLAW_NPM_TELEGRAM_CREDENTIAL_SOURCE=convex` plus
`OPENCLAW_QA_CONVEX_SITE_URL` and the role secret. If
`OPENCLAW_QA_CONVEX_SITE_URL` and a Convex role secret are present in CI,
the Docker wrapper selects Convex automatically.
- `OPENCLAW_NPM_TELEGRAM_CREDENTIAL_ROLE=ci|maintainer` overrides the shared
`OPENCLAW_QA_CREDENTIAL_ROLE` for this lane only.
- `pnpm test:docker:bundled-channel-deps`
- Packs and installs the current OpenClaw build in Docker, starts the Gateway
with OpenAI configured, then enables bundled channel/plugins via config

View File

@@ -88,9 +88,11 @@ OpenClaw has three public release lanes:
`node --import tsx scripts/openclaw-npm-postpublish-verify.ts YYYY.M.D`
(or the matching beta/correction version) to verify the published registry
install path in a fresh temp prefix
- After a beta publish, run `OPENCLAW_NPM_TELEGRAM_PACKAGE_SPEC=openclaw@YYYY.M.D-beta.N pnpm test:docker:npm-telegram-live`
- After a beta publish, run `OPENCLAW_NPM_TELEGRAM_PACKAGE_SPEC=openclaw@YYYY.M.D-beta.N OPENCLAW_NPM_TELEGRAM_CREDENTIAL_SOURCE=convex OPENCLAW_NPM_TELEGRAM_CREDENTIAL_ROLE=ci pnpm test:docker:npm-telegram-live`
to verify installed-package onboarding, Telegram setup, and real Telegram E2E
against the published npm package.
against the published npm package using the shared leased Telegram credential
pool. Local maintainer one-offs may omit the Convex vars and pass the three
`OPENCLAW_QA_TELEGRAM_*` env credentials directly.
- Maintainer release automation now uses preflight-then-promote:
- real npm publish must pass a successful npm `preflight_run_id`
- the real npm publish must be dispatched from the same `main` or

View File

@@ -9,6 +9,32 @@ DOCKER_TARGET="${OPENCLAW_NPM_TELEGRAM_DOCKER_TARGET:-build}"
PACKAGE_SPEC="${OPENCLAW_NPM_TELEGRAM_PACKAGE_SPEC:-openclaw@beta}"
OUTPUT_DIR="${OPENCLAW_NPM_TELEGRAM_OUTPUT_DIR:-.artifacts/qa-e2e/npm-telegram-live}"
resolve_credential_source() {
if [ -n "${OPENCLAW_NPM_TELEGRAM_CREDENTIAL_SOURCE:-}" ]; then
printf "%s" "$OPENCLAW_NPM_TELEGRAM_CREDENTIAL_SOURCE"
return 0
fi
if [ -n "${OPENCLAW_QA_CREDENTIAL_SOURCE:-}" ]; then
printf "%s" "$OPENCLAW_QA_CREDENTIAL_SOURCE"
return 0
fi
if [ -n "${CI:-}" ] && [ -n "${OPENCLAW_QA_CONVEX_SITE_URL:-}" ]; then
if [ -n "${OPENCLAW_QA_CONVEX_SECRET_CI:-}" ] || [ -n "${OPENCLAW_QA_CONVEX_SECRET_MAINTAINER:-}" ]; then
printf "convex"
fi
fi
}
resolve_credential_role() {
if [ -n "${OPENCLAW_NPM_TELEGRAM_CREDENTIAL_ROLE:-}" ]; then
printf "%s" "$OPENCLAW_NPM_TELEGRAM_CREDENTIAL_ROLE"
return 0
fi
if [ -n "${OPENCLAW_QA_CREDENTIAL_ROLE:-}" ]; then
printf "%s" "$OPENCLAW_QA_CREDENTIAL_ROLE"
fi
}
validate_openclaw_package_spec() {
local spec="$1"
if [[ "$spec" =~ ^openclaw@(beta|latest|[0-9]{4}\.[1-9][0-9]*\.[1-9][0-9]*(-[1-9][0-9]*|-beta\.[1-9][0-9]*)?)$ ]]; then
@@ -24,6 +50,8 @@ docker_e2e_build_or_reuse "$IMAGE_NAME" npm-telegram-live "$ROOT_DIR/scripts/e2e
mkdir -p "$ROOT_DIR/.artifacts/qa-e2e"
run_log="$(mktemp "${TMPDIR:-/tmp}/openclaw-npm-telegram-live.XXXXXX")"
credential_source="$(resolve_credential_source)"
credential_role="$(resolve_credential_role)"
docker_env=(
-e COREPACK_ENABLE_DOWNLOAD_PROMPT=0
@@ -39,6 +67,13 @@ forward_env_if_set() {
fi
}
if [ -n "$credential_source" ]; then
docker_env+=(-e OPENCLAW_QA_CREDENTIAL_SOURCE="$credential_source")
fi
if [ -n "$credential_role" ]; then
docker_env+=(-e OPENCLAW_QA_CREDENTIAL_ROLE="$credential_role")
fi
for key in \
OPENAI_API_KEY \
ANTHROPIC_API_KEY \
@@ -50,8 +85,6 @@ for key in \
OPENCLAW_QA_TELEGRAM_GROUP_ID \
OPENCLAW_QA_TELEGRAM_DRIVER_BOT_TOKEN \
OPENCLAW_QA_TELEGRAM_SUT_BOT_TOKEN \
OPENCLAW_QA_CREDENTIAL_SOURCE \
OPENCLAW_QA_CREDENTIAL_ROLE \
OPENCLAW_QA_CONVEX_SITE_URL \
OPENCLAW_QA_CONVEX_SECRET_CI \
OPENCLAW_QA_CONVEX_SECRET_MAINTAINER \

View File

@@ -2,6 +2,7 @@
import fs from "node:fs/promises";
import path from "node:path";
import { pathToFileURL } from "node:url";
import { runTelegramQaLive } from "../../extensions/qa-lab/src/live-transports/telegram/telegram-live.runtime.ts";
import { formatErrorMessage } from "../../src/infra/errors.ts";
@@ -17,6 +18,14 @@ function splitCsv(value: string | undefined) {
.filter((entry) => entry.length > 0);
}
function resolveCredentialSource(env: NodeJS.ProcessEnv) {
return env.OPENCLAW_NPM_TELEGRAM_CREDENTIAL_SOURCE ?? env.OPENCLAW_QA_CREDENTIAL_SOURCE;
}
function resolveCredentialRole(env: NodeJS.ProcessEnv) {
return env.OPENCLAW_NPM_TELEGRAM_CREDENTIAL_ROLE ?? env.OPENCLAW_QA_CREDENTIAL_ROLE;
}
async function resolveTrustedOpenClawCommand(rawCommand: string) {
if (!path.isAbsolute(rawCommand)) {
throw new Error("OPENCLAW_NPM_TELEGRAM_SUT_COMMAND must be an absolute path.");
@@ -63,8 +72,8 @@ async function main() {
fastMode: parseBoolean(process.env.OPENCLAW_NPM_TELEGRAM_FAST),
scenarioIds: splitCsv(process.env.OPENCLAW_NPM_TELEGRAM_SCENARIOS),
sutAccountId: process.env.OPENCLAW_NPM_TELEGRAM_SUT_ACCOUNT,
credentialSource: process.env.OPENCLAW_QA_CREDENTIAL_SOURCE,
credentialRole: process.env.OPENCLAW_QA_CREDENTIAL_ROLE,
credentialSource: resolveCredentialSource(process.env),
credentialRole: resolveCredentialRole(process.env),
});
process.stdout.write(`NPM Telegram QA report: ${result.reportPath}\n`);
@@ -78,7 +87,14 @@ async function main() {
}
}
main().catch((error) => {
process.stderr.write(`npm telegram live e2e failed: ${formatErrorMessage(error)}\n`);
process.exitCode = 1;
});
if (process.argv[1] && import.meta.url === pathToFileURL(process.argv[1]).href) {
main().catch((error) => {
process.stderr.write(`npm telegram live e2e failed: ${formatErrorMessage(error)}\n`);
process.exitCode = 1;
});
}
export const __testing = {
resolveCredentialRole,
resolveCredentialSource,
};

View File

@@ -0,0 +1,42 @@
import { readFileSync } from "node:fs";
import { describe, expect, it } from "vitest";
import { __testing } from "../../scripts/e2e/npm-telegram-live-runner.ts";
const DOCKER_SCRIPT_PATH = "scripts/e2e/npm-telegram-live-docker.sh";
describe("npm Telegram live Docker E2E", () => {
it("supports npm-specific Convex credential aliases", () => {
const script = readFileSync(DOCKER_SCRIPT_PATH, "utf8");
expect(script).toContain("OPENCLAW_NPM_TELEGRAM_CREDENTIAL_SOURCE");
expect(script).toContain("OPENCLAW_NPM_TELEGRAM_CREDENTIAL_ROLE");
expect(script).toContain('docker_env+=(-e OPENCLAW_QA_CREDENTIAL_SOURCE="$credential_source")');
expect(script).toContain('docker_env+=(-e OPENCLAW_QA_CREDENTIAL_ROLE="$credential_role")');
});
it("defaults CI runs to Convex when broker credentials are present", () => {
const script = readFileSync(DOCKER_SCRIPT_PATH, "utf8");
expect(script).toContain(
'if [ -n "${CI:-}" ] && [ -n "${OPENCLAW_QA_CONVEX_SITE_URL:-}" ]; then',
);
expect(script).toContain("OPENCLAW_QA_CONVEX_SECRET_CI");
expect(script).toContain("OPENCLAW_QA_CONVEX_SECRET_MAINTAINER");
expect(script).toContain('printf "convex"');
});
it("lets npm-specific credential aliases override shared QA env", () => {
expect(
__testing.resolveCredentialSource({
OPENCLAW_NPM_TELEGRAM_CREDENTIAL_SOURCE: "convex",
OPENCLAW_QA_CREDENTIAL_SOURCE: "env",
}),
).toBe("convex");
expect(
__testing.resolveCredentialRole({
OPENCLAW_NPM_TELEGRAM_CREDENTIAL_ROLE: "ci",
OPENCLAW_QA_CREDENTIAL_ROLE: "maintainer",
}),
).toBe("ci");
});
});