mirror of
https://github.com/openclaw/openclaw.git
synced 2026-10-03 09:39:25 +00:00
* fix(qa): verify leased Telegram tester group access Check tester membership and effective text permission in the leased user driver before group readiness. Reuse the check in doctor and select trusted skill scripts for frozen release candidate QA. Preserve supported private DM turns and leave credential repair to the pool owner. * ci: install Chromium for native live browser tests The native-live-test shard includes the real Gateway widget restart proof, which launches Playwright after restoring the interrupted session. Chromium was installed only in separate Repo E2E jobs, leaving the live shard without its required executable. Install the candidate UI's pinned Chromium and system dependencies only for the selected native-live-test row. Preserve profile selection and all test gates. Verified the unchanged dc420 widget restart test with real OpenAI, Gateway process replacement, and interactive Chromium dashboard assertions on Blacksmith Testbox; canonical workflow checks and formatting also pass. * test(release): prove supported cross-OS 9.2 transition Select the explicitly supported external package-manager and fresh Doctor transition only for 2026.9.2 to 2026.9.3. Preserve the old updater's safe schema-15 refusal as negative evidence and never report self-update passed. Verify backup, exact package identity, schema migration, retained settings and session history, candidate serving version, and a fresh persisted turn. Keep credential-bearing backup archives out of CI evidence and remove them on both successful and failed runs. Other release pairs retain existing updater and Windows fallback behavior. Validation: 13 cross-OS upgrade lane tests, two pre-fix regression failures, full changed checks, and independent review. Real packaged cross-OS/live qualification remains required against the aggregate candidate. * test(installer): prove supported historical package transitions * test(release): exercise same-schema updater boundaries Keep updater-specific plugin repair and consent checks on the prepared candidate, then target explicit synthetic later versions with the same runtime and storage schema. Retain installed-version and plugin-policy assertions, and remove the obsolete legacy post-update fallback. Add versioned future-tarball generation to the existing first-hop fixture owner, with immutable input and source/target digest receipts. Restore the reserved runtime-promotion staging ignore in package-derived Git fixtures so the updater's unchanged-source check stays meaningful. Validation: 26 focused tests, a pre-fix Git staging regression, full changed checks, exact candidate tarball fixture generation, and P2 review. Actual Docker update/consent/channel qualification remains required in aggregate CI. * test(release): verify channel update staging cleanup Assert the real channel flow refuses ordinary untracked user files without changing source, then require successful channel updates to remove every reserved runtime staging entry. Preserve recovery data when the assertion detects leftovers. No ignore or production cleanup policy is broadened. * test(onboard): select configured model through explicit picker * ci: pin release performance checks to reviewed Kova accounting Select the reviewed Linux process-lifetime CPU accounting and bounded worker-watchdog implementation from Kova PR #110 for canonical, legacy-list, and trusted live fixtures. Keep existing trust classification, timeout values, and performance thresholds. * fix(ci): distinguish bundle build modes in job names * test(release): build matching future runtime fixtures Derive a synthetic Codex runtime cohort from its verified candidate package by changing only package.version and openclaw.build.openclawVersion. Require matching source metadata and preserve payload, constraints, immutable input, and source/target digest receipts. Reuse the existing private tarball lifecycle and sequence validation. Validated 11 focused tests, pre-change CLI failures, full changed checks, and P2 review. * docs(release): prepare private QA before local E2E * fix(release): admit package metadata before validation dispatch Port the reviewed early source admission into trusted Tooling, preserving the current selected REST transport. Reject invalid version notes and misaligned core packages before any Git push, non-GET API write, or workflow dispatch; retain explicitly allowed substantive draft notes. * test(release): qualify supported historical upgrade transitions Prove the published 2026.8.2/2026.9.2 to 2026.9.3 external package-manager and fresh Doctor contract through one shared helper. Preserve the old in-process updater refusal and schema 15, require owner-stopped migration with a verified private backup, and verify schema 16 plus retained Gateway history afterward. Keep current-runtime update coverage distinct: managed restart uses separately identified future core and matching runtime fixtures, with real updater, canary, service replacement, authentication, and serving checks. Fix fixture-only channel environment pollution and mock serving nonce responses. Sealed Docker journey, historical first-hop, current-candidate survivor, root-managed VPS, and onboarding pass. Managed-auth historical preservation passes; its future canary exposes an independent existing plugin projection blocker, retained as failing proof for the candidate repair owner. No product schema or refusal guard changes. * test(release): narrow recorded update command before indexing * fix(ci): align historical upgrade fixture ownership Keep all seven external transition assertion cases with the first-hop package fixtures: both own the historical upgrade boundary and now share its temporary-state lifecycle. Preserve helper test selection and all assertions while avoiding an additional standalone tooling group. Provide the new inference and future-package preparation boundaries in isolated service, mobile, and cron bootstrap probes, and verify each updater argument without changing readiness or migration assertions. Register the path-launched assertion CLI as a Knip entry. Validation: 67 related tests; 70 exact-merge planner and combined-suite tests; five 80-job stress plans; full Knip unused-file scans; scoped checks and P2 review. * fix(ci): model upgrade preparation in isolated probes Complete the companion fixture and Knip repairs for the preceding transition-test consolidation. Model the independent inference and future-package preparation producers, verify exact updater argument boundaries, and retain service-readiness, authored-state, and cron migration assertions. Declare the path-launched transition assertion CLI in the existing Knip entrypoint list. * test(release): preserve fixture registry on managed restart Capture the fake service manager registry alongside its endpoint paths, then refresh that owned context after preparing the future cohort. Projected native service callers cannot drop or replace it; transient update state still stays outside the managed child. The executable service regression fails on the original shim and passes with missing and conflicting caller registries. Four focused tests, the changed gate, and P2 review pass. Reuse the existing d928 package for the final managed-upgrade replay. * test(release): preserve prepared UI identity in future fixtures Advance synthetic package versions while retaining the opaque build ID already embedded in unchanged Control UI assets. The canonical asset-health regression fails the prior builder as stale, then verifies readiness and unchanged UI bytes for both future fixture sequences. Package-version update admission and managed-restart proof remain unchanged. * test(release): retain manager-owned fixture policy Capture the existing automation and offline-channel policy with registry identity when generating the manager shim. Native service clients project these values away; losing them activated retained synthetic channel credentials and correctly failed readiness. Restore only this explicit manager allowlist and keep transient update/compatibility state excluded. The executable service regression fails on missing manager flags and passes across projected or conflicting caller environments. Four focused tests, the full changed gate, and fresh P2 review pass. Actual corrected managed Docker proof remains pending. * docs(ci): keep bundle identity with routing guidance * fix(release): retry transient GraphQL EOF failures Classify the observed gh unexpected EOF transport failure within the existing five-attempt retry budget. Preserve authentication, invalid-response, inventory and snapshot handling. Exercise recovery, exhaustion and fail-fast errors through the real verifier CLI with a fake gh transport; also modernize the existing disposable-array sort required by touched-test lint. * test(release): align survivor fixtures with manager preparation Supply manager environment JSON to directly launched supervisors, and model the independent manager preparation phase in config-parking and companion fixtures. Preserve service readiness, restart, diagnostics, and strict phase-order assertions without changing production behavior or test limits. * test(release): align upgrades with deferred schema publication Restore installed-updater survivor and first-hop coverage after shared migration ownership moved into the durable update ledger. Record applied schema content separately from published schema version, retain the genuine missing-chunk negative control, and label external installation as an alternate with no self-update attempt. Preserve production-owned unsupported migration refusals. * test(release): restore supported packaged upgrade coverage Restore real 2026.9.2 to 2026.9.3 self-update after ledger-driven schema migration support. Keep retained conversations, private backup, settings, candidate identity, and serving inference proof. Require migrated content independently of publication grace and remove obsolete external-install diversion from cross-OS and installer update smoke. Shared external helper remains separately owned. * test(release): refresh legacy manager before updater restart Bind the service manager to the candidate registry before the published baseline updater starts its managed service. Preserve restart verification for successful and recoverable outcomes alongside explicit future targets. Exercise stale registry capture, replacement failures, pre-update identity, and attribution without changing timeouts or caps.
187 lines
7.1 KiB
TypeScript
187 lines
7.1 KiB
TypeScript
// Package git fixture tests cover package-derived Docker git install fixtures.
|
|
import { spawnSync } from "node:child_process";
|
|
import { mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
import path from "node:path";
|
|
import { afterEach, describe, expect, it } from "vitest";
|
|
import { resolveNpmRunner } from "../../scripts/npm-runner.mts";
|
|
import { useAutoCleanupTempDirTracker } from "../helpers/temp-dir.js";
|
|
|
|
describe("package git fixture", () => {
|
|
const tempDirs = useAutoCleanupTempDirTracker(afterEach);
|
|
|
|
it("installs the packed runtime without resolving checkout-only development dependencies", () => {
|
|
const root = tempDirs.make("openclaw-package-git-fixture-install-");
|
|
const runtimeDir = path.join(root, "runtime");
|
|
mkdirSync(runtimeDir);
|
|
writeFileSync(
|
|
path.join(runtimeDir, "package.json"),
|
|
JSON.stringify({ name: "fixture-runtime", version: "1.0.0", main: "index.cjs" }),
|
|
);
|
|
writeFileSync(path.join(runtimeDir, "index.cjs"), 'module.exports = "packed runtime";\n');
|
|
writeFileSync(
|
|
path.join(root, "package.json"),
|
|
JSON.stringify({
|
|
name: "prebuilt-fixture",
|
|
version: "1.0.0",
|
|
dependencies: { "fixture-runtime": "file:./runtime" },
|
|
devDependencies: { "checkout-build-tool": "workspace:*" },
|
|
}),
|
|
);
|
|
const prepared = spawnSync(
|
|
process.execPath,
|
|
["scripts/e2e/lib/package-git-fixture.mjs", "prepare", root],
|
|
{ encoding: "utf8" },
|
|
);
|
|
expect(prepared.status, prepared.stderr).toBe(0);
|
|
const npm = resolveNpmRunner({
|
|
npmArgs: [
|
|
"install",
|
|
"--omit=dev",
|
|
"--offline",
|
|
"--ignore-scripts",
|
|
"--no-fund",
|
|
"--no-audit",
|
|
],
|
|
});
|
|
const installed = spawnSync(npm.command, npm.args, {
|
|
cwd: root,
|
|
encoding: "utf8",
|
|
env: npm.env,
|
|
shell: npm.shell,
|
|
windowsVerbatimArguments: npm.windowsVerbatimArguments,
|
|
timeout: 30_000,
|
|
});
|
|
expect(installed.status, `${installed.stdout}\n${installed.stderr}`).toBe(0);
|
|
const runtime = spawnSync(process.execPath, ["-p", 'require("fixture-runtime")'], {
|
|
cwd: root,
|
|
encoding: "utf8",
|
|
});
|
|
expect(runtime.status, runtime.stderr).toBe(0);
|
|
expect(runtime.stdout.trim()).toBe("packed runtime");
|
|
});
|
|
|
|
it("stages bundled ai runtime as a local file dependency", async () => {
|
|
const root = tempDirs.make("openclaw-package-git-fixture-");
|
|
writeFileSync(path.join(root, ".gitignore"), "dist/\n");
|
|
mkdirSync(path.join(root, "node_modules", "@openclaw", "ai"), { recursive: true });
|
|
writeFileSync(
|
|
path.join(root, "package.json"),
|
|
`${JSON.stringify(
|
|
{
|
|
dependencies: { "@openclaw/ai": "2026.6.11", chalk: "5.6.2" },
|
|
bundleDependencies: ["@openclaw/ai", "chalk"],
|
|
scripts: {
|
|
build: "node build.mjs",
|
|
openclaw: "node scripts/run-node.mjs",
|
|
postinstall: "node scripts/postinstall-bundled-plugins.mjs",
|
|
},
|
|
},
|
|
null,
|
|
2,
|
|
)}\n`,
|
|
);
|
|
writeFileSync(
|
|
path.join(root, "node_modules", "@openclaw", "ai", "package.json"),
|
|
`${JSON.stringify({
|
|
name: "@openclaw/ai",
|
|
version: "2026.6.11",
|
|
type: "module",
|
|
main: "./dist/index.mjs",
|
|
exports: { ".": "./dist/index.mjs" },
|
|
devDependencies: { "@openclaw/normalization-core": "0.0.0-private" },
|
|
})}\n`,
|
|
);
|
|
|
|
const result = spawnSync(
|
|
process.execPath,
|
|
["scripts/e2e/lib/package-git-fixture.mjs", "prepare", root],
|
|
{ cwd: process.cwd(), encoding: "utf8" },
|
|
);
|
|
|
|
expect(result.status, `${result.stdout}\n${result.stderr}`).toBe(0);
|
|
expect(readFileSync(path.join(root, ".gitignore"), "utf8").split(/\r?\n/u)).toEqual(
|
|
expect.arrayContaining(["dist/", "node_modules", "**/node_modules/", "pnpm-lock.yaml"]),
|
|
);
|
|
const packageJson = JSON.parse(readFileSync(path.join(root, "package.json"), "utf8"));
|
|
expect(packageJson.dependencies["@openclaw/ai"]).toBe("file:.openclaw-fixture/packages/ai");
|
|
expect(packageJson.bundleDependencies).toEqual(["chalk"]);
|
|
expect(packageJson.scripts).toEqual({
|
|
build: "node build.mjs",
|
|
openclaw: "node openclaw.mjs",
|
|
});
|
|
const relocatedAiPackage = JSON.parse(
|
|
readFileSync(path.join(root, ".openclaw-fixture", "packages", "ai", "package.json"), "utf8"),
|
|
);
|
|
expect(relocatedAiPackage).toMatchObject({
|
|
name: "@openclaw/ai",
|
|
version: "2026.6.11",
|
|
type: "module",
|
|
main: "./dist/index.mjs",
|
|
exports: { ".": "./dist/index.mjs" },
|
|
});
|
|
expect(relocatedAiPackage).not.toHaveProperty("devDependencies");
|
|
|
|
mkdirSync(path.join(root, "node_modules", "chalk"), { recursive: true });
|
|
writeFileSync(path.join(root, "node_modules", "chalk", "package.json"), "{}\n");
|
|
mkdirSync(path.join(root, ".openclaw-fixture", "packages", "ai", "node_modules", "zod"), {
|
|
recursive: true,
|
|
});
|
|
writeFileSync(
|
|
path.join(root, ".openclaw-fixture", "packages", "ai", "node_modules", "zod", "package.json"),
|
|
"{}\n",
|
|
);
|
|
writeFileSync(path.join(root, "pnpm-lock.yaml"), "lockfileVersion: '9.0'\n");
|
|
for (const destination of ["dist", "node_modules"]) {
|
|
const staging = path.join(
|
|
root,
|
|
`${destination}.openclaw-update-00000000-0000-4000-8000-000000000000.tmp`,
|
|
);
|
|
mkdirSync(staging);
|
|
writeFileSync(path.join(staging, "candidate"), "staged runtime");
|
|
}
|
|
writeFileSync(path.join(root, "operator-notes.tmp"), "keep visible");
|
|
expect(spawnSync("git", ["init", "-q", root], { encoding: "utf8" }).status).toBe(0);
|
|
expect(spawnSync("git", ["-C", root, "add", "-A"], { encoding: "utf8" }).status).toBe(0);
|
|
const staged = spawnSync("git", ["-C", root, "diff", "--cached", "--name-only"], {
|
|
encoding: "utf8",
|
|
});
|
|
expect(staged.status).toBe(0);
|
|
expect(staged.stdout).not.toContain("node_modules");
|
|
expect(staged.stdout).not.toContain("pnpm-lock.yaml");
|
|
expect(staged.stdout).not.toContain(".openclaw-update-");
|
|
expect(staged.stdout).toContain("operator-notes.tmp");
|
|
});
|
|
|
|
it("uses the packed entrypoint without a bundled ai runtime", () => {
|
|
const root = tempDirs.make("openclaw-package-git-fixture-no-ai-");
|
|
writeFileSync(
|
|
path.join(root, "package.json"),
|
|
`${JSON.stringify(
|
|
{
|
|
dependencies: { chalk: "5.6.2" },
|
|
scripts: {
|
|
lint: "node lint.mjs",
|
|
openclaw: "node scripts/run-node.mjs",
|
|
postinstall: "node scripts/postinstall-bundled-plugins.mjs",
|
|
},
|
|
},
|
|
null,
|
|
2,
|
|
)}\n`,
|
|
);
|
|
|
|
const result = spawnSync(
|
|
process.execPath,
|
|
["scripts/e2e/lib/package-git-fixture.mjs", "prepare", root],
|
|
{ cwd: process.cwd(), encoding: "utf8" },
|
|
);
|
|
|
|
expect(result.status, `${result.stdout}\n${result.stderr}`).toBe(0);
|
|
const packageJson = JSON.parse(readFileSync(path.join(root, "package.json"), "utf8"));
|
|
expect(packageJson.scripts).toEqual({
|
|
lint: "node lint.mjs",
|
|
openclaw: "node openclaw.mjs",
|
|
});
|
|
expect(packageJson.dependencies).not.toHaveProperty("@openclaw/ai");
|
|
});
|
|
});
|