@inixiative/config 0.4.2 → 0.5.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/README.md +2 -2
- package/dist/cli.js +77 -13
- package/package.json +1 -1
- package/versions.json +2 -2
package/README.md
CHANGED
|
@@ -60,9 +60,9 @@ bunx @inixiative/config train [root]
|
|
|
60
60
|
|
|
61
61
|
`sync` applies every fix, re-locks via `bun install`, and runs `bun update` on stale ecosystem entries. It refuses to run on a dirty working tree without `--force`. The react preset is inferred from a `react` dependency; override with `--preset`. Missing scripts are filled with defaults; existing script bodies are never touched.
|
|
62
62
|
|
|
63
|
-
`scan` runs `check` across every ecosystem checkout under a root directory. Targets are derived from the BOM's `ecosystem` keys and matched by package name, so directory names and local layout never need declaring.
|
|
63
|
+
`scan` runs `check` across every ecosystem checkout under a root directory. Targets are derived from the BOM's `ecosystem` keys and matched by package name, so directory names and local layout never need declaring. Origin is the truth, not the checkout: scan fetches per repo and fails on checkouts behind origin (their findings describe a stale tree), fails when a BOM entry has no checkout at all, and surfaces unmerged `claude/*` session branches.
|
|
64
64
|
|
|
65
|
-
`train` is the release cascade, run from this repo's checkout. It walks the ecosystem in dependency order; per repo it:
|
|
65
|
+
`train` is the release cascade, run from this repo's checkout. Origin is the truth: it refuses to run from a config checkout behind origin or with any BOM repo missing a checkout, and it fast-forwards clean checkouts to origin before working (dirty or diverged repos still skip). It walks the ecosystem in dependency order; per repo it: bumps ecosystem ranges to the BOM → re-locks → runs the repo's `check` → commits only its own changes (`package.json` + `bun.lock`) → publishes via `npm publish` when the local version is ahead of npm (OTP prompts pass through) → records the published version in the BOM. It never pushes; review its commits, push, then commit and publish this package so the BOM names the new state.
|
|
66
66
|
|
|
67
67
|
Division of labor: this CLI owns the toolchain set, ecosystem coherence, stubs, and lockfile format. Renovate owns everything else plus bumping `@inixiative/config` itself, and must be fenced off the toolchain packages.
|
|
68
68
|
|
package/dist/cli.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
// src/cli.ts
|
|
4
4
|
import { spawnSync as spawnSync2 } from "child_process";
|
|
5
|
-
import { existsSync as existsSync2 } from "fs";
|
|
5
|
+
import { existsSync as existsSync2, readFileSync as readFileSync2 } from "fs";
|
|
6
6
|
import { join as join2, resolve } from "path";
|
|
7
7
|
|
|
8
8
|
// src/lib.ts
|
|
@@ -160,6 +160,12 @@ var discoverRepos = (root, manifest2) => {
|
|
|
160
160
|
}
|
|
161
161
|
return repos.sort((a, b) => a.name.localeCompare(b.name));
|
|
162
162
|
};
|
|
163
|
+
var missingRepos = (repos, manifest2) => {
|
|
164
|
+
const found = new Set(repos.map((repo) => repo.name));
|
|
165
|
+
return Object.keys(manifest2.ecosystem).filter(
|
|
166
|
+
(name) => name !== "@inixiative/config" && !found.has(name)
|
|
167
|
+
);
|
|
168
|
+
};
|
|
163
169
|
var detectPreset = (pkg, override) => {
|
|
164
170
|
if (override) return override;
|
|
165
171
|
const hasReact = DEP_FIELDS.some((field) => pkg[field]?.react !== void 0);
|
|
@@ -510,6 +516,34 @@ var report = (findings) => {
|
|
|
510
516
|
if (process.versions.bun && process.versions.bun !== manifest.bun) {
|
|
511
517
|
console.log(`\u26A0 running bun ${process.versions.bun}, blessed is ${manifest.bun} (bun upgrade)`);
|
|
512
518
|
}
|
|
519
|
+
var git = (cwd, ...gitArgs) => spawnSync2("git", gitArgs, { cwd, encoding: "utf8" });
|
|
520
|
+
var behindOrigin = (cwd) => {
|
|
521
|
+
const behind = git(cwd, "rev-list", "--count", "HEAD..@{upstream}");
|
|
522
|
+
return behind.status === 0 ? Number(behind.stdout.trim()) : 0;
|
|
523
|
+
};
|
|
524
|
+
var staleCheckoutFindings = (cwd) => {
|
|
525
|
+
git(cwd, "fetch", "--quiet");
|
|
526
|
+
const behind = behindOrigin(cwd);
|
|
527
|
+
return behind > 0 ? [
|
|
528
|
+
{
|
|
529
|
+
level: "error",
|
|
530
|
+
message: `checkout is ${behind} commit${behind === 1 ? "" : "s"} behind origin \u2014 local state is stale, pull before trusting findings`
|
|
531
|
+
}
|
|
532
|
+
] : [];
|
|
533
|
+
};
|
|
534
|
+
var unmergedSessionBranches = (cwd) => {
|
|
535
|
+
const branches = git(
|
|
536
|
+
cwd,
|
|
537
|
+
"branch",
|
|
538
|
+
"-r",
|
|
539
|
+
"--no-merged",
|
|
540
|
+
"@{upstream}",
|
|
541
|
+
"--list",
|
|
542
|
+
"origin/claude/*"
|
|
543
|
+
);
|
|
544
|
+
if (branches.status !== 0) return [];
|
|
545
|
+
return branches.stdout.split("\n").map((line) => line.trim()).filter(Boolean);
|
|
546
|
+
};
|
|
513
547
|
if (command === "check") {
|
|
514
548
|
const { findings } = inspect(dir, manifest, presetFlag);
|
|
515
549
|
process.exit(report(findings) > 0 ? 1 : 0);
|
|
@@ -520,17 +554,24 @@ if (command === "scan") {
|
|
|
520
554
|
console.error(`\u2717 no ecosystem repos found under ${dir}`);
|
|
521
555
|
process.exit(1);
|
|
522
556
|
}
|
|
557
|
+
const missing = missingRepos(repos, manifest);
|
|
523
558
|
const drifted = [];
|
|
524
559
|
for (const repo of repos) {
|
|
525
560
|
console.log(`
|
|
526
561
|
${repo.name} \u2014 ${repo.dir}`);
|
|
527
|
-
|
|
562
|
+
const findings = [...staleCheckoutFindings(repo.dir), ...inspect(repo.dir, manifest).findings];
|
|
563
|
+
if (report(findings) > 0) drifted.push(repo.name);
|
|
564
|
+
for (const branch of unmergedSessionBranches(repo.dir)) {
|
|
565
|
+
console.log(`\u26A0 unmerged session branch: ${branch}`);
|
|
566
|
+
}
|
|
528
567
|
}
|
|
568
|
+
if (missing.length > 0) console.error(`
|
|
569
|
+
\u2717 no checkout found for: ${missing.join(", ")}`);
|
|
529
570
|
console.log(
|
|
530
571
|
`
|
|
531
|
-
scanned ${repos.length} repos: ${drifted.length === 0 ? "all in sync" : `${drifted.length} drifted (${drifted.join(", ")})`}`
|
|
572
|
+
scanned ${repos.length} repos: ${drifted.length === 0 ? "all in sync" : `${drifted.length} drifted (${drifted.join(", ")})`}${missing.length > 0 ? `, ${missing.length} missing` : ""}`
|
|
532
573
|
);
|
|
533
|
-
process.exit(drifted.length > 0 ? 1 : 0);
|
|
574
|
+
process.exit(drifted.length > 0 || missing.length > 0 ? 1 : 0);
|
|
534
575
|
}
|
|
535
576
|
if (command === "train") {
|
|
536
577
|
const order = topoOrder(dir, manifest);
|
|
@@ -538,6 +579,18 @@ if (command === "train") {
|
|
|
538
579
|
console.error(`\u2717 no ecosystem repos found under ${dir}`);
|
|
539
580
|
process.exit(1);
|
|
540
581
|
}
|
|
582
|
+
const missing = missingRepos(order, manifest);
|
|
583
|
+
if (missing.length > 0) {
|
|
584
|
+
console.error(
|
|
585
|
+
`\u2717 no checkout under ${dir} for: ${missing.join(", ")} \u2014 a partial train ships an incoherent set`
|
|
586
|
+
);
|
|
587
|
+
process.exit(1);
|
|
588
|
+
}
|
|
589
|
+
git(packageRoot, "fetch", "--quiet");
|
|
590
|
+
if (behindOrigin(packageRoot) > 0) {
|
|
591
|
+
console.error("\u2717 this config checkout is behind origin \u2014 its blessed set is stale; pull first");
|
|
592
|
+
process.exit(1);
|
|
593
|
+
}
|
|
541
594
|
console.log(`train order: ${order.map((repo) => repo.name).join(" \u2192 ")}`);
|
|
542
595
|
const published = [];
|
|
543
596
|
const skipped = [];
|
|
@@ -559,15 +612,26 @@ if (command === "train") {
|
|
|
559
612
|
skipped.push(repo.name);
|
|
560
613
|
continue;
|
|
561
614
|
}
|
|
562
|
-
|
|
563
|
-
const
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
if (behind
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
615
|
+
git(repo.dir, "fetch", "--quiet");
|
|
616
|
+
for (const branch of unmergedSessionBranches(repo.dir)) {
|
|
617
|
+
console.log(`\u26A0 unmerged session branch: ${branch} \u2014 a bump may be hiding there`);
|
|
618
|
+
}
|
|
619
|
+
const behind = behindOrigin(repo.dir);
|
|
620
|
+
if (behind > 0) {
|
|
621
|
+
const localOnly = git(repo.dir, "rev-list", "--count", "@{upstream}..HEAD");
|
|
622
|
+
if (localOnly.status === 0 && Number(localOnly.stdout.trim()) > 0) {
|
|
623
|
+
console.log("\u26A0 diverged from origin \u2014 reconcile first, skipping");
|
|
624
|
+
skipped.push(repo.name);
|
|
625
|
+
continue;
|
|
626
|
+
}
|
|
627
|
+
const ff = git(repo.dir, "merge", "--ff-only", "@{upstream}");
|
|
628
|
+
if (ff.status !== 0) {
|
|
629
|
+
console.log("\u26A0 fast-forward to origin failed \u2014 reconcile first, skipping");
|
|
630
|
+
skipped.push(repo.name);
|
|
631
|
+
continue;
|
|
632
|
+
}
|
|
633
|
+
console.log(`\u2193 fast-forwarded to origin (+${behind})`);
|
|
634
|
+
repo.pkg = JSON.parse(readFileSync2(join2(repo.dir, "package.json"), "utf8"));
|
|
571
635
|
}
|
|
572
636
|
const inspection = inspect(repo.dir, manifest);
|
|
573
637
|
const bumps = inspection.findings.filter((finding) => finding.kind === "ecosystem-range");
|
package/package.json
CHANGED
package/versions.json
CHANGED
|
@@ -13,8 +13,8 @@
|
|
|
13
13
|
"@types/bun"
|
|
14
14
|
],
|
|
15
15
|
"ecosystem": {
|
|
16
|
-
"@inixiative/config": "0.
|
|
17
|
-
"@inixiative/json-rules": "2.
|
|
16
|
+
"@inixiative/config": "0.5.1",
|
|
17
|
+
"@inixiative/json-rules": "2.15.0",
|
|
18
18
|
"@inixiative/permissions": "0.3.2",
|
|
19
19
|
"@inixiative/transitions": "0.1.0",
|
|
20
20
|
"@inixiative/rules-builder": "0.15.0",
|