@treeseed/sdk 0.6.36 → 0.6.38
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/operations/services/git-workflow.js +5 -5
- package/dist/operations/services/github-actions-verification.d.ts +4 -0
- package/dist/operations/services/github-actions-verification.js +5 -3
- package/dist/operations/services/github-automation.d.ts +6 -98
- package/dist/operations/services/github-automation.js +1 -74
- package/dist/operations/services/release-candidate.js +5 -11
- package/dist/operations/services/release-history.d.ts +59 -0
- package/dist/operations/services/release-history.js +159 -0
- package/dist/operations/services/repository-save-orchestrator.js +7 -8
- package/dist/operations/services/save-deploy-preflight.d.ts +0 -5
- package/dist/operations/services/save-deploy-preflight.js +1 -9
- package/dist/scripts/tenant-build.js +31 -2
- package/dist/scripts/workspace-command-e2e.js +3 -3
- package/dist/verification.js +0 -1
- package/dist/workflow/operations.d.ts +14 -2
- package/dist/workflow/operations.js +293 -131
- package/package.json +1 -1
- package/templates/github/deploy.workflow.yml +12 -9
|
@@ -57,7 +57,6 @@ import {
|
|
|
57
57
|
headCommit,
|
|
58
58
|
listTaskBranches,
|
|
59
59
|
mergeBranchIntoTarget,
|
|
60
|
-
mergeStagingIntoMain,
|
|
61
60
|
prepareReleaseBranches,
|
|
62
61
|
PRODUCTION_BRANCH,
|
|
63
62
|
pushBranch,
|
|
@@ -68,7 +67,7 @@ import {
|
|
|
68
67
|
squashMergeBranchIntoStaging,
|
|
69
68
|
syncBranchWithOrigin
|
|
70
69
|
} from "../operations/services/git-workflow.js";
|
|
71
|
-
import {
|
|
70
|
+
import { resolveGitHubRepositorySlug } from "../operations/services/github-automation.js";
|
|
72
71
|
import {
|
|
73
72
|
formatGitHubActionsGateFailure,
|
|
74
73
|
inspectGitHubActionsVerification,
|
|
@@ -78,6 +77,11 @@ import {
|
|
|
78
77
|
import {
|
|
79
78
|
runReleaseCandidateGate
|
|
80
79
|
} from "../operations/services/release-candidate.js";
|
|
80
|
+
import {
|
|
81
|
+
collectReleaseHistoryCommits,
|
|
82
|
+
renderAdministrativeCommitMessage,
|
|
83
|
+
upsertReleaseChangelog
|
|
84
|
+
} from "../operations/services/release-history.js";
|
|
81
85
|
import { loadCliDeployConfig, packageScriptPath, resolveWranglerBin } from "../operations/services/runtime-tools.js";
|
|
82
86
|
import { runTenantDeployPreflight, runWorkspaceReleasePreflight, runWorkspaceSavePreflight } from "../operations/services/save-deploy-preflight.js";
|
|
83
87
|
import { collectCliPreflight } from "../operations/services/workspace-preflight.js";
|
|
@@ -338,9 +342,6 @@ function shouldDispatchSwitchToManagedWorktree(root, input, env) {
|
|
|
338
342
|
return !isManagedWorkflowWorktree(root) && effectiveWorkflowWorktreeMode(input.worktreeMode, env) === "on";
|
|
339
343
|
}
|
|
340
344
|
function assertHostedGitHubWorkflowAuthReady(operation, root) {
|
|
341
|
-
if (getGitHubAutomationMode() === "stub") {
|
|
342
|
-
return null;
|
|
343
|
-
}
|
|
344
345
|
const tools = collectTreeseedToolStatus({
|
|
345
346
|
tenantRoot: root,
|
|
346
347
|
env: process.env
|
|
@@ -372,7 +373,7 @@ function assertHostedGitHubWorkflowAuthReady(operation, root) {
|
|
|
372
373
|
}
|
|
373
374
|
async function waitForWorkflowGates(operation, gates, ciMode, options = {}) {
|
|
374
375
|
if (ciMode === "off" || process.env.TREESEED_STAGE_WAIT_MODE === "skip") {
|
|
375
|
-
return gates.map((gate) => skippedGitHubActionsGate(gate,
|
|
376
|
+
return gates.map((gate) => skippedGitHubActionsGate(gate, "disabled"));
|
|
376
377
|
}
|
|
377
378
|
if (gates.length === 0) {
|
|
378
379
|
return [];
|
|
@@ -405,7 +406,9 @@ async function waitForWorkflowGates(operation, gates, ciMode, options = {}) {
|
|
|
405
406
|
...result,
|
|
406
407
|
workflow: String(result.workflow ?? gate.workflow),
|
|
407
408
|
branch: String(result.branch ?? gate.branch),
|
|
408
|
-
headSha: String(result.headSha ?? gate.headSha)
|
|
409
|
+
headSha: String(result.headSha ?? gate.headSha),
|
|
410
|
+
timeoutSeconds: gate.timeoutSeconds ?? null,
|
|
411
|
+
cached: false
|
|
409
412
|
};
|
|
410
413
|
if (normalized.status === "completed" && normalized.conclusion !== "success") {
|
|
411
414
|
workflowError(operation, "github_workflow_failed", formatGitHubActionsGateFailure(gate, normalized), {
|
|
@@ -419,13 +422,21 @@ async function waitForWorkflowGates(operation, gates, ciMode, options = {}) {
|
|
|
419
422
|
}
|
|
420
423
|
return results;
|
|
421
424
|
}
|
|
425
|
+
const RELEASE_DEPLOY_GATE_TIMEOUT_SECONDS = 45 * 60;
|
|
426
|
+
function releaseDeployGate(gate) {
|
|
427
|
+
return {
|
|
428
|
+
...gate,
|
|
429
|
+
timeoutSeconds: gate.timeoutSeconds ?? RELEASE_DEPLOY_GATE_TIMEOUT_SECONDS
|
|
430
|
+
};
|
|
431
|
+
}
|
|
422
432
|
function recordHostedDeploymentStatesFromRootGates(root, rootRelease, workflowGates) {
|
|
423
433
|
const gates = Array.isArray(workflowGates) ? workflowGates.map((gate) => stringRecord(gate)).filter((gate) => Boolean(gate)) : [];
|
|
424
434
|
const releaseRecord = stringRecord(rootRelease) ?? {};
|
|
425
435
|
const reports = [];
|
|
436
|
+
const releaseTag = typeof releaseRecord.rootVersion === "string" ? releaseRecord.rootVersion : null;
|
|
426
437
|
for (const target of [
|
|
427
438
|
{ scope: "staging", branch: STAGING_BRANCH, commit: releaseRecord.stagingCommit },
|
|
428
|
-
{ scope: "prod", branch: PRODUCTION_BRANCH, commit: releaseRecord.releasedCommit }
|
|
439
|
+
{ scope: "prod", branch: releaseTag ?? PRODUCTION_BRANCH, commit: releaseRecord.releasedCommit }
|
|
429
440
|
]) {
|
|
430
441
|
const gate = gates.find((candidate) => candidate.workflow === "deploy.yml" && candidate.branch === target.branch && candidate.status === "completed" && candidate.conclusion === "success");
|
|
431
442
|
const timestamp = typeof gate?.updatedAt === "string" && gate.updatedAt.trim() ? gate.updatedAt : null;
|
|
@@ -452,10 +463,10 @@ function recordHostedDeploymentStatesFromRootGates(root, rootRelease, workflowGa
|
|
|
452
463
|
return reports;
|
|
453
464
|
}
|
|
454
465
|
function ensureTreeseedCommandReadiness(root) {
|
|
455
|
-
if (
|
|
466
|
+
if (process.env.TREESEED_COMMAND_READINESS_MODE === "skip") {
|
|
456
467
|
return {
|
|
457
468
|
status: "skipped",
|
|
458
|
-
reason: "
|
|
469
|
+
reason: "disabled",
|
|
459
470
|
checks: [],
|
|
460
471
|
missing: []
|
|
461
472
|
};
|
|
@@ -705,13 +716,13 @@ function remoteTagCommit(repoDir, tagName) {
|
|
|
705
716
|
const direct = output.split("\n").find((line) => line.endsWith(`refs/tags/${tagName}`));
|
|
706
717
|
return (peeled ?? direct)?.split(/\s+/u)[0] ?? null;
|
|
707
718
|
}
|
|
708
|
-
function ensureReleaseTag(repoDir, tagName, commitSha) {
|
|
719
|
+
function ensureReleaseTag(repoDir, tagName, commitSha, message) {
|
|
709
720
|
const localCommit = gitObjectCommit(repoDir, tagName);
|
|
710
721
|
if (localCommit && localCommit !== commitSha) {
|
|
711
722
|
throw new Error(`Release tag ${tagName} already exists locally at ${localCommit}, expected ${commitSha}.`);
|
|
712
723
|
}
|
|
713
724
|
if (!localCommit) {
|
|
714
|
-
run("git", ["tag", "-a", tagName, commitSha, "-m", `release: ${tagName}`], { cwd: repoDir });
|
|
725
|
+
run("git", ["tag", "-a", tagName, commitSha, "-m", message ?? `release: ${tagName}`], { cwd: repoDir });
|
|
715
726
|
}
|
|
716
727
|
const remoteCommit = remoteTagCommit(repoDir, tagName);
|
|
717
728
|
if (remoteCommit && remoteCommit !== commitSha) {
|
|
@@ -734,6 +745,51 @@ function commitAllIfChanged(repoDir, message) {
|
|
|
734
745
|
run("git", ["commit", "-m", message], { cwd: repoDir });
|
|
735
746
|
return { committed: true, commitSha: headCommit(repoDir) };
|
|
736
747
|
}
|
|
748
|
+
function releaseHistoryCommits(repoDir, sourceRef = `origin/${PRODUCTION_BRANCH}`, targetRef = "HEAD") {
|
|
749
|
+
try {
|
|
750
|
+
return collectReleaseHistoryCommits(repoDir, sourceRef, targetRef);
|
|
751
|
+
} catch {
|
|
752
|
+
return [];
|
|
753
|
+
}
|
|
754
|
+
}
|
|
755
|
+
function versionLines(versions) {
|
|
756
|
+
return [...(versions ?? /* @__PURE__ */ new Map()).entries()].sort(([left], [right]) => left.localeCompare(right)).map(([name, version]) => `${name}: ${version}`);
|
|
757
|
+
}
|
|
758
|
+
function updateReleaseChangelog(repoDir, input) {
|
|
759
|
+
const sourceRef = input.sourceRef ?? `origin/${PRODUCTION_BRANCH}`;
|
|
760
|
+
const targetRef = input.targetRef ?? "HEAD";
|
|
761
|
+
const commits = input.commits ?? releaseHistoryCommits(repoDir, sourceRef, targetRef);
|
|
762
|
+
return upsertReleaseChangelog(repoDir, {
|
|
763
|
+
version: input.version,
|
|
764
|
+
sourceRef,
|
|
765
|
+
targetRef,
|
|
766
|
+
commits,
|
|
767
|
+
extraBullets: input.extraDependencyBullets?.length ? { Dependencies: input.extraDependencyBullets } : void 0
|
|
768
|
+
});
|
|
769
|
+
}
|
|
770
|
+
function releaseAdminMessage(input) {
|
|
771
|
+
return renderAdministrativeCommitMessage({
|
|
772
|
+
subject: input.subject,
|
|
773
|
+
version: input.version,
|
|
774
|
+
tagName: input.tagName,
|
|
775
|
+
sourceRef: input.sourceRef ?? STAGING_BRANCH,
|
|
776
|
+
targetRef: input.targetRef ?? PRODUCTION_BRANCH,
|
|
777
|
+
commits: input.commits ?? [],
|
|
778
|
+
changelog: input.changelog ?? null,
|
|
779
|
+
extraLines: input.extraLines
|
|
780
|
+
});
|
|
781
|
+
}
|
|
782
|
+
function completedJournalStepData(root, runId, stepId) {
|
|
783
|
+
const journal = readWorkflowRunJournal(root, runId);
|
|
784
|
+
return stringRecord(journal?.steps.find((step) => step.id === stepId && step.status === "completed")?.data);
|
|
785
|
+
}
|
|
786
|
+
function shouldResumeReleaseAtRootGates(root, runId) {
|
|
787
|
+
const journal = readWorkflowRunJournal(root, runId);
|
|
788
|
+
if (!journal || journal.command !== "release") return false;
|
|
789
|
+
const rootStep = journal.steps.find((step) => step.id === "release-root");
|
|
790
|
+
const gateStep = journal.steps.find((step) => step.id === "release-root-gates");
|
|
791
|
+
return rootStep?.status === "completed" && gateStep?.status !== "completed";
|
|
792
|
+
}
|
|
737
793
|
function createNextSteps(steps) {
|
|
738
794
|
return steps.map(renderWorkflowStep);
|
|
739
795
|
}
|
|
@@ -1368,9 +1424,6 @@ function failWorkflowRun(root, runId, error, recovery) {
|
|
|
1368
1424
|
releaseWorkflowLock(root, runId);
|
|
1369
1425
|
}
|
|
1370
1426
|
function validatePackageReleaseWorkflows(root, packageNames) {
|
|
1371
|
-
if (process.env.TREESEED_GITHUB_AUTOMATION_MODE === "stub") {
|
|
1372
|
-
return;
|
|
1373
|
-
}
|
|
1374
1427
|
const missing = checkedOutWorkspacePackageRepos(root).filter((pkg) => packageNames.includes(pkg.name)).filter((pkg) => !existsSync(resolve(pkg.dir, ".github", "workflows", "publish.yml"))).map((pkg) => pkg.name);
|
|
1375
1428
|
if (missing.length > 0) {
|
|
1376
1429
|
workflowError("release", "workflow_contract_missing", `Treeseed release requires .github/workflows/publish.yml in: ${missing.join(", ")}.`, {
|
|
@@ -1381,7 +1434,7 @@ function validatePackageReleaseWorkflows(root, packageNames) {
|
|
|
1381
1434
|
}
|
|
1382
1435
|
}
|
|
1383
1436
|
function validateStagingWorkflowContracts(root) {
|
|
1384
|
-
if (process.env.
|
|
1437
|
+
if (process.env.TREESEED_STAGE_WAIT_MODE === "skip") {
|
|
1385
1438
|
return;
|
|
1386
1439
|
}
|
|
1387
1440
|
const missing = [];
|
|
@@ -1397,14 +1450,31 @@ function validateStagingWorkflowContracts(root) {
|
|
|
1397
1450
|
}
|
|
1398
1451
|
}
|
|
1399
1452
|
function shouldSkipReleaseInstall() {
|
|
1400
|
-
return process.env.
|
|
1453
|
+
return process.env.TREESEED_SAVE_NPM_INSTALL_MODE === "skip";
|
|
1401
1454
|
}
|
|
1402
1455
|
function runReleaseNpmInstall(repoDir, options = {}) {
|
|
1403
1456
|
if (shouldSkipReleaseInstall()) {
|
|
1404
|
-
return { status: "skipped", reason: "
|
|
1457
|
+
return { status: "skipped", reason: "disabled" };
|
|
1458
|
+
}
|
|
1459
|
+
const args = repoDir === options.workspaceRoot ? ["install", "--package-lock-only", "--ignore-scripts", "--no-audit", "--no-fund"] : ["install", "--package-lock-only", "--ignore-scripts", "--workspaces=false", "--no-audit", "--no-fund"];
|
|
1460
|
+
const result = spawnSync("npm", args, {
|
|
1461
|
+
cwd: repoDir,
|
|
1462
|
+
env: {
|
|
1463
|
+
...process.env,
|
|
1464
|
+
npm_config_audit: "false",
|
|
1465
|
+
npm_config_fund: "false"
|
|
1466
|
+
},
|
|
1467
|
+
stdio: "pipe",
|
|
1468
|
+
encoding: "utf8"
|
|
1469
|
+
});
|
|
1470
|
+
if (result.status !== 0) {
|
|
1471
|
+
const detail = [
|
|
1472
|
+
result.error?.message,
|
|
1473
|
+
result.stderr?.trim(),
|
|
1474
|
+
result.stdout?.trim()
|
|
1475
|
+
].filter(Boolean).join("\n");
|
|
1476
|
+
throw new Error(detail || `npm ${args.join(" ")} failed`);
|
|
1405
1477
|
}
|
|
1406
|
-
const args = repoDir === options.workspaceRoot ? ["install", "--package-lock-only", "--ignore-scripts"] : ["install", "--package-lock-only", "--ignore-scripts", "--workspaces=false"];
|
|
1407
|
-
run("npm", args, { cwd: repoDir });
|
|
1408
1478
|
return { status: "completed", reason: null };
|
|
1409
1479
|
}
|
|
1410
1480
|
function pathIsWithin(parent, candidate) {
|
|
@@ -1422,7 +1492,7 @@ function assertNoInternalDevReferencesForRepo(root, repoDir, packageNames) {
|
|
|
1422
1492
|
throw new Error(`Stable release still contains internal Git/dev dependency references.
|
|
1423
1493
|
${rendered}`);
|
|
1424
1494
|
}
|
|
1425
|
-
function backMergeProductionIntoStaging(repoDir, repoName) {
|
|
1495
|
+
function backMergeProductionIntoStaging(repoDir, repoName, message) {
|
|
1426
1496
|
syncBranchWithOrigin(repoDir, PRODUCTION_BRANCH);
|
|
1427
1497
|
syncBranchWithOrigin(repoDir, STAGING_BRANCH);
|
|
1428
1498
|
checkoutBranch(repoDir, STAGING_BRANCH);
|
|
@@ -1439,7 +1509,7 @@ function backMergeProductionIntoStaging(repoDir, repoName) {
|
|
|
1439
1509
|
} catch {
|
|
1440
1510
|
}
|
|
1441
1511
|
try {
|
|
1442
|
-
run("git", ["merge", "--no-ff", `origin/${PRODUCTION_BRANCH}`, "-m", `release: back-merge ${PRODUCTION_BRANCH} into ${STAGING_BRANCH}`], { cwd: repoDir });
|
|
1512
|
+
run("git", ["merge", "--no-ff", `origin/${PRODUCTION_BRANCH}`, "-m", message ?? `release: back-merge ${PRODUCTION_BRANCH} into ${STAGING_BRANCH}`], { cwd: repoDir });
|
|
1443
1513
|
} catch (error) {
|
|
1444
1514
|
const report = collectMergeConflictReport(repoDir);
|
|
1445
1515
|
throw new TreeseedWorkflowError("release", "merge_conflict", formatMergeConflictReport(report, repoDir, STAGING_BRANCH), {
|
|
@@ -1457,14 +1527,32 @@ function backMergeProductionIntoStaging(repoDir, repoName) {
|
|
|
1457
1527
|
commitSha: headCommit(repoDir)
|
|
1458
1528
|
};
|
|
1459
1529
|
}
|
|
1460
|
-
function backMergeRootProductionIntoStaging(root, syncPackageStagingHeads) {
|
|
1530
|
+
function backMergeRootProductionIntoStaging(root, syncPackageStagingHeads, options = {}) {
|
|
1461
1531
|
const gitRoot = repoRoot(root);
|
|
1462
|
-
const
|
|
1532
|
+
const commits = releaseHistoryCommits(gitRoot, STAGING_BRANCH, `origin/${PRODUCTION_BRANCH}`);
|
|
1533
|
+
const backMerge = backMergeProductionIntoStaging(gitRoot, "@treeseed/market", releaseAdminMessage({
|
|
1534
|
+
subject: `release: back-merge ${PRODUCTION_BRANCH} into ${STAGING_BRANCH}`,
|
|
1535
|
+
version: options.version,
|
|
1536
|
+
sourceRef: PRODUCTION_BRANCH,
|
|
1537
|
+
targetRef: STAGING_BRANCH,
|
|
1538
|
+
commits,
|
|
1539
|
+
changelog: options.changelog ?? null,
|
|
1540
|
+
extraLines: versionLines(options.selectedVersions).map((line) => `Released package ${line}`)
|
|
1541
|
+
}));
|
|
1463
1542
|
if (!syncPackageStagingHeads) {
|
|
1464
1543
|
return backMerge;
|
|
1465
1544
|
}
|
|
1466
1545
|
syncAllCheckedOutPackageRepos(root, STAGING_BRANCH);
|
|
1467
|
-
const
|
|
1546
|
+
const pointerCommits = releaseHistoryCommits(gitRoot, `origin/${STAGING_BRANCH}`, "HEAD");
|
|
1547
|
+
const pointerSync = commitAllIfChanged(gitRoot, releaseAdminMessage({
|
|
1548
|
+
subject: "release: sync package staging heads",
|
|
1549
|
+
version: options.version,
|
|
1550
|
+
sourceRef: "package staging heads",
|
|
1551
|
+
targetRef: STAGING_BRANCH,
|
|
1552
|
+
commits: pointerCommits,
|
|
1553
|
+
changelog: options.changelog ?? null,
|
|
1554
|
+
extraLines: versionLines(options.selectedVersions).map((line) => `Staging package ${line}`)
|
|
1555
|
+
}));
|
|
1468
1556
|
if (pointerSync.committed) {
|
|
1469
1557
|
pushBranch(gitRoot, STAGING_BRANCH);
|
|
1470
1558
|
}
|
|
@@ -1590,8 +1678,8 @@ function collectReleasePlanBlockers(session, mode, selectedPackageNames) {
|
|
|
1590
1678
|
}
|
|
1591
1679
|
return blockers;
|
|
1592
1680
|
}
|
|
1593
|
-
function assertReleaseGitHubAutomationReady(root, selectedPackageNames) {
|
|
1594
|
-
if (
|
|
1681
|
+
function assertReleaseGitHubAutomationReady(root, selectedPackageNames, ciMode) {
|
|
1682
|
+
if (ciMode === "off") {
|
|
1595
1683
|
return;
|
|
1596
1684
|
}
|
|
1597
1685
|
assertHostedGitHubWorkflowAuthReady("release", root);
|
|
@@ -3494,7 +3582,10 @@ async function workflowRelease(helpers, input) {
|
|
|
3494
3582
|
const freshPreparation = freshRelease && executionMode === "execute" ? prepareFreshReleaseRun(root, session.branchName, rootRepo, packageReports) : { archived: [], blockers: [] };
|
|
3495
3583
|
const autoResumeRun = executionMode === "execute" && !explicitResumeRunId && !freshRelease ? findAutoResumableReleaseRun(root, session.branchName, rootRepo, packageReports) : null;
|
|
3496
3584
|
const planAutoResumeRun = executionMode === "plan" && input.fresh !== true ? findAutoResumableReleaseRun(root, session.branchName, rootRepo, packageReports) : null;
|
|
3497
|
-
const effectiveInput = autoResumeRun ?
|
|
3585
|
+
const effectiveInput = autoResumeRun ? {
|
|
3586
|
+
...autoResumeRun.input,
|
|
3587
|
+
ciMode: input.ciMode ?? autoResumeRun.input.ciMode
|
|
3588
|
+
} : input;
|
|
3498
3589
|
const level = effectiveInput.bump ?? "patch";
|
|
3499
3590
|
const ciMode = normalizeCiMode(effectiveInput.ciMode, "release");
|
|
3500
3591
|
const isResume = Boolean(explicitResumeRunId || autoResumeRun);
|
|
@@ -3576,6 +3667,10 @@ async function workflowRelease(helpers, input) {
|
|
|
3576
3667
|
if (autoResumeRun) {
|
|
3577
3668
|
helpers.write(`[workflow][resume] Resuming interrupted release ${autoResumeRun.runId} on ${STAGING_BRANCH}.`);
|
|
3578
3669
|
}
|
|
3670
|
+
const resumeAtRootGates = workflowRun.resumed && shouldResumeReleaseAtRootGates(root, workflowRun.runId);
|
|
3671
|
+
if (resumeAtRootGates) {
|
|
3672
|
+
helpers.write(`[workflow][resume] Resuming release ${workflowRun.runId} directly at production deploy gates.`);
|
|
3673
|
+
}
|
|
3579
3674
|
let releaseCleanupSnapshot = null;
|
|
3580
3675
|
try {
|
|
3581
3676
|
const releasePlan = await executeJournalStep(root, workflowRun.runId, "release-plan", () => plannedRelease);
|
|
@@ -3584,31 +3679,68 @@ async function workflowRelease(helpers, input) {
|
|
|
3584
3679
|
const effectiveVersions = releasePlanVersionMap(releasePlan.plannedVersions);
|
|
3585
3680
|
const rootVersion = String(releasePlan.rootVersion);
|
|
3586
3681
|
applyTreeseedEnvironmentToProcess({ tenantRoot: root, scope: "staging", override: true });
|
|
3587
|
-
assertReleaseGitHubAutomationReady(root, effectiveSelectedPackageNames);
|
|
3588
|
-
const releaseCandidate = await executeJournalStep(root, workflowRun.runId, "release-candidate", () => runReleaseCandidateForPlan("release", root, releasePlan, { allowReuse: true }));
|
|
3589
|
-
if (!isResume) {
|
|
3682
|
+
assertReleaseGitHubAutomationReady(root, effectiveSelectedPackageNames, ciMode);
|
|
3683
|
+
const releaseCandidate = resumeAtRootGates ? completedJournalStepData(root, workflowRun.runId, "release-candidate") : await executeJournalStep(root, workflowRun.runId, "release-candidate", () => runReleaseCandidateForPlan("release", root, releasePlan, { allowReuse: true }));
|
|
3684
|
+
if (!resumeAtRootGates && !isResume) {
|
|
3590
3685
|
assertSessionBranchSafety("release", session, { requireCleanPackages: true, requireCurrentBranch: true });
|
|
3591
3686
|
assertCleanWorktree(root);
|
|
3592
3687
|
}
|
|
3593
|
-
|
|
3594
|
-
|
|
3595
|
-
|
|
3596
|
-
|
|
3688
|
+
if (!resumeAtRootGates) {
|
|
3689
|
+
prepareReleaseBranches(root);
|
|
3690
|
+
ensureWorkflowWorkspaceLinks(root, helpers, effectiveInput.workspaceLinks ?? "auto");
|
|
3691
|
+
runWorkspaceReleasePreflight({ cwd: root });
|
|
3692
|
+
await executeJournalStep(root, workflowRun.runId, "workspace-unlink", () => unlinkWorkflowWorkspaceLinks(root, helpers, effectiveInput.workspaceLinks ?? "auto"), { rerunCompleted: true });
|
|
3693
|
+
}
|
|
3597
3694
|
if (mode === "root-only") {
|
|
3598
3695
|
const rootRelease2 = await executeJournalStep(root, workflowRun.runId, "release-root", () => {
|
|
3599
3696
|
setRootPackageJsonVersion(root, rootVersion);
|
|
3600
3697
|
run("git", ["checkout", STAGING_BRANCH], { cwd: gitRoot });
|
|
3601
|
-
|
|
3698
|
+
const rootCommitsBeforeChangelog = releaseHistoryCommits(gitRoot);
|
|
3699
|
+
const changelog = updateReleaseChangelog(gitRoot, {
|
|
3700
|
+
version: rootVersion,
|
|
3701
|
+
commits: rootCommitsBeforeChangelog,
|
|
3702
|
+
extraDependencyBullets: [`Release @treeseed/market ${rootVersion}.`]
|
|
3703
|
+
});
|
|
3704
|
+
commitAllIfChanged(gitRoot, releaseAdminMessage({
|
|
3705
|
+
subject: `release: ${level} bump`,
|
|
3706
|
+
version: rootVersion,
|
|
3707
|
+
tagName: rootVersion,
|
|
3708
|
+
commits: rootCommitsBeforeChangelog,
|
|
3709
|
+
changelog
|
|
3710
|
+
}));
|
|
3602
3711
|
pushBranch(gitRoot, STAGING_BRANCH);
|
|
3603
3712
|
const stagingCommit = headCommit(gitRoot);
|
|
3604
|
-
const
|
|
3605
|
-
const
|
|
3713
|
+
const rootCommits = releaseHistoryCommits(gitRoot);
|
|
3714
|
+
const released = mergeBranchIntoTarget(root, {
|
|
3715
|
+
sourceBranch: STAGING_BRANCH,
|
|
3716
|
+
targetBranch: PRODUCTION_BRANCH,
|
|
3717
|
+
message: releaseAdminMessage({
|
|
3718
|
+
subject: `release: ${STAGING_BRANCH} -> ${PRODUCTION_BRANCH}`,
|
|
3719
|
+
version: rootVersion,
|
|
3720
|
+
tagName: rootVersion,
|
|
3721
|
+
commits: rootCommits,
|
|
3722
|
+
changelog
|
|
3723
|
+
}),
|
|
3724
|
+
pushTarget: true
|
|
3725
|
+
});
|
|
3726
|
+
const tag = ensureReleaseTag(gitRoot, rootVersion, released.commitSha, releaseAdminMessage({
|
|
3727
|
+
subject: `release: ${rootVersion}`,
|
|
3728
|
+
version: rootVersion,
|
|
3729
|
+
tagName: rootVersion,
|
|
3730
|
+
commits: rootCommits,
|
|
3731
|
+
changelog
|
|
3732
|
+
}));
|
|
3606
3733
|
syncBranchWithOrigin(gitRoot, STAGING_BRANCH);
|
|
3607
3734
|
return {
|
|
3608
3735
|
rootVersion,
|
|
3609
3736
|
stagingCommit,
|
|
3610
3737
|
releasedCommit: released.commitSha,
|
|
3611
|
-
tag
|
|
3738
|
+
tag,
|
|
3739
|
+
changelog,
|
|
3740
|
+
adminCommitSummary: {
|
|
3741
|
+
commitCount: rootCommits.length,
|
|
3742
|
+
notableCommits: rootCommits.slice(0, 12)
|
|
3743
|
+
}
|
|
3612
3744
|
};
|
|
3613
3745
|
});
|
|
3614
3746
|
rootRepo.committed = true;
|
|
@@ -3618,48 +3750,23 @@ async function workflowRelease(helpers, input) {
|
|
|
3618
3750
|
rootRepo.commitSha = String(rootRelease2?.releasedCommit ?? headCommit(gitRoot));
|
|
3619
3751
|
rootRepo.tagName = String(rootRelease2?.rootVersion ?? "");
|
|
3620
3752
|
const rootWorkflowGateResult2 = await executeJournalStep(root, workflowRun.runId, "release-root-gates", () => waitForWorkflowGates("release", [
|
|
3621
|
-
{
|
|
3622
|
-
name: rootRepo.name,
|
|
3623
|
-
repoPath: rootRepo.path,
|
|
3624
|
-
workflow: "verify.yml",
|
|
3625
|
-
branch: STAGING_BRANCH,
|
|
3626
|
-
headSha: String(rootRelease2?.stagingCommit ?? "")
|
|
3627
|
-
},
|
|
3628
|
-
{
|
|
3753
|
+
releaseDeployGate({
|
|
3629
3754
|
name: rootRepo.name,
|
|
3630
3755
|
repoPath: rootRepo.path,
|
|
3631
3756
|
workflow: "deploy.yml",
|
|
3632
|
-
branch: STAGING_BRANCH,
|
|
3633
|
-
headSha: String(rootRelease2?.stagingCommit ?? "")
|
|
3634
|
-
},
|
|
3635
|
-
{
|
|
3636
|
-
name: rootRepo.name,
|
|
3637
|
-
repoPath: rootRepo.path,
|
|
3638
|
-
workflow: "verify.yml",
|
|
3639
3757
|
branch: rootVersion,
|
|
3640
3758
|
headSha: String(rootRelease2?.releasedCommit ?? rootRepo.commitSha ?? "")
|
|
3641
|
-
}
|
|
3642
|
-
{
|
|
3643
|
-
name: rootRepo.name,
|
|
3644
|
-
repoPath: rootRepo.path,
|
|
3645
|
-
workflow: "verify.yml",
|
|
3646
|
-
branch: PRODUCTION_BRANCH,
|
|
3647
|
-
headSha: String(rootRelease2?.releasedCommit ?? rootRepo.commitSha ?? "")
|
|
3648
|
-
},
|
|
3649
|
-
{
|
|
3650
|
-
name: rootRepo.name,
|
|
3651
|
-
repoPath: rootRepo.path,
|
|
3652
|
-
workflow: "deploy.yml",
|
|
3653
|
-
branch: PRODUCTION_BRANCH,
|
|
3654
|
-
headSha: String(rootRelease2?.releasedCommit ?? rootRepo.commitSha ?? "")
|
|
3655
|
-
}
|
|
3759
|
+
})
|
|
3656
3760
|
].filter((gate) => gate.headSha), ciMode, {
|
|
3657
3761
|
root,
|
|
3658
3762
|
runId: workflowRun.runId,
|
|
3659
3763
|
onProgress: (line, stream) => helpers.write(line, stream)
|
|
3660
3764
|
}).then((workflowGates) => ({ workflowGates })));
|
|
3661
3765
|
const hostedDeploymentState2 = recordHostedDeploymentStatesFromRootGates(root, rootRelease2, rootWorkflowGateResult2?.workflowGates);
|
|
3662
|
-
const releaseBackMerge2 = await executeJournalStep(root, workflowRun.runId, "release-back-merge", () => backMergeRootProductionIntoStaging(root, false
|
|
3766
|
+
const releaseBackMerge2 = await executeJournalStep(root, workflowRun.runId, "release-back-merge", () => backMergeRootProductionIntoStaging(root, false, {
|
|
3767
|
+
version: rootVersion,
|
|
3768
|
+
changelog: rootRelease2?.changelog ?? null
|
|
3769
|
+
}));
|
|
3663
3770
|
const workspaceLinks2 = ensureWorkflowWorkspaceLinks(root, helpers, effectiveInput.workspaceLinks ?? "auto");
|
|
3664
3771
|
const payload2 = {
|
|
3665
3772
|
mode,
|
|
@@ -3698,13 +3805,15 @@ async function workflowRelease(helpers, input) {
|
|
|
3698
3805
|
])
|
|
3699
3806
|
});
|
|
3700
3807
|
}
|
|
3701
|
-
|
|
3702
|
-
|
|
3703
|
-
|
|
3704
|
-
|
|
3808
|
+
if (!resumeAtRootGates) {
|
|
3809
|
+
validatePackageReleaseWorkflows(root, effectivePackageSelection.selected);
|
|
3810
|
+
for (const pkg of checkedOutWorkspacePackageRepos(root)) {
|
|
3811
|
+
if (effectiveSelectedPackageNames.has(pkg.name)) {
|
|
3812
|
+
prepareReleaseBranches(pkg.dir);
|
|
3813
|
+
}
|
|
3705
3814
|
}
|
|
3706
3815
|
}
|
|
3707
|
-
releaseCleanupSnapshot = collectReleaseCleanupSnapshot(root, effectiveSelectedPackageNames);
|
|
3816
|
+
releaseCleanupSnapshot = resumeAtRootGates ? null : collectReleaseCleanupSnapshot(root, effectiveSelectedPackageNames);
|
|
3708
3817
|
const metadata = await executeJournalStep(root, workflowRun.runId, "prepare-release-metadata", () => {
|
|
3709
3818
|
const releasedPackageDevTags2 = Object.fromEntries(
|
|
3710
3819
|
checkedOutWorkspacePackageRepos(root).filter((pkg) => effectiveSelectedPackageNames.has(pkg.name)).map((pkg) => {
|
|
@@ -3724,7 +3833,7 @@ async function workflowRelease(helpers, input) {
|
|
|
3724
3833
|
replacedDevReferences: replacedDevReferences2,
|
|
3725
3834
|
releaseInstalls: releaseInstalls2
|
|
3726
3835
|
};
|
|
3727
|
-
}, { rerunCompleted: workflowRun.resumed });
|
|
3836
|
+
}, { rerunCompleted: workflowRun.resumed && !resumeAtRootGates });
|
|
3728
3837
|
const replacedDevReferences = Array.isArray(metadata?.replacedDevReferences) ? metadata.replacedDevReferences : [];
|
|
3729
3838
|
const releaseInstalls = Array.isArray(metadata?.releaseInstalls) ? metadata.releaseInstalls : [];
|
|
3730
3839
|
const releasedPackageDevTags = new Map(Object.entries(metadata?.releasedPackageDevTags ?? {}).map(([name, version]) => [name, String(version)]));
|
|
@@ -3739,24 +3848,52 @@ async function workflowRelease(helpers, input) {
|
|
|
3739
3848
|
}
|
|
3740
3849
|
const releasedPackage = await executeJournalStep(root, workflowRun.runId, `release-${report.name}`, async () => {
|
|
3741
3850
|
checkoutBranch(pkg.dir, STAGING_BRANCH);
|
|
3851
|
+
const tagName = String(effectiveVersions.get(pkg.name));
|
|
3742
3852
|
releaseInstalls.push({
|
|
3743
3853
|
name: pkg.name,
|
|
3744
3854
|
...runReleaseNpmInstall(pkg.dir, { workspaceRoot: root })
|
|
3745
3855
|
});
|
|
3746
3856
|
assertNoInternalDevReferencesForRepo(root, pkg.dir, effectiveSelectedPackageNames);
|
|
3857
|
+
const packageCommitsBeforeChangelog = releaseHistoryCommits(pkg.dir);
|
|
3858
|
+
const changelog = updateReleaseChangelog(pkg.dir, {
|
|
3859
|
+
version: tagName,
|
|
3860
|
+
commits: packageCommitsBeforeChangelog,
|
|
3861
|
+
extraDependencyBullets: [`Release ${pkg.name} ${tagName}.`]
|
|
3862
|
+
});
|
|
3747
3863
|
if (hasMeaningfulChanges(pkg.dir)) {
|
|
3748
3864
|
run("git", ["add", "-A"], { cwd: pkg.dir });
|
|
3749
|
-
run("git", ["commit", "-m",
|
|
3865
|
+
run("git", ["commit", "-m", releaseAdminMessage({
|
|
3866
|
+
subject: `release: ${tagName}`,
|
|
3867
|
+
version: tagName,
|
|
3868
|
+
tagName,
|
|
3869
|
+
commits: packageCommitsBeforeChangelog,
|
|
3870
|
+
changelog,
|
|
3871
|
+
extraLines: [`Package: ${pkg.name}`]
|
|
3872
|
+
})], { cwd: pkg.dir });
|
|
3750
3873
|
}
|
|
3751
3874
|
pushBranch(pkg.dir, STAGING_BRANCH);
|
|
3875
|
+
const packageCommits = releaseHistoryCommits(pkg.dir);
|
|
3752
3876
|
const mergeResult = mergeBranchIntoTarget(pkg.dir, {
|
|
3753
3877
|
sourceBranch: STAGING_BRANCH,
|
|
3754
3878
|
targetBranch: PRODUCTION_BRANCH,
|
|
3755
|
-
message:
|
|
3879
|
+
message: releaseAdminMessage({
|
|
3880
|
+
subject: `release: ${STAGING_BRANCH} -> ${PRODUCTION_BRANCH}`,
|
|
3881
|
+
version: tagName,
|
|
3882
|
+
tagName,
|
|
3883
|
+
commits: packageCommits,
|
|
3884
|
+
changelog,
|
|
3885
|
+
extraLines: [`Package: ${pkg.name}`]
|
|
3886
|
+
}),
|
|
3756
3887
|
pushTarget: true
|
|
3757
3888
|
});
|
|
3758
|
-
const
|
|
3759
|
-
|
|
3889
|
+
const tag = ensureReleaseTag(pkg.dir, tagName, mergeResult.commitSha, releaseAdminMessage({
|
|
3890
|
+
subject: `release: ${tagName}`,
|
|
3891
|
+
version: tagName,
|
|
3892
|
+
tagName,
|
|
3893
|
+
commits: packageCommits,
|
|
3894
|
+
changelog,
|
|
3895
|
+
extraLines: [`Package: ${pkg.name}`]
|
|
3896
|
+
}));
|
|
3760
3897
|
const workflowGates = await waitForWorkflowGates("release", [
|
|
3761
3898
|
{
|
|
3762
3899
|
name: pkg.name,
|
|
@@ -3764,20 +3901,6 @@ async function workflowRelease(helpers, input) {
|
|
|
3764
3901
|
workflow: "publish.yml",
|
|
3765
3902
|
headSha: mergeResult.commitSha,
|
|
3766
3903
|
branch: tagName
|
|
3767
|
-
},
|
|
3768
|
-
{
|
|
3769
|
-
name: pkg.name,
|
|
3770
|
-
repoPath: pkg.dir,
|
|
3771
|
-
workflow: "verify.yml",
|
|
3772
|
-
headSha: mergeResult.commitSha,
|
|
3773
|
-
branch: tagName
|
|
3774
|
-
},
|
|
3775
|
-
{
|
|
3776
|
-
name: pkg.name,
|
|
3777
|
-
repoPath: pkg.dir,
|
|
3778
|
-
workflow: "verify.yml",
|
|
3779
|
-
headSha: mergeResult.commitSha,
|
|
3780
|
-
branch: PRODUCTION_BRANCH
|
|
3781
3904
|
}
|
|
3782
3905
|
], ciMode, {
|
|
3783
3906
|
root,
|
|
@@ -3786,12 +3909,26 @@ async function workflowRelease(helpers, input) {
|
|
|
3786
3909
|
});
|
|
3787
3910
|
const publish = workflowGates.find((gate) => gate.workflow === "publish.yml") ?? workflowGates[0] ?? null;
|
|
3788
3911
|
assertReleaseGitHubWorkflowSucceeded(pkg.name, publish);
|
|
3789
|
-
const backMerge = backMergeProductionIntoStaging(pkg.dir, pkg.name
|
|
3912
|
+
const backMerge = backMergeProductionIntoStaging(pkg.dir, pkg.name, releaseAdminMessage({
|
|
3913
|
+
subject: `release: back-merge ${PRODUCTION_BRANCH} into ${STAGING_BRANCH}`,
|
|
3914
|
+
version: tagName,
|
|
3915
|
+
tagName,
|
|
3916
|
+
sourceRef: PRODUCTION_BRANCH,
|
|
3917
|
+
targetRef: STAGING_BRANCH,
|
|
3918
|
+
commits: packageCommits,
|
|
3919
|
+
changelog,
|
|
3920
|
+
extraLines: [`Package: ${pkg.name}`]
|
|
3921
|
+
}));
|
|
3790
3922
|
syncBranchWithOrigin(pkg.dir, STAGING_BRANCH);
|
|
3791
3923
|
return {
|
|
3792
3924
|
commitSha: mergeResult.commitSha,
|
|
3793
3925
|
tagName,
|
|
3794
3926
|
tag,
|
|
3927
|
+
changelog,
|
|
3928
|
+
adminCommitSummary: {
|
|
3929
|
+
commitCount: packageCommits.length,
|
|
3930
|
+
notableCommits: packageCommits.slice(0, 12)
|
|
3931
|
+
},
|
|
3795
3932
|
publish,
|
|
3796
3933
|
workflowGates,
|
|
3797
3934
|
backMerge
|
|
@@ -3805,6 +3942,8 @@ async function workflowRelease(helpers, input) {
|
|
|
3805
3942
|
report.publishWait = releasedPackage?.publish ?? null;
|
|
3806
3943
|
report.workflowGates = Array.isArray(releasedPackage?.workflowGates) ? releasedPackage.workflowGates : [];
|
|
3807
3944
|
report.backMerge = releasedPackage?.backMerge ?? null;
|
|
3945
|
+
report.changelog = releasedPackage?.changelog ?? null;
|
|
3946
|
+
report.adminCommitSummary = releasedPackage?.adminCommitSummary ?? null;
|
|
3808
3947
|
report.branch = STAGING_BRANCH;
|
|
3809
3948
|
publishWait.push({
|
|
3810
3949
|
name: report.name,
|
|
@@ -3815,16 +3954,41 @@ async function workflowRelease(helpers, input) {
|
|
|
3815
3954
|
const rootRelease = await executeJournalStep(root, workflowRun.runId, "release-root", () => {
|
|
3816
3955
|
setRootPackageJsonVersion(root, rootVersion);
|
|
3817
3956
|
run("git", ["checkout", STAGING_BRANCH], { cwd: gitRoot });
|
|
3818
|
-
|
|
3957
|
+
const rootCommitsBeforeChangelog = releaseHistoryCommits(gitRoot);
|
|
3958
|
+
const changelog = updateReleaseChangelog(gitRoot, {
|
|
3959
|
+
version: rootVersion,
|
|
3960
|
+
commits: rootCommitsBeforeChangelog,
|
|
3961
|
+
extraDependencyBullets: [
|
|
3962
|
+
`Release @treeseed/market ${rootVersion}.`,
|
|
3963
|
+
...versionLines(effectiveVersions).map((line) => `Release package ${line}.`)
|
|
3964
|
+
]
|
|
3965
|
+
});
|
|
3966
|
+
commitAllIfChanged(gitRoot, releaseAdminMessage({
|
|
3967
|
+
subject: `release: ${level} bump`,
|
|
3968
|
+
version: rootVersion,
|
|
3969
|
+
tagName: rootVersion,
|
|
3970
|
+
commits: rootCommitsBeforeChangelog,
|
|
3971
|
+
changelog,
|
|
3972
|
+
extraLines: versionLines(effectiveVersions).map((line) => `Package ${line}`)
|
|
3973
|
+
}));
|
|
3819
3974
|
pushBranch(gitRoot, STAGING_BRANCH);
|
|
3820
3975
|
const stagingCommit = headCommit(gitRoot);
|
|
3976
|
+
const rootCommits = releaseHistoryCommits(gitRoot);
|
|
3821
3977
|
let released;
|
|
3822
3978
|
let submoduleReconciliation = null;
|
|
3979
|
+
const mergeMessage = releaseAdminMessage({
|
|
3980
|
+
subject: `release: ${STAGING_BRANCH} -> ${PRODUCTION_BRANCH}`,
|
|
3981
|
+
version: rootVersion,
|
|
3982
|
+
tagName: rootVersion,
|
|
3983
|
+
commits: rootCommits,
|
|
3984
|
+
changelog,
|
|
3985
|
+
extraLines: versionLines(effectiveVersions).map((line) => `Package ${line}`)
|
|
3986
|
+
});
|
|
3823
3987
|
try {
|
|
3824
3988
|
released = mergeBranchIntoTarget(root, {
|
|
3825
3989
|
sourceBranch: STAGING_BRANCH,
|
|
3826
3990
|
targetBranch: PRODUCTION_BRANCH,
|
|
3827
|
-
message:
|
|
3991
|
+
message: mergeMessage,
|
|
3828
3992
|
pushTarget: false,
|
|
3829
3993
|
quietMerge: true
|
|
3830
3994
|
});
|
|
@@ -3835,7 +3999,7 @@ async function workflowRelease(helpers, input) {
|
|
|
3835
3999
|
}
|
|
3836
4000
|
helpers.write(`[release][reconcile] Resolving generated package pointer reconciliation for ${reconciliation.entries.map((entry) => String(entry.path)).join(", ")}.`);
|
|
3837
4001
|
submoduleReconciliation = reconciliation;
|
|
3838
|
-
commitAllIfChanged(gitRoot,
|
|
4002
|
+
commitAllIfChanged(gitRoot, mergeMessage);
|
|
3839
4003
|
released = { commitSha: headCommit(gitRoot) };
|
|
3840
4004
|
}
|
|
3841
4005
|
for (const pkg of checkedOutWorkspacePackageRepos(root)) {
|
|
@@ -3843,9 +4007,26 @@ async function workflowRelease(helpers, input) {
|
|
|
3843
4007
|
syncBranchWithOrigin(pkg.dir, PRODUCTION_BRANCH);
|
|
3844
4008
|
}
|
|
3845
4009
|
}
|
|
3846
|
-
|
|
4010
|
+
const mainPointerCommits = releaseHistoryCommits(gitRoot, released.commitSha, "HEAD");
|
|
4011
|
+
commitAllIfChanged(gitRoot, releaseAdminMessage({
|
|
4012
|
+
subject: "release: sync package main heads",
|
|
4013
|
+
version: rootVersion,
|
|
4014
|
+
tagName: rootVersion,
|
|
4015
|
+
sourceRef: "package main heads",
|
|
4016
|
+
targetRef: PRODUCTION_BRANCH,
|
|
4017
|
+
commits: mainPointerCommits,
|
|
4018
|
+
changelog,
|
|
4019
|
+
extraLines: versionLines(effectiveVersions).map((line) => `Main package ${line}`)
|
|
4020
|
+
}));
|
|
3847
4021
|
const releasedCommit = headCommit(gitRoot);
|
|
3848
|
-
const tag = ensureReleaseTag(gitRoot, rootVersion, releasedCommit
|
|
4022
|
+
const tag = ensureReleaseTag(gitRoot, rootVersion, releasedCommit, releaseAdminMessage({
|
|
4023
|
+
subject: `release: ${rootVersion}`,
|
|
4024
|
+
version: rootVersion,
|
|
4025
|
+
tagName: rootVersion,
|
|
4026
|
+
commits: rootCommits,
|
|
4027
|
+
changelog,
|
|
4028
|
+
extraLines: versionLines(effectiveVersions).map((line) => `Package ${line}`)
|
|
4029
|
+
}));
|
|
3849
4030
|
run("git", ["push", "origin", PRODUCTION_BRANCH], { cwd: gitRoot });
|
|
3850
4031
|
syncAllCheckedOutPackageRepos(root, STAGING_BRANCH);
|
|
3851
4032
|
syncBranchWithOrigin(gitRoot, STAGING_BRANCH);
|
|
@@ -3855,6 +4036,11 @@ async function workflowRelease(helpers, input) {
|
|
|
3855
4036
|
releasedCommit,
|
|
3856
4037
|
mergeCommit: released.commitSha,
|
|
3857
4038
|
tag,
|
|
4039
|
+
changelog,
|
|
4040
|
+
adminCommitSummary: {
|
|
4041
|
+
commitCount: rootCommits.length,
|
|
4042
|
+
notableCommits: rootCommits.slice(0, 12)
|
|
4043
|
+
},
|
|
3858
4044
|
submoduleReconciliation
|
|
3859
4045
|
};
|
|
3860
4046
|
});
|
|
@@ -3865,48 +4051,24 @@ async function workflowRelease(helpers, input) {
|
|
|
3865
4051
|
rootRepo.commitSha = String(rootRelease?.releasedCommit ?? headCommit(gitRoot));
|
|
3866
4052
|
rootRepo.tagName = String(rootRelease?.rootVersion ?? "");
|
|
3867
4053
|
const rootWorkflowGateResult = await executeJournalStep(root, workflowRun.runId, "release-root-gates", () => waitForWorkflowGates("release", [
|
|
3868
|
-
{
|
|
3869
|
-
name: rootRepo.name,
|
|
3870
|
-
repoPath: rootRepo.path,
|
|
3871
|
-
workflow: "verify.yml",
|
|
3872
|
-
branch: STAGING_BRANCH,
|
|
3873
|
-
headSha: String(rootRelease?.stagingCommit ?? "")
|
|
3874
|
-
},
|
|
3875
|
-
{
|
|
4054
|
+
releaseDeployGate({
|
|
3876
4055
|
name: rootRepo.name,
|
|
3877
4056
|
repoPath: rootRepo.path,
|
|
3878
4057
|
workflow: "deploy.yml",
|
|
3879
|
-
branch: STAGING_BRANCH,
|
|
3880
|
-
headSha: String(rootRelease?.stagingCommit ?? "")
|
|
3881
|
-
},
|
|
3882
|
-
{
|
|
3883
|
-
name: rootRepo.name,
|
|
3884
|
-
repoPath: rootRepo.path,
|
|
3885
|
-
workflow: "verify.yml",
|
|
3886
4058
|
branch: rootVersion,
|
|
3887
4059
|
headSha: String(rootRelease?.releasedCommit ?? rootRepo.commitSha ?? "")
|
|
3888
|
-
}
|
|
3889
|
-
{
|
|
3890
|
-
name: rootRepo.name,
|
|
3891
|
-
repoPath: rootRepo.path,
|
|
3892
|
-
workflow: "verify.yml",
|
|
3893
|
-
branch: PRODUCTION_BRANCH,
|
|
3894
|
-
headSha: String(rootRelease?.releasedCommit ?? rootRepo.commitSha ?? "")
|
|
3895
|
-
},
|
|
3896
|
-
{
|
|
3897
|
-
name: rootRepo.name,
|
|
3898
|
-
repoPath: rootRepo.path,
|
|
3899
|
-
workflow: "deploy.yml",
|
|
3900
|
-
branch: PRODUCTION_BRANCH,
|
|
3901
|
-
headSha: String(rootRelease?.releasedCommit ?? rootRepo.commitSha ?? "")
|
|
3902
|
-
}
|
|
4060
|
+
})
|
|
3903
4061
|
].filter((gate) => gate.headSha), ciMode, {
|
|
3904
4062
|
root,
|
|
3905
4063
|
runId: workflowRun.runId,
|
|
3906
4064
|
onProgress: (line, stream) => helpers.write(line, stream)
|
|
3907
4065
|
}).then((workflowGates) => ({ workflowGates })));
|
|
3908
4066
|
const hostedDeploymentState = recordHostedDeploymentStatesFromRootGates(root, rootRelease, rootWorkflowGateResult?.workflowGates);
|
|
3909
|
-
const releaseBackMerge = await executeJournalStep(root, workflowRun.runId, "release-back-merge", () => backMergeRootProductionIntoStaging(root, true
|
|
4067
|
+
const releaseBackMerge = await executeJournalStep(root, workflowRun.runId, "release-back-merge", () => backMergeRootProductionIntoStaging(root, true, {
|
|
4068
|
+
version: rootVersion,
|
|
4069
|
+
changelog: rootRelease?.changelog ?? null,
|
|
4070
|
+
selectedVersions: effectiveVersions
|
|
4071
|
+
}));
|
|
3910
4072
|
const devTagCleanupMode = effectiveInput.devTagCleanup ?? "safe-after-release";
|
|
3911
4073
|
const devTagCleanup = devTagCleanupMode === "off" ? (skipJournalStep(root, workflowRun.runId, "cleanup-dev-tags", { status: "skipped", reason: "disabled" }), { status: "skipped", reason: "disabled" }) : await executeJournalStep(root, workflowRun.runId, "cleanup-dev-tags", () => {
|
|
3912
4074
|
const activeDevTags = collectActiveDevTagReferences(root);
|