@gpc-cli/cli 0.9.58 → 0.9.59
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bin.js +2 -2
- package/dist/{chunk-2SVDYAY4.js → chunk-2AM4XW7Q.js} +8 -8
- package/dist/{config-WXGCYY3U.js → config-ZLXFAFMN.js} +2 -2
- package/dist/{doctor-VET7CGBM.js → doctor-PACXOJZ2.js} +2 -2
- package/dist/{feedback-3TCRBPSI.js → feedback-RO76QRIZ.js} +2 -2
- package/dist/index.js +1 -1
- package/dist/{update-ZYW63YX3.js → update-PDYA3B45.js} +2 -2
- package/dist/{version-G3WWEAHE.js → version-FGBT5A7I.js} +2 -2
- package/dist/{vitals-RETD7K55.js → vitals-QPHS6QFH.js} +2 -2
- package/dist/vitals-QPHS6QFH.js.map +1 -0
- package/package.json +5 -5
- package/dist/vitals-RETD7K55.js.map +0 -1
- /package/dist/{chunk-2SVDYAY4.js.map → chunk-2AM4XW7Q.js.map} +0 -0
- /package/dist/{config-WXGCYY3U.js.map → config-ZLXFAFMN.js.map} +0 -0
- /package/dist/{doctor-VET7CGBM.js.map → doctor-PACXOJZ2.js.map} +0 -0
- /package/dist/{feedback-3TCRBPSI.js.map → feedback-RO76QRIZ.js.map} +0 -0
- /package/dist/{update-ZYW63YX3.js.map → update-PDYA3B45.js.map} +0 -0
- /package/dist/{version-G3WWEAHE.js.map → version-FGBT5A7I.js.map} +0 -0
package/dist/bin.js
CHANGED
|
@@ -3,7 +3,7 @@ import {
|
|
|
3
3
|
createProgram,
|
|
4
4
|
handleCliError,
|
|
5
5
|
loadPlugins
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-2AM4XW7Q.js";
|
|
7
7
|
import {
|
|
8
8
|
checkForUpdate,
|
|
9
9
|
formatUpdateNotification
|
|
@@ -57,7 +57,7 @@ if (!_isJsonMode && !_isQuiet && !_isSetupCommand && !existsSync(getUserConfigPa
|
|
|
57
57
|
}
|
|
58
58
|
await setupNetworking();
|
|
59
59
|
initAudit(getConfigDir());
|
|
60
|
-
var currentVersion = "0.9.
|
|
60
|
+
var currentVersion = "0.9.59";
|
|
61
61
|
var isUpdateCommand = process.argv[2] === "update";
|
|
62
62
|
var updateCheckPromise = isUpdateCommand ? Promise.resolve(null) : checkForUpdate(currentVersion);
|
|
63
63
|
if (process.argv.includes("--ci")) {
|
|
@@ -67,19 +67,19 @@ function registerPluginCommands(program, manager) {
|
|
|
67
67
|
import { Command } from "commander";
|
|
68
68
|
async function createProgram(pluginManager) {
|
|
69
69
|
const program = new Command();
|
|
70
|
-
program.name("gpc").description("GPC \u2014 Google Play Console CLI").version("0.9.
|
|
70
|
+
program.name("gpc").description("GPC \u2014 Google Play Console CLI").version("0.9.59", "-V, --version").option("-o, --output <format>", "Output format: table, json, yaml, markdown, junit").option("-v, --verbose", "Enable debug logging").option("-q, --quiet", "Suppress non-essential output").option("-a, --app <package>", "App package name").option("-p, --profile <name>", "Auth profile name").option("--no-color", "Disable colored output").option("--no-interactive", "Disable interactive prompts").option("-y, --yes", "Skip confirmation prompts").option("--dry-run", "Preview changes without executing").option("--notify [target]", "Send webhook notification on completion (slack, discord, custom)").option("--ci", "Force CI mode (JSON output, no prompts, strict exit codes)").option("-j, --json", "Shorthand for --output json").option("--apps <csv>", "Comma-separated package names for multi-app operations").showSuggestionAfterError(false);
|
|
71
71
|
const commandLoaders = {
|
|
72
72
|
auth: async () => {
|
|
73
73
|
(await import("./auth-4DRT7ZH2.js")).registerAuthCommands(program);
|
|
74
74
|
},
|
|
75
75
|
config: async () => {
|
|
76
|
-
(await import("./config-
|
|
76
|
+
(await import("./config-ZLXFAFMN.js")).registerConfigCommands(program);
|
|
77
77
|
},
|
|
78
78
|
doctor: async () => {
|
|
79
|
-
(await import("./doctor-
|
|
79
|
+
(await import("./doctor-PACXOJZ2.js")).registerDoctorCommand(program);
|
|
80
80
|
},
|
|
81
81
|
update: async () => {
|
|
82
|
-
(await import("./update-
|
|
82
|
+
(await import("./update-PDYA3B45.js")).registerUpdateCommand(program);
|
|
83
83
|
},
|
|
84
84
|
docs: async () => {
|
|
85
85
|
(await import("./docs-GP6AEX4N.js")).registerDocsCommand(program);
|
|
@@ -113,7 +113,7 @@ async function createProgram(pluginManager) {
|
|
|
113
113
|
(await import("./reviews-P4M6BEJI.js")).registerReviewsCommands(program);
|
|
114
114
|
},
|
|
115
115
|
vitals: async () => {
|
|
116
|
-
(await import("./vitals-
|
|
116
|
+
(await import("./vitals-QPHS6QFH.js")).registerVitalsCommands(program);
|
|
117
117
|
},
|
|
118
118
|
subscriptions: async () => {
|
|
119
119
|
(await import("./subscriptions-GTVJB4HX.js")).registerSubscriptionsCommands(program);
|
|
@@ -190,13 +190,13 @@ async function createProgram(pluginManager) {
|
|
|
190
190
|
(await import("./verify-H4ZUVHMZ.js")).registerVerifyCommand(program);
|
|
191
191
|
},
|
|
192
192
|
version: async () => {
|
|
193
|
-
(await import("./version-
|
|
193
|
+
(await import("./version-FGBT5A7I.js")).registerVersionCommand(program);
|
|
194
194
|
},
|
|
195
195
|
cache: async () => {
|
|
196
196
|
(await import("./cache-FGNP7Y37.js")).registerCacheCommand(program);
|
|
197
197
|
},
|
|
198
198
|
feedback: async () => {
|
|
199
|
-
(await import("./feedback-
|
|
199
|
+
(await import("./feedback-RO76QRIZ.js")).registerFeedbackCommand(program);
|
|
200
200
|
},
|
|
201
201
|
quickstart: async () => {
|
|
202
202
|
(await import("./quickstart-FOWM3OKT.js")).registerQuickstartCommand(program);
|
|
@@ -464,4 +464,4 @@ export {
|
|
|
464
464
|
createProgram,
|
|
465
465
|
handleCliError
|
|
466
466
|
};
|
|
467
|
-
//# sourceMappingURL=chunk-
|
|
467
|
+
//# sourceMappingURL=chunk-2AM4XW7Q.js.map
|
|
@@ -78,7 +78,7 @@ Configuration file created: ${path}`);
|
|
|
78
78
|
});
|
|
79
79
|
console.log("\nVerifying setup...");
|
|
80
80
|
try {
|
|
81
|
-
const { registerDoctorCommand } = await import("./doctor-
|
|
81
|
+
const { registerDoctorCommand } = await import("./doctor-PACXOJZ2.js");
|
|
82
82
|
const { Command } = await import("commander");
|
|
83
83
|
const doctorProgram = new Command();
|
|
84
84
|
doctorProgram.option("-o, --output <format>", "Output format").option("-j, --json", "JSON mode");
|
|
@@ -107,4 +107,4 @@ Configuration file created: ${path}`);
|
|
|
107
107
|
export {
|
|
108
108
|
registerConfigCommands
|
|
109
109
|
};
|
|
110
|
-
//# sourceMappingURL=config-
|
|
110
|
+
//# sourceMappingURL=config-ZLXFAFMN.js.map
|
|
@@ -141,7 +141,7 @@ function checkCiEnvironment() {
|
|
|
141
141
|
};
|
|
142
142
|
}
|
|
143
143
|
async function checkGpcVersion() {
|
|
144
|
-
const currentVersion = "0.9.
|
|
144
|
+
const currentVersion = "0.9.59";
|
|
145
145
|
if (currentVersion === "0.0.0") {
|
|
146
146
|
return { name: "version", status: "info", message: "GPC development build" };
|
|
147
147
|
}
|
|
@@ -800,4 +800,4 @@ export {
|
|
|
800
800
|
checkVerificationDeadline,
|
|
801
801
|
registerDoctorCommand
|
|
802
802
|
};
|
|
803
|
-
//# sourceMappingURL=doctor-
|
|
803
|
+
//# sourceMappingURL=doctor-PACXOJZ2.js.map
|
|
@@ -9,7 +9,7 @@ import { execFile } from "child_process";
|
|
|
9
9
|
import { listAuditEvents } from "@gpc-cli/core";
|
|
10
10
|
function registerFeedbackCommand(program) {
|
|
11
11
|
program.command("feedback").description("Open a pre-filled GitHub issue with system diagnostics").option("--title <title>", "Issue title").option("--print", "Print the report to stdout instead of opening a browser").action(async (opts) => {
|
|
12
|
-
const version = "0.9.
|
|
12
|
+
const version = "0.9.59";
|
|
13
13
|
let lastCommand = "";
|
|
14
14
|
try {
|
|
15
15
|
const events = await listAuditEvents({ limit: 3 });
|
|
@@ -67,4 +67,4 @@ ${url}`);
|
|
|
67
67
|
export {
|
|
68
68
|
registerFeedbackCommand
|
|
69
69
|
};
|
|
70
|
-
//# sourceMappingURL=feedback-
|
|
70
|
+
//# sourceMappingURL=feedback-RO76QRIZ.js.map
|
package/dist/index.js
CHANGED
|
@@ -17,7 +17,7 @@ function registerUpdateCommand(program) {
|
|
|
17
17
|
program.command("update").description("Update gpc to the latest version").option("--check", "Check for updates without installing (exits 0 always)").option("--force", "Update even if already on the latest version").action(async (opts, cmd) => {
|
|
18
18
|
const parentOpts = cmd.parent?.opts() ?? {};
|
|
19
19
|
const jsonMode = !!(parentOpts["json"] || parentOpts["output"] === "json");
|
|
20
|
-
const currentVersion = "0.9.
|
|
20
|
+
const currentVersion = "0.9.59";
|
|
21
21
|
if (currentVersion === "0.0.0") {
|
|
22
22
|
if (jsonMode) {
|
|
23
23
|
console.log(
|
|
@@ -172,4 +172,4 @@ Run: gpc update`);
|
|
|
172
172
|
export {
|
|
173
173
|
registerUpdateCommand
|
|
174
174
|
};
|
|
175
|
-
//# sourceMappingURL=update-
|
|
175
|
+
//# sourceMappingURL=update-PDYA3B45.js.map
|
|
@@ -7,7 +7,7 @@ import "./chunk-3SJ6OXCZ.js";
|
|
|
7
7
|
// src/commands/version.ts
|
|
8
8
|
function registerVersionCommand(program) {
|
|
9
9
|
program.command("version").description("Show version information").action(() => {
|
|
10
|
-
const version = "0.9.
|
|
10
|
+
const version = "0.9.59";
|
|
11
11
|
if (program.opts()["output"] === "json") {
|
|
12
12
|
console.log(
|
|
13
13
|
JSON.stringify({
|
|
@@ -25,4 +25,4 @@ function registerVersionCommand(program) {
|
|
|
25
25
|
export {
|
|
26
26
|
registerVersionCommand
|
|
27
27
|
};
|
|
28
|
-
//# sourceMappingURL=version-
|
|
28
|
+
//# sourceMappingURL=version-FGBT5A7I.js.map
|
|
@@ -297,7 +297,7 @@ function registerVitalsCommands(program) {
|
|
|
297
297
|
battery: "excessiveWakeupRateMetricSet",
|
|
298
298
|
memory: "stuckBackgroundWakelockRateMetricSet",
|
|
299
299
|
wakeup: "excessiveWakeupRateMetricSet",
|
|
300
|
-
lmk: "
|
|
300
|
+
lmk: "lmkRateMetricSet",
|
|
301
301
|
"error-count": "errorCountMetricSet"
|
|
302
302
|
};
|
|
303
303
|
vitals.command("compare <metric>").description("Compare metric trend: this period vs previous period").option("--days <n>", "Period length in days", (v) => parseInt(v, 10), 7).action(async (metric, options) => {
|
|
@@ -434,4 +434,4 @@ ${red("\u2717")} Threshold breached (${(value * 100).toFixed(3)}% > ${options.th
|
|
|
434
434
|
export {
|
|
435
435
|
registerVitalsCommands
|
|
436
436
|
};
|
|
437
|
-
//# sourceMappingURL=vitals-
|
|
437
|
+
//# sourceMappingURL=vitals-QPHS6QFH.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/commands/vitals.ts"],"sourcesContent":["import { resolvePackageName } from \"../resolve.js\";\nimport type { Command } from \"commander\";\nimport type { GpcConfig } from \"@gpc-cli/config\";\nimport { loadConfig } from \"@gpc-cli/config\";\nimport { resolveAuth } from \"@gpc-cli/auth\";\nimport { createReportingClient, PlayApiError } from \"@gpc-cli/api\";\nimport type { ReportingDimension } from \"@gpc-cli/api\";\nimport type { VitalsMetricSet } from \"@gpc-cli/api\";\nimport {\n getVitalsOverview,\n getVitalsCrashes,\n getVitalsAnr,\n getVitalsStartup,\n getVitalsRendering,\n getVitalsBattery,\n getVitalsMemory,\n getVitalsLmk,\n getVitalsErrorCount,\n getVitalsAnomalies,\n searchVitalsErrors,\n compareVitalsTrend,\n compareVersionVitals,\n watchVitalsWithAutoHalt,\n checkThreshold,\n formatOutput,\n GpcError,\n} from \"@gpc-cli/core\";\nimport { getOutputFormat } from \"../format.js\";\nimport { red, yellow, green } from \"../colors.js\";\n\nasync function getReportingClient(config: GpcConfig) {\n const auth = await resolveAuth({ serviceAccountPath: config.auth?.serviceAccount });\n return createReportingClient({ auth });\n}\n\nconst VALID_DIMENSIONS: ReportingDimension[] = [\n \"apiLevel\",\n \"versionCode\",\n \"deviceModel\",\n \"deviceType\",\n \"countryCode\",\n \"deviceRamBucket\",\n \"deviceSocName\",\n \"deviceCpuMakeModel\",\n \"deviceGlEsVersion\",\n \"deviceVulkanVersion\",\n \"deviceOpenGlVersion\",\n \"deviceBrand\",\n \"startType\", // Required dimension for slowStartRateMetricSet\n];\n\nconst THRESHOLD_CONFIG_KEYS: Record<string, string> = {\n crashes: \"crashRate\",\n anr: \"anrRate\",\n startup: \"slowStartRate\",\n rendering: \"slowRenderingRate\",\n battery: \"excessiveWakeupRate\",\n memory: \"stuckWakelockRate\",\n wakeup: \"excessiveWakeupRate\",\n lmk: \"lmkRate\",\n \"error-count\": \"errorReportCount\",\n};\n\nfunction validateDimension(dim: string): ReportingDimension {\n if (!(VALID_DIMENSIONS as readonly string[]).includes(dim)) {\n throw new GpcError(\n `Invalid dimension \"${dim}\". Valid dimensions: ${VALID_DIMENSIONS.join(\", \")}`,\n \"VITALS_USAGE_ERROR\",\n 2,\n `Use one of: ${VALID_DIMENSIONS.join(\", \")}`,\n );\n }\n return dim as ReportingDimension;\n}\n\ntype MetricFn = typeof getVitalsCrashes;\n\nfunction registerMetricCommand(\n parent: Command,\n name: string,\n description: string,\n fn: MetricFn,\n program: Command,\n): void {\n parent\n .command(name)\n .description(description)\n .option(\"--dim <dimension>\", \"Group by dimension\")\n .option(\"--days <n>\", \"Number of days to query\", parseInt)\n .option(\"--threshold <value>\", \"Threshold value for CI alerting\", parseFloat)\n .action(async (options) => {\n const config = await loadConfig();\n const packageName = resolvePackageName(program.opts()[\"app\"], config);\n const reporting = await getReportingClient(config);\n const format = getOutputFormat(program, config);\n\n let result;\n try {\n result = await fn(reporting, packageName, {\n dimension: options.dim ? validateDimension(options.dim) : undefined,\n days: options.days,\n });\n } catch (err) {\n if (err instanceof PlayApiError && err.statusCode === 403) {\n if (format === \"json\") {\n console.log(\n formatOutput(\n { rows: [], message: \"Reporting API not enabled or insufficient permissions\" },\n format,\n ),\n );\n } else {\n console.log(\n `${yellow(\"⚠\")} No vitals data available. The Reporting API may not be enabled for this project.`,\n );\n console.log(\n ` Enable it at: https://console.cloud.google.com/apis/library/playdeveloperreporting.googleapis.com`,\n );\n }\n return;\n }\n throw err;\n }\n if (format !== \"json\" && (!result.rows || result.rows.length === 0)) {\n console.log(`${yellow(\"⚠\")} No vitals data available.`);\n return;\n }\n if (format !== \"json\" && result.rows) {\n const rows = result.rows.map((row: unknown) => {\n const rowR = row as Record<string, unknown>;\n const startTime = rowR[\"startTime\"] as Record<string, unknown> | undefined;\n const metrics = rowR[\"metrics\"] as\n | Record<string, Record<string, unknown>>\n | unknown[]\n | undefined;\n const flat: Record<string, unknown> = {\n date: startTime\n ? `${startTime[\"year\"]}-${String(startTime[\"month\"]).padStart(2, \"0\")}-${String(startTime[\"day\"]).padStart(2, \"0\")}`\n : \"-\",\n };\n if (metrics && !Array.isArray(metrics)) {\n for (const [key, val] of Object.entries(metrics)) {\n flat[key] =\n (val as Record<string, unknown>)?.[\"decimalValue\"] !== undefined\n ? ((val as Record<string, Record<string, unknown>>)?.[\"decimalValue\"]?.[\n \"value\"\n ] ?? \"-\")\n : \"-\";\n }\n } else if (Array.isArray(metrics)) {\n // Fallback: if API returns metrics as array, use metric names from config\n for (let i = 0; i < metrics.length; i++) {\n const val = metrics[i] as Record<string, unknown> | undefined;\n const metricName = val?.[\"metric\"] as string | undefined;\n const key = metricName ?? `metric${i}`;\n flat[key] =\n (val as Record<string, unknown>)?.[\"decimalValue\"] !== undefined\n ? ((val as Record<string, Record<string, unknown>>)?.[\"decimalValue\"]?.[\n \"value\"\n ] ?? \"-\")\n : \"-\";\n }\n }\n const dims = rowR[\"dimensions\"] as Record<string, unknown> | unknown[] | undefined;\n if (dims && !Array.isArray(dims)) {\n for (const [key, val] of Object.entries(dims)) {\n flat[key] = (val as Record<string, unknown>)?.[\"stringValue\"] ?? \"-\";\n }\n } else if (Array.isArray(dims)) {\n // Fallback: if API returns dimensions as array\n for (let i = 0; i < dims.length; i++) {\n const val = dims[i] as Record<string, unknown> | undefined;\n const dimName = val?.[\"dimension\"] as string | undefined;\n flat[dimName ?? `dim${i}`] = val?.[\"stringValue\"] ?? val?.[\"int64Value\"] ?? \"-\";\n }\n }\n return flat;\n });\n console.log(formatOutput(rows, format));\n } else {\n console.log(formatOutput(result, format));\n }\n\n // Check threshold from flag or config\n const configKey = THRESHOLD_CONFIG_KEYS[name];\n const configThreshold = configKey\n ? (config as unknown as Record<string, unknown>)[\"vitals\"]\n ? ((config as unknown as Record<string, unknown>)[\"vitals\"] as Record<string, unknown>)[\n \"thresholds\"\n ]\n ? (\n (\n (config as unknown as Record<string, unknown>)[\"vitals\"] as Record<\n string,\n unknown\n >\n )[\"thresholds\"] as Record<string, unknown>\n )[configKey]\n : undefined\n : undefined\n : undefined;\n const threshold =\n options.threshold ?? (configThreshold !== undefined ? Number(configThreshold) : undefined);\n if (threshold !== undefined) {\n const latestRow = result.rows?.[result.rows.length - 1];\n const metricKeys = latestRow?.metrics ? Object.keys(latestRow.metrics) : [];\n const firstMetric = metricKeys[0];\n const value = firstMetric\n ? Number(latestRow?.metrics[firstMetric]?.decimalValue?.value)\n : undefined;\n const check = checkThreshold(value, threshold);\n if (check.breached) {\n console.error(`${red(\"✗\")} Threshold breached: ${check.value} > ${check.threshold}`);\n process.exitCode = 6;\n }\n }\n });\n}\n\nexport function registerVitalsCommands(program: Command): void {\n const vitals = program\n .command(\"vitals\")\n .description(\"Monitor app vitals, crash rates, and performance metrics\");\n\n vitals\n .command(\"overview\")\n .description(\"Dashboard summary of all vital metrics\")\n .action(async () => {\n const config = await loadConfig();\n const packageName = resolvePackageName(program.opts()[\"app\"], config);\n const reporting = await getReportingClient(config);\n const format = getOutputFormat(program, config);\n\n const result = await getVitalsOverview(reporting, packageName);\n if (Object.keys(result).length === 0) {\n if (format === \"json\") {\n console.log(formatOutput({ vitals: [], message: \"No vitals data available\" }, format));\n } else {\n console.log(\"No vitals data available.\");\n }\n return;\n }\n if (format !== \"json\") {\n const overview = result as Record<string, unknown>;\n const rows = Object.entries(overview).map(([metric, data]) => {\n const metricRows = data as Record<string, unknown>[] | undefined;\n const latest = metricRows?.[metricRows.length - 1];\n const metrics = latest?.[\"metrics\"] as\n | Record<string, Record<string, unknown>>\n | undefined;\n const firstKey = metrics ? Object.keys(metrics)[0] : undefined;\n const value = firstKey\n ? (metrics?.[firstKey]?.[\"decimalValue\"] as Record<string, unknown> | undefined)?.[\n \"value\"\n ]\n : undefined;\n return {\n metric,\n dataPoints: metricRows?.length || 0,\n latestValue: value ?? \"-\",\n };\n });\n console.log(formatOutput(rows, format));\n } else {\n console.log(formatOutput(result, format));\n }\n });\n\n registerMetricCommand(vitals, \"crashes\", \"Query crash rate metrics\", getVitalsCrashes, program);\n registerMetricCommand(vitals, \"anr\", \"Query ANR rate metrics\", getVitalsAnr, program);\n registerMetricCommand(vitals, \"startup\", \"Query slow startup metrics\", getVitalsStartup, program);\n registerMetricCommand(\n vitals,\n \"rendering\",\n \"Query slow rendering metrics\",\n getVitalsRendering,\n program,\n );\n registerMetricCommand(\n vitals,\n \"battery\",\n \"Query excessive wakeup metrics\",\n getVitalsBattery,\n program,\n );\n registerMetricCommand(vitals, \"memory\", \"Query stuck wakelock metrics\", getVitalsMemory, program);\n registerMetricCommand(\n vitals,\n \"wakeup\",\n \"Query excessive wakeup rate metrics\",\n getVitalsBattery,\n program,\n );\n registerMetricCommand(\n vitals,\n \"lmk\",\n \"Query low-memory kill (stuck wakelock) metrics\",\n getVitalsLmk,\n program,\n );\n registerMetricCommand(\n vitals,\n \"error-count\",\n \"Query error report count metrics\",\n getVitalsErrorCount,\n program,\n );\n\n vitals\n .command(\"anomalies\")\n .description(\"Detect anomalies in app vitals\")\n .action(async () => {\n const config = await loadConfig();\n const packageName = resolvePackageName(program.opts()[\"app\"], config);\n const reporting = await getReportingClient(config);\n const format = getOutputFormat(program, config);\n\n let result;\n try {\n result = await getVitalsAnomalies(reporting, packageName);\n } catch (err) {\n if (err instanceof PlayApiError && err.statusCode === 403) {\n if (format === \"json\") {\n console.log(\n formatOutput(\n { anomalies: [], message: \"Reporting API not enabled or insufficient permissions\" },\n format,\n ),\n );\n } else {\n console.log(\n `${yellow(\"⚠\")} No anomaly data available. The Reporting API may not be enabled for this project.`,\n );\n console.log(\n ` Enable it at: https://console.cloud.google.com/apis/library/playdeveloperreporting.googleapis.com`,\n );\n }\n return;\n }\n throw err;\n }\n console.log(formatOutput(result, format));\n });\n\n const errors = vitals.command(\"errors\").description(\"Search and view error issues\");\n\n errors\n .command(\"search\")\n .description(\"Search error issues\")\n .option(\"--filter <text>\", \"Filter expression\")\n .option(\"--max <n>\", \"Maximum results\", parseInt)\n .action(async (options) => {\n const config = await loadConfig();\n const packageName = resolvePackageName(program.opts()[\"app\"], config);\n const reporting = await getReportingClient(config);\n const format = getOutputFormat(program, config);\n\n const result = await searchVitalsErrors(reporting, packageName, {\n filter: options.filter,\n maxResults: options.max,\n });\n const issues = (result as unknown as Record<string, unknown>)[\"errorIssues\"] as\n | unknown[]\n | undefined;\n if (format !== \"json\" && (!issues || issues.length === 0)) {\n console.log(\"No error issues found.\");\n return;\n }\n console.log(formatOutput(result, format));\n });\n\n const METRIC_MAP: Record<string, VitalsMetricSet> = {\n crashes: \"crashRateMetricSet\",\n anr: \"anrRateMetricSet\",\n startup: \"slowStartRateMetricSet\",\n rendering: \"slowRenderingRateMetricSet\",\n battery: \"excessiveWakeupRateMetricSet\",\n memory: \"stuckBackgroundWakelockRateMetricSet\",\n wakeup: \"excessiveWakeupRateMetricSet\",\n lmk: \"lmkRateMetricSet\",\n \"error-count\": \"errorCountMetricSet\",\n };\n\n vitals\n .command(\"compare <metric>\")\n .description(\"Compare metric trend: this period vs previous period\")\n .option(\"--days <n>\", \"Period length in days\", (v) => parseInt(v, 10), 7)\n .action(async (metric: string, options) => {\n const metricSet = METRIC_MAP[metric];\n if (!metricSet) {\n throw new GpcError(\n `Unknown metric \"${metric}\". Use: ${Object.keys(METRIC_MAP).join(\", \")}`,\n \"VITALS_USAGE_ERROR\",\n 2,\n `Valid metrics: ${Object.keys(METRIC_MAP).join(\", \")}`,\n );\n }\n\n const config = await loadConfig();\n const packageName = resolvePackageName(program.opts()[\"app\"], config);\n const reporting = await getReportingClient(config);\n const format = getOutputFormat(program, config);\n\n const result = await compareVitalsTrend(reporting, packageName, metricSet, options.days);\n console.log(formatOutput(result, format));\n });\n\n vitals\n .command(\"compare-versions <v1> <v2>\")\n .description(\"Compare vitals side-by-side for two version codes\")\n .option(\"--days <n>\", \"Number of days to query\", (v) => parseInt(v, 10), 30)\n .action(async (v1: string, v2: string, options) => {\n const config = await loadConfig();\n const packageName = resolvePackageName(program.opts()[\"app\"], config);\n const reporting = await getReportingClient(config);\n const format = getOutputFormat(program, config);\n\n const result = await compareVersionVitals(reporting, packageName, v1, v2, {\n days: options.days,\n });\n\n if (format === \"json\") {\n console.log(formatOutput(result, format));\n return;\n }\n\n const metrics: [keyof typeof result.v1, string][] = [\n [\"crashRate\", \"Crash Rate\"],\n [\"anrRate\", \"ANR Rate\"],\n [\"slowStartRate\", \"Slow Start Rate\"],\n [\"slowRenderingRate\", \"Slow Rendering Rate\"],\n ];\n\n console.log(`\\nVersion Comparison — ${packageName}`);\n console.log(`${\"─\".repeat(60)}`);\n console.log(`${\"Metric\".padEnd(22)} ${\"v\" + v1.padEnd(14)} ${\"v\" + v2.padEnd(14)} Change`);\n console.log(`${\"─\".repeat(60)}`);\n\n for (const [key, label] of metrics) {\n const val1 = result.v1[key] as number | undefined;\n const val2 = result.v2[key] as number | undefined;\n const s1 = val1 !== undefined ? (val1 * 100).toFixed(3) + \"%\" : \"N/A\";\n const s2 = val2 !== undefined ? (val2 * 100).toFixed(3) + \"%\" : \"N/A\";\n const isRegression = result.regressions.includes(key as string);\n const change =\n val1 !== undefined && val2 !== undefined ? ((val2 - val1) / val1) * 100 : undefined;\n const changeStr =\n change !== undefined ? (change > 0 ? \"+\" : \"\") + change.toFixed(1) + \"%\" : \"N/A\";\n const colorFn = isRegression\n ? red\n : change !== undefined && change < -1\n ? green\n : (s: string) => s;\n console.log(\n `${label.padEnd(22)} ${s1.padEnd(15)} ${colorFn(s2.padEnd(15))} ${colorFn(changeStr)}`,\n );\n }\n\n if (result.regressions.length > 0) {\n console.log(`\\n${red(\"✗\")} Regressions detected: ${result.regressions.join(\", \")}`);\n } else {\n console.log(`\\n${green(\"✓\")} No regressions detected.`);\n }\n });\n\n vitals\n .command(\"watch\")\n .description(\"Monitor vitals continuously and optionally auto-halt rollout on breach\")\n .requiredOption(\"--threshold <value>\", \"Breach threshold value\", parseFloat)\n .option(\n \"--metric <name>\",\n \"Metric to monitor (crashes, anr, startup, rendering, battery, memory, wakeup, lmk, error-count)\",\n \"crashes\",\n )\n .option(\"--interval <seconds>\", \"Polling interval in seconds\", (v) => parseInt(v, 10), 300)\n .option(\"--auto-halt-rollout\", \"Automatically halt rollout if threshold is breached\")\n .option(\"--track <name>\", \"Track to halt rollout on (required with --auto-halt-rollout)\")\n .action(async (options) => {\n const metricSet = METRIC_MAP[options.metric as string];\n if (!metricSet) {\n throw new GpcError(\n `Unknown metric \"${options.metric}\". Use: ${Object.keys(METRIC_MAP).join(\", \")}`,\n \"VITALS_USAGE_ERROR\",\n 2,\n `Valid metrics: ${Object.keys(METRIC_MAP).join(\", \")}`,\n );\n }\n\n if (options.autoHaltRollout && !options.track) {\n throw new GpcError(\n \"--track <name> is required when using --auto-halt-rollout\",\n \"VITALS_USAGE_ERROR\",\n 2,\n \"Add --track <name> to specify which track to halt on breach.\",\n );\n }\n\n const config = await loadConfig();\n const packageName = resolvePackageName(program.opts()[\"app\"], config);\n const reporting = await getReportingClient(config);\n const intervalMs = (options.interval as number) * 1000;\n\n console.log(`Watching ${options.metric} for ${packageName}`);\n console.log(`Threshold: ${options.threshold} Interval: ${options.interval}s`);\n if (options.autoHaltRollout) {\n console.log(`Auto-halt enabled on track: ${options.track}`);\n }\n console.log(\"Press Ctrl+C to stop.\\n\");\n\n const stop = watchVitalsWithAutoHalt(reporting, packageName, {\n intervalMs,\n threshold: options.threshold as number,\n metricSet,\n onPoll: (value, breached) => {\n const ts = new Date().toISOString();\n const valStr = value !== undefined ? (value * 100).toFixed(3) + \"%\" : \"N/A\";\n const indicator = breached ? red(\"✗ BREACH\") : green(\"✓ OK\");\n console.log(`[${ts}] ${options.metric}: ${valStr} — ${indicator}`);\n },\n onHalt: options.autoHaltRollout\n ? async (value: number) => {\n console.error(\n `\\n${red(\"✗\")} Threshold breached (${(value * 100).toFixed(3)}% > ${options.threshold}%). Halting rollout on track \"${options.track}\"...`,\n );\n try {\n const { resolveAuth } = await import(\"@gpc-cli/auth\");\n const { createApiClient } = await import(\"@gpc-cli/api\");\n const { updateRollout } = await import(\"@gpc-cli/core\");\n const auth = await resolveAuth({ serviceAccountPath: config.auth?.serviceAccount });\n const apiClient = createApiClient({ auth });\n await updateRollout(apiClient, packageName, options.track as string, \"halt\");\n console.error(`${red(\"⚠\")} Rollout halted on track \"${options.track}\".`);\n } catch (err) {\n console.error(\n `Failed to halt rollout: ${err instanceof Error ? err.message : String(err)}`,\n );\n }\n stop();\n process.exitCode = 6;\n }\n : undefined,\n });\n\n process.on(\"SIGINT\", () => {\n stop();\n console.log(\"\\nWatch stopped.\");\n });\n });\n}\n"],"mappings":"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","names":["resolveAuth"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gpc-cli/cli",
|
|
3
|
-
"version": "0.9.
|
|
3
|
+
"version": "0.9.59",
|
|
4
4
|
"description": "GPC — Google Play Console CLI. 217 API endpoints including Managed Google Play. Upload AABs, manage releases, monitor vitals, publish private enterprise apps. Fastlane alternative for Android.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -19,11 +19,11 @@
|
|
|
19
19
|
],
|
|
20
20
|
"dependencies": {
|
|
21
21
|
"commander": "^14.0.3",
|
|
22
|
-
"@gpc-cli/api": "1.0.
|
|
22
|
+
"@gpc-cli/api": "1.0.34",
|
|
23
23
|
"@gpc-cli/auth": "0.9.12",
|
|
24
|
-
"@gpc-cli/
|
|
25
|
-
"@gpc-cli/
|
|
26
|
-
"@gpc-cli/
|
|
24
|
+
"@gpc-cli/config": "0.9.12",
|
|
25
|
+
"@gpc-cli/core": "0.9.49",
|
|
26
|
+
"@gpc-cli/plugin-sdk": "0.9.8"
|
|
27
27
|
},
|
|
28
28
|
"keywords": [
|
|
29
29
|
"google-play",
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/commands/vitals.ts"],"sourcesContent":["import { resolvePackageName } from \"../resolve.js\";\nimport type { Command } from \"commander\";\nimport type { GpcConfig } from \"@gpc-cli/config\";\nimport { loadConfig } from \"@gpc-cli/config\";\nimport { resolveAuth } from \"@gpc-cli/auth\";\nimport { createReportingClient, PlayApiError } from \"@gpc-cli/api\";\nimport type { ReportingDimension } from \"@gpc-cli/api\";\nimport type { VitalsMetricSet } from \"@gpc-cli/api\";\nimport {\n getVitalsOverview,\n getVitalsCrashes,\n getVitalsAnr,\n getVitalsStartup,\n getVitalsRendering,\n getVitalsBattery,\n getVitalsMemory,\n getVitalsLmk,\n getVitalsErrorCount,\n getVitalsAnomalies,\n searchVitalsErrors,\n compareVitalsTrend,\n compareVersionVitals,\n watchVitalsWithAutoHalt,\n checkThreshold,\n formatOutput,\n GpcError,\n} from \"@gpc-cli/core\";\nimport { getOutputFormat } from \"../format.js\";\nimport { red, yellow, green } from \"../colors.js\";\n\nasync function getReportingClient(config: GpcConfig) {\n const auth = await resolveAuth({ serviceAccountPath: config.auth?.serviceAccount });\n return createReportingClient({ auth });\n}\n\nconst VALID_DIMENSIONS: ReportingDimension[] = [\n \"apiLevel\",\n \"versionCode\",\n \"deviceModel\",\n \"deviceType\",\n \"countryCode\",\n \"deviceRamBucket\",\n \"deviceSocName\",\n \"deviceCpuMakeModel\",\n \"deviceGlEsVersion\",\n \"deviceVulkanVersion\",\n \"deviceOpenGlVersion\",\n \"deviceBrand\",\n \"startType\", // Required dimension for slowStartRateMetricSet\n];\n\nconst THRESHOLD_CONFIG_KEYS: Record<string, string> = {\n crashes: \"crashRate\",\n anr: \"anrRate\",\n startup: \"slowStartRate\",\n rendering: \"slowRenderingRate\",\n battery: \"excessiveWakeupRate\",\n memory: \"stuckWakelockRate\",\n wakeup: \"excessiveWakeupRate\",\n lmk: \"lmkRate\",\n \"error-count\": \"errorReportCount\",\n};\n\nfunction validateDimension(dim: string): ReportingDimension {\n if (!(VALID_DIMENSIONS as readonly string[]).includes(dim)) {\n throw new GpcError(\n `Invalid dimension \"${dim}\". Valid dimensions: ${VALID_DIMENSIONS.join(\", \")}`,\n \"VITALS_USAGE_ERROR\",\n 2,\n `Use one of: ${VALID_DIMENSIONS.join(\", \")}`,\n );\n }\n return dim as ReportingDimension;\n}\n\ntype MetricFn = typeof getVitalsCrashes;\n\nfunction registerMetricCommand(\n parent: Command,\n name: string,\n description: string,\n fn: MetricFn,\n program: Command,\n): void {\n parent\n .command(name)\n .description(description)\n .option(\"--dim <dimension>\", \"Group by dimension\")\n .option(\"--days <n>\", \"Number of days to query\", parseInt)\n .option(\"--threshold <value>\", \"Threshold value for CI alerting\", parseFloat)\n .action(async (options) => {\n const config = await loadConfig();\n const packageName = resolvePackageName(program.opts()[\"app\"], config);\n const reporting = await getReportingClient(config);\n const format = getOutputFormat(program, config);\n\n let result;\n try {\n result = await fn(reporting, packageName, {\n dimension: options.dim ? validateDimension(options.dim) : undefined,\n days: options.days,\n });\n } catch (err) {\n if (err instanceof PlayApiError && err.statusCode === 403) {\n if (format === \"json\") {\n console.log(\n formatOutput(\n { rows: [], message: \"Reporting API not enabled or insufficient permissions\" },\n format,\n ),\n );\n } else {\n console.log(\n `${yellow(\"⚠\")} No vitals data available. The Reporting API may not be enabled for this project.`,\n );\n console.log(\n ` Enable it at: https://console.cloud.google.com/apis/library/playdeveloperreporting.googleapis.com`,\n );\n }\n return;\n }\n throw err;\n }\n if (format !== \"json\" && (!result.rows || result.rows.length === 0)) {\n console.log(`${yellow(\"⚠\")} No vitals data available.`);\n return;\n }\n if (format !== \"json\" && result.rows) {\n const rows = result.rows.map((row: unknown) => {\n const rowR = row as Record<string, unknown>;\n const startTime = rowR[\"startTime\"] as Record<string, unknown> | undefined;\n const metrics = rowR[\"metrics\"] as\n | Record<string, Record<string, unknown>>\n | unknown[]\n | undefined;\n const flat: Record<string, unknown> = {\n date: startTime\n ? `${startTime[\"year\"]}-${String(startTime[\"month\"]).padStart(2, \"0\")}-${String(startTime[\"day\"]).padStart(2, \"0\")}`\n : \"-\",\n };\n if (metrics && !Array.isArray(metrics)) {\n for (const [key, val] of Object.entries(metrics)) {\n flat[key] =\n (val as Record<string, unknown>)?.[\"decimalValue\"] !== undefined\n ? ((val as Record<string, Record<string, unknown>>)?.[\"decimalValue\"]?.[\n \"value\"\n ] ?? \"-\")\n : \"-\";\n }\n } else if (Array.isArray(metrics)) {\n // Fallback: if API returns metrics as array, use metric names from config\n for (let i = 0; i < metrics.length; i++) {\n const val = metrics[i] as Record<string, unknown> | undefined;\n const metricName = val?.[\"metric\"] as string | undefined;\n const key = metricName ?? `metric${i}`;\n flat[key] =\n (val as Record<string, unknown>)?.[\"decimalValue\"] !== undefined\n ? ((val as Record<string, Record<string, unknown>>)?.[\"decimalValue\"]?.[\n \"value\"\n ] ?? \"-\")\n : \"-\";\n }\n }\n const dims = rowR[\"dimensions\"] as Record<string, unknown> | unknown[] | undefined;\n if (dims && !Array.isArray(dims)) {\n for (const [key, val] of Object.entries(dims)) {\n flat[key] = (val as Record<string, unknown>)?.[\"stringValue\"] ?? \"-\";\n }\n } else if (Array.isArray(dims)) {\n // Fallback: if API returns dimensions as array\n for (let i = 0; i < dims.length; i++) {\n const val = dims[i] as Record<string, unknown> | undefined;\n const dimName = val?.[\"dimension\"] as string | undefined;\n flat[dimName ?? `dim${i}`] = val?.[\"stringValue\"] ?? val?.[\"int64Value\"] ?? \"-\";\n }\n }\n return flat;\n });\n console.log(formatOutput(rows, format));\n } else {\n console.log(formatOutput(result, format));\n }\n\n // Check threshold from flag or config\n const configKey = THRESHOLD_CONFIG_KEYS[name];\n const configThreshold = configKey\n ? (config as unknown as Record<string, unknown>)[\"vitals\"]\n ? ((config as unknown as Record<string, unknown>)[\"vitals\"] as Record<string, unknown>)[\n \"thresholds\"\n ]\n ? (\n (\n (config as unknown as Record<string, unknown>)[\"vitals\"] as Record<\n string,\n unknown\n >\n )[\"thresholds\"] as Record<string, unknown>\n )[configKey]\n : undefined\n : undefined\n : undefined;\n const threshold =\n options.threshold ?? (configThreshold !== undefined ? Number(configThreshold) : undefined);\n if (threshold !== undefined) {\n const latestRow = result.rows?.[result.rows.length - 1];\n const metricKeys = latestRow?.metrics ? Object.keys(latestRow.metrics) : [];\n const firstMetric = metricKeys[0];\n const value = firstMetric\n ? Number(latestRow?.metrics[firstMetric]?.decimalValue?.value)\n : undefined;\n const check = checkThreshold(value, threshold);\n if (check.breached) {\n console.error(`${red(\"✗\")} Threshold breached: ${check.value} > ${check.threshold}`);\n process.exitCode = 6;\n }\n }\n });\n}\n\nexport function registerVitalsCommands(program: Command): void {\n const vitals = program\n .command(\"vitals\")\n .description(\"Monitor app vitals, crash rates, and performance metrics\");\n\n vitals\n .command(\"overview\")\n .description(\"Dashboard summary of all vital metrics\")\n .action(async () => {\n const config = await loadConfig();\n const packageName = resolvePackageName(program.opts()[\"app\"], config);\n const reporting = await getReportingClient(config);\n const format = getOutputFormat(program, config);\n\n const result = await getVitalsOverview(reporting, packageName);\n if (Object.keys(result).length === 0) {\n if (format === \"json\") {\n console.log(formatOutput({ vitals: [], message: \"No vitals data available\" }, format));\n } else {\n console.log(\"No vitals data available.\");\n }\n return;\n }\n if (format !== \"json\") {\n const overview = result as Record<string, unknown>;\n const rows = Object.entries(overview).map(([metric, data]) => {\n const metricRows = data as Record<string, unknown>[] | undefined;\n const latest = metricRows?.[metricRows.length - 1];\n const metrics = latest?.[\"metrics\"] as\n | Record<string, Record<string, unknown>>\n | undefined;\n const firstKey = metrics ? Object.keys(metrics)[0] : undefined;\n const value = firstKey\n ? (metrics?.[firstKey]?.[\"decimalValue\"] as Record<string, unknown> | undefined)?.[\n \"value\"\n ]\n : undefined;\n return {\n metric,\n dataPoints: metricRows?.length || 0,\n latestValue: value ?? \"-\",\n };\n });\n console.log(formatOutput(rows, format));\n } else {\n console.log(formatOutput(result, format));\n }\n });\n\n registerMetricCommand(vitals, \"crashes\", \"Query crash rate metrics\", getVitalsCrashes, program);\n registerMetricCommand(vitals, \"anr\", \"Query ANR rate metrics\", getVitalsAnr, program);\n registerMetricCommand(vitals, \"startup\", \"Query slow startup metrics\", getVitalsStartup, program);\n registerMetricCommand(\n vitals,\n \"rendering\",\n \"Query slow rendering metrics\",\n getVitalsRendering,\n program,\n );\n registerMetricCommand(\n vitals,\n \"battery\",\n \"Query excessive wakeup metrics\",\n getVitalsBattery,\n program,\n );\n registerMetricCommand(vitals, \"memory\", \"Query stuck wakelock metrics\", getVitalsMemory, program);\n registerMetricCommand(\n vitals,\n \"wakeup\",\n \"Query excessive wakeup rate metrics\",\n getVitalsBattery,\n program,\n );\n registerMetricCommand(\n vitals,\n \"lmk\",\n \"Query low-memory kill (stuck wakelock) metrics\",\n getVitalsLmk,\n program,\n );\n registerMetricCommand(\n vitals,\n \"error-count\",\n \"Query error report count metrics\",\n getVitalsErrorCount,\n program,\n );\n\n vitals\n .command(\"anomalies\")\n .description(\"Detect anomalies in app vitals\")\n .action(async () => {\n const config = await loadConfig();\n const packageName = resolvePackageName(program.opts()[\"app\"], config);\n const reporting = await getReportingClient(config);\n const format = getOutputFormat(program, config);\n\n let result;\n try {\n result = await getVitalsAnomalies(reporting, packageName);\n } catch (err) {\n if (err instanceof PlayApiError && err.statusCode === 403) {\n if (format === \"json\") {\n console.log(\n formatOutput(\n { anomalies: [], message: \"Reporting API not enabled or insufficient permissions\" },\n format,\n ),\n );\n } else {\n console.log(\n `${yellow(\"⚠\")} No anomaly data available. The Reporting API may not be enabled for this project.`,\n );\n console.log(\n ` Enable it at: https://console.cloud.google.com/apis/library/playdeveloperreporting.googleapis.com`,\n );\n }\n return;\n }\n throw err;\n }\n console.log(formatOutput(result, format));\n });\n\n const errors = vitals.command(\"errors\").description(\"Search and view error issues\");\n\n errors\n .command(\"search\")\n .description(\"Search error issues\")\n .option(\"--filter <text>\", \"Filter expression\")\n .option(\"--max <n>\", \"Maximum results\", parseInt)\n .action(async (options) => {\n const config = await loadConfig();\n const packageName = resolvePackageName(program.opts()[\"app\"], config);\n const reporting = await getReportingClient(config);\n const format = getOutputFormat(program, config);\n\n const result = await searchVitalsErrors(reporting, packageName, {\n filter: options.filter,\n maxResults: options.max,\n });\n const issues = (result as unknown as Record<string, unknown>)[\"errorIssues\"] as\n | unknown[]\n | undefined;\n if (format !== \"json\" && (!issues || issues.length === 0)) {\n console.log(\"No error issues found.\");\n return;\n }\n console.log(formatOutput(result, format));\n });\n\n const METRIC_MAP: Record<string, VitalsMetricSet> = {\n crashes: \"crashRateMetricSet\",\n anr: \"anrRateMetricSet\",\n startup: \"slowStartRateMetricSet\",\n rendering: \"slowRenderingRateMetricSet\",\n battery: \"excessiveWakeupRateMetricSet\",\n memory: \"stuckBackgroundWakelockRateMetricSet\",\n wakeup: \"excessiveWakeupRateMetricSet\",\n lmk: \"lowMemoryKillerRateMetricSet\",\n \"error-count\": \"errorCountMetricSet\",\n };\n\n vitals\n .command(\"compare <metric>\")\n .description(\"Compare metric trend: this period vs previous period\")\n .option(\"--days <n>\", \"Period length in days\", (v) => parseInt(v, 10), 7)\n .action(async (metric: string, options) => {\n const metricSet = METRIC_MAP[metric];\n if (!metricSet) {\n throw new GpcError(\n `Unknown metric \"${metric}\". Use: ${Object.keys(METRIC_MAP).join(\", \")}`,\n \"VITALS_USAGE_ERROR\",\n 2,\n `Valid metrics: ${Object.keys(METRIC_MAP).join(\", \")}`,\n );\n }\n\n const config = await loadConfig();\n const packageName = resolvePackageName(program.opts()[\"app\"], config);\n const reporting = await getReportingClient(config);\n const format = getOutputFormat(program, config);\n\n const result = await compareVitalsTrend(reporting, packageName, metricSet, options.days);\n console.log(formatOutput(result, format));\n });\n\n vitals\n .command(\"compare-versions <v1> <v2>\")\n .description(\"Compare vitals side-by-side for two version codes\")\n .option(\"--days <n>\", \"Number of days to query\", (v) => parseInt(v, 10), 30)\n .action(async (v1: string, v2: string, options) => {\n const config = await loadConfig();\n const packageName = resolvePackageName(program.opts()[\"app\"], config);\n const reporting = await getReportingClient(config);\n const format = getOutputFormat(program, config);\n\n const result = await compareVersionVitals(reporting, packageName, v1, v2, {\n days: options.days,\n });\n\n if (format === \"json\") {\n console.log(formatOutput(result, format));\n return;\n }\n\n const metrics: [keyof typeof result.v1, string][] = [\n [\"crashRate\", \"Crash Rate\"],\n [\"anrRate\", \"ANR Rate\"],\n [\"slowStartRate\", \"Slow Start Rate\"],\n [\"slowRenderingRate\", \"Slow Rendering Rate\"],\n ];\n\n console.log(`\\nVersion Comparison — ${packageName}`);\n console.log(`${\"─\".repeat(60)}`);\n console.log(`${\"Metric\".padEnd(22)} ${\"v\" + v1.padEnd(14)} ${\"v\" + v2.padEnd(14)} Change`);\n console.log(`${\"─\".repeat(60)}`);\n\n for (const [key, label] of metrics) {\n const val1 = result.v1[key] as number | undefined;\n const val2 = result.v2[key] as number | undefined;\n const s1 = val1 !== undefined ? (val1 * 100).toFixed(3) + \"%\" : \"N/A\";\n const s2 = val2 !== undefined ? (val2 * 100).toFixed(3) + \"%\" : \"N/A\";\n const isRegression = result.regressions.includes(key as string);\n const change =\n val1 !== undefined && val2 !== undefined ? ((val2 - val1) / val1) * 100 : undefined;\n const changeStr =\n change !== undefined ? (change > 0 ? \"+\" : \"\") + change.toFixed(1) + \"%\" : \"N/A\";\n const colorFn = isRegression\n ? red\n : change !== undefined && change < -1\n ? green\n : (s: string) => s;\n console.log(\n `${label.padEnd(22)} ${s1.padEnd(15)} ${colorFn(s2.padEnd(15))} ${colorFn(changeStr)}`,\n );\n }\n\n if (result.regressions.length > 0) {\n console.log(`\\n${red(\"✗\")} Regressions detected: ${result.regressions.join(\", \")}`);\n } else {\n console.log(`\\n${green(\"✓\")} No regressions detected.`);\n }\n });\n\n vitals\n .command(\"watch\")\n .description(\"Monitor vitals continuously and optionally auto-halt rollout on breach\")\n .requiredOption(\"--threshold <value>\", \"Breach threshold value\", parseFloat)\n .option(\n \"--metric <name>\",\n \"Metric to monitor (crashes, anr, startup, rendering, battery, memory, wakeup, lmk, error-count)\",\n \"crashes\",\n )\n .option(\"--interval <seconds>\", \"Polling interval in seconds\", (v) => parseInt(v, 10), 300)\n .option(\"--auto-halt-rollout\", \"Automatically halt rollout if threshold is breached\")\n .option(\"--track <name>\", \"Track to halt rollout on (required with --auto-halt-rollout)\")\n .action(async (options) => {\n const metricSet = METRIC_MAP[options.metric as string];\n if (!metricSet) {\n throw new GpcError(\n `Unknown metric \"${options.metric}\". Use: ${Object.keys(METRIC_MAP).join(\", \")}`,\n \"VITALS_USAGE_ERROR\",\n 2,\n `Valid metrics: ${Object.keys(METRIC_MAP).join(\", \")}`,\n );\n }\n\n if (options.autoHaltRollout && !options.track) {\n throw new GpcError(\n \"--track <name> is required when using --auto-halt-rollout\",\n \"VITALS_USAGE_ERROR\",\n 2,\n \"Add --track <name> to specify which track to halt on breach.\",\n );\n }\n\n const config = await loadConfig();\n const packageName = resolvePackageName(program.opts()[\"app\"], config);\n const reporting = await getReportingClient(config);\n const intervalMs = (options.interval as number) * 1000;\n\n console.log(`Watching ${options.metric} for ${packageName}`);\n console.log(`Threshold: ${options.threshold} Interval: ${options.interval}s`);\n if (options.autoHaltRollout) {\n console.log(`Auto-halt enabled on track: ${options.track}`);\n }\n console.log(\"Press Ctrl+C to stop.\\n\");\n\n const stop = watchVitalsWithAutoHalt(reporting, packageName, {\n intervalMs,\n threshold: options.threshold as number,\n metricSet,\n onPoll: (value, breached) => {\n const ts = new Date().toISOString();\n const valStr = value !== undefined ? (value * 100).toFixed(3) + \"%\" : \"N/A\";\n const indicator = breached ? red(\"✗ BREACH\") : green(\"✓ OK\");\n console.log(`[${ts}] ${options.metric}: ${valStr} — ${indicator}`);\n },\n onHalt: options.autoHaltRollout\n ? async (value: number) => {\n console.error(\n `\\n${red(\"✗\")} Threshold breached (${(value * 100).toFixed(3)}% > ${options.threshold}%). Halting rollout on track \"${options.track}\"...`,\n );\n try {\n const { resolveAuth } = await import(\"@gpc-cli/auth\");\n const { createApiClient } = await import(\"@gpc-cli/api\");\n const { updateRollout } = await import(\"@gpc-cli/core\");\n const auth = await resolveAuth({ serviceAccountPath: config.auth?.serviceAccount });\n const apiClient = createApiClient({ auth });\n await updateRollout(apiClient, packageName, options.track as string, \"halt\");\n console.error(`${red(\"⚠\")} Rollout halted on track \"${options.track}\".`);\n } catch (err) {\n console.error(\n `Failed to halt rollout: ${err instanceof Error ? err.message : String(err)}`,\n );\n }\n stop();\n process.exitCode = 6;\n }\n : undefined,\n });\n\n process.on(\"SIGINT\", () => {\n stop();\n console.log(\"\\nWatch stopped.\");\n });\n });\n}\n"],"mappings":"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","names":["resolveAuth"]}
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|