@mutmutco/cli 4.3.57 → 4.3.59
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 +105 -264
- package/package.json +1 -1
package/dist/main.cjs
CHANGED
|
@@ -6046,6 +6046,15 @@ var REGISTRY_FETCH_TIMEOUT_MS = 8e3;
|
|
|
6046
6046
|
init_fetch_retry();
|
|
6047
6047
|
init_client_version();
|
|
6048
6048
|
|
|
6049
|
+
// ../shared/schedule-inventory.ts
|
|
6050
|
+
function classifyLlmValue(raw) {
|
|
6051
|
+
const value = raw.trim().toLowerCase();
|
|
6052
|
+
if (/^no\b|^none\b/.test(value)) return "no";
|
|
6053
|
+
if (/^yes\b/.test(value)) return "yes";
|
|
6054
|
+
if (/^embeddings\b/.test(value)) return "embeddings";
|
|
6055
|
+
return "unknown";
|
|
6056
|
+
}
|
|
6057
|
+
|
|
6049
6058
|
// src/workflow-context.ts
|
|
6050
6059
|
function parseWorkflowJobs(yaml) {
|
|
6051
6060
|
const lines2 = yaml.split(/\r?\n/);
|
|
@@ -6324,25 +6333,10 @@ function resolvedLabel(entry, now) {
|
|
|
6324
6333
|
var ORG = "mutmutco";
|
|
6325
6334
|
var DOC_START_MARKER = "<!-- schedules:inventory:start -->";
|
|
6326
6335
|
var DOC_END_MARKER = "<!-- schedules:inventory:end -->";
|
|
6327
|
-
function isJervResource(name) {
|
|
6328
|
-
return /^jerv-memory(?:-|$)/i.test(name);
|
|
6329
|
-
}
|
|
6330
6336
|
function llmFromHeader(yamlText) {
|
|
6331
6337
|
const m = /^#\s*llm:\s*(.+)$/im.exec(yamlText);
|
|
6332
6338
|
return m ? classifyLlmValue(m[1]) : "unknown";
|
|
6333
6339
|
}
|
|
6334
|
-
function classifyLlmValue(raw) {
|
|
6335
|
-
const value = raw.trim().toLowerCase();
|
|
6336
|
-
if (/^no\b|^none\b/.test(value)) return "no";
|
|
6337
|
-
if (/^yes\b/.test(value)) return "yes";
|
|
6338
|
-
if (/^embeddings\b/.test(value)) return "embeddings";
|
|
6339
|
-
return "unknown";
|
|
6340
|
-
}
|
|
6341
|
-
function readLlmDeclaration(text) {
|
|
6342
|
-
if (!text) return "unknown";
|
|
6343
|
-
const m = /\bllm:\s*(.+)/i.exec(text);
|
|
6344
|
-
return m ? classifyLlmValue(m[1]) : "unknown";
|
|
6345
|
-
}
|
|
6346
6340
|
function extractWorkflowCrons(yamlText) {
|
|
6347
6341
|
const crons = [];
|
|
6348
6342
|
for (const rawLine of yamlText.split("\n")) {
|
|
@@ -6366,126 +6360,6 @@ function workflowEntry(repo, workflowPath, yamlText) {
|
|
|
6366
6360
|
harbourUnmanaged: isHarbourUnmanaged(yamlText)
|
|
6367
6361
|
};
|
|
6368
6362
|
}
|
|
6369
|
-
function awsRuleEntries(payload) {
|
|
6370
|
-
if (!payload || typeof payload !== "object") {
|
|
6371
|
-
throw new Error("aws events list-rules answered a non-object payload \u2014 refusing to read it as zero rules");
|
|
6372
|
-
}
|
|
6373
|
-
const { Rules: rules } = payload;
|
|
6374
|
-
if (!Array.isArray(rules)) {
|
|
6375
|
-
throw new Error("aws events list-rules answered no Rules array \u2014 refusing to read it as zero rules");
|
|
6376
|
-
}
|
|
6377
|
-
const entries = [];
|
|
6378
|
-
for (const node of rules) {
|
|
6379
|
-
if (!node || typeof node !== "object") {
|
|
6380
|
-
throw new Error("aws events list-rules returned a non-object rule \u2014 refusing to read it as no rule");
|
|
6381
|
-
}
|
|
6382
|
-
const { Name, ScheduleExpression, State, Description } = node;
|
|
6383
|
-
if (typeof Name !== "string") {
|
|
6384
|
-
throw new Error("aws events list-rules returned a rule with no Name string \u2014 refusing to read it as no rule");
|
|
6385
|
-
}
|
|
6386
|
-
if (typeof ScheduleExpression !== "string") continue;
|
|
6387
|
-
if (State !== "ENABLED" || isJervResource(Name)) continue;
|
|
6388
|
-
entries.push({
|
|
6389
|
-
name: Name,
|
|
6390
|
-
cadence: ScheduleExpression,
|
|
6391
|
-
executor: "aws-eventbridge-rule",
|
|
6392
|
-
// An AWS rule declares `llm:` in its own Description (the shared convention) — a rule with no
|
|
6393
|
-
// Description reads `unknown`, and stack-internal plumbing like the Lambda warmer should say
|
|
6394
|
-
// `llm: no` there to go green.
|
|
6395
|
-
llm: readLlmDeclaration(typeof Description === "string" ? Description : void 0),
|
|
6396
|
-
resolved: "live",
|
|
6397
|
-
source: `aws events rule ${Name} (eu-central-1)`
|
|
6398
|
-
});
|
|
6399
|
-
}
|
|
6400
|
-
return entries;
|
|
6401
|
-
}
|
|
6402
|
-
function lambdaTargetFromArn(arn) {
|
|
6403
|
-
const marker = ":function:";
|
|
6404
|
-
const i = arn.indexOf(marker);
|
|
6405
|
-
if (i < 0) return { functionName: arn.split(":").pop() ?? "" };
|
|
6406
|
-
const rest = arn.slice(i + marker.length);
|
|
6407
|
-
const q = rest.indexOf(":");
|
|
6408
|
-
if (q < 0) return { functionName: rest };
|
|
6409
|
-
return { functionName: rest.slice(0, q), qualifier: rest.slice(q + 1) };
|
|
6410
|
-
}
|
|
6411
|
-
function awsScheduleEntry(payload) {
|
|
6412
|
-
if (!payload || typeof payload !== "object") {
|
|
6413
|
-
throw new Error("aws scheduler get-schedule answered a non-object payload \u2014 refusing to read it as no schedule");
|
|
6414
|
-
}
|
|
6415
|
-
const { Name, ScheduleExpression, State, Target, Description, CreationDate } = payload;
|
|
6416
|
-
if (typeof Name !== "string" || typeof ScheduleExpression !== "string") {
|
|
6417
|
-
throw new Error("aws scheduler get-schedule answered no Name/ScheduleExpression strings \u2014 refusing to read it as no schedule");
|
|
6418
|
-
}
|
|
6419
|
-
if (State !== "ENABLED" || isJervResource(Name)) return null;
|
|
6420
|
-
let target = "";
|
|
6421
|
-
let qualifier;
|
|
6422
|
-
let scheduleId;
|
|
6423
|
-
if (Target && typeof Target === "object") {
|
|
6424
|
-
const { Arn, Input } = Target;
|
|
6425
|
-
if (typeof Arn === "string") {
|
|
6426
|
-
const parsed = lambdaTargetFromArn(Arn);
|
|
6427
|
-
target = parsed.functionName;
|
|
6428
|
-
qualifier = parsed.qualifier;
|
|
6429
|
-
}
|
|
6430
|
-
if (typeof Input === "string") {
|
|
6431
|
-
try {
|
|
6432
|
-
const parsed = JSON.parse(Input);
|
|
6433
|
-
if (typeof parsed?.scheduleId === "string" && parsed.scheduleId) scheduleId = parsed.scheduleId;
|
|
6434
|
-
} catch {
|
|
6435
|
-
}
|
|
6436
|
-
}
|
|
6437
|
-
}
|
|
6438
|
-
const sourceBase = `aws scheduler schedule ${Name} (eu-central-1)`;
|
|
6439
|
-
const source = qualifier && target ? `${sourceBase} \u2192 ${target}:${qualifier}` : sourceBase;
|
|
6440
|
-
const armedAt = armedAtFromCreationDate(CreationDate);
|
|
6441
|
-
return {
|
|
6442
|
-
name: Name,
|
|
6443
|
-
cadence: ScheduleExpression,
|
|
6444
|
-
executor: target ? `aws-scheduler \u2192 ${target}` : "aws-scheduler",
|
|
6445
|
-
llm: readLlmDeclaration(typeof Description === "string" ? Description : void 0),
|
|
6446
|
-
resolved: "live",
|
|
6447
|
-
source,
|
|
6448
|
-
...scheduleId ? { scheduleId } : {},
|
|
6449
|
-
...armedAt ? { armedAt } : {}
|
|
6450
|
-
};
|
|
6451
|
-
}
|
|
6452
|
-
function armedAtFromCreationDate(creationDate) {
|
|
6453
|
-
if (creationDate instanceof Date) {
|
|
6454
|
-
return Number.isNaN(creationDate.getTime()) ? void 0 : creationDate.toISOString().slice(0, 10);
|
|
6455
|
-
}
|
|
6456
|
-
if (typeof creationDate === "string" && creationDate.trim()) {
|
|
6457
|
-
const parsed = Date.parse(creationDate);
|
|
6458
|
-
return Number.isNaN(parsed) ? void 0 : new Date(parsed).toISOString().slice(0, 10);
|
|
6459
|
-
}
|
|
6460
|
-
if (typeof creationDate === "number" && Number.isFinite(creationDate)) {
|
|
6461
|
-
const ms = creationDate > 1e12 ? creationDate : creationDate * 1e3;
|
|
6462
|
-
const date = new Date(ms);
|
|
6463
|
-
return Number.isNaN(date.getTime()) ? void 0 : date.toISOString().slice(0, 10);
|
|
6464
|
-
}
|
|
6465
|
-
return void 0;
|
|
6466
|
-
}
|
|
6467
|
-
function awsScheduleRefs(payload) {
|
|
6468
|
-
if (!payload || typeof payload !== "object") {
|
|
6469
|
-
throw new Error("aws scheduler list-schedules answered a non-object payload \u2014 refusing to read it as zero schedules");
|
|
6470
|
-
}
|
|
6471
|
-
const { Schedules: schedules } = payload;
|
|
6472
|
-
if (!Array.isArray(schedules)) {
|
|
6473
|
-
throw new Error("aws scheduler list-schedules answered no Schedules array \u2014 refusing to read it as zero schedules");
|
|
6474
|
-
}
|
|
6475
|
-
const refs = [];
|
|
6476
|
-
for (const s of schedules) {
|
|
6477
|
-
if (!s || typeof s !== "object") {
|
|
6478
|
-
throw new Error("aws scheduler list-schedules returned a non-object schedule \u2014 refusing to read it as no schedule");
|
|
6479
|
-
}
|
|
6480
|
-
const { Name, GroupName } = s;
|
|
6481
|
-
if (typeof Name !== "string") {
|
|
6482
|
-
throw new Error("aws scheduler list-schedules returned a schedule with no Name string \u2014 refusing to read it as no schedule");
|
|
6483
|
-
}
|
|
6484
|
-
if (isJervResource(Name)) continue;
|
|
6485
|
-
refs.push(typeof GroupName === "string" && GroupName !== "default" && GroupName !== "" ? { name: Name, group: GroupName } : { name: Name });
|
|
6486
|
-
}
|
|
6487
|
-
return refs;
|
|
6488
|
-
}
|
|
6489
6363
|
function decorateAwsModel(entries, registry2, verdicts) {
|
|
6490
6364
|
if (!registry2 || registry2.length === 0) return [...entries];
|
|
6491
6365
|
const rowById = new Map(registry2.map((r) => [r.id, r]));
|
|
@@ -6960,6 +6834,24 @@ async function fetchDeployFactsBySlug(slug, deps) {
|
|
|
6960
6834
|
return null;
|
|
6961
6835
|
}
|
|
6962
6836
|
}
|
|
6837
|
+
async function fetchScheduleInventory(deps) {
|
|
6838
|
+
try {
|
|
6839
|
+
if (!deps.baseUrl) return null;
|
|
6840
|
+
const token = await deps.token();
|
|
6841
|
+
if (!token) return null;
|
|
6842
|
+
const res = await retriedFetch(deps, `${deps.baseUrl.replace(/\/$/, "")}/schedules/inventory`, {
|
|
6843
|
+
method: "GET",
|
|
6844
|
+
headers: { Authorization: `Bearer ${token}` }
|
|
6845
|
+
});
|
|
6846
|
+
if (!res.ok) return null;
|
|
6847
|
+
const body = await res.json();
|
|
6848
|
+
if (!body || !Array.isArray(body.entries) || !Array.isArray(body.incomplete) || !body.incomplete.every((v) => typeof v === "string") || typeof body.schedulerRead !== "boolean" || !body.schedulerRead && body.incomplete.length === 0) return null;
|
|
6849
|
+
if (!body.entries.every((e) => e && typeof e.name === "string" && typeof e.cadence === "string" && typeof e.executor === "string" && typeof e.source === "string" && e.resolved === "live" && ["yes", "no", "embeddings", "unknown"].includes(e.llm) && (e.scheduleId === void 0 || typeof e.scheduleId === "string") && (e.armedAt === void 0 || typeof e.armedAt === "string"))) return null;
|
|
6850
|
+
return body;
|
|
6851
|
+
} catch {
|
|
6852
|
+
return null;
|
|
6853
|
+
}
|
|
6854
|
+
}
|
|
6963
6855
|
async function fetchSchedulesList(deps) {
|
|
6964
6856
|
if (!deps.baseUrl) return null;
|
|
6965
6857
|
const token = await deps.token();
|
|
@@ -7071,6 +6963,9 @@ async function tenantReconcile(payload, deps) {
|
|
|
7071
6963
|
async function tenantDeploy(payload, deps) {
|
|
7072
6964
|
return postJson("/tenant-deploy", payload, deps, "POST", { noRetry: true, timeoutMs: TENANT_DEPLOY_TIMEOUT_MS });
|
|
7073
6965
|
}
|
|
6966
|
+
async function releaseAnnouncement(payload, deps) {
|
|
6967
|
+
return postJson("/release-announcement", payload, deps, "POST", { noRetry: true, timeoutMs: 3e4 });
|
|
6968
|
+
}
|
|
7074
6969
|
async function actionsCanary(payload, deps) {
|
|
7075
6970
|
return postJson("/actions-canary", payload, deps, "POST", { noRetry: true });
|
|
7076
6971
|
}
|
|
@@ -11324,6 +11219,22 @@ async function collectBoardItems(cfg, options, deps) {
|
|
|
11324
11219
|
after = void 0;
|
|
11325
11220
|
}
|
|
11326
11221
|
} while (after);
|
|
11222
|
+
if (options.activeOnly && nodes.length === 0) {
|
|
11223
|
+
try {
|
|
11224
|
+
const verify = await fetchProjectPage(client, cfg, void 0, void 0);
|
|
11225
|
+
const survivors = (verify.organization?.projectV2?.items.nodes ?? []).filter((node) => !shouldSkipInactiveBoardNode(node, cfg));
|
|
11226
|
+
if (survivors.length) {
|
|
11227
|
+
warnings.push(
|
|
11228
|
+
`partial board read: the active items filter (${ACTIVE_BOARD_ITEMS_FILTER}) returned no rows while ${survivors.length} active item(s) remain on the board \u2014 served by an unfiltered verification scan; GitHub's filtered items query may lag`
|
|
11229
|
+
);
|
|
11230
|
+
partial = true;
|
|
11231
|
+
nodes.push(...survivors);
|
|
11232
|
+
}
|
|
11233
|
+
} catch (e) {
|
|
11234
|
+
warnings.push(`partial board read: the active items filter returned no rows and the unfiltered verification read failed (${e.message}) \u2014 the empty board answer is unverified`);
|
|
11235
|
+
partial = true;
|
|
11236
|
+
}
|
|
11237
|
+
}
|
|
11327
11238
|
const read = nodesToItems(nodes, warnings, cfg);
|
|
11328
11239
|
if (read.failures.length) {
|
|
11329
11240
|
const message2 = `partial board read: ${read.failures.length} item(s) came back truncated and were not read \u2014 ${read.failures.join(" | ")}`;
|
|
@@ -15877,10 +15788,10 @@ var rollout_plan_default = {
|
|
|
15877
15788
|
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)."
|
|
15878
15789
|
},
|
|
15879
15790
|
baseline: {
|
|
15880
|
-
version: "4.3.
|
|
15881
|
-
tag: "v4.3.
|
|
15882
|
-
commit: "
|
|
15883
|
-
npm: "@mutmutco/cli@4.3.
|
|
15791
|
+
version: "4.3.59",
|
|
15792
|
+
tag: "v4.3.59",
|
|
15793
|
+
commit: "0f695d53cba6",
|
|
15794
|
+
npm: "@mutmutco/cli@4.3.59"
|
|
15884
15795
|
},
|
|
15885
15796
|
exitCriterion: "fleet-n-of-n",
|
|
15886
15797
|
hubOnlyShortcut: "forbidden",
|
|
@@ -15897,14 +15808,14 @@ var rollout_plan_default = {
|
|
|
15897
15808
|
repo: "mutmutco/mmi-hub",
|
|
15898
15809
|
role: "canary",
|
|
15899
15810
|
schedule: "train",
|
|
15900
|
-
v3Target: "v4.3.
|
|
15811
|
+
v3Target: "v4.3.59"
|
|
15901
15812
|
}
|
|
15902
15813
|
],
|
|
15903
15814
|
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.",
|
|
15904
15815
|
rollback: {
|
|
15905
15816
|
independent: true,
|
|
15906
|
-
mechanism: "npm dist-tag latest -> 4.3.
|
|
15907
|
-
v3Target: "v4.3.
|
|
15817
|
+
mechanism: "npm dist-tag latest -> 4.3.59 and redeploy the Hub Lambda from tag v4.3.59 (0f695d53cba6); installed clients repair via `mmi-cli doctor`. No other cohort is touched.",
|
|
15818
|
+
v3Target: "v4.3.59 (@mutmutco/cli@4.3.59, tag commit 0f695d53cba6 \u2014 last known-good release carrying the repo-index v4-only contract)"
|
|
15908
15819
|
}
|
|
15909
15820
|
},
|
|
15910
15821
|
{
|
|
@@ -31875,10 +31786,9 @@ var surfaces_default = {
|
|
|
31875
31786
|
certification: "Hermes Agent v0.20.1 release v2026.8.13, upstream f80f453ae0679347e38abc917c7f94f717bf96c5 (#5053)"
|
|
31876
31787
|
},
|
|
31877
31788
|
enforcementCeilings: [
|
|
31878
|
-
"Hermes
|
|
31789
|
+
"MMI ships no Hermes hooks (#5908): the plugin contributes skills and the /mmi command only; enforcement is host-side.",
|
|
31879
31790
|
"Hermes user plugins are opt-in through plugins.enabled; operator consent and host process isolation remain Hermes-owned.",
|
|
31880
|
-
"npm is MMI transport only: MMI-Hub extracts @mutmutco/hermes-plugin into $HERMES_HOME/plugins/mmi and provisions the canonical skills into $HERMES_HOME/skills/mmi/; a fresh Hermes Agent process is required for discovery."
|
|
31881
|
-
"Final assistant output is outside Hermes pre_tool_call hook control."
|
|
31791
|
+
"npm is MMI transport only: MMI-Hub extracts @mutmutco/hermes-plugin into $HERMES_HOME/plugins/mmi and provisions the canonical skills into $HERMES_HOME/skills/mmi/; a fresh Hermes Agent process is required for discovery."
|
|
31882
31792
|
]
|
|
31883
31793
|
}
|
|
31884
31794
|
],
|
|
@@ -35594,15 +35504,9 @@ function writeError(res) {
|
|
|
35594
35504
|
|
|
35595
35505
|
// src/schedules-commands.ts
|
|
35596
35506
|
var import_promises5 = require("node:fs/promises");
|
|
35597
|
-
var import_node_child_process11 = require("node:child_process");
|
|
35598
|
-
var import_node_util6 = require("node:util");
|
|
35599
35507
|
init_clean_exit();
|
|
35600
35508
|
init_github_client();
|
|
35601
35509
|
init_cli_shared();
|
|
35602
|
-
var execFileP4 = (0, import_node_util6.promisify)(import_node_child_process11.execFile);
|
|
35603
|
-
var AWS_REGION = "eu-central-1";
|
|
35604
|
-
var AWS_TIMEOUT_MS = 3e4;
|
|
35605
|
-
var AWS_RETRY_DELAY_MS = 1500;
|
|
35606
35510
|
async function listWorkflows(client, repo) {
|
|
35607
35511
|
const all = [];
|
|
35608
35512
|
for (let page = 1; ; page += 1) {
|
|
@@ -35699,44 +35603,11 @@ async function githubEntries(client) {
|
|
|
35699
35603
|
drift.push(...reconciliation.map(renderDrift));
|
|
35700
35604
|
return { entries, incomplete, drift, reconciliation, readRepos, workflowNames: [...workflows.map((w) => w.name), ...unreadableNames], disabledWorkflowNames };
|
|
35701
35605
|
}
|
|
35702
|
-
async function awsJson(args) {
|
|
35703
|
-
const run = async () => {
|
|
35704
|
-
const { stdout } = await execFileP4("aws", [...args, "--region", AWS_REGION, "--output", "json"], {
|
|
35705
|
-
encoding: "utf8",
|
|
35706
|
-
windowsHide: true,
|
|
35707
|
-
timeout: AWS_TIMEOUT_MS
|
|
35708
|
-
});
|
|
35709
|
-
return JSON.parse(stdout);
|
|
35710
|
-
};
|
|
35711
|
-
try {
|
|
35712
|
-
return await run();
|
|
35713
|
-
} catch {
|
|
35714
|
-
await new Promise((resolve7) => setTimeout(resolve7, AWS_RETRY_DELAY_MS));
|
|
35715
|
-
return run();
|
|
35716
|
-
}
|
|
35717
|
-
}
|
|
35718
35606
|
async function awsEntries() {
|
|
35719
|
-
const
|
|
35720
|
-
|
|
35721
|
-
|
|
35722
|
-
|
|
35723
|
-
} catch (e) {
|
|
35724
|
-
incomplete.push(`aws: events list-rules failed \u2014 ${e.message}`);
|
|
35725
|
-
}
|
|
35726
|
-
let schedulerRead = false;
|
|
35727
|
-
try {
|
|
35728
|
-
const refs = awsScheduleRefs(await awsJson(["scheduler", "list-schedules"]));
|
|
35729
|
-
for (const ref of refs) {
|
|
35730
|
-
const args = ["scheduler", "get-schedule", "--name", ref.name, ...ref.group ? ["--group-name", ref.group] : []];
|
|
35731
|
-
const entry = awsScheduleEntry(await awsJson(args));
|
|
35732
|
-
if (entry) entries.push(entry);
|
|
35733
|
-
}
|
|
35734
|
-
schedulerRead = true;
|
|
35735
|
-
} catch (e) {
|
|
35736
|
-
incomplete.push(`aws: scheduler listing failed \u2014 ${e.message}`);
|
|
35737
|
-
}
|
|
35738
|
-
const reconciliation = unlauncheredLlmDrifts(entries);
|
|
35739
|
-
return { entries, incomplete, drift: reconciliation.map(renderDrift), reconciliation, schedulerRead };
|
|
35607
|
+
const inventory = await fetchScheduleInventory(registryClientDeps(await loadConfig()));
|
|
35608
|
+
if (!inventory) return { entries: [], incomplete: ["aws: Hub schedule inventory unavailable or unauthenticated"], drift: [], reconciliation: [], schedulerRead: false };
|
|
35609
|
+
const reconciliation = unlauncheredLlmDrifts(inventory.entries);
|
|
35610
|
+
return { ...inventory, reconciliation, drift: reconciliation.map(renderDrift) };
|
|
35740
35611
|
}
|
|
35741
35612
|
async function readOrFail(read) {
|
|
35742
35613
|
try {
|
|
@@ -36593,8 +36464,13 @@ async function resolveStageBuildSecrets(input) {
|
|
|
36593
36464
|
out[envKey] = fromVault;
|
|
36594
36465
|
continue;
|
|
36595
36466
|
}
|
|
36467
|
+
const fromGitHub = await input.githubToken?.();
|
|
36468
|
+
if (fromGitHub) {
|
|
36469
|
+
out[envKey] = fromGitHub;
|
|
36470
|
+
continue;
|
|
36471
|
+
}
|
|
36596
36472
|
missing.push(
|
|
36597
|
-
`${envKey}=${GITHUB_PACKAGES_TOKEN_REF} (
|
|
36473
|
+
`${envKey}=${GITHUB_PACKAGES_TOKEN_REF} (sign in with gh auth login using a package-readable GitHub identity, or provide process env ${envKey} or stageless project vault secret ${envKey}; npm.pkg.github.com still requires package read permission)`
|
|
36598
36474
|
);
|
|
36599
36475
|
continue;
|
|
36600
36476
|
}
|
|
@@ -36628,6 +36504,7 @@ async function fetchVaultRef(fetchVault, ref) {
|
|
|
36628
36504
|
}
|
|
36629
36505
|
|
|
36630
36506
|
// src/stage-commands.ts
|
|
36507
|
+
init_github_client();
|
|
36631
36508
|
function registerStageCommands(program3) {
|
|
36632
36509
|
function stagePortFromArgv() {
|
|
36633
36510
|
const raw = rawValue("--port", "");
|
|
@@ -36687,7 +36564,8 @@ function registerStageCommands(program3) {
|
|
|
36687
36564
|
const d = makeSecretsDeps(cfg);
|
|
36688
36565
|
const merge = await resolveStageBuildSecrets({
|
|
36689
36566
|
requiredBuildSecrets: required,
|
|
36690
|
-
fetchVault: (key, opts) => fetchSecretValue(d, key, opts ?? {})
|
|
36567
|
+
fetchVault: (key, opts) => fetchSecretValue(d, key, opts ?? {}),
|
|
36568
|
+
githubToken
|
|
36691
36569
|
});
|
|
36692
36570
|
return Object.keys(merge).length ? merge : void 0;
|
|
36693
36571
|
}
|
|
@@ -37089,7 +36967,7 @@ function renderVerifySecrets(body) {
|
|
|
37089
36967
|
}
|
|
37090
36968
|
|
|
37091
36969
|
// src/command-register-collaboration.ts
|
|
37092
|
-
var
|
|
36970
|
+
var import_node_child_process15 = require("node:child_process");
|
|
37093
36971
|
var import_node_fs41 = require("node:fs");
|
|
37094
36972
|
var import_promises7 = require("node:fs/promises");
|
|
37095
36973
|
init_clean_exit();
|
|
@@ -37475,12 +37353,12 @@ function boardAdvanceFailureMessage(result) {
|
|
|
37475
37353
|
}
|
|
37476
37354
|
|
|
37477
37355
|
// src/test-policy-core.ts
|
|
37478
|
-
var
|
|
37356
|
+
var import_node_child_process12 = require("node:child_process");
|
|
37479
37357
|
var import_node_fs35 = require("node:fs");
|
|
37480
37358
|
var import_node_path33 = require("node:path");
|
|
37481
37359
|
|
|
37482
37360
|
// src/test-command-policy-shared.mjs
|
|
37483
|
-
var
|
|
37361
|
+
var import_node_child_process11 = require("node:child_process");
|
|
37484
37362
|
var TEST_COMMAND_CLASS = "test";
|
|
37485
37363
|
var TRAILER_KEY = "Test-Policy-Override";
|
|
37486
37364
|
var OVERRIDE_RE = /^Test-Policy-Override:\s*(.+)$/im;
|
|
@@ -37597,7 +37475,7 @@ function evaluateTestCommandPolicy({ paths, mandatory, regulated = true, overrid
|
|
|
37597
37475
|
};
|
|
37598
37476
|
}
|
|
37599
37477
|
function git(args, cwd) {
|
|
37600
|
-
return (0,
|
|
37478
|
+
return (0, import_node_child_process11.execFileSync)("git", args, { windowsHide: true, cwd, encoding: "utf8", maxBuffer: 32 * 1024 * 1024 });
|
|
37601
37479
|
}
|
|
37602
37480
|
function parseScope(value) {
|
|
37603
37481
|
const scoped = /^\[([^\]]*)\]\s*([\s\S]*)$/.exec(value);
|
|
@@ -38096,14 +37974,14 @@ function evaluate(changed, policy, present = () => false) {
|
|
|
38096
37974
|
return findings;
|
|
38097
37975
|
}
|
|
38098
37976
|
function git2(args, cwd) {
|
|
38099
|
-
return (0,
|
|
37977
|
+
return (0, import_node_child_process12.execFileSync)("git", args, { windowsHide: true, cwd, encoding: "utf8", maxBuffer: 32 * 1024 * 1024 });
|
|
38100
37978
|
}
|
|
38101
37979
|
var COAUTHOR_KEY = "Co-authored-by";
|
|
38102
37980
|
var GH_MESSAGE_SEPARATOR = /^-{5,}$/;
|
|
38103
37981
|
var LIFTED_KEYS = new RegExp(`^(?:${TRAILER_KEY}|${COAUTHOR_KEY}):`, "i");
|
|
38104
37982
|
function parseTrailers(message2, cwd) {
|
|
38105
37983
|
try {
|
|
38106
|
-
return (0,
|
|
37984
|
+
return (0, import_node_child_process12.execFileSync)("git", ["interpret-trailers", "--parse", "--unfold"], {
|
|
38107
37985
|
windowsHide: true,
|
|
38108
37986
|
cwd,
|
|
38109
37987
|
input: message2,
|
|
@@ -38859,7 +38737,7 @@ function postMergeReconWarnings(input) {
|
|
|
38859
38737
|
}
|
|
38860
38738
|
|
|
38861
38739
|
// src/review-verdict.ts
|
|
38862
|
-
var
|
|
38740
|
+
var import_node_child_process13 = require("node:child_process");
|
|
38863
38741
|
var import_node_fs38 = require("node:fs");
|
|
38864
38742
|
var import_node_os19 = require("node:os");
|
|
38865
38743
|
var import_node_path36 = require("node:path");
|
|
@@ -38959,8 +38837,8 @@ async function checkPrReview(number, repo, head, deps = {
|
|
|
38959
38837
|
}
|
|
38960
38838
|
function computePrPatchId(number, repo) {
|
|
38961
38839
|
return new Promise((resolve7, reject) => {
|
|
38962
|
-
const gh = (0,
|
|
38963
|
-
const git3 = (0,
|
|
38840
|
+
const gh = (0, import_node_child_process13.spawn)("gh", ["pr", "diff", number, "--repo", repo], { windowsHide: true, stdio: ["ignore", "pipe", "pipe"] });
|
|
38841
|
+
const git3 = (0, import_node_child_process13.spawn)("git", ["patch-id", "--stable"], { windowsHide: true, stdio: ["pipe", "pipe", "pipe"] });
|
|
38964
38842
|
let out = "";
|
|
38965
38843
|
let ghErr = "";
|
|
38966
38844
|
let gitErr = "";
|
|
@@ -39042,7 +38920,7 @@ async function postPrCommentFromFile(number, repo, body) {
|
|
|
39042
38920
|
}
|
|
39043
38921
|
|
|
39044
38922
|
// src/pr-create-docs-check.ts
|
|
39045
|
-
var
|
|
38923
|
+
var import_node_child_process14 = require("node:child_process");
|
|
39046
38924
|
init_cli_shared();
|
|
39047
38925
|
var GIT_TIMEOUT_MS2 = 15e3;
|
|
39048
38926
|
function catFileBatch(root, ref, paths) {
|
|
@@ -39050,7 +38928,7 @@ function catFileBatch(root, ref, paths) {
|
|
|
39050
38928
|
return new Promise((resolve7) => {
|
|
39051
38929
|
const chunks = [];
|
|
39052
38930
|
let settled = false;
|
|
39053
|
-
const child2 = (0,
|
|
38931
|
+
const child2 = (0, import_node_child_process14.spawn)("git", ["-C", root, "cat-file", "--batch", "--buffer"], { windowsHide: true });
|
|
39054
38932
|
const finish = () => {
|
|
39055
38933
|
if (settled) return;
|
|
39056
38934
|
settled = true;
|
|
@@ -40197,7 +40075,7 @@ function scheduleRelatedDiscovery(o) {
|
|
|
40197
40075
|
try {
|
|
40198
40076
|
const args = ["issue", "discover-related", "--number", String(o.number), "--title", o.title, "--body", o.body, "--fail-soft"];
|
|
40199
40077
|
if (o.repo) args.push("--repo", o.repo);
|
|
40200
|
-
spawnDetachedSelf(args, { spawn:
|
|
40078
|
+
spawnDetachedSelf(args, { spawn: import_node_child_process15.spawn, execPath: process.execPath, scriptPath: process.argv[1] }, { cwd: process.cwd() });
|
|
40201
40079
|
} catch {
|
|
40202
40080
|
}
|
|
40203
40081
|
}
|
|
@@ -41893,7 +41771,7 @@ ${SSH_RECIPE_AGENT_NOTE}`);
|
|
|
41893
41771
|
}
|
|
41894
41772
|
|
|
41895
41773
|
// src/dist-drift.ts
|
|
41896
|
-
var
|
|
41774
|
+
var import_node_child_process16 = require("node:child_process");
|
|
41897
41775
|
var import_node_crypto13 = require("node:crypto");
|
|
41898
41776
|
var import_node_fs44 = require("node:fs");
|
|
41899
41777
|
var import_node_os20 = require("node:os");
|
|
@@ -42038,7 +41916,7 @@ function bomPathFor(root) {
|
|
|
42038
41916
|
}
|
|
42039
41917
|
}
|
|
42040
41918
|
function rebuildTo(packageRoot, outDir) {
|
|
42041
|
-
(0,
|
|
41919
|
+
(0, import_node_child_process16.execFileSync)(process.execPath, ["build.mjs"], {
|
|
42042
41920
|
cwd: packageRoot,
|
|
42043
41921
|
env: { ...process.env, MMI_DIST_OUTDIR: outDir },
|
|
42044
41922
|
windowsHide: true,
|
|
@@ -42265,7 +42143,7 @@ function registerSchedulesLiftCommand(program3, deps = {}) {
|
|
|
42265
42143
|
}
|
|
42266
42144
|
|
|
42267
42145
|
// src/spawn-policy-core.ts
|
|
42268
|
-
var
|
|
42146
|
+
var import_node_child_process17 = require("node:child_process");
|
|
42269
42147
|
var import_node_fs45 = require("node:fs");
|
|
42270
42148
|
var import_node_path43 = require("node:path");
|
|
42271
42149
|
var SPAWNERS = ["spawn", "spawnSync", "exec", "execSync", "execFile", "execFileSync"];
|
|
@@ -42336,7 +42214,7 @@ function findViolationsInSource(raw) {
|
|
|
42336
42214
|
return found;
|
|
42337
42215
|
}
|
|
42338
42216
|
function policedFiles(root) {
|
|
42339
|
-
const r = (0,
|
|
42217
|
+
const r = (0, import_node_child_process17.spawnSync)("git", ["ls-files", "-z", "--cached", "--others", "--exclude-standard"], {
|
|
42340
42218
|
cwd: root,
|
|
42341
42219
|
encoding: "utf8",
|
|
42342
42220
|
windowsHide: true,
|
|
@@ -42642,50 +42520,6 @@ init_house_map();
|
|
|
42642
42520
|
// src/hotfix-apply.ts
|
|
42643
42521
|
var import_promises9 = require("node:fs/promises");
|
|
42644
42522
|
|
|
42645
|
-
// src/slack-alert.ts
|
|
42646
|
-
var SSM_REGION = "eu-central-1";
|
|
42647
|
-
var SSM_TOKEN_PARAM = "/mmi-future/_org/slack/SLACK_BOT_TOKEN";
|
|
42648
|
-
var SSM_CHANNEL_PARAM = "/mmi-future/_org/slack/SLACK_ALERTS_CHANNEL";
|
|
42649
|
-
var SLACK_TIMEOUT_MS = 1e4;
|
|
42650
|
-
async function readSsmParameter(deps, name, decrypt) {
|
|
42651
|
-
const args = [
|
|
42652
|
-
"ssm",
|
|
42653
|
-
"get-parameter",
|
|
42654
|
-
"--region",
|
|
42655
|
-
SSM_REGION,
|
|
42656
|
-
"--name",
|
|
42657
|
-
name,
|
|
42658
|
-
"--query",
|
|
42659
|
-
"Parameter.Value",
|
|
42660
|
-
"--output",
|
|
42661
|
-
"text",
|
|
42662
|
-
...decrypt ? ["--with-decryption"] : []
|
|
42663
|
-
];
|
|
42664
|
-
const value = (await deps.run("aws", args)).trim();
|
|
42665
|
-
if (!value || value === "None") throw new Error(`SSM parameter ${name} is empty`);
|
|
42666
|
-
return value;
|
|
42667
|
-
}
|
|
42668
|
-
async function postToChannel(deps, channel, text) {
|
|
42669
|
-
const resolved = channel.trim();
|
|
42670
|
-
if (!resolved || resolved === "None") throw new Error("no Slack channel resolved");
|
|
42671
|
-
const token = await readSsmParameter(deps, SSM_TOKEN_PARAM, true);
|
|
42672
|
-
const fetchImpl = deps.fetchImpl ?? fetch;
|
|
42673
|
-
const res = await fetchImpl("https://slack.com/api/chat.postMessage", {
|
|
42674
|
-
method: "POST",
|
|
42675
|
-
headers: { Authorization: `Bearer ${token}`, "Content-Type": "application/json; charset=utf-8" },
|
|
42676
|
-
body: JSON.stringify({ channel: resolved, text, unfurl_links: false }),
|
|
42677
|
-
signal: AbortSignal.timeout(SLACK_TIMEOUT_MS)
|
|
42678
|
-
});
|
|
42679
|
-
const json = await res.json().catch(() => ({}));
|
|
42680
|
-
if (!json.ok) throw new Error(`slack postMessage failed: ${json.error ?? `http ${res.status}`}`);
|
|
42681
|
-
return { status: "posted", note: "posted" };
|
|
42682
|
-
}
|
|
42683
|
-
async function postToAlertsChannel(deps, text) {
|
|
42684
|
-
const channel = await readSsmParameter(deps, SSM_CHANNEL_PARAM, false);
|
|
42685
|
-
await postToChannel(deps, channel, text);
|
|
42686
|
-
return { status: "posted", note: "posted to the alerts channel" };
|
|
42687
|
-
}
|
|
42688
|
-
|
|
42689
42523
|
// src/release-announce.ts
|
|
42690
42524
|
var ANNOUNCE_REPO = "mutmutco/MMI-Hub";
|
|
42691
42525
|
var MAX_BULLETS = 6;
|
|
@@ -42792,12 +42626,6 @@ async function announceRelease(deps, args) {
|
|
|
42792
42626
|
if (args.summaryFile) {
|
|
42793
42627
|
if (!deps.readFile) throw new Error("summary file given but deps.readFile is missing");
|
|
42794
42628
|
lines2 = summaryFileLines(await deps.readFile(args.summaryFile), neutralize);
|
|
42795
|
-
if (deps.removeFile) {
|
|
42796
|
-
try {
|
|
42797
|
-
await deps.removeFile(args.summaryFile);
|
|
42798
|
-
} catch {
|
|
42799
|
-
}
|
|
42800
|
-
}
|
|
42801
42629
|
}
|
|
42802
42630
|
if (lines2.length === 0) {
|
|
42803
42631
|
if (target.kind !== "alerts") {
|
|
@@ -42813,12 +42641,16 @@ async function announceRelease(deps, args) {
|
|
|
42813
42641
|
releaseUrl,
|
|
42814
42642
|
...target.kind === "channel" ? { language: target.language } : {}
|
|
42815
42643
|
});
|
|
42816
|
-
|
|
42817
|
-
|
|
42818
|
-
|
|
42644
|
+
const delivery = await deps.postAnnouncement({ repo: args.repo, tag: args.tag, text });
|
|
42645
|
+
if (delivery === "skipped") return { status: "skipped", note: missingChannelNote(args.repo) };
|
|
42646
|
+
if (args.summaryFile && deps.removeFile) {
|
|
42647
|
+
try {
|
|
42648
|
+
await deps.removeFile(args.summaryFile);
|
|
42649
|
+
} catch {
|
|
42650
|
+
}
|
|
42819
42651
|
}
|
|
42820
|
-
|
|
42821
|
-
return { status: "announced", note:
|
|
42652
|
+
const destination = target.kind === "alerts" ? "alerts channel" : "project release channel";
|
|
42653
|
+
return { status: "announced", note: `${delivery === "already-posted" ? "already announced" : "announced"} ${args.tag} to the ${destination}` };
|
|
42822
42654
|
} catch (e) {
|
|
42823
42655
|
return { status: "failed", note: `announce failed (release unaffected): ${e.message}` };
|
|
42824
42656
|
}
|
|
@@ -43945,12 +43777,12 @@ async function findInFlightHotfixVersion(deps, ctx, latestMainTag, workflows = H
|
|
|
43945
43777
|
}
|
|
43946
43778
|
|
|
43947
43779
|
// src/hotfix-coverage.ts
|
|
43948
|
-
var
|
|
43780
|
+
var import_node_child_process18 = require("node:child_process");
|
|
43949
43781
|
var CHERRY_TRAILER = /\(cherry picked from commit ([0-9a-f]{7,40})\)/g;
|
|
43950
43782
|
function checkHotfixCoverage(options = {}) {
|
|
43951
43783
|
const { cwd = process.cwd(), mainRef = "origin/main", rcRef = "origin/rc", manifestPaths = [] } = options;
|
|
43952
43784
|
const ack = (options.ack ?? []).filter(Boolean);
|
|
43953
|
-
const git3 = options.git ?? ((args, opts) => (0,
|
|
43785
|
+
const git3 = options.git ?? ((args, opts) => (0, import_node_child_process18.execFileSync)("git", args, { cwd, encoding: "utf8", input: opts?.input, stdio: ["pipe", "pipe", "pipe"] }));
|
|
43954
43786
|
const revList = (range) => {
|
|
43955
43787
|
const out = git3(["rev-list", "--no-merges", range]).trim();
|
|
43956
43788
|
return out ? out.split("\n") : [];
|
|
@@ -44018,7 +43850,7 @@ function checkHotfixCoverage(options = {}) {
|
|
|
44018
43850
|
}
|
|
44019
43851
|
function checkHotfixCarries(options) {
|
|
44020
43852
|
const { cwd = process.cwd(), branch, baseRef, targets } = options;
|
|
44021
|
-
const git3 = options.git ?? ((args, opts) => (0,
|
|
43853
|
+
const git3 = options.git ?? ((args, opts) => (0, import_node_child_process18.execFileSync)("git", args, { cwd, encoding: "utf8", input: opts?.input, stdio: ["pipe", "pipe", "pipe"] }));
|
|
44022
43854
|
const isAncestor = (sha, ref) => {
|
|
44023
43855
|
try {
|
|
44024
43856
|
git3(["merge-base", "--is-ancestor", sha, ref]);
|
|
@@ -44288,6 +44120,15 @@ function trainApplyDeps() {
|
|
|
44288
44120
|
// registry releaseChannel META for a product repo — best-effort inside announceRelease itself.
|
|
44289
44121
|
announce: (args) => announceRelease({
|
|
44290
44122
|
run: async (file, cmdArgs) => (await execFileP(file, cmdArgs, { timeout: GH_TRAIN_TIMEOUT_MS })).stdout,
|
|
44123
|
+
postAnnouncement: async (payload) => {
|
|
44124
|
+
const res = await releaseAnnouncement(payload, registryClientDeps(await loadConfig()));
|
|
44125
|
+
const body = res.body;
|
|
44126
|
+
if (!res.ok) throw new Error(body?.error ?? `Hub announcement failed (HTTP ${res.status}); verify delivery before retrying`);
|
|
44127
|
+
if (body?.ok !== true || body.status !== "posted" && body?.status !== "already-posted" && body?.status !== "skipped") {
|
|
44128
|
+
throw new Error("Hub announcement returned an unverified delivery result; do not resend");
|
|
44129
|
+
}
|
|
44130
|
+
return body.status;
|
|
44131
|
+
},
|
|
44291
44132
|
readFile: (path2) => (0, import_promises10.readFile)(path2, "utf8"),
|
|
44292
44133
|
removeFile: (path2) => (0, import_promises10.unlink)(path2),
|
|
44293
44134
|
// #6521/#6523: the project's own release channel AND releaseLanguage, read from registry META in ONE
|
package/package.json
CHANGED