litmus-cli 1.4.24 → 1.4.26
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/README.md +20 -3
- package/dist/commands/doctor.d.ts.map +1 -1
- package/dist/commands/doctor.js +11 -0
- package/dist/commands/doctor.js.map +1 -1
- package/dist/commands/init.d.ts +3 -0
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +67 -26
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/setup-check.d.ts +19 -0
- package/dist/commands/setup-check.d.ts.map +1 -0
- package/dist/commands/setup-check.js +48 -0
- package/dist/commands/setup-check.js.map +1 -0
- package/dist/commands/submit.js +6 -1
- package/dist/commands/submit.js.map +1 -1
- package/dist/index.js +16 -0
- package/dist/index.js.map +1 -1
- package/dist/lib/ai-tracking.d.ts +55 -7
- package/dist/lib/ai-tracking.d.ts.map +1 -1
- package/dist/lib/ai-tracking.js +580 -36
- package/dist/lib/ai-tracking.js.map +1 -1
- package/dist/lib/capture-nudge.d.ts.map +1 -1
- package/dist/lib/capture-nudge.js +10 -8
- package/dist/lib/capture-nudge.js.map +1 -1
- package/dist/lib/environment-checks.d.ts +123 -0
- package/dist/lib/environment-checks.d.ts.map +1 -0
- package/dist/lib/environment-checks.js +324 -0
- package/dist/lib/environment-checks.js.map +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1,324 @@
|
|
|
1
|
+
import { existsSync, mkdirSync, mkdtempSync, readFileSync, rmSync, writeFileSync } from "fs";
|
|
2
|
+
import os from "os";
|
|
3
|
+
import path from "path";
|
|
4
|
+
import { execSync } from "child_process";
|
|
5
|
+
import { CLI_VERSION } from "./version.js";
|
|
6
|
+
import { startTracker, trackerDiagnostics } from "./tracker.js";
|
|
7
|
+
/** The `engines.node` floor in package.json; pinned to it by test. */
|
|
8
|
+
export const NODE_MIN_MAJOR = 18;
|
|
9
|
+
export const REINSTALL_COMMAND = "npm install -g litmus-cli@latest";
|
|
10
|
+
/** How long the watcher smoke waits for the ready marker before calling the boot failed. */
|
|
11
|
+
export const WATCHER_BOOT_TIMEOUT_MS = 6000;
|
|
12
|
+
/** Registry document for the `latest` dist-tag. */
|
|
13
|
+
export const NPM_LATEST_URL = "https://registry.npmjs.org/litmus-cli/latest";
|
|
14
|
+
const REGISTRY_TIMEOUT_MS = 5000;
|
|
15
|
+
const SERVER_TIMEOUT_MS = 8000;
|
|
16
|
+
/** Above this the connection is reported as slow. Still `ok`: slowness is not a fix the candidate can apply. */
|
|
17
|
+
const SERVER_SLOW_MS = 3000;
|
|
18
|
+
// ── Node ─────────────────────────────────────────────────────────────
|
|
19
|
+
export function parseNodeMajor(version) {
|
|
20
|
+
const m = /^v?(\d+)/.exec(version.trim());
|
|
21
|
+
return m ? Number(m[1]) : null;
|
|
22
|
+
}
|
|
23
|
+
export function checkNodeVersion(version = process.version) {
|
|
24
|
+
const major = parseNodeMajor(version);
|
|
25
|
+
if (major === null) {
|
|
26
|
+
return { name: "node", status: "warn", detail: `Node.js: version could not be read (${version})` };
|
|
27
|
+
}
|
|
28
|
+
if (major < NODE_MIN_MAJOR) {
|
|
29
|
+
return {
|
|
30
|
+
name: "node",
|
|
31
|
+
status: "fail",
|
|
32
|
+
detail: `Node.js: ${version} is too old. Install Node.js ${NODE_MIN_MAJOR} or newer from https://nodejs.org, then run "litmus setup-check" again.`,
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
return { name: "node", status: "ok", detail: `Node.js: ${version}` };
|
|
36
|
+
}
|
|
37
|
+
// ── CLI version against npm ──────────────────────────────────────────
|
|
38
|
+
/**
|
|
39
|
+
* Numeric compare of dotted versions; prerelease suffixes are ignored, so
|
|
40
|
+
* `1.4.25-beta` compares as `1.4.25`. Returns <0 when a is behind b.
|
|
41
|
+
*/
|
|
42
|
+
export function compareVersions(a, b) {
|
|
43
|
+
const parse = (v) => v.replace(/^v/, "").split("-")[0].split(".").map((n) => Number(n) || 0);
|
|
44
|
+
const pa = parse(a);
|
|
45
|
+
const pb = parse(b);
|
|
46
|
+
const len = Math.max(pa.length, pb.length);
|
|
47
|
+
for (let i = 0; i < len; i++) {
|
|
48
|
+
const d = (pa[i] ?? 0) - (pb[i] ?? 0);
|
|
49
|
+
if (d !== 0)
|
|
50
|
+
return d;
|
|
51
|
+
}
|
|
52
|
+
return 0;
|
|
53
|
+
}
|
|
54
|
+
export async function fetchNpmLatest(fetchImpl = fetch) {
|
|
55
|
+
const res = await fetchImpl(NPM_LATEST_URL, { signal: AbortSignal.timeout(REGISTRY_TIMEOUT_MS) });
|
|
56
|
+
if (!res.ok)
|
|
57
|
+
throw new Error(`registry answered HTTP ${res.status}`);
|
|
58
|
+
const body = (await res.json());
|
|
59
|
+
if (typeof body?.version !== "string")
|
|
60
|
+
throw new Error("registry document has no version");
|
|
61
|
+
return body.version;
|
|
62
|
+
}
|
|
63
|
+
export async function checkCliVersion(opts = {}) {
|
|
64
|
+
const installed = opts.installed ?? CLI_VERSION;
|
|
65
|
+
let latest;
|
|
66
|
+
try {
|
|
67
|
+
latest = await (opts.fetchLatest ?? fetchNpmLatest)();
|
|
68
|
+
}
|
|
69
|
+
catch (err) {
|
|
70
|
+
// Could not verify is not a failure: the candidate's install may be
|
|
71
|
+
// current and the registry merely unreachable from where they sit.
|
|
72
|
+
return {
|
|
73
|
+
name: "cli_version",
|
|
74
|
+
status: "warn",
|
|
75
|
+
detail: `Litmus CLI: ${installed} installed (could not check npm for a newer version)`,
|
|
76
|
+
verbose: err instanceof Error ? err.message : String(err),
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
if (installed === "unknown") {
|
|
80
|
+
return { name: "cli_version", status: "warn", detail: `Litmus CLI: installed version could not be read (${latest} is current)` };
|
|
81
|
+
}
|
|
82
|
+
if (compareVersions(installed, latest) < 0) {
|
|
83
|
+
return {
|
|
84
|
+
name: "cli_version",
|
|
85
|
+
status: "fail",
|
|
86
|
+
detail: `Litmus CLI: ${installed} installed, ${latest} is current. Run "${REINSTALL_COMMAND}" and then "litmus setup-check" again.`,
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
return { name: "cli_version", status: "ok", detail: `Litmus CLI: ${installed} (current)` };
|
|
90
|
+
}
|
|
91
|
+
// ── Server reachability ──────────────────────────────────────────────
|
|
92
|
+
/**
|
|
93
|
+
* Any HTTP answer from the API host counts as reachable — the question is
|
|
94
|
+
* whether this machine can talk to us at all, not whether the endpoint is
|
|
95
|
+
* healthy. `/api/health/db` is public (Clerk's middleware lets `/api/health/`
|
|
96
|
+
* through) and cheap.
|
|
97
|
+
*/
|
|
98
|
+
export async function checkServerReachable(opts) {
|
|
99
|
+
const now = opts.now ?? Date.now;
|
|
100
|
+
const url = `${opts.apiBase.replace(/\/$/, "")}/api/health/db`;
|
|
101
|
+
const started = now();
|
|
102
|
+
try {
|
|
103
|
+
const res = await (opts.fetchImpl ?? fetch)(url, { signal: AbortSignal.timeout(SERVER_TIMEOUT_MS) });
|
|
104
|
+
const ms = now() - started;
|
|
105
|
+
const slow = ms > SERVER_SLOW_MS;
|
|
106
|
+
return {
|
|
107
|
+
name: "server",
|
|
108
|
+
status: "ok",
|
|
109
|
+
detail: slow
|
|
110
|
+
? `Server connection: OK but slow (${ms}ms). Downloads may take a while; a wired or stronger connection helps.`
|
|
111
|
+
: `Server connection: OK (${ms}ms)`,
|
|
112
|
+
verbose: `GET ${url} -> HTTP ${res.status}`,
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
catch (err) {
|
|
116
|
+
return {
|
|
117
|
+
name: "server",
|
|
118
|
+
status: "fail",
|
|
119
|
+
detail: `Server connection: FAILED. Check your internet connection (and any VPN or firewall), then run "litmus setup-check" again.`,
|
|
120
|
+
verbose: `GET ${url}: ${err instanceof Error ? err.message : String(err)}`,
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
// ── git ──────────────────────────────────────────────────────────────
|
|
125
|
+
export function checkGit(exec = (cmd) => execSync(cmd, { stdio: "pipe", windowsHide: true }).toString()) {
|
|
126
|
+
try {
|
|
127
|
+
const out = exec("git --version").trim();
|
|
128
|
+
return { name: "git", status: "ok", detail: `Git: ${out.replace(/^git version\s*/i, "")}` };
|
|
129
|
+
}
|
|
130
|
+
catch (err) {
|
|
131
|
+
// `litmus init` runs `git init` and the tracker records commits, so a
|
|
132
|
+
// missing git is a real blocker with a one-step fix.
|
|
133
|
+
return {
|
|
134
|
+
name: "git",
|
|
135
|
+
status: "fail",
|
|
136
|
+
detail: "Git: not found. Install it from https://git-scm.com, then run \"litmus setup-check\" again.",
|
|
137
|
+
verbose: err instanceof Error ? err.message : String(err),
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
// ── Watcher boot smoke ───────────────────────────────────────────────
|
|
142
|
+
/**
|
|
143
|
+
* Spawn the REAL watcher against a throwaway directory and wait for it to
|
|
144
|
+
* stamp `tracker.ready`, which it does only once its monitors are running
|
|
145
|
+
* (end of its module init). Then ask it to exit through the shutdown
|
|
146
|
+
* sentinel it already polls — never a signal at a pid — and delete the dir.
|
|
147
|
+
*
|
|
148
|
+
* Safe to run on a candidate's machine before any assessment exists: with no
|
|
149
|
+
* config the watcher has no token and no backend, so it uploads nothing, arms
|
|
150
|
+
* no auto-submit, and its capture nudge needs two scans ten minutes apart
|
|
151
|
+
* before it will notify. Everything it writes lands under the temp dir.
|
|
152
|
+
*/
|
|
153
|
+
export async function checkWatcherBoot(opts = {}) {
|
|
154
|
+
const timeoutMs = opts.timeoutMs ?? WATCHER_BOOT_TIMEOUT_MS;
|
|
155
|
+
let dir;
|
|
156
|
+
try {
|
|
157
|
+
dir = mkdtempSync(path.join(opts.tmpRoot ?? os.tmpdir(), "litmus-setup-check-"));
|
|
158
|
+
}
|
|
159
|
+
catch (err) {
|
|
160
|
+
return {
|
|
161
|
+
name: "watcher",
|
|
162
|
+
status: "fail",
|
|
163
|
+
detail: "Activity tracker: could not create a temporary folder to test in. Check that your temp directory is writable, then run \"litmus setup-check\" again.",
|
|
164
|
+
verbose: err instanceof Error ? err.message : String(err),
|
|
165
|
+
};
|
|
166
|
+
}
|
|
167
|
+
const litmusDir = path.join(dir, ".litmus");
|
|
168
|
+
const readyFile = path.join(litmusDir, "tracker.ready");
|
|
169
|
+
const logFile = path.join(litmusDir, "tracker.log");
|
|
170
|
+
const stderrTail = () => {
|
|
171
|
+
try {
|
|
172
|
+
return readFileSync(logFile, "utf8").trim().split("\n").slice(-12).join("\n");
|
|
173
|
+
}
|
|
174
|
+
catch {
|
|
175
|
+
return "(no tracker.log)";
|
|
176
|
+
}
|
|
177
|
+
};
|
|
178
|
+
let stopOutcome = null;
|
|
179
|
+
const annotate = (check) => {
|
|
180
|
+
if (!stopOutcome || stopOutcome.how === "sentinel" || stopOutcome.how === "never_started")
|
|
181
|
+
return check;
|
|
182
|
+
const note = stopOutcome.exited
|
|
183
|
+
? `smoke watcher ignored the shutdown sentinel and was stopped with ${stopOutcome.how.toUpperCase()}`
|
|
184
|
+
: `smoke watcher pid could not be stopped; its folder ${dir} was left in place`;
|
|
185
|
+
return { ...check, verbose: check.verbose ? `${check.verbose}\n${note}` : note };
|
|
186
|
+
};
|
|
187
|
+
let result;
|
|
188
|
+
try {
|
|
189
|
+
mkdirSync(litmusDir, { recursive: true });
|
|
190
|
+
startTracker(dir);
|
|
191
|
+
const deadline = Date.now() + timeoutMs;
|
|
192
|
+
let ready = false;
|
|
193
|
+
let died = false;
|
|
194
|
+
while (Date.now() < deadline) {
|
|
195
|
+
if (existsSync(readyFile)) {
|
|
196
|
+
ready = true;
|
|
197
|
+
break;
|
|
198
|
+
}
|
|
199
|
+
const diag = trackerDiagnostics(dir);
|
|
200
|
+
if (diag.pid !== null && !diag.pidAlive) {
|
|
201
|
+
died = true;
|
|
202
|
+
break;
|
|
203
|
+
}
|
|
204
|
+
await new Promise((r) => setTimeout(r, 100));
|
|
205
|
+
}
|
|
206
|
+
if (ready) {
|
|
207
|
+
result = { name: "watcher", status: "ok", detail: "Activity tracker: starts and runs", verbose: stderrTail() };
|
|
208
|
+
}
|
|
209
|
+
else {
|
|
210
|
+
const tail = stderrTail();
|
|
211
|
+
const looksBlocked = /EPERM|EACCES|operation not permitted|access is denied/i.test(tail);
|
|
212
|
+
result = {
|
|
213
|
+
name: "watcher",
|
|
214
|
+
status: "fail",
|
|
215
|
+
detail: died
|
|
216
|
+
? looksBlocked
|
|
217
|
+
? "Activity tracker: exited during startup because something on this machine blocked it from writing files. Antivirus or endpoint-protection software is the usual cause; allow Node.js and the folder you will work in, then run \"litmus setup-check\" again."
|
|
218
|
+
: "Activity tracker: exited during startup. Copy this whole output into an email to support@litmushiring.com."
|
|
219
|
+
: "Activity tracker: did not finish starting in time. Run \"litmus setup-check\" again; if this line repeats, copy this whole output into an email to support@litmushiring.com.",
|
|
220
|
+
verbose: tail,
|
|
221
|
+
};
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
catch (err) {
|
|
225
|
+
result = {
|
|
226
|
+
name: "watcher",
|
|
227
|
+
status: "fail",
|
|
228
|
+
detail: "Activity tracker: could not be started. Copy this whole output into an email to support@litmushiring.com.",
|
|
229
|
+
verbose: `${err instanceof Error ? err.message : String(err)}\n${stderrTail()}`,
|
|
230
|
+
};
|
|
231
|
+
}
|
|
232
|
+
finally {
|
|
233
|
+
stopOutcome = await stopSmokeWatcher(dir);
|
|
234
|
+
}
|
|
235
|
+
return annotate(result);
|
|
236
|
+
}
|
|
237
|
+
/**
|
|
238
|
+
* Stop the smoke watcher and remove its directory, in that order and never
|
|
239
|
+
* the other way round (Greptile P1 on #2410): a watcher that wedged during
|
|
240
|
+
* init has not reached its sentinel poll and cannot see a shutdown file, so
|
|
241
|
+
* deleting the directory under it would orphan a live process with no
|
|
242
|
+
* control files left to stop it by.
|
|
243
|
+
*
|
|
244
|
+
* Escalation: the sentinel first (the watcher's own graceful path, and the
|
|
245
|
+
* only one that works on Windows without killing handlers), then SIGTERM,
|
|
246
|
+
* then SIGKILL. Signalling a pid is safe HERE where doctor refuses it: this
|
|
247
|
+
* pid was written by our own `startTracker` into a directory we created
|
|
248
|
+
* moments ago, so it is provably our child and not a recycled stranger.
|
|
249
|
+
* The directory is removed only once the process is gone; if it somehow
|
|
250
|
+
* survives even SIGKILL the directory is left in place so the files that
|
|
251
|
+
* name it are still there for a human.
|
|
252
|
+
*/
|
|
253
|
+
export async function stopSmokeWatcher(dir, opts = {}) {
|
|
254
|
+
const kill = opts.kill ?? ((pid, signal) => process.kill(pid, signal));
|
|
255
|
+
const graceMs = opts.graceMs ?? 3000;
|
|
256
|
+
const litmusDir = path.join(dir, ".litmus");
|
|
257
|
+
const alive = () => {
|
|
258
|
+
const diag = trackerDiagnostics(dir);
|
|
259
|
+
return diag.pid !== null && diag.pidAlive;
|
|
260
|
+
};
|
|
261
|
+
const waitForExit = async (ms) => {
|
|
262
|
+
const deadline = Date.now() + ms;
|
|
263
|
+
while (Date.now() < deadline) {
|
|
264
|
+
if (!alive())
|
|
265
|
+
return true;
|
|
266
|
+
await new Promise((r) => setTimeout(r, 100));
|
|
267
|
+
}
|
|
268
|
+
return !alive();
|
|
269
|
+
};
|
|
270
|
+
const remove = () => {
|
|
271
|
+
try {
|
|
272
|
+
rmSync(dir, { recursive: true, force: true });
|
|
273
|
+
}
|
|
274
|
+
catch { /* a still-held handle on Windows; the OS temp cleaner takes it */ }
|
|
275
|
+
};
|
|
276
|
+
if (!alive()) {
|
|
277
|
+
remove();
|
|
278
|
+
return { exited: true, how: "never_started" };
|
|
279
|
+
}
|
|
280
|
+
try {
|
|
281
|
+
writeFileSync(path.join(litmusDir, "shutdown"), "", "utf8");
|
|
282
|
+
}
|
|
283
|
+
catch { /* fall through to signals */ }
|
|
284
|
+
if (await waitForExit(graceMs)) {
|
|
285
|
+
remove();
|
|
286
|
+
return { exited: true, how: "sentinel" };
|
|
287
|
+
}
|
|
288
|
+
const pid = trackerDiagnostics(dir).pid;
|
|
289
|
+
if (pid !== null) {
|
|
290
|
+
try {
|
|
291
|
+
kill(pid, "SIGTERM");
|
|
292
|
+
}
|
|
293
|
+
catch { /* already gone */ }
|
|
294
|
+
if (await waitForExit(graceMs)) {
|
|
295
|
+
remove();
|
|
296
|
+
return { exited: true, how: "sigterm" };
|
|
297
|
+
}
|
|
298
|
+
try {
|
|
299
|
+
kill(pid, "SIGKILL");
|
|
300
|
+
}
|
|
301
|
+
catch { /* already gone */ }
|
|
302
|
+
if (await waitForExit(graceMs)) {
|
|
303
|
+
remove();
|
|
304
|
+
return { exited: true, how: "sigkill" };
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
return { exited: false, how: "survived" };
|
|
308
|
+
}
|
|
309
|
+
// ── Composition ──────────────────────────────────────────────────────
|
|
310
|
+
/**
|
|
311
|
+
* The checks a candidate can act on before init, in the order they print.
|
|
312
|
+
* `apiBase` is the resolved frontend base (`resolveApiBase`).
|
|
313
|
+
*/
|
|
314
|
+
export async function runEnvironmentChecks(opts) {
|
|
315
|
+
const results = [];
|
|
316
|
+
const push = (c) => { results.push(c); opts.record(c); };
|
|
317
|
+
push(checkNodeVersion());
|
|
318
|
+
push(await checkCliVersion());
|
|
319
|
+
push(checkGit());
|
|
320
|
+
push(await checkServerReachable({ apiBase: opts.apiBase }));
|
|
321
|
+
push(await checkWatcherBoot());
|
|
322
|
+
return results;
|
|
323
|
+
}
|
|
324
|
+
//# sourceMappingURL=environment-checks.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"environment-checks.js","sourceRoot":"","sources":["../../src/lib/environment-checks.ts"],"names":[],"mappings":"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"}
|