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
|
|
@ -1,6 +1,7 @@
|
|||
// Pure view models for the screens: release timeline stages, health series against the store thresholds, review
|
||||
// inbox stats, catalog parity matrix, the portfolio's "needs attention" list, and the command palette matcher.
|
||||
// "Unknown, never false": every derivation keeps "not read" apart from "none" / "ok".
|
||||
import { plainError } from '../../../../cli/lib/google-errors';
|
||||
import type { AppStatus, ProjectSummary } from '../api';
|
||||
import { t } from '../i18n';
|
||||
|
||||
|
|
@ -23,7 +24,8 @@ export interface AppleHealth {
|
|||
signatures: { build: string; type: string; signature: string; weight: number }[];
|
||||
betaCrashes: { build: string; count: number }[];
|
||||
}
|
||||
export interface HealthSnapshot { date: string; play?: PlayHealth | { error: string }; apple?: AppleHealth | { error: string } }
|
||||
export type StoreReadError = import('../../../../cli/lib/health').StoreReadError;
|
||||
export interface HealthSnapshot { date: string; play?: PlayHealth | StoreReadError; apple?: AppleHealth | StoreReadError }
|
||||
export interface Review { store: 'apple' | 'play'; id: string; rating: number; title?: string; body: string; where?: string; date: string; appVersion?: string; reply?: { text: string; date?: string; state?: string } }
|
||||
export interface TfGroup { id: string; name: string; internal: boolean; testers: number; builds: number | 'all'; publicLink: boolean }
|
||||
export interface TfBuild { version: string | null; build: string | null; processing: string | null; internal: string | null; external: string | null; uploaded: string | null }
|
||||
|
|
@ -47,7 +49,7 @@ export interface ScanResult {
|
|||
declarations: { changed: boolean; items: { area: string; what: string; value: string; status: 'detected' | 'ask'; evidence: { file: string; line: number }[] }[] };
|
||||
}
|
||||
|
||||
export const isError = (x: unknown): x is { error: string } => !!x && typeof x === 'object' && typeof (x as { error?: unknown }).error === 'string';
|
||||
export const isError = (x: unknown): x is StoreReadError => !!x && typeof x === 'object' && typeof (x as { error?: unknown }).error === 'string';
|
||||
|
||||
// ---- Release timeline ----
|
||||
// The stages and lanes live in cli/lib/train.ts, shared with `storebound release status | plan`.
|
||||
|
|
@ -139,8 +141,8 @@ export function attention(projectId: string, name: string, e: AppStatus | undefi
|
|||
for (const w of (e.check?.warnings ?? []).slice(0, 3)) out.push({ ...base, tone: 'warn', text: w, tab: 'checks' });
|
||||
const l = live ?? (e.release.source === 'live' ? e : undefined);
|
||||
if (l) {
|
||||
if (l.storeErrors.ios) out.push({ ...base, tone: 'warn', text: t('att.storeError', { store: 'App Store', error: l.storeErrors.ios }), tab: 'releases' });
|
||||
if (l.storeErrors.android) out.push({ ...base, tone: 'warn', text: t('att.storeError', { store: 'Google Play', error: l.storeErrors.android }), tab: 'releases' });
|
||||
if (l.storeErrors.ios) out.push({ ...base, tone: 'warn', text: t('att.storeError', { store: 'App Store', error: plainError(l.storeErrors.ios) }), tab: 'releases' });
|
||||
if (l.storeErrors.android) out.push({ ...base, tone: 'warn', text: t('att.storeError', { store: 'Google Play', error: plainError(l.storeErrors.android) }), tab: 'releases' });
|
||||
for (const r of l.release.all ?? []) {
|
||||
if (r.phase === 'rejected') out.push({ ...base, tone: 'bad', text: t('att.rejected', { store: r.store === 'ios' ? 'App Store' : 'Google Play', version: r.version ?? '' }), tab: 'releases' });
|
||||
if (r.phase === 'halted') out.push({ ...base, tone: 'bad', text: t('att.halted', { store: r.store === 'ios' ? 'App Store' : 'Google Play', version: r.version ?? '' }), tab: 'releases' });
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue