fix(coding-agent): support custom npmCommand for git deps

closes #3604
This commit is contained in:
Mario Zechner
2026-04-23 22:32:32 +02:00
parent c091aa732f
commit 8700ac1f0e
6 changed files with 79 additions and 5 deletions

View File

@@ -500,6 +500,33 @@ Content`,
expect(runCommandSpy).toHaveBeenCalledWith("npm", ["install", "--omit=dev"], { cwd: targetDir });
});
it("should use plain install for git package dependencies when npmCommand is configured", async () => {
settingsManager = SettingsManager.inMemory({
npmCommand: ["pnpm"],
});
packageManager = new DefaultPackageManager({
cwd: tempDir,
agentDir,
settingsManager,
});
const source = "git:github.com/user/repo";
const targetDir = join(agentDir, "git", "github.com", "user", "repo");
const runCommandSpy = vi
.spyOn(packageManager as any, "runCommand")
.mockImplementation(async (...callArgs: unknown[]) => {
const [command, args] = callArgs as [string, string[]];
if (command === "git" && args[0] === "clone") {
mkdirSync(targetDir, { recursive: true });
writeFileSync(join(targetDir, "package.json"), JSON.stringify({ name: "repo", version: "1.0.0" }));
}
});
await packageManager.install(source);
expect(runCommandSpy).toHaveBeenCalledWith("pnpm", ["install"], { cwd: targetDir });
});
it("should update git package dependencies with --omit=dev", async () => {
const source = "git:github.com/user/repo";
const targetDir = join(tempDir, ".pi", "git", "github.com", "user", "repo");
@@ -527,6 +554,44 @@ Content`,
expect(runCommandSpy).toHaveBeenCalledWith("npm", ["install", "--omit=dev"], { cwd: targetDir });
});
it("should use plain install through npmCommand argv when updating git package dependencies", async () => {
settingsManager = SettingsManager.inMemory({
npmCommand: ["mise", "exec", "node@20", "--", "pnpm"],
});
packageManager = new DefaultPackageManager({
cwd: tempDir,
agentDir,
settingsManager,
});
const source = "git:github.com/user/repo";
const targetDir = join(tempDir, ".pi", "git", "github.com", "user", "repo");
mkdirSync(targetDir, { recursive: true });
writeFileSync(join(targetDir, "package.json"), JSON.stringify({ name: "repo", version: "1.0.0" }));
settingsManager.setProjectPackages([source]);
vi.spyOn(packageManager as any, "runCommandCapture").mockImplementation(async (...callArgs: unknown[]) => {
const [_command, args] = callArgs as [string, string[]];
if (args[0] === "rev-parse" && args[1] === "--abbrev-ref" && args[2] === "@{upstream}") {
return "origin/main";
}
if (args[0] === "rev-parse" && args[1] === "@{upstream}") {
return "remote-head";
}
if (args[0] === "rev-parse" && args[1] === "HEAD") {
return "local-head";
}
throw new Error(`Unexpected runCommandCapture args: ${args.join(" ")}`);
});
const runCommandSpy = vi.spyOn(packageManager as any, "runCommand").mockResolvedValue(undefined);
await packageManager.update(source);
expect(runCommandSpy).toHaveBeenCalledWith("mise", ["exec", "node@20", "--", "pnpm", "install"], {
cwd: targetDir,
});
});
it("should use npmCommand argv for npm root lookup and invalidate cached root when npmCommand changes", () => {
settingsManager = SettingsManager.inMemory({
npmCommand: ["mise", "exec", "node@20", "--", "npm"],