fix(cli): add --skip-install flag to init, fix e2e test timeout

- Add --skip-install flag to nerve init for testing/offline use
- Use --skip-install in e2e tests to avoid real pnpm install
- Reduce e2e init test timeout from 60s to 10s

Closes #181
This commit is contained in:
Scott Wei
2026-04-27 16:37:41 +08:00
parent 0a0121d2ca
commit 57e4d992e2
2 changed files with 33 additions and 21 deletions
@@ -192,11 +192,11 @@ describe("e2e init", () => {
}
});
it("init --force creates workspace layout", { timeout: 60_000 }, async () => {
it("init --force creates workspace layout", { timeout: 10_000 }, async () => {
fakeHome = mkdtempSync(join(tmpdir(), "nerve-init-e2e-"));
const nerveRoot = join(fakeHome, ".uncaged-nerve");
const result = await runTestCli(fakeHome, ["init", "--force"]);
const result = await runTestCli(fakeHome, ["init", "--force", "--skip-install"]);
// init should exit 0 (install/git failures are warnings, not fatal)
expect(result.exitCode).toBe(0);
expect(result.stdout).toContain("✅");
@@ -213,10 +213,10 @@ describe("e2e init", () => {
);
});
it("generated nerve.yaml passes validate", { timeout: 60_000 }, async () => {
it("generated nerve.yaml passes validate", { timeout: 10_000 }, async () => {
fakeHome = mkdtempSync(join(tmpdir(), "nerve-init-e2e-"));
await runTestCli(fakeHome, ["init", "--force"]);
await runTestCli(fakeHome, ["init", "--force", "--skip-install"]);
const validateResult = await runTestCli(fakeHome, ["validate"]);
expect(validateResult.exitCode).toBe(0);
+29 -17
View File
@@ -240,9 +240,14 @@ const initWorkspaceCommand = defineCommand({
description: "Reinitialize even if workspace already exists (preserves data/)",
default: false,
},
"skip-install": {
type: "boolean",
description: "Skip dependency installation (for testing or offline use)",
default: false,
},
},
async run({ args }) {
await runInitWorkspace(args.force);
await runInitWorkspace(args.force, args["skip-install"]);
},
});
@@ -334,7 +339,7 @@ async function runInitFromGit(url: string): Promise<void> {
);
}
async function runInitWorkspace(force: boolean): Promise<void> {
async function runInitWorkspace(force: boolean, skipInstall = false): Promise<void> {
const nerveRoot = getNerveRoot();
if (existsSync(nerveRoot) && !force) {
@@ -357,21 +362,23 @@ async function runInitWorkspace(force: boolean): Promise<void> {
CPU_MIGRATION_SQL,
);
process.stdout.write("Installing dependencies…\n");
const { cmd, installArgs } = await detectPackageManager();
try {
await runCommand(cmd, installArgs, nerveRoot);
} catch {
process.stdout.write(
`⚠️ Install failed. Try manually:\n cd ${nerveRoot} && ${cmd} ${installArgs.join(" ")}\n`,
);
}
if (!skipInstall) {
process.stdout.write("Installing dependencies…\n");
const { cmd, installArgs } = await detectPackageManager();
try {
await runCommand(cmd, installArgs, nerveRoot);
} catch {
process.stdout.write(
`⚠️ Install failed. Try manually:\n cd ${nerveRoot} && ${cmd} ${installArgs.join(" ")}\n`,
);
}
if (!(await verifyNodeSqlite())) {
process.stdout.write(
"⚠️ Built-in SQLite (node:sqlite) is not available in this Node.js build. " +
"The daemon requires Node.js 22.5 or newer with SQLite enabled.\n",
);
if (!(await verifyNodeSqlite())) {
process.stdout.write(
"⚠️ Built-in SQLite (node:sqlite) is not available in this Node.js build. " +
"The daemon requires Node.js 22.5 or newer with SQLite enabled.\n",
);
}
}
if (!existsSync(join(nerveRoot, ".git"))) {
@@ -406,6 +413,11 @@ export const initCommand = defineCommand({
description: "Clone an existing git repo into ~/.uncaged-nerve instead of scaffolding",
required: false,
},
"skip-install": {
type: "boolean",
description: "Skip dependency installation (for testing or offline use)",
default: false,
},
},
subCommands: {
workflow: initWorkflowCommand,
@@ -416,6 +428,6 @@ export const initCommand = defineCommand({
await runInitFromGit(String(args.from));
return;
}
await runInitWorkspace(args.force);
await runInitWorkspace(args.force, args["skip-install"]);
},
});