@treeseed/sdk 0.12.34 → 0.12.36

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.
@@ -222,6 +222,9 @@ function beamPackageAdapter(root, dir) {
222
222
  const versionSource = resolve(dir, versionSourceRel);
223
223
  const image = typeof manifest?.image === "string" && manifest.image.trim() ? manifest.image.trim() : id === "treedx" ? "treeseed/treedx" : null;
224
224
  const dockerArtifacts = manifestDockerArtifacts(manifest?.artifacts);
225
+ const dockerImages = stringRecord(manifest?.dockerImages);
226
+ const dockerImageReleaseWorkflow = stringValue(dockerImages.releaseWorkflow);
227
+ const dockerImageArchitectures = stringArray(dockerImages.architectures);
225
228
  const repository = stringValue(manifest?.repository) ?? (id === "treedx" ? "treeseed-ai/treedx" : null);
226
229
  const hostedVerifyWorkflow = stringValue(manifest?.hostedVerifyWorkflow) ?? stringValue(stringRecord(manifest?.releaseGate).workflow) ?? (existsSync(resolve(dir, ".github/workflows/release-gate.yml")) ? "release-gate.yml" : null);
227
230
  const projectArchitecture = normalizeTreeseedPackageProjectArchitecture(manifest?.projectArchitecture, id);
@@ -255,7 +258,7 @@ function beamPackageAdapter(root, dir) {
255
258
  context: artifact.context ?? ".",
256
259
  target: artifact.target,
257
260
  role: artifact.role ?? id,
258
- architectures: artifact.architectures.length > 0 ? artifact.architectures : stringArray(stringRecord(manifest?.dockerImages).architectures)
261
+ architectures: artifact.architectures.length > 0 ? artifact.architectures : dockerImageArchitectures
259
262
  })) : image ? [{
260
263
  provider: "docker",
261
264
  name: image,
@@ -264,7 +267,7 @@ function beamPackageAdapter(root, dir) {
264
267
  context: ".",
265
268
  target: null,
266
269
  role: id,
267
- architectures: stringArray(stringRecord(manifest?.dockerImages).architectures)
270
+ architectures: dockerImageArchitectures
268
271
  }] : [],
269
272
  releaseChecks: dockerArtifacts.length > 0 ? dockerArtifacts.map((artifact) => ({ kind: "docker-manifest", name: `${artifact.name} Docker image manifest`, detail: `${artifact.name}:${version ?? "<version>"}` })) : image ? [{ kind: "docker-manifest", name: "Docker image manifest", detail: `${image}:${version ?? "<version>"}` }] : [],
270
273
  metadata: {
@@ -272,7 +275,9 @@ function beamPackageAdapter(root, dir) {
272
275
  hasDockerfile: existsSync(resolve(dir, "Dockerfile")),
273
276
  repository,
274
277
  deploymentSource: stringRecord(manifest?.deploymentSource),
275
- imageHosting: stringRecord(stringRecord(manifest?.dockerImages).hosting),
278
+ dockerImageReleaseWorkflow: dockerImageReleaseWorkflow ? `.github/workflows/${dockerImageReleaseWorkflow}` : null,
279
+ dockerImageArchitectures,
280
+ imageHosting: stringRecord(dockerImages.hosting),
276
281
  versionSource: versionSourceRel,
277
282
  ...hostedVerifyWorkflow ? {
278
283
  hostedVerifyWorkflow: hostedVerifyWorkflow.startsWith(".github/workflows/") ? hostedVerifyWorkflow : `.github/workflows/${hostedVerifyWorkflow}`
@@ -818,6 +823,9 @@ function shellQuoteWorkflowArg(value) {
818
823
  return `'${value.replace(/'/gu, `'\\''`)}'`;
819
824
  }
820
825
  function workflowTemplatesForAdapter(adapter) {
826
+ if (adapter.metadata.workflowTemplateVersion === "custom") {
827
+ return [];
828
+ }
821
829
  const hasDocker = adapter.artifacts.some((artifact) => artifact.provider === "docker");
822
830
  const hasNpm = adapter.artifacts.some((artifact) => artifact.provider === "npm");
823
831
  return [
@@ -70,6 +70,7 @@ type WorkflowApplicationSelection = {
70
70
  }>;
71
71
  source: 'changed-paths' | 'package-selection' | 'default';
72
72
  };
73
+ export declare function orderReleasePackageNames(packageNames: string[]): string[];
73
74
  export declare function workflowProof(helpers: WorkflowOperationHelpers, input?: TreeseedProofInput): Promise<TreeseedWorkflowResult<Record<string, unknown> & {
74
75
  finalState?: WorkflowStatePayload;
75
76
  timing?: TreeseedWorkflowTiming;
@@ -980,9 +981,9 @@ export declare function workflowRelease(helpers: WorkflowOperationHelpers, input
980
981
  stagingBranch: string;
981
982
  productionBranch: string;
982
983
  packageSelection: {
983
- changed: any[];
984
- dependents: any[];
985
- selected: any[];
984
+ changed: string[];
985
+ dependents: string[];
986
+ selected: string[];
986
987
  };
987
988
  plannedVersions: any;
988
989
  stableDependencyVersions: Record<string, string>;
@@ -995,13 +996,14 @@ export declare function workflowRelease(helpers: WorkflowOperationHelpers, input
995
996
  spec: string;
996
997
  reason: string;
997
998
  }[];
999
+ releaseOrder: string[];
998
1000
  plannedPublishWaits: {
999
- name: any;
1001
+ name: string;
1000
1002
  workflow: string;
1001
1003
  branch: string;
1002
1004
  status: string;
1003
1005
  }[];
1004
- touchedPackages: any[];
1006
+ touchedPackages: string[];
1005
1007
  repos: WorkflowRepoReport[];
1006
1008
  rootRepo: WorkflowRepoReport;
1007
1009
  finalBranch: string;
@@ -1256,9 +1258,9 @@ export declare function workflowRelease(helpers: WorkflowOperationHelpers, input
1256
1258
  stagingBranch: string;
1257
1259
  productionBranch: string;
1258
1260
  packageSelection: {
1259
- changed: any[];
1260
- dependents: any[];
1261
- selected: any[];
1261
+ changed: string[];
1262
+ dependents: string[];
1263
+ selected: string[];
1262
1264
  };
1263
1265
  plannedVersions: any;
1264
1266
  stableDependencyVersions: Record<string, string>;
@@ -1271,8 +1273,9 @@ export declare function workflowRelease(helpers: WorkflowOperationHelpers, input
1271
1273
  spec: string;
1272
1274
  reason: string;
1273
1275
  }[];
1276
+ releaseOrder: string[];
1274
1277
  plannedPublishWaits: {
1275
- name: any;
1278
+ name: string;
1276
1279
  workflow: string;
1277
1280
  branch: string;
1278
1281
  status: string;
@@ -2006,9 +2006,9 @@ function failWorkflowRun(root, runId, error, recovery) {
2006
2006
  releaseWorkflowLock(root, runId);
2007
2007
  }
2008
2008
  function validatePackageReleaseWorkflows(root, packageNames) {
2009
- const missing = checkedOutWorkspacePackageRepos(root).filter((pkg) => packageNames.includes(pkg.name)).filter((pkg) => !existsSync(resolve(pkg.dir, ".github/workflows/publish.yml"))).map((pkg) => pkg.name);
2009
+ const missing = checkedOutWorkspacePackageRepos(root).filter((pkg) => packageNames.includes(pkg.name)).map((pkg) => ({ pkg, workflow: releaseWorkflowForPackage(root, pkg.name) })).filter((entry) => !existsSync(resolve(entry.pkg.dir, ".github/workflows", entry.workflow))).map((entry) => `${entry.pkg.name} (${entry.workflow})`);
2010
2010
  if (missing.length > 0) {
2011
- workflowError("release", "workflow_contract_missing", `Treeseed release requires .github/workflows/publish.yml in: ${missing.join(", ")}.`, {
2011
+ workflowError("release", "workflow_contract_missing", `Treeseed release requires package release workflows in: ${missing.join(", ")}.`, {
2012
2012
  details: {
2013
2013
  missing
2014
2014
  }
@@ -2016,9 +2016,9 @@ function validatePackageReleaseWorkflows(root, packageNames) {
2016
2016
  }
2017
2017
  }
2018
2018
  function releaseWorkflowForPackage(root, packageName) {
2019
- void root;
2020
- void packageName;
2021
- return "publish.yml";
2019
+ const adapter = discoverTreeseedPackageAdapters(root).find((entry) => entry.id === packageName || entry.name === packageName);
2020
+ const configured = typeof adapter?.metadata?.dockerImageReleaseWorkflow === "string" ? adapter.metadata.dockerImageReleaseWorkflow : null;
2021
+ return configured && configured.trim() ? configured.trim().replace(/^\.github\/workflows\//u, "") : "publish.yml";
2022
2022
  }
2023
2023
  function productionDeployWorkflowForPackage(root, packageName) {
2024
2024
  const adapter = discoverTreeseedPackageAdapters(root).find((entry) => entry.id === packageName || entry.name === packageName);
@@ -2251,6 +2251,30 @@ function releasePlanPackageSelection(value) {
2251
2251
  selected: Array.isArray(record.selected) ? record.selected.map(String) : []
2252
2252
  };
2253
2253
  }
2254
+ const RELEASE_PACKAGE_DEPENDENCIES = {
2255
+ "@treeseed/api": ["treedx"]
2256
+ };
2257
+ function orderReleasePackageNames(packageNames) {
2258
+ const selected = new Set(packageNames);
2259
+ const ordered = [];
2260
+ const visiting = /* @__PURE__ */ new Set();
2261
+ const visited = /* @__PURE__ */ new Set();
2262
+ const visit = (name) => {
2263
+ if (visited.has(name)) return;
2264
+ if (visiting.has(name)) {
2265
+ throw new Error(`Cycle detected in release package dependency order at ${name}.`);
2266
+ }
2267
+ visiting.add(name);
2268
+ for (const dependency of RELEASE_PACKAGE_DEPENDENCIES[name] ?? []) {
2269
+ if (selected.has(dependency)) visit(dependency);
2270
+ }
2271
+ visiting.delete(name);
2272
+ visited.add(name);
2273
+ ordered.push(name);
2274
+ };
2275
+ for (const name of packageNames) visit(name);
2276
+ return ordered;
2277
+ }
2254
2278
  function stableDependencyVersionsForReleaseLine(root, options) {
2255
2279
  const targetLine = typeof options.targetLine === "string" ? options.targetLine : null;
2256
2280
  const group = new Set(Array.isArray(options.group) ? options.group.map(String) : []);
@@ -2492,7 +2516,7 @@ function buildReleasePlanSnapshot(input) {
2492
2516
  versionPlan.versions.set(adapter.id, incrementVersion(adapter.version, input.level));
2493
2517
  }
2494
2518
  }
2495
- const plannedSelected = [...versionPlan.selected].filter((name) => versionPlan.versions.has(name));
2519
+ const plannedSelected = orderReleasePackageNames([...versionPlan.selected].filter((name) => versionPlan.versions.has(name)));
2496
2520
  const plannedChanged = input.repairVersionLine === true ? plannedSelected : Array.from(new Set(input.packageSelection.changed.filter((name) => plannedSelected.includes(name))));
2497
2521
  const plannedDependents = plannedSelected.filter((name) => !plannedChanged.includes(name));
2498
2522
  const plannedPackageSelection = {
@@ -2528,6 +2552,7 @@ function buildReleasePlanSnapshot(input) {
2528
2552
  stableDependencyVersions,
2529
2553
  applicationSelection,
2530
2554
  plannedDevReferenceRewrites,
2555
+ releaseOrder: plannedPackageSelection.selected,
2531
2556
  plannedPublishWaits: plannedPackageSelection.selected.map((name) => ({
2532
2557
  name,
2533
2558
  workflow: releaseWorkflowForPackage(input.root, name),
@@ -5717,7 +5742,10 @@ ${rendered}`);
5717
5742
  };
5718
5743
  });
5719
5744
  const packageReleases = [];
5720
- for (const pkg of checkedOutWorkspacePackageRepos(root).filter((entry) => selectedPackageSet.has(entry.name))) {
5745
+ const packageRepoByName = new Map(checkedOutWorkspacePackageRepos(root).map((entry) => [entry.name, entry]));
5746
+ for (const packageName of selectedPackageNames) {
5747
+ const pkg = packageRepoByName.get(packageName);
5748
+ if (!pkg) continue;
5721
5749
  const version = selectedVersions.get(pkg.name);
5722
5750
  if (!version) continue;
5723
5751
  const packageRelease = await executeJournalStep(root, workflowRun.runId, `release-${pkg.name}`, async () => {
@@ -5832,7 +5860,7 @@ ${rendered}`);
5832
5860
  }).then((workflowGates) => ({ workflowGates })));
5833
5861
  const productionWebVerification = await executeJournalStep(root, workflowRun.runId, "production-web-live-verification", () => runReleaseWebLiveVerification(root, "prod", helpers, "release"));
5834
5862
  const backMerge = await executeJournalStep(root, workflowRun.runId, "release-back-merge", () => {
5835
- const packageBackMerges = checkedOutWorkspacePackageRepos(root).filter((pkg) => selectedPackageSet.has(pkg.name)).map((pkg) => backMergeProductionIntoStaging(pkg.dir, pkg.name, releaseAdminMessage({
5863
+ const packageBackMerges = selectedPackageNames.map((name) => packageRepoByName.get(name)).filter((pkg) => Boolean(pkg)).map((pkg) => backMergeProductionIntoStaging(pkg.dir, pkg.name, releaseAdminMessage({
5836
5864
  subject: `release: back-merge ${PRODUCTION_BRANCH} into ${STAGING_BRANCH}`,
5837
5865
  version: selectedVersions.get(pkg.name) ?? null,
5838
5866
  sourceRef: PRODUCTION_BRANCH,
@@ -6234,6 +6262,7 @@ export {
6234
6262
  normalizeReleaseCandidateMode,
6235
6263
  normalizeSaveCiMode,
6236
6264
  normalizeSaveLane,
6265
+ orderReleasePackageNames,
6237
6266
  reconcileTreeseedBranchPreview,
6238
6267
  shouldUseHostedSaveCi,
6239
6268
  workflowCi,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@treeseed/sdk",
3
- "version": "0.12.34",
3
+ "version": "0.12.36",
4
4
  "description": "Shared Treeseed SDK for content-backed and D1-backed object models.",
5
5
  "license": "AGPL-3.0-only",
6
6
  "repository": {