@plexus-ms/cli 0.4.0 → 0.5.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/plx.js +298 -143
- package/package.json +3 -3
package/dist/plx.js
CHANGED
|
@@ -7268,7 +7268,7 @@ var require_public_api = __commonJS({
|
|
|
7268
7268
|
}
|
|
7269
7269
|
return doc;
|
|
7270
7270
|
}
|
|
7271
|
-
function
|
|
7271
|
+
function parse5(src, reviver, options) {
|
|
7272
7272
|
let _reviver = void 0;
|
|
7273
7273
|
if (typeof reviver === "function") {
|
|
7274
7274
|
_reviver = reviver;
|
|
@@ -7309,7 +7309,7 @@ var require_public_api = __commonJS({
|
|
|
7309
7309
|
return value.toString(options);
|
|
7310
7310
|
return new Document.Document(value, _replacer, options).toString(options);
|
|
7311
7311
|
}
|
|
7312
|
-
exports.parse =
|
|
7312
|
+
exports.parse = parse5;
|
|
7313
7313
|
exports.parseAllDocuments = parseAllDocuments;
|
|
7314
7314
|
exports.parseDocument = parseDocument;
|
|
7315
7315
|
exports.stringify = stringify;
|
|
@@ -7655,9 +7655,83 @@ async function readCatalog(ctx, compendium) {
|
|
|
7655
7655
|
return catalog;
|
|
7656
7656
|
}
|
|
7657
7657
|
|
|
7658
|
+
// ../lib/dist/changedApps.js
|
|
7659
|
+
import { join as join2 } from "node:path";
|
|
7660
|
+
var BOOKKEEPING = /(^|\/)(PLEXUS\.md|\.copier-answers\.yml)$/;
|
|
7661
|
+
var GLOBALS = /^(pnpm-lock\.yaml|pnpm-workspace\.yaml|package\.json|turbo\.json|mise\.toml|\.npmrc|\.node-version)$/;
|
|
7662
|
+
var NO_REF = /^0*$/;
|
|
7663
|
+
async function selectChangedApps(input) {
|
|
7664
|
+
const all = [...input.all].sort();
|
|
7665
|
+
if (input.changed === void 0)
|
|
7666
|
+
return { apps: all, reason: "no base ref: every app counts as changed" };
|
|
7667
|
+
const changed = input.changed.filter((f) => !BOOKKEEPING.test(f));
|
|
7668
|
+
const under = (app) => changed.some((f) => f.startsWith(`apps/${app}/`));
|
|
7669
|
+
if (!input.workspace)
|
|
7670
|
+
return { apps: all.filter(under), reason: "files under the apps changed" };
|
|
7671
|
+
if (changed.length === 0)
|
|
7672
|
+
return { apps: [], reason: "nothing but bookkeeping changed" };
|
|
7673
|
+
if (changed.some((f) => GLOBALS.test(f)))
|
|
7674
|
+
return { apps: all, reason: "a workspace-global input changed: every app counts as changed" };
|
|
7675
|
+
const outside = changed.some((f) => !f.startsWith("apps/"));
|
|
7676
|
+
const listed = new Set(await input.dependents?.() ?? []);
|
|
7677
|
+
return {
|
|
7678
|
+
apps: all.filter((app) => listed.has(app) && (outside || under(app))),
|
|
7679
|
+
reason: "sources or their dependencies changed"
|
|
7680
|
+
};
|
|
7681
|
+
}
|
|
7682
|
+
async function readChangedApps(ctx, dir, from, to = "HEAD") {
|
|
7683
|
+
const git2 = (args) => ctx.read("git", args, { cwd: dir });
|
|
7684
|
+
const workspace = await exists(ctx, join2(dir, "pnpm-workspace.yaml"));
|
|
7685
|
+
const all = await deployableApps(ctx, dir, workspace);
|
|
7686
|
+
let changed;
|
|
7687
|
+
if (from !== "" && !NO_REF.test(from) && await isCommit(git2, from))
|
|
7688
|
+
changed = (await git2(["diff", "--name-only", from, to])).split("\n").filter(Boolean);
|
|
7689
|
+
const dependents = async () => {
|
|
7690
|
+
const out = await ctx.read("pnpm", ["--filter", `...[${from}...${to}]`, "ls", "--depth", "-1", "--parseable"], {
|
|
7691
|
+
cwd: dir
|
|
7692
|
+
});
|
|
7693
|
+
return out.split("\n").map((line) => /(?:^|\/)apps\/([^/]+)$/.exec(line.trim())?.[1]).filter((app) => app !== void 0);
|
|
7694
|
+
};
|
|
7695
|
+
const result = await selectChangedApps({ workspace, all, changed, dependents });
|
|
7696
|
+
ctx.say(`\u2192 ${result.reason}`, 1);
|
|
7697
|
+
return result;
|
|
7698
|
+
}
|
|
7699
|
+
async function isCommit(git2, ref) {
|
|
7700
|
+
try {
|
|
7701
|
+
await git2(["rev-parse", "--verify", "--quiet", `${ref}^{commit}`]);
|
|
7702
|
+
return true;
|
|
7703
|
+
} catch {
|
|
7704
|
+
return false;
|
|
7705
|
+
}
|
|
7706
|
+
}
|
|
7707
|
+
async function deployableApps(ctx, dir, workspace) {
|
|
7708
|
+
const entries = await ctx.readDir(join2(dir, "apps")).catch(() => []);
|
|
7709
|
+
const apps = [];
|
|
7710
|
+
for (const e of entries) {
|
|
7711
|
+
if (!e.directory)
|
|
7712
|
+
continue;
|
|
7713
|
+
const marks = workspace ? ["package.json"] : ["docker/compose.yaml", "compose.yaml"];
|
|
7714
|
+
for (const mark of marks) {
|
|
7715
|
+
if (await exists(ctx, join2(dir, "apps", e.name, mark))) {
|
|
7716
|
+
apps.push(e.name);
|
|
7717
|
+
break;
|
|
7718
|
+
}
|
|
7719
|
+
}
|
|
7720
|
+
}
|
|
7721
|
+
return apps.sort();
|
|
7722
|
+
}
|
|
7723
|
+
async function exists(ctx, path3) {
|
|
7724
|
+
try {
|
|
7725
|
+
await ctx.readFile(path3);
|
|
7726
|
+
return true;
|
|
7727
|
+
} catch {
|
|
7728
|
+
return false;
|
|
7729
|
+
}
|
|
7730
|
+
}
|
|
7731
|
+
|
|
7658
7732
|
// ../lib/dist/changeset.js
|
|
7659
7733
|
var import_yaml2 = __toESM(require_dist(), 1);
|
|
7660
|
-
import { join as
|
|
7734
|
+
import { join as join3 } from "node:path";
|
|
7661
7735
|
|
|
7662
7736
|
// ../lib/dist/io.js
|
|
7663
7737
|
import { spawn } from "node:child_process";
|
|
@@ -7680,7 +7754,7 @@ function realIo(prompt) {
|
|
|
7680
7754
|
stdout: process.stdout,
|
|
7681
7755
|
stderr: process.stderr,
|
|
7682
7756
|
prompt: prompt && isInteractive() ? prompt : void 0,
|
|
7683
|
-
exec: (command, args, options = {}) => new Promise((
|
|
7757
|
+
exec: (command, args, options = {}) => new Promise((resolve9, reject) => {
|
|
7684
7758
|
const child = spawn(command, args, {
|
|
7685
7759
|
cwd: options.cwd,
|
|
7686
7760
|
env: options.env,
|
|
@@ -7703,7 +7777,7 @@ function realIo(prompt) {
|
|
|
7703
7777
|
child.on("error", reject);
|
|
7704
7778
|
child.on("close", (code) => {
|
|
7705
7779
|
if (code === 0)
|
|
7706
|
-
|
|
7780
|
+
resolve9(stdout);
|
|
7707
7781
|
else
|
|
7708
7782
|
reject(new ExecError(render(command, args), code, stderr));
|
|
7709
7783
|
});
|
|
@@ -7794,7 +7868,7 @@ ${header.join("\n")}
|
|
|
7794
7868
|
|
|
7795
7869
|
${lines.join("\n")}
|
|
7796
7870
|
`;
|
|
7797
|
-
return { path: path3, releases, changes, content, plan: [write(root ?
|
|
7871
|
+
return { path: path3, releases, changes, content, plan: [write(root ? join3(root, path3) : path3, content)] };
|
|
7798
7872
|
}
|
|
7799
7873
|
function describeChange(c) {
|
|
7800
7874
|
const peer = c.field === "peerDependencies" ? " (peer)" : "";
|
|
@@ -7843,7 +7917,7 @@ async function readChangeset(ctx, dir, base, branch) {
|
|
|
7843
7917
|
};
|
|
7844
7918
|
const current = async (path4) => {
|
|
7845
7919
|
try {
|
|
7846
|
-
return await ctx.readFile(
|
|
7920
|
+
return await ctx.readFile(join3(dir, path4));
|
|
7847
7921
|
} catch {
|
|
7848
7922
|
return void 0;
|
|
7849
7923
|
}
|
|
@@ -7859,7 +7933,7 @@ async function readChangeset(ctx, dir, base, branch) {
|
|
|
7859
7933
|
}
|
|
7860
7934
|
const config = await current(`${CHANGESET_DIR}/config.json`);
|
|
7861
7935
|
const ignore = config ? JSON.parse(config).ignore ?? [] : [];
|
|
7862
|
-
const entries = await ctx.readDir(
|
|
7936
|
+
const entries = await ctx.readDir(join3(dir, CHANGESET_DIR)).catch(() => []);
|
|
7863
7937
|
const path3 = changesetPath(head);
|
|
7864
7938
|
return planChangeset({
|
|
7865
7939
|
branch: head,
|
|
@@ -7879,7 +7953,7 @@ async function expand(ctx, root, glob) {
|
|
|
7879
7953
|
if (star < 0)
|
|
7880
7954
|
return [glob.replace(/\/$/, "")];
|
|
7881
7955
|
const parent = glob.slice(0, star).replace(/\/$/, "");
|
|
7882
|
-
const entries = await ctx.readDir(
|
|
7956
|
+
const entries = await ctx.readDir(join3(root, parent)).catch(() => []);
|
|
7883
7957
|
return entries.filter((e) => e.directory && !e.name.startsWith(".")).map((e) => parent ? `${parent}/${e.name}` : e.name).sort();
|
|
7884
7958
|
}
|
|
7885
7959
|
|
|
@@ -7975,6 +8049,8 @@ var Context = class {
|
|
|
7975
8049
|
*/
|
|
7976
8050
|
result(data, human = renderHuman) {
|
|
7977
8051
|
const text = this.json ? JSON.stringify(data, null, 2) : human(data);
|
|
8052
|
+
if (text === "")
|
|
8053
|
+
return;
|
|
7978
8054
|
this.io.stdout.write(text.endsWith("\n") ? text : `${text}
|
|
7979
8055
|
`);
|
|
7980
8056
|
}
|
|
@@ -8069,6 +8145,13 @@ function parseAnswers(text) {
|
|
|
8069
8145
|
};
|
|
8070
8146
|
}
|
|
8071
8147
|
|
|
8148
|
+
// ../lib/dist/deployTargets.js
|
|
8149
|
+
var import_yaml4 = __toESM(require_dist(), 1);
|
|
8150
|
+
import { join as join5 } from "node:path";
|
|
8151
|
+
|
|
8152
|
+
// ../lib/dist/train.js
|
|
8153
|
+
import { join as join4 } from "node:path";
|
|
8154
|
+
|
|
8072
8155
|
// ../lib/dist/doctor.js
|
|
8073
8156
|
import { relative as relative2 } from "node:path";
|
|
8074
8157
|
function diagnose(root, catalog) {
|
|
@@ -8128,6 +8211,130 @@ function compareTrains(a, b) {
|
|
|
8128
8211
|
return 0;
|
|
8129
8212
|
}
|
|
8130
8213
|
|
|
8214
|
+
// ../lib/dist/train.js
|
|
8215
|
+
var TRAIN_REPOS = [
|
|
8216
|
+
"platform",
|
|
8217
|
+
"ci-cd",
|
|
8218
|
+
"preset-repo-web",
|
|
8219
|
+
"preset-app-nextjs",
|
|
8220
|
+
"preset-repo-platform",
|
|
8221
|
+
"compendium"
|
|
8222
|
+
];
|
|
8223
|
+
var UPSTREAM = "plexus-ms";
|
|
8224
|
+
var isTrainVersion = (v) => /^\d+\.\d+\.\d+$/.test(v);
|
|
8225
|
+
function nextMinor(version2) {
|
|
8226
|
+
const [major = "0", minor = "0"] = version2.split(".");
|
|
8227
|
+
return `${major}.${Number(minor) + 1}.0`;
|
|
8228
|
+
}
|
|
8229
|
+
function latestTag(tags) {
|
|
8230
|
+
return tags.filter((t) => /^v?\d/.test(t)).sort((a, b) => compareTrains(a.replace(/^v/, ""), b.replace(/^v/, ""))).at(-1);
|
|
8231
|
+
}
|
|
8232
|
+
async function readTrain(ctx, upstream) {
|
|
8233
|
+
const repos = [];
|
|
8234
|
+
const all = /* @__PURE__ */ new Set();
|
|
8235
|
+
for (const name of TRAIN_REPOS) {
|
|
8236
|
+
const path3 = join4(upstream, name);
|
|
8237
|
+
try {
|
|
8238
|
+
await ctx.read("git", ["rev-parse", "--git-dir"], { cwd: path3 });
|
|
8239
|
+
} catch {
|
|
8240
|
+
throw new Error(`${path3} is not a git repo`);
|
|
8241
|
+
}
|
|
8242
|
+
try {
|
|
8243
|
+
await ctx.read("git", ["fetch", "origin", "--tags", "--quiet"], { cwd: path3 });
|
|
8244
|
+
} catch {
|
|
8245
|
+
throw new Error(`${name}: fetch from origin failed`);
|
|
8246
|
+
}
|
|
8247
|
+
const tags = (await ctx.read("git", ["tag", "--list", "v*", "[0-9]*"], { cwd: path3 })).split("\n").filter(Boolean);
|
|
8248
|
+
for (const t of tags)
|
|
8249
|
+
all.add(t.replace(/^v/, ""));
|
|
8250
|
+
const tag = latestTag(tags);
|
|
8251
|
+
const range = tag ? `${tag}..HEAD` : "HEAD";
|
|
8252
|
+
const pending = (await ctx.read("git", ["log", "--oneline", range], { cwd: path3 })).split("\n").filter(Boolean);
|
|
8253
|
+
repos.push({ name, path: path3, tag, latest: tag?.replace(/^v/, ""), pending });
|
|
8254
|
+
}
|
|
8255
|
+
const latest = repos.map((r) => r.latest);
|
|
8256
|
+
return { repos, last: latestTag([...all]), skew: latest.some((l) => l !== latest[0]) };
|
|
8257
|
+
}
|
|
8258
|
+
async function preflightRelease(ctx, train) {
|
|
8259
|
+
for (const { name, path: path3 } of train.repos) {
|
|
8260
|
+
const branch = (await ctx.read("git", ["rev-parse", "--abbrev-ref", "HEAD"], { cwd: path3 })).trim();
|
|
8261
|
+
if (branch !== "main")
|
|
8262
|
+
throw new Error(`${name} is on '${branch}', trains cut from main`);
|
|
8263
|
+
if ((await ctx.read("git", ["status", "--porcelain"], { cwd: path3 })).trim() !== "")
|
|
8264
|
+
throw new Error(`${name} has uncommitted changes \u2014 commit first`);
|
|
8265
|
+
const behind = (await ctx.read("git", ["rev-list", "--count", "main..origin/main"], { cwd: path3 })).trim();
|
|
8266
|
+
if (behind !== "0")
|
|
8267
|
+
throw new Error(`${name} is ${behind} commit(s) behind origin/main \u2014 pull first, or the tag lands on a stale commit`);
|
|
8268
|
+
}
|
|
8269
|
+
}
|
|
8270
|
+
function resolveVersion(train, explicit, propagateOnly) {
|
|
8271
|
+
if (explicit !== void 0 && !isTrainVersion(explicit))
|
|
8272
|
+
throw new UsageError(`'${explicit}' is not plain semver (X.Y.Z, no v)`);
|
|
8273
|
+
if (propagateOnly) {
|
|
8274
|
+
const v = explicit ?? train.last;
|
|
8275
|
+
if (!v)
|
|
8276
|
+
throw new Error("no train version found to propagate");
|
|
8277
|
+
return v;
|
|
8278
|
+
}
|
|
8279
|
+
if (explicit)
|
|
8280
|
+
return explicit;
|
|
8281
|
+
if (train.skew) {
|
|
8282
|
+
const report = train.repos.map((r) => ` ${r.name}: ${r.latest ?? "none"}`).join("\n");
|
|
8283
|
+
throw new Error(`the train repos' latest tags disagree:
|
|
8284
|
+
${report}
|
|
8285
|
+
pass the version explicitly (--train ${train.last}) to finish the half-tagged train, or a higher one to start a new one`);
|
|
8286
|
+
}
|
|
8287
|
+
return train.last ? nextMinor(train.last) : "0.1.0";
|
|
8288
|
+
}
|
|
8289
|
+
var UsageError = class extends Error {
|
|
8290
|
+
};
|
|
8291
|
+
|
|
8292
|
+
// ../lib/dist/deployTargets.js
|
|
8293
|
+
var VARS_DIRS = ["group_vars", "host_vars"];
|
|
8294
|
+
function parseInventoryFile(path3, text) {
|
|
8295
|
+
const data = (0, import_yaml4.parse)(text);
|
|
8296
|
+
const vars = data !== null && typeof data === "object" ? data : {};
|
|
8297
|
+
const target = typeof vars.plexus_deploy_target === "string" ? vars.plexus_deploy_target : void 0;
|
|
8298
|
+
const records = Array.isArray(vars.plexus_apps) ? vars.plexus_apps : [];
|
|
8299
|
+
const apps = records.map((r) => r !== null && typeof r === "object" ? r.name : void 0).filter((n) => typeof n === "string");
|
|
8300
|
+
return { path: path3, target, apps };
|
|
8301
|
+
}
|
|
8302
|
+
function selectDeployTargets(files) {
|
|
8303
|
+
const targets = {};
|
|
8304
|
+
const declaredIn = {};
|
|
8305
|
+
for (const file of [...files].sort((a, b) => a.path.localeCompare(b.path))) {
|
|
8306
|
+
if (file.target === void 0)
|
|
8307
|
+
continue;
|
|
8308
|
+
for (const app of file.apps) {
|
|
8309
|
+
if (app in targets)
|
|
8310
|
+
throw new Error(`app "${app}" is declared with a deploy target in both ${declaredIn[app]} and ${file.path}`);
|
|
8311
|
+
targets[app] = file.target;
|
|
8312
|
+
declaredIn[app] = file.path;
|
|
8313
|
+
}
|
|
8314
|
+
}
|
|
8315
|
+
return Object.fromEntries(Object.entries(targets).sort(([a], [b]) => a.localeCompare(b)));
|
|
8316
|
+
}
|
|
8317
|
+
async function readDeployTargets(ctx, inventory) {
|
|
8318
|
+
const files = [];
|
|
8319
|
+
let found = false;
|
|
8320
|
+
for (const sub of VARS_DIRS) {
|
|
8321
|
+
const dir = join5(inventory, sub);
|
|
8322
|
+
const entries = await ctx.readDir(dir).catch(() => void 0);
|
|
8323
|
+
if (entries === void 0)
|
|
8324
|
+
continue;
|
|
8325
|
+
found = true;
|
|
8326
|
+
for (const e of entries) {
|
|
8327
|
+
if (e.directory || !/\.ya?ml$/.test(e.name))
|
|
8328
|
+
continue;
|
|
8329
|
+
const path3 = join5(dir, e.name);
|
|
8330
|
+
files.push(parseInventoryFile(path3, await ctx.readFile(path3)));
|
|
8331
|
+
}
|
|
8332
|
+
}
|
|
8333
|
+
if (!found && await ctx.readDir(inventory).catch(() => void 0) === void 0)
|
|
8334
|
+
throw new UsageError(`no inventory directory at ${inventory}`);
|
|
8335
|
+
return selectDeployTargets(files);
|
|
8336
|
+
}
|
|
8337
|
+
|
|
8131
8338
|
// ../lib/dist/model.js
|
|
8132
8339
|
function kindOf(declaration) {
|
|
8133
8340
|
const has = (code) => declaration.modules.includes(code);
|
|
@@ -8149,7 +8356,7 @@ function isNotable(dir) {
|
|
|
8149
8356
|
}
|
|
8150
8357
|
|
|
8151
8358
|
// ../lib/dist/overview.js
|
|
8152
|
-
import { join as
|
|
8359
|
+
import { join as join6 } from "node:path";
|
|
8153
8360
|
var PRUNED = /* @__PURE__ */ new Set([
|
|
8154
8361
|
"node_modules",
|
|
8155
8362
|
".hg",
|
|
@@ -8197,7 +8404,7 @@ async function walk(ctx, path3, name, options) {
|
|
|
8197
8404
|
}
|
|
8198
8405
|
const subdirs = entries.filter((e) => e.directory && e.name !== ".git" && !PRUNED.has(e.name)).map((e) => e.name).sort();
|
|
8199
8406
|
for (const sub of subdirs) {
|
|
8200
|
-
const child = await walk(ctx,
|
|
8407
|
+
const child = await walk(ctx, join6(path3, sub), sub, options);
|
|
8201
8408
|
if (isNotable(child) || child.children.length > 0)
|
|
8202
8409
|
dir.children.push(child);
|
|
8203
8410
|
}
|
|
@@ -8205,7 +8412,7 @@ async function walk(ctx, path3, name, options) {
|
|
|
8205
8412
|
}
|
|
8206
8413
|
async function facet(ctx, dir, file, read) {
|
|
8207
8414
|
try {
|
|
8208
|
-
read(await ctx.readFile(
|
|
8415
|
+
read(await ctx.readFile(join6(dir.path, file)));
|
|
8209
8416
|
} catch (error) {
|
|
8210
8417
|
dir.problems ??= [];
|
|
8211
8418
|
dir.problems.push(`${file}: ${error instanceof Error ? error.message : String(error)}`);
|
|
@@ -8244,93 +8451,12 @@ async function templateFacet(ctx, cwd) {
|
|
|
8244
8451
|
}
|
|
8245
8452
|
|
|
8246
8453
|
// ../lib/dist/propagate.js
|
|
8247
|
-
import { join as
|
|
8248
|
-
|
|
8249
|
-
// ../lib/dist/train.js
|
|
8250
|
-
import { join as join4 } from "node:path";
|
|
8251
|
-
var TRAIN_REPOS = [
|
|
8252
|
-
"platform",
|
|
8253
|
-
"ci-cd",
|
|
8254
|
-
"preset-repo-web",
|
|
8255
|
-
"preset-app-nextjs",
|
|
8256
|
-
"preset-repo-platform",
|
|
8257
|
-
"compendium"
|
|
8258
|
-
];
|
|
8259
|
-
var UPSTREAM = "plexus-ms";
|
|
8260
|
-
var isTrainVersion = (v) => /^\d+\.\d+\.\d+$/.test(v);
|
|
8261
|
-
function nextMinor(version2) {
|
|
8262
|
-
const [major = "0", minor = "0"] = version2.split(".");
|
|
8263
|
-
return `${major}.${Number(minor) + 1}.0`;
|
|
8264
|
-
}
|
|
8265
|
-
function latestTag(tags) {
|
|
8266
|
-
return tags.filter((t) => /^v?\d/.test(t)).sort((a, b) => compareTrains(a.replace(/^v/, ""), b.replace(/^v/, ""))).at(-1);
|
|
8267
|
-
}
|
|
8268
|
-
async function readTrain(ctx, upstream) {
|
|
8269
|
-
const repos = [];
|
|
8270
|
-
const all = /* @__PURE__ */ new Set();
|
|
8271
|
-
for (const name of TRAIN_REPOS) {
|
|
8272
|
-
const path3 = join4(upstream, name);
|
|
8273
|
-
try {
|
|
8274
|
-
await ctx.read("git", ["rev-parse", "--git-dir"], { cwd: path3 });
|
|
8275
|
-
} catch {
|
|
8276
|
-
throw new Error(`${path3} is not a git repo`);
|
|
8277
|
-
}
|
|
8278
|
-
try {
|
|
8279
|
-
await ctx.read("git", ["fetch", "origin", "--tags", "--quiet"], { cwd: path3 });
|
|
8280
|
-
} catch {
|
|
8281
|
-
throw new Error(`${name}: fetch from origin failed`);
|
|
8282
|
-
}
|
|
8283
|
-
const tags = (await ctx.read("git", ["tag", "--list", "v*", "[0-9]*"], { cwd: path3 })).split("\n").filter(Boolean);
|
|
8284
|
-
for (const t of tags)
|
|
8285
|
-
all.add(t.replace(/^v/, ""));
|
|
8286
|
-
const tag = latestTag(tags);
|
|
8287
|
-
const range = tag ? `${tag}..HEAD` : "HEAD";
|
|
8288
|
-
const pending = (await ctx.read("git", ["log", "--oneline", range], { cwd: path3 })).split("\n").filter(Boolean);
|
|
8289
|
-
repos.push({ name, path: path3, tag, latest: tag?.replace(/^v/, ""), pending });
|
|
8290
|
-
}
|
|
8291
|
-
const latest = repos.map((r) => r.latest);
|
|
8292
|
-
return { repos, last: latestTag([...all]), skew: latest.some((l) => l !== latest[0]) };
|
|
8293
|
-
}
|
|
8294
|
-
async function preflightRelease(ctx, train) {
|
|
8295
|
-
for (const { name, path: path3 } of train.repos) {
|
|
8296
|
-
const branch = (await ctx.read("git", ["rev-parse", "--abbrev-ref", "HEAD"], { cwd: path3 })).trim();
|
|
8297
|
-
if (branch !== "main")
|
|
8298
|
-
throw new Error(`${name} is on '${branch}', trains cut from main`);
|
|
8299
|
-
if ((await ctx.read("git", ["status", "--porcelain"], { cwd: path3 })).trim() !== "")
|
|
8300
|
-
throw new Error(`${name} has uncommitted changes \u2014 commit first`);
|
|
8301
|
-
const behind = (await ctx.read("git", ["rev-list", "--count", "main..origin/main"], { cwd: path3 })).trim();
|
|
8302
|
-
if (behind !== "0")
|
|
8303
|
-
throw new Error(`${name} is ${behind} commit(s) behind origin/main \u2014 pull first, or the tag lands on a stale commit`);
|
|
8304
|
-
}
|
|
8305
|
-
}
|
|
8306
|
-
function resolveVersion(train, explicit, propagateOnly) {
|
|
8307
|
-
if (explicit !== void 0 && !isTrainVersion(explicit))
|
|
8308
|
-
throw new UsageError(`'${explicit}' is not plain semver (X.Y.Z, no v)`);
|
|
8309
|
-
if (propagateOnly) {
|
|
8310
|
-
const v = explicit ?? train.last;
|
|
8311
|
-
if (!v)
|
|
8312
|
-
throw new Error("no train version found to propagate");
|
|
8313
|
-
return v;
|
|
8314
|
-
}
|
|
8315
|
-
if (explicit)
|
|
8316
|
-
return explicit;
|
|
8317
|
-
if (train.skew) {
|
|
8318
|
-
const report = train.repos.map((r) => ` ${r.name}: ${r.latest ?? "none"}`).join("\n");
|
|
8319
|
-
throw new Error(`the train repos' latest tags disagree:
|
|
8320
|
-
${report}
|
|
8321
|
-
pass the version explicitly (--train ${train.last}) to finish the half-tagged train, or a higher one to start a new one`);
|
|
8322
|
-
}
|
|
8323
|
-
return train.last ? nextMinor(train.last) : "0.1.0";
|
|
8324
|
-
}
|
|
8325
|
-
var UsageError = class extends Error {
|
|
8326
|
-
};
|
|
8327
|
-
|
|
8328
|
-
// ../lib/dist/propagate.js
|
|
8454
|
+
import { join as join7, relative as relative3 } from "node:path";
|
|
8329
8455
|
var isClean = (s) => s.conflicted.length === 0 && s.failed.length === 0 && s.skipped.length === 0;
|
|
8330
8456
|
var PREVIEW_BASE = "ship-base";
|
|
8331
8457
|
async function propagate(ctx, workspace, train) {
|
|
8332
8458
|
const summary = { train, preview: ctx.dryRun, clean: [], conflicted: [], failed: [], skipped: [] };
|
|
8333
|
-
const upstream =
|
|
8459
|
+
const upstream = join7(workspace, UPSTREAM);
|
|
8334
8460
|
const tree = await overview(ctx, workspace);
|
|
8335
8461
|
const upstreamDir = tree.children.find((c) => c.path === upstream);
|
|
8336
8462
|
const presets = TRAIN_REPOS.filter((r) => upstreamDir?.children.some((c) => c.name === r && c.template));
|
|
@@ -8347,7 +8473,7 @@ async function propagate(ctx, workspace, train) {
|
|
|
8347
8473
|
const cloneOf = async (consumer) => {
|
|
8348
8474
|
let clone = clones.get(consumer.path);
|
|
8349
8475
|
if (!clone) {
|
|
8350
|
-
clone =
|
|
8476
|
+
clone = join7(scratch ?? "", consumer.rel);
|
|
8351
8477
|
await ctx.stage(run("git", ["clone", "--quiet", consumer.path, clone]));
|
|
8352
8478
|
await ctx.stage(run("git", ["tag", PREVIEW_BASE], { cwd: clone }));
|
|
8353
8479
|
clones.set(consumer.path, clone);
|
|
@@ -8374,7 +8500,7 @@ async function propagate(ctx, workspace, train) {
|
|
|
8374
8500
|
if (sites.length === 0)
|
|
8375
8501
|
ctx.say(`\u2022 no consumers of ${presetSource(preset)} found under ${workspace}`);
|
|
8376
8502
|
for (const [consumer, site] of sites)
|
|
8377
|
-
await updateSite(ctx, consumer, site,
|
|
8503
|
+
await updateSite(ctx, consumer, site, join7(upstream, preset), summary, cloneOf, previewCommit);
|
|
8378
8504
|
}
|
|
8379
8505
|
await refreshLockfiles(ctx, active, summary, clones);
|
|
8380
8506
|
await bumpConsumerRefs(ctx, consumers, train);
|
|
@@ -8391,9 +8517,9 @@ async function updateSite(ctx, consumer, site, localPreset, summary, cloneOf, pr
|
|
|
8391
8517
|
if (ctx.dryRun) {
|
|
8392
8518
|
ctx.say(`\u2192 ${site.rel}: copier update (preview from ${localPreset}@main)`);
|
|
8393
8519
|
repo = await cloneOf(consumer);
|
|
8394
|
-
target =
|
|
8395
|
-
const answers = await ctx.readFile(
|
|
8396
|
-
await ctx.stage(write(
|
|
8520
|
+
target = join7(repo, relative3(consumer.path, site.path));
|
|
8521
|
+
const answers = await ctx.readFile(join7(site.path, ANSWERS_FILE));
|
|
8522
|
+
await ctx.stage(write(join7(target, ANSWERS_FILE), answers.replace(/^_src_path: .*$/m, `_src_path: ${localPreset}`)));
|
|
8397
8523
|
await previewCommit(repo, `plx preview: ${site.rel} reads ${localPreset} from the local checkout`);
|
|
8398
8524
|
await ctx.stage(run("copier", ["update", "--skip-answered", "--trust", "--defaults", "--skip-tasks", "--vcs-ref", "main"], {
|
|
8399
8525
|
cwd: target
|
|
@@ -8412,7 +8538,7 @@ async function updateSite(ctx, consumer, site, localPreset, summary, cloneOf, pr
|
|
|
8412
8538
|
let conflict = hasUnmergedEntries(status);
|
|
8413
8539
|
const changed = (await ctx.read("git", ["diff", "--name-only"], { cwd: repo })).split("\n").filter(Boolean);
|
|
8414
8540
|
for (const f of changed) {
|
|
8415
|
-
const text = await ctx.readFile(
|
|
8541
|
+
const text = await ctx.readFile(join7(repo, f)).catch(() => "");
|
|
8416
8542
|
if (hasConflictMarkers(text))
|
|
8417
8543
|
conflict = true;
|
|
8418
8544
|
}
|
|
@@ -8430,17 +8556,17 @@ async function updateSite(ctx, consumer, site, localPreset, summary, cloneOf, pr
|
|
|
8430
8556
|
await previewCommit(repo, `plx preview: ${site.rel} updated`);
|
|
8431
8557
|
}
|
|
8432
8558
|
async function syncSiteMarker(ctx, site, target) {
|
|
8433
|
-
const marker = await ctx.readFile(
|
|
8559
|
+
const marker = await ctx.readFile(join7(target, MARKER_FILE)).catch(() => void 0);
|
|
8434
8560
|
if (marker === void 0)
|
|
8435
8561
|
return;
|
|
8436
|
-
const { commit } = parseAnswers(await ctx.readFile(
|
|
8562
|
+
const { commit } = parseAnswers(await ctx.readFile(join7(target, ANSWERS_FILE)));
|
|
8437
8563
|
if (!commit)
|
|
8438
8564
|
return;
|
|
8439
8565
|
const synced = syncMarker(marker, commit);
|
|
8440
8566
|
if (synced === marker)
|
|
8441
8567
|
return;
|
|
8442
8568
|
ctx.say(` marker: plexus \u2192 ${commit} in ${site.rel}/${MARKER_FILE}`);
|
|
8443
|
-
const step = write(
|
|
8569
|
+
const step = write(join7(target, MARKER_FILE), synced);
|
|
8444
8570
|
if (ctx.dryRun)
|
|
8445
8571
|
await ctx.stage(step);
|
|
8446
8572
|
else
|
|
@@ -8449,7 +8575,7 @@ async function syncSiteMarker(ctx, site, target) {
|
|
|
8449
8575
|
async function refreshLockfiles(ctx, consumers, summary, clones) {
|
|
8450
8576
|
const manifests = ["*package.json", "pnpm-workspace.yaml"];
|
|
8451
8577
|
for (const c of consumers) {
|
|
8452
|
-
if (await ctx.readFile(
|
|
8578
|
+
if (await ctx.readFile(join7(c.path, "pnpm-workspace.yaml")).catch(() => void 0) === void 0)
|
|
8453
8579
|
continue;
|
|
8454
8580
|
const repo = ctx.dryRun ? clones.get(c.path) : c.path;
|
|
8455
8581
|
if (!repo)
|
|
@@ -8469,7 +8595,7 @@ async function refreshLockfiles(ctx, consumers, summary, clones) {
|
|
|
8469
8595
|
}
|
|
8470
8596
|
async function bumpConsumerRefs(ctx, consumers, train) {
|
|
8471
8597
|
for (const c of consumers) {
|
|
8472
|
-
const dir =
|
|
8598
|
+
const dir = join7(c.path, ".github", "workflows");
|
|
8473
8599
|
const entries = await ctx.readDir(dir).catch(() => []);
|
|
8474
8600
|
const files = entries.filter((e) => !e.directory && /\.ya?ml$/.test(e.name)).map((e) => e.name).sort();
|
|
8475
8601
|
if (files.length === 0)
|
|
@@ -8479,14 +8605,14 @@ async function bumpConsumerRefs(ctx, consumers, train) {
|
|
|
8479
8605
|
continue;
|
|
8480
8606
|
}
|
|
8481
8607
|
for (const f of files) {
|
|
8482
|
-
const text = await ctx.readFile(
|
|
8608
|
+
const text = await ctx.readFile(join7(dir, f));
|
|
8483
8609
|
if (!text.includes(WORKFLOW_REF))
|
|
8484
8610
|
continue;
|
|
8485
8611
|
const bumped = bumpWorkflowRefs(text, train);
|
|
8486
8612
|
if (bumped === text)
|
|
8487
8613
|
continue;
|
|
8488
8614
|
ctx.say(`\u2192 ${c.rel}: ${f} ci-cd refs \u2192 @${train}`);
|
|
8489
|
-
await ctx.apply([write(
|
|
8615
|
+
await ctx.apply([write(join7(dir, f), bumped)]);
|
|
8490
8616
|
}
|
|
8491
8617
|
}
|
|
8492
8618
|
}
|
|
@@ -8497,7 +8623,7 @@ var detail = (error) => {
|
|
|
8497
8623
|
};
|
|
8498
8624
|
|
|
8499
8625
|
// ../lib/dist/requirements.js
|
|
8500
|
-
import { join as
|
|
8626
|
+
import { join as join8 } from "node:path";
|
|
8501
8627
|
var KEYWORD = /MUST|SHOULD|MAY/;
|
|
8502
8628
|
var hasKeyword = (line) => KEYWORD.test(line.replace(/MUSTs|SHOULDs|MAYs/g, ""));
|
|
8503
8629
|
var list = (value) => value.replace(/^\s*\[/, "").replace(/\].*$/, "").split(",").map((s) => s.trim()).filter(Boolean);
|
|
@@ -8590,7 +8716,7 @@ var MAP_PAGE = "essentials/standard.md";
|
|
|
8590
8716
|
async function modulePages(ctx, compendium) {
|
|
8591
8717
|
const pages = [];
|
|
8592
8718
|
for (const dir of Object.keys(CATALOG_DIRS)) {
|
|
8593
|
-
const entries = await ctx.readDir(
|
|
8719
|
+
const entries = await ctx.readDir(join8(compendium, dir));
|
|
8594
8720
|
for (const e of entries.filter((e2) => !e2.directory && e2.name.endsWith(".md") && e2.name !== "index.md").sort())
|
|
8595
8721
|
pages.push(`${dir}/${e.name}`);
|
|
8596
8722
|
}
|
|
@@ -8598,11 +8724,11 @@ async function modulePages(ctx, compendium) {
|
|
|
8598
8724
|
}
|
|
8599
8725
|
async function checkCompendium(ctx, compendium) {
|
|
8600
8726
|
const defects = [];
|
|
8601
|
-
defects.push(...scanPage(await ctx.readFile(
|
|
8727
|
+
defects.push(...scanPage(await ctx.readFile(join8(compendium, MAP_PAGE)), MAP_PAGE, "map").defects);
|
|
8602
8728
|
const pages = await modulePages(ctx, compendium);
|
|
8603
8729
|
const scans = /* @__PURE__ */ new Map();
|
|
8604
8730
|
for (const page of pages) {
|
|
8605
|
-
const scan = scanPage(await ctx.readFile(
|
|
8731
|
+
const scan = scanPage(await ctx.readFile(join8(compendium, page)), page, "module");
|
|
8606
8732
|
defects.push(...scan.defects);
|
|
8607
8733
|
scans.set(page, scan);
|
|
8608
8734
|
}
|
|
@@ -8649,9 +8775,9 @@ async function checkCompendium(ctx, compendium) {
|
|
|
8649
8775
|
}
|
|
8650
8776
|
|
|
8651
8777
|
// ../lib/dist/ship.js
|
|
8652
|
-
import { join as
|
|
8778
|
+
import { join as join9 } from "node:path";
|
|
8653
8779
|
async function ship(ctx, options) {
|
|
8654
|
-
const upstream =
|
|
8780
|
+
const upstream = join9(options.workspace, UPSTREAM);
|
|
8655
8781
|
const propagateOnly = options.propagateOnly ?? false;
|
|
8656
8782
|
const train = await readTrain(ctx, upstream);
|
|
8657
8783
|
if (!propagateOnly)
|
|
@@ -8702,7 +8828,7 @@ async function planBookkeeping(ctx, train, next, today2) {
|
|
|
8702
8828
|
return r;
|
|
8703
8829
|
};
|
|
8704
8830
|
const edit = async (r, rel, what, transform) => {
|
|
8705
|
-
const path3 =
|
|
8831
|
+
const path3 = join9(r.path, rel);
|
|
8706
8832
|
const text = await ctx.readFile(path3).catch(() => void 0);
|
|
8707
8833
|
if (text === void 0)
|
|
8708
8834
|
return;
|
|
@@ -8723,7 +8849,7 @@ async function planBookkeeping(ctx, train, next, today2) {
|
|
|
8723
8849
|
const comp = repo("compendium");
|
|
8724
8850
|
await edit(comp, MAP_PAGE, `version \u2192 ${next}, timestamp \u2192 ${today2}`, (t) => stampStandard(t, next, today2));
|
|
8725
8851
|
for (const page of await modulePages(ctx, comp.path)) {
|
|
8726
|
-
const text = await ctx.readFile(
|
|
8852
|
+
const text = await ctx.readFile(join9(comp.path, page));
|
|
8727
8853
|
if (frontmatterField(text, "maturity") !== "standard")
|
|
8728
8854
|
continue;
|
|
8729
8855
|
const previous = comp.tag ? await ctx.read("git", ["show", `${comp.tag}:${page}`], { cwd: comp.path }).catch(() => "") : "";
|
|
@@ -9686,13 +9812,13 @@ import { AsyncResource as AsyncResource3 } from "node:async_hooks";
|
|
|
9686
9812
|
|
|
9687
9813
|
// ../../node_modules/.pnpm/@inquirer+type@4.2.0_@types+node@26.6.5/node_modules/@inquirer/type/dist/utils.js
|
|
9688
9814
|
function withResolver() {
|
|
9689
|
-
let
|
|
9815
|
+
let resolve9;
|
|
9690
9816
|
let reject;
|
|
9691
9817
|
const promise = new Promise((res, rej) => {
|
|
9692
|
-
|
|
9818
|
+
resolve9 = res;
|
|
9693
9819
|
reject = rej;
|
|
9694
9820
|
});
|
|
9695
|
-
return { promise, resolve:
|
|
9821
|
+
return { promise, resolve: resolve9, reject };
|
|
9696
9822
|
}
|
|
9697
9823
|
|
|
9698
9824
|
// ../../node_modules/.pnpm/@inquirer+core@12.0.5_@types+node@26.6.5/node_modules/@inquirer/core/dist/lib/create-prompt.js
|
|
@@ -10071,7 +10197,7 @@ function createPrompt(view) {
|
|
|
10071
10197
|
});
|
|
10072
10198
|
output.mute();
|
|
10073
10199
|
const screen = new ScreenManager(rl);
|
|
10074
|
-
const { promise, resolve:
|
|
10200
|
+
const { promise, resolve: resolve9, reject } = withResolver();
|
|
10075
10201
|
return withHooks(rl, (cycle) => {
|
|
10076
10202
|
const clearEffects = AsyncResource3.bind(() => effectScheduler.clearAll());
|
|
10077
10203
|
const settlePrompt = (settle) => {
|
|
@@ -10082,7 +10208,7 @@ function createPrompt(view) {
|
|
|
10082
10208
|
reject(error);
|
|
10083
10209
|
}
|
|
10084
10210
|
};
|
|
10085
|
-
const resolvePrompt = (value) => settlePrompt(() =>
|
|
10211
|
+
const resolvePrompt = (value) => settlePrompt(() => resolve9(value));
|
|
10086
10212
|
const rejectPrompt = (error) => settlePrompt(() => reject(error));
|
|
10087
10213
|
const promptPromise = Object.assign(promise.finally(() => {
|
|
10088
10214
|
cleanups.forEach((cleanup) => cleanup());
|
|
@@ -13601,12 +13727,22 @@ function useColor() {
|
|
|
13601
13727
|
// ../../node_modules/.pnpm/commander@15.0.0/node_modules/commander/index.js
|
|
13602
13728
|
var program = new Command();
|
|
13603
13729
|
|
|
13604
|
-
// src/commands/
|
|
13730
|
+
// src/commands/changed-apps.ts
|
|
13605
13731
|
import { resolve } from "node:path";
|
|
13606
13732
|
function register(program2) {
|
|
13733
|
+
program2.command("changed-apps").description("list the apps whose sources changed between two refs, dependents of a changed package included").argument("<from>", "the base ref; empty, all zeros or unknown lists every app").argument("[to]", "the ref compared against", "HEAD").option("-C, --dir <dir>", "the checkout to read", ".").action(async (from, to, opts, command) => {
|
|
13734
|
+
const ctx = contextOf2(command);
|
|
13735
|
+
const result = await readChangedApps(ctx, resolve(opts.dir), from, to);
|
|
13736
|
+
ctx.result(result.apps);
|
|
13737
|
+
});
|
|
13738
|
+
}
|
|
13739
|
+
|
|
13740
|
+
// src/commands/changeset.ts
|
|
13741
|
+
import { resolve as resolve2 } from "node:path";
|
|
13742
|
+
function register2(program2) {
|
|
13607
13743
|
program2.command("changeset").description("write the changeset a dependency bump owes: a patch per package whose runtime dependencies moved").argument("[dir]", "a checkout of the package repo, on the bump branch", ".").option("--base <ref>", "the trunk the branch is diffed against, at the merge base", "origin/main").option("--branch <name>", "the branch name that names the file (default: the checked-out branch)").action(async (dir, opts, command) => {
|
|
13608
13744
|
const ctx = contextOf2(command);
|
|
13609
|
-
const changeset = await readChangeset(ctx,
|
|
13745
|
+
const changeset = await readChangeset(ctx, resolve2(dir), opts.base, opts.branch);
|
|
13610
13746
|
await ctx.apply(changeset.plan);
|
|
13611
13747
|
ctx.result(changeset, renderChangeset);
|
|
13612
13748
|
});
|
|
@@ -13617,9 +13753,19 @@ function renderChangeset(c) {
|
|
|
13617
13753
|
return [`\u2713 ${c.path}`, ...releases.map(([name, bump]) => ` ${name}: ${bump}`)].join("\n");
|
|
13618
13754
|
}
|
|
13619
13755
|
|
|
13756
|
+
// src/commands/deploy-targets.ts
|
|
13757
|
+
import { resolve as resolve3 } from "node:path";
|
|
13758
|
+
function register3(program2) {
|
|
13759
|
+
program2.command("deploy-targets").description("map each app of a platform repo to the deploy target of the inventory file that declares it").argument("[inventory]", "the inventory directory", "inventory").action(async (inventory, _opts, command) => {
|
|
13760
|
+
const ctx = contextOf2(command);
|
|
13761
|
+
const targets = await readDeployTargets(ctx, resolve3(inventory));
|
|
13762
|
+
ctx.result(targets, (t) => JSON.stringify(t));
|
|
13763
|
+
});
|
|
13764
|
+
}
|
|
13765
|
+
|
|
13620
13766
|
// src/commands/doctor.ts
|
|
13621
13767
|
import { existsSync } from "node:fs";
|
|
13622
|
-
import { join as
|
|
13768
|
+
import { join as join10, resolve as resolve4 } from "node:path";
|
|
13623
13769
|
|
|
13624
13770
|
// src/style.ts
|
|
13625
13771
|
function style(enabled) {
|
|
@@ -13630,15 +13776,15 @@ var colorByDefault = () => process.stdout.isTTY === true && !process.env.NO_COLO
|
|
|
13630
13776
|
|
|
13631
13777
|
// src/commands/doctor.ts
|
|
13632
13778
|
var WORKSPACE_COMPENDIUM = "plexus-ms/compendium";
|
|
13633
|
-
function
|
|
13779
|
+
function register4(program2) {
|
|
13634
13780
|
program2.command("doctor").description("check every PLEXUS.md under a directory for modules that changed since and dependencies not declared").argument("[dir]", "directory to check", ".").option(
|
|
13635
13781
|
"--compendium <path>",
|
|
13636
13782
|
`compendium checkout to read the modules from (default: <dir>/${WORKSPACE_COMPENDIUM})`
|
|
13637
13783
|
).option("--color", "colour the report even when piped").option("--no-color", "never colour the report").action(async (dir, opts, command) => {
|
|
13638
13784
|
const ctx = contextOf2(command);
|
|
13639
|
-
const root =
|
|
13640
|
-
const compendium =
|
|
13641
|
-
if (!existsSync(
|
|
13785
|
+
const root = resolve4(dir);
|
|
13786
|
+
const compendium = resolve4(opts.compendium ?? join10(root, WORKSPACE_COMPENDIUM));
|
|
13787
|
+
if (!existsSync(join10(compendium, "contracts")))
|
|
13642
13788
|
throw new Error(
|
|
13643
13789
|
`no compendium at ${compendium}; pass --compendium <path to a checkout of plexus-ms/compendium>`
|
|
13644
13790
|
);
|
|
@@ -13666,11 +13812,11 @@ function renderReport(report, s, showCurrent) {
|
|
|
13666
13812
|
}
|
|
13667
13813
|
|
|
13668
13814
|
// src/commands/overview.ts
|
|
13669
|
-
import { resolve as
|
|
13670
|
-
function
|
|
13815
|
+
import { resolve as resolve5 } from "node:path";
|
|
13816
|
+
function register5(program2) {
|
|
13671
13817
|
program2.command("overview").description("map the git repos, copier templates and projects, and Plexus units under a directory").argument("[dir]", "directory to map", ".").option("--color", "colour the tree even when piped").option("--no-color", "never colour the tree").action(async (dir, opts, command) => {
|
|
13672
13818
|
const ctx = contextOf2(command);
|
|
13673
|
-
const tree = await overview(ctx,
|
|
13819
|
+
const tree = await overview(ctx, resolve5(dir));
|
|
13674
13820
|
const s = style(opts.color ?? colorByDefault());
|
|
13675
13821
|
ctx.result(tree, (t) => renderTree(t, s, ctx.verbose >= 1));
|
|
13676
13822
|
});
|
|
@@ -13713,14 +13859,14 @@ function annotate(dir, s, modules) {
|
|
|
13713
13859
|
}
|
|
13714
13860
|
|
|
13715
13861
|
// src/commands/propagate.ts
|
|
13716
|
-
import { resolve as
|
|
13862
|
+
import { resolve as resolve7 } from "node:path";
|
|
13717
13863
|
|
|
13718
13864
|
// src/commands/ship.ts
|
|
13719
|
-
import { resolve as
|
|
13720
|
-
function
|
|
13865
|
+
import { resolve as resolve6 } from "node:path";
|
|
13866
|
+
function register6(program2) {
|
|
13721
13867
|
program2.command("ship").description("release the train: tag every train repo identically, then copier-update every consumer").argument("[dir]", "the workspace: plexus-ms/ and the consumers sit under it", ".").option("--train <version>", "the train version, plain semver (default: minor+1 over the latest train)").action(async (dir, opts, command) => {
|
|
13722
13868
|
const ctx = contextOf2(command);
|
|
13723
|
-
const result = await ship(ctx, { workspace:
|
|
13869
|
+
const result = await ship(ctx, { workspace: resolve6(dir), train: opts.train });
|
|
13724
13870
|
ctx.result(result, (r) => renderSummary(r, `plx -y ship --train ${r.train} ${dir}`));
|
|
13725
13871
|
if (!isClean(result)) process.exitCode = 1;
|
|
13726
13872
|
});
|
|
@@ -13743,23 +13889,23 @@ function renderSummary(s, realCommand) {
|
|
|
13743
13889
|
}
|
|
13744
13890
|
|
|
13745
13891
|
// src/commands/propagate.ts
|
|
13746
|
-
function
|
|
13892
|
+
function register7(program2) {
|
|
13747
13893
|
program2.command("propagate").description("copier-update every consumer of the presets to the current train, and pin their ci-cd workflow refs").argument("[dir]", "the workspace: plexus-ms/ and the consumers sit under it", ".").option("--train <version>", "the train to propagate (default: the current one)").action(async (dir, opts, command) => {
|
|
13748
13894
|
const ctx = contextOf2(command);
|
|
13749
|
-
const result = await ship(ctx, { workspace:
|
|
13895
|
+
const result = await ship(ctx, { workspace: resolve7(dir), train: opts.train, propagateOnly: true });
|
|
13750
13896
|
ctx.result(result, (r) => renderSummary(r, `plx -y propagate --train ${r.train} ${dir}`));
|
|
13751
13897
|
if (!isClean(result)) process.exitCode = 1;
|
|
13752
13898
|
});
|
|
13753
13899
|
}
|
|
13754
13900
|
|
|
13755
13901
|
// src/commands/requirements.ts
|
|
13756
|
-
import { join as
|
|
13757
|
-
function
|
|
13902
|
+
import { join as join11, resolve as resolve8 } from "node:path";
|
|
13903
|
+
function register8(program2) {
|
|
13758
13904
|
program2.command("requirements").description("lint the standard's map and module pages, or extract one module's requirement lines").argument("[dir]", "a checkout of the compendium", ".").option("--extract <page>", "print a module page's requirement lines instead of linting (path relative to dir)").action(async (dir, opts, command) => {
|
|
13759
13905
|
const ctx = contextOf2(command);
|
|
13760
|
-
const compendium =
|
|
13906
|
+
const compendium = resolve8(dir);
|
|
13761
13907
|
if (opts.extract) {
|
|
13762
|
-
ctx.result(extractRequirements(await ctx.readFile(
|
|
13908
|
+
ctx.result(extractRequirements(await ctx.readFile(join11(compendium, opts.extract))));
|
|
13763
13909
|
return;
|
|
13764
13910
|
}
|
|
13765
13911
|
const check = await checkCompendium(ctx, compendium);
|
|
@@ -13773,7 +13919,16 @@ function renderCheck(c) {
|
|
|
13773
13919
|
}
|
|
13774
13920
|
|
|
13775
13921
|
// src/commands/index.ts
|
|
13776
|
-
var commands = [
|
|
13922
|
+
var commands = [
|
|
13923
|
+
register5,
|
|
13924
|
+
register4,
|
|
13925
|
+
register6,
|
|
13926
|
+
register7,
|
|
13927
|
+
register8,
|
|
13928
|
+
register2,
|
|
13929
|
+
register,
|
|
13930
|
+
register3
|
|
13931
|
+
];
|
|
13777
13932
|
|
|
13778
13933
|
// src/program.ts
|
|
13779
13934
|
var { version, description } = createRequire(import.meta.url)("../package.json");
|
|
@@ -13782,7 +13937,7 @@ function buildProgram() {
|
|
|
13782
13937
|
program2.addOption(new Option("-n, --dry-run", "print every effect this run would have, perform none").env("PLX_DRY_RUN")).addOption(
|
|
13783
13938
|
new Option("-v, --verbose", "say more: once for reads and inputs, twice for command output").argParser((_value, previous) => previous + 1).default(0)
|
|
13784
13939
|
).addOption(new Option("-q, --quiet", "say nothing but results and errors").env("PLX_QUIET")).addOption(new Option("-y, --yes", "answer every confirmation with yes (needed off a terminal)").env("PLX_YES")).addOption(new Option("--json", "print results as JSON").env("PLX_JSON"));
|
|
13785
|
-
for (const
|
|
13940
|
+
for (const register9 of commands) register9(program2);
|
|
13786
13941
|
return program2;
|
|
13787
13942
|
}
|
|
13788
13943
|
function contextOf2(command) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@plexus-ms/cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.0",
|
|
4
4
|
"description": "plx, the Plexus command-line tool: a single-script adapter over @plexus-ms/lib",
|
|
5
5
|
"license": "GPL-3.0-or-later",
|
|
6
6
|
"type": "module",
|
|
@@ -20,11 +20,11 @@
|
|
|
20
20
|
"access": "public"
|
|
21
21
|
},
|
|
22
22
|
"engines": {
|
|
23
|
-
"node": ">=24"
|
|
23
|
+
"node": ">=24.22.1"
|
|
24
24
|
},
|
|
25
25
|
"dependencies": {
|
|
26
26
|
"@inquirer/prompts": "^8.7.4",
|
|
27
|
-
"@plexus-ms/lib": "0.
|
|
27
|
+
"@plexus-ms/lib": "0.5.0",
|
|
28
28
|
"commander": "^15.0.0"
|
|
29
29
|
},
|
|
30
30
|
"devDependencies": {
|