@geonosis/doctor 2.0.0 → 2.1.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/README.md +9 -7
- package/dist/{chunk-SMCRXSH5.js → chunk-R2R2OYH3.js} +495 -404
- package/dist/doctor-cli.js +115 -1
- package/dist/index.d.ts +3 -1
- package/dist/index.js +1 -1
- package/package.json +5 -2
package/dist/doctor-cli.js
CHANGED
|
@@ -1,12 +1,99 @@
|
|
|
1
1
|
import {
|
|
2
2
|
CHECKS,
|
|
3
|
+
ENVELOPES_DIR,
|
|
3
4
|
formatDoctor,
|
|
4
5
|
formatJson,
|
|
5
6
|
runDoctor
|
|
6
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-R2R2OYH3.js";
|
|
7
8
|
|
|
8
9
|
// src/doctor-cli.ts
|
|
10
|
+
import { fstatSync, statSync } from "fs";
|
|
9
11
|
import { resolve } from "path";
|
|
12
|
+
|
|
13
|
+
// src/envelope-write.ts
|
|
14
|
+
import { mkdirSync, readFileSync, writeFileSync } from "fs";
|
|
15
|
+
import { dirname, join } from "path";
|
|
16
|
+
import { fileURLToPath } from "url";
|
|
17
|
+
var envelopePath = (root, tool) => join(root, ENVELOPES_DIR, `${tool}.json`);
|
|
18
|
+
var UnbalancedEnvelope = class extends Error {
|
|
19
|
+
constructor(message) {
|
|
20
|
+
super(message);
|
|
21
|
+
this.name = "UnbalancedEnvelope";
|
|
22
|
+
}
|
|
23
|
+
};
|
|
24
|
+
var isCount = (value) => Number.isSafeInteger(value) && value >= 0;
|
|
25
|
+
var unbalancedMessage = (envelope, next) => `${envelope.tool}: considered ${envelope.considered} but accounts for ${envelope.read + envelope.refused.length + envelope.excused.length} \u2014 ${envelope.read} read + ${envelope.refused.length} refused + ${envelope.excused.length} excused. A run that has lost count of its own inputs cannot say what it measured, so no verdict was rendered and no envelope was written. Next: ${next}`;
|
|
26
|
+
var writeEnvelope = ({
|
|
27
|
+
envelope,
|
|
28
|
+
next,
|
|
29
|
+
root
|
|
30
|
+
}) => {
|
|
31
|
+
if (envelope.tool.trim() === "") {
|
|
32
|
+
throw new UnbalancedEnvelope(
|
|
33
|
+
`an envelope with no tool name cannot be filed or reported against. Next: ${next}`
|
|
34
|
+
);
|
|
35
|
+
}
|
|
36
|
+
if (envelope.version.trim() === "") {
|
|
37
|
+
throw new UnbalancedEnvelope(
|
|
38
|
+
`${envelope.tool}: an envelope that cannot name the build that wrote it dates nothing, and a stale one reads exactly like a fresh one. Next: ${next}`
|
|
39
|
+
);
|
|
40
|
+
}
|
|
41
|
+
if (!isCount(envelope.considered) || !isCount(envelope.read)) {
|
|
42
|
+
throw new UnbalancedEnvelope(
|
|
43
|
+
`${envelope.tool}: considered ${envelope.considered} and read ${envelope.read} \u2014 a census is a whole number of things, and arithmetic over anything else balances by accident. Next: ${next}`
|
|
44
|
+
);
|
|
45
|
+
}
|
|
46
|
+
if (envelope.considered !== envelope.read + envelope.refused.length + envelope.excused.length) {
|
|
47
|
+
throw new UnbalancedEnvelope(unbalancedMessage(envelope, next));
|
|
48
|
+
}
|
|
49
|
+
const at = envelopePath(root, envelope.tool);
|
|
50
|
+
mkdirSync(dirname(at), { recursive: true });
|
|
51
|
+
writeFileSync(at, `${JSON.stringify(envelope, void 0, 2)}
|
|
52
|
+
`);
|
|
53
|
+
return at;
|
|
54
|
+
};
|
|
55
|
+
var UNKNOWN = "unknown";
|
|
56
|
+
var versionIn = (dir) => {
|
|
57
|
+
try {
|
|
58
|
+
const manifest = JSON.parse(readFileSync(join(dir, "package.json"), "utf8"));
|
|
59
|
+
return typeof manifest.version === "string" ? manifest.version : void 0;
|
|
60
|
+
} catch {
|
|
61
|
+
return void 0;
|
|
62
|
+
}
|
|
63
|
+
};
|
|
64
|
+
var versionOf = (moduleUrl) => {
|
|
65
|
+
let dir = dirname(fileURLToPath(moduleUrl));
|
|
66
|
+
for (; ; ) {
|
|
67
|
+
const found = versionIn(dir);
|
|
68
|
+
if (found !== void 0) return found;
|
|
69
|
+
const up = dirname(dir);
|
|
70
|
+
if (up === dir) return UNKNOWN;
|
|
71
|
+
dir = up;
|
|
72
|
+
}
|
|
73
|
+
};
|
|
74
|
+
var DOCTOR_TOOL = "doctor";
|
|
75
|
+
var DOCTOR_NEXT = "geonosis-doctor --json and count the checks it printed \u2014 this run considered every question the tool has, and a check nobody asked for is excused by name rather than left out of the denominator";
|
|
76
|
+
var doctorEnvelope = ({
|
|
77
|
+
durationMs,
|
|
78
|
+
report
|
|
79
|
+
}) => {
|
|
80
|
+
const ran = new Set(report.ran);
|
|
81
|
+
return {
|
|
82
|
+
considered: CHECKS.length,
|
|
83
|
+
durationMs,
|
|
84
|
+
excused: CHECKS.filter((check) => !ran.has(check)).map((check) => ({
|
|
85
|
+
path: check,
|
|
86
|
+
reason: "not asked for by --only, so this run says nothing about it"
|
|
87
|
+
})),
|
|
88
|
+
findings: report.findings,
|
|
89
|
+
read: report.ran.length,
|
|
90
|
+
refused: [],
|
|
91
|
+
tool: DOCTOR_TOOL,
|
|
92
|
+
version: versionOf(import.meta.url)
|
|
93
|
+
};
|
|
94
|
+
};
|
|
95
|
+
|
|
96
|
+
// src/doctor-cli.ts
|
|
10
97
|
var ABOUT = {
|
|
11
98
|
baseline: `The ratchet's numbers at HEAD against another ref. A ratchet lowers its own baseline
|
|
12
99
|
when a number shrinks, so nothing inside one checkout can see a branch raise one back
|
|
@@ -94,6 +181,10 @@ plugin-route-namespaced on its package root, while the shipped corpus says acme
|
|
|
94
181
|
|
|
95
182
|
--print-config-shape every file this reads, and the keys it reads out of each
|
|
96
183
|
|
|
184
|
+
Every run writes .geonosis/envelopes/doctor.json: the ten checks CONSIDERED against the ones this
|
|
185
|
+
run read, with the rest excused by name, so a --only run can never read as a verdict about the whole
|
|
186
|
+
tree. The envelope check SKIPs that one file \u2014 this run is the one writing it.
|
|
187
|
+
|
|
97
188
|
Exits 1 when any line is a FAIL or an UNJUDGED \u2014 a question this could not ask is not a pass \u2014 and
|
|
98
189
|
2 when the run could not be made at all. --strict promotes every WARN to a FAIL. --json prints the
|
|
99
190
|
whole report for a CI step to read.`;
|
|
@@ -186,6 +277,15 @@ geonosis.json \u2192 "rails.egress"
|
|
|
186
277
|
.geonosis/rails-run.json
|
|
187
278
|
deniedEgress object[] what a run reached for and was refused. A GATE AT ZERO (D-025): one
|
|
188
279
|
entry fails, and it is never a counter to hold flat`;
|
|
280
|
+
var sameFile = (fd, path) => {
|
|
281
|
+
try {
|
|
282
|
+
const open = fstatSync(fd);
|
|
283
|
+
const there = statSync(path);
|
|
284
|
+
return open.dev === there.dev && open.ino === there.ino;
|
|
285
|
+
} catch {
|
|
286
|
+
return false;
|
|
287
|
+
}
|
|
288
|
+
};
|
|
189
289
|
var main = async () => {
|
|
190
290
|
const argv = process.argv.slice(2);
|
|
191
291
|
if (argv.includes("--help") || argv.includes("-h")) {
|
|
@@ -199,7 +299,21 @@ var main = async () => {
|
|
|
199
299
|
return 0;
|
|
200
300
|
}
|
|
201
301
|
const { json, ...options } = parseDoctorArgs(argv, process.cwd());
|
|
302
|
+
const started = Date.now();
|
|
202
303
|
const report = await runDoctor(options);
|
|
304
|
+
const at = envelopePath(options.root, "doctor");
|
|
305
|
+
if (sameFile(process.stdout.fd, at)) {
|
|
306
|
+
process.stderr.write(
|
|
307
|
+
`geonosis-doctor: stdout is ${ENVELOPES_DIR}/doctor.json, so no envelope was written \u2014 it would have overwritten the report redirected there. Send --json somewhere else and the envelope is written after every run.
|
|
308
|
+
`
|
|
309
|
+
);
|
|
310
|
+
} else {
|
|
311
|
+
writeEnvelope({
|
|
312
|
+
envelope: doctorEnvelope({ durationMs: Date.now() - started, report }),
|
|
313
|
+
next: DOCTOR_NEXT,
|
|
314
|
+
root: options.root
|
|
315
|
+
});
|
|
316
|
+
}
|
|
203
317
|
process.stdout.write(json ? formatJson(report) : formatDoctor(report));
|
|
204
318
|
return report.ok ? 0 : 1;
|
|
205
319
|
};
|
package/dist/index.d.ts
CHANGED
|
@@ -83,6 +83,8 @@ type DoctorOptions = {
|
|
|
83
83
|
type DoctorReport = {
|
|
84
84
|
counts: Record<Verdict, number>;
|
|
85
85
|
findings: Finding[];
|
|
86
|
+
/** The checks this run asked. `--only` makes it a subset, and the envelope's denominator needs it. */
|
|
87
|
+
ran: CheckName[];
|
|
86
88
|
/**
|
|
87
89
|
* False as soon as one line is a FAIL or an UNJUDGED — after `--strict` has promoted the
|
|
88
90
|
* warnings. "We could not tell" is not a pass; it is the quietest way there is of reading green.
|
|
@@ -189,7 +191,7 @@ declare const checkDrift: ({ readers, root, userSettings, workspaces, }: {
|
|
|
189
191
|
* duplicated here on purpose: it is one comparison over three numbers, and it is the check.
|
|
190
192
|
*/
|
|
191
193
|
declare const ENVELOPES_DIR = ".geonosis/envelopes";
|
|
192
|
-
declare const NO_ENVELOPES = "no .geonosis/envelopes/*.json \u2014 the tools write one per run, so an absent envelope is a run nobody has made here yet, and it is not a balanced one";
|
|
194
|
+
declare const NO_ENVELOPES = "no .geonosis/envelopes/*.json \u2014 the tools write one per run, so an absent envelope is a run nobody has made here yet, and it is not a balanced one (this run\u2019s own doctor.json is not one of them: it is written after these checks, and balanced at write time)";
|
|
193
195
|
declare const checkEnvelopes: ({ root }: {
|
|
194
196
|
root: string;
|
|
195
197
|
}) => Finding[];
|
package/dist/index.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@geonosis/doctor",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.1.0",
|
|
4
4
|
"types": "./dist/index.d.ts",
|
|
5
5
|
"description": "The adoption doctor — declared ≠ loaded, enabled ≠ exercised, a baseline that grew, a runner whose exit code is the only verdict.",
|
|
6
6
|
"keywords": [
|
|
@@ -35,7 +35,10 @@
|
|
|
35
35
|
"dist"
|
|
36
36
|
],
|
|
37
37
|
"dependencies": {
|
|
38
|
-
"@geonosis/lint-parity": "2.
|
|
38
|
+
"@geonosis/lint-parity": "2.1.0"
|
|
39
|
+
},
|
|
40
|
+
"devDependencies": {
|
|
41
|
+
"@geonosis/ratchet": "2.1.0"
|
|
39
42
|
},
|
|
40
43
|
"peerDependencies": {
|
|
41
44
|
"oxlint": ">=1.77"
|