fix(coding-agent): surface invalid inherited profile env as clean CLI error
- Revalidate OMP/PI profile env in runCli when no explicit --profile is passed - Convert module-load profile parse failures into CLI error reporting path - Preserve successful execution flow for valid profile selection paths - Add integration test ensuring invalid env emits clear error and non-zero exit
This commit is contained in:
@@ -1,5 +1,12 @@
|
||||
#!/usr/bin/env bun
|
||||
import { APP_NAME, getActiveProfile, MIN_BUN_VERSION, setProfile, VERSION } from "@oh-my-pi/pi-utils/dirs";
|
||||
import {
|
||||
APP_NAME,
|
||||
getActiveProfile,
|
||||
MIN_BUN_VERSION,
|
||||
normalizeProfileName,
|
||||
setProfile,
|
||||
VERSION,
|
||||
} from "@oh-my-pi/pi-utils/dirs";
|
||||
|
||||
// Strip macOS malloc-stack-logging env vars before any subprocess is spawned.
|
||||
// Keep this local instead of importing `@oh-my-pi/pi-utils/procmgr`: that module
|
||||
@@ -60,6 +67,13 @@ export async function runCli(argv: string[]): Promise<void> {
|
||||
resolvedArgv = extracted.argv;
|
||||
if (extracted.profile !== undefined) {
|
||||
setProfile(extracted.profile);
|
||||
} else {
|
||||
// No explicit --profile: re-validate any OMP_PROFILE/PI_PROFILE inherited
|
||||
// from the environment. Module-load resolution deliberately swallows an
|
||||
// invalid value to avoid an uncaught throw before this try/catch is in
|
||||
// scope (see `readProfileFromEnvSafe` in dirs.ts). Surfacing it here turns
|
||||
// `OMP_PROFILE=.. omp --version` into a clean error instead of a stack trace.
|
||||
normalizeProfileName(process.env.OMP_PROFILE || process.env.PI_PROFILE);
|
||||
}
|
||||
if (extracted.aliasName !== undefined) {
|
||||
const profile = extracted.profile ?? getActiveProfile();
|
||||
|
||||
@@ -168,4 +168,53 @@ describe("global --profile flag", () => {
|
||||
await fs.rm(root, { recursive: true, force: true });
|
||||
}
|
||||
});
|
||||
|
||||
it("surfaces an invalid OMP_PROFILE env as a clean error, not an import crash", async () => {
|
||||
const root = await fs.mkdtemp(path.join(os.tmpdir(), "omp-profile-cli-env-bad-"));
|
||||
try {
|
||||
const home = path.join(root, "home");
|
||||
await fs.mkdir(home, { recursive: true });
|
||||
|
||||
const probePath = path.join(root, "probe.ts");
|
||||
await Bun.write(
|
||||
probePath,
|
||||
[
|
||||
`import { runCli } from ${JSON.stringify(url.pathToFileURL(cliEntry).href)};`,
|
||||
'await runCli(["--version"]);',
|
||||
// Reached only if the module import did NOT throw — i.e. the invalid
|
||||
// env was deferred to runCli's error handler instead of crashing the
|
||||
// process during the static import of dirs.ts.
|
||||
'process.stdout.write("HANDLED");',
|
||||
].join("\n"),
|
||||
);
|
||||
|
||||
const childEnv: Record<string, string | undefined> = {
|
||||
...process.env,
|
||||
HOME: home,
|
||||
PI_CONFIG_DIR: ".omp-profile-cli-env-bad",
|
||||
OMP_PROFILE: "..",
|
||||
NO_COLOR: "1",
|
||||
};
|
||||
delete childEnv.PI_PROFILE;
|
||||
delete childEnv.PI_CODING_AGENT_DIR;
|
||||
|
||||
const proc = Bun.spawn([process.execPath, probePath], {
|
||||
cwd: repoRoot,
|
||||
stdout: "pipe",
|
||||
stderr: "pipe",
|
||||
env: childEnv,
|
||||
});
|
||||
const [stdout, stderr, exitCode] = await Promise.all([
|
||||
readStream(proc.stdout as ReadableStream<Uint8Array>),
|
||||
readStream(proc.stderr as ReadableStream<Uint8Array>),
|
||||
proc.exited,
|
||||
]);
|
||||
|
||||
expect(stdout, stderr).toContain("HANDLED");
|
||||
expect(stderr).toContain("Invalid OMP profile");
|
||||
expect(exitCode).toBe(1);
|
||||
} finally {
|
||||
await fs.rm(root, { recursive: true, force: true });
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user