@plexus-ms/cli 0.9.0 → 0.100.0-rc.3
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 +350 -174
- package/package.json +3 -3
package/dist/plx.js
CHANGED
|
@@ -7567,9 +7567,10 @@ function frontmatterField(text, key) {
|
|
|
7567
7567
|
|
|
7568
7568
|
// ../lib/dist/bookkeeping.js
|
|
7569
7569
|
var bumpGalaxyVersion = (text, train) => text.replace(/^(version: )\d+\.\d+\.\d+/m, `$1${train}`);
|
|
7570
|
+
var COLLECTION_SOURCE = "plexus-ms/primitives.git";
|
|
7570
7571
|
function bumpCollectionPin(text, train) {
|
|
7571
7572
|
const lines = text.split("\n");
|
|
7572
|
-
const start = lines.findIndex((l) => l.includes(
|
|
7573
|
+
const start = lines.findIndex((l) => l.includes(COLLECTION_SOURCE));
|
|
7573
7574
|
if (start === -1)
|
|
7574
7575
|
return text;
|
|
7575
7576
|
for (let i = start; i < lines.length; i++) {
|
|
@@ -7581,8 +7582,13 @@ function bumpCollectionPin(text, train) {
|
|
|
7581
7582
|
}
|
|
7582
7583
|
return lines.join("\n");
|
|
7583
7584
|
}
|
|
7584
|
-
var WORKFLOW_REF = "plexus-ms/
|
|
7585
|
-
var bumpWorkflowRefs = (text, train) => text.replace(/(plexus-ms\/
|
|
7585
|
+
var WORKFLOW_REF = "plexus-ms/primitives/.github/workflows/";
|
|
7586
|
+
var bumpWorkflowRefs = (text, train) => text.replace(/(plexus-ms\/primitives\/\.github\/workflows\/[A-Za-z0-9._-]+)@v?[0-9.]+/g, `$1@${train}`);
|
|
7587
|
+
var bumpManifestVersion = (text, train) => text.replace(/^(\s*"version":\s*")[^"]*(")/m, `$1${train}$2`);
|
|
7588
|
+
var PLX_PIN = "npm:@plexus-ms/cli";
|
|
7589
|
+
var bumpPlxPin = (text, train) => text.replace(/("npm:@plexus-ms\/cli"\s*=\s*(?:\{\s*version\s*=\s*)?")[^"]*(")/g, `$1${train}$2`);
|
|
7590
|
+
var CONFIG_PIN = "@plexus-ms/config";
|
|
7591
|
+
var bumpConfigPin = (text, train) => text.replace(/("@plexus-ms\/config":\s*")(?!workspace:|catalog:)[^"]*(")/g, `$1${train}$2`);
|
|
7586
7592
|
var stampStandard = (text, train, today2) => setFrontmatterField(setFrontmatterField(text, "version", train), "timestamp", today2);
|
|
7587
7593
|
var stampChanged = (text, train) => setFrontmatterField(text, "changed", train, { after: "binds" });
|
|
7588
7594
|
var hasConflictMarkers = (text) => /^<<<<<<< /m.test(text);
|
|
@@ -7968,13 +7974,13 @@ async function expand(ctx, root, glob) {
|
|
|
7968
7974
|
|
|
7969
7975
|
// ../lib/dist/consumers.js
|
|
7970
7976
|
import { relative } from "node:path";
|
|
7971
|
-
function expectedBranch(declaration) {
|
|
7977
|
+
function expectedBranch(declaration, answers = {}) {
|
|
7972
7978
|
if (!declaration)
|
|
7973
7979
|
return void 0;
|
|
7974
7980
|
if (declaration.modules.includes("PLX-Platform"))
|
|
7975
7981
|
return "main";
|
|
7976
7982
|
if (declaration.modules.includes("PLX-Repo"))
|
|
7977
|
-
return "develop";
|
|
7983
|
+
return answers.publishes_packages === true ? "main" : "develop";
|
|
7978
7984
|
return void 0;
|
|
7979
7985
|
}
|
|
7980
7986
|
var presetSource = (preset) => `gh:plexus-ms/${preset}`;
|
|
@@ -7993,11 +7999,12 @@ async function findConsumers(ctx, root, presets) {
|
|
|
7993
7999
|
else {
|
|
7994
8000
|
let consumer = consumers.get(here.path);
|
|
7995
8001
|
if (!consumer) {
|
|
8002
|
+
const expected = expectedBranch(here.declaration, here.copier?.answers);
|
|
7996
8003
|
consumer = {
|
|
7997
8004
|
path: here.path,
|
|
7998
8005
|
rel: relative(root.path, here.path) || ".",
|
|
7999
|
-
branch: here.git?.branch ?? "
|
|
8000
|
-
expected
|
|
8006
|
+
branch: expected ?? here.git?.branch ?? "main",
|
|
8007
|
+
expected,
|
|
8001
8008
|
sites: []
|
|
8002
8009
|
};
|
|
8003
8010
|
consumers.set(here.path, consumer);
|
|
@@ -8012,13 +8019,11 @@ async function findConsumers(ctx, root, presets) {
|
|
|
8012
8019
|
for (const site of orphans)
|
|
8013
8020
|
ctx.say(`\u26A0 ${site.rel}: not inside a git repo \u2014 skipped`);
|
|
8014
8021
|
for (const c of consumers.values()) {
|
|
8015
|
-
|
|
8016
|
-
|
|
8017
|
-
|
|
8018
|
-
|
|
8019
|
-
|
|
8020
|
-
if (tracked !== "")
|
|
8021
|
-
c.skipped = "has uncommitted changes";
|
|
8022
|
+
const origin = (await ctx.read("git", ["remote", "get-url", "origin"], { cwd: c.path }).catch(() => "")).trim();
|
|
8023
|
+
if (origin === "")
|
|
8024
|
+
c.skipped = "no origin remote";
|
|
8025
|
+
else
|
|
8026
|
+
c.origin = origin;
|
|
8022
8027
|
}
|
|
8023
8028
|
return [...consumers.values()];
|
|
8024
8029
|
}
|
|
@@ -8222,14 +8227,20 @@ function compareTrains(a, b) {
|
|
|
8222
8227
|
}
|
|
8223
8228
|
|
|
8224
8229
|
// ../lib/dist/train.js
|
|
8230
|
+
var PRIMITIVES = "primitives";
|
|
8225
8231
|
var TRAIN_REPOS = [
|
|
8226
|
-
|
|
8227
|
-
"ci-cd",
|
|
8232
|
+
PRIMITIVES,
|
|
8228
8233
|
"preset-repo-web",
|
|
8229
8234
|
"preset-app-nextjs",
|
|
8230
8235
|
"preset-repo-platform",
|
|
8231
8236
|
"compendium"
|
|
8232
8237
|
];
|
|
8238
|
+
var PHASES = [[PRIMITIVES], TRAIN_REPOS.filter((r) => r !== PRIMITIVES)];
|
|
8239
|
+
var TRAIN_PACKAGES = [
|
|
8240
|
+
{ name: "@plexus-ms/cli", dir: "packages/cli" },
|
|
8241
|
+
{ name: "@plexus-ms/lib", dir: "packages/lib" },
|
|
8242
|
+
{ name: "@plexus-ms/config", dir: "packages/config" }
|
|
8243
|
+
];
|
|
8233
8244
|
var UPSTREAM = "plexus-ms";
|
|
8234
8245
|
var isTrainVersion = (v) => /^\d+\.\d+\.\d+$/.test(v);
|
|
8235
8246
|
function nextMinor(version2) {
|
|
@@ -8265,6 +8276,7 @@ async function readTrain(ctx, upstream) {
|
|
|
8265
8276
|
const latest = repos2.map((r) => r.latest);
|
|
8266
8277
|
return { repos: repos2, last: latestTag([...all]), skew: latest.some((l) => l !== latest[0]) };
|
|
8267
8278
|
}
|
|
8279
|
+
var phasesOf = (train) => PHASES.map((names) => train.repos.filter((r) => names.includes(r.name)));
|
|
8268
8280
|
async function preflightRelease(ctx, train) {
|
|
8269
8281
|
for (const { name, path: path3 } of train.repos) {
|
|
8270
8282
|
const branch = (await ctx.read("git", ["rev-parse", "--abbrev-ref", "HEAD"], { cwd: path3 })).trim();
|
|
@@ -8277,6 +8289,13 @@ async function preflightRelease(ctx, train) {
|
|
|
8277
8289
|
throw new Error(`${name} is ${behind} commit(s) behind origin/main \u2014 pull first, or the tag lands on a stale commit`);
|
|
8278
8290
|
}
|
|
8279
8291
|
}
|
|
8292
|
+
async function preflightForge(ctx) {
|
|
8293
|
+
try {
|
|
8294
|
+
await ctx.read("gh", ["auth", "status"]);
|
|
8295
|
+
} catch {
|
|
8296
|
+
throw new Error("gh is not logged in (gh auth status failed) \u2014 run gh auth login first");
|
|
8297
|
+
}
|
|
8298
|
+
}
|
|
8280
8299
|
function resolveVersion(train, explicit, propagateOnly) {
|
|
8281
8300
|
if (explicit !== void 0 && !isTrainVersion(explicit))
|
|
8282
8301
|
throw new UsageError(`'${explicit}' is not plain semver (X.Y.Z, no v)`);
|
|
@@ -8663,9 +8682,18 @@ async function templateFacet(ctx, cwd) {
|
|
|
8663
8682
|
// ../lib/dist/propagate.js
|
|
8664
8683
|
import { join as join8, relative as relative3 } from "node:path";
|
|
8665
8684
|
var isClean = (s) => s.conflicted.length === 0 && s.failed.length === 0 && s.skipped.length === 0;
|
|
8666
|
-
var
|
|
8685
|
+
var BASE_TAG = "ship-base";
|
|
8686
|
+
var trainBranch = (train) => `train/${train}`;
|
|
8667
8687
|
async function propagate(ctx, workspace, train) {
|
|
8668
|
-
const summary = {
|
|
8688
|
+
const summary = {
|
|
8689
|
+
train,
|
|
8690
|
+
preview: ctx.dryRun,
|
|
8691
|
+
clean: [],
|
|
8692
|
+
conflicted: [],
|
|
8693
|
+
failed: [],
|
|
8694
|
+
skipped: [],
|
|
8695
|
+
pulls: []
|
|
8696
|
+
};
|
|
8669
8697
|
const upstream = join8(workspace, UPSTREAM);
|
|
8670
8698
|
const tree = await overview(ctx, workspace);
|
|
8671
8699
|
const upstreamDir = tree.children.find((c) => c.path === upstream);
|
|
@@ -8677,64 +8705,63 @@ async function propagate(ctx, workspace, train) {
|
|
|
8677
8705
|
ctx.say(`\u26A0 ${c.rel}: ${c.skipped} \u2014 skipped (fix it, then re-run propagate)`);
|
|
8678
8706
|
summary.skipped.push({ path: c.rel, reason: c.skipped });
|
|
8679
8707
|
}
|
|
8680
|
-
const
|
|
8681
|
-
|
|
8682
|
-
|
|
8683
|
-
const
|
|
8684
|
-
let clone = clones.get(consumer.path);
|
|
8685
|
-
if (!clone) {
|
|
8686
|
-
clone = join8(scratch ?? "", consumer.rel);
|
|
8687
|
-
await ctx.stage(run("git", ["clone", "--quiet", consumer.path, clone]));
|
|
8688
|
-
await ctx.stage(run("git", ["tag", PREVIEW_BASE], { cwd: clone }));
|
|
8689
|
-
clones.set(consumer.path, clone);
|
|
8690
|
-
}
|
|
8691
|
-
return clone;
|
|
8692
|
-
};
|
|
8693
|
-
const previewCommit = (clone, message) => ctx.stage(run("git", ["add", "-A"], { cwd: clone })).then(() => ctx.stage(run("git", [
|
|
8694
|
-
"-c",
|
|
8695
|
-
"commit.gpgsign=false",
|
|
8696
|
-
"-c",
|
|
8697
|
-
"user.name=plx",
|
|
8698
|
-
"-c",
|
|
8699
|
-
"user.email=plx@localhost",
|
|
8700
|
-
"commit",
|
|
8701
|
-
"--quiet",
|
|
8702
|
-
"--no-verify",
|
|
8703
|
-
"--allow-empty",
|
|
8704
|
-
"-m",
|
|
8705
|
-
message
|
|
8706
|
-
], { cwd: clone })));
|
|
8708
|
+
for (const preset of presets)
|
|
8709
|
+
if (!consumers.some((c) => c.sites.some((s) => s.preset === preset)))
|
|
8710
|
+
ctx.say(`\u2022 no consumers of ${presetSource(preset)} found under ${workspace}`);
|
|
8711
|
+
const scratch = (await ctx.stage(run("mktemp", ["-d"])))?.trim() ?? "";
|
|
8707
8712
|
try {
|
|
8708
|
-
for (const
|
|
8709
|
-
|
|
8710
|
-
|
|
8711
|
-
|
|
8712
|
-
|
|
8713
|
-
|
|
8714
|
-
|
|
8715
|
-
|
|
8716
|
-
|
|
8713
|
+
for (const consumer of consumers) {
|
|
8714
|
+
if (consumer.skipped || !consumer.origin)
|
|
8715
|
+
continue;
|
|
8716
|
+
const clone = join8(scratch, consumer.rel);
|
|
8717
|
+
ctx.say(`\u2192 ${consumer.rel}: clone ${consumer.origin} at ${consumer.branch}`);
|
|
8718
|
+
try {
|
|
8719
|
+
await ctx.stage(run("git", ["clone", "--quiet", "--branch", consumer.branch, consumer.origin, clone]));
|
|
8720
|
+
await ctx.stage(run("git", ["tag", BASE_TAG], { cwd: clone }));
|
|
8721
|
+
} catch (error) {
|
|
8722
|
+
ctx.say(` \u2717 FAILED \u2014 clone${detail(error)}`);
|
|
8723
|
+
summary.failed.push(consumer.rel);
|
|
8724
|
+
continue;
|
|
8725
|
+
}
|
|
8726
|
+
for (const site of consumer.sites)
|
|
8727
|
+
await updateSite(ctx, consumer, site, clone, upstream, summary);
|
|
8728
|
+
await refreshLockfile(ctx, consumer, clone, summary);
|
|
8729
|
+
await bumpConsumerRefs(ctx, consumer, clone, train);
|
|
8730
|
+
await openPull(ctx, consumer, clone, train, summary);
|
|
8731
|
+
}
|
|
8717
8732
|
} finally {
|
|
8718
8733
|
if (scratch)
|
|
8719
8734
|
await ctx.stage(run("rm", ["-rf", scratch]));
|
|
8720
8735
|
}
|
|
8721
8736
|
return summary;
|
|
8722
8737
|
}
|
|
8723
|
-
|
|
8724
|
-
|
|
8725
|
-
|
|
8738
|
+
var previewCommit = (ctx, clone, message) => ctx.stage(run("git", ["add", "-A"], { cwd: clone })).then(() => ctx.stage(run("git", [
|
|
8739
|
+
"-c",
|
|
8740
|
+
"commit.gpgsign=false",
|
|
8741
|
+
"-c",
|
|
8742
|
+
"user.name=plx",
|
|
8743
|
+
"-c",
|
|
8744
|
+
"user.email=plx@localhost",
|
|
8745
|
+
"commit",
|
|
8746
|
+
"--quiet",
|
|
8747
|
+
"--no-verify",
|
|
8748
|
+
"--allow-empty",
|
|
8749
|
+
"-m",
|
|
8750
|
+
message
|
|
8751
|
+
], { cwd: clone })));
|
|
8752
|
+
async function updateSite(ctx, consumer, site, clone, upstream, summary) {
|
|
8753
|
+
const target = join8(clone, relative3(consumer.path, site.path));
|
|
8754
|
+
const localPreset = join8(upstream, site.preset);
|
|
8726
8755
|
try {
|
|
8727
8756
|
if (ctx.dryRun) {
|
|
8728
8757
|
ctx.say(`\u2192 ${site.rel}: copier update (preview from ${localPreset}@main)`);
|
|
8729
|
-
|
|
8730
|
-
target = join8(repo, relative3(consumer.path, site.path));
|
|
8731
|
-
const answers = await ctx.readFile(join8(site.path, ANSWERS_FILE));
|
|
8758
|
+
const answers = await ctx.readFile(join8(target, ANSWERS_FILE));
|
|
8732
8759
|
await ctx.stage(write(join8(target, ANSWERS_FILE), answers.replace(/^_src_path: .*$/m, `_src_path: ${localPreset}`)));
|
|
8733
|
-
await previewCommit(
|
|
8760
|
+
await previewCommit(ctx, clone, `plx preview: ${site.rel} reads ${localPreset} from the local checkout`);
|
|
8734
8761
|
await ctx.stage(run("mise", copierVia(["update", "--skip-answered", "--trust", "--defaults", "--skip-tasks", "--vcs-ref", "main"]), { cwd: target }));
|
|
8735
8762
|
} else {
|
|
8736
8763
|
ctx.say(`\u2192 ${site.rel}: copier update`);
|
|
8737
|
-
const args = ["update", "--skip-answered", "--trust", ...ctx.yes ? ["--defaults"] : []];
|
|
8764
|
+
const args = ["update", "--skip-answered", "--trust", "--skip-tasks", ...ctx.yes ? ["--defaults"] : []];
|
|
8738
8765
|
await ctx.apply([run("mise", copierVia(args), { cwd: target, interactive: true })]);
|
|
8739
8766
|
}
|
|
8740
8767
|
} catch (error) {
|
|
@@ -8742,17 +8769,17 @@ async function updateSite(ctx, consumer, site, localPreset, summary, cloneOf, pr
|
|
|
8742
8769
|
summary.failed.push(site.rel);
|
|
8743
8770
|
return;
|
|
8744
8771
|
}
|
|
8745
|
-
const status = await ctx.read("git", ["status", "--porcelain"], { cwd:
|
|
8772
|
+
const status = await ctx.read("git", ["status", "--porcelain", "--", "."], { cwd: target });
|
|
8746
8773
|
let conflict = hasUnmergedEntries(status);
|
|
8747
|
-
const changed = (await ctx.read("git", ["diff", "--name-only"], { cwd:
|
|
8774
|
+
const changed = (await ctx.read("git", ["diff", "--name-only", "--relative", "--", "."], { cwd: target })).split("\n").filter(Boolean);
|
|
8748
8775
|
for (const f of changed) {
|
|
8749
|
-
const text = await ctx.readFile(join8(
|
|
8776
|
+
const text = await ctx.readFile(join8(target, f)).catch(() => "");
|
|
8750
8777
|
if (hasConflictMarkers(text))
|
|
8751
8778
|
conflict = true;
|
|
8752
8779
|
}
|
|
8753
8780
|
await syncSiteMarker(ctx, site, target);
|
|
8754
8781
|
if (conflict) {
|
|
8755
|
-
ctx.say(" \u2717 CONFLICTS \u2014
|
|
8782
|
+
ctx.say(" \u2717 CONFLICTS \u2014 committed with their <<<<<<< markers, to resolve in the pull request:");
|
|
8756
8783
|
summary.conflicted.push(site.rel);
|
|
8757
8784
|
} else {
|
|
8758
8785
|
ctx.say(" \u2713 merged clean:");
|
|
@@ -8761,7 +8788,7 @@ async function updateSite(ctx, consumer, site, localPreset, summary, cloneOf, pr
|
|
|
8761
8788
|
for (const line of status.split("\n").filter(Boolean))
|
|
8762
8789
|
ctx.say(` ${line}`);
|
|
8763
8790
|
if (ctx.dryRun)
|
|
8764
|
-
await previewCommit(
|
|
8791
|
+
await previewCommit(ctx, clone, `plx preview: ${site.rel} updated`);
|
|
8765
8792
|
}
|
|
8766
8793
|
async function syncSiteMarker(ctx, site, target) {
|
|
8767
8794
|
const marker = await ctx.readFile(join8(target, MARKER_FILE)).catch(() => void 0);
|
|
@@ -8774,55 +8801,129 @@ async function syncSiteMarker(ctx, site, target) {
|
|
|
8774
8801
|
if (synced === marker)
|
|
8775
8802
|
return;
|
|
8776
8803
|
ctx.say(` marker: plexus \u2192 ${commit} in ${site.rel}/${MARKER_FILE}`);
|
|
8777
|
-
|
|
8778
|
-
if (ctx.dryRun)
|
|
8779
|
-
await ctx.stage(step);
|
|
8780
|
-
else
|
|
8781
|
-
await ctx.apply([step]);
|
|
8804
|
+
await ctx.stage(write(join8(target, MARKER_FILE), synced));
|
|
8782
8805
|
}
|
|
8783
|
-
async function
|
|
8806
|
+
async function refreshLockfile(ctx, consumer, clone, summary) {
|
|
8807
|
+
if (await ctx.readFile(join8(clone, "pnpm-workspace.yaml")).catch(() => void 0) === void 0)
|
|
8808
|
+
return;
|
|
8784
8809
|
const manifests = ["*package.json", "pnpm-workspace.yaml"];
|
|
8785
|
-
|
|
8786
|
-
|
|
8787
|
-
|
|
8788
|
-
|
|
8789
|
-
|
|
8790
|
-
|
|
8791
|
-
|
|
8792
|
-
|
|
8793
|
-
|
|
8794
|
-
continue;
|
|
8795
|
-
ctx.say(`\u2192 ${c.rel}: pnpm install (manifests changed)`);
|
|
8796
|
-
try {
|
|
8797
|
-
await ctx.apply([run("mise", ["exec", "--", "pnpm", "install", "--reporter=silent"], { cwd: c.path })]);
|
|
8798
|
-
} catch (error) {
|
|
8799
|
-
ctx.say(` \u2717 pnpm install failed${detail(error)}`);
|
|
8800
|
-
summary.failed.push(`${c.rel}/pnpm-lock.yaml`);
|
|
8801
|
-
}
|
|
8810
|
+
const unchanged = await ctx.read("git", ["diff", "--quiet", BASE_TAG, "--", ...manifests], { cwd: clone }).then(() => true).catch(() => false);
|
|
8811
|
+
if (unchanged)
|
|
8812
|
+
return;
|
|
8813
|
+
ctx.say(`\u2192 ${consumer.rel}: pnpm install (manifests changed)`);
|
|
8814
|
+
try {
|
|
8815
|
+
await ctx.apply([run("mise", ["exec", "--", "pnpm", "install", "--reporter=silent"], { cwd: clone })]);
|
|
8816
|
+
} catch (error) {
|
|
8817
|
+
ctx.say(` \u2717 pnpm install failed${detail(error)}`);
|
|
8818
|
+
summary.failed.push(`${consumer.rel}/pnpm-lock.yaml`);
|
|
8802
8819
|
}
|
|
8803
8820
|
}
|
|
8804
|
-
async function bumpConsumerRefs(ctx,
|
|
8805
|
-
|
|
8806
|
-
|
|
8807
|
-
|
|
8808
|
-
|
|
8809
|
-
|
|
8821
|
+
async function bumpConsumerRefs(ctx, consumer, clone, train) {
|
|
8822
|
+
const dir = join8(clone, ".github", "workflows");
|
|
8823
|
+
const entries = await ctx.readDir(dir).catch(() => []);
|
|
8824
|
+
const files = entries.filter((e) => !e.directory && /\.ya?ml$/.test(e.name)).map((e) => e.name).sort();
|
|
8825
|
+
for (const f of files) {
|
|
8826
|
+
const text = await ctx.readFile(join8(dir, f));
|
|
8827
|
+
if (!text.includes(WORKFLOW_REF))
|
|
8810
8828
|
continue;
|
|
8811
|
-
|
|
8812
|
-
|
|
8829
|
+
const bumped = bumpWorkflowRefs(text, train);
|
|
8830
|
+
if (bumped === text)
|
|
8813
8831
|
continue;
|
|
8814
|
-
}
|
|
8815
|
-
|
|
8816
|
-
|
|
8817
|
-
|
|
8818
|
-
|
|
8819
|
-
|
|
8820
|
-
|
|
8821
|
-
|
|
8822
|
-
|
|
8823
|
-
|
|
8824
|
-
|
|
8832
|
+
ctx.say(`\u2192 ${consumer.rel}: ${f} workflow refs \u2192 @${train}`);
|
|
8833
|
+
await ctx.stage(write(join8(dir, f), bumped));
|
|
8834
|
+
}
|
|
8835
|
+
}
|
|
8836
|
+
async function openPull(ctx, consumer, clone, train, summary) {
|
|
8837
|
+
const branch = trainBranch(train);
|
|
8838
|
+
if (ctx.dryRun) {
|
|
8839
|
+
ctx.say(` (preview) ${consumer.rel}: would commit, push ${branch} and open a pull request against ${consumer.branch}`);
|
|
8840
|
+
return;
|
|
8841
|
+
}
|
|
8842
|
+
if ((await ctx.read("git", ["status", "--porcelain"], { cwd: clone })).trim() === "") {
|
|
8843
|
+
ctx.say(`\u2022 ${consumer.rel}: nothing changed \u2014 no pull request`);
|
|
8844
|
+
return;
|
|
8825
8845
|
}
|
|
8846
|
+
const head = `${consumer.origin} ${branch}`;
|
|
8847
|
+
try {
|
|
8848
|
+
await ctx.apply([
|
|
8849
|
+
run("git", ["add", "-A"], { cwd: clone }),
|
|
8850
|
+
run("git", ["commit", "--quiet", "--no-verify", "-m", `chore: train ${train}`], { cwd: clone })
|
|
8851
|
+
]);
|
|
8852
|
+
await ctx.read("git", ["fetch", "--quiet", "origin", `+refs/heads/${branch}:refs/remotes/origin/${branch}`], {
|
|
8853
|
+
cwd: clone
|
|
8854
|
+
}).catch(() => "");
|
|
8855
|
+
await ctx.apply([
|
|
8856
|
+
run("git", ["push", "--quiet", "--force-with-lease", "origin", `HEAD:refs/heads/${branch}`], { cwd: clone })
|
|
8857
|
+
]);
|
|
8858
|
+
} catch (error) {
|
|
8859
|
+
ctx.say(` \u2717 FAILED \u2014 push to ${head}${detail(error)}`);
|
|
8860
|
+
summary.failed.push(consumer.rel);
|
|
8861
|
+
return;
|
|
8862
|
+
}
|
|
8863
|
+
const existing = (await ctx.read("gh", [
|
|
8864
|
+
"pr",
|
|
8865
|
+
"list",
|
|
8866
|
+
"--head",
|
|
8867
|
+
branch,
|
|
8868
|
+
"--base",
|
|
8869
|
+
consumer.branch,
|
|
8870
|
+
"--state",
|
|
8871
|
+
"open",
|
|
8872
|
+
"--json",
|
|
8873
|
+
"url",
|
|
8874
|
+
"--jq",
|
|
8875
|
+
".[0].url"
|
|
8876
|
+
], { cwd: clone }).catch(() => "")).trim();
|
|
8877
|
+
if (existing) {
|
|
8878
|
+
ctx.say(`\u2022 ${consumer.rel}: pull request updated: ${existing}`);
|
|
8879
|
+
summary.pulls.push(existing);
|
|
8880
|
+
return;
|
|
8881
|
+
}
|
|
8882
|
+
const sites = consumer.sites.map((s) => s.rel);
|
|
8883
|
+
const conflicted = sites.filter((s) => summary.conflicted.includes(s));
|
|
8884
|
+
const body2 = [
|
|
8885
|
+
`Train ${train} (\xA7 1.5 PLX): \`copier update\` at ${sites.join(", ")}, the marker, the lockfile where manifests moved, and the workflow refs.`,
|
|
8886
|
+
conflicted.length > 0 ? `Conflicts to resolve, committed with their markers: ${conflicted.join(", ")}.` : "Merged clean at every site.",
|
|
8887
|
+
"Opened by `plx ship`."
|
|
8888
|
+
].join("\n\n");
|
|
8889
|
+
try {
|
|
8890
|
+
await ctx.apply([
|
|
8891
|
+
run("gh", [
|
|
8892
|
+
"pr",
|
|
8893
|
+
"create",
|
|
8894
|
+
"--base",
|
|
8895
|
+
consumer.branch,
|
|
8896
|
+
"--head",
|
|
8897
|
+
branch,
|
|
8898
|
+
"--title",
|
|
8899
|
+
`chore: train ${train}`,
|
|
8900
|
+
"--body",
|
|
8901
|
+
body2
|
|
8902
|
+
], { cwd: clone })
|
|
8903
|
+
]);
|
|
8904
|
+
} catch (error) {
|
|
8905
|
+
ctx.say(` \u2717 FAILED \u2014 pull request${detail(error)}`);
|
|
8906
|
+
summary.failed.push(consumer.rel);
|
|
8907
|
+
return;
|
|
8908
|
+
}
|
|
8909
|
+
const url = (await ctx.read("gh", [
|
|
8910
|
+
"pr",
|
|
8911
|
+
"list",
|
|
8912
|
+
"--head",
|
|
8913
|
+
branch,
|
|
8914
|
+
"--base",
|
|
8915
|
+
consumer.branch,
|
|
8916
|
+
"--state",
|
|
8917
|
+
"open",
|
|
8918
|
+
"--json",
|
|
8919
|
+
"url",
|
|
8920
|
+
"--jq",
|
|
8921
|
+
".[0].url"
|
|
8922
|
+
], {
|
|
8923
|
+
cwd: clone
|
|
8924
|
+
}).catch(() => "")).trim();
|
|
8925
|
+
ctx.say(`\u2022 ${consumer.rel}: pull request opened${url ? `: ${url}` : ""}`);
|
|
8926
|
+
summary.pulls.push(url || `${consumer.rel} ${branch}`);
|
|
8826
8927
|
}
|
|
8827
8928
|
var detail = (error) => {
|
|
8828
8929
|
const message = error instanceof Error ? error.message : String(error);
|
|
@@ -8996,59 +9097,118 @@ async function preflightSelf(ctx, running) {
|
|
|
8996
9097
|
|
|
8997
9098
|
// ../lib/dist/ship.js
|
|
8998
9099
|
import { join as join10 } from "node:path";
|
|
9100
|
+
var DEFAULT_WAIT = { interval: 15e3, timeout: 20 * 6e4 };
|
|
8999
9101
|
async function ship(ctx, options) {
|
|
9000
9102
|
const upstream = join10(options.workspace, UPSTREAM);
|
|
9001
9103
|
const propagateOnly = options.propagateOnly ?? false;
|
|
9002
9104
|
if (options.plx)
|
|
9003
9105
|
await preflightSelf(ctx, options.plx);
|
|
9004
9106
|
const train = await readTrain(ctx, upstream);
|
|
9005
|
-
|
|
9107
|
+
await preflightForge(ctx);
|
|
9108
|
+
if (!propagateOnly) {
|
|
9006
9109
|
await preflightRelease(ctx, train);
|
|
9110
|
+
await preflightImmutable(ctx, train);
|
|
9111
|
+
}
|
|
9007
9112
|
const next = resolveVersion(train, options.train, propagateOnly);
|
|
9008
9113
|
if (!propagateOnly)
|
|
9009
|
-
await release(ctx, train, next, options.today ?? today());
|
|
9114
|
+
await release(ctx, train, next, options.today ?? today(), { ...DEFAULT_WAIT, ...options.wait });
|
|
9010
9115
|
const summary = await propagate(ctx, options.workspace, next);
|
|
9011
9116
|
return { ...summary, released: !propagateOnly };
|
|
9012
9117
|
}
|
|
9013
|
-
async function
|
|
9118
|
+
async function preflightImmutable(ctx, train) {
|
|
9119
|
+
for (const repo of train.repos) {
|
|
9120
|
+
const newest = (await ctx.read("gh", ["api", "repos/{owner}/{repo}/releases?per_page=1", "--jq", ".[0].immutable"], { cwd: repo.path }).catch(() => "")).trim();
|
|
9121
|
+
if (newest === "false")
|
|
9122
|
+
throw new Error(mutableRelease(`${repo.name}: its newest GitHub release is not immutable`));
|
|
9123
|
+
}
|
|
9124
|
+
}
|
|
9125
|
+
var mutableRelease = (what) => `${what} \u2014 enable immutable releases on the plexus-ms organisation (Settings \u2192 General \u2192 Releases); existing releases stay as they are (never delete one: a deleted immutable release burns its number)`;
|
|
9126
|
+
async function release(ctx, train, next, today2, wait) {
|
|
9014
9127
|
ctx.say(`\u2192 train ${train.last ?? "none"} \u2192 ${next}`);
|
|
9015
9128
|
for (const repo of train.repos) {
|
|
9016
9129
|
if (repo.pending.length === 0)
|
|
9017
9130
|
ctx.say(` ${repo.name}: no changes since ${repo.latest} \u2014 tag only`);
|
|
9018
9131
|
else {
|
|
9019
9132
|
ctx.say(` ${repo.name} (since ${repo.latest ?? "the beginning"}):`);
|
|
9020
|
-
for (const line of repo.pending)
|
|
9133
|
+
for (const line of repo.pending.slice(0, PENDING_SHOWN))
|
|
9021
9134
|
ctx.say(` ${line}`);
|
|
9135
|
+
if (repo.pending.length > PENDING_SHOWN)
|
|
9136
|
+
ctx.say(` \u2026 and ${repo.pending.length - PENDING_SHOWN} more`);
|
|
9022
9137
|
}
|
|
9023
9138
|
}
|
|
9024
|
-
if (!await ctx.confirm(`tag all ${train.repos.length} repos as ${next} and push?`))
|
|
9139
|
+
if (!await ctx.confirm(`tag all ${train.repos.length} repos as ${next}, release them and push?`))
|
|
9025
9140
|
throw new Error("aborted");
|
|
9141
|
+
const [one = [], two = []] = phasesOf(train);
|
|
9026
9142
|
try {
|
|
9027
|
-
|
|
9028
|
-
await ctx
|
|
9029
|
-
|
|
9030
|
-
const tagged = await ctx.read("git", ["rev-parse", "-q", "--verify", `refs/tags/${next}`], { cwd: repo.path }).then(() => true).catch(() => false);
|
|
9031
|
-
if (tagged)
|
|
9032
|
-
ctx.say(`\u2022 ${repo.name}: already tagged ${next}`);
|
|
9033
|
-
else
|
|
9034
|
-
await ctx.apply([run("git", ["tag", "-a", next, "-m", `train ${next}`], { cwd: repo.path })]);
|
|
9035
|
-
await ctx.apply([run("git", ["push", "origin", "main", next], { cwd: repo.path })]);
|
|
9036
|
-
}
|
|
9143
|
+
await releasePhase(ctx, train, one, next, today2);
|
|
9144
|
+
await awaitPublished(ctx, next, wait);
|
|
9145
|
+
await releasePhase(ctx, train, two, next, today2);
|
|
9037
9146
|
} catch (error) {
|
|
9038
9147
|
const message = error instanceof Error ? error.message : String(error);
|
|
9039
9148
|
throw new Error(`${message}
|
|
9040
|
-
\u2717 ship stopped during the release; re-run with --train ${next} to finish it (tagged repos are skipped)`);
|
|
9149
|
+
\u2717 ship stopped during the release; re-run with --train ${next} to finish it (tagged repos and existing releases are skipped; if the registry already has ${next}, update plx first: it is the same code, built from the commit phase one tagged)`);
|
|
9041
9150
|
}
|
|
9042
9151
|
}
|
|
9043
|
-
|
|
9152
|
+
var PENDING_SHOWN = 20;
|
|
9153
|
+
async function releasePhase(ctx, train, repos2, next, today2) {
|
|
9154
|
+
ctx.say(`\u2192 phase: ${repos2.map((r) => r.name).join(", ")}`);
|
|
9155
|
+
await ctx.apply(await planBookkeeping(ctx, train, repos2, next, today2));
|
|
9156
|
+
for (const repo of repos2)
|
|
9157
|
+
await tagAndRelease(ctx, repo, next);
|
|
9158
|
+
}
|
|
9159
|
+
async function tagAndRelease(ctx, repo, next) {
|
|
9160
|
+
const tagged = await ctx.read("git", ["rev-parse", "-q", "--verify", `refs/tags/${next}`], { cwd: repo.path }).then(() => true).catch(() => false);
|
|
9161
|
+
if (tagged)
|
|
9162
|
+
ctx.say(`\u2022 ${repo.name}: already tagged ${next}`);
|
|
9163
|
+
else
|
|
9164
|
+
await ctx.apply([run("git", ["tag", "-a", next, "-m", `train ${next}`], { cwd: repo.path })]);
|
|
9165
|
+
await ctx.apply([run("git", ["push", "origin", "main", next], { cwd: repo.path })]);
|
|
9166
|
+
const released = await ctx.read("gh", ["release", "view", next], { cwd: repo.path }).then(() => true).catch(() => false);
|
|
9167
|
+
if (released) {
|
|
9168
|
+
ctx.say(`\u2022 ${repo.name}: release ${next} exists`);
|
|
9169
|
+
return;
|
|
9170
|
+
}
|
|
9171
|
+
await ctx.apply([
|
|
9172
|
+
run("gh", ["release", "create", next, "--verify-tag", "--generate-notes", "--title", next], { cwd: repo.path })
|
|
9173
|
+
]);
|
|
9174
|
+
if (ctx.dryRun)
|
|
9175
|
+
return;
|
|
9176
|
+
const immutable = (await ctx.read("gh", ["api", `repos/{owner}/{repo}/releases/tags/${next}`, "--jq", ".immutable"], {
|
|
9177
|
+
cwd: repo.path
|
|
9178
|
+
})).trim();
|
|
9179
|
+
if (immutable !== "true")
|
|
9180
|
+
throw new Error(mutableRelease(`${repo.name}: release ${next} was created mutable, and its tag can still move`));
|
|
9181
|
+
}
|
|
9182
|
+
async function awaitPublished(ctx, next, wait) {
|
|
9183
|
+
const names = TRAIN_PACKAGES.map((p) => p.name);
|
|
9184
|
+
const list2 = names.map((n) => `${n}@${next}`).join(", ");
|
|
9185
|
+
if (ctx.dryRun) {
|
|
9186
|
+
ctx.say(`\u23F3 [dry-run] would wait for ${list2} on npm (${PRIMITIVES}' release workflow publishes them)`);
|
|
9187
|
+
return;
|
|
9188
|
+
}
|
|
9189
|
+
ctx.say(`\u23F3 waiting for ${list2} on npm (${PRIMITIVES}' release workflow publishes them)`);
|
|
9190
|
+
const started = Date.now();
|
|
9191
|
+
let missing = [...names];
|
|
9192
|
+
for (; ; ) {
|
|
9193
|
+
const still = [];
|
|
9194
|
+
for (const name of missing) {
|
|
9195
|
+
const seen = (await ctx.read("npm", ["view", `${name}@${next}`, "version"]).catch(() => "")).trim();
|
|
9196
|
+
if (seen !== next)
|
|
9197
|
+
still.push(name);
|
|
9198
|
+
}
|
|
9199
|
+
missing = still;
|
|
9200
|
+
if (missing.length === 0)
|
|
9201
|
+
break;
|
|
9202
|
+
if (Date.now() - started >= wait.timeout)
|
|
9203
|
+
throw new Error(`${missing.join(", ")} not on npm at ${next} after ${Math.round(wait.timeout / 6e4)} min \u2014 check the release workflow (gh run list -R plexus-ms/${PRIMITIVES})`);
|
|
9204
|
+
await new Promise((resolve10) => setTimeout(resolve10, wait.interval));
|
|
9205
|
+
}
|
|
9206
|
+
ctx.say(` \u2713 ${list2} on npm`);
|
|
9207
|
+
}
|
|
9208
|
+
async function planBookkeeping(ctx, train, repos2, next, today2) {
|
|
9044
9209
|
const plan = [];
|
|
9045
9210
|
const touched = /* @__PURE__ */ new Set();
|
|
9046
|
-
const repo = (name) =>
|
|
9047
|
-
const r = train.repos.find((r2) => r2.name === name);
|
|
9048
|
-
if (!r)
|
|
9049
|
-
throw new Error(`${name} is not a train repo`);
|
|
9050
|
-
return r;
|
|
9051
|
-
};
|
|
9211
|
+
const repo = (name) => repos2.find((r) => r.name === name);
|
|
9052
9212
|
const edit = async (r, rel, what, transform) => {
|
|
9053
9213
|
const path3 = join10(r.path, rel);
|
|
9054
9214
|
const text = await ctx.readFile(path3).catch(() => void 0);
|
|
@@ -9061,23 +9221,36 @@ async function planBookkeeping(ctx, train, next, today2) {
|
|
|
9061
9221
|
plan.push(write(path3, edited));
|
|
9062
9222
|
touched.add(r);
|
|
9063
9223
|
};
|
|
9064
|
-
await
|
|
9065
|
-
|
|
9066
|
-
|
|
9067
|
-
|
|
9068
|
-
for (const
|
|
9069
|
-
await edit(
|
|
9224
|
+
const grep = async (r, needle, pathspecs) => (await ctx.read("git", ["grep", "-l", needle, "--", ...pathspecs], { cwd: r.path }).catch(() => "")).split("\n").filter(Boolean);
|
|
9225
|
+
const primitives = repo(PRIMITIVES);
|
|
9226
|
+
if (primitives) {
|
|
9227
|
+
await edit(primitives, "ansible/galaxy.yml", `version \u2192 ${next}`, (t) => bumpGalaxyVersion(t, next));
|
|
9228
|
+
for (const p of TRAIN_PACKAGES)
|
|
9229
|
+
await edit(primitives, `${p.dir}/package.json`, `${p.name} \u2192 ${next}`, (t) => bumpManifestVersion(t, next));
|
|
9230
|
+
}
|
|
9231
|
+
const platformPreset = repo("preset-repo-platform");
|
|
9232
|
+
if (platformPreset)
|
|
9233
|
+
await edit(platformPreset, "template/requirements.yml", `plexus.platform pin \u2192 ${next}`, (t) => bumpCollectionPin(t, next));
|
|
9234
|
+
for (const r of repos2) {
|
|
9235
|
+
for (const f of await grep(r, WORKFLOW_REF, ["*.yml", "*.yaml", "*.jinja"]))
|
|
9236
|
+
await edit(r, f, `workflow refs \u2192 @${next}`, (t) => bumpWorkflowRefs(t, next));
|
|
9237
|
+
for (const f of await grep(r, PLX_PIN, ["*.toml", "*.toml.jinja"]))
|
|
9238
|
+
await edit(r, f, `plx pin \u2192 ${next}`, (t) => bumpPlxPin(t, next));
|
|
9239
|
+
for (const f of await grep(r, `"${CONFIG_PIN}"`, ["*package.json", "*package.json.jinja"]))
|
|
9240
|
+
await edit(r, f, `${CONFIG_PIN} pin \u2192 ${next}`, (t) => bumpConfigPin(t, next));
|
|
9070
9241
|
}
|
|
9071
9242
|
const comp = repo("compendium");
|
|
9072
|
-
|
|
9073
|
-
|
|
9074
|
-
const
|
|
9075
|
-
|
|
9076
|
-
|
|
9077
|
-
|
|
9078
|
-
|
|
9079
|
-
|
|
9080
|
-
|
|
9243
|
+
if (comp) {
|
|
9244
|
+
await edit(comp, MAP_PAGE, `version \u2192 ${next}, timestamp \u2192 ${today2}`, (t) => stampStandard(t, next, today2));
|
|
9245
|
+
for (const page of await modulePages(ctx, comp.path)) {
|
|
9246
|
+
const text = await ctx.readFile(join10(comp.path, page));
|
|
9247
|
+
if (frontmatterField(text, "maturity") !== "standard")
|
|
9248
|
+
continue;
|
|
9249
|
+
const previous = comp.tag ? await ctx.read("git", ["show", `${comp.tag}:${page}`], { cwd: comp.path }).catch(() => "") : "";
|
|
9250
|
+
if (extractRequirements(text).join("\n") === extractRequirements(previous).join("\n"))
|
|
9251
|
+
continue;
|
|
9252
|
+
await edit(comp, page, `requirements changed since ${comp.latest ?? "the beginning"} \u2192 changed: ${next}`, (t) => stampChanged(t, next));
|
|
9253
|
+
}
|
|
9081
9254
|
}
|
|
9082
9255
|
for (const r of train.repos) {
|
|
9083
9256
|
if (!touched.has(r))
|
|
@@ -9091,7 +9264,7 @@ async function planBookkeeping(ctx, train, next, today2) {
|
|
|
9091
9264
|
// src/program.ts
|
|
9092
9265
|
import { createRequire } from "node:module";
|
|
9093
9266
|
|
|
9094
|
-
// ../../node_modules/.pnpm/@inquirer+core@12.0.
|
|
9267
|
+
// ../../node_modules/.pnpm/@inquirer+core@12.0.6_@types+node@26.6.5/node_modules/@inquirer/core/dist/lib/key.js
|
|
9095
9268
|
var keybindings = ["emacs", "vim"];
|
|
9096
9269
|
var keybindingLookup = new Set(keybindings);
|
|
9097
9270
|
function isKeybinding(value) {
|
|
@@ -9106,7 +9279,7 @@ function getDefaultKeybindings() {
|
|
|
9106
9279
|
var isTabKey = (key) => key.name === "tab";
|
|
9107
9280
|
var isEnterKey = (key) => key.name === "enter" || key.name === "return";
|
|
9108
9281
|
|
|
9109
|
-
// ../../node_modules/.pnpm/@inquirer+core@12.0.
|
|
9282
|
+
// ../../node_modules/.pnpm/@inquirer+core@12.0.6_@types+node@26.6.5/node_modules/@inquirer/core/dist/lib/errors.js
|
|
9110
9283
|
var AbortPromptError = class extends Error {
|
|
9111
9284
|
name = "AbortPromptError";
|
|
9112
9285
|
message = "Prompt was aborted";
|
|
@@ -9129,10 +9302,10 @@ var ValidationError = class extends Error {
|
|
|
9129
9302
|
name = "ValidationError";
|
|
9130
9303
|
};
|
|
9131
9304
|
|
|
9132
|
-
// ../../node_modules/.pnpm/@inquirer+core@12.0.
|
|
9305
|
+
// ../../node_modules/.pnpm/@inquirer+core@12.0.6_@types+node@26.6.5/node_modules/@inquirer/core/dist/lib/use-state.js
|
|
9133
9306
|
import { AsyncResource as AsyncResource2 } from "node:async_hooks";
|
|
9134
9307
|
|
|
9135
|
-
// ../../node_modules/.pnpm/@inquirer+core@12.0.
|
|
9308
|
+
// ../../node_modules/.pnpm/@inquirer+core@12.0.6_@types+node@26.6.5/node_modules/@inquirer/core/dist/lib/hook-engine.js
|
|
9136
9309
|
import { AsyncLocalStorage, AsyncResource } from "node:async_hooks";
|
|
9137
9310
|
var hookStorage = new AsyncLocalStorage();
|
|
9138
9311
|
function createStore(rl) {
|
|
@@ -9236,7 +9409,7 @@ var effectScheduler = {
|
|
|
9236
9409
|
}
|
|
9237
9410
|
};
|
|
9238
9411
|
|
|
9239
|
-
// ../../node_modules/.pnpm/@inquirer+core@12.0.
|
|
9412
|
+
// ../../node_modules/.pnpm/@inquirer+core@12.0.6_@types+node@26.6.5/node_modules/@inquirer/core/dist/lib/use-state.js
|
|
9240
9413
|
function isFactory(value) {
|
|
9241
9414
|
return typeof value === "function";
|
|
9242
9415
|
}
|
|
@@ -9262,7 +9435,7 @@ function useState(defaultValue) {
|
|
|
9262
9435
|
});
|
|
9263
9436
|
}
|
|
9264
9437
|
|
|
9265
|
-
// ../../node_modules/.pnpm/@inquirer+core@12.0.
|
|
9438
|
+
// ../../node_modules/.pnpm/@inquirer+core@12.0.6_@types+node@26.6.5/node_modules/@inquirer/core/dist/lib/use-effect.js
|
|
9266
9439
|
function useEffect(cb, depArray) {
|
|
9267
9440
|
withPointer((pointer) => {
|
|
9268
9441
|
const oldDeps = pointer.get();
|
|
@@ -9274,10 +9447,10 @@ function useEffect(cb, depArray) {
|
|
|
9274
9447
|
});
|
|
9275
9448
|
}
|
|
9276
9449
|
|
|
9277
|
-
// ../../node_modules/.pnpm/@inquirer+core@12.0.
|
|
9450
|
+
// ../../node_modules/.pnpm/@inquirer+core@12.0.6_@types+node@26.6.5/node_modules/@inquirer/core/dist/lib/theme.js
|
|
9278
9451
|
import { styleText } from "node:util";
|
|
9279
9452
|
|
|
9280
|
-
// ../../node_modules/.pnpm/@inquirer+figures@2.0.
|
|
9453
|
+
// ../../node_modules/.pnpm/@inquirer+figures@2.0.10/node_modules/@inquirer/figures/dist/index.js
|
|
9281
9454
|
import process2 from "node:process";
|
|
9282
9455
|
function isUnicodeSupported() {
|
|
9283
9456
|
if (!process2.platform.startsWith("win")) {
|
|
@@ -9570,7 +9743,7 @@ var figures = shouldUseMain ? mainSymbols : fallbackSymbols;
|
|
|
9570
9743
|
var dist_default = figures;
|
|
9571
9744
|
var replacements = Object.entries(specialMainSymbols);
|
|
9572
9745
|
|
|
9573
|
-
// ../../node_modules/.pnpm/@inquirer+core@12.0.
|
|
9746
|
+
// ../../node_modules/.pnpm/@inquirer+core@12.0.6_@types+node@26.6.5/node_modules/@inquirer/core/dist/lib/theme.js
|
|
9574
9747
|
var defaultTheme = {
|
|
9575
9748
|
prefix: {
|
|
9576
9749
|
idle: styleText("blue", "?"),
|
|
@@ -9598,7 +9771,7 @@ function getDefaultTheme() {
|
|
|
9598
9771
|
};
|
|
9599
9772
|
}
|
|
9600
9773
|
|
|
9601
|
-
// ../../node_modules/.pnpm/@inquirer+core@12.0.
|
|
9774
|
+
// ../../node_modules/.pnpm/@inquirer+core@12.0.6_@types+node@26.6.5/node_modules/@inquirer/core/dist/lib/make-theme.js
|
|
9602
9775
|
function isPlainObject(value) {
|
|
9603
9776
|
if (typeof value !== "object" || value === null)
|
|
9604
9777
|
return false;
|
|
@@ -9626,7 +9799,7 @@ function makeTheme(...themes) {
|
|
|
9626
9799
|
return deepMerge(...themesToMerge);
|
|
9627
9800
|
}
|
|
9628
9801
|
|
|
9629
|
-
// ../../node_modules/.pnpm/@inquirer+core@12.0.
|
|
9802
|
+
// ../../node_modules/.pnpm/@inquirer+core@12.0.6_@types+node@26.6.5/node_modules/@inquirer/core/dist/lib/use-prefix.js
|
|
9630
9803
|
function usePrefix({ status = "idle", theme }) {
|
|
9631
9804
|
const [showLoader, setShowLoader] = useState(false);
|
|
9632
9805
|
const [tick, setTick] = useState(0);
|
|
@@ -9657,12 +9830,12 @@ function usePrefix({ status = "idle", theme }) {
|
|
|
9657
9830
|
return typeof prefix === "string" ? prefix : prefix[iconName] ?? prefix["idle"];
|
|
9658
9831
|
}
|
|
9659
9832
|
|
|
9660
|
-
// ../../node_modules/.pnpm/@inquirer+core@12.0.
|
|
9833
|
+
// ../../node_modules/.pnpm/@inquirer+core@12.0.6_@types+node@26.6.5/node_modules/@inquirer/core/dist/lib/use-ref.js
|
|
9661
9834
|
function useRef(val) {
|
|
9662
9835
|
return useState({ current: val })[0];
|
|
9663
9836
|
}
|
|
9664
9837
|
|
|
9665
|
-
// ../../node_modules/.pnpm/@inquirer+core@12.0.
|
|
9838
|
+
// ../../node_modules/.pnpm/@inquirer+core@12.0.6_@types+node@26.6.5/node_modules/@inquirer/core/dist/lib/use-keypress.js
|
|
9666
9839
|
function useKeypress(userHandler) {
|
|
9667
9840
|
const signal = useRef(userHandler);
|
|
9668
9841
|
signal.current = userHandler;
|
|
@@ -9681,7 +9854,7 @@ function useKeypress(userHandler) {
|
|
|
9681
9854
|
}, []);
|
|
9682
9855
|
}
|
|
9683
9856
|
|
|
9684
|
-
// ../../node_modules/.pnpm/@inquirer+core@12.0.
|
|
9857
|
+
// ../../node_modules/.pnpm/@inquirer+core@12.0.6_@types+node@26.6.5/node_modules/@inquirer/core/dist/lib/utils.js
|
|
9685
9858
|
var import_cli_width = __toESM(require_cli_width(), 1);
|
|
9686
9859
|
|
|
9687
9860
|
// ../../node_modules/.pnpm/fast-string-truncated-width@3.0.3/node_modules/fast-string-truncated-width/dist/utils.js
|
|
@@ -10020,7 +10193,7 @@ function wrapAnsi(string, columns, options) {
|
|
|
10020
10193
|
return String(string).normalize().split(CRLF_OR_LF).map((line) => exec(line, columns, options)).join("\n");
|
|
10021
10194
|
}
|
|
10022
10195
|
|
|
10023
|
-
// ../../node_modules/.pnpm/@inquirer+core@12.0.
|
|
10196
|
+
// ../../node_modules/.pnpm/@inquirer+core@12.0.6_@types+node@26.6.5/node_modules/@inquirer/core/dist/lib/utils.js
|
|
10024
10197
|
function breakLines(content, width) {
|
|
10025
10198
|
return content.split("\n").flatMap((line) => wrapAnsi(line, width, { trim: false, wordWrap: false }).split("\n").map((str) => str.trimEnd())).join("\n");
|
|
10026
10199
|
}
|
|
@@ -10028,11 +10201,11 @@ function readlineWidth() {
|
|
|
10028
10201
|
return (0, import_cli_width.default)({ defaultWidth: 80, output: readline().output });
|
|
10029
10202
|
}
|
|
10030
10203
|
|
|
10031
|
-
// ../../node_modules/.pnpm/@inquirer+core@12.0.
|
|
10204
|
+
// ../../node_modules/.pnpm/@inquirer+core@12.0.6_@types+node@26.6.5/node_modules/@inquirer/core/dist/lib/create-prompt.js
|
|
10032
10205
|
import * as readline2 from "node:readline";
|
|
10033
10206
|
import { AsyncResource as AsyncResource3 } from "node:async_hooks";
|
|
10034
10207
|
|
|
10035
|
-
// ../../node_modules/.pnpm/@inquirer+type@4.2.
|
|
10208
|
+
// ../../node_modules/.pnpm/@inquirer+type@4.2.1_@types+node@26.6.5/node_modules/@inquirer/type/dist/utils.js
|
|
10036
10209
|
function withResolver() {
|
|
10037
10210
|
let resolve10;
|
|
10038
10211
|
let reject;
|
|
@@ -10043,7 +10216,7 @@ function withResolver() {
|
|
|
10043
10216
|
return { promise, resolve: resolve10, reject };
|
|
10044
10217
|
}
|
|
10045
10218
|
|
|
10046
|
-
// ../../node_modules/.pnpm/@inquirer+core@12.0.
|
|
10219
|
+
// ../../node_modules/.pnpm/@inquirer+core@12.0.6_@types+node@26.6.5/node_modules/@inquirer/core/dist/lib/create-prompt.js
|
|
10047
10220
|
var import_mute_stream = __toESM(require_lib(), 1);
|
|
10048
10221
|
|
|
10049
10222
|
// ../../node_modules/.pnpm/signal-exit@4.1.0/node_modules/signal-exit/dist/mjs/signals.js
|
|
@@ -10297,10 +10470,10 @@ var {
|
|
|
10297
10470
|
unload
|
|
10298
10471
|
} = signalExitWrap(processOk(process3) ? new SignalExit(process3) : new SignalExitFallback());
|
|
10299
10472
|
|
|
10300
|
-
// ../../node_modules/.pnpm/@inquirer+core@12.0.
|
|
10473
|
+
// ../../node_modules/.pnpm/@inquirer+core@12.0.6_@types+node@26.6.5/node_modules/@inquirer/core/dist/lib/screen-manager.js
|
|
10301
10474
|
import { stripVTControlCharacters } from "node:util";
|
|
10302
10475
|
|
|
10303
|
-
// ../../node_modules/.pnpm/@inquirer+ansi@2.0.
|
|
10476
|
+
// ../../node_modules/.pnpm/@inquirer+ansi@2.0.10/node_modules/@inquirer/ansi/dist/index.js
|
|
10304
10477
|
var ESC2 = "\x1B[";
|
|
10305
10478
|
var cursorLeft = ESC2 + "G";
|
|
10306
10479
|
var cursorHide = ESC2 + "?25l";
|
|
@@ -10316,7 +10489,7 @@ var cursorTo = (x, y) => {
|
|
|
10316
10489
|
var eraseLine = ESC2 + "2K";
|
|
10317
10490
|
var eraseLines = (lines) => lines > 0 ? (eraseLine + cursorUp(1)).repeat(lines - 1) + eraseLine + cursorLeft : "";
|
|
10318
10491
|
|
|
10319
|
-
// ../../node_modules/.pnpm/@inquirer+core@12.0.
|
|
10492
|
+
// ../../node_modules/.pnpm/@inquirer+core@12.0.6_@types+node@26.6.5/node_modules/@inquirer/core/dist/lib/screen-manager.js
|
|
10320
10493
|
var height = (content) => content.split("\n").length;
|
|
10321
10494
|
var lastLine = (content) => content.split("\n").pop() ?? "";
|
|
10322
10495
|
var ScreenManager = class {
|
|
@@ -10377,7 +10550,7 @@ var ScreenManager = class {
|
|
|
10377
10550
|
}
|
|
10378
10551
|
};
|
|
10379
10552
|
|
|
10380
|
-
// ../../node_modules/.pnpm/@inquirer+core@12.0.
|
|
10553
|
+
// ../../node_modules/.pnpm/@inquirer+core@12.0.6_@types+node@26.6.5/node_modules/@inquirer/core/dist/lib/create-prompt.js
|
|
10381
10554
|
import path from "node:path";
|
|
10382
10555
|
var nativeSetImmediate = globalThis.setImmediate;
|
|
10383
10556
|
var nativeClearImmediate = globalThis.clearImmediate;
|
|
@@ -10485,7 +10658,7 @@ function createPrompt(view) {
|
|
|
10485
10658
|
}
|
|
10486
10659
|
});
|
|
10487
10660
|
};
|
|
10488
|
-
if ("readableFlowing" in input) {
|
|
10661
|
+
if ("readableFlowing" in input && input.isTTY) {
|
|
10489
10662
|
const immediate = nativeSetImmediate(startCycle);
|
|
10490
10663
|
cleanups.add(() => nativeClearImmediate(immediate));
|
|
10491
10664
|
} else {
|
|
@@ -10497,7 +10670,7 @@ function createPrompt(view) {
|
|
|
10497
10670
|
return prompt;
|
|
10498
10671
|
}
|
|
10499
10672
|
|
|
10500
|
-
// ../../node_modules/.pnpm/@inquirer+confirm@6.3.
|
|
10673
|
+
// ../../node_modules/.pnpm/@inquirer+confirm@6.3.5_@types+node@26.6.5/node_modules/@inquirer/confirm/dist/index.js
|
|
10501
10674
|
import { styleText as styleText2 } from "node:util";
|
|
10502
10675
|
var confirmTheme = {
|
|
10503
10676
|
keywords: {
|
|
@@ -14119,7 +14292,9 @@ import { resolve as resolve8 } from "node:path";
|
|
|
14119
14292
|
// src/commands/ship.ts
|
|
14120
14293
|
import { resolve as resolve7 } from "node:path";
|
|
14121
14294
|
function register7(program2) {
|
|
14122
|
-
program2.command("ship").description(
|
|
14295
|
+
program2.command("ship").description(
|
|
14296
|
+
"release the train: tag and release every train repo identically, then open a pull request per consumer"
|
|
14297
|
+
).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) => {
|
|
14123
14298
|
const ctx = contextOf2(command);
|
|
14124
14299
|
const result = await ship(ctx, { workspace: resolve7(dir), train: opts.train, plx: version });
|
|
14125
14300
|
ctx.result(result, (r) => renderSummary(r, `plx -y ship --train ${r.train} ${dir}`));
|
|
@@ -14132,12 +14307,13 @@ function renderSummary(s, realCommand) {
|
|
|
14132
14307
|
for (const p of s.conflicted) lines.push(` \u2717 conflicts: ${p}`);
|
|
14133
14308
|
for (const p of s.failed) lines.push(` \u2717 failed: ${p}`);
|
|
14134
14309
|
for (const { path: path3, reason } of s.skipped) lines.push(` \u26A0 skipped: ${path3} (${reason})`);
|
|
14310
|
+
for (const url of s.pulls) lines.push(` \u2192 pull: ${url}`);
|
|
14135
14311
|
const clean = isClean(s);
|
|
14136
14312
|
if (s.preview) {
|
|
14137
14313
|
lines.push(" (preview only \u2014 nothing was changed)");
|
|
14138
14314
|
if (clean) lines.push(`\u2713 dry run clean \u2014 run it for real: ${realCommand}`);
|
|
14139
14315
|
} else if (clean) {
|
|
14140
|
-
lines.push("\u2713 done \u2014 review
|
|
14316
|
+
lines.push("\u2713 done \u2014 review and merge the pull requests");
|
|
14141
14317
|
}
|
|
14142
14318
|
if (!clean) lines.push("\u2717 needs attention \u2014 see above; fix the consumer, then re-run propagate");
|
|
14143
14319
|
return lines.join("\n");
|
|
@@ -14145,7 +14321,7 @@ function renderSummary(s, realCommand) {
|
|
|
14145
14321
|
|
|
14146
14322
|
// src/commands/propagate.ts
|
|
14147
14323
|
function register8(program2) {
|
|
14148
|
-
program2.command("propagate").description("copier-update every consumer of the presets to the current train,
|
|
14324
|
+
program2.command("propagate").description("copier-update every consumer of the presets to the current train, as one pull request per consumer").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) => {
|
|
14149
14325
|
const ctx = contextOf2(command);
|
|
14150
14326
|
const result = await ship(ctx, { workspace: resolve8(dir), train: opts.train, propagateOnly: true, plx: version });
|
|
14151
14327
|
ctx.result(result, (r) => renderSummary(r, `plx -y propagate --train ${r.train} ${dir}`));
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@plexus-ms/cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.100.0-rc.3",
|
|
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",
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
],
|
|
13
13
|
"repository": {
|
|
14
14
|
"type": "git",
|
|
15
|
-
"url": "git+https://github.com/plexus-ms/
|
|
15
|
+
"url": "git+https://github.com/plexus-ms/primitives.git",
|
|
16
16
|
"directory": "packages/cli"
|
|
17
17
|
},
|
|
18
18
|
"publishConfig": {
|
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
},
|
|
25
25
|
"dependencies": {
|
|
26
26
|
"@inquirer/prompts": "^8.7.4",
|
|
27
|
-
"@plexus-ms/lib": "0.
|
|
27
|
+
"@plexus-ms/lib": "0.100.0-rc.3",
|
|
28
28
|
"commander": "^15.0.0"
|
|
29
29
|
},
|
|
30
30
|
"devDependencies": {
|