@treeseed/sdk 0.12.42 → 0.12.44
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.
|
@@ -8,6 +8,7 @@ import { resolveTreeseedWorkflowState, type TreeseedWorkflowStatusOptions } from
|
|
|
8
8
|
import { type TreeseedReconcileResult } from '../reconcile/index.js';
|
|
9
9
|
import { type TreeseedWorkflowRunCommand, type TreeseedWorkflowRunJournal } from './runs.js';
|
|
10
10
|
import { type TreeseedWorkflowMode } from './session.js';
|
|
11
|
+
import { type TreeseedManagedRepository } from '../operations/services/managed-repositories.js';
|
|
11
12
|
import type { TreeseedCloseInput, TreeseedCiInput, TreeseedConfigInput, TreeseedDestroyInput, TreeseedExportInput, TreeseedReleaseCandidateInput, TreeseedReleaseInput, TreeseedRecoverInput, TreeseedResumeInput, TreeseedSaveInput, TreeseedStageInput, TreeseedSwitchInput, TreeseedTaskBranchMetadata, TreeseedUpdateInput, TreeseedWorkflowContext, TreeseedWorkflowCiMode, TreeseedWorkflowDevInput, TreeseedWorkflowExecutionMode, TreeseedWorkflowOperationId, TreeseedWorkflowResult, TreeseedWorkflowWorktreeMode, TreeseedReleaseCandidateMode, TreeseedProofInput } from '../workflow.js';
|
|
12
13
|
type WorkflowWrite = NonNullable<TreeseedWorkflowContext['write']>;
|
|
13
14
|
type WorkflowStatePayload = ReturnType<typeof resolveTreeseedWorkflowState>;
|
|
@@ -845,6 +846,7 @@ type StageRepoPlan = {
|
|
|
845
846
|
name: string;
|
|
846
847
|
path: string;
|
|
847
848
|
kind: 'root' | 'managed';
|
|
849
|
+
repoKind?: TreeseedManagedRepository['kind'];
|
|
848
850
|
sourceBranch: string;
|
|
849
851
|
targetBranch: typeof STAGING_BRANCH;
|
|
850
852
|
remoteSourceExists: boolean;
|
|
@@ -957,6 +959,12 @@ export declare function workflowRelease(helpers: WorkflowOperationHelpers, input
|
|
|
957
959
|
sceneArtifacts: "full" | "screenshots";
|
|
958
960
|
releaseImageRefs: Record<string, string>;
|
|
959
961
|
localCleanup: import("../workflow-support.js").TreeseedLocalCleanupReport | null;
|
|
962
|
+
releaseHelperRepos: {
|
|
963
|
+
name: string;
|
|
964
|
+
kind: import("../operations/services/managed-repositories.js").TreeseedManagedRepositoryKind;
|
|
965
|
+
path: string;
|
|
966
|
+
remote: string | null;
|
|
967
|
+
}[];
|
|
960
968
|
autoResumeCandidate: {
|
|
961
969
|
runId: string;
|
|
962
970
|
branch: string | null;
|
|
@@ -1045,6 +1053,30 @@ export declare function workflowRelease(helpers: WorkflowOperationHelpers, input
|
|
|
1045
1053
|
workspaceUnlink: import("../operations/services/workspace-dependency-mode.js").WorkspaceDependencyModeReport;
|
|
1046
1054
|
};
|
|
1047
1055
|
packageReleases: Record<string, unknown>[];
|
|
1056
|
+
managedHelperReleases: {
|
|
1057
|
+
status: string;
|
|
1058
|
+
repos: {
|
|
1059
|
+
name: string;
|
|
1060
|
+
kind: import("../operations/services/managed-repositories.js").TreeseedManagedRepositoryKind;
|
|
1061
|
+
path: string;
|
|
1062
|
+
stagingHead: string;
|
|
1063
|
+
promotion: {
|
|
1064
|
+
targetBranch: string;
|
|
1065
|
+
expectedBefore: string | null;
|
|
1066
|
+
commitSha: string;
|
|
1067
|
+
pushed: boolean;
|
|
1068
|
+
verified: boolean;
|
|
1069
|
+
};
|
|
1070
|
+
backMerge: {
|
|
1071
|
+
status: string;
|
|
1072
|
+
merged: boolean;
|
|
1073
|
+
repoName: string;
|
|
1074
|
+
sourceBranch: string;
|
|
1075
|
+
targetBranch: string;
|
|
1076
|
+
commitSha: string;
|
|
1077
|
+
};
|
|
1078
|
+
}[];
|
|
1079
|
+
};
|
|
1048
1080
|
rootRelease: {
|
|
1049
1081
|
name: string;
|
|
1050
1082
|
version: string;
|
|
@@ -1248,6 +1280,12 @@ export declare function workflowRelease(helpers: WorkflowOperationHelpers, input
|
|
|
1248
1280
|
sceneArtifacts: "full" | "screenshots";
|
|
1249
1281
|
releaseImageRefs: Record<string, string>;
|
|
1250
1282
|
localCleanup: import("../workflow-support.js").TreeseedLocalCleanupReport | null;
|
|
1283
|
+
releaseHelperRepos: {
|
|
1284
|
+
name: string;
|
|
1285
|
+
kind: import("../operations/services/managed-repositories.js").TreeseedManagedRepositoryKind;
|
|
1286
|
+
path: string;
|
|
1287
|
+
remote: string | null;
|
|
1288
|
+
}[];
|
|
1251
1289
|
freshArchivedRuns: never[];
|
|
1252
1290
|
autoResumeCandidate: {
|
|
1253
1291
|
runId: string;
|
|
@@ -2265,6 +2265,28 @@ function backMergeProductionIntoStaging(repoDir, repoName, message) {
|
|
|
2265
2265
|
commitSha: headCommit(repoDir)
|
|
2266
2266
|
};
|
|
2267
2267
|
}
|
|
2268
|
+
function releaseHelperRepoToProduction(repo) {
|
|
2269
|
+
syncBranchWithOrigin(repo.dir, STAGING_BRANCH);
|
|
2270
|
+
if (!remoteBranchExists(repo.dir, STAGING_BRANCH)) {
|
|
2271
|
+
throw new Error(`${repo.name} has no origin/${STAGING_BRANCH} branch to release.`);
|
|
2272
|
+
}
|
|
2273
|
+
const stagingHead = remoteHeadCommit(repo.dir, STAGING_BRANCH);
|
|
2274
|
+
const promotion = promoteCommitToProductionBranch(repo.dir, stagingHead);
|
|
2275
|
+
const backMerge = backMergeProductionIntoStaging(repo.dir, repo.name, releaseAdminMessage({
|
|
2276
|
+
subject: `release: back-merge ${PRODUCTION_BRANCH} into ${STAGING_BRANCH}`,
|
|
2277
|
+
version: null,
|
|
2278
|
+
sourceRef: PRODUCTION_BRANCH,
|
|
2279
|
+
targetRef: STAGING_BRANCH
|
|
2280
|
+
}));
|
|
2281
|
+
return {
|
|
2282
|
+
name: repo.name,
|
|
2283
|
+
kind: repo.kind,
|
|
2284
|
+
path: repo.relativeDir,
|
|
2285
|
+
stagingHead,
|
|
2286
|
+
promotion,
|
|
2287
|
+
backMerge
|
|
2288
|
+
};
|
|
2289
|
+
}
|
|
2268
2290
|
function backMergeRootProductionIntoStaging(root, syncPackageStagingHeads, options = {}) {
|
|
2269
2291
|
const gitRoot = repoRoot(root);
|
|
2270
2292
|
const commits = releaseHistoryCommits(gitRoot, STAGING_BRANCH, `origin/${PRODUCTION_BRANCH}`);
|
|
@@ -2309,6 +2331,27 @@ function releasePlanStableDependencyVersionMap(plannedRelease) {
|
|
|
2309
2331
|
const stableDependencyVersions = plannedRelease.stableDependencyVersions && typeof plannedRelease.stableDependencyVersions === "object" && !Array.isArray(plannedRelease.stableDependencyVersions) ? plannedRelease.stableDependencyVersions : {};
|
|
2310
2332
|
return new Map(Object.entries(stableDependencyVersions).map(([name, version]) => [name, String(version)]));
|
|
2311
2333
|
}
|
|
2334
|
+
function collectReleaseHelperRepoBlockers(root) {
|
|
2335
|
+
const blockers = [];
|
|
2336
|
+
for (const repo of checkedOutReleaseHelperRepos(root)) {
|
|
2337
|
+
const branch = currentBranch(repo.dir) || null;
|
|
2338
|
+
if (hasMeaningfulChanges(repo.dir)) {
|
|
2339
|
+
blockers.push(`${repo.name} has uncommitted changes.`);
|
|
2340
|
+
}
|
|
2341
|
+
if (branch !== STAGING_BRANCH) {
|
|
2342
|
+
blockers.push(`${repo.name} is on ${branch ?? "(detached)"} instead of ${STAGING_BRANCH}.`);
|
|
2343
|
+
}
|
|
2344
|
+
try {
|
|
2345
|
+
originRemoteUrl(repo.dir);
|
|
2346
|
+
} catch {
|
|
2347
|
+
blockers.push(`${repo.name} has no readable origin remote.`);
|
|
2348
|
+
}
|
|
2349
|
+
if (!remoteBranchExists(repo.dir, STAGING_BRANCH)) {
|
|
2350
|
+
blockers.push(`${repo.name} has no origin/${STAGING_BRANCH} branch.`);
|
|
2351
|
+
}
|
|
2352
|
+
}
|
|
2353
|
+
return blockers;
|
|
2354
|
+
}
|
|
2312
2355
|
function releasePlanPackageSelection(value) {
|
|
2313
2356
|
const record = value && typeof value === "object" ? value : {};
|
|
2314
2357
|
return {
|
|
@@ -5043,16 +5086,38 @@ function writeStageCandidateManifest(root, runId, manifest) {
|
|
|
5043
5086
|
}
|
|
5044
5087
|
return manifest;
|
|
5045
5088
|
}
|
|
5046
|
-
function
|
|
5047
|
-
|
|
5089
|
+
function dedupeManagedReposByRemote(repos) {
|
|
5090
|
+
const seen = /* @__PURE__ */ new Set();
|
|
5091
|
+
const deduped = [];
|
|
5092
|
+
for (const repo of repos) {
|
|
5093
|
+
const key = repo.remoteUrl ? `remote:${repo.remoteUrl}` : `path:${repo.dir}`;
|
|
5094
|
+
if (seen.has(key)) continue;
|
|
5095
|
+
seen.add(key);
|
|
5096
|
+
deduped.push(repo);
|
|
5097
|
+
}
|
|
5098
|
+
return deduped;
|
|
5099
|
+
}
|
|
5100
|
+
function checkedOutStagePromotionRepos(root) {
|
|
5101
|
+
return dedupeManagedReposByRemote(checkedOutManagedWorkflowRepos(root).filter((repo) => repo.kind === "package" || repo.kind === "template" || repo.kind === "fixture"));
|
|
5102
|
+
}
|
|
5103
|
+
function checkedOutReleaseHelperRepos(root) {
|
|
5104
|
+
return dedupeManagedReposByRemote(checkedOutManagedWorkflowRepos(root).filter((repo) => repo.kind === "template" || repo.kind === "fixture"));
|
|
5105
|
+
}
|
|
5106
|
+
function syncAllCheckedOutReleaseHelperRepos(root, branchName) {
|
|
5107
|
+
for (const repo of checkedOutManagedWorkflowRepos(root).filter((entry) => entry.kind === "template" || entry.kind === "fixture")) {
|
|
5108
|
+
if (remoteBranchExists(repo.dir, branchName)) {
|
|
5109
|
+
syncBranchWithOrigin(repo.dir, branchName);
|
|
5110
|
+
}
|
|
5111
|
+
}
|
|
5048
5112
|
}
|
|
5049
5113
|
function buildStagePromotionPlan(root, branchName, input) {
|
|
5050
5114
|
const gitRoot = repoRoot(root);
|
|
5051
5115
|
const repos = [
|
|
5052
|
-
...
|
|
5116
|
+
...checkedOutStagePromotionRepos(root).map((repo) => ({
|
|
5053
5117
|
name: repo.name,
|
|
5054
5118
|
path: repo.dir,
|
|
5055
5119
|
kind: "managed",
|
|
5120
|
+
repoKind: repo.kind,
|
|
5056
5121
|
sourceBranch: branchName,
|
|
5057
5122
|
targetBranch: STAGING_BRANCH,
|
|
5058
5123
|
remoteSourceExists: remoteBranchExists(repo.dir, branchName),
|
|
@@ -5149,6 +5214,7 @@ function createStageCandidateManifest(root, runId, branchName, plan, verificatio
|
|
|
5149
5214
|
packages: packageRepos.map((repo) => ({
|
|
5150
5215
|
name: repo.name,
|
|
5151
5216
|
path: repo.path,
|
|
5217
|
+
repoKind: repo.repoKind,
|
|
5152
5218
|
commit: headCommit(repo.path),
|
|
5153
5219
|
remote: (() => {
|
|
5154
5220
|
try {
|
|
@@ -5165,7 +5231,7 @@ function createStageCandidateManifest(root, runId, branchName, plan, verificatio
|
|
|
5165
5231
|
}
|
|
5166
5232
|
function cleanupStageSourceBranches(root, branchName, manifest) {
|
|
5167
5233
|
const results = [];
|
|
5168
|
-
for (const repo of
|
|
5234
|
+
for (const repo of checkedOutStagePromotionRepos(root)) {
|
|
5169
5235
|
const manifestRepo = manifest.packages.find((entry) => entry.name === repo.name);
|
|
5170
5236
|
if (!manifestRepo) continue;
|
|
5171
5237
|
const remoteDeleted = deleteRemoteBranch(repo.dir, branchName);
|
|
@@ -5320,7 +5386,7 @@ ${currentBlockers.map((entry) => `- ${entry}`).join("\n")}`, {
|
|
|
5320
5386
|
const mergeDown = await executeJournalStep(root, workflowRun.runId, "merge-staging-down", () => {
|
|
5321
5387
|
const results = [];
|
|
5322
5388
|
try {
|
|
5323
|
-
for (const repo of
|
|
5389
|
+
for (const repo of checkedOutStagePromotionRepos(root)) {
|
|
5324
5390
|
if (!remoteBranchExists(repo.dir, featureBranch)) {
|
|
5325
5391
|
results.push({ name: repo.name, path: repo.dir, skipped: true, reason: "remote-branch-missing" });
|
|
5326
5392
|
continue;
|
|
@@ -5622,6 +5688,7 @@ async function workflowRelease(helpers, input) {
|
|
|
5622
5688
|
const rootRepo = createWorkspaceRootRepoReport(root);
|
|
5623
5689
|
traceReleaseStartup("inspect package repos");
|
|
5624
5690
|
const packageReports = createWorkspacePackageReports(root);
|
|
5691
|
+
const releaseHelperRepos = checkedOutReleaseHelperRepos(root);
|
|
5625
5692
|
const explicitResumeRunId = helpers.context.workflow?.resumeRunId ?? null;
|
|
5626
5693
|
traceReleaseStartup("check auto resume");
|
|
5627
5694
|
const autoResumeRun = executionMode === "execute" && !explicitResumeRunId && input.fresh !== true ? findAutoResumableReleaseRun(root, session.branchName, rootRepo, packageReports, { archiveStale: false }) : null;
|
|
@@ -5653,6 +5720,7 @@ async function workflowRelease(helpers, input) {
|
|
|
5653
5720
|
level,
|
|
5654
5721
|
repairVersionLine: effectiveInput.repairVersionLine === true
|
|
5655
5722
|
});
|
|
5723
|
+
blockers.push(...collectReleaseHelperRepoBlockers(root));
|
|
5656
5724
|
const selectedVersions = releasePlanVersionMap(plannedRelease.plannedVersions);
|
|
5657
5725
|
const releaseImageVersions = productionReleaseImageRefVersions(root, selectedVersions);
|
|
5658
5726
|
const releaseImageRefs = productionReleaseImageRefEnv(releaseImageVersions);
|
|
@@ -5673,6 +5741,12 @@ async function workflowRelease(helpers, input) {
|
|
|
5673
5741
|
sceneArtifacts: normalizeSceneArtifactsMode(effectiveInput.sceneArtifacts),
|
|
5674
5742
|
releaseImageRefs,
|
|
5675
5743
|
localCleanup,
|
|
5744
|
+
releaseHelperRepos: releaseHelperRepos.map((repo) => ({
|
|
5745
|
+
name: repo.name,
|
|
5746
|
+
kind: repo.kind,
|
|
5747
|
+
path: repo.relativeDir,
|
|
5748
|
+
remote: repo.remoteUrl
|
|
5749
|
+
})),
|
|
5676
5750
|
freshArchivedRuns: [],
|
|
5677
5751
|
autoResumeCandidate: planAutoResumeRun ? {
|
|
5678
5752
|
runId: planAutoResumeRun.runId,
|
|
@@ -5740,6 +5814,14 @@ ${blockers.join("\n")}`, {
|
|
|
5740
5814
|
resumable: true
|
|
5741
5815
|
};
|
|
5742
5816
|
}),
|
|
5817
|
+
{
|
|
5818
|
+
id: "release-helper-repos",
|
|
5819
|
+
description: "Promote starter templates and shared fixture repositories from staging to production",
|
|
5820
|
+
repoName: rootRepo.name,
|
|
5821
|
+
repoPath: rootRepo.path,
|
|
5822
|
+
branch: STAGING_BRANCH,
|
|
5823
|
+
resumable: true
|
|
5824
|
+
},
|
|
5743
5825
|
{ id: "verify-published-artifacts", description: "Verify immutable registry artifacts exist after publish workflows", repoName: rootRepo.name, repoPath: rootRepo.path, branch: PRODUCTION_BRANCH, resumable: true },
|
|
5744
5826
|
{ id: "production-package-deploy-workflows", description: "Wait for production package deploy workflows before live verification", repoName: rootRepo.name, repoPath: rootRepo.path, branch: PRODUCTION_BRANCH, resumable: true },
|
|
5745
5827
|
{ id: "production-hosting", description: "Reconcile and live-verify production hosted resources before root deploy", repoName: rootRepo.name, repoPath: rootRepo.path, branch: PRODUCTION_BRANCH, resumable: true },
|
|
@@ -5861,6 +5943,11 @@ ${rendered}`);
|
|
|
5861
5943
|
});
|
|
5862
5944
|
packageReleases.push(packageRelease);
|
|
5863
5945
|
}
|
|
5946
|
+
const managedHelperReleases = await executeJournalStep(root, workflowRun.runId, "release-helper-repos", () => {
|
|
5947
|
+
const releases = releaseHelperRepos.map((repo) => releaseHelperRepoToProduction(repo));
|
|
5948
|
+
syncAllCheckedOutReleaseHelperRepos(root, STAGING_BRANCH);
|
|
5949
|
+
return { status: "completed", repos: releases };
|
|
5950
|
+
});
|
|
5864
5951
|
const publishedArtifacts = await executeJournalStep(root, workflowRun.runId, "verify-published-artifacts", () => verifyPublishedReleaseArtifacts(selectedVersions));
|
|
5865
5952
|
const productionPackageDeployWorkflows = await executeJournalStep(root, workflowRun.runId, "production-package-deploy-workflows", () => {
|
|
5866
5953
|
const deployGates = productionPackageDeployGates(root, allVersions);
|
|
@@ -5950,6 +6037,7 @@ ${rendered}`);
|
|
|
5950
6037
|
workspaceUnlink,
|
|
5951
6038
|
releaseMetadata,
|
|
5952
6039
|
packageReleases,
|
|
6040
|
+
managedHelperReleases,
|
|
5953
6041
|
rootRelease,
|
|
5954
6042
|
publishWait: publishWait.workflowGates,
|
|
5955
6043
|
publishedArtifacts,
|