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:
CRTkafa 2026-10-13 23:20:04 +08:00
parent f69c10d3a0
commit 89256f1e80
28 changed files with 666 additions and 47 deletions

View file

@ -15,6 +15,7 @@
// stats/store_performance/store_performance_<package>_<yyyyMM>_country.csv (Store listing acquisitions / visitors)
// stats/installs/installs_<package>_<yyyyMM>_country.csv (Daily User Installs, ...)
// https://support.google.com/googleplay/android-developer/answer/6135870
import { plainError } from './google-errors';
import { createHash } from 'node:crypto';
import { parseCsvRecords } from './csv';
import { mdTable, pct, textTable } from './table';
@ -144,7 +145,7 @@ export function storeErrors(snaps: Snapshot[]): { apple?: string; play?: string
for (const k of ['apple', 'play'] as const) {
if (series[k].length) continue;
const last = [...snaps].sort((x, y) => x.date.localeCompare(y.date)).reverse().find(s => s[k] && 'error' in s[k]!);
if (last) out[k] = (last[k] as { error: string }).error;
if (last) out[k] = plainError((last[k] as { error: string }).error, { withUrl: true });
}
return out;
}