@geonosis/release 2.1.0 → 2.2.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/dist/{chunk-MZWAN6WT.js → chunk-IPCIF5DO.js} +79 -32
- package/dist/index.d.ts +93 -65
- package/dist/index.js +1 -1
- package/dist/release-cli.js +6 -4
- package/package.json +2 -2
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
// src/phases.ts
|
|
2
|
+
var PHASES = ["typecheck", "lint", "test", "doctor"];
|
|
3
|
+
|
|
1
4
|
// src/config.ts
|
|
2
5
|
import { existsSync, readFileSync } from "fs";
|
|
3
6
|
import { resolve } from "path";
|
|
@@ -96,17 +99,15 @@ var parseSchema = (value2) => {
|
|
|
96
99
|
};
|
|
97
100
|
var SMOKE_KEYS = "expected { exclude?, snapshots? }";
|
|
98
101
|
var SNAPSHOT_KEYS = "expected { commands?, install?, name }";
|
|
99
|
-
var SMOKE_PHASES =
|
|
102
|
+
var SMOKE_PHASES = PHASES;
|
|
100
103
|
var parseCommands = (value2, at) => {
|
|
101
104
|
if (value2 === void 0) return {};
|
|
102
105
|
if (!isRecord(value2)) {
|
|
103
106
|
throw new CannotRun(
|
|
104
|
-
`${at}.commands must be an object \u2014 expected
|
|
107
|
+
`${at}.commands must be an object \u2014 expected one command per phase: ${PHASES.map((one) => `${one}?`).join(", ")}`
|
|
105
108
|
);
|
|
106
109
|
}
|
|
107
|
-
const unknown = Object.keys(value2).find(
|
|
108
|
-
(key) => !SMOKE_PHASES.includes(key)
|
|
109
|
-
);
|
|
110
|
+
const unknown = Object.keys(value2).find((key) => !SMOKE_PHASES.includes(key));
|
|
110
111
|
if (unknown !== void 0) {
|
|
111
112
|
throw new CannotRun(
|
|
112
113
|
`${at}.commands.${unknown} is not a phase the smoke runs \u2014 it runs ${SMOKE_PHASES.join(", ")}`
|
|
@@ -210,7 +211,7 @@ var readReleaseConfig = (root) => {
|
|
|
210
211
|
|
|
211
212
|
// src/envelope.ts
|
|
212
213
|
import { mkdirSync, readFileSync as readFileSync2, writeFileSync } from "fs";
|
|
213
|
-
import { dirname, join } from "path";
|
|
214
|
+
import { dirname, join, resolve as resolve2 } from "path";
|
|
214
215
|
import { fileURLToPath } from "url";
|
|
215
216
|
var ENVELOPES_DIR = ".geonosis/envelopes";
|
|
216
217
|
var envelopePath = (root, tool) => join(root, ENVELOPES_DIR, `${tool}.json`);
|
|
@@ -222,6 +223,14 @@ var UnbalancedEnvelope = class extends Error {
|
|
|
222
223
|
};
|
|
223
224
|
var isCount = (value2) => Number.isSafeInteger(value2) && value2 >= 0;
|
|
224
225
|
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}`;
|
|
226
|
+
var FORBIDDEN_ROOT = "GEONOSIS_ENVELOPES_FORBIDDEN_ROOT";
|
|
227
|
+
var refuseForbiddenRoot = (root) => {
|
|
228
|
+
const forbidden = process.env[FORBIDDEN_ROOT];
|
|
229
|
+
if (forbidden === void 0 || resolve2(forbidden) !== resolve2(root)) return;
|
|
230
|
+
throw new UnbalancedEnvelope(
|
|
231
|
+
`${root} is off limits to envelope writers in this process (${FORBIDDEN_ROOT}) \u2014 a run that writes one into a shared root races every other run reading it, and leaves a file the next one takes for real. Point this at a scratch root of its own: tooling/scratch-dir.ts.`
|
|
232
|
+
);
|
|
233
|
+
};
|
|
225
234
|
var writeEnvelope = ({
|
|
226
235
|
envelope,
|
|
227
236
|
next,
|
|
@@ -245,6 +254,7 @@ var writeEnvelope = ({
|
|
|
245
254
|
if (envelope.considered !== envelope.read + envelope.refused.length + envelope.excused.length) {
|
|
246
255
|
throw new UnbalancedEnvelope(unbalancedMessage(envelope, next));
|
|
247
256
|
}
|
|
257
|
+
refuseForbiddenRoot(root);
|
|
248
258
|
const at = envelopePath(root, envelope.tool);
|
|
249
259
|
mkdirSync(dirname(at), { recursive: true });
|
|
250
260
|
writeFileSync(at, `${JSON.stringify(envelope, void 0, 2)}
|
|
@@ -496,7 +506,7 @@ import {
|
|
|
496
506
|
statSync,
|
|
497
507
|
writeFileSync as writeFileSync2
|
|
498
508
|
} from "fs";
|
|
499
|
-
import { join as join3, relative as relative2, resolve as
|
|
509
|
+
import { join as join3, relative as relative2, resolve as resolve3 } from "path";
|
|
500
510
|
var SNAPSHOTS_DIR = ".geonosis/consumer-snapshots";
|
|
501
511
|
var LOCKFILES = [
|
|
502
512
|
{ file: "bun.lock", manager: "bun" },
|
|
@@ -509,6 +519,7 @@ var UNMEASURED = [
|
|
|
509
519
|
];
|
|
510
520
|
var EXCLUDED_DIRS = [
|
|
511
521
|
".cache",
|
|
522
|
+
".claude",
|
|
512
523
|
".geonosis",
|
|
513
524
|
".git",
|
|
514
525
|
".next",
|
|
@@ -519,7 +530,6 @@ var EXCLUDED_DIRS = [
|
|
|
519
530
|
"node_modules",
|
|
520
531
|
"storybook-static"
|
|
521
532
|
];
|
|
522
|
-
var PHASES = ["typecheck", "lint", "doctor"];
|
|
523
533
|
var headOf = (from) => {
|
|
524
534
|
const done = spawnSync("git", ["-C", from, "rev-parse", "HEAD"], { encoding: "utf8" });
|
|
525
535
|
if (done.error !== void 0) {
|
|
@@ -628,11 +638,40 @@ var commandsFor = (manifest, manifests, named) => {
|
|
|
628
638
|
return {
|
|
629
639
|
doctor: phase("doctor", doctorCommand),
|
|
630
640
|
lint: phase("lint", { why: 'the tree has no "lint" script and no --lint command was named' }),
|
|
641
|
+
test: phase("test", { why: 'the tree has no "test" script and no --test command was named' }),
|
|
631
642
|
typecheck: phase("typecheck", {
|
|
632
643
|
why: 'the tree has no "typecheck" script and no --typecheck command was named'
|
|
633
644
|
})
|
|
634
645
|
};
|
|
635
646
|
};
|
|
647
|
+
var asPattern = (glob) => new RegExp(
|
|
648
|
+
`^${glob.split("/").map(
|
|
649
|
+
(part) => part === "**" ? ".*" : part.replaceAll(/[.+^${}()|[\]\\]/g, String.raw`\$&`).replaceAll("*", "[^/]*")
|
|
650
|
+
).join("/").replaceAll(".*/", "(?:.*/)?")}$`
|
|
651
|
+
);
|
|
652
|
+
var filesUnder = (root, at = root) => readdirSync2(at, { withFileTypes: true }).flatMap((entry) => {
|
|
653
|
+
const full = join3(at, entry.name);
|
|
654
|
+
if (entry.isDirectory()) return filesUnder(root, full);
|
|
655
|
+
return entry.isFile() ? [full.slice(root.length + 1)] : [];
|
|
656
|
+
});
|
|
657
|
+
var seamsIn = (tree) => {
|
|
658
|
+
const at = join3(tree, "geonosis.json");
|
|
659
|
+
if (!existsSync2(at)) return void 0;
|
|
660
|
+
let globs;
|
|
661
|
+
try {
|
|
662
|
+
const declared = JSON.parse(readFileSync4(at, "utf8")).adoption?.seams;
|
|
663
|
+
globs = Array.isArray(declared) ? declared.filter((one) => typeof one === "string") : [];
|
|
664
|
+
} catch {
|
|
665
|
+
return void 0;
|
|
666
|
+
}
|
|
667
|
+
if (globs.length === 0) return void 0;
|
|
668
|
+
const patterns = globs.map(asPattern);
|
|
669
|
+
const lines2 = filesUnder(tree).filter((one) => patterns.some((pattern) => pattern.test(one))).reduce((total, one) => {
|
|
670
|
+
const body = readFileSync4(join3(tree, one), "utf8");
|
|
671
|
+
return total + (body === "" ? 0 : body.replace(/\n$/, "").split("\n").length);
|
|
672
|
+
}, 0);
|
|
673
|
+
return { globs, lines: lines2 };
|
|
674
|
+
};
|
|
636
675
|
var snapshotDir = (root, name) => join3(root, SNAPSHOTS_DIR, name);
|
|
637
676
|
var readSnapshot = (root, name) => {
|
|
638
677
|
const at = join3(snapshotDir(root, name), "snapshot.json");
|
|
@@ -655,7 +694,7 @@ var runSnapshot = (input) => {
|
|
|
655
694
|
`"${input.name}" is not a snapshot name \u2014 a name is letters, digits, dots, dashes and underscores, so that ${SNAPSHOTS_DIR}/<name> is the only place the bytes can land`
|
|
656
695
|
);
|
|
657
696
|
}
|
|
658
|
-
const from =
|
|
697
|
+
const from = resolve3(input.from);
|
|
659
698
|
if (!existsSync2(join3(from, "package.json"))) {
|
|
660
699
|
throw new CannotRun(`${from} has no package.json \u2014 that is not a tree a consumer installs`);
|
|
661
700
|
}
|
|
@@ -676,9 +715,11 @@ var runSnapshot = (input) => {
|
|
|
676
715
|
const tree = join3(at, "tree");
|
|
677
716
|
const { bytes, files } = copyInto(from, tree, new Set(excluded));
|
|
678
717
|
const manifests = manifestsUnder2(tree);
|
|
718
|
+
const seams = seamsIn(tree);
|
|
679
719
|
const record = {
|
|
680
720
|
at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
681
721
|
bytes,
|
|
722
|
+
...seams === void 0 ? {} : { seams },
|
|
682
723
|
commit: headOf(from),
|
|
683
724
|
commands: commandsFor(readManifest(join3(tree, "package.json")), manifests, input.named),
|
|
684
725
|
excluded,
|
|
@@ -822,9 +863,12 @@ var runAdoption = async ({
|
|
|
822
863
|
});
|
|
823
864
|
continue;
|
|
824
865
|
}
|
|
825
|
-
const
|
|
866
|
+
const record = readSnapshot(root, one.name);
|
|
867
|
+
const declarations = declarationsIn(record, new Set(current.keys()));
|
|
868
|
+
const seams = record.seams;
|
|
826
869
|
consumers.push({
|
|
827
870
|
declared: declarations.length,
|
|
871
|
+
...seams === void 0 ? {} : { seams },
|
|
828
872
|
findings: [
|
|
829
873
|
...distance(one.name, declarations, current),
|
|
830
874
|
...incoherence(one.name, groups, declarations),
|
|
@@ -854,7 +898,10 @@ var blockFor = (consumer) => {
|
|
|
854
898
|
const head = faults.length === 0 ? [
|
|
855
899
|
` MATCH ${consumer.name} \u2014 ${consumer.declared} spec(s) on the versions this release is cut at`
|
|
856
900
|
] : [];
|
|
857
|
-
|
|
901
|
+
const seams = consumer.seams === void 0 ? [] : [
|
|
902
|
+
` SEAMS ${consumer.name} \u2014 ${consumer.seams.lines} lines in ${consumer.seams.globs.join(", ")} at this recording; a floor is adopted the day it deletes more than it adds`
|
|
903
|
+
];
|
|
904
|
+
return [...head, ...seams, ...new Set(consumer.findings.map(lineOf))];
|
|
858
905
|
};
|
|
859
906
|
var formatAdoption = (report) => [
|
|
860
907
|
`adoption \u2014 ${report.considered} declared, ${report.consumers.length} read, ${report.excused.length} excused; against ${report.registry ?? "this workspace"}`,
|
|
@@ -877,7 +924,7 @@ var adoptionEnvelope = (report, durationMs) => ({
|
|
|
877
924
|
|
|
878
925
|
// src/wrangler.ts
|
|
879
926
|
import { readFileSync as readFileSync6 } from "fs";
|
|
880
|
-
import { resolve as
|
|
927
|
+
import { resolve as resolve4 } from "path";
|
|
881
928
|
var isRecord3 = (value2) => typeof value2 === "object" && value2 !== null && !Array.isArray(value2);
|
|
882
929
|
var parseJsonc = (source) => {
|
|
883
930
|
let out = "";
|
|
@@ -1054,7 +1101,7 @@ var declaredIn = (config) => {
|
|
|
1054
1101
|
};
|
|
1055
1102
|
};
|
|
1056
1103
|
var readWrangler = (root, relative5, env) => {
|
|
1057
|
-
const path =
|
|
1104
|
+
const path = resolve4(root, relative5);
|
|
1058
1105
|
let parsed;
|
|
1059
1106
|
try {
|
|
1060
1107
|
const source = readFileSync6(path, "utf8");
|
|
@@ -1070,13 +1117,13 @@ var readWrangler = (root, relative5, env) => {
|
|
|
1070
1117
|
|
|
1071
1118
|
// src/deployed.ts
|
|
1072
1119
|
import { existsSync as existsSync4, readFileSync as readFileSync7 } from "fs";
|
|
1073
|
-
import { resolve as
|
|
1120
|
+
import { resolve as resolve5 } from "path";
|
|
1074
1121
|
var DEPLOYED_FILE = ".geonosis/deployed.json";
|
|
1075
1122
|
var NOTHING_SAYS = "nothing here says what is deployed \u2014 .geonosis/deployed.json is written by the pipeline after promote, and its absence is not a pass";
|
|
1076
1123
|
var listOf = (found) => Array.isArray(found) ? found.filter((one) => typeof one === "string") : [];
|
|
1077
1124
|
var isRecord4 = (value2) => typeof value2 === "object" && value2 !== null && !Array.isArray(value2);
|
|
1078
1125
|
var readDeployed = (root) => {
|
|
1079
|
-
const path =
|
|
1126
|
+
const path = resolve5(root, DEPLOYED_FILE);
|
|
1080
1127
|
if (!existsSync4(path)) throw new CannotRun(NOTHING_SAYS);
|
|
1081
1128
|
let parsed;
|
|
1082
1129
|
try {
|
|
@@ -1359,18 +1406,18 @@ var refusalsIn = (path, body, firstLine = 1) => {
|
|
|
1359
1406
|
// src/migrations.ts
|
|
1360
1407
|
import { mkdtempSync, readFileSync as readFileSync8, rmSync as rmSync2, writeFileSync as writeFileSync3 } from "fs";
|
|
1361
1408
|
import { tmpdir } from "os";
|
|
1362
|
-
import { basename, join as join5, resolve as
|
|
1409
|
+
import { basename, join as join5, resolve as resolve7 } from "path";
|
|
1363
1410
|
|
|
1364
1411
|
// src/squawk.ts
|
|
1365
1412
|
import { spawnSync as spawnSync3 } from "child_process";
|
|
1366
1413
|
import { existsSync as existsSync5 } from "fs";
|
|
1367
|
-
import { dirname as dirname2, resolve as
|
|
1414
|
+
import { dirname as dirname2, resolve as resolve6 } from "path";
|
|
1368
1415
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
1369
1416
|
var HERE = dirname2(fileURLToPath2(import.meta.url));
|
|
1370
1417
|
var PINNED = "2.63.0";
|
|
1371
1418
|
var findSquawk = (from = HERE) => {
|
|
1372
1419
|
for (let dir = from; ; dir = dirname2(dir)) {
|
|
1373
|
-
const candidate =
|
|
1420
|
+
const candidate = resolve6(dir, "node_modules/.bin/squawk");
|
|
1374
1421
|
if (existsSync5(candidate)) return candidate;
|
|
1375
1422
|
if (dirname2(dir) === dir) break;
|
|
1376
1423
|
}
|
|
@@ -1452,7 +1499,7 @@ var runMigrations = (input) => {
|
|
|
1452
1499
|
const forSquawk = [];
|
|
1453
1500
|
const states = /* @__PURE__ */ new Map();
|
|
1454
1501
|
for (const { entry, file } of matched) {
|
|
1455
|
-
const source = readFileSync8(
|
|
1502
|
+
const source = readFileSync8(resolve7(input.root, file), "utf8");
|
|
1456
1503
|
const found = markersIn(source);
|
|
1457
1504
|
const bad = found.flatMap((one) => {
|
|
1458
1505
|
const why = judge(one, input.root, input.since);
|
|
@@ -1480,7 +1527,7 @@ var runMigrations = (input) => {
|
|
|
1480
1527
|
const staging = mkdtempSync(join5(tmpdir(), "geonosis-release-squawk-"));
|
|
1481
1528
|
try {
|
|
1482
1529
|
for (const one of forSquawk) {
|
|
1483
|
-
const path = one.entry.dialect === "mikro-orm-ts" ? join5(staging, `${basename(one.file, ".ts")}.sql`) :
|
|
1530
|
+
const path = one.entry.dialect === "mikro-orm-ts" ? join5(staging, `${basename(one.file, ".ts")}.sql`) : resolve7(input.root, one.file);
|
|
1484
1531
|
if (one.entry.dialect === "mikro-orm-ts") writeFileSync3(path, `${one.sql}
|
|
1485
1532
|
`);
|
|
1486
1533
|
const found = squawkOn({
|
|
@@ -1625,7 +1672,7 @@ var Runner = class {
|
|
|
1625
1672
|
if (this.closed !== void 0) {
|
|
1626
1673
|
throw new CannotRun(`the runner is gone before "${request.step}": ${this.closed}`);
|
|
1627
1674
|
}
|
|
1628
|
-
const line = await new Promise((
|
|
1675
|
+
const line = await new Promise((resolve10, reject) => {
|
|
1629
1676
|
const timer = setTimeout(() => {
|
|
1630
1677
|
reject(
|
|
1631
1678
|
new CannotRun(
|
|
@@ -1635,7 +1682,7 @@ var Runner = class {
|
|
|
1635
1682
|
}, timeoutMs);
|
|
1636
1683
|
this.waiting.push((answer) => {
|
|
1637
1684
|
clearTimeout(timer);
|
|
1638
|
-
|
|
1685
|
+
resolve10(answer);
|
|
1639
1686
|
});
|
|
1640
1687
|
this.child.on("close", () => {
|
|
1641
1688
|
clearTimeout(timer);
|
|
@@ -1749,10 +1796,10 @@ var formatVerdict = (verdict) => verdict.ok ? `OK prove: ${verdict.steps.join
|
|
|
1749
1796
|
|
|
1750
1797
|
// src/schema-walls.ts
|
|
1751
1798
|
import { readdirSync as readdirSync3, readFileSync as readFileSync9 } from "fs";
|
|
1752
|
-
import { join as join6, relative as relative3, resolve as
|
|
1799
|
+
import { join as join6, relative as relative3, resolve as resolve8, sep as sep2 } from "path";
|
|
1753
1800
|
var MIGRATION_FILE = /\.(?:sql|ts)$/;
|
|
1754
1801
|
var CURRENT_SETTING = /current_setting\s*\(\s*'([^']+)'/gi;
|
|
1755
|
-
var
|
|
1802
|
+
var filesUnder2 = (root, dir) => {
|
|
1756
1803
|
const found = [];
|
|
1757
1804
|
const walk = (at) => {
|
|
1758
1805
|
let entries;
|
|
@@ -1767,7 +1814,7 @@ var filesUnder = (root, dir) => {
|
|
|
1767
1814
|
else if (MIGRATION_FILE.test(entry.name)) found.push(path);
|
|
1768
1815
|
}
|
|
1769
1816
|
};
|
|
1770
|
-
walk(
|
|
1817
|
+
walk(resolve8(root, dir));
|
|
1771
1818
|
return found.map((path) => relative3(root, path).split(sep2).join("/")).toSorted();
|
|
1772
1819
|
};
|
|
1773
1820
|
var lineOf3 = (body, index) => body.slice(0, index).split("\n").length;
|
|
@@ -1820,11 +1867,11 @@ var runSchema = ({ root }) => {
|
|
|
1820
1867
|
);
|
|
1821
1868
|
}
|
|
1822
1869
|
const dirs = schema.domains.map((one) => one.dir);
|
|
1823
|
-
const files = [...new Set(dirs.flatMap((dir) =>
|
|
1870
|
+
const files = [...new Set(dirs.flatMap((dir) => filesUnder2(root, dir)))].toSorted();
|
|
1824
1871
|
const findings = [];
|
|
1825
1872
|
const unreadable = [];
|
|
1826
1873
|
for (const path of files) {
|
|
1827
|
-
const source = readFileSync9(
|
|
1874
|
+
const source = readFileSync9(resolve8(root, path), "utf8");
|
|
1828
1875
|
let sql;
|
|
1829
1876
|
try {
|
|
1830
1877
|
sql = sqlOf(path, source);
|
|
@@ -1864,7 +1911,7 @@ var formatSchema = (report) => {
|
|
|
1864
1911
|
// src/smoke-run.ts
|
|
1865
1912
|
import { spawnSync as spawnSync4 } from "child_process";
|
|
1866
1913
|
import { existsSync as existsSync7, mkdirSync as mkdirSync3, readdirSync as readdirSync4, readFileSync as readFileSync10, rmSync as rmSync3, writeFileSync as writeFileSync4 } from "fs";
|
|
1867
|
-
import { join as join7, relative as relative4, resolve as
|
|
1914
|
+
import { join as join7, relative as relative4, resolve as resolve9 } from "path";
|
|
1868
1915
|
var BASELINE_FILE = "baseline.json";
|
|
1869
1916
|
var INSTALL = {
|
|
1870
1917
|
bun: ["install"],
|
|
@@ -2064,8 +2111,8 @@ var smokeOver = (input) => {
|
|
|
2064
2111
|
rmSync3(work, { force: true, recursive: true });
|
|
2065
2112
|
copyInto(join7(at, "tree"), work, new Set(EXCLUDED_DIRS));
|
|
2066
2113
|
ownRepository(work);
|
|
2067
|
-
const packed = input.rc === void 0 ? [] : packRc(
|
|
2068
|
-
const findings = input.rc === void 0 ? [] : promisedButNotPacked(
|
|
2114
|
+
const packed = input.rc === void 0 ? [] : packRc(resolve9(input.rc), join7(at, "rc"));
|
|
2115
|
+
const findings = input.rc === void 0 ? [] : promisedButNotPacked(resolve9(input.rc), packed);
|
|
2069
2116
|
const swapped = rewriteManifests(
|
|
2070
2117
|
work,
|
|
2071
2118
|
record.manifests.map((one) => one.path),
|
|
@@ -2113,7 +2160,7 @@ var recordBaseline = (input) => {
|
|
|
2113
2160
|
at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
2114
2161
|
packed: packed.map((one) => ({ name: one.name, version: one.version })),
|
|
2115
2162
|
phases: outcomes,
|
|
2116
|
-
rc: input.rc === void 0 ? "the versions the tree names" :
|
|
2163
|
+
rc: input.rc === void 0 ? "the versions the tree names" : resolve9(input.rc)
|
|
2117
2164
|
};
|
|
2118
2165
|
writeFileSync4(baselinePath(input.root, input.name), `${JSON.stringify(baseline, void 0, 2)}
|
|
2119
2166
|
`);
|
|
@@ -2356,6 +2403,7 @@ var smokeEnvelope = (comparison, durationMs) => {
|
|
|
2356
2403
|
};
|
|
2357
2404
|
|
|
2358
2405
|
export {
|
|
2406
|
+
PHASES,
|
|
2359
2407
|
CannotRun,
|
|
2360
2408
|
parseReleaseConfig,
|
|
2361
2409
|
readReleaseConfig,
|
|
@@ -2375,7 +2423,6 @@ export {
|
|
|
2375
2423
|
formatPublished,
|
|
2376
2424
|
SNAPSHOTS_DIR,
|
|
2377
2425
|
EXCLUDED_DIRS,
|
|
2378
|
-
PHASES,
|
|
2379
2426
|
headOf,
|
|
2380
2427
|
snapshotDir,
|
|
2381
2428
|
readSnapshot,
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,96 @@
|
|
|
1
1
|
import { ReportEnvelope } from '@geonosis/ratchet';
|
|
2
2
|
|
|
3
|
+
/** What a phase runs: a script of theirs, a binary their install put there, or nothing at all. */
|
|
4
|
+
type Command = {
|
|
5
|
+
exec: string;
|
|
6
|
+
} | {
|
|
7
|
+
run: string;
|
|
8
|
+
} | {
|
|
9
|
+
why: string;
|
|
10
|
+
};
|
|
11
|
+
type SmokePhase = 'doctor' | 'lint' | 'test' | 'typecheck';
|
|
12
|
+
/**
|
|
13
|
+
* The gates a release is read against, in the order they run.
|
|
14
|
+
*
|
|
15
|
+
* Its own module because the runner and the config reader both need it and each imports the other:
|
|
16
|
+
* read through `smoke.ts`, `PHASES` was still undefined when `config.ts` initialised, and the
|
|
17
|
+
* config refused every `geonosis.json` with `Cannot read properties of undefined`.
|
|
18
|
+
*
|
|
19
|
+
* #272: `test` is here because a floor change can keep a consumer's types and their linter green
|
|
20
|
+
* and still redden their suites — the one thing only their own tests can say. A recording taken
|
|
21
|
+
* before it existed has no baseline for the phase, and a phase with nothing to compare against is
|
|
22
|
+
* reported as uncomparable rather than as a pass.
|
|
23
|
+
*/
|
|
24
|
+
declare const PHASES: SmokePhase[];
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Where a consumer's bytes live while the release is being read against them.
|
|
28
|
+
*
|
|
29
|
+
* D-048: a consumer tree is private, and a copy of one that reaches a commit cannot be taken back.
|
|
30
|
+
* The directory is under `.geonosis/`, which every repo in this kit's orbit already ignores, and
|
|
31
|
+
* `smoke snapshot` asks git — in the tree it is about to write into — whether that is still true
|
|
32
|
+
* before it copies a single file.
|
|
33
|
+
*/
|
|
34
|
+
declare const SNAPSHOTS_DIR = ".geonosis/consumer-snapshots";
|
|
35
|
+
/** The managers a snapshot can be installed with here, each measured on this machine. */
|
|
36
|
+
type Manager = 'bun' | 'pnpm';
|
|
37
|
+
/**
|
|
38
|
+
* Directories a consumer builds or installs into. They are excluded by name at every depth: the
|
|
39
|
+
* snapshot is the SOURCE of a tree, and the install the smoke runs is the thing under test.
|
|
40
|
+
*/
|
|
41
|
+
declare const EXCLUDED_DIRS: string[];
|
|
42
|
+
/** Where the source tree stood, or the sentence saying why nothing here could say. */
|
|
43
|
+
type RecordedCommit = {
|
|
44
|
+
sha: string;
|
|
45
|
+
} | {
|
|
46
|
+
why: string;
|
|
47
|
+
};
|
|
48
|
+
/**
|
|
49
|
+
* The seam a consumer declared, measured on the bytes this recording holds (#280).
|
|
50
|
+
*
|
|
51
|
+
* The user's rule for a floor: it is adopted the day it deletes more than it adds. The sweep can
|
|
52
|
+
* only say so about trees it has recorded, so the number is taken WHERE the tree is read — a
|
|
53
|
+
* `.geonosis/` of theirs never reaches a snapshot (it is an excluded directory), so their own bump
|
|
54
|
+
* report is not available here and this is the figure that is.
|
|
55
|
+
*/
|
|
56
|
+
type RecordedSeams = {
|
|
57
|
+
globs: string[];
|
|
58
|
+
lines: number;
|
|
59
|
+
};
|
|
60
|
+
type SnapshotRecord = {
|
|
61
|
+
at: string;
|
|
62
|
+
bytes: number;
|
|
63
|
+
/** Absent in a recording taken before this was recorded at all. */
|
|
64
|
+
commit?: RecordedCommit;
|
|
65
|
+
commands: Record<SmokePhase, Command>;
|
|
66
|
+
excluded: string[];
|
|
67
|
+
files: number;
|
|
68
|
+
from: string;
|
|
69
|
+
lockfile: string;
|
|
70
|
+
manager: Manager;
|
|
71
|
+
manifests: {
|
|
72
|
+
path: string;
|
|
73
|
+
versions: Record<string, string>;
|
|
74
|
+
}[];
|
|
75
|
+
name: string;
|
|
76
|
+
/** Absent when this consumer declares no `adoption.seams`, or the recording predates the block. */
|
|
77
|
+
seams?: RecordedSeams;
|
|
78
|
+
};
|
|
79
|
+
/** git asked in THEIR tree, and only ever asked: law 5 forbids this tool writing a byte there. */
|
|
80
|
+
declare const headOf: (from: string) => RecordedCommit;
|
|
81
|
+
declare const snapshotDir: (root: string, name: string) => string;
|
|
82
|
+
declare const readSnapshot: (root: string, name: string) => SnapshotRecord;
|
|
83
|
+
type SnapshotInput = {
|
|
84
|
+
exclude?: string[];
|
|
85
|
+
from: string;
|
|
86
|
+
name: string;
|
|
87
|
+
named: Partial<Record<SmokePhase, string>>;
|
|
88
|
+
replace: boolean;
|
|
89
|
+
root: string;
|
|
90
|
+
};
|
|
91
|
+
declare const runSnapshot: (input: SnapshotInput) => SnapshotRecord;
|
|
92
|
+
declare const formatSnapshot: (record: SnapshotRecord) => string;
|
|
93
|
+
|
|
3
94
|
type AdoptionVerdict = 'BEHIND' | 'FLOOR UNDECLARED' | 'INCOHERENT' | 'UNJUDGED';
|
|
4
95
|
type AdoptionFinding = {
|
|
5
96
|
consumer: string;
|
|
@@ -12,6 +103,7 @@ type AdoptionConsumer = {
|
|
|
12
103
|
declared: number;
|
|
13
104
|
findings: AdoptionFinding[];
|
|
14
105
|
name: string;
|
|
106
|
+
seams?: RecordedSeams;
|
|
15
107
|
};
|
|
16
108
|
type AdoptionReport = {
|
|
17
109
|
considered: number;
|
|
@@ -412,70 +504,6 @@ declare class Runner {
|
|
|
412
504
|
close(): void;
|
|
413
505
|
}
|
|
414
506
|
|
|
415
|
-
/**
|
|
416
|
-
* Where a consumer's bytes live while the release is being read against them.
|
|
417
|
-
*
|
|
418
|
-
* D-048: a consumer tree is private, and a copy of one that reaches a commit cannot be taken back.
|
|
419
|
-
* The directory is under `.geonosis/`, which every repo in this kit's orbit already ignores, and
|
|
420
|
-
* `smoke snapshot` asks git — in the tree it is about to write into — whether that is still true
|
|
421
|
-
* before it copies a single file.
|
|
422
|
-
*/
|
|
423
|
-
declare const SNAPSHOTS_DIR = ".geonosis/consumer-snapshots";
|
|
424
|
-
/** The managers a snapshot can be installed with here, each measured on this machine. */
|
|
425
|
-
type Manager = 'bun' | 'pnpm';
|
|
426
|
-
/**
|
|
427
|
-
* Directories a consumer builds or installs into. They are excluded by name at every depth: the
|
|
428
|
-
* snapshot is the SOURCE of a tree, and the install the smoke runs is the thing under test.
|
|
429
|
-
*/
|
|
430
|
-
declare const EXCLUDED_DIRS: string[];
|
|
431
|
-
/** What a phase runs: a script of theirs, a binary their install put there, or nothing at all. */
|
|
432
|
-
type Command = {
|
|
433
|
-
exec: string;
|
|
434
|
-
} | {
|
|
435
|
-
run: string;
|
|
436
|
-
} | {
|
|
437
|
-
why: string;
|
|
438
|
-
};
|
|
439
|
-
type SmokePhase = 'doctor' | 'lint' | 'typecheck';
|
|
440
|
-
declare const PHASES: SmokePhase[];
|
|
441
|
-
/** Where the source tree stood, or the sentence saying why nothing here could say. */
|
|
442
|
-
type RecordedCommit = {
|
|
443
|
-
sha: string;
|
|
444
|
-
} | {
|
|
445
|
-
why: string;
|
|
446
|
-
};
|
|
447
|
-
type SnapshotRecord = {
|
|
448
|
-
at: string;
|
|
449
|
-
bytes: number;
|
|
450
|
-
/** Absent in a recording taken before this was recorded at all. */
|
|
451
|
-
commit?: RecordedCommit;
|
|
452
|
-
commands: Record<SmokePhase, Command>;
|
|
453
|
-
excluded: string[];
|
|
454
|
-
files: number;
|
|
455
|
-
from: string;
|
|
456
|
-
lockfile: string;
|
|
457
|
-
manager: Manager;
|
|
458
|
-
manifests: {
|
|
459
|
-
path: string;
|
|
460
|
-
versions: Record<string, string>;
|
|
461
|
-
}[];
|
|
462
|
-
name: string;
|
|
463
|
-
};
|
|
464
|
-
/** git asked in THEIR tree, and only ever asked: law 5 forbids this tool writing a byte there. */
|
|
465
|
-
declare const headOf: (from: string) => RecordedCommit;
|
|
466
|
-
declare const snapshotDir: (root: string, name: string) => string;
|
|
467
|
-
declare const readSnapshot: (root: string, name: string) => SnapshotRecord;
|
|
468
|
-
type SnapshotInput = {
|
|
469
|
-
exclude?: string[];
|
|
470
|
-
from: string;
|
|
471
|
-
name: string;
|
|
472
|
-
named: Partial<Record<SmokePhase, string>>;
|
|
473
|
-
replace: boolean;
|
|
474
|
-
root: string;
|
|
475
|
-
};
|
|
476
|
-
declare const runSnapshot: (input: SnapshotInput) => SnapshotRecord;
|
|
477
|
-
declare const formatSnapshot: (record: SnapshotRecord) => string;
|
|
478
|
-
|
|
479
507
|
/** What a phase did, or the sentence saying there was nothing of theirs to do it with. */
|
|
480
508
|
type PhaseOutcome = {
|
|
481
509
|
code: number;
|
|
@@ -656,4 +684,4 @@ declare const statementsOf: (sql: string) => string;
|
|
|
656
684
|
/** One refusal per verb per file, at the line of that verb's first occurrence. */
|
|
657
685
|
declare const refusalsIn: (path: string, body: string, firstLine?: number) => Refusal[];
|
|
658
686
|
|
|
659
|
-
export { ADOPTION_NEXT, ADOPTION_TOOL, type AdoptionConsumer, type AdoptionFinding, type AdoptionReport, type AdoptionVerdict, BASELINE_FILE, CONSUMER_TREES_FILE, type Command, DEFAULT_REGISTRY, DEPLOYED_FILE, type Declared, type Deployed, type DeployedReport, type Dialect, type Drift, EXCLUDED_DIRS, EXISTS_BUT, type Manager, type MigrationDir, type MigrationsReport, NARROWING, NOTHING_SAYS, PHASES, PLANTS, type Packed, type Phase, type PhaseOutcome, type PlanReport, type ProveOutcome, type PublishedLine, type PublishedReport, type PublishedVerdict, type RecordedCommit, type Refusal, type RegistryAnswer, type ReleaseConfig, Runner, SMOKE_NEXT, SMOKE_TOOL, SNAPSHOTS_DIR, STEPS, type SchemaConfig, type SchemaDomain, type SchemaFinding, type SchemaReport, type SmokeBaseline, type SmokeComparison, type SmokePhase, type SmokeSweep, type SnapshotRecord, type SweepEntry, type SweepNote, type Verdict, WHY_VERSION_IDENTITY, type WantedSnapshot, addSqlIn, adoptionEnvelope, askRegistry, censusOf, compareToBaseline, comparisonsIn, declaredIn, driftBetween, formatAdoption, formatBaseline, formatDeployed, formatMigrations, formatPlan, formatProve, formatPublished, formatSchema, formatSmoke, formatSnapshot, formatSweep, formatVerdict, headOf, markersIn, packRc, parseJsonc, parseReleaseConfig, parseToml, promisedButNotPacked, prove, proveOver, readBaseline, readDeployed, readReleaseConfig, readSnapshot, readWrangler, recordBaseline, refusalsIn, registryPathOf, rewriteManifests, runAdoption, runDeployed, runMigrations, runPlan, runPublished, runSchema, runSmoke, runSnapshot, smokeEnvelope, snapshotDir, statementsOf, sweepEnvelope, sweepSmoke };
|
|
687
|
+
export { ADOPTION_NEXT, ADOPTION_TOOL, type AdoptionConsumer, type AdoptionFinding, type AdoptionReport, type AdoptionVerdict, BASELINE_FILE, CONSUMER_TREES_FILE, type Command, DEFAULT_REGISTRY, DEPLOYED_FILE, type Declared, type Deployed, type DeployedReport, type Dialect, type Drift, EXCLUDED_DIRS, EXISTS_BUT, type Manager, type MigrationDir, type MigrationsReport, NARROWING, NOTHING_SAYS, PHASES, PLANTS, type Packed, type Phase, type PhaseOutcome, type PlanReport, type ProveOutcome, type PublishedLine, type PublishedReport, type PublishedVerdict, type RecordedCommit, type RecordedSeams, type Refusal, type RegistryAnswer, type ReleaseConfig, Runner, SMOKE_NEXT, SMOKE_TOOL, SNAPSHOTS_DIR, STEPS, type SchemaConfig, type SchemaDomain, type SchemaFinding, type SchemaReport, type SmokeBaseline, type SmokeComparison, type SmokePhase, type SmokeSweep, type SnapshotRecord, type SweepEntry, type SweepNote, type Verdict, WHY_VERSION_IDENTITY, type WantedSnapshot, addSqlIn, adoptionEnvelope, askRegistry, censusOf, compareToBaseline, comparisonsIn, declaredIn, driftBetween, formatAdoption, formatBaseline, formatDeployed, formatMigrations, formatPlan, formatProve, formatPublished, formatSchema, formatSmoke, formatSnapshot, formatSweep, formatVerdict, headOf, markersIn, packRc, parseJsonc, parseReleaseConfig, parseToml, promisedButNotPacked, prove, proveOver, readBaseline, readDeployed, readReleaseConfig, readSnapshot, readWrangler, recordBaseline, refusalsIn, registryPathOf, rewriteManifests, runAdoption, runDeployed, runMigrations, runPlan, runPublished, runSchema, runSmoke, runSnapshot, smokeEnvelope, snapshotDir, statementsOf, sweepEnvelope, sweepSmoke };
|
package/dist/index.js
CHANGED
package/dist/release-cli.js
CHANGED
|
@@ -36,7 +36,7 @@ import {
|
|
|
36
36
|
sweepEnvelope,
|
|
37
37
|
sweepSmoke,
|
|
38
38
|
writeEnvelope
|
|
39
|
-
} from "./chunk-
|
|
39
|
+
} from "./chunk-IPCIF5DO.js";
|
|
40
40
|
|
|
41
41
|
// src/release-cli.ts
|
|
42
42
|
import { existsSync } from "fs";
|
|
@@ -119,7 +119,7 @@ var USAGE = `geonosis-release <command> [options]
|
|
|
119
119
|
from it (D-061).
|
|
120
120
|
|
|
121
121
|
smoke snapshot <name> --from <their tree> [--replace] [--root <dir>] [--json]
|
|
122
|
-
[--typecheck <cmd>] [--lint <cmd>] [--doctor <cmd>]
|
|
122
|
+
[--typecheck <cmd>] [--lint <cmd>] [--test <cmd>] [--doctor <cmd>]
|
|
123
123
|
|
|
124
124
|
Copy a consumer tree, read-only, into .geonosis/consumer-snapshots/<name>/ \u2014 the
|
|
125
125
|
thing a release must be read against. Installed packages, build output and the git
|
|
@@ -137,9 +137,9 @@ var USAGE = `geonosis-release <command> [options]
|
|
|
137
137
|
what a consumer installs, and a release that shipped no declarations shipped them in
|
|
138
138
|
the tree and not in the tarball), point a COPY of the snapshot's manifests at those
|
|
139
139
|
tarballs, install with the snapshot's own manager, and run the snapshot's own
|
|
140
|
-
typecheck, lint and doctor.
|
|
140
|
+
typecheck, lint, tests and doctor.
|
|
141
141
|
|
|
142
|
-
\`baseline\` records what those
|
|
142
|
+
\`baseline\` records what those four answered at the versions the consumer is on.
|
|
143
143
|
\`run\` compares against it and refuses only what THIS release broke, in their
|
|
144
144
|
compiler's and their doctor's own lines. Exit 0 nothing new, 1 a new failure,
|
|
145
145
|
2 the run could not be made \u2014 including a phase the baseline cannot be compared to.
|
|
@@ -163,6 +163,7 @@ var VALUED = /* @__PURE__ */ new Set([
|
|
|
163
163
|
"--runner",
|
|
164
164
|
"--since",
|
|
165
165
|
"--snapshot",
|
|
166
|
+
"--test",
|
|
166
167
|
"--typecheck",
|
|
167
168
|
"--wait"
|
|
168
169
|
]);
|
|
@@ -333,6 +334,7 @@ var adoption = async (parsed, cwd) => {
|
|
|
333
334
|
var namedCommands = (parsed) => ({
|
|
334
335
|
...parsed.read["--doctor"] === void 0 ? {} : { doctor: parsed.read["--doctor"] },
|
|
335
336
|
...parsed.read["--lint"] === void 0 ? {} : { lint: parsed.read["--lint"] },
|
|
337
|
+
...parsed.read["--test"] === void 0 ? {} : { test: parsed.read["--test"] },
|
|
336
338
|
...parsed.read["--typecheck"] === void 0 ? {} : { typecheck: parsed.read["--typecheck"] }
|
|
337
339
|
});
|
|
338
340
|
var snapshot = (parsed, root) => {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@geonosis/release",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.2.0",
|
|
4
4
|
"types": "./dist/index.d.ts",
|
|
5
5
|
"description": "The release contract with its proofs: an expand-only migration gate over three dialects, a smoke that must name the version that answered it, and declared ≠ deployed.",
|
|
6
6
|
"keywords": [
|
|
@@ -45,7 +45,7 @@
|
|
|
45
45
|
},
|
|
46
46
|
"devDependencies": {
|
|
47
47
|
"squawk-cli": "2.63.0",
|
|
48
|
-
"@geonosis/ratchet": "2.
|
|
48
|
+
"@geonosis/ratchet": "2.2.0"
|
|
49
49
|
},
|
|
50
50
|
"engines": {
|
|
51
51
|
"node": ">=22"
|