@ishlabs/cli 0.17.4 → 0.17.5
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/index.js +4 -3
- package/dist/lib/command-helpers.js +7 -2
- package/dist/lib/observability.d.ts +25 -0
- package/dist/lib/observability.js +42 -0
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -26,7 +26,7 @@ import { tagAlias, ALIAS_PREFIX } from "./lib/alias-store.js";
|
|
|
26
26
|
import { output } from "./lib/output.js";
|
|
27
27
|
import { ishDir } from "./lib/paths.js";
|
|
28
28
|
import { findInstalledSkill } from "./lib/skill-content.js";
|
|
29
|
-
import { initObservability } from "./lib/observability.js";
|
|
29
|
+
import { exitWithFlush, initObservability } from "./lib/observability.js";
|
|
30
30
|
import { setSurfaceBaggage } from "./lib/baggage.js";
|
|
31
31
|
import pkg from "../package.json" with { type: "json" };
|
|
32
32
|
const { version } = pkg;
|
|
@@ -62,7 +62,8 @@ program.exitOverride((err) => {
|
|
|
62
62
|
if (err.code === "commander.helpDisplayed"
|
|
63
63
|
|| err.code === "commander.version"
|
|
64
64
|
|| err.code === "commander.help") {
|
|
65
|
-
|
|
65
|
+
void exitWithFlush(0);
|
|
66
|
+
return;
|
|
66
67
|
}
|
|
67
68
|
// Detect --json without relying on parsed opts (parse may have failed).
|
|
68
69
|
const useJson = process.argv.includes("--json") || !process.stdout.isTTY;
|
|
@@ -80,7 +81,7 @@ program.exitOverride((err) => {
|
|
|
80
81
|
console.error(`Error: ${err.message}`);
|
|
81
82
|
console.error(" → Run `ish <command> --help` for usage");
|
|
82
83
|
}
|
|
83
|
-
|
|
84
|
+
void exitWithFlush(EXIT_USAGE);
|
|
84
85
|
});
|
|
85
86
|
// Global options
|
|
86
87
|
program
|
|
@@ -10,6 +10,7 @@ import { outputError, setVerbose, setFields, setGetField } from "./output.js";
|
|
|
10
10
|
import { setColorsEnabled, colorsEnabled } from "./colors.js";
|
|
11
11
|
import { loadConfig } from "../config.js";
|
|
12
12
|
import { resolveId } from "./alias-store.js";
|
|
13
|
+
import { exitWithFlush } from "./observability.js";
|
|
13
14
|
function isSimulatable(p) {
|
|
14
15
|
return Boolean(p.simulation_config_id) || Boolean(p.simulation_config);
|
|
15
16
|
}
|
|
@@ -277,6 +278,10 @@ export function getGlobals(cmd) {
|
|
|
277
278
|
|| process.argv.includes("--get")
|
|
278
279
|
|| !process.stdout.isTTY;
|
|
279
280
|
outputError(err, useJson);
|
|
281
|
+
// Sync exit path: getGlobals is called from non-async Commander hooks,
|
|
282
|
+
// so we can't await exitWithFlush here. Usage errors are typed early-
|
|
283
|
+
// exits without rich Sentry signal; accept losing the flush on this
|
|
284
|
+
// one site rather than cascading async through every getGlobals caller.
|
|
280
285
|
process.exit(exitCodeFromError(err));
|
|
281
286
|
}
|
|
282
287
|
// Apply side effects (verbose, fields, colors, get-field, active workspace)
|
|
@@ -409,7 +414,7 @@ export async function withClient(cmd, fn) {
|
|
|
409
414
|
}
|
|
410
415
|
catch (err) {
|
|
411
416
|
outputError(err, globals.json);
|
|
412
|
-
|
|
417
|
+
await exitWithFlush(exitCodeFromError(err));
|
|
413
418
|
}
|
|
414
419
|
}
|
|
415
420
|
/**
|
|
@@ -424,7 +429,7 @@ export async function runInline(cmd, fn) {
|
|
|
424
429
|
}
|
|
425
430
|
catch (err) {
|
|
426
431
|
outputError(err, globals.json);
|
|
427
|
-
|
|
432
|
+
await exitWithFlush(exitCodeFromError(err));
|
|
428
433
|
}
|
|
429
434
|
}
|
|
430
435
|
export function getWebUrl(globals, path) {
|
|
@@ -27,3 +27,28 @@
|
|
|
27
27
|
* import time on some Bun-compile builds. */
|
|
28
28
|
export declare function isBunRuntime(): boolean;
|
|
29
29
|
export declare function initObservability(): Promise<void>;
|
|
30
|
+
/**
|
|
31
|
+
* Drain the Sentry buffer before exiting the process.
|
|
32
|
+
*
|
|
33
|
+
* Why this exists: Sentry's transport buffers events asynchronously. `ish`
|
|
34
|
+
* is a short-lived process — most commands call `process.exit(code)` within
|
|
35
|
+
* milliseconds of init, so the buffered envelope is dropped before the HTTP
|
|
36
|
+
* batch fires. Net effect: zero telemetry from real CLI invocations.
|
|
37
|
+
*
|
|
38
|
+
* Wrap every `process.exit(code)` callsite with `exitWithFlush(code)` instead,
|
|
39
|
+
* OR await `flushObservability()` directly before exit.
|
|
40
|
+
*
|
|
41
|
+
* Always safe to call: no-op when Sentry wasn't initialised (no DSN, or
|
|
42
|
+
* init failed). Never throws — an observability outage must not crash the
|
|
43
|
+
* CLI.
|
|
44
|
+
*/
|
|
45
|
+
export declare function flushObservability(timeoutMs?: number): Promise<void>;
|
|
46
|
+
/**
|
|
47
|
+
* Async-flush-then-exit helper. Use this in place of `process.exit(code)`
|
|
48
|
+
* anywhere we want telemetry to ship before teardown.
|
|
49
|
+
*
|
|
50
|
+
* The Node `beforeExit` event would fire automatically on natural process
|
|
51
|
+
* end, but it does NOT fire when `process.exit()` is called explicitly —
|
|
52
|
+
* which the CLI does from at least 5 sites. This helper closes that gap.
|
|
53
|
+
*/
|
|
54
|
+
export declare function exitWithFlush(code: number): Promise<never>;
|
|
@@ -24,6 +24,10 @@
|
|
|
24
24
|
*/
|
|
25
25
|
import pkg from "../../package.json" with { type: "json" };
|
|
26
26
|
import { beforeSend } from "./sentry-scrub.js";
|
|
27
|
+
/** Module-local reference to the loaded Sentry module so `flushObservability`
|
|
28
|
+
* can call `flush()` without re-importing (which would lose runtime-pinned
|
|
29
|
+
* state and create a second Hub in some bundler configurations). */
|
|
30
|
+
let _sentryModule = null;
|
|
27
31
|
/** Bun-global probe. ``typeof Bun !== 'undefined'`` is the only reliable
|
|
28
32
|
* runtime-detect: ``process.versions.bun`` exists but is set up well after
|
|
29
33
|
* import time on some Bun-compile builds. */
|
|
@@ -44,6 +48,7 @@ export async function initObservability() {
|
|
|
44
48
|
const sentryModule = bun
|
|
45
49
|
? await import("@sentry/bun")
|
|
46
50
|
: await import("@sentry/node");
|
|
51
|
+
_sentryModule = sentryModule;
|
|
47
52
|
const init = sentryModule.init;
|
|
48
53
|
init({
|
|
49
54
|
dsn,
|
|
@@ -121,3 +126,40 @@ async function initOtelNode() {
|
|
|
121
126
|
instrumentations: [new UndiciInstrumentation()],
|
|
122
127
|
});
|
|
123
128
|
}
|
|
129
|
+
/**
|
|
130
|
+
* Drain the Sentry buffer before exiting the process.
|
|
131
|
+
*
|
|
132
|
+
* Why this exists: Sentry's transport buffers events asynchronously. `ish`
|
|
133
|
+
* is a short-lived process — most commands call `process.exit(code)` within
|
|
134
|
+
* milliseconds of init, so the buffered envelope is dropped before the HTTP
|
|
135
|
+
* batch fires. Net effect: zero telemetry from real CLI invocations.
|
|
136
|
+
*
|
|
137
|
+
* Wrap every `process.exit(code)` callsite with `exitWithFlush(code)` instead,
|
|
138
|
+
* OR await `flushObservability()` directly before exit.
|
|
139
|
+
*
|
|
140
|
+
* Always safe to call: no-op when Sentry wasn't initialised (no DSN, or
|
|
141
|
+
* init failed). Never throws — an observability outage must not crash the
|
|
142
|
+
* CLI.
|
|
143
|
+
*/
|
|
144
|
+
export async function flushObservability(timeoutMs = 2000) {
|
|
145
|
+
if (!_initialized || _sentryModule?.flush === undefined)
|
|
146
|
+
return;
|
|
147
|
+
try {
|
|
148
|
+
await _sentryModule.flush(timeoutMs);
|
|
149
|
+
}
|
|
150
|
+
catch {
|
|
151
|
+
// Swallow — same rationale as init failure.
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* Async-flush-then-exit helper. Use this in place of `process.exit(code)`
|
|
156
|
+
* anywhere we want telemetry to ship before teardown.
|
|
157
|
+
*
|
|
158
|
+
* The Node `beforeExit` event would fire automatically on natural process
|
|
159
|
+
* end, but it does NOT fire when `process.exit()` is called explicitly —
|
|
160
|
+
* which the CLI does from at least 5 sites. This helper closes that gap.
|
|
161
|
+
*/
|
|
162
|
+
export async function exitWithFlush(code) {
|
|
163
|
+
await flushObservability();
|
|
164
|
+
process.exit(code);
|
|
165
|
+
}
|