@mutmutco/cli 4.4.9 → 4.4.11
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 +122 -163
- package/package.json +1 -1
package/dist/main.cjs
CHANGED
|
@@ -15938,10 +15938,10 @@ var rollout_plan_default = {
|
|
|
15938
15938
|
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)."
|
|
15939
15939
|
},
|
|
15940
15940
|
baseline: {
|
|
15941
|
-
version: "4.4.
|
|
15942
|
-
tag: "v4.4.
|
|
15943
|
-
commit: "
|
|
15944
|
-
npm: "@mutmutco/cli@4.4.
|
|
15941
|
+
version: "4.4.11",
|
|
15942
|
+
tag: "v4.4.11",
|
|
15943
|
+
commit: "47113a5df32d",
|
|
15944
|
+
npm: "@mutmutco/cli@4.4.11"
|
|
15945
15945
|
},
|
|
15946
15946
|
exitCriterion: "fleet-n-of-n",
|
|
15947
15947
|
hubOnlyShortcut: "forbidden",
|
|
@@ -15958,14 +15958,14 @@ var rollout_plan_default = {
|
|
|
15958
15958
|
repo: "mutmutco/mmi-hub",
|
|
15959
15959
|
role: "canary",
|
|
15960
15960
|
schedule: "train",
|
|
15961
|
-
v3Target: "v4.4.
|
|
15961
|
+
v3Target: "v4.4.11"
|
|
15962
15962
|
}
|
|
15963
15963
|
],
|
|
15964
15964
|
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.",
|
|
15965
15965
|
rollback: {
|
|
15966
15966
|
independent: true,
|
|
15967
|
-
mechanism: "npm dist-tag latest -> 4.4.
|
|
15968
|
-
v3Target: "v4.4.
|
|
15967
|
+
mechanism: "npm dist-tag latest -> 4.4.11 and redeploy the Hub Lambda from tag v4.4.11 (47113a5df32d); installed clients repair via `mmi-cli doctor`. No other cohort is touched.",
|
|
15968
|
+
v3Target: "v4.4.11 (@mutmutco/cli@4.4.11, tag commit 47113a5df32d \u2014 last known-good release carrying the repo-index v4-only contract)"
|
|
15969
15969
|
}
|
|
15970
15970
|
},
|
|
15971
15971
|
{
|
|
@@ -18235,7 +18235,7 @@ async function correlateRun(deps, args) {
|
|
|
18235
18235
|
});
|
|
18236
18236
|
const tokens2 = args.mode === "dispatch" ? args.titleIncludes : void 0;
|
|
18237
18237
|
const titleMatch = tokens2 && tokens2.length ? candidates.find((c) => tokens2.every((t) => (c.row.displayTitle ?? "").includes(t))) : void 0;
|
|
18238
|
-
const match = titleMatch ?? (windowProvenWhole ? candidates[0] : void 0);
|
|
18238
|
+
const match = titleMatch ?? (args.mode === "workflow" || windowProvenWhole ? candidates[0] : void 0);
|
|
18239
18239
|
if (match) return { runId: match.row.databaseId, runUrl: match.row.url, read: "found" };
|
|
18240
18240
|
if (!windowProvenWhole) truncatedWindow = true;
|
|
18241
18241
|
}
|
|
@@ -18256,9 +18256,6 @@ async function correlateRun(deps, args) {
|
|
|
18256
18256
|
function correlateTenantRun(deps, since, titleIncludes) {
|
|
18257
18257
|
return correlateRun(deps, { workflow: "tenant-deploy.yml", since, mode: "dispatch", titleIncludes });
|
|
18258
18258
|
}
|
|
18259
|
-
function correlatePublishRun(deps, since, titleIncludes) {
|
|
18260
|
-
return correlateRun(deps, { workflow: "tenant-publish.yml", since, mode: "dispatch", titleIncludes });
|
|
18261
|
-
}
|
|
18262
18259
|
function correlateGetPublishRun(deps, since, product) {
|
|
18263
18260
|
return correlateRun(deps, { workflow: "get-publish.yml", since, mode: "dispatch", titleIncludes: [product] });
|
|
18264
18261
|
}
|
|
@@ -18877,134 +18874,19 @@ async function dispatchTenantDeployWithRetry(deps, input) {
|
|
|
18877
18874
|
}
|
|
18878
18875
|
}
|
|
18879
18876
|
}
|
|
18880
|
-
function
|
|
18881
|
-
const parts = [
|
|
18882
|
-
`gh workflow run tenant-publish.yml --repo ${HUB_REPO2}`,
|
|
18883
|
-
`-f slug=${slug}`,
|
|
18884
|
-
`-f repo=${repo}`,
|
|
18885
|
-
`-f ref=${ref}`,
|
|
18886
|
-
`-f stage=${stage}`
|
|
18887
|
-
];
|
|
18888
|
-
if (publishDir && publishDir !== ".") parts.push(`-f publishDir=${publishDir}`);
|
|
18889
|
-
return parts.join(" ");
|
|
18890
|
-
}
|
|
18891
|
-
var PUBLISH_CONFLICT_SIGNAL = /E409|cannot publish over|previously published|\b(?:HTTP|status|code)\s*[:=]?\s*409\b|\b409\s+Conflict\b/i;
|
|
18892
|
-
var PUBLISH_LOG_RETRY_ATTEMPTS = 4;
|
|
18893
|
-
var PUBLISH_LOG_RETRY_DELAY_MS = 6e3;
|
|
18894
|
-
function publishRegistryTarget(meta, repo, publishRef) {
|
|
18895
|
-
const version = publishRef.replace(/^v/, "");
|
|
18896
|
-
if (!/^\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?$/.test(version)) return void 0;
|
|
18897
|
-
try {
|
|
18898
|
-
return { name: resolveReleaseAbortNpmPackage(meta, repo), version };
|
|
18899
|
-
} catch {
|
|
18900
|
-
return void 0;
|
|
18901
|
-
}
|
|
18902
|
-
}
|
|
18903
|
-
async function provePublishedVersion(deps, target) {
|
|
18904
|
-
try {
|
|
18905
|
-
return clean2(await deps.run("npm", ["view", `${target.name}@${target.version}`, "version"])) === target.version;
|
|
18906
|
-
} catch {
|
|
18907
|
-
return false;
|
|
18908
|
-
}
|
|
18909
|
-
}
|
|
18910
|
-
function publishReconcileFailureNote(input) {
|
|
18911
|
-
if (input.signal && input.target) {
|
|
18912
|
-
return `run FAILED and its log shows a publish conflict (${input.signal}) but the registry does not report ${input.target.name}@${input.target.version} live \u2014 the failure stands (verify with an authenticated registry read, never a bare npm view \u2014 see docs/Guides/train-troubleshooting.md#publish-private-package)`;
|
|
18913
|
-
}
|
|
18914
|
-
if (input.signal) {
|
|
18915
|
-
return `run FAILED and its log shows a publish conflict (${input.signal}) but no npm package name could be resolved to prove the exact version live \u2014 the failure stands`;
|
|
18916
|
-
}
|
|
18917
|
-
if (input.readError) {
|
|
18918
|
-
return `run FAILED and its log could not be read (${input.readError}) \u2014 the failure stands`;
|
|
18919
|
-
}
|
|
18920
|
-
return 'run FAILED and its log shows no publish-conflict signal (E409, "cannot publish over", "previously published", or a 409 status) \u2014 the failure stands';
|
|
18921
|
-
}
|
|
18922
|
-
async function reconcilePublishFailure(deps, runId, target) {
|
|
18923
|
-
if (runId == null) {
|
|
18924
|
-
return { status: "failure", note: "the failed publish run had no run id to re-read \u2014 the failure stands" };
|
|
18925
|
-
}
|
|
18926
|
-
const sleep2 = resolveSleep(deps);
|
|
18927
|
-
let signal;
|
|
18928
|
-
let readError;
|
|
18929
|
-
for (let attempt = 0; attempt < PUBLISH_LOG_RETRY_ATTEMPTS; attempt++) {
|
|
18930
|
-
if (attempt > 0) await sleep2(PUBLISH_LOG_RETRY_DELAY_MS);
|
|
18931
|
-
const log = await fetchControlRunLog(deps, runId);
|
|
18932
|
-
if (!log.ok) {
|
|
18933
|
-
readError = log.error;
|
|
18934
|
-
continue;
|
|
18935
|
-
}
|
|
18936
|
-
const match = log.log.match(PUBLISH_CONFLICT_SIGNAL);
|
|
18937
|
-
if (!match) continue;
|
|
18938
|
-
signal = match[0];
|
|
18939
|
-
if (target && await provePublishedVersion(deps, target)) {
|
|
18940
|
-
return {
|
|
18941
|
-
status: "success",
|
|
18942
|
-
note: `registry reports ${target.name}@${target.version} live; run failed with a publish conflict (${signal}) \u2014 #2428/#6777`
|
|
18943
|
-
};
|
|
18944
|
-
}
|
|
18945
|
-
}
|
|
18946
|
-
return { status: "failure", note: publishReconcileFailureNote({ signal, readError, target }) };
|
|
18947
|
-
}
|
|
18948
|
-
async function dispatchTenantPublish(deps, ctx, stage, ref, watch, dispatchFailure = "throw", publishDir, publishTarget) {
|
|
18949
|
-
deps.warn?.("Release: Starting package publishing");
|
|
18950
|
-
const since = (deps.now ?? Date.now)();
|
|
18951
|
-
const dispatchArgs = [
|
|
18952
|
-
"workflow",
|
|
18953
|
-
"run",
|
|
18954
|
-
"tenant-publish.yml",
|
|
18955
|
-
"--repo",
|
|
18956
|
-
HUB_REPO2,
|
|
18957
|
-
"-f",
|
|
18958
|
-
`slug=${ctx.slug}`,
|
|
18959
|
-
"-f",
|
|
18960
|
-
`repo=${ctx.repo}`,
|
|
18961
|
-
"-f",
|
|
18962
|
-
`ref=${ref}`,
|
|
18963
|
-
"-f",
|
|
18964
|
-
`stage=${stage}`
|
|
18965
|
-
];
|
|
18966
|
-
if (publishDir && publishDir !== ".") dispatchArgs.push("-f", `publishDir=${publishDir}`);
|
|
18967
|
-
try {
|
|
18968
|
-
await deps.run("gh", dispatchArgs);
|
|
18969
|
-
} catch (e) {
|
|
18970
|
-
if (dispatchFailure === "throw") throw e;
|
|
18971
|
-
const msg = e instanceof Error ? e.message : String(e);
|
|
18972
|
-
const recovery = tenantPublishRecoveryCommand(ctx.slug, ctx.repo, ref, stage, publishDir);
|
|
18973
|
-
return {
|
|
18974
|
-
note: `tenant-publish dispatch FAILED: ${msg}. The promotion itself landed \u2014 recover with \`${recovery}\``,
|
|
18975
|
-
deployStatus: "failure"
|
|
18976
|
-
};
|
|
18977
|
-
}
|
|
18978
|
-
const correlated = await correlatePublishRun(deps, since, [ctx.slug, stage]);
|
|
18979
|
-
if (correlated.read === "failed") {
|
|
18980
|
-
return {
|
|
18981
|
-
note: `tenant-publish dispatched (slug=${ctx.slug}, ref=${ref}, stage=${stage}) but its run could not be READ: ${correlated.error}. The promotion itself landed \u2014 check the Actions tab, and if the publish never ran, recover with \`${tenantPublishRecoveryCommand(ctx.slug, ctx.repo, ref, stage, publishDir)}\``,
|
|
18982
|
-
deployStatus: "failure"
|
|
18983
|
-
};
|
|
18984
|
-
}
|
|
18985
|
-
const { runId, runUrl } = correlated;
|
|
18986
|
-
let deployStatus = watch ? await watchTenantRun(deps, runId) : "pending";
|
|
18987
|
-
let note = `dispatched tenant-publish.yml (slug=${ctx.slug}, ref=${ref}, stage=${stage})`;
|
|
18988
|
-
if (deployStatus === "failure") {
|
|
18989
|
-
const reconciled = await reconcilePublishFailure(deps, runId, publishTarget);
|
|
18990
|
-
deployStatus = reconciled.status;
|
|
18991
|
-
note = `${note}; ${reconciled.note}`;
|
|
18992
|
-
}
|
|
18993
|
-
return { note, runId, runUrl, deployStatus };
|
|
18994
|
-
}
|
|
18995
|
-
async function dispatchPublishIfRequired(deps, ctx, meta, model, stage, publishRef, watch, dispatchFailure) {
|
|
18877
|
+
async function observePublishIfRequired(deps, ctx, meta, model, stage, releaseSha, watch) {
|
|
18996
18878
|
if (!meta.publishRequired || stage !== "main") return null;
|
|
18997
18879
|
if (model !== "tenant-container" && model !== "solo-container") return null;
|
|
18998
|
-
|
|
18999
|
-
|
|
19000
|
-
|
|
19001
|
-
|
|
19002
|
-
|
|
19003
|
-
|
|
19004
|
-
|
|
19005
|
-
|
|
19006
|
-
|
|
19007
|
-
|
|
18880
|
+
const target = { workflow: "publish.yml", event: "release" };
|
|
18881
|
+
const workflowRuns = watch ? await watchOwnWorkflowRuns(deps, ctx.repo, [target], 0, releaseSha) : [await listTargetRun(deps, ctx.repo, target, releaseSha)];
|
|
18882
|
+
const primary = workflowRuns[0];
|
|
18883
|
+
return {
|
|
18884
|
+
note: `observed ${ctx.repo} release-triggered publish.yml for ${releaseSha}`,
|
|
18885
|
+
runId: primary?.runId,
|
|
18886
|
+
runUrl: primary?.runUrl,
|
|
18887
|
+
workflowRuns,
|
|
18888
|
+
deployStatus: aggregateWorkflowRuns(workflowRuns)
|
|
18889
|
+
};
|
|
19008
18890
|
}
|
|
19009
18891
|
function appendPublishDispatch(deploy, publish) {
|
|
19010
18892
|
if (!publish) return deploy;
|
|
@@ -19012,7 +18894,7 @@ function appendPublishDispatch(deploy, publish) {
|
|
|
19012
18894
|
note: `${deploy.note}; ${publish.note}`,
|
|
19013
18895
|
runId: deploy.runId,
|
|
19014
18896
|
runUrl: deploy.runUrl,
|
|
19015
|
-
workflowRuns: [...deploy.workflowRuns ?? [], ...publish.workflowRuns ?? [{ workflow: "
|
|
18897
|
+
workflowRuns: [...deploy.workflowRuns ?? [], ...publish.workflowRuns ?? [{ workflow: "publish.yml", runId: publish.runId, runUrl: publish.runUrl, conclusion: publish.deployStatus }]],
|
|
19016
18898
|
deployStatus: deploy.deployStatus === "failure" || publish.deployStatus === "failure" ? "failure" : deploy.deployStatus === "pending" || publish.deployStatus === "pending" ? "pending" : "success"
|
|
19017
18899
|
};
|
|
19018
18900
|
}
|
|
@@ -19020,6 +18902,11 @@ var HUB_SERVED_PRODUCT = "mmi";
|
|
|
19020
18902
|
function getPublishDispatchCommand(repo, product = HUB_SERVED_PRODUCT) {
|
|
19021
18903
|
return `gh workflow run get-publish.yml --repo ${repo} --ref main -f product=${product}`;
|
|
19022
18904
|
}
|
|
18905
|
+
var HUB_GET_SLUG = "mmi-get";
|
|
18906
|
+
var HUB_GET_STAGE = "main";
|
|
18907
|
+
function mmiGetRedeployCommand(repo) {
|
|
18908
|
+
return `gh workflow run tenant-deploy.yml --repo ${repo} --ref main -f slug=${HUB_GET_SLUG} -f repo=${repo} -f ref=${HUB_GET_STAGE} -f stage=${HUB_GET_STAGE}`;
|
|
18909
|
+
}
|
|
19023
18910
|
function readLocalLauncherVersion(root = process.cwd()) {
|
|
19024
18911
|
try {
|
|
19025
18912
|
const raw = (0, import_node_fs19.readFileSync)((0, import_node_path17.join)(root, "installer", "launcher", "package.json"), "utf8");
|
|
@@ -19051,6 +18938,69 @@ async function fetchServedChannelVersion(url, fetchImpl = fetch) {
|
|
|
19051
18938
|
return { ok: false, error: e instanceof Error ? e.message : String(e) };
|
|
19052
18939
|
}
|
|
19053
18940
|
}
|
|
18941
|
+
async function appendMmiGetRedeploy(deps, input, dispatch) {
|
|
18942
|
+
if (!isHubControlRepo(input.repo)) return dispatch;
|
|
18943
|
+
const remedy = mmiGetRedeployCommand(input.repo);
|
|
18944
|
+
const withNote = (note, deployStatus) => ({
|
|
18945
|
+
...dispatch,
|
|
18946
|
+
note: `${dispatch.note}; ${note}`,
|
|
18947
|
+
...deployStatus ? { deployStatus } : {}
|
|
18948
|
+
});
|
|
18949
|
+
if (input.publishStatus !== "success") {
|
|
18950
|
+
return withNote(`mmi-get box NOT redeployed (publish did not succeed) \u2014 after the publish is green, run \`${remedy}\``);
|
|
18951
|
+
}
|
|
18952
|
+
const since = (deps.now ?? Date.now)();
|
|
18953
|
+
try {
|
|
18954
|
+
await deps.run("gh", [
|
|
18955
|
+
"workflow",
|
|
18956
|
+
"run",
|
|
18957
|
+
"tenant-deploy.yml",
|
|
18958
|
+
"--repo",
|
|
18959
|
+
input.repo,
|
|
18960
|
+
"--ref",
|
|
18961
|
+
"main",
|
|
18962
|
+
"-f",
|
|
18963
|
+
`slug=${HUB_GET_SLUG}`,
|
|
18964
|
+
"-f",
|
|
18965
|
+
`repo=${input.repo}`,
|
|
18966
|
+
"-f",
|
|
18967
|
+
`ref=${HUB_GET_STAGE}`,
|
|
18968
|
+
"-f",
|
|
18969
|
+
`stage=${HUB_GET_STAGE}`
|
|
18970
|
+
]);
|
|
18971
|
+
} catch (e) {
|
|
18972
|
+
const msg = e instanceof Error ? e.message : String(e);
|
|
18973
|
+
return withNote(`tenant-deploy dispatch FAILED: ${msg}. The release itself landed, but the MMI-GET BOX WAS NOT REDEPLOYED \u2014 recover with \`${remedy}\``, "failure");
|
|
18974
|
+
}
|
|
18975
|
+
const correlated = await correlateTenantRun(deps, since, [HUB_GET_SLUG, HUB_GET_STAGE]);
|
|
18976
|
+
if (correlated.read === "failed" || correlated.read === "absent") {
|
|
18977
|
+
const why = correlated.read === "failed" ? `its run could not be READ: ${correlated.error}` : "no matching run appeared";
|
|
18978
|
+
return withNote(`tenant-deploy dispatched (slug=${HUB_GET_SLUG}, stage=${HUB_GET_STAGE}) but ${why}. Check the Actions tab; if it never ran, recover with \`${remedy}\``, "failure");
|
|
18979
|
+
}
|
|
18980
|
+
const { runId, runUrl } = correlated;
|
|
18981
|
+
const runRow = { workflow: "tenant-deploy.yml", ...runId ? { runId } : {}, ...runUrl ? { runUrl } : {} };
|
|
18982
|
+
if (!input.watch) {
|
|
18983
|
+
return {
|
|
18984
|
+
...dispatch,
|
|
18985
|
+
note: `${dispatch.note}; dispatched tenant-deploy.yml (slug=${HUB_GET_SLUG}, ref=${HUB_GET_STAGE}, stage=${HUB_GET_STAGE}) \u2014 NOT watched, so the mmi-get box is not yet proven redeployed`,
|
|
18986
|
+
workflowRuns: [...dispatch.workflowRuns ?? [], { ...runRow, conclusion: "pending" }]
|
|
18987
|
+
};
|
|
18988
|
+
}
|
|
18989
|
+
const runStatus = await watchTenantRun(deps, runId, input.repo);
|
|
18990
|
+
if (runStatus !== "success") {
|
|
18991
|
+
return {
|
|
18992
|
+
...dispatch,
|
|
18993
|
+
note: `${dispatch.note}; tenant-deploy.yml ${runStatus} \u2014 the MMI-GET BOX WAS NOT REDEPLOYED; recover with \`${remedy}\``,
|
|
18994
|
+
workflowRuns: [...dispatch.workflowRuns ?? [], { ...runRow, conclusion: runStatus }],
|
|
18995
|
+
deployStatus: "failure"
|
|
18996
|
+
};
|
|
18997
|
+
}
|
|
18998
|
+
return {
|
|
18999
|
+
...dispatch,
|
|
19000
|
+
note: `${dispatch.note}; mmi-get box redeployed (tenant-deploy.yml slug=${HUB_GET_SLUG} stage=${HUB_GET_STAGE})`,
|
|
19001
|
+
workflowRuns: [...dispatch.workflowRuns ?? [], { ...runRow, conclusion: "success" }]
|
|
19002
|
+
};
|
|
19003
|
+
}
|
|
19054
19004
|
async function appendServedChannelPublish(deps, input, dispatch) {
|
|
19055
19005
|
if (!isHubControlRepo(input.repo)) return dispatch;
|
|
19056
19006
|
const channelUrl = input.channelUrl ?? readServedChannelUrl();
|
|
@@ -19118,9 +19068,16 @@ async function appendServedChannelPublish(deps, input, dispatch) {
|
|
|
19118
19068
|
deployStatus: "failure"
|
|
19119
19069
|
};
|
|
19120
19070
|
}
|
|
19071
|
+
if (!expected) {
|
|
19072
|
+
return {
|
|
19073
|
+
...dispatch,
|
|
19074
|
+
note: `${dispatch.note}; get-publish.yml succeeded and ${channelUrl} reports ${probe.version}, but the local launcher version could not be read \u2014 nothing was compared, so the move is unverified`,
|
|
19075
|
+
workflowRuns: runs
|
|
19076
|
+
};
|
|
19077
|
+
}
|
|
19121
19078
|
return {
|
|
19122
19079
|
...dispatch,
|
|
19123
|
-
note: `${dispatch.note}; served channel moved \u2014 ${channelUrl} now reports ${probe.version}
|
|
19080
|
+
note: `${dispatch.note}; served channel moved \u2014 ${channelUrl} now reports ${probe.version}`,
|
|
19124
19081
|
workflowRuns: runs
|
|
19125
19082
|
};
|
|
19126
19083
|
}
|
|
@@ -21505,7 +21462,8 @@ function publishPhaseInput(model, dispatch, publishDispatch, publishRequired, op
|
|
|
21505
21462
|
const sha = opts.releaseSha;
|
|
21506
21463
|
const publishRow = publishDispatch ? {
|
|
21507
21464
|
state: publishDispatch.deployStatus === "success" ? "complete" : publishDispatch.deployStatus === "failure" ? "failed" : "pending",
|
|
21508
|
-
...
|
|
21465
|
+
...sha ? { sha } : {},
|
|
21466
|
+
...runMetadata({ runId: publishDispatch.runId, runUrl: publishDispatch.runUrl, workflow: "publish.yml", event: "release" }, opts.repo ?? "", "sha"),
|
|
21509
21467
|
note: publishDispatch.note
|
|
21510
21468
|
} : void 0;
|
|
21511
21469
|
switch (model) {
|
|
@@ -23645,29 +23603,28 @@ ${recovery.note}`), recoveryInput);
|
|
|
23645
23603
|
await recordPhase(ledger, deps, ledgerAnchors, "deploy", deployLeg, {
|
|
23646
23604
|
landed: "the immutable tag, the green required-check wall, the origin/main fast-forward, and the verified GitHub Release"
|
|
23647
23605
|
});
|
|
23648
|
-
const publishDispatch0 =
|
|
23606
|
+
const publishDispatch0 = await observePublishIfRequired(deps, ctx, meta, deployModel, "main", releaseSha, watch);
|
|
23649
23607
|
const publishDispatch = publishDispatch0 ? await recoverFailedDispatchPhase(
|
|
23650
23608
|
deps,
|
|
23651
23609
|
ledger,
|
|
23652
23610
|
ledgerAnchors,
|
|
23653
23611
|
"publish",
|
|
23654
23612
|
publishDispatch0,
|
|
23655
|
-
{ repo:
|
|
23613
|
+
{ repo: ctx.repo, sha: releaseSha, watched: false, workflow: "publish.yml" }
|
|
23656
23614
|
) : null;
|
|
23657
|
-
let publishSkipNote;
|
|
23658
|
-
if (!publishDispatch && deployDispatch.deployStatus !== "success" && meta.publishRequired && (deployModel === "tenant-container" || deployModel === "solo-container")) {
|
|
23659
|
-
publishSkipNote = deployDispatch.deployStatus === "failure" ? "box deploy failed - redeploy the box before publishing" : "box deploy not confirmed (run with --watch) - publish after the box deploy lands";
|
|
23660
|
-
}
|
|
23661
23615
|
const publishLeg = phaseEntry(publishPhaseInput(deployModel, deployDispatch, publishDispatch, meta.publishRequired === true, {
|
|
23662
23616
|
releaseSha,
|
|
23663
|
-
repo: ctx.repo
|
|
23664
|
-
...publishSkipNote !== void 0 ? { skipPublishNote: publishSkipNote } : {}
|
|
23617
|
+
repo: ctx.repo
|
|
23665
23618
|
}));
|
|
23666
23619
|
await recordPhase(ledger, deps, ledgerAnchors, "publish", publishLeg, {
|
|
23667
23620
|
landed: "the immutable tag, the green required-check wall, origin/main, the verified GitHub Release, and the dispatched deploy path"
|
|
23668
23621
|
});
|
|
23669
23622
|
let dispatch = appendPublishDispatch(deployDispatch, publishDispatch);
|
|
23670
|
-
|
|
23623
|
+
dispatch = await appendMmiGetRedeploy(
|
|
23624
|
+
deps,
|
|
23625
|
+
{ repo: ctx.repo, publishStatus: publishLeg.state === "complete" ? "success" : "failure", watch },
|
|
23626
|
+
dispatch
|
|
23627
|
+
);
|
|
23671
23628
|
dispatch = await appendServedChannelPublish(
|
|
23672
23629
|
deps,
|
|
23673
23630
|
{ repo: ctx.repo, publishStatus: publishLeg.state === "complete" ? "success" : "failure", watch },
|
|
@@ -23992,6 +23949,15 @@ Nothing was written. Inspect ${ledger.path} (or clear it only after proving the
|
|
|
23992
23949
|
workflowRuns: historicalRows
|
|
23993
23950
|
});
|
|
23994
23951
|
const phaseInputs = phaseInputsFromRunRows(deployModel, dispatch2.workflowRuns ?? historicalRows, tagSha, { repo: ctx.repo });
|
|
23952
|
+
const companion = await observePublishIfRequired(deps, ctx, meta, deployModel, "main", tagSha, watch);
|
|
23953
|
+
if (companion) {
|
|
23954
|
+
if (persisted) phaseInputs.deploy = persisted.phases.deploy;
|
|
23955
|
+
phaseInputs.publish = publishPhaseInput(deployModel, dispatch2, companion, true, { releaseSha: tagSha, repo: ctx.repo });
|
|
23956
|
+
historicalRows.push(...companion.workflowRuns ?? []);
|
|
23957
|
+
historicalDeploy = phaseInputs.deploy.state === "failed" || companion.deployStatus === "failure" ? "failure" : phaseInputs.deploy.state === "complete" && companion.deployStatus === "success" ? "success" : "pending";
|
|
23958
|
+
dispatch2.deployStatus = historicalDeploy;
|
|
23959
|
+
dispatch2.note = `historical ${deployModel} deploy/publish status: ${historicalDeploy}; ${companion.note}`;
|
|
23960
|
+
}
|
|
23995
23961
|
if (persisted) {
|
|
23996
23962
|
if (persisted.phases.deploy.superseded !== true) {
|
|
23997
23963
|
await recordPhase(ledger, deps, anchors, "deploy", phaseEntry(phaseInputs.deploy), { strict: true, landed: "the verified GitHub Release and origin/main at the immutable tag SHA" });
|
|
@@ -24003,7 +23969,7 @@ Nothing was written. Inspect ${ledger.path} (or clear it only after proving the
|
|
|
24003
23969
|
await recordPhase(ledger, deps, anchors, "promotion", phaseEntry({ state: "complete", sha: tagSha, note: "re-verified live: origin/main contains the immutable tag SHA" }), { strict: true, landed: "nothing beyond the already-public release" });
|
|
24004
23970
|
}
|
|
24005
23971
|
if (isJervHubRepo(ctx.repo)) steps2.push(dispatch2.note);
|
|
24006
|
-
const announceNote2 = persisted && !shippedBefore && persisted.phases.deploy.superseded !== true && prodReleaseTargets(deployModel).length > 0 ? await announceShippedRelease(
|
|
23972
|
+
const announceNote2 = persisted && !shippedBefore && persisted.phases.deploy.superseded !== true && (prodReleaseTargets(deployModel).length > 0 || companion !== null) ? await announceShippedRelease(
|
|
24007
23973
|
deps,
|
|
24008
23974
|
{ repo: ctx.repo, tag, summaryFile: options.announceSummaryFile },
|
|
24009
23975
|
deployModel,
|
|
@@ -24114,14 +24080,14 @@ ${recovery.note}`), recoveryInput);
|
|
|
24114
24080
|
strict: ledgerMode === "strict",
|
|
24115
24081
|
landed: "the immutable tag, the re-proven wall, the origin/main push, and the verified GitHub Release"
|
|
24116
24082
|
});
|
|
24117
|
-
const publishDispatch0 =
|
|
24083
|
+
const publishDispatch0 = await observePublishIfRequired(deps, ctx, meta, deployModel, "main", tagSha, watch);
|
|
24118
24084
|
const publishDispatch = publishDispatch0 ? await recoverFailedDispatchPhase(
|
|
24119
24085
|
deps,
|
|
24120
24086
|
ledger,
|
|
24121
24087
|
anchors,
|
|
24122
24088
|
"publish",
|
|
24123
24089
|
publishDispatch0,
|
|
24124
|
-
{ repo:
|
|
24090
|
+
{ repo: ctx.repo, sha: tagSha, watched: false, workflow: "publish.yml" }
|
|
24125
24091
|
) : null;
|
|
24126
24092
|
const publishLeg = phaseEntry(publishPhaseInput(deployModel, deployDispatch, publishDispatch, meta.publishRequired === true, { releaseSha: tagSha, repo: ctx.repo }));
|
|
24127
24093
|
await recordPhase(ledger, deps, anchors, "publish", publishLeg, {
|
|
@@ -44481,27 +44447,20 @@ ${decision.note}`);
|
|
|
44481
44447
|
deploy0,
|
|
44482
44448
|
{ repo: releaseRunRepoFor(deployModel, ctx.repo), sha: mergedSha, watched: true, workflow: "tenant-deploy.yml" }
|
|
44483
44449
|
);
|
|
44484
|
-
const publish0 =
|
|
44450
|
+
const publish0 = await observePublishIfRequired(deps, ctx, meta, deployModel, "main", mergedSha, true);
|
|
44485
44451
|
const publish = publish0 ? await recoverFailedDispatchPhase(
|
|
44486
44452
|
deps,
|
|
44487
44453
|
ledger,
|
|
44488
44454
|
anchors,
|
|
44489
44455
|
"publish",
|
|
44490
44456
|
publish0,
|
|
44491
|
-
{ repo:
|
|
44457
|
+
{ repo: ctx.repo, sha: mergedSha, watched: false, workflow: "publish.yml" }
|
|
44492
44458
|
) : null;
|
|
44493
44459
|
tenantPublishDispatch = publish;
|
|
44494
|
-
|
|
44495
|
-
if (!publish && deploy.deployStatus !== "success" && meta.publishRequired) {
|
|
44496
|
-
const reason = deploy.deployStatus === "failure" ? "box deploy failed \u2014 redeploy the box before publishing" : "box deploy not confirmed (run with --watch) \u2014 publish after the box deploy lands";
|
|
44497
|
-
dispatch = {
|
|
44498
|
-
...dispatch,
|
|
44499
|
-
note: `${dispatch.note}; tenant-publish.yml skipped (${reason})`
|
|
44500
|
-
};
|
|
44501
|
-
}
|
|
44460
|
+
const dispatch = appendPublishDispatch(deploy, publish);
|
|
44502
44461
|
deployNote = dispatch.note;
|
|
44503
44462
|
runs.push(hotfixWorkflowRunFromDispatch("tenant-deploy.yml", deploy));
|
|
44504
|
-
if (publish) runs.push(hotfixWorkflowRunFromDispatch("
|
|
44463
|
+
if (publish) runs.push(hotfixWorkflowRunFromDispatch("publish.yml", publish));
|
|
44505
44464
|
} else {
|
|
44506
44465
|
deployNote = `no hotfix deploy dispatch for deployModel=${deployModel} \u2014 prod deploy is repo-specific`;
|
|
44507
44466
|
}
|
package/package.json
CHANGED