@mutmutco/cli 4.3.68 → 4.4.1
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/main.cjs +75 -51
- package/package.json +1 -1
package/dist/main.cjs
CHANGED
|
@@ -6380,7 +6380,7 @@ function decorateAwsModel(entries, registry2, verdicts) {
|
|
|
6380
6380
|
});
|
|
6381
6381
|
}
|
|
6382
6382
|
var DECLARED_ENTRIES = [
|
|
6383
|
-
{ name: "mmi-backup (mm-central,
|
|
6383
|
+
{ name: "mmi-backup (mm-central, mm-work, zuber, mmi-oguz)", cadence: "17 2 * * *", executor: "box cron.d", llm: "no", resolved: "declared", source: "/etc/cron.d/mmi-backup \u2192 /opt/mmi-control/nightly-backup.sh (verify: mmi-cli devops runtime box get <box> --ssh)" },
|
|
6384
6384
|
// #3370/#6270: the one runner hygiene layer (runner-hygiene.yml was folded in and deleted). A workflow ran ON the runner and needed checkout +
|
|
6385
6385
|
// setup-node before it can prune, so at 100% it dies at checkout and never prunes — the cleanup is
|
|
6386
6386
|
// unavailable exactly when it is needed. This one is root cron on the box: no checkout, no node, and
|
|
@@ -9439,6 +9439,18 @@ function resolveUseEnvNames(keys, name) {
|
|
|
9439
9439
|
}
|
|
9440
9440
|
return { ok: true, entries };
|
|
9441
9441
|
}
|
|
9442
|
+
function referencesDollarEnv(arg, name) {
|
|
9443
|
+
return arg.includes(`\${${name}}`) || new RegExp(`\\$${name}(?![A-Za-z0-9_])`).test(arg);
|
|
9444
|
+
}
|
|
9445
|
+
function secretsUseDollarHint(command, envNames) {
|
|
9446
|
+
for (const arg of command) {
|
|
9447
|
+
for (const name of envNames) {
|
|
9448
|
+
if (!referencesDollarEnv(arg, name)) continue;
|
|
9449
|
+
return `secrets use: $${name} is injected into the CHILD's env, not your shell \u2014 the caller expanded it (empty) before this ran. Wrap the consumer so expansion happens inside: bash -c 'your-command "$${name}"'`;
|
|
9450
|
+
}
|
|
9451
|
+
}
|
|
9452
|
+
return null;
|
|
9453
|
+
}
|
|
9442
9454
|
var PRE_SPAWN_DRAIN_TIMEOUT_MS = 2e3;
|
|
9443
9455
|
async function drainHttpPoolBeforeSpawn() {
|
|
9444
9456
|
const drained = await Promise.race([
|
|
@@ -9490,6 +9502,8 @@ async function secretsUse(deps, keys, opts) {
|
|
|
9490
9502
|
deps.err(named.error);
|
|
9491
9503
|
return false;
|
|
9492
9504
|
}
|
|
9505
|
+
const dollarHint = secretsUseDollarHint(command, named.entries.map((e) => e.envName));
|
|
9506
|
+
if (dollarHint) deps.err(dollarHint);
|
|
9493
9507
|
const repo = await targetRepo(deps, opts);
|
|
9494
9508
|
const slug = opts.slug?.toLowerCase();
|
|
9495
9509
|
const env = { ...process.env };
|
|
@@ -14238,9 +14252,6 @@ function expectedHosts(cfg) {
|
|
|
14238
14252
|
for (const env of ENV_PREFIXES) out.push(env ? `${env}.${base}` : base);
|
|
14239
14253
|
}
|
|
14240
14254
|
}
|
|
14241
|
-
if (cfg.fofuSubdomain !== void 0) {
|
|
14242
|
-
out.push(cfg.fofuSubdomain ? `${cfg.fofuSubdomain}.fofu.ai` : "fofu.ai");
|
|
14243
|
-
}
|
|
14244
14255
|
return uniq([...out, ...cfg.edgeHosts ?? []]);
|
|
14245
14256
|
}
|
|
14246
14257
|
function expectedJsOrigins(cfg) {
|
|
@@ -14305,10 +14316,7 @@ function parseOauthConfig(mmiConfig, slug) {
|
|
|
14305
14316
|
);
|
|
14306
14317
|
}
|
|
14307
14318
|
const extraCallbackPaths = parseExtraCallbackPaths(raw.extraCallbackPaths);
|
|
14308
|
-
|
|
14309
|
-
const rawFofuSub = raw.fofuSubdomain;
|
|
14310
|
-
const fofuSubdomain = meta.fofuEnabled === true ? typeof rawFofuSub === "string" ? rawFofuSub : defaultSubdomain(slug) : void 0;
|
|
14311
|
-
return { subdomains, domains, callbackPath, extraCallbackPaths, fofuSubdomain, edgeHosts: Object.values(edgeDomainsByStage(mmiConfig)) };
|
|
14319
|
+
return { subdomains, domains, callbackPath, extraCallbackPaths, edgeHosts: Object.values(edgeDomainsByStage(mmiConfig)) };
|
|
14312
14320
|
}
|
|
14313
14321
|
function probeRedirectUri(callbackPath, port = 9123) {
|
|
14314
14322
|
return `http://localhost:${port}${callbackPath}`;
|
|
@@ -15862,10 +15870,10 @@ var rollout_plan_default = {
|
|
|
15862
15870
|
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)."
|
|
15863
15871
|
},
|
|
15864
15872
|
baseline: {
|
|
15865
|
-
version: "4.
|
|
15866
|
-
tag: "v4.
|
|
15867
|
-
commit: "
|
|
15868
|
-
npm: "@mutmutco/cli@4.
|
|
15873
|
+
version: "4.4.1",
|
|
15874
|
+
tag: "v4.4.1",
|
|
15875
|
+
commit: "a4bb2ac4bdb4",
|
|
15876
|
+
npm: "@mutmutco/cli@4.4.1"
|
|
15869
15877
|
},
|
|
15870
15878
|
exitCriterion: "fleet-n-of-n",
|
|
15871
15879
|
hubOnlyShortcut: "forbidden",
|
|
@@ -15882,14 +15890,14 @@ var rollout_plan_default = {
|
|
|
15882
15890
|
repo: "mutmutco/mmi-hub",
|
|
15883
15891
|
role: "canary",
|
|
15884
15892
|
schedule: "train",
|
|
15885
|
-
v3Target: "v4.
|
|
15893
|
+
v3Target: "v4.4.1"
|
|
15886
15894
|
}
|
|
15887
15895
|
],
|
|
15888
15896
|
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.",
|
|
15889
15897
|
rollback: {
|
|
15890
15898
|
independent: true,
|
|
15891
|
-
mechanism: "npm dist-tag latest -> 4.
|
|
15892
|
-
v3Target: "v4.
|
|
15899
|
+
mechanism: "npm dist-tag latest -> 4.4.1 and redeploy the Hub Lambda from tag v4.4.1 (a4bb2ac4bdb4); installed clients repair via `mmi-cli doctor`. No other cohort is touched.",
|
|
15900
|
+
v3Target: "v4.4.1 (@mutmutco/cli@4.4.1, tag commit a4bb2ac4bdb4 \u2014 last known-good release carrying the repo-index v4-only contract)"
|
|
15893
15901
|
}
|
|
15894
15902
|
},
|
|
15895
15903
|
{
|
|
@@ -15986,12 +15994,6 @@ var rollout_plan_default = {
|
|
|
15986
15994
|
schedule: "train",
|
|
15987
15995
|
v3Target: "v0.3.0"
|
|
15988
15996
|
},
|
|
15989
|
-
{
|
|
15990
|
-
repo: "mutmutco/mm-fofu",
|
|
15991
|
-
role: "member",
|
|
15992
|
-
schedule: "train",
|
|
15993
|
-
v3Target: "v0.1.0"
|
|
15994
|
-
},
|
|
15995
15997
|
{
|
|
15996
15998
|
repo: "mutmutco/mmi-junior",
|
|
15997
15999
|
role: "member",
|
|
@@ -21626,6 +21628,9 @@ async function supersedeContentCausedDeployLeg(deps, cwd) {
|
|
|
21626
21628
|
function supersedeablePublishLegShape(rec) {
|
|
21627
21629
|
return rec.state === "failed" || rec.state === "pending" && rec.runId == null;
|
|
21628
21630
|
}
|
|
21631
|
+
function deferredGatewayDeployLegShape(rec) {
|
|
21632
|
+
return rec.state === "pending" && rec.runId == null && rec.workflow === "jerv-gateway";
|
|
21633
|
+
}
|
|
21629
21634
|
async function supersedeContentCausedPublishLeg(deps, cwd) {
|
|
21630
21635
|
const path2 = releaseLedgerPath(cwd);
|
|
21631
21636
|
return withFileLock(`${path2}.lock`, { label: "release ledger" }, async () => {
|
|
@@ -21651,7 +21656,9 @@ async function supersedeContentCausedPublishLeg(deps, cwd) {
|
|
|
21651
21656
|
const closed = await alignmentLegClosedLive(deps, prior);
|
|
21652
21657
|
if (closed) phases.alignment = closed;
|
|
21653
21658
|
}
|
|
21654
|
-
|
|
21659
|
+
let gatewayDeploy;
|
|
21660
|
+
const deferredGateway = isJervHubRepo(prior.repo) && deferredGatewayDeployLegShape(phases.deploy);
|
|
21661
|
+
const unresolved = ["promotion", "ordinaryCi", "githubRelease", "deploy", "alignment"].filter((phase) => !(phase === "deploy" && deferredGateway)).filter((phase) => phases[phase].state === "pending" || phases[phase].state === "failed");
|
|
21655
21662
|
if (unresolved.length > 0) {
|
|
21656
21663
|
throw new Error(
|
|
21657
21664
|
`release --supersede-publish: ${prior.tag} has unresolved legs besides publish (${unresolved.map((p) => `${p}=${phases[p].state}`).join(", ")}) \u2014 the supersession closes only the publish leg of an otherwise-complete release; resolve those first, nothing was written (#6638)`
|
|
@@ -21704,6 +21711,25 @@ async function supersedeContentCausedPublishLeg(deps, cwd) {
|
|
|
21704
21711
|
note: `closed the deleted ${prior.tag} publish failure by archiving its ledger after origin and GitHub both proved absent; start a fresh release train to carry the cause fix`
|
|
21705
21712
|
};
|
|
21706
21713
|
}
|
|
21714
|
+
if (deferredGateway) {
|
|
21715
|
+
const dispatch = await appendJervGatewayReleaseDeploy(
|
|
21716
|
+
deps,
|
|
21717
|
+
prior.repo,
|
|
21718
|
+
prior.tag,
|
|
21719
|
+
prior.tagSha,
|
|
21720
|
+
{ note: `Jerv Gateway operator-host deploy leg for ${prior.tag} run during the publish supersession`, deployStatus: "success" }
|
|
21721
|
+
);
|
|
21722
|
+
phases.deploy = {
|
|
21723
|
+
...phaseEntry(deployPhaseInput("registry-publish", dispatch, { releaseSha: prior.tagSha })),
|
|
21724
|
+
updatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
21725
|
+
};
|
|
21726
|
+
if (dispatch.deployStatus !== "success") {
|
|
21727
|
+
throw new Error(
|
|
21728
|
+
`release --supersede-publish: the deferred ${prior.tag} Jerv Gateway operator-host deploy leg did not verify (${dispatch.note}) \u2014 run \`scripts/jerv-gateway-release-deploy.sh --tag ${prior.tag}\` to a healthy receipt naming the released tag and commit, then retry; nothing was written (#6742)`
|
|
21729
|
+
);
|
|
21730
|
+
}
|
|
21731
|
+
gatewayDeploy = { workflow: "jerv-gateway", state: "complete", note: dispatch.note };
|
|
21732
|
+
}
|
|
21707
21733
|
const note = `superseded: content-caused publish failure on the immutable promoted ${prior.tag} \u2014 the cause fix rides the next patch train (master-approved closure, #6638)`;
|
|
21708
21734
|
atomicWriteJson(path2, {
|
|
21709
21735
|
...prior,
|
|
@@ -21718,7 +21744,8 @@ async function supersedeContentCausedPublishLeg(deps, cwd) {
|
|
|
21718
21744
|
repo: prior.repo,
|
|
21719
21745
|
tag: prior.tag,
|
|
21720
21746
|
tagSha: prior.tagSha,
|
|
21721
|
-
note: `closed the ${prior.tag} publish leg as superseded (skipped) \u2014 the ledger is phases-green; rerun the train doctor to confirm, then run the next patch train (hotfix or release) to carry the cause fix
|
|
21747
|
+
note: `closed the ${prior.tag} publish leg as superseded (skipped) \u2014 the ledger is phases-green; rerun the train doctor to confirm, then run the next patch train (hotfix or release) to carry the cause fix`,
|
|
21748
|
+
...gatewayDeploy ? { gatewayDeploy } : {}
|
|
21722
21749
|
};
|
|
21723
21750
|
});
|
|
21724
21751
|
}
|
|
@@ -29667,12 +29694,12 @@ function registerDeployCommands(program3) {
|
|
|
29667
29694
|
init_cli_shared();
|
|
29668
29695
|
|
|
29669
29696
|
// src/project-set.ts
|
|
29670
|
-
var UNSET_KEYS = ["oauth", "requiredRuntimeSecrets", "requiredBuildSecrets", "tenantTasks", "secrets", "edgeDomains", "requiredGcpApis", "publishRequired", "publishDir", "releaseChannel", "releaseLanguage", "dsManifestPath", "
|
|
29697
|
+
var UNSET_KEYS = ["oauth", "requiredRuntimeSecrets", "requiredBuildSecrets", "tenantTasks", "secrets", "edgeDomains", "requiredGcpApis", "publishRequired", "publishDir", "releaseChannel", "releaseLanguage", "dsManifestPath", "consumesDesignSystem", "ci", "requiredChecks", "requiredCheckBranches", "ciExemptReason", "gate", "seedCanary"];
|
|
29671
29698
|
var UNSET_KEY_SET = new Set(UNSET_KEYS);
|
|
29672
29699
|
var RUNTIME_SECRET_STAGES = ["dev", "rc", "main"];
|
|
29673
29700
|
var SECRET_CONSUMERS = ["runtime", "build", "lambda", "actions", "agent", "box"];
|
|
29674
29701
|
var SECRET_ENV_NAME_RE = /^[A-Za-z][A-Za-z0-9_]*$/;
|
|
29675
|
-
var BUILD_SECRET_REF_RE = /^(?:[A-Z_][A-Z0-9_]*=)?(?:[A-Z_][A-Z0-9_]*|(?:
|
|
29702
|
+
var BUILD_SECRET_REF_RE = /^(?:[A-Z_][A-Z0-9_]*=)?(?:[A-Z_][A-Z0-9_]*|(?:_org\/[a-z0-9][a-z0-9-]*):[A-Z_][A-Z0-9_]*|@github-packages-token)$/;
|
|
29676
29703
|
function previewRegistryMetaMerge(existing, patch) {
|
|
29677
29704
|
const out = { ...existing ?? {} };
|
|
29678
29705
|
for (const [key, value] of Object.entries(patch)) {
|
|
@@ -29868,7 +29895,7 @@ function parseOauthVar(raw) {
|
|
|
29868
29895
|
throw new Error(`org project set: oauth must be JSON, e.g. {"subdomains":["app"],"domains":["example.co"],"callbackPath":"${DEFAULT_CALLBACK_PATH}"}`);
|
|
29869
29896
|
}
|
|
29870
29897
|
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
29871
|
-
throw new Error("org project set: oauth must be a {subdomains,domains,callbackPath,extraCallbackPaths
|
|
29898
|
+
throw new Error("org project set: oauth must be a {subdomains,domains,callbackPath,extraCallbackPaths} object");
|
|
29872
29899
|
}
|
|
29873
29900
|
const map = parsed;
|
|
29874
29901
|
const out = {};
|
|
@@ -29896,11 +29923,8 @@ function parseOauthVar(raw) {
|
|
|
29896
29923
|
} catch (e) {
|
|
29897
29924
|
throw new Error(`org project set: ${e.message}`);
|
|
29898
29925
|
}
|
|
29899
|
-
} else if (key === "fofuSubdomain") {
|
|
29900
|
-
if (typeof value !== "string") throw new Error('org project set: oauth.fofuSubdomain must be a string ("" selects the apex fofu.ai)');
|
|
29901
|
-
out.fofuSubdomain = value.trim();
|
|
29902
29926
|
} else {
|
|
29903
|
-
throw new Error(`org project set: oauth key "${key}" \u2014 expected only subdomains/domains/callbackPath/extraCallbackPaths
|
|
29927
|
+
throw new Error(`org project set: oauth key "${key}" \u2014 expected only subdomains/domains/callbackPath/extraCallbackPaths`);
|
|
29904
29928
|
}
|
|
29905
29929
|
}
|
|
29906
29930
|
return out;
|
|
@@ -29922,11 +29946,6 @@ function parsePublishRequiredVar(raw) {
|
|
|
29922
29946
|
if (raw === "false") return false;
|
|
29923
29947
|
throw new Error("org project set: publishRequired must be true or false");
|
|
29924
29948
|
}
|
|
29925
|
-
function parseFofuEnabledVar(raw) {
|
|
29926
|
-
if (raw === "true") return true;
|
|
29927
|
-
if (raw === "false") return false;
|
|
29928
|
-
throw new Error("org project set: fofuEnabled must be true or false");
|
|
29929
|
-
}
|
|
29930
29949
|
function parseRuntimeVaultOnlyVar(raw) {
|
|
29931
29950
|
if (raw === "true") return true;
|
|
29932
29951
|
if (raw === "false") return false;
|
|
@@ -30084,7 +30103,6 @@ var SETTABLE_VAR_KEYS = [
|
|
|
30084
30103
|
"releaseChannel",
|
|
30085
30104
|
"releaseLanguage",
|
|
30086
30105
|
"dsManifestPath",
|
|
30087
|
-
"fofuEnabled",
|
|
30088
30106
|
"consumesDesignSystem",
|
|
30089
30107
|
"runtimeVaultOnly",
|
|
30090
30108
|
"requiredGcpApis",
|
|
@@ -30113,12 +30131,11 @@ var SETTABLE_VAR_HINTS = {
|
|
|
30113
30131
|
releaseChannel: "Slack channel id, e.g. C0BE0BRGAT0",
|
|
30114
30132
|
releaseLanguage: "2-letter language code for release notes, e.g. tr (default en)",
|
|
30115
30133
|
dsManifestPath: "relative path to a package.json, e.g. web/package.json",
|
|
30116
|
-
fofuEnabled: "true|false",
|
|
30117
30134
|
consumesDesignSystem: '"fofu"',
|
|
30118
30135
|
runtimeVaultOnly: "true|false",
|
|
30119
30136
|
seedCanary: "true|false",
|
|
30120
30137
|
repos: 'JSON array, e.g. ["mutmutco/mm-foo"]',
|
|
30121
|
-
oauth: "JSON {subdomains,domains,callbackPath,extraCallbackPaths
|
|
30138
|
+
oauth: "JSON {subdomains,domains,callbackPath,extraCallbackPaths}",
|
|
30122
30139
|
requiredGcpApis: "comma-string",
|
|
30123
30140
|
requiredRuntimeSecrets: 'JSON stage map, e.g. {"dev":["KEY"],"rc":["KEY"],"main":["KEY"]}',
|
|
30124
30141
|
requiredBuildSecrets: 'JSON flat array, e.g. ["NODE_AUTH_TOKEN=@github-packages-token"]',
|
|
@@ -30214,8 +30231,6 @@ function buildProjectSetPatch(input) {
|
|
|
30214
30231
|
patch[key] = parseReposVar(raw);
|
|
30215
30232
|
} else if (key === "publishRequired") {
|
|
30216
30233
|
patch[key] = parsePublishRequiredVar(raw);
|
|
30217
|
-
} else if (key === "fofuEnabled") {
|
|
30218
|
-
patch[key] = parseFofuEnabledVar(raw);
|
|
30219
30234
|
} else if (key === "runtimeVaultOnly") {
|
|
30220
30235
|
patch[key] = parseRuntimeVaultOnlyVar(raw);
|
|
30221
30236
|
} else if (key === "seedCanary") {
|
|
@@ -36752,7 +36767,7 @@ async function runStageLiveDown(deps, t) {
|
|
|
36752
36767
|
var GITHUB_PACKAGES_TOKEN_REF = "@github-packages-token";
|
|
36753
36768
|
var ENV_ID_RE = /^[A-Z_][A-Z0-9_]*$/;
|
|
36754
36769
|
var BARE_VAULT_KEY_RE = /^[A-Z_][A-Z0-9_]*$/;
|
|
36755
|
-
var CROSS_SLUG_REF_RE = /^(?:
|
|
36770
|
+
var CROSS_SLUG_REF_RE = /^(?:_org\/[a-z0-9][a-z0-9-]*):[A-Z_][A-Z0-9_]*$/;
|
|
36756
36771
|
function parseStageBuildSecretEntry(entry) {
|
|
36757
36772
|
const trimmed = entry.trim();
|
|
36758
36773
|
if (!trimmed) return null;
|
|
@@ -36824,7 +36839,6 @@ async function fetchVaultRef(fetchVault, ref) {
|
|
|
36824
36839
|
if (colon === -1) return fetchVault(ref);
|
|
36825
36840
|
const prefix = ref.slice(0, colon);
|
|
36826
36841
|
const key = ref.slice(colon + 1);
|
|
36827
|
-
if (prefix === "mm-fofu") return fetchVault(key, { slug: "mm-fofu" });
|
|
36828
36842
|
if (prefix.startsWith("_org/")) {
|
|
36829
36843
|
const provider = prefix.slice("_org/".length);
|
|
36830
36844
|
return fetchVault(`${provider}/${key}`, { slug: "_org" });
|
|
@@ -42014,7 +42028,7 @@ function formatBoxTable(boxes) {
|
|
|
42014
42028
|
}
|
|
42015
42029
|
return lines2.join("\n");
|
|
42016
42030
|
}
|
|
42017
|
-
function formatSshRecipe(box) {
|
|
42031
|
+
function formatSshRecipe(box, remoteCommand) {
|
|
42018
42032
|
if (!box.address) {
|
|
42019
42033
|
return `box ${box.name} has no public IPv4 \u2014 it is not directly reachable over ssh.`;
|
|
42020
42034
|
}
|
|
@@ -42028,13 +42042,21 @@ function formatSshRecipe(box) {
|
|
|
42028
42042
|
" --with-decryption --query Parameter.Value --output text --region eu-central-1 \\",
|
|
42029
42043
|
` | tr -d '\\r' > "$kf"`,
|
|
42030
42044
|
'test -s "$kf" # never hand ssh an empty key file',
|
|
42031
|
-
`ssh -i "$kf" -o StrictHostKeyChecking=accept-new root@${box.address}
|
|
42045
|
+
`ssh -i "$kf" -o StrictHostKeyChecking=accept-new root@${box.address} ${shellSingleQuote(sshRemoteCommand(remoteCommand))}`
|
|
42032
42046
|
].join("\n");
|
|
42033
42047
|
}
|
|
42048
|
+
var SSH_DEFAULT_PROBE = "hostname; uptime";
|
|
42049
|
+
function sshRemoteCommand(remoteCommand) {
|
|
42050
|
+
const trimmed = remoteCommand?.trim();
|
|
42051
|
+
return trimmed ? trimmed : SSH_DEFAULT_PROBE;
|
|
42052
|
+
}
|
|
42053
|
+
function shellSingleQuote(value) {
|
|
42054
|
+
return `'${value.replace(/'/g, `'\\''`)}'`;
|
|
42055
|
+
}
|
|
42034
42056
|
var SSH_RECIPE_AGENT_NOTE = "# agent callers: this is multi-line, so running it inline is denied (#1473/#2125).\n# Use `mmi-cli devops runtime box get <name> --ssh --script <path>` to write it to a file, then `bash <path>`.";
|
|
42035
|
-
function sshRecipeScript(box) {
|
|
42057
|
+
function sshRecipeScript(box, remoteCommand) {
|
|
42036
42058
|
return `#!/usr/bin/env bash
|
|
42037
|
-
${formatSshRecipe(box)}
|
|
42059
|
+
${formatSshRecipe(box, remoteCommand)}
|
|
42038
42060
|
`;
|
|
42039
42061
|
}
|
|
42040
42062
|
|
|
@@ -42109,7 +42131,7 @@ function registerBoxCommands(program3) {
|
|
|
42109
42131
|
await failGraceful(e.message);
|
|
42110
42132
|
}
|
|
42111
42133
|
});
|
|
42112
|
-
box.command("get <name>").description("one box by name \u2014 its address and ssh key path; --ssh prints a ready-to-run connect recipe").option("--json", "machine-readable output").option("--ssh", "print a copy-paste ssh recipe (materializes the key to a temp file; never echoes it)").option("--script <path>", "with --ssh: write the recipe to <path> and print the one line to run \u2014 the runnable form for agent callers, whose transport denies a multi-line inline body (#3385)").action(async (name, o) => {
|
|
42134
|
+
box.command("get <name> [command...]").description("one box by name \u2014 its address and ssh key path; --ssh prints a ready-to-run connect recipe").option("--json", "machine-readable output").option("--ssh", "print a copy-paste ssh recipe (materializes the key to a temp file; never echoes it)").option("--script <path>", "with --ssh: write the recipe to <path> and print the one line to run \u2014 the runnable form for agent callers, whose transport denies a multi-line inline body (#3385)").action(async (name, command, o) => {
|
|
42113
42135
|
try {
|
|
42114
42136
|
const { boxes, incomplete } = await fetchInventory();
|
|
42115
42137
|
const result = lookupBox(name, boxes, incomplete);
|
|
@@ -42129,8 +42151,9 @@ function registerBoxCommands(program3) {
|
|
|
42129
42151
|
await failGraceful("runtime box get: --script requires --ssh (it writes the ssh connect recipe)");
|
|
42130
42152
|
return;
|
|
42131
42153
|
}
|
|
42154
|
+
const remote = command && command.length ? command.join(" ") : void 0;
|
|
42132
42155
|
const wroteScript = o.ssh && o.script ? o.script : null;
|
|
42133
|
-
if (wroteScript) (0, import_node_fs42.writeFileSync)(wroteScript, sshRecipeScript(found), "utf8");
|
|
42156
|
+
if (wroteScript) (0, import_node_fs42.writeFileSync)(wroteScript, sshRecipeScript(found, remote), "utf8");
|
|
42134
42157
|
if (o.json) {
|
|
42135
42158
|
console.log(JSON.stringify({
|
|
42136
42159
|
box: found,
|
|
@@ -42138,7 +42161,7 @@ function registerBoxCommands(program3) {
|
|
|
42138
42161
|
...wroteScript ? { script: { path: wroteScript, run: `bash "${wroteScript}"` } } : {}
|
|
42139
42162
|
}, null, 2));
|
|
42140
42163
|
} else if (wroteScript) console.log(`wrote ${wroteScript} \u2014 run: bash "${wroteScript}"`);
|
|
42141
|
-
else if (o.ssh) console.log(`${formatSshRecipe(found)}
|
|
42164
|
+
else if (o.ssh) console.log(`${formatSshRecipe(found, remote)}
|
|
42142
42165
|
${SSH_RECIPE_AGENT_NOTE}`);
|
|
42143
42166
|
else console.log(formatBoxTable([found]));
|
|
42144
42167
|
if (!o.json) warnIncomplete2(incomplete);
|
|
@@ -44615,7 +44638,8 @@ function renderReleaseSupersedeDeploy(r) {
|
|
|
44615
44638
|
return `mmi-cli devops release --supersede-deploy --apply: ${r.repo} ${r.tag} (${r.tagSha.slice(0, 12)}) \u2014 ${r.note}`;
|
|
44616
44639
|
}
|
|
44617
44640
|
function renderReleaseSupersedePublish(r) {
|
|
44618
|
-
|
|
44641
|
+
const base = `mmi-cli devops release --supersede-publish --apply: ${r.repo} ${r.tag} (${r.tagSha.slice(0, 12)}) \u2014 ${r.note}`;
|
|
44642
|
+
return r.gatewayDeploy ? `${base}; the deferred Jerv Gateway operator-host deploy leg was run and verified during the supersession (jerv-gateway=complete): ${r.gatewayDeploy.note}` : base;
|
|
44619
44643
|
}
|
|
44620
44644
|
function renderReleasePublishRetry(r) {
|
|
44621
44645
|
return `mmi-cli devops release --retry-publish: ${r.repo} ${r.tag} (${r.tagSha.slice(0, 12)}) \u2014 ${r.note}; ${r.runUrl}`;
|
|
@@ -44847,7 +44871,7 @@ function registerTrainOperationsCommands(program3, runProjectInfoSyncCallback) {
|
|
|
44847
44871
|
{ flags: "--dev", description: "full-track repos release development -> main directly, skipping rc (refuses if rc carries content not in development; no-op on direct-track repos) (#1062)" },
|
|
44848
44872
|
{ flags: "--abort", description: "with --apply, delete only a proven unpublished failed release candidate on any registered deploy model and restore local main for a same-version recut (#3944/#5650/#5657)" },
|
|
44849
44873
|
{ flags: "--supersede-deploy", description: "with --apply, master-approved closure of a content-caused failed deploy leg on a PUBLISHED release whose immutable tag can never deploy green \u2014 the next patch train then carries the fix (#6553)" },
|
|
44850
|
-
{ flags: "--supersede-publish", description: "with --apply, master-approved closure of a content-caused failed publish leg on a fully PROMOTED release whose immutable tag can never publish green \u2014 the next patch train then carries the fix (#6638)" },
|
|
44874
|
+
{ flags: "--supersede-publish", description: "with --apply, master-approved closure of a content-caused failed publish leg on a fully PROMOTED release whose immutable tag can never publish green \u2014 a deferred Jerv-Hub operator-host Gateway deploy leg is run and verified as part of the closure \u2014 the next patch train then carries the fix (#6638/#6742)" },
|
|
44851
44875
|
{ flags: "--retry-publish <run-id>", description: "with --apply, retry one proven failed or cancelled Hub publish release run (#3949/#5797)" }
|
|
44852
44876
|
];
|
|
44853
44877
|
for (const f of RELEASE_ONLY_FLAGS) {
|
package/package.json
CHANGED