From 9755c8a05fecfcd89637b4141d72fb8642255124 Mon Sep 17 00:00:00 2001 From: Ayaan Zaidi Date: Fri, 24 Apr 2026 09:07:54 +0530 Subject: [PATCH] test(release): add npm telegram live smoke --- docs/help/testing.md | 7 ++ docs/reference/RELEASING.md | 3 + package.json | 1 + scripts/e2e/npm-telegram-live-docker.sh | 95 +++++++++++++++++++++++++ scripts/e2e/npm-telegram-live-runner.ts | 58 +++++++++++++++ 5 files changed, 164 insertions(+) create mode 100755 scripts/e2e/npm-telegram-live-docker.sh create mode 100644 scripts/e2e/npm-telegram-live-runner.ts diff --git a/docs/help/testing.md b/docs/help/testing.md index c103d0d2fff..7a8dda01b1b 100644 --- a/docs/help/testing.md +++ b/docs/help/testing.md @@ -106,6 +106,13 @@ runs the same lanes before release approval. endpoint. - Use `OPENCLAW_NPM_ONBOARD_CHANNEL=discord` to run the same packaged-install lane with Discord. +- `pnpm test:docker:npm-telegram-live` + - Installs a published OpenClaw package in Docker, runs installed-package + onboarding, configures Telegram through the installed CLI, then reuses the + 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 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 diff --git a/docs/reference/RELEASING.md b/docs/reference/RELEASING.md index 829b96795c8..3df429a052f 100644 --- a/docs/reference/RELEASING.md +++ b/docs/reference/RELEASING.md @@ -88,6 +88,9 @@ 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` + to verify installed-package onboarding, Telegram setup, and real Telegram E2E + against the published npm package. - 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 diff --git a/package.json b/package.json index b9ee57cc4ba..47dde53f6d5 100644 --- a/package.json +++ b/package.json @@ -1484,6 +1484,7 @@ "test:docker:live-models:gemini": "OPENCLAW_LIVE_PROVIDERS=google-gemini-cli OPENCLAW_LIVE_MODELS=google-gemini-cli/gemini-3.1-pro-preview bash scripts/test-live-models-docker.sh", "test:docker:mcp-channels": "bash scripts/e2e/mcp-channels-docker.sh", "test:docker:npm-onboard-channel-agent": "bash scripts/e2e/npm-onboard-channel-agent-docker.sh", + "test:docker:npm-telegram-live": "bash scripts/e2e/npm-telegram-live-docker.sh", "test:docker:onboard": "bash scripts/e2e/onboard-docker.sh", "test:docker:openai-image-auth": "bash scripts/e2e/openai-image-auth-docker.sh", "test:docker:openai-web-search-minimal": "bash scripts/e2e/openai-web-search-minimal-docker.sh", diff --git a/scripts/e2e/npm-telegram-live-docker.sh b/scripts/e2e/npm-telegram-live-docker.sh new file mode 100755 index 00000000000..ae83146be42 --- /dev/null +++ b/scripts/e2e/npm-telegram-live-docker.sh @@ -0,0 +1,95 @@ +#!/usr/bin/env bash +set -euo pipefail + +ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)" +source "$ROOT_DIR/scripts/lib/docker-e2e-image.sh" + +IMAGE_NAME="$(docker_e2e_resolve_image "openclaw-npm-telegram-live-e2e" OPENCLAW_NPM_TELEGRAM_LIVE_E2E_IMAGE)" +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}" + +docker_e2e_build_or_reuse "$IMAGE_NAME" npm-telegram-live "$ROOT_DIR/scripts/e2e/Dockerfile" "$ROOT_DIR" "$DOCKER_TARGET" + +mkdir -p "$ROOT_DIR/.artifacts/qa-e2e" +run_log="$(mktemp "${TMPDIR:-/tmp}/openclaw-npm-telegram-live.XXXXXX")" + +docker_env=( + -e COREPACK_ENABLE_DOWNLOAD_PROMPT=0 + -e OPENCLAW_NPM_TELEGRAM_PACKAGE_SPEC="$PACKAGE_SPEC" + -e OPENCLAW_NPM_TELEGRAM_OUTPUT_DIR="$OUTPUT_DIR" + -e OPENCLAW_NPM_TELEGRAM_FAST="${OPENCLAW_NPM_TELEGRAM_FAST:-1}" +) + +forward_env_if_set() { + local key="$1" + if [ -n "${!key:-}" ]; then + docker_env+=(-e "$key=${!key}") + fi +} + +for key in \ + OPENAI_API_KEY \ + ANTHROPIC_API_KEY \ + GOOGLE_API_KEY \ + OPENCLAW_LIVE_OPENAI_KEY \ + OPENCLAW_LIVE_ANTHROPIC_KEY \ + OPENCLAW_LIVE_GEMINI_KEY \ + 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 \ + OPENCLAW_QA_CREDENTIAL_LEASE_TTL_MS \ + OPENCLAW_QA_CREDENTIAL_HEARTBEAT_INTERVAL_MS \ + OPENCLAW_QA_CREDENTIAL_ACQUIRE_TIMEOUT_MS \ + OPENCLAW_QA_CREDENTIAL_HTTP_TIMEOUT_MS \ + OPENCLAW_QA_CONVEX_ENDPOINT_PREFIX \ + OPENCLAW_QA_CREDENTIAL_OWNER_ID \ + OPENCLAW_QA_ALLOW_INSECURE_HTTP \ + OPENCLAW_QA_REDACT_PUBLIC_METADATA \ + OPENCLAW_QA_TELEGRAM_CAPTURE_CONTENT \ + OPENCLAW_QA_SUITE_PROGRESS \ + OPENCLAW_NPM_TELEGRAM_PROVIDER_MODE \ + OPENCLAW_NPM_TELEGRAM_MODEL \ + OPENCLAW_NPM_TELEGRAM_ALT_MODEL \ + OPENCLAW_NPM_TELEGRAM_SCENARIOS \ + OPENCLAW_NPM_TELEGRAM_SUT_ACCOUNT \ + OPENCLAW_NPM_TELEGRAM_ALLOW_FAILURES; do + forward_env_if_set "$key" +done + +echo "Running published npm Telegram live Docker E2E ($PACKAGE_SPEC)..." +if ! docker run --rm \ + "${docker_env[@]}" \ + -v "$ROOT_DIR/.artifacts:/app/.artifacts" \ + -i "$IMAGE_NAME" bash -s >"$run_log" 2>&1 <<'EOF' +set -euo pipefail + +export HOME="$(mktemp -d "/tmp/openclaw-npm-telegram-live.XXXXXX")" +export NPM_CONFIG_PREFIX="$HOME/.npm-global" +export PATH="$NPM_CONFIG_PREFIX/bin:$PATH" +export OPENCLAW_NPM_TELEGRAM_REPO_ROOT="/app" + +package_spec="${OPENCLAW_NPM_TELEGRAM_PACKAGE_SPEC:?missing OPENCLAW_NPM_TELEGRAM_PACKAGE_SPEC}" +echo "Installing ${package_spec}..." +npm install -g "$package_spec" --no-fund --no-audit + +command -v openclaw +openclaw --version + +export OPENCLAW_NPM_TELEGRAM_SUT_COMMAND="$(command -v openclaw)" +node --import tsx scripts/e2e/npm-telegram-live-runner.ts +EOF +then + cat "$run_log" + rm -f "$run_log" + exit 1 +fi + +cat "$run_log" +rm -f "$run_log" +echo "published npm Telegram live Docker E2E passed ($PACKAGE_SPEC)" diff --git a/scripts/e2e/npm-telegram-live-runner.ts b/scripts/e2e/npm-telegram-live-runner.ts new file mode 100644 index 00000000000..30dc9db7ed2 --- /dev/null +++ b/scripts/e2e/npm-telegram-live-runner.ts @@ -0,0 +1,58 @@ +#!/usr/bin/env -S node --import tsx + +import path from "node:path"; +import { runTelegramQaLive } from "../../extensions/qa-lab/src/live-transports/telegram/telegram-live.runtime.ts"; +import { formatErrorMessage } from "../../src/infra/errors.ts"; + +function parseBoolean(value: string | undefined) { + const normalized = value?.trim().toLowerCase(); + return normalized === "1" || normalized === "true" || normalized === "yes"; +} + +function splitCsv(value: string | undefined) { + return (value ?? "") + .split(",") + .map((entry) => entry.trim()) + .filter((entry) => entry.length > 0); +} + +async function main() { + const sutOpenClawCommand = process.env.OPENCLAW_NPM_TELEGRAM_SUT_COMMAND?.trim(); + if (!sutOpenClawCommand) { + throw new Error("Missing OPENCLAW_NPM_TELEGRAM_SUT_COMMAND."); + } + + const repoRoot = path.resolve(process.env.OPENCLAW_NPM_TELEGRAM_REPO_ROOT ?? process.cwd()); + const outputDir = + process.env.OPENCLAW_NPM_TELEGRAM_OUTPUT_DIR?.trim() || + path.join(repoRoot, ".artifacts", "qa-e2e", `npm-telegram-live-${Date.now().toString(36)}`); + const result = await runTelegramQaLive({ + repoRoot, + outputDir, + sutOpenClawCommand, + preflightInstalledOnboarding: true, + providerMode: process.env.OPENCLAW_NPM_TELEGRAM_PROVIDER_MODE, + primaryModel: process.env.OPENCLAW_NPM_TELEGRAM_MODEL, + alternateModel: process.env.OPENCLAW_NPM_TELEGRAM_ALT_MODEL, + 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, + }); + + process.stdout.write(`NPM Telegram QA report: ${result.reportPath}\n`); + process.stdout.write(`NPM Telegram QA summary: ${result.summaryPath}\n`); + process.stdout.write(`NPM Telegram QA observed messages: ${result.observedMessagesPath}\n`); + if ( + !parseBoolean(process.env.OPENCLAW_NPM_TELEGRAM_ALLOW_FAILURES) && + result.scenarios.some((scenario) => scenario.status === "fail") + ) { + process.exitCode = 1; + } +} + +main().catch((error) => { + process.stderr.write(`npm telegram live e2e failed: ${formatErrorMessage(error)}\n`); + process.exitCode = 1; +});