run402 4.30.0 → 4.31.0
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/lib/argparse.mjs +11 -4
- package/lib/cloud.mjs +1 -2
- package/lib/errors.mjs +37 -21
- package/package.json +1 -1
package/lib/argparse.mjs
CHANGED
|
@@ -20,10 +20,17 @@ export function hasHelp(args = []) {
|
|
|
20
20
|
return args.includes("--help") || args.includes("-h");
|
|
21
21
|
}
|
|
22
22
|
|
|
23
|
-
// CLI-wide convention:
|
|
24
|
-
//
|
|
25
|
-
//
|
|
26
|
-
//
|
|
23
|
+
// CLI-wide convention (cli-output-shape): JSON is ALWAYS the default on
|
|
24
|
+
// stdout, and `--json` is a universally-accepted NO-OP. Every command accepts
|
|
25
|
+
// it; passing it never changes the shape, content, or byte count of stdout.
|
|
26
|
+
// Baking it into the baseline known set here makes acceptance structural, so a
|
|
27
|
+
// newly added command inherits it without a per-command allowlist entry.
|
|
28
|
+
//
|
|
29
|
+
// No command may gate its stdout format on this flag. A command offering a
|
|
30
|
+
// human-readable view exposes it behind `--human` (see `up.mjs`, `errors.mjs`)
|
|
31
|
+
// and rejects `--human` combined with `--json`. The single sanctioned
|
|
32
|
+
// exception to the no-op rule is `assets put --json`, a preserved deprecated
|
|
33
|
+
// alias for `--stream` that selects NDJSON progress rather than a format.
|
|
27
34
|
const ALWAYS_KNOWN_FLAGS = ["--json"];
|
|
28
35
|
|
|
29
36
|
export function assertKnownFlags(args = [], knownFlags = [], flagsWithValues = []) {
|
package/lib/cloud.mjs
CHANGED
|
@@ -92,7 +92,6 @@ async function create(rawArgs) {
|
|
|
92
92
|
const output = flagValue(args, "--output");
|
|
93
93
|
const wait = args.includes("--wait") || Boolean(output);
|
|
94
94
|
const jsonStream = args.includes("--json-stream");
|
|
95
|
-
const json = args.includes("--json") || jsonStream || true;
|
|
96
95
|
const idempotencyKey = flagValue(args, "--idempotency-key") ?? undefined;
|
|
97
96
|
const pollIntervalMs = parseIntegerFlag("--poll-interval", flagValue(args, "--poll-interval"), { min: 100, def: 1000 });
|
|
98
97
|
const timeoutMs = parseIntegerFlag("--timeout", flagValue(args, "--timeout"), { min: 1000, def: 600000 });
|
|
@@ -156,7 +155,7 @@ async function create(rawArgs) {
|
|
|
156
155
|
retryable: false,
|
|
157
156
|
result,
|
|
158
157
|
}));
|
|
159
|
-
} else
|
|
158
|
+
} else {
|
|
160
159
|
console.log(JSON.stringify(result, null, 2));
|
|
161
160
|
}
|
|
162
161
|
if (archive.status !== "ready") process.exit(1);
|
package/lib/errors.mjs
CHANGED
|
@@ -3,13 +3,16 @@
|
|
|
3
3
|
* promote/revert verdict (gateway release-error-rollup).
|
|
4
4
|
*
|
|
5
5
|
* Two audiences from one wire envelope:
|
|
6
|
-
*
|
|
7
|
-
* watch triggering/final page). No reshaping — CLI-JSON and
|
|
8
|
-
* consumers see one contract.
|
|
9
|
-
*
|
|
6
|
+
* default → the gateway envelope VERBATIM as JSON (list page, detail row, or
|
|
7
|
+
* the watch triggering/final page). No reshaping — CLI-JSON and
|
|
8
|
+
* HTTP consumers see one contract.
|
|
9
|
+
* --human → a rendered read: the verdict first (so "0 errors over 0 traffic"
|
|
10
10
|
* is never mistaken for health), then one line per fingerprint,
|
|
11
11
|
* then a runnable logs drill-down.
|
|
12
12
|
*
|
|
13
|
+
* JSON is ALWAYS the default (cli-output-shape). `--json` is a universally
|
|
14
|
+
* accepted no-op; stdout shape is never gated on it.
|
|
15
|
+
*
|
|
13
16
|
* The promote gate: `--new-in <release> --fail-on-new` exits 0 when no error
|
|
14
17
|
* identity was first seen under that release, 1 when new fingerprints appear,
|
|
15
18
|
* and 2 when a verdict could not be produced (outage / auth / gate misuse) —
|
|
@@ -40,9 +43,9 @@ export const DEFAULT_INTERVAL_MS = 15000;
|
|
|
40
43
|
const HELP = `run402 errors — grouped error fingerprints + a promote/revert verdict
|
|
41
44
|
|
|
42
45
|
Usage:
|
|
43
|
-
run402 errors [--project <id>] [filters] [--
|
|
44
|
-
run402 errors <fingerprint_id> [--project <id>] [--
|
|
45
|
-
run402 errors --new-in <release_id|active> --fail-on-new [--
|
|
46
|
+
run402 errors [--project <id>] [filters] [--human]
|
|
47
|
+
run402 errors <fingerprint_id> [--project <id>] [--human]
|
|
48
|
+
run402 errors --new-in <release_id|active> --fail-on-new [--human]
|
|
46
49
|
run402 errors --new-in <release_id|active> --watch <dur> [--fail-on-new]
|
|
47
50
|
|
|
48
51
|
What this is:
|
|
@@ -76,7 +79,9 @@ Filters (each maps 1:1 to a query param):
|
|
|
76
79
|
Never parse or compare it — pass it back as-is.
|
|
77
80
|
|
|
78
81
|
Output:
|
|
79
|
-
--
|
|
82
|
+
--human Render the human-readable view instead of JSON.
|
|
83
|
+
Cannot be combined with --json.
|
|
84
|
+
--json Accepted no-op (JSON is already the default).
|
|
80
85
|
--watch <dur> Poll the release for new identities for <dur>, then
|
|
81
86
|
stop. Requires --new-in. Durations: 90s, 10m, 2h, or a
|
|
82
87
|
bare number of seconds. Progress ticks go to stderr so
|
|
@@ -136,7 +141,7 @@ export async function run(sub, args = []) {
|
|
|
136
141
|
"--project", "--since", "--until", "--function", "--kind",
|
|
137
142
|
"--fingerprint", "--new-in", "--limit", "--cursor", "--watch", "--interval",
|
|
138
143
|
];
|
|
139
|
-
const boolFlags = ["--json", "--fail-on-new", "--help", "-h"];
|
|
144
|
+
const boolFlags = ["--json", "--human", "--fail-on-new", "--help", "-h"];
|
|
140
145
|
assertKnownFlags(a, [...valueFlags, ...boolFlags], valueFlags);
|
|
141
146
|
|
|
142
147
|
const positionals = positionalArgs(a, valueFlags);
|
|
@@ -148,7 +153,18 @@ export async function run(sub, args = []) {
|
|
|
148
153
|
});
|
|
149
154
|
}
|
|
150
155
|
const fingerprintId = positionals[0] ?? null;
|
|
151
|
-
|
|
156
|
+
// Output contract (cli-output-shape): JSON is ALWAYS the default. `--json`
|
|
157
|
+
// is a universally-accepted no-op; human rendering is the `--human`
|
|
158
|
+
// opt-out, matching `run402 up`. Never gate stdout shape on `--json`.
|
|
159
|
+
const human = a.includes("--human");
|
|
160
|
+
if (human && a.includes("--json")) {
|
|
161
|
+
fail({
|
|
162
|
+
code: "BAD_USAGE",
|
|
163
|
+
message: "--human cannot be combined with --json.",
|
|
164
|
+
details: { flags: a.filter((arg) => arg === "--human" || arg === "--json") },
|
|
165
|
+
hint: "JSON is the default; drop --json to keep it, or keep --human alone for the rendered view.",
|
|
166
|
+
});
|
|
167
|
+
}
|
|
152
168
|
const failOnNew = a.includes("--fail-on-new");
|
|
153
169
|
const project = flagValue(a, "--project");
|
|
154
170
|
const newIn = flagValue(a, "--new-in");
|
|
@@ -166,7 +182,7 @@ export async function run(sub, args = []) {
|
|
|
166
182
|
fail({
|
|
167
183
|
code: "BAD_USAGE",
|
|
168
184
|
message: `${offending} is not valid with a <fingerprint_id> (detail view).`,
|
|
169
|
-
hint: "Detail view accepts only --project and --
|
|
185
|
+
hint: "Detail view accepts only --project and --human. Drop the fingerprint id to list + get a verdict.",
|
|
170
186
|
});
|
|
171
187
|
}
|
|
172
188
|
const projectId = resolveProjectId(project);
|
|
@@ -177,7 +193,7 @@ export async function run(sub, args = []) {
|
|
|
177
193
|
reportSdkError(err);
|
|
178
194
|
return;
|
|
179
195
|
}
|
|
180
|
-
if (
|
|
196
|
+
if (!human) {
|
|
181
197
|
console.log(JSON.stringify(detail, null, 2));
|
|
182
198
|
return;
|
|
183
199
|
}
|
|
@@ -277,19 +293,19 @@ export async function run(sub, args = []) {
|
|
|
277
293
|
return;
|
|
278
294
|
}
|
|
279
295
|
|
|
280
|
-
if (
|
|
296
|
+
if (!human) console.log(JSON.stringify(page, null, 2));
|
|
281
297
|
|
|
282
298
|
if (failOnNew) {
|
|
283
299
|
const totalNew = Number(page?.verdict?.new_fingerprints ?? 0);
|
|
284
300
|
if (totalNew > 0) {
|
|
285
|
-
if (
|
|
301
|
+
if (human) console.log(renderFailOnNewList(page?.errors ?? [], newIn, totalNew));
|
|
286
302
|
process.exit(1);
|
|
287
303
|
}
|
|
288
|
-
if (
|
|
304
|
+
if (human) console.log(renderCleanGate(page?.verdict, newIn));
|
|
289
305
|
process.exit(0);
|
|
290
306
|
}
|
|
291
307
|
|
|
292
|
-
if (
|
|
308
|
+
if (human) console.log(renderHumanList(page));
|
|
293
309
|
}
|
|
294
310
|
|
|
295
311
|
// ─── Watch driver ────────────────────────────────────────────────────────────
|
|
@@ -327,7 +343,7 @@ async function runWatch({ projectId, newIn, durationMs, intervalMs, failOnNew, j
|
|
|
327
343
|
const newErrors = Array.isArray(result?.new_errors) ? result.new_errors : [];
|
|
328
344
|
const totalNew = Number(result?.verdict?.new_fingerprints ?? newErrors.length);
|
|
329
345
|
|
|
330
|
-
if (
|
|
346
|
+
if (!human) {
|
|
331
347
|
// The triggering page if we fired early, else the last poll's page. Fall
|
|
332
348
|
// back to a page-shaped envelope only if no poll ever ran (edge case).
|
|
333
349
|
const page = triggeringPage ?? lastPage ?? {
|
|
@@ -340,17 +356,17 @@ async function runWatch({ projectId, newIn, durationMs, intervalMs, failOnNew, j
|
|
|
340
356
|
|
|
341
357
|
if (failOnNew) {
|
|
342
358
|
if (!clean) {
|
|
343
|
-
if (
|
|
359
|
+
if (human) console.log(renderFailOnNewList(newErrors, newIn, totalNew));
|
|
344
360
|
process.exit(1);
|
|
345
361
|
}
|
|
346
|
-
if (
|
|
362
|
+
if (human) {
|
|
347
363
|
console.log(renderCleanGate(result?.verdict, newIn, { watched: true, durationMs, polls: result?.polls }));
|
|
348
364
|
}
|
|
349
365
|
process.exit(0);
|
|
350
366
|
}
|
|
351
367
|
|
|
352
368
|
// --watch without --fail-on-new: report and exit 0.
|
|
353
|
-
if (
|
|
369
|
+
if (human) {
|
|
354
370
|
const page = triggeringPage ?? lastPage;
|
|
355
371
|
if (page) console.log(renderHumanList(page));
|
|
356
372
|
else console.log(renderVerdict(result?.verdict));
|
|
@@ -532,7 +548,7 @@ export function renderHumanList(page) {
|
|
|
532
548
|
|
|
533
549
|
if (p.has_more) {
|
|
534
550
|
parts.push("");
|
|
535
|
-
parts.push(`More rows available — page with --cursor ${p.next_cursor ?? "<next_cursor from
|
|
551
|
+
parts.push(`More rows available — page with --cursor ${p.next_cursor ?? "<next_cursor from the JSON output>"} (cursors are opaque; pass as-is).`);
|
|
536
552
|
}
|
|
537
553
|
|
|
538
554
|
const top = errors[0];
|
package/package.json
CHANGED