Google API errors as typed findings, never raw JSON: cli/lib/google-errors.ts parses SERVICE_DISABLED (api-disabled: service, Cloud project, console page), PERMISSION_DENIED (no-app-access: which app, Users and permissions), 401 / invalid_grant (auth-revoked) and 429 (quota); health / analytics print one line with the URL, raw text in detail and the log; desktop Health tab: the line, 'Turn it on in Google Cloud' and 'Check again', raw text in a collapsed Details; Portfolio shows a Cloud project blocking several apps once. Findings exit codes are results: the sidecar reports outcome (ok / findings / declined / failed) and the command's own error line; scan / check / validate / health exit 1 with findings show and cache the findings; no bare 'Exit code N' anywhere. tests/google-errors.test.ts, boot check errors cases (api-disabled, scan-findings, scan-failed) (pitfall 57)
This commit is contained in:
parent
f69c10d3a0
commit
89256f1e80
28 changed files with 666 additions and 47 deletions
|
|
@ -28,7 +28,8 @@ export interface RunOptions {
|
|||
machine?: boolean;
|
||||
}
|
||||
|
||||
export interface RunResult { code: number; out: string; data?: unknown; cancelled: boolean }
|
||||
/** `err`: the stderr lines only (for the command's own error line). */
|
||||
export interface RunResult { code: number; out: string; err?: string; data?: unknown; cancelled: boolean }
|
||||
|
||||
export interface Running { result: Promise<RunResult>; cancel(): void }
|
||||
|
||||
|
|
@ -70,6 +71,7 @@ export function runCommand(argv: string[], o: RunOptions): Running {
|
|||
const p = rt.spawn([...selfCommand(), ...argv], { cwd: o.cwd, stdin: 'ignore', stdout: 'pipe', stderr: 'pipe', env: childEnv(o.env, o.machine) });
|
||||
let cancelled = false;
|
||||
const lines: string[] = [];
|
||||
const errs: string[] = [];
|
||||
let data: unknown;
|
||||
const each = (line: string, kind: 'stdout' | 'stderr'): void => {
|
||||
if (kind === 'stdout' && line.startsWith(RESULT_MARK)) {
|
||||
|
|
@ -77,12 +79,13 @@ export function runCommand(argv: string[], o: RunOptions): Running {
|
|||
return;
|
||||
}
|
||||
lines.push(line);
|
||||
if (kind === 'stderr') errs.push(line);
|
||||
o.onLine?.(line, kind);
|
||||
};
|
||||
const result = (async (): Promise<RunResult> => {
|
||||
await Promise.all([pump(p.stdout, 'stdout', each), pump(p.stderr, 'stderr', each)]);
|
||||
const code = await p.exited;
|
||||
return { code, out: lines.join('\n').trim(), ...(data === undefined ? {} : { data }), cancelled };
|
||||
return { code, out: lines.join('\n').trim(), err: errs.join('\n').trim(), ...(data === undefined ? {} : { data }), cancelled };
|
||||
})();
|
||||
return { result, cancel: () => { cancelled = true; p.kill(); } };
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue