Skip to content

Commit 0ec2fac

Browse files
ci: add packaged-install TUI smoke
The dev-path TUI import smoke cannot catch packaging breaks: OpenTUI's Solid transform skips node_modules sources, so a dev checkout always loads while a published install resolves against its own installed dependencies. Pack the real tarball, install prod-only under a node_modules path, and import the TUI entry from there — the exact load path OpenCode's plugin cache uses. Verified non-vacuous against the published 0.31.1 artifact (fails with the sidebar-breaking module resolution error). Co-authored-by: Alfonso [Magic Context] <288211368+alfonso-magic-context@users.noreply.github.com>
1 parent 9b65bcd commit 0ec2fac

3 files changed

Lines changed: 74 additions & 0 deletions

File tree

.github/workflows/ci.yml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,13 @@ jobs:
8080
- name: Smoke (TUI entry import)
8181
run: bun packages/plugin/scripts/smoke-tui-import.ts
8282

83+
# The dev-path import above cannot catch packaging breaks: OpenTUI's Solid
84+
# transform skips node_modules sources, so only a packed PROD install
85+
# exercises the resolution path OpenCode's plugin cache uses (v0.31.1
86+
# shipped without runtime deps and passed every dev-path check).
87+
- name: Smoke (TUI packaged install import)
88+
run: bun packages/plugin/scripts/smoke-tui-pack-install.ts
89+
8390
check-pi-plugin:
8491
name: Check (pi-plugin)
8592
runs-on: ubuntu-latest

.github/workflows/release.yml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,11 @@ jobs:
9494
- name: Smoke (TUI entry import)
9595
run: bun packages/plugin/scripts/smoke-tui-import.ts
9696

97+
# Packaged-install import — the only check that exercises the published
98+
# node_modules load path (the v0.31.1 failure class).
99+
- name: Smoke (TUI packaged install import)
100+
run: bun packages/plugin/scripts/smoke-tui-pack-install.ts
101+
97102
test-pi:
98103
name: Test (pi-plugin)
99104
runs-on: ubuntu-latest
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
#!/usr/bin/env bun
2+
// Packaged-install TUI smoke: prove the TUI entry loads from a PROD npm install
3+
// living under node_modules — the path OpenCode's plugin cache actually uses.
4+
//
5+
// Why this exists: the dev checkout can NEVER catch a TUI packaging break.
6+
// OpenTUI's Solid transform skips any source under node_modules (sourceFilter
7+
// negative-lookahead), so a dev checkout (file:// path) gets the host's module
8+
// remapping while a published install does not — the published install must
9+
// resolve @opentui/solid and solid-js from its own installed dependencies.
10+
// v0.31.1 shipped without those runtime deps, passed every dev-path check, and
11+
// broke the sidebar for every npm install. This smoke packs the real tarball,
12+
// installs it with --omit=dev under a node_modules path, and imports the TUI
13+
// entry from there — failing exactly the way OpenCode would.
14+
15+
import { execFileSync } from "node:child_process";
16+
import { mkdtempSync, rmSync, writeFileSync, readdirSync } from "node:fs";
17+
import { tmpdir } from "node:os";
18+
import { join, resolve } from "node:path";
19+
20+
const pluginRoot = resolve(import.meta.dir, "..");
21+
const stage = mkdtempSync(join(tmpdir(), "mc-tui-pack-smoke-"));
22+
23+
function fail(message: string): never {
24+
console.error(`smoke-tui-pack-install: FAIL — ${message}`);
25+
process.exit(1);
26+
}
27+
28+
try {
29+
// 1. Pack the real publish artifact.
30+
execFileSync("npm", ["pack", "--pack-destination", stage], {
31+
cwd: pluginRoot,
32+
stdio: "pipe",
33+
});
34+
const tarball = readdirSync(stage).find((f) => f.endsWith(".tgz"));
35+
if (!tarball) fail("npm pack produced no tarball");
36+
37+
// 2. Install it PROD-ONLY into a scratch package, mirroring OpenCode's
38+
// plugin cache shape (<root>/node_modules/<pkg>/...).
39+
writeFileSync(join(stage, "package.json"), JSON.stringify({ name: "smoke-host", private: true }));
40+
execFileSync("npm", ["install", "--omit=dev", "--no-audit", "--no-fund", join(stage, tarball)], {
41+
cwd: stage,
42+
stdio: "pipe",
43+
});
44+
45+
// 3. Import the TUI entry from INSIDE node_modules, exactly as the host
46+
// would. A missing runtime dep (the v0.31.1 failure) throws
47+
// "Cannot find module '@opentui/solid/jsx-dev-runtime'" here.
48+
const installed = join(stage, "node_modules", "@cortexkit", "opencode-magic-context");
49+
const probe = `
50+
const mod = await import(${JSON.stringify(join(installed, "src", "tui", "index.tsx"))});
51+
const plugin = mod.default;
52+
if (!plugin || typeof plugin !== "object") throw new Error("TUI entry has no default export object");
53+
console.log("ok packaged TUI entry imports and exports the plugin object");
54+
`;
55+
execFileSync("bun", ["-e", probe], { cwd: stage, stdio: "inherit" });
56+
57+
console.log("smoke-tui-pack-install: all checks passed");
58+
} catch (error) {
59+
fail(error instanceof Error ? error.message : String(error));
60+
} finally {
61+
rmSync(stage, { recursive: true, force: true });
62+
}

0 commit comments

Comments
 (0)