@plexus-ms/cli-ci 0.119.0 → 0.121.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.
Files changed (2) hide show
  1. package/dist/plx-ci.js +85 -70
  2. package/package.json +3 -3
package/dist/plx-ci.js CHANGED
@@ -5358,10 +5358,10 @@ var require_cst_scalar = __commonJS({
5358
5358
  case "|":
5359
5359
  case ">": {
5360
5360
  const he = source.indexOf("\n");
5361
- const head = source.substring(0, he);
5361
+ const head2 = source.substring(0, he);
5362
5362
  const body2 = source.substring(he + 1) + "\n";
5363
5363
  const props = [
5364
- { type: "block-scalar-header", offset, indent: indent2, source: head }
5364
+ { type: "block-scalar-header", offset, indent: indent2, source: head2 }
5365
5365
  ];
5366
5366
  if (!addEndtoBlockProps(props, end))
5367
5367
  props.push({ type: "newline", offset: -1, indent: indent2, source: "\n" });
@@ -5421,19 +5421,19 @@ var require_cst_scalar = __commonJS({
5421
5421
  }
5422
5422
  function setBlockScalarValue(token, source) {
5423
5423
  const he = source.indexOf("\n");
5424
- const head = source.substring(0, he);
5424
+ const head2 = source.substring(0, he);
5425
5425
  const body2 = source.substring(he + 1) + "\n";
5426
5426
  if (token.type === "block-scalar") {
5427
5427
  const header = token.props[0];
5428
5428
  if (header.type !== "block-scalar-header")
5429
5429
  throw new Error("Invalid block scalar header");
5430
- header.source = head;
5430
+ header.source = head2;
5431
5431
  token.source = body2;
5432
5432
  } else {
5433
5433
  const { offset } = token;
5434
5434
  const indent2 = "indent" in token ? token.indent : -1;
5435
5435
  const props = [
5436
- { type: "block-scalar-header", offset, indent: indent2, source: head }
5436
+ { type: "block-scalar-header", offset, indent: indent2, source: head2 }
5437
5437
  ];
5438
5438
  if (!addEndtoBlockProps(props, "end" in token ? token.end : void 0))
5439
5439
  props.push({ type: "newline", offset: -1, indent: indent2, source: "\n" });
@@ -7368,6 +7368,34 @@ var require_dist = __commonJS({
7368
7368
  }
7369
7369
  });
7370
7370
 
7371
+ // ../lib/dist/lints.js
7372
+ var MONTH = "Jan(?:uary)?|Feb(?:ruary)?|Mar(?:ch)?|Apr(?:il)?|May|June?|July?|Aug(?:ust)?|Sep(?:t(?:ember)?)?|Oct(?:ober)?|Nov(?:ember)?|Dec(?:ember)?";
7373
+ var YEAR = "(?:19|20)\\d{2}";
7374
+ var DATE_OR_VERSION = new RegExp([
7375
+ // 2026-11-04, 2026-07, 2026-11-04T10:00Z
7376
+ `(?<![\\w-])${YEAR}-(?:0[1-9]|1[0-2])(?:-(?:0[1-9]|[12]\\d|3[01])(?:T\\d{2}:\\d{2}(?::\\d{2}(?:\\.\\d+)?)?(?:Z|[+-]\\d{2}:?\\d{2})?)?)?(?![\\w-])`,
7377
+ // November 2026, Nov. 4, 2026
7378
+ `\\b(?:${MONTH})\\.?\\s+(?:\\d{1,2}(?:st|nd|rd|th)?,?\\s+)?${YEAR}\\b`,
7379
+ // in 2026, since 2025, Q3 2026
7380
+ `\\b(?:[Ii]n|[Ss]ince|[Uu]ntil|[Tt]ill|[Aa]s of|[Bb]efore|[Aa]fter|[Dd]uring|[Ee]arly|[Mm]id|[Ll]ate|Q[1-4])\\s+${YEAR}\\b(?![.,]?\\d)`,
7381
+ // 0.111.0, 1.2.3-rc.1; not the dotted parts of an IP address, not a section number
7382
+ "(?<![\\w.\xA7]|\xA7\\s*)(?!1\\.0\\.0(?![\\w-]|\\.\\d))\\d+\\.\\d+\\.\\d+(?:-[0-9A-Za-z.]+)?(?!\\.?\\d)",
7383
+ // v24, v1.48
7384
+ "(?<![\\w./-])v\\d+(?:\\.\\d+)*\\b",
7385
+ // pnpm@12, hk@1.48 (three parts are caught above)
7386
+ "(?<=@)\\d+(?:\\.\\d+)?\\b(?!\\.\\d)"
7387
+ ].join("|"), "g");
7388
+ var CODE = "PLX(?:-[A-Z][A-Za-z]+)?(?![A-Za-z])";
7389
+ var NUMBER = "\\d+(?:\\.\\d+)*";
7390
+ var NUMBERS = `${NUMBER}(?:[ \\t\\u00a0]*(?:,|and|or|&|\u2013|-|to)[ \\t\\u00a0]*${NUMBER})*`;
7391
+ var GAP = "(?:[ \\t\\u00a0]+|[ \\t]*\\r?\\n[ \\t]*(?:#+|//+|\\*|>)?[ \\t]*)";
7392
+ var SIGN = `(?<!\xA7)\xA7\xA7?[ \\t\\u00a0]*`;
7393
+ var NAME_LIKE = "PLX-[A-Z][A-Za-z]+(?:/[\\w-]+)+";
7394
+ var FORWARD = new RegExp(`${SIGN}(${NUMBERS})${GAP}(${CODE})`, "g");
7395
+ var REVERSE = new RegExp(`(?<![\\w-])(${CODE})[ \\t\\u00a0]*,?[ \\t\\u00a0]*${SIGN}(${NUMBERS})`, "g");
7396
+ var BARE = new RegExp(`${SIGN}(${NUMBERS})`, "g");
7397
+ var NAME_CITATION = new RegExp(`(?<![\\w/-])${NAME_LIKE}(?![\\w/])`, "g");
7398
+
7371
7399
  // ../lib/dist/marker.js
7372
7400
  var import_yaml = __toESM(require_dist(), 1);
7373
7401
 
@@ -7389,6 +7417,15 @@ ${stderr.trimEnd()}` : ""}`);
7389
7417
  this.stderr = stderr;
7390
7418
  }
7391
7419
  };
7420
+ async function orAbsent(read, absent = () => true) {
7421
+ try {
7422
+ return await read;
7423
+ } catch (error) {
7424
+ if (error instanceof ExecError && absent(error))
7425
+ return void 0;
7426
+ throw error;
7427
+ }
7428
+ }
7392
7429
  var isInteractive = () => process.stdin.isTTY === true && process.stderr.isTTY === true;
7393
7430
  function realIo(prompt) {
7394
7431
  return {
@@ -7462,20 +7499,20 @@ function body(step) {
7462
7499
  }
7463
7500
  }
7464
7501
 
7465
- // ../lib/dist/train.js
7502
+ // ../lib/dist/version.js
7466
7503
  var COMPENDIUM = "compendium";
7467
- var TRAIN_REPOS = [
7468
- "primitives",
7469
- "preset-repo-turbo",
7470
- "preset-app-nextjs",
7471
- "preset-repo-operations",
7504
+ var VERSIONED_REPOS = [
7505
+ "tooling",
7506
+ "template-repo-turbo",
7507
+ "template-app-nextjs",
7508
+ "template-repo-operations",
7472
7509
  COMPENDIUM
7473
7510
  ];
7474
7511
  var UsageError = class extends Error {
7475
7512
  };
7476
7513
 
7477
7514
  // ../lib/dist/consumers.js
7478
- var PRESETS = TRAIN_REPOS.filter((r) => r.startsWith("preset-"));
7515
+ var TEMPLATES = VERSIONED_REPOS.filter((r) => r.startsWith("template-"));
7479
7516
 
7480
7517
  // ../lib/dist/context.js
7481
7518
  var Context = class {
@@ -7684,7 +7721,7 @@ async function readDeployTargets(ctx, inventory) {
7684
7721
  var DAY = 24 * 60 * 60 * 1e3;
7685
7722
 
7686
7723
  // ../lib/dist/update.js
7687
- var TRAINS = `plexus-ms/${COMPENDIUM}`;
7724
+ var RELEASES_REPO = `plexus-ms/${COMPENDIUM}`;
7688
7725
 
7689
7726
  // src/program.ts
7690
7727
  import { createRequire } from "node:module";
@@ -11378,66 +11415,50 @@ async function startSidecars(ctx, storage, owner, now = /* @__PURE__ */ new Date
11378
11415
  );
11379
11416
  return { current: buckets.current, previous: buckets.previous, previousAnswers };
11380
11417
  }
11381
- async function manifestStatus(ctx, port, app, tag) {
11418
+ var curlNotFound = (error) => error.code === 22 && /\b404\b/.test(error.stderr);
11419
+ var craneNotFound = (error) => /MANIFEST_UNKNOWN|NAME_UNKNOWN|\b404\b/.test(error.stderr);
11420
+ async function lookUp(ctx, ref, command, args, absent) {
11382
11421
  try {
11383
- return (await ctx.read("curl", [
11384
- "-s",
11385
- "-o",
11386
- "/dev/null",
11387
- "-w",
11388
- "%{http_code}",
11389
- "-I",
11390
- "-H",
11391
- `Accept: ${ACCEPT}`,
11392
- `http://127.0.0.1:${port}/v2/${app}/manifests/${tag}`
11393
- ])).trim();
11394
- } catch {
11395
- return "000";
11422
+ return await orAbsent(ctx.read(command, args), absent);
11423
+ } catch (error) {
11424
+ const why = error instanceof ExecError ? `could not look up ${ref}: ${error.message}` : `${command} could not run to look up ${ref}; is it installed in this job?`;
11425
+ if (!ctx.dryRun) throw new Error(why, { cause: error });
11426
+ ctx.say(`[dry-run] ${why.split("\n")[0]}; taken for absent`);
11427
+ return void 0;
11396
11428
  }
11397
11429
  }
11430
+ var manifestUrl = (port, app, tag) => `http://127.0.0.1:${port}/v2/${app}/manifests/${tag}`;
11431
+ var head = (ctx, port, app, tag, absent = curlNotFound) => lookUp(
11432
+ ctx,
11433
+ `localhost:${port}/${app}:${tag}`,
11434
+ "curl",
11435
+ ["-fsS", "-I", "-H", `Accept: ${ACCEPT}`, manifestUrl(port, app, tag)],
11436
+ absent
11437
+ );
11398
11438
  async function tagExists(ctx, app, tag) {
11399
- for (const port of [CURRENT_PORT, PREVIOUS_PORT]) {
11400
- if (await manifestStatus(ctx, port, app, tag) === "200") return port;
11401
- }
11439
+ if (await head(ctx, CURRENT_PORT, app, tag) !== void 0) return CURRENT_PORT;
11440
+ if (await head(ctx, PREVIOUS_PORT, app, tag, () => true) !== void 0) return PREVIOUS_PORT;
11402
11441
  return void 0;
11403
11442
  }
11404
11443
  async function digest(ctx, app, tag, port = CURRENT_PORT) {
11405
- try {
11406
- const head = await ctx.read("curl", [
11407
- "-fsS",
11408
- "-I",
11409
- "-H",
11410
- `Accept: ${ACCEPT}`,
11411
- `http://127.0.0.1:${port}/v2/${app}/manifests/${tag}`
11412
- ]);
11413
- return head.match(/^docker-content-digest:\s*(\S+)/im)?.[1];
11414
- } catch {
11415
- return void 0;
11416
- }
11444
+ return (await head(ctx, port, app, tag))?.match(/^docker-content-digest:\s*(\S+)/im)?.[1];
11417
11445
  }
11418
11446
  async function layers(ctx, app, tag, port = CURRENT_PORT) {
11419
- try {
11420
- const body2 = await ctx.read("curl", [
11421
- "-fsS",
11422
- "-H",
11423
- `Accept: ${ACCEPT}`,
11424
- `http://127.0.0.1:${port}/v2/${app}/manifests/${tag}`
11425
- ]);
11426
- const data = JSON.parse(body2);
11427
- return (data.layers ?? []).map((l) => ({ digest: l.digest, size: l.size }));
11428
- } catch {
11429
- return void 0;
11430
- }
11447
+ const manifest = await lookUp(
11448
+ ctx,
11449
+ `localhost:${port}/${app}:${tag}`,
11450
+ "curl",
11451
+ ["-fsS", "-H", `Accept: ${ACCEPT}`, manifestUrl(port, app, tag)],
11452
+ curlNotFound
11453
+ );
11454
+ return manifest === void 0 ? void 0 : layersIn(manifest);
11431
11455
  }
11456
+ var layersIn = (manifest) => (JSON.parse(manifest).layers ?? []).map((l) => ({ digest: l.digest, size: l.size }));
11432
11457
  function candidateRef(registry, app, tag) {
11433
11458
  return registry.kind === "own" ? `localhost:${CURRENT_PORT}/${app}:${tag}` : `${imageName(registry.prefix, app)}:${tag}`;
11434
11459
  }
11435
11460
  async function craneDigest(ctx, ref) {
11436
- try {
11437
- return (await ctx.read("crane", ["digest", ref])).trim() || void 0;
11438
- } catch {
11439
- return void 0;
11440
- }
11461
+ return (await lookUp(ctx, ref, "crane", ["digest", ref], craneNotFound))?.trim() || void 0;
11441
11462
  }
11442
11463
  async function findTag(ctx, registry, app, tag) {
11443
11464
  if (registry.kind === "own") {
@@ -11452,12 +11473,9 @@ function digestOf(ctx, registry, app, tag) {
11452
11473
  }
11453
11474
  async function layersOf(ctx, registry, app, tag) {
11454
11475
  if (registry.kind === "own") return layers(ctx, app, tag);
11455
- try {
11456
- const data = JSON.parse(await ctx.read("crane", ["manifest", candidateRef(registry, app, tag)]));
11457
- return (data.layers ?? []).map((l) => ({ digest: l.digest, size: l.size }));
11458
- } catch {
11459
- return void 0;
11460
- }
11476
+ const ref = candidateRef(registry, app, tag);
11477
+ const manifest = await lookUp(ctx, ref, "crane", ["manifest", ref], craneNotFound);
11478
+ return manifest === void 0 ? void 0 : layersIn(manifest);
11461
11479
  }
11462
11480
  async function loggedIn(ctx, host, env = process.env) {
11463
11481
  const file = `${env.DOCKER_CONFIG || `${env.HOME}/.docker`}/config.json`;
@@ -12729,11 +12747,8 @@ function packageOf(prefix, app) {
12729
12747
  async function prune(ctx, packages, names, now = /* @__PURE__ */ new Date()) {
12730
12748
  const pruned = [];
12731
12749
  for (const name of names) {
12732
- let versions;
12733
- try {
12734
- versions = await packages.versions(name);
12735
- } catch (error) {
12736
- if (!(error instanceof ExecError)) throw error;
12750
+ const versions = await orAbsent(packages.versions(name), curlNotFound);
12751
+ if (versions === void 0) {
12737
12752
  ctx.say(`rotate: no package ${name} in ghcr.io/${packages.org}`);
12738
12753
  continue;
12739
12754
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@plexus-ms/cli-ci",
3
- "version": "0.119.0",
3
+ "version": "0.121.0",
4
4
  "description": "plx-ci, the CI verbs of Plexus: throwaway runners on a cloud, a registry on object storage, reproducible image builds, and their teardown",
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/primitives.git",
15
+ "url": "git+https://github.com/plexus-ms/tooling.git",
16
16
  "directory": "packages/cli-ci"
17
17
  },
18
18
  "publishConfig": {
@@ -23,7 +23,7 @@
23
23
  "node": ">=24.22.1"
24
24
  },
25
25
  "dependencies": {
26
- "@plexus-ms/lib": "0.119.0",
26
+ "@plexus-ms/lib": "0.121.0",
27
27
  "commander": "^15.0.0",
28
28
  "yaml": "^2.9.1"
29
29
  },