@biffo/cli 0.214.0 → 0.214.1
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 +63 -30
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -9126,12 +9126,24 @@ import { Command as Command23 } from "commander";
|
|
|
9126
9126
|
|
|
9127
9127
|
// src/scripts/check-adr-numbering.ts
|
|
9128
9128
|
import { existsSync as existsSync32 } from "fs";
|
|
9129
|
-
import { join as
|
|
9129
|
+
import { join as join32 } from "path";
|
|
9130
9130
|
import { execa as execa5 } from "execa";
|
|
9131
9131
|
|
|
9132
9132
|
// src/lib/adr-numbering-guard.ts
|
|
9133
|
-
import { existsSync as existsSync31, readdirSync as readdirSync13 } from "fs";
|
|
9133
|
+
import { existsSync as existsSync31, readdirSync as readdirSync13, readFileSync as readFileSync24 } from "fs";
|
|
9134
|
+
import { join as join31 } from "path";
|
|
9134
9135
|
var ADR_FILENAME = /^(\d{4})-.+\.md$/;
|
|
9136
|
+
var ALLOWLIST_FILENAME = ".numbering-allowlist";
|
|
9137
|
+
function readAdrNumberingAllowlist(adrDir) {
|
|
9138
|
+
const path = join31(adrDir, ALLOWLIST_FILENAME);
|
|
9139
|
+
if (!existsSync31(path)) return /* @__PURE__ */ new Set();
|
|
9140
|
+
const numbers = /* @__PURE__ */ new Set();
|
|
9141
|
+
for (const rawLine of readFileSync24(path, "utf8").split("\n")) {
|
|
9142
|
+
const line = rawLine.split("#")[0].trim();
|
|
9143
|
+
if (line) numbers.add(line);
|
|
9144
|
+
}
|
|
9145
|
+
return numbers;
|
|
9146
|
+
}
|
|
9135
9147
|
function adrNumbersIn(adrDir) {
|
|
9136
9148
|
const claims = /* @__PURE__ */ new Map();
|
|
9137
9149
|
if (!existsSync31(adrDir)) return claims;
|
|
@@ -9144,12 +9156,20 @@ function adrNumbersIn(adrDir) {
|
|
|
9144
9156
|
return claims;
|
|
9145
9157
|
}
|
|
9146
9158
|
function findAdrNumberCollisions(adrDir) {
|
|
9159
|
+
const allowlist = readAdrNumberingAllowlist(adrDir);
|
|
9147
9160
|
const collisions = [];
|
|
9148
9161
|
for (const [number, files] of [...adrNumbersIn(adrDir).entries()].sort()) {
|
|
9149
|
-
if (files.length > 1
|
|
9162
|
+
if (files.length > 1 && !allowlist.has(number)) {
|
|
9163
|
+
collisions.push({ number, files: [...files].sort() });
|
|
9164
|
+
}
|
|
9150
9165
|
}
|
|
9151
9166
|
return collisions;
|
|
9152
9167
|
}
|
|
9168
|
+
function findStaleAdrNumberingAllowlistEntries(adrDir) {
|
|
9169
|
+
const allowlist = readAdrNumberingAllowlist(adrDir);
|
|
9170
|
+
const claims = adrNumbersIn(adrDir);
|
|
9171
|
+
return [...allowlist].filter((number) => (claims.get(number)?.length ?? 0) < 2).sort();
|
|
9172
|
+
}
|
|
9153
9173
|
function formatAdrNumberCollisions(collisions) {
|
|
9154
9174
|
return collisions.map(
|
|
9155
9175
|
(c) => ` ADR-${c.number} is claimed by: ${c.files.join(", ")}
|
|
@@ -9161,18 +9181,31 @@ function formatAdrNumberCollisions(collisions) {
|
|
|
9161
9181
|
// src/scripts/check-adr-numbering.ts
|
|
9162
9182
|
async function runAdrNumberingCheck() {
|
|
9163
9183
|
const root = (await execa5("git", ["rev-parse", "--show-toplevel"])).stdout.trim();
|
|
9164
|
-
const adrDir =
|
|
9184
|
+
const adrDir = join32(root, "docs", "ADR");
|
|
9165
9185
|
if (!existsSync32(adrDir)) {
|
|
9166
9186
|
console.log("\u2713 ADR numbering guard: no docs/ADR/ directory \u2014 nothing to compare");
|
|
9167
9187
|
return;
|
|
9168
9188
|
}
|
|
9169
9189
|
const collisions = findAdrNumberCollisions(adrDir);
|
|
9190
|
+
const stale = findStaleAdrNumberingAllowlistEntries(adrDir);
|
|
9191
|
+
let failed = false;
|
|
9170
9192
|
if (collisions.length > 0) {
|
|
9193
|
+
failed = true;
|
|
9171
9194
|
console.error("\u2717 ADR numbering guard: two ADRs in docs/ADR/ share a number\n");
|
|
9172
9195
|
console.error(formatAdrNumberCollisions(collisions));
|
|
9173
|
-
console.error(
|
|
9174
|
-
|
|
9196
|
+
console.error(
|
|
9197
|
+
`
|
|
9198
|
+
Already accepted? List it in docs/ADR/${ALLOWLIST_FILENAME} instead of leaving this red forever. See tabsii-platform#449 for how this class of collision happens.`
|
|
9199
|
+
);
|
|
9200
|
+
}
|
|
9201
|
+
if (stale.length > 0) {
|
|
9202
|
+
failed = true;
|
|
9203
|
+
console.error(
|
|
9204
|
+
`\u2717 ADR numbering guard: docs/ADR/${ALLOWLIST_FILENAME} names a number that no longer collides: ${stale.join(", ")}
|
|
9205
|
+
Remove the stale entry \u2014 an allowlist nothing checks against just hides the next real one.`
|
|
9206
|
+
);
|
|
9175
9207
|
}
|
|
9208
|
+
if (failed) process.exit(1);
|
|
9176
9209
|
console.log("\u2713 ADR numbering guard: OK");
|
|
9177
9210
|
}
|
|
9178
9211
|
|
|
@@ -9460,8 +9493,8 @@ async function runOwnershipCheck(argv) {
|
|
|
9460
9493
|
const { stdout } = await execa7("git", ["diff", "--cached", "--name-status"], { cwd: root });
|
|
9461
9494
|
({ changed: changedFiles, deleted: deletedFiles } = parseNameStatus(stdout));
|
|
9462
9495
|
if (messageFile) {
|
|
9463
|
-
const { readFileSync:
|
|
9464
|
-
if (existsSync37(messageFile)) commitMessage =
|
|
9496
|
+
const { readFileSync: readFileSync27, existsSync: existsSync37 } = await import("fs");
|
|
9497
|
+
if (existsSync37(messageFile)) commitMessage = readFileSync27(messageFile, "utf8");
|
|
9465
9498
|
}
|
|
9466
9499
|
} else {
|
|
9467
9500
|
const base = process.env["GITHUB_BASE_REF"] ?? args[0];
|
|
@@ -9563,12 +9596,12 @@ ${BOLD}If the divergence is deliberate${OFF}
|
|
|
9563
9596
|
|
|
9564
9597
|
// src/scripts/check-plugin-collisions.ts
|
|
9565
9598
|
import { existsSync as existsSync34 } from "fs";
|
|
9566
|
-
import { join as
|
|
9599
|
+
import { join as join34 } from "path";
|
|
9567
9600
|
import { execa as execa8 } from "execa";
|
|
9568
9601
|
|
|
9569
9602
|
// src/lib/plugin-collision-guard.ts
|
|
9570
9603
|
import { existsSync as existsSync33, readdirSync as readdirSync14, statSync as statSync7 } from "fs";
|
|
9571
|
-
import { join as
|
|
9604
|
+
import { join as join33 } from "path";
|
|
9572
9605
|
var PYTEST_SPECIAL = /* @__PURE__ */ new Set(["conftest.py"]);
|
|
9573
9606
|
var IGNORED_DIRS = /* @__PURE__ */ new Set([".venv", "node_modules", "__pycache__", ".git", "dist", "build"]);
|
|
9574
9607
|
function subdirectories(dir) {
|
|
@@ -9576,19 +9609,19 @@ function subdirectories(dir) {
|
|
|
9576
9609
|
return readdirSync14(dir).filter((entry) => {
|
|
9577
9610
|
if (IGNORED_DIRS.has(entry) || entry.startsWith(".")) return false;
|
|
9578
9611
|
try {
|
|
9579
|
-
return statSync7(
|
|
9612
|
+
return statSync7(join33(dir, entry)).isDirectory();
|
|
9580
9613
|
} catch {
|
|
9581
9614
|
return false;
|
|
9582
9615
|
}
|
|
9583
9616
|
});
|
|
9584
9617
|
}
|
|
9585
9618
|
function regularPackagesOf(pluginDir2) {
|
|
9586
|
-
return subdirectories(pluginDir2).filter((name) => existsSync33(
|
|
9619
|
+
return subdirectories(pluginDir2).filter((name) => existsSync33(join33(pluginDir2, name, "__init__.py"))).sort();
|
|
9587
9620
|
}
|
|
9588
9621
|
function bareTestModulesOf(pluginDir2) {
|
|
9589
|
-
const testsDir =
|
|
9622
|
+
const testsDir = join33(pluginDir2, "tests");
|
|
9590
9623
|
if (!existsSync33(testsDir)) return [];
|
|
9591
|
-
if (existsSync33(
|
|
9624
|
+
if (existsSync33(join33(testsDir, "__init__.py"))) return [];
|
|
9592
9625
|
return readdirSync14(testsDir).filter((f) => f.endsWith(".py") && !PYTEST_SPECIAL.has(f)).sort();
|
|
9593
9626
|
}
|
|
9594
9627
|
function findCollisions(servicesDir, pluginDirs) {
|
|
@@ -9597,7 +9630,7 @@ function findCollisions(servicesDir, pluginDirs) {
|
|
|
9597
9630
|
const gather = (kind, namesOf) => {
|
|
9598
9631
|
const claims = /* @__PURE__ */ new Map();
|
|
9599
9632
|
for (const plugin of plugins) {
|
|
9600
|
-
for (const name of namesOf(
|
|
9633
|
+
for (const name of namesOf(join33(servicesDir, plugin))) {
|
|
9601
9634
|
claims.set(name, [...claims.get(name) ?? [], plugin]);
|
|
9602
9635
|
}
|
|
9603
9636
|
}
|
|
@@ -9635,7 +9668,7 @@ function formatCollisions(collisions) {
|
|
|
9635
9668
|
// src/scripts/check-plugin-collisions.ts
|
|
9636
9669
|
async function runPluginCollisionCheck() {
|
|
9637
9670
|
const root = (await execa8("git", ["rev-parse", "--show-toplevel"])).stdout.trim();
|
|
9638
|
-
const servicesDir =
|
|
9671
|
+
const servicesDir = join34(root, "services");
|
|
9639
9672
|
if (!existsSync34(servicesDir)) {
|
|
9640
9673
|
console.log("\u2713 plugin collision guard: no services/ directory \u2014 nothing to compare");
|
|
9641
9674
|
return;
|
|
@@ -9656,8 +9689,8 @@ async function runPluginCollisionCheck() {
|
|
|
9656
9689
|
import { execa as execa9 } from "execa";
|
|
9657
9690
|
|
|
9658
9691
|
// src/lib/plugin-terraform-guard.ts
|
|
9659
|
-
import { existsSync as existsSync35, readFileSync as
|
|
9660
|
-
import { dirname as dirname9, join as
|
|
9692
|
+
import { existsSync as existsSync35, readFileSync as readFileSync25, readdirSync as readdirSync15 } from "fs";
|
|
9693
|
+
import { dirname as dirname9, join as join35, relative as relative6, sep as sep3 } from "path";
|
|
9661
9694
|
var SKIP_DIRS = /* @__PURE__ */ new Set(["node_modules", ".git", ".worktrees", "dist", ".venv", "__pycache__"]);
|
|
9662
9695
|
var PLUGIN_MANIFEST_FILE2 = "biffo.plugin.json";
|
|
9663
9696
|
function findPluginManifests(root) {
|
|
@@ -9672,9 +9705,9 @@ function findPluginManifests(root) {
|
|
|
9672
9705
|
for (const entry of entries) {
|
|
9673
9706
|
if (entry.isDirectory()) {
|
|
9674
9707
|
if (SKIP_DIRS.has(entry.name)) continue;
|
|
9675
|
-
walk(
|
|
9708
|
+
walk(join35(dir, entry.name));
|
|
9676
9709
|
} else if (entry.isFile() && entry.name === PLUGIN_MANIFEST_FILE2) {
|
|
9677
|
-
found.push(relative6(root,
|
|
9710
|
+
found.push(relative6(root, join35(dir, entry.name)).split(sep3).join("/"));
|
|
9678
9711
|
}
|
|
9679
9712
|
}
|
|
9680
9713
|
};
|
|
@@ -9684,7 +9717,7 @@ function findPluginManifests(root) {
|
|
|
9684
9717
|
function readSubscriptions(absManifestPath) {
|
|
9685
9718
|
let parsed;
|
|
9686
9719
|
try {
|
|
9687
|
-
parsed = JSON.parse(
|
|
9720
|
+
parsed = JSON.parse(readFileSync25(absManifestPath, "utf8"));
|
|
9688
9721
|
} catch {
|
|
9689
9722
|
return null;
|
|
9690
9723
|
}
|
|
@@ -9699,14 +9732,14 @@ function readSubscriptions(absManifestPath) {
|
|
|
9699
9732
|
}
|
|
9700
9733
|
function checkPluginTerraform(root) {
|
|
9701
9734
|
const violations = [];
|
|
9702
|
-
const coreManifest = existsSync35(
|
|
9735
|
+
const coreManifest = existsSync35(join35(root, CORE_MANIFEST_FILE)) ? readCoreManifest(root) : null;
|
|
9703
9736
|
for (const manifest of findPluginManifests(root)) {
|
|
9704
9737
|
if (coreManifest && !isTemplateOwned(manifest, coreManifest)) continue;
|
|
9705
|
-
const absManifest =
|
|
9738
|
+
const absManifest = join35(root, manifest);
|
|
9706
9739
|
const subscriptions = readSubscriptions(absManifest);
|
|
9707
9740
|
if (subscriptions === null) continue;
|
|
9708
9741
|
const pluginDir2 = dirname9(absManifest);
|
|
9709
|
-
if (existsSync35(
|
|
9742
|
+
if (existsSync35(join35(pluginDir2, "terraform"))) continue;
|
|
9710
9743
|
const relPluginDir = relative6(root, pluginDir2).split(sep3).join("/");
|
|
9711
9744
|
violations.push({
|
|
9712
9745
|
manifest,
|
|
@@ -9859,8 +9892,8 @@ function rawArgsAfter(subcommand) {
|
|
|
9859
9892
|
}
|
|
9860
9893
|
|
|
9861
9894
|
// src/commands/doctor.ts
|
|
9862
|
-
import { existsSync as existsSync36, readFileSync as
|
|
9863
|
-
import { join as
|
|
9895
|
+
import { existsSync as existsSync36, readFileSync as readFileSync26 } from "fs";
|
|
9896
|
+
import { join as join36, resolve as resolve18 } from "path";
|
|
9864
9897
|
import chalk21 from "chalk";
|
|
9865
9898
|
import { Command as Command24 } from "commander";
|
|
9866
9899
|
|
|
@@ -10035,10 +10068,10 @@ async function runDoctor(options, deps = { git: new GitAdapter() }) {
|
|
|
10035
10068
|
return runDoctorChecks(facts);
|
|
10036
10069
|
}
|
|
10037
10070
|
function readLocalCoreVersion(cwd) {
|
|
10038
|
-
const path =
|
|
10071
|
+
const path = join36(cwd, INSTANCE_CORE_FILE);
|
|
10039
10072
|
if (!existsSync36(path)) return null;
|
|
10040
10073
|
try {
|
|
10041
|
-
return parseCoreRecord(
|
|
10074
|
+
return parseCoreRecord(readFileSync26(path, "utf8"));
|
|
10042
10075
|
} catch {
|
|
10043
10076
|
return null;
|
|
10044
10077
|
}
|
|
@@ -10053,10 +10086,10 @@ function parseCoreRecord(contents) {
|
|
|
10053
10086
|
}
|
|
10054
10087
|
}
|
|
10055
10088
|
function readFossil(cwd) {
|
|
10056
|
-
const path =
|
|
10089
|
+
const path = join36(cwd, CORE_VERSION_FILE);
|
|
10057
10090
|
if (!existsSync36(path)) return null;
|
|
10058
10091
|
try {
|
|
10059
|
-
const value =
|
|
10092
|
+
const value = readFileSync26(path, "utf8").trim();
|
|
10060
10093
|
return value === "" ? null : value;
|
|
10061
10094
|
} catch {
|
|
10062
10095
|
return null;
|