fix(ci): stabilize full release validation

This commit is contained in:
Peter Steinberger
2026-04-28 23:54:38 +01:00
parent 490e6d6dc5
commit 955b4df093
14 changed files with 98 additions and 0 deletions

View File

@@ -246,6 +246,23 @@ jobs:
echo "- Target SHA: \`${TARGET_SHA}\`"
} >> "$GITHUB_STEP_SUMMARY"
cancel_same_sha_push_ci() {
local run_ids run_id
run_ids="$(
gh run list --workflow ci.yml --limit 100 --json databaseId,event,headSha,status \
--jq 'map(select(.event == "push" and .headSha == env.TARGET_SHA and (.status == "queued" or .status == "in_progress" or .status == "waiting" or .status == "pending"))) | .[].databaseId'
)"
if [[ -z "${run_ids// }" ]]; then
return 0
fi
while IFS= read -r run_id; do
[[ -n "${run_id// }" ]] || continue
echo "Cancelling same-SHA push CI run ${run_id}; Full Release Validation dispatches the full manual CI child for ${TARGET_SHA}."
gh run cancel "$run_id" || gh api -X POST "repos/${GITHUB_REPOSITORY}/actions/runs/${run_id}/force-cancel" || true
done <<< "$run_ids"
}
cancel_same_sha_push_ci
dispatch_and_wait ci.yml -f target_ref="$TARGET_SHA"
release_checks:

View File

@@ -1893,6 +1893,7 @@ jobs:
echo 'OPENCLAW_LIVE_CLI_BACKEND_RESUME_ARGS=["exec","resume","{sessionId}","-c","sandbox_mode=\"danger-full-access\"","--skip-git-repo-check"]' >> "$GITHUB_ENV"
echo "OPENCLAW_LIVE_CLI_BACKEND_DEBUG=1" >> "$GITHUB_ENV"
echo "OPENCLAW_CLI_BACKEND_LOG_OUTPUT=1" >> "$GITHUB_ENV"
echo "OPENCLAW_TEST_CONSOLE=1" >> "$GITHUB_ENV"
echo "OPENCLAW_LIVE_CLI_BACKEND_USE_CI_SAFE_CODEX_CONFIG=1" >> "$GITHUB_ENV"
;;
live-codex-harness-docker)
@@ -1900,6 +1901,9 @@ jobs:
# is currently stale, but the wrapper still supports codex-auth for
# local maintainer reruns without changing Peter's flow.
echo "OPENCLAW_LIVE_CODEX_HARNESS_AUTH=api-key" >> "$GITHUB_ENV"
echo "OPENCLAW_LIVE_CODEX_HARNESS_DEBUG=1" >> "$GITHUB_ENV"
echo "OPENCLAW_CLI_BACKEND_LOG_OUTPUT=1" >> "$GITHUB_ENV"
echo "OPENCLAW_TEST_CONSOLE=1" >> "$GITHUB_ENV"
;;
live-acp-bind-docker)
if [[ -n "${GEMINI_API_KEY:-}" || -n "${GOOGLE_API_KEY:-}" ]]; then

View File

@@ -55,6 +55,20 @@ const providerConfig = {
},
};
const RELEASE_SMOKE_PLUGIN_ALLOWLIST_BASE = [
"acpx",
"bonjour",
"browser",
"device-pair",
"memory-core",
"phone-control",
"talk-voice",
];
export function buildCrossOsReleaseSmokePluginAllowlist(providerMeta) {
return [...new Set([providerMeta.extensionId, ...RELEASE_SMOKE_PLUGIN_ALLOWLIST_BASE])];
}
const PACKAGE_DIST_INVENTORY_RELATIVE_PATH = "dist/postinstall-inventory.json";
const OMITTED_QA_EXTENSION_PREFIXES = [
"dist/extensions/qa-channel/",
@@ -1844,6 +1858,20 @@ async function runInstalledModelsSet(params) {
logPath: params.logPath,
timeoutMs: 2 * 60 * 1000,
});
await runInstalledCli({
cliPath: params.cliPath,
args: [
"config",
"set",
"plugins.allow",
JSON.stringify(buildCrossOsReleaseSmokePluginAllowlist(params.providerConfig)),
"--strict-json",
],
cwd: params.cwd,
env: params.env,
logPath: params.logPath,
timeoutMs: 2 * 60 * 1000,
});
await runInstalledCli({
cliPath: params.cliPath,
args: ["config", "set", "agents.defaults.skipBootstrap", "true", "--strict-json"],
@@ -2600,6 +2628,19 @@ async function runModelsSet(params) {
logPath: params.logPath,
timeoutMs: 2 * 60 * 1000,
});
await runOpenClaw({
lane: params.lane,
env: params.env,
args: [
"config",
"set",
"plugins.allow",
JSON.stringify(buildCrossOsReleaseSmokePluginAllowlist(params.providerConfig)),
"--strict-json",
],
logPath: params.logPath,
timeoutMs: 2 * 60 * 1000,
});
await runOpenClaw({
lane: params.lane,
env: params.env,

View File

@@ -451,6 +451,10 @@ export function createBundledRuntimeDependencyInstallEnv(env = process.env) {
return {
...createNestedNpmInstallEnv(env),
npm_config_dry_run: "false",
npm_config_fetch_retries: env.npm_config_fetch_retries ?? "5",
npm_config_fetch_retry_maxtimeout: env.npm_config_fetch_retry_maxtimeout ?? "120000",
npm_config_fetch_retry_mintimeout: env.npm_config_fetch_retry_mintimeout ?? "10000",
npm_config_fetch_timeout: env.npm_config_fetch_timeout ?? "300000",
npm_config_legacy_peer_deps: "true",
npm_config_package_lock: "false",
npm_config_save: "false",

View File

@@ -886,6 +886,10 @@ function runNpmInstall(params) {
CI: "1",
npm_config_audit: "false",
npm_config_dry_run: "false",
npm_config_fetch_retries: process.env.npm_config_fetch_retries ?? "5",
npm_config_fetch_retry_maxtimeout: process.env.npm_config_fetch_retry_maxtimeout ?? "120000",
npm_config_fetch_retry_mintimeout: process.env.npm_config_fetch_retry_mintimeout ?? "10000",
npm_config_fetch_timeout: process.env.npm_config_fetch_timeout ?? "300000",
npm_config_fund: "false",
npm_config_legacy_peer_deps: "true",
npm_config_loglevel: "error",

View File

@@ -471,6 +471,7 @@ DOCKER_RUN_ARGS=(docker run --rm -t \
-e OPENCLAW_LIVE_CLI_BACKEND=1 \
-e OPENCLAW_LIVE_CLI_BACKEND_DEBUG="${OPENCLAW_LIVE_CLI_BACKEND_DEBUG:-}" \
-e OPENCLAW_CLI_BACKEND_LOG_OUTPUT="${OPENCLAW_CLI_BACKEND_LOG_OUTPUT:-}" \
-e OPENCLAW_TEST_CONSOLE="${OPENCLAW_TEST_CONSOLE:-}" \
-e OPENCLAW_LIVE_CLI_BACKEND_MODEL="$CLI_MODEL" \
-e OPENCLAW_LIVE_CLI_BACKEND_COMMAND="${OPENCLAW_LIVE_CLI_BACKEND_COMMAND:-}" \
-e OPENCLAW_LIVE_CLI_BACKEND_ARGS="${OPENCLAW_LIVE_CLI_BACKEND_ARGS:-}" \

View File

@@ -257,6 +257,8 @@ DOCKER_RUN_ARGS=(docker run --rm -t \
-e OPENCLAW_LIVE_CODEX_HARNESS_SUBAGENT_ONLY="${OPENCLAW_LIVE_CODEX_HARNESS_SUBAGENT_ONLY:-}" \
-e OPENCLAW_LIVE_CODEX_HARNESS_SUBAGENT_PROBE="${OPENCLAW_LIVE_CODEX_HARNESS_SUBAGENT_PROBE:-1}" \
-e OPENCLAW_LIVE_CODEX_HARNESS_USE_CI_SAFE_CODEX_CONFIG="${OPENCLAW_LIVE_CODEX_HARNESS_USE_CI_SAFE_CODEX_CONFIG:-1}" \
-e OPENCLAW_CLI_BACKEND_LOG_OUTPUT="${OPENCLAW_CLI_BACKEND_LOG_OUTPUT:-}" \
-e OPENCLAW_TEST_CONSOLE="${OPENCLAW_TEST_CONSOLE:-}" \
-e OPENCLAW_LIVE_DOCKER_SCRIPTS_DIR="${DOCKER_TRUSTED_HARNESS_CONTAINER_DIR}/scripts" \
-e OPENCLAW_LIVE_DOCKER_TRUSTED_HARNESS_DIR="$DOCKER_TRUSTED_HARNESS_CONTAINER_DIR" \
-e OPENCLAW_LIVE_CODEX_TRUSTED_HARNESS_DIR="$DOCKER_TRUSTED_HARNESS_CONTAINER_DIR" \

View File

@@ -23,6 +23,10 @@ export function createNpmProjectInstallEnv(
return {
...nextEnv,
npm_config_dry_run: "false",
npm_config_fetch_retries: nextEnv.npm_config_fetch_retries ?? "5",
npm_config_fetch_retry_maxtimeout: nextEnv.npm_config_fetch_retry_maxtimeout ?? "120000",
npm_config_fetch_retry_mintimeout: nextEnv.npm_config_fetch_retry_mintimeout ?? "10000",
npm_config_fetch_timeout: nextEnv.npm_config_fetch_timeout ?? "300000",
npm_config_global: "false",
npm_config_location: "project",
npm_config_package_lock: "false",

View File

@@ -66,6 +66,7 @@ describe("tsdown config", () => {
"agents/auth-profiles.runtime",
"agents/model-catalog.runtime",
"agents/models-config.runtime",
"plugins/memory-state",
"subagent-registry.runtime",
"task-registry-control.runtime",
"agents/pi-model-discovery-runtime",

View File

@@ -186,6 +186,10 @@ describe("resolveBundledRuntimeDepsNpmRunner", () => {
PATH: "/usr/bin:/bin",
npm_config_cache: "/opt/openclaw/runtime-cache",
npm_config_dry_run: "false",
npm_config_fetch_retries: "5",
npm_config_fetch_retry_maxtimeout: "120000",
npm_config_fetch_retry_mintimeout: "10000",
npm_config_fetch_timeout: "300000",
npm_config_global: "false",
npm_config_legacy_peer_deps: "true",
npm_config_location: "project",

View File

@@ -15,6 +15,7 @@ import { describe, expect, it } from "vitest";
import { LOCAL_BUILD_METADATA_DIST_PATHS } from "../../scripts/lib/local-build-metadata-paths.mjs";
import {
agentOutputHasExpectedOkMarker,
buildCrossOsReleaseSmokePluginAllowlist,
buildReleaseOnboardArgs,
buildWindowsDevUpdateToolchainCheckScript,
buildWindowsFreshShellVersionCheckScript,
@@ -111,6 +112,15 @@ describe("scripts/openclaw-cross-os-release-checks", () => {
);
});
it("keeps release smoke plugin allowlists focused on agent-turn essentials", () => {
const allowlist = buildCrossOsReleaseSmokePluginAllowlist({ extensionId: "openai" });
expect(allowlist).toEqual(expect.arrayContaining(["openai", "memory-core", "acpx"]));
expect(allowlist).not.toContain("document-extract");
expect(allowlist).not.toContain("microsoft");
expect(allowlist).not.toContain("web-readability");
});
it("keeps cross-OS live smoke agent turns on minimal thinking", () => {
const source = readFileSync("scripts/openclaw-cross-os-release-checks.ts", "utf8");

View File

@@ -148,6 +148,10 @@ describe("bundled plugin postinstall", () => {
).toEqual({
HOME: "/tmp/home",
npm_config_dry_run: "false",
npm_config_fetch_retries: "5",
npm_config_fetch_retry_maxtimeout: "120000",
npm_config_fetch_retry_mintimeout: "10000",
npm_config_fetch_timeout: "300000",
npm_config_legacy_peer_deps: "true",
npm_config_package_lock: "false",
npm_config_save: "false",

View File

@@ -18,5 +18,6 @@ describe("scripts/test-live-cli-backend-docker.sh", () => {
expect(forwardedVars).toContain("OPENCLAW_LIVE_CLI_BACKEND_ARGS");
expect(forwardedVars).toContain("OPENCLAW_LIVE_CLI_BACKEND_RESUME_ARGS");
expect(forwardedVars).toContain("OPENCLAW_TEST_CONSOLE");
});
});

View File

@@ -212,6 +212,7 @@ function buildCoreDistEntries(): Record<string, string> {
"agents/auth-profiles.runtime": "src/agents/auth-profiles.runtime.ts",
"agents/model-catalog.runtime": "src/agents/model-catalog.runtime.ts",
"agents/models-config.runtime": "src/agents/models-config.runtime.ts",
"plugins/memory-state": "src/plugins/memory-state.ts",
"subagent-registry.runtime": "src/agents/subagent-registry.runtime.ts",
"task-registry-control.runtime": "src/tasks/task-registry-control.runtime.ts",
"agents/pi-model-discovery-runtime": "src/agents/pi-model-discovery-runtime.ts",