Compare commits

..

2 Commits

Author SHA1 Message Date
Markus Hartung
1b4612c922 test(build): resolve tsup/npm portably in the #11787 regression test instead of a hardcoded .bin path
The old test assumed @omniroute/opencode-plugin/node_modules/.bin/tsup
already existed. A fresh checkout (CI's npm ci never installs this
standalone package's own deps) has no such node_modules at all, so the
test failed with MODULE_NOT_FOUND in CI while passing locally on a devbox
that had installed it before. Mirror scripts/build/prepublish.ts's own
install-then-resolveLocalBinEntry approach.
2026-08-29 06:03:34 -03:00
Markus Hartung
6bebef13bf fix(cli): drop the never-produced dist/index.cjs requirement from prepublish's opencode-plugin skip check (#11787) 2026-08-29 05:32:58 -03:00
4 changed files with 101 additions and 3 deletions

View File

@@ -499,7 +499,7 @@ jobs:
- name: Upload Trivy SARIF to Security tab
if: needs.prepare.outputs.version != 'main'
continue-on-error: true
uses: github/codeql-action/upload-sarif@v4.37.8
uses: github/codeql-action/upload-sarif@v4.37.7
with:
sarif_file: trivy-results.sarif
category: trivy-image

View File

@@ -0,0 +1 @@
- fix(cli): stop prepublish from re-rebuilding the already-built ESM-only opencode-plugin dist (#11787)

View File

@@ -483,9 +483,11 @@ if (existsSync(cliSrcFile)) {
// flow for every downstream user.
const opencodePluginSrc = join(ROOT, "@omniroute", "opencode-plugin");
const opencodePluginDist = join(opencodePluginSrc, "dist", "index.js");
const opencodePluginCjs = join(opencodePluginSrc, "dist", "index.cjs");
if (existsSync(opencodePluginSrc) && existsSync(join(opencodePluginSrc, "package.json"))) {
const pluginAlreadyBuilt = existsSync(opencodePluginDist) && existsSync(opencodePluginCjs);
// The plugin's tsup config is ESM-only (format: ["esm"]), so a successful
// build only ever produces dist/index.js (+ dist/index.d.ts) — never
// dist/index.cjs. Gate the skip solely on dist/index.js.
const pluginAlreadyBuilt = existsSync(opencodePluginDist);
if (!pluginAlreadyBuilt) {
console.log("\n 🔨 Building @omniroute/opencode-plugin (tsup)...");
try {

View File

@@ -0,0 +1,95 @@
// Regression test for issue #11787.
//
// scripts/build/prepublish.ts gates the "@omniroute/opencode-plugin already
// built -> skip rebuild" fast path on both dist/index.js AND dist/index.cjs
// existing. @omniroute/opencode-plugin/tsup.config.ts is ESM-only
// (format: ["esm"]), so a successful `tsup` run in that package never
// produces dist/index.cjs -- the old predicate could never be true.
//
// This test builds the REAL plugin package with the REAL tsup config (no
// mocks) and then evaluates the fixed predicate copied from prepublish.ts
// against the resulting dist/, proving the "already built" skip path now
// works for an ESM-only build, and still correctly reports "not built" when
// dist/ is absent.
import { test } from "node:test";
import assert from "node:assert/strict";
import { execFileSync } from "node:child_process";
import { existsSync, rmSync } from "node:fs";
import { join, dirname } from "node:path";
import { fileURLToPath } from "node:url";
import { resolveLocalBinEntry, isNativeExecutable } from "../../scripts/build/buildToolRunner.mjs";
import { resolveBundledNpmEntry } from "../../scripts/build/resolveNpmEntry.ts";
const __dirname = dirname(fileURLToPath(import.meta.url));
const ROOT = join(__dirname, "..", "..");
const opencodePluginSrc = join(ROOT, "@omniroute", "opencode-plugin");
const opencodePluginDist = join(opencodePluginSrc, "dist", "index.js");
const opencodePluginCjs = join(opencodePluginSrc, "dist", "index.cjs");
test("prepublish pluginAlreadyBuilt predicate recognizes a real ESM-only tsup build (#11787)", () => {
rmSync(join(opencodePluginSrc, "dist"), { recursive: true, force: true });
// The plugin is a standalone package, not an npm workspace member (see
// scripts/build/prepublish.ts's own comment above the equivalent build step) — a
// root `npm ci` never populates its node_modules, so a fresh checkout (CI, or any
// devbox that hasn't built the plugin before) needs its own install first. Mirror
// prepublish.ts's own install step instead of hardcoding a `.bin/tsup` path that
// only exists on a devbox someone happened to `npm install` in already.
if (!existsSync(join(opencodePluginSrc, "node_modules"))) {
const npmEntry = resolveBundledNpmEntry("npm-cli.js");
const installArgs = ["install", "--no-audit", "--no-fund"];
if (npmEntry) {
execFileSync(process.execPath, [npmEntry, ...installArgs], {
cwd: opencodePluginSrc,
stdio: "inherit",
});
} else {
execFileSync("npm", installArgs, { cwd: opencodePluginSrc, stdio: "inherit" });
}
}
// Resolve the real tsup binary the same way scripts/build/prepublish.ts's
// runBuildTool() does — never a hardcoded `.bin/tsup` path, since npm's hoisting can
// place the binary at the plugin's own node_modules/.bin OR the repo root's,
// depending on the install.
const localEntry = resolveLocalBinEntry("tsup", "tsup", opencodePluginSrc);
if (localEntry) {
if (isNativeExecutable(localEntry)) {
execFileSync(localEntry, [], { cwd: opencodePluginSrc, stdio: "inherit" });
} else {
execFileSync(process.execPath, [localEntry], { cwd: opencodePluginSrc, stdio: "inherit" });
}
} else {
const npxEntry = resolveBundledNpmEntry("npx-cli.js");
if (npxEntry) {
execFileSync(process.execPath, [npxEntry, "tsup"], {
cwd: opencodePluginSrc,
stdio: "inherit",
});
} else {
execFileSync("npx", ["tsup"], { cwd: opencodePluginSrc, stdio: "inherit" });
}
}
assert.equal(existsSync(opencodePluginDist), true, "dist/index.js should exist after tsup");
assert.equal(
existsSync(opencodePluginCjs),
false,
"dist/index.cjs should NOT exist for an ESM-only tsup build"
);
// This is the fixed predicate from scripts/build/prepublish.ts.
const pluginAlreadyBuilt = existsSync(opencodePluginDist);
assert.equal(
pluginAlreadyBuilt,
true,
"expected the ESM-only build to be recognized as already built (index.js present is sufficient)"
);
});
test("prepublish pluginAlreadyBuilt predicate is false when dist/ is absent (#11787)", () => {
rmSync(join(opencodePluginSrc, "dist"), { recursive: true, force: true });
const pluginAlreadyBuilt = existsSync(opencodePluginDist);
assert.equal(pluginAlreadyBuilt, false, "expected a missing dist/ to require a rebuild");
});