@xemahq/repo-build-tooling 0.8.1 → 0.8.2
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/package.json +1 -1
- package/src/readiness.mjs +15 -7
- package/src/readiness.test.mjs +17 -5
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@xemahq/repo-build-tooling",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.2",
|
|
4
4
|
"description": "Dev-time build tooling shared by every Xema repository. Ships as plain ESM with zero dependencies so the published artifact is the reviewed source.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"author": "Neuralchowder Inc. <developer@xema.dev> (https://xema.dev)",
|
package/src/readiness.mjs
CHANGED
|
@@ -439,10 +439,18 @@ export function packagesOwningPaths(root, relPaths, script = 'test') {
|
|
|
439
439
|
* REPO-WIDE, labelled, because skipping would drop a proof.
|
|
440
440
|
* - `inapplicable`— nothing declares it. Genuinely nothing to run.
|
|
441
441
|
*/
|
|
442
|
-
export function affectedStagePlan({ base, paths, packages, rootDeclares }) {
|
|
443
|
-
|
|
442
|
+
export function affectedStagePlan({ base, paths, packages, rootDeclares, membersDeclare }) {
|
|
443
|
+
// REPO-WIDE means WHAT CI RUNS, and every CI in this fleet runs the stage as
|
|
444
|
+
// `pnpm -r --if-present run <script>` — per member, never the root script.
|
|
445
|
+
// Measured 2026-09-20 in xema-kernel-sdk: the root `lint` is `eslint .`,
|
|
446
|
+
// which also lints `tooling/**` and re-lints every package under the ROOT
|
|
447
|
+
// config, and reports 139 errors CI has never seen. Running it here made
|
|
448
|
+
// readiness a SECOND lint authority that disagreed with the first. The root
|
|
449
|
+
// script is used only where no member declares the stage at all.
|
|
450
|
+
if (!base) return { mode: 'workspace', viaRoot: rootDeclares && !membersDeclare };
|
|
444
451
|
if (packages.length > 0) return { mode: 'affected', packages };
|
|
445
|
-
if (paths.length > 0 && rootDeclares) return { mode: 'root' };
|
|
452
|
+
if (paths.length > 0 && rootDeclares && !membersDeclare) return { mode: 'root' };
|
|
453
|
+
if (paths.length > 0 && membersDeclare) return { mode: 'workspace', viaRoot: false };
|
|
446
454
|
return { mode: 'inapplicable' };
|
|
447
455
|
}
|
|
448
456
|
|
|
@@ -455,6 +463,7 @@ function runAffectedStage({ id, script, why }) {
|
|
|
455
463
|
paths,
|
|
456
464
|
packages,
|
|
457
465
|
rootDeclares: Boolean(scripts[script]),
|
|
466
|
+
membersDeclare: servicesWith(script).length > 0,
|
|
458
467
|
});
|
|
459
468
|
switch (plan.mode) {
|
|
460
469
|
case 'workspace':
|
|
@@ -482,10 +491,9 @@ function runAffectedStage({ id, script, why }) {
|
|
|
482
491
|
return;
|
|
483
492
|
case 'root':
|
|
484
493
|
// FALLBACK, and it is the difference between "inapplicable" and "not
|
|
485
|
-
// checked"
|
|
486
|
-
//
|
|
487
|
-
//
|
|
488
|
-
// runs, LABELLED as repo-wide rather than affected.
|
|
494
|
+
// checked": a repository that owns a stage ONLY at the root (no member
|
|
495
|
+
// declares it). Skipping there would silently drop a real proof, so the
|
|
496
|
+
// root script runs, LABELLED as repo-wide rather than affected.
|
|
489
497
|
console.log(
|
|
490
498
|
` ${paths.length} changed path(s) since ${base.slice(0, 9)}; no changed` +
|
|
491
499
|
` package declares \`${script}\`, but the ROOT does — running it\n` +
|
package/src/readiness.test.mjs
CHANGED
|
@@ -218,28 +218,40 @@ test('an affected stage with NO branch point runs REPO-WIDE — it never skips',
|
|
|
218
218
|
// The defect this pins: a scratch export or an archive has no origin/develop,
|
|
219
219
|
// and the stage used to SKIP and let the run end "converged — safe to push"
|
|
220
220
|
// with typecheck, lint and tests all unexecuted. Green over nothing.
|
|
221
|
+
// Members declare it: CI's `pnpm -r` form, even when the root ALSO has a
|
|
222
|
+
// script — the root's is a second authority (kernel-sdk's `eslint .`).
|
|
221
223
|
assert.deepEqual(
|
|
222
|
-
affectedStagePlan({ base: undefined, paths: [], packages: [], rootDeclares: true }),
|
|
224
|
+
affectedStagePlan({ base: undefined, paths: [], packages: [], rootDeclares: true, membersDeclare: true }),
|
|
225
|
+
{ mode: 'workspace', viaRoot: false },
|
|
226
|
+
);
|
|
227
|
+
// Only the root declares it: the root script is the only place it lives.
|
|
228
|
+
assert.deepEqual(
|
|
229
|
+
affectedStagePlan({ base: undefined, paths: [], packages: [], rootDeclares: true, membersDeclare: false }),
|
|
223
230
|
{ mode: 'workspace', viaRoot: true },
|
|
224
231
|
);
|
|
225
232
|
assert.deepEqual(
|
|
226
|
-
affectedStagePlan({ base: undefined, paths: [], packages: [], rootDeclares: false }),
|
|
233
|
+
affectedStagePlan({ base: undefined, paths: [], packages: [], rootDeclares: false, membersDeclare: false }),
|
|
227
234
|
{ mode: 'workspace', viaRoot: false },
|
|
228
235
|
);
|
|
229
236
|
// A base with owning packages is the ordinary affected run.
|
|
230
237
|
assert.deepEqual(
|
|
231
|
-
affectedStagePlan({ base: 'abc', paths: ['a/x.ts'], packages: ['a'], rootDeclares: true }),
|
|
238
|
+
affectedStagePlan({ base: 'abc', paths: ['a/x.ts'], packages: ['a'], rootDeclares: true, membersDeclare: true }),
|
|
232
239
|
{ mode: 'affected', packages: ['a'] },
|
|
233
240
|
);
|
|
234
241
|
// A base where only the ROOT declares the script runs the root, labelled.
|
|
235
242
|
assert.deepEqual(
|
|
236
|
-
affectedStagePlan({ base: 'abc', paths: ['README.md'], packages: [], rootDeclares: true }),
|
|
243
|
+
affectedStagePlan({ base: 'abc', paths: ['README.md'], packages: [], rootDeclares: true, membersDeclare: false }),
|
|
237
244
|
{ mode: 'root' },
|
|
238
245
|
);
|
|
246
|
+
// A root-only path change where members own the stage: CI's form, not the root's.
|
|
247
|
+
assert.deepEqual(
|
|
248
|
+
affectedStagePlan({ base: 'abc', paths: ['README.md'], packages: [], rootDeclares: true, membersDeclare: true }),
|
|
249
|
+
{ mode: 'workspace', viaRoot: false },
|
|
250
|
+
);
|
|
239
251
|
// Nothing declares it: the only outcome that runs nothing, and it needs a
|
|
240
252
|
// base to be trusted — without one it is the workspace run above.
|
|
241
253
|
assert.deepEqual(
|
|
242
|
-
affectedStagePlan({ base: 'abc', paths: ['README.md'], packages: [], rootDeclares: false }),
|
|
254
|
+
affectedStagePlan({ base: 'abc', paths: ['README.md'], packages: [], rootDeclares: false, membersDeclare: false }),
|
|
243
255
|
{ mode: 'inapplicable' },
|
|
244
256
|
);
|
|
245
257
|
});
|