test(omo-claude): make sync-mcp self-healing and test:claude order-independent
sync-mcp rebuilds the lsp component if a prior sync wiped its dist; sync-mcp.test builds in a before hook; checkVendored flags only real unbundled imports (a guarded require.resolve fallback is allowed); test:claude runs the destructive sync-components test in its own node --test pass so it never races the build-checking tests. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
+1
-1
@@ -71,7 +71,7 @@
|
||||
"typecheck:script": "tsgo --noEmit -p script/tsconfig.json",
|
||||
"test": "bun test",
|
||||
"test:codex": "bun test src/cli/install-codex/codex-cache.test.ts src/cli/install-codex/install-codex.test.ts src/cli/install-codex/link-cached-plugin-agents.test.ts packages/omo-codex/src/**/*.test.ts packages/utils/src/jsonc-parser.test.ts packages/utils/src/frontmatter.test.ts packages/hashline-core/src/hash-computation.test.ts packages/hashline-core/src/smoke-untested-modules.test.ts packages/rules-engine/src/index.test.ts packages/rules-engine/src/security-boundary.test.ts packages/agents-md-core/src/injector.test.ts && node --test packages/omo-codex/plugin/test/*.test.mjs packages/omo-codex/scripts/install-local.test.mjs packages/omo-codex/scripts/install-agent-links.test.mjs packages/omo-codex/scripts/install-bin-links.test.mjs packages/omo-codex/scripts/sync-telemetry-component.test.mjs",
|
||||
"test:claude": "bun test packages/omo-claude/src/**/*.test.ts packages/omo-claude/plugin/components/ultragoal/test/*.test.ts script/sync-lazyclaudecode-marketplace.test.ts && node --test packages/omo-claude/plugin/test/*.test.mjs packages/omo-claude/plugin/scripts/*.test.mjs packages/omo-claude/scripts/*.test.mjs",
|
||||
"test:claude": "bun test packages/omo-claude/src/**/*.test.ts packages/omo-claude/plugin/components/ultragoal/test/*.test.ts script/sync-lazyclaudecode-marketplace.test.ts && node --test packages/omo-claude/plugin/scripts/sync-components.test.mjs && node --test packages/omo-claude/plugin/test/aggregate.test.mjs packages/omo-claude/plugin/scripts/sync-mcp.test.mjs packages/omo-claude/scripts/sync-telemetry-component.test.mjs",
|
||||
"test:windows-codex": "bun run test:codex",
|
||||
"build:ast-grep-mcp": "bun run --cwd packages/ast-grep-mcp build"
|
||||
},
|
||||
|
||||
@@ -102,9 +102,8 @@ export async function vendorMcp() {
|
||||
// a plugin cache; bundling inlines it (result: node-builtins only).
|
||||
export async function bundleLspComponentHook() {
|
||||
if (!(await pathExists(LSP_COMPONENT_HOOK))) {
|
||||
throw new Error(
|
||||
`lsp component hook missing at ${LSP_COMPONENT_HOOK}; build the lsp component first`,
|
||||
);
|
||||
// A prior component sync can wipe components/lsp/dist; rebuild it before bundling.
|
||||
run("npm", ["run", "build", "--workspace", "components/lsp"], PLUGIN_ROOT);
|
||||
}
|
||||
const tmp = `${LSP_COMPONENT_HOOK}.bundle.mjs`;
|
||||
bundle(LSP_COMPONENT_HOOK, tmp);
|
||||
@@ -143,11 +142,16 @@ export async function checkVendored() {
|
||||
}
|
||||
}
|
||||
|
||||
// The hook must be self-contained: no bare @code-yeongyu/lsp-tools-mcp import.
|
||||
// The hook must be self-contained: no UNBUNDLED bare import/require of
|
||||
// lsp-tools-mcp. A `require.resolve(...)` is allowed as the monorepo/dev
|
||||
// fallback guarded by CLAUDE_PLUGIN_ROOT (the vendored mcp/lsp/cli.js path is
|
||||
// used in a cache), so it never executes from a node_modules-free tree.
|
||||
if (await pathExists(LSP_COMPONENT_HOOK)) {
|
||||
const hook = await readFile(LSP_COMPONENT_HOOK, "utf8");
|
||||
if (hook.includes("@code-yeongyu/lsp-tools-mcp")) {
|
||||
problems.push("components/lsp/dist/cli.js still imports @code-yeongyu/lsp-tools-mcp (not bundled)");
|
||||
const unbundledImport =
|
||||
/\bfrom\s*["'][^"']*@code-yeongyu\/lsp-tools-mcp|\brequire\s*\(\s*["'][^"']*@code-yeongyu\/lsp-tools-mcp/;
|
||||
if (unbundledImport.test(hook)) {
|
||||
problems.push("components/lsp/dist/cli.js still has an unbundled @code-yeongyu/lsp-tools-mcp import");
|
||||
}
|
||||
} else {
|
||||
problems.push("missing components/lsp/dist/cli.js");
|
||||
|
||||
@@ -2,7 +2,7 @@ import { spawnSync } from "node:child_process";
|
||||
import assert from "node:assert/strict";
|
||||
import { readFile } from "node:fs/promises";
|
||||
import { dirname, join } from "node:path";
|
||||
import { test } from "node:test";
|
||||
import { before, test } from "node:test";
|
||||
import { fileURLToPath } from "node:url";
|
||||
|
||||
import {
|
||||
@@ -11,11 +11,19 @@ import {
|
||||
LSP_DEST,
|
||||
MCP_JSON_PATH,
|
||||
checkVendored,
|
||||
syncMcp,
|
||||
} from "./sync-mcp.mjs";
|
||||
|
||||
const SCRIPT_DIR = dirname(fileURLToPath(import.meta.url));
|
||||
const SCRIPT_PATH = join(SCRIPT_DIR, "sync-mcp.mjs");
|
||||
|
||||
// Self-contained: build + vendor + bundle so these assertions never depend on
|
||||
// prior build state or test ordering (sync-components.test re-syncs the lsp
|
||||
// component and wipes its dist; this rebuilds it before we check).
|
||||
before(async () => {
|
||||
await syncMcp({ build: true });
|
||||
});
|
||||
|
||||
function runCli(args) {
|
||||
return spawnSync(process.execPath, [SCRIPT_PATH, ...args], { encoding: "utf8" });
|
||||
}
|
||||
@@ -54,10 +62,14 @@ test("vendored server entrypoints exist", async () => {
|
||||
}
|
||||
});
|
||||
|
||||
test("lsp component hook is bundled (no bare @code-yeongyu/lsp-tools-mcp import)", async () => {
|
||||
test("lsp component hook is bundled (no unbundled @code-yeongyu/lsp-tools-mcp import)", async () => {
|
||||
const hook = await readFile(LSP_COMPONENT_HOOK, "utf8");
|
||||
// A guarded require.resolve(...) fallback is allowed. An actual import/require
|
||||
// statement is not (it would fail to resolve from a node_modules-free cache).
|
||||
const unbundledImport =
|
||||
/\bfrom\s*["'][^"']*@code-yeongyu\/lsp-tools-mcp|\brequire\s*\(\s*["'][^"']*@code-yeongyu\/lsp-tools-mcp/;
|
||||
assert.ok(
|
||||
!hook.includes("@code-yeongyu/lsp-tools-mcp"),
|
||||
!unbundledImport.test(hook),
|
||||
"the lsp component hook must inline lsp-tools-mcp so it resolves from a cache",
|
||||
);
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user