Archived
fix(cli): diagnose macOS node-pty spawn-helper permissions
This commit is contained in:
@@ -0,0 +1,97 @@
|
||||
import { mkdir, mkdtemp, rm, writeFile } from "node:fs/promises";
|
||||
import { tmpdir } from "node:os";
|
||||
import { join } from "node:path";
|
||||
import { afterEach, describe, expect, it } from "vitest";
|
||||
import { checkNodePtyDarwinSpawnHelper, formatNodePtyDarwinSpawnHelperCheck, PI_WEB_SPAWN_HELPER_ISSUE_URL } from "./nodePtySpawnHelper.js";
|
||||
|
||||
const allowAccess = (): void => undefined;
|
||||
|
||||
describe("node-pty macOS spawn-helper diagnostics", () => {
|
||||
const tempRoots: string[] = [];
|
||||
|
||||
afterEach(async () => {
|
||||
await Promise.all(tempRoots.map((root) => rm(root, { recursive: true, force: true })));
|
||||
tempRoots.length = 0;
|
||||
});
|
||||
|
||||
it("skips the check outside macOS", () => {
|
||||
const check = checkNodePtyDarwinSpawnHelper({ platform: "linux" });
|
||||
|
||||
expect(check).toEqual({ status: "skipped", reason: "not-macos" });
|
||||
expect(formatNodePtyDarwinSpawnHelperCheck(check)).toEqual({ ok: true, lines: [] });
|
||||
});
|
||||
|
||||
it("reports a proposed chmod workaround for non-executable helpers", async () => {
|
||||
const fixture = await createNodePtyFixture();
|
||||
|
||||
const check = checkNodePtyDarwinSpawnHelper({
|
||||
platform: "darwin",
|
||||
arch: "arm64",
|
||||
nodePtyPackageJsonPath: fixture.packageJsonPath,
|
||||
access: () => { throw new Error("not executable"); },
|
||||
});
|
||||
|
||||
expect(check).toMatchObject({
|
||||
status: "spawn-helper-not-executable",
|
||||
helperPath: fixture.helperPath,
|
||||
nodePtyRoot: fixture.root,
|
||||
fixCommand: `chmod +x '${fixture.helperPath}'`,
|
||||
});
|
||||
|
||||
const formatted = formatNodePtyDarwinSpawnHelperCheck(check);
|
||||
expect(formatted.ok).toBe(false);
|
||||
expect(formatted.lines).toContain(` PI WEB tracking issue: ${PI_WEB_SPAWN_HELPER_ISSUE_URL}`);
|
||||
expect(formatted.lines).toContain(` chmod +x '${fixture.helperPath}'`);
|
||||
});
|
||||
|
||||
it("passes when the selected helper is executable", async () => {
|
||||
const fixture = await createNodePtyFixture();
|
||||
|
||||
const check = checkNodePtyDarwinSpawnHelper({
|
||||
platform: "darwin",
|
||||
arch: "arm64",
|
||||
nodePtyPackageJsonPath: fixture.packageJsonPath,
|
||||
access: allowAccess,
|
||||
});
|
||||
|
||||
expect(check).toMatchObject({ status: "ok", helperPath: fixture.helperPath, nodePtyRoot: fixture.root });
|
||||
expect(formatNodePtyDarwinSpawnHelperCheck(check)).toEqual({
|
||||
ok: true,
|
||||
lines: ["✓ node-pty macOS spawn-helper executable", ` ${fixture.helperPath}`],
|
||||
});
|
||||
});
|
||||
|
||||
it("checks the helper next to node-pty's selected native module", async () => {
|
||||
const fixture = await createNodePtyFixture();
|
||||
const buildDir = join(fixture.root, "build", "Release");
|
||||
await mkdir(buildDir, { recursive: true });
|
||||
await writeFile(join(buildDir, "pty.node"), "");
|
||||
const buildHelperPath = join(buildDir, "spawn-helper");
|
||||
await writeFile(buildHelperPath, "");
|
||||
|
||||
const check = checkNodePtyDarwinSpawnHelper({
|
||||
platform: "darwin",
|
||||
arch: "arm64",
|
||||
nodePtyPackageJsonPath: fixture.packageJsonPath,
|
||||
access: allowAccess,
|
||||
});
|
||||
|
||||
expect(check).toMatchObject({ status: "ok", helperPath: buildHelperPath });
|
||||
});
|
||||
|
||||
async function createNodePtyFixture(): Promise<{ root: string; packageJsonPath: string; helperPath: string }> {
|
||||
const root = await mkdtemp(join(tmpdir(), "pi-web-node-pty-"));
|
||||
tempRoots.push(root);
|
||||
|
||||
const packageJsonPath = join(root, "package.json");
|
||||
const prebuildDir = join(root, "prebuilds", "darwin-arm64");
|
||||
await mkdir(prebuildDir, { recursive: true });
|
||||
await writeFile(packageJsonPath, "{}");
|
||||
await writeFile(join(prebuildDir, "pty.node"), "");
|
||||
|
||||
const helperPath = join(prebuildDir, "spawn-helper");
|
||||
await writeFile(helperPath, "");
|
||||
|
||||
return { root, packageJsonPath, helperPath };
|
||||
}
|
||||
});
|
||||
Reference in New Issue
Block a user