ignore-scripts

This commit is contained in:
Sebastian Herrlinger
2026-03-30 22:26:56 +02:00
parent 09abc88d23
commit 3f00f65554
5 changed files with 41 additions and 4 deletions

View File

@@ -148,6 +148,7 @@ npm plugins can declare a version compatibility range in `package.json` using th
- `patchPluginConfig` returns structured result unions (`ok`, `code`, fields by error kind) instead of custom thrown errors.
- `patchPluginConfig` serializes per-target config writes with `Flock.acquire(...)`.
- `patchPluginConfig` uses targeted `jsonc-parser` edits, so existing JSONC comments are preserved when plugin entries are added or replaced.
- npm plugin package installs are executed with `--ignore-scripts`, so package `install` / `postinstall` lifecycle scripts are not run.
- Without `--force`, an already-configured npm package name is a no-op.
- With `--force`, replacement matches by package name. If the existing row is `[spec, options]`, those tuple options are kept.
- Explicit npm specs with a version suffix (for example `pkg@1.2.3`) are pinned. Runtime install requests that exact version and does not run stale/latest checks for newer registry versions.

View File

@@ -50,7 +50,7 @@ export namespace BunProc {
}),
)
export async function install(pkg: string, version = "latest") {
export async function install(pkg: string, version = "latest", opts?: { ignoreScripts?: boolean }) {
// Use lock to ensure only one install at a time
using _ = await Lock.write("bun-install")
@@ -82,6 +82,7 @@ export namespace BunProc {
"add",
"--force",
"--exact",
...(opts?.ignoreScripts ? ["--ignore-scripts"] : []),
// TODO: get rid of this case (see: https://github.com/oven-sh/bun/issues/19936)
...(proxied() || process.env.CI ? ["--no-cache"] : []),
"--cwd",

View File

@@ -189,7 +189,7 @@ export async function checkPluginCompatibility(target: string, opencodeVersion:
export async function resolvePluginTarget(spec: string, parsed = parsePluginSpecifier(spec)) {
if (isPathPluginSpec(spec)) return resolvePathPluginTarget(spec)
return BunProc.install(parsed.pkg, parsed.version)
return BunProc.install(parsed.pkg, parsed.version, { ignoreScripts: true })
}
export async function readPluginPackage(target: string): Promise<PluginPackage> {

View File

@@ -99,4 +99,39 @@ describe("BunProc install pinning", () => {
}
}
})
test("passes --ignore-scripts when requested", async () => {
const pkg = `ignore-test-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 8)}`
const ver = "4.5.6"
const mod = path.join(Global.Path.cache, "node_modules", pkg)
const data = path.join(Global.Path.cache, "package.json")
const run = spyOn(Process, "run").mockImplementation(async () => ({
code: 0,
stdout: Buffer.alloc(0),
stderr: Buffer.alloc(0),
}))
try {
await fs.rm(mod, { recursive: true, force: true })
await BunProc.install(pkg, ver, { ignoreScripts: true })
expect(run).toHaveBeenCalled()
const call = run.mock.calls[0]?.[0]
expect(call).toContain("--ignore-scripts")
expect(call).toContain(`${pkg}@${ver}`)
} finally {
run.mockRestore()
await fs.rm(mod, { recursive: true, force: true })
const end = await fs
.readFile(data, "utf8")
.then((item) => JSON.parse(item) as { dependencies?: Record<string, string> })
.catch(() => undefined)
if (end?.dependencies) {
delete end.dependencies[pkg]
await Bun.write(data, JSON.stringify(end, null, 2))
}
}
})
})

View File

@@ -266,8 +266,8 @@ describe("plugin.loader.shared", () => {
try {
await load(tmp.path)
expect(install.mock.calls).toContainEqual(["acme-plugin", "latest"])
expect(install.mock.calls).toContainEqual(["scope-plugin", "2.3.4"])
expect(install.mock.calls).toContainEqual(["acme-plugin", "latest", { ignoreScripts: true }])
expect(install.mock.calls).toContainEqual(["scope-plugin", "2.3.4", { ignoreScripts: true }])
} finally {
install.mockRestore()
}