@mutmutco/cli 4.5.125 → 4.5.127

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/main.cjs +39 -16
  2. package/package.json +1 -1
package/dist/main.cjs CHANGED
@@ -8766,8 +8766,9 @@ async function retireProject(slug, deps) {
8766
8766
  async function setDeployCoords(slug, payload, deps) {
8767
8767
  return postJson(`/projects/${encodeURIComponent(slug)}/deploy`, payload, deps);
8768
8768
  }
8769
- async function retireDeployCoords(slug, stage, deps) {
8770
- return postJson(`/projects/${encodeURIComponent(slug)}/deploy/${encodeURIComponent(stage)}`, {}, deps, "DELETE", { noRetry: true });
8769
+ async function retireDeployCoords(slug, stage, deps, decommissioned = false) {
8770
+ const q = decommissioned ? "?decommissioned=1" : "";
8771
+ return postJson(`/projects/${encodeURIComponent(slug)}/deploy/${encodeURIComponent(stage)}${q}`, {}, deps, "DELETE", { noRetry: true });
8771
8772
  }
8772
8773
  async function postSchedulesLift(repo, schedules, deps) {
8773
8774
  const res = await postJson("/schedules/lift", { repo, schedules }, deps);
@@ -18243,10 +18244,10 @@ var rollout_plan_default = {
18243
18244
  note: "The v4.0.0 stamp happens at cut time (D6e #4463); until then the candidate is the origin/development head artifacts (built cli/dist + npm pack), identity proven by dist content hash (D6a)."
18244
18245
  },
18245
18246
  baseline: {
18246
- version: "4.5.125",
18247
- tag: "v4.5.125",
18248
- commit: "00accba6d8e0",
18249
- npm: "@mutmutco/cli@4.5.125"
18247
+ version: "4.5.127",
18248
+ tag: "v4.5.127",
18249
+ commit: "1a7a42121998",
18250
+ npm: "@mutmutco/cli@4.5.127"
18250
18251
  },
18251
18252
  exitCriterion: "fleet-n-of-n",
18252
18253
  hubOnlyShortcut: "forbidden",
@@ -18263,14 +18264,14 @@ var rollout_plan_default = {
18263
18264
  repo: "mutmutco/mmi-hub",
18264
18265
  role: "canary",
18265
18266
  schedule: "train",
18266
- v3Target: "v4.5.125"
18267
+ v3Target: "v4.5.127"
18267
18268
  }
18268
18269
  ],
18269
18270
  rollbackTrigger: "Any red inside the post-contract soak window: `devops train gate` FAIL attributable to the v4 doors, Hub endpoint health probe failure, a pre-v4 client admitted instead of receiving actionable HTTP 426, or npm consumer install/doctor failure on the v4-only dist.",
18270
18271
  rollback: {
18271
18272
  independent: true,
18272
- mechanism: "npm dist-tag latest -> 4.5.125 and redeploy the Hub Lambda from tag v4.5.125 (00accba6d8e0); installed clients repair via `mmi-cli doctor`. No other cohort is touched.",
18273
- v3Target: "v4.5.125 (@mutmutco/cli@4.5.125, tag commit 00accba6d8e0 \u2014 last known-good release carrying the repo-index v4-only contract)"
18273
+ mechanism: "npm dist-tag latest -> 4.5.127 and redeploy the Hub Lambda from tag v4.5.127 (1a7a42121998); installed clients repair via `mmi-cli doctor`. No other cohort is touched.",
18274
+ v3Target: "v4.5.127 (@mutmutco/cli@4.5.127, tag commit 1a7a42121998 \u2014 last known-good release carrying the repo-index v4-only contract)"
18274
18275
  }
18275
18276
  },
18276
18277
  {
@@ -32313,7 +32314,7 @@ function parseTenantTasksVar(raw) {
32313
32314
  if (typeof task.service !== "string" || !serviceRe.test(task.service)) throw new Error(`org project set: tenantTasks.${name}.service has an unsafe shape`);
32314
32315
  if (!Array.isArray(task.command) || task.command.length < 1 || task.command.length > 32 || task.command.some((arg) => typeof arg !== "string" || arg.length < 1 || arg.length > 256 || /[\u0000\r\n]/.test(arg))) throw new Error(`org project set: tenantTasks.${name}.command must be 1-32 bounded argv strings`);
32315
32316
  if (!Array.isArray(task.stages) || task.stages.length < 1 || task.stages.length > 3 || task.stages.some((stage) => typeof stage !== "string" || !validStages.has(stage)) || new Set(task.stages).size !== task.stages.length) throw new Error(`org project set: tenantTasks.${name}.stages must be unique dev/rc/main values`);
32316
- const maxTimeout = task.secretOutput !== void 0 ? 3600 : 7200;
32317
+ const maxTimeout = task.secretOutput !== void 0 ? 3600 : 10800;
32317
32318
  if (task.timeoutSeconds !== void 0 && (!Number.isInteger(task.timeoutSeconds) || task.timeoutSeconds < 1 || task.timeoutSeconds > maxTimeout)) throw new Error(`org project set: tenantTasks.${name}.timeoutSeconds must be an integer 1..${maxTimeout}`);
32318
32319
  const artifact = task.artifact ?? "none";
32319
32320
  if (artifact !== "none" && artifact !== "required") throw new Error(`org project set: tenantTasks.${name}.artifact must be none or required`);
@@ -52870,7 +52871,10 @@ function buildDeployRetirePlan(input) {
52870
52871
  if (!["dev", "rc", "main"].includes(input.stage)) {
52871
52872
  throw new Error("org project deploy retire: --stage must be dev, rc, or main");
52872
52873
  }
52873
- return { slug, stage: input.stage, apply: Boolean(input.apply) };
52874
+ if (input.decommissioned && input.stage !== "main") {
52875
+ throw new Error("org project deploy retire: --decommissioned applies to --stage main only (dev/rc always retire)");
52876
+ }
52877
+ return { slug, stage: input.stage, apply: Boolean(input.apply), decommissioned: Boolean(input.decommissioned) };
52874
52878
  }
52875
52879
  async function runDeployRetire(input, deps) {
52876
52880
  const plan = buildDeployRetirePlan(input);
@@ -52879,7 +52883,20 @@ async function runDeployRetire(input, deps) {
52879
52883
  if (!plan.apply) {
52880
52884
  return { slug: plan.slug, stage: plan.stage, applied: false, ok: facts !== null, existing };
52881
52885
  }
52882
- const res = await retireDeployCoords(plan.slug, plan.stage, deps.registry);
52886
+ if (plan.decommissioned) {
52887
+ const state = deps.boxServiceState ? await deps.boxServiceState(plan.stage) : "unknown";
52888
+ if (state !== "missing") {
52889
+ return {
52890
+ slug: plan.slug,
52891
+ stage: plan.stage,
52892
+ applied: false,
52893
+ ok: false,
52894
+ existing,
52895
+ error: `--decommissioned needs the box to show ${plan.stage} gone (tenant-control status serviceState=missing), got ${state} \u2014 run tenant control <repo> ${plan.stage} retire first`
52896
+ };
52897
+ }
52898
+ }
52899
+ const res = await retireDeployCoords(plan.slug, plan.stage, deps.registry, plan.decommissioned);
52883
52900
  if (!res.ok) {
52884
52901
  return { slug: plan.slug, stage: plan.stage, applied: true, ok: false, existing, error: writeError2(res) };
52885
52902
  }
@@ -56155,7 +56172,7 @@ projectDeploy.command("doctor").description("read-only estate port scan; --box l
56155
56172
  if (report.error && report.status !== 403) return failGraceful(`org project deploy doctor: ${report.error}`);
56156
56173
  if (!report.ok && !report.error) process.exitCode = 1;
56157
56174
  });
56158
- projectDeploy.command("retire [owner/repo]").description("retire (tombstone) one stage's DEPLOY# row for a project that no longer deploys through it (#7095, master-only). --stage is required. DRY-RUN by default \u2014 pass --apply to actually write; defaults to the current repo. Refuses a tenant-container project's live main row.").addOption(new Option("--stage <stage>", "dev | rc | main (required)").choices(["dev", "rc", "main"])).option("--apply", "actually retire (default is a dry-run preview of the row that would be retired)").option("--json", "machine-readable output").action(async (repoOrSlug, o) => {
56175
+ projectDeploy.command("retire [owner/repo]").description("retire (tombstone) one stage's DEPLOY# row for a project that no longer deploys through it (#7095, master-only). --stage is required. DRY-RUN by default \u2014 pass --apply to actually write; defaults to the current repo. Refuses a tenant-container project's live main row.").addOption(new Option("--stage <stage>", "dev | rc | main (required)").choices(["dev", "rc", "main"])).option("--apply", "actually retire (default is a dry-run preview of the row that would be retired)").option("--decommissioned", "main only (#8148): retire a tenant-container main row after `runtime tenant control <repo> main retire`; the box must show main gone").option("--json", "machine-readable output").action(async (repoOrSlug, o) => {
56159
56176
  const stage = projectDeploy.opts().stage;
56160
56177
  if (!stage) return fail("org project deploy retire: --stage is required (dev | rc | main)");
56161
56178
  const cfg = await loadConfig();
@@ -56168,8 +56185,14 @@ projectDeploy.command("retire [owner/repo]").description("retire (tombstone) one
56168
56185
  let result;
56169
56186
  try {
56170
56187
  result = await runDeployRetire(
56171
- { target, stage, apply: Boolean(o.apply) },
56172
- { registry: registryClientDeps(cfg) }
56188
+ { target, stage, apply: Boolean(o.apply), decommissioned: Boolean(o.decommissioned) },
56189
+ {
56190
+ registry: registryClientDeps(cfg),
56191
+ boxServiceState: async (s) => {
56192
+ const r = await runTenantControl(trainApplyDeps(), { repo: target, stage: s, action: "status", watch: true });
56193
+ return r.conclusion === "success" ? r.serviceState ?? "unknown" : "error";
56194
+ }
56195
+ }
56173
56196
  );
56174
56197
  } catch (e) {
56175
56198
  return fail(e.message);
@@ -56434,7 +56457,7 @@ ${filelessTransitionGuide(target, o.stage)}`
56434
56457
  return reportWrite("org project set-deploy", res);
56435
56458
  });
56436
56459
  var projectTenantTasks = project.command("tenant-tasks").description("project-admin self-declare of tenant tasks for every stage of your own repo \u2014 new-task-only; editing an existing task stays master-only (`org project set --var tenantTasks=...`)");
56437
- projectTenantTasks.command("declare <name>").description("register a NEW tenant task \u2014 becomes runnable via `runtime tenant control \u2026 run-task` on its declared dev/rc/main stages. Body shape {service,command[],stages[],timeoutSeconds?,artifact?}; required artifact tasks must carry {artifact} in the command argv.").option("--service <name>", "service in the tenant runtime the task runs in (required unless --var carries it)").option("--command <argv...>", `task command as argv (repeatable; required unless --var carries it). An argv token that starts with "-" (python -m mod) is read as an option and the whole call fails to parse: declare such a command with --var '{"service":"<svc>","command":["python","-m","mod"],"stages":["dev"]}' instead (#7668)`).option("--stages <list>", "comma-separated dev,rc,main stages this task may run on (required unless --var carries it)").option("--timeout-seconds <n>", "optional wall-clock ceiling 1..7200 (1..3600 with a secretOutput)").option("--artifact <none|required>", "artifact contract (default none; required tasks must contain {artifact} in argv)").option("--var <json>", "full task object {service,command[],stages[],timeoutSeconds?,artifact?} \u2014 use instead of the individual flags. A task carrying secretOutput:{path,vault:{repo,key},overwrite?} is master-only; declare that via `org project set --var tenantTasks=...`").option("--repo <owner/repo>", "target repo (defaults to the current repo)").option("--json", "machine-readable output").action(async (name, o) => {
56460
+ projectTenantTasks.command("declare <name>").description("register a NEW tenant task \u2014 becomes runnable via `runtime tenant control \u2026 run-task` on its declared dev/rc/main stages. Body shape {service,command[],stages[],timeoutSeconds?,artifact?}; required artifact tasks must carry {artifact} in the command argv.").option("--service <name>", "service in the tenant runtime the task runs in (required unless --var carries it)").option("--command <argv...>", `task command as argv (repeatable; required unless --var carries it). An argv token that starts with "-" (python -m mod) is read as an option and the whole call fails to parse: declare such a command with --var '{"service":"<svc>","command":["python","-m","mod"],"stages":["dev"]}' instead (#7668)`).option("--stages <list>", "comma-separated dev,rc,main stages this task may run on (required unless --var carries it)").option("--timeout-seconds <n>", "optional wall-clock ceiling 1..10800 (1..3600 with a secretOutput)").option("--artifact <none|required>", "artifact contract (default none; required tasks must contain {artifact} in argv)").option("--var <json>", "full task object {service,command[],stages[],timeoutSeconds?,artifact?} \u2014 use instead of the individual flags. A task carrying secretOutput:{path,vault:{repo,key},overwrite?} is master-only; declare that via `org project set --var tenantTasks=...`").option("--repo <owner/repo>", "target repo (defaults to the current repo)").option("--json", "machine-readable output").action(async (name, o) => {
56438
56461
  const cfg = await loadConfig();
56439
56462
  let target;
56440
56463
  try {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mutmutco/cli",
3
- "version": "4.5.125",
3
+ "version": "4.5.127",
4
4
  "description": "MMI Future CLI — the org dev toolbox and shared cross-IDE engine for every registry-declared MMI coding surface.",
5
5
  "type": "module",
6
6
  "license": "UNLICENSED",