@kungfu-tech/buildchain 3.0.4-alpha.6 → 3.0.4-alpha.8

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.
@@ -74,6 +74,7 @@ export {
74
74
  collectPaperFleetAudit,
75
75
  discoverPaperFleet,
76
76
  planPaperFleetUpdate,
77
+ paperFleetTransitionWorkspace,
77
78
  writePaperFleetUpdate,
78
79
  } from "./paper-fleet.js";
79
80
 
@@ -113,6 +114,7 @@ const PAPER_SCAFFOLD_PATHS = Object.freeze([
113
114
  PAPER_PATHS.buildWorkflow,
114
115
  PAPER_PATHS.verifyWorkflow,
115
116
  PAPER_PATHS.releaseWorkflow,
117
+ PAPER_PATHS.pnpmWorkspace,
116
118
  PAPER_PATHS.provisioningAuthority,
117
119
  "Makefile",
118
120
  "package.json",
@@ -134,6 +136,7 @@ const DEFAULT_TOOLCHAIN_COMMAND = "latexmk -pdf -outdir=_build paper/main.tex";
134
136
  const SHA256_PATTERN = /^sha256:[0-9a-f]{64}$/i;
135
137
  const GIT_SHA_PATTERN = /^[0-9a-f]{40}$/i;
136
138
  const PACKAGE_PATTERN = /^(?:@[a-z0-9][a-z0-9._-]*\/)?[a-z0-9][a-z0-9._-]*$/i;
139
+ const BUILDCHAIN_PACKAGE_NAME = "@kungfu-tech/buildchain";
137
140
 
138
141
  function toPosix(value) {
139
142
  return String(value || "")
@@ -149,6 +152,66 @@ function jsonText(value) {
149
152
  return `${JSON.stringify(value, null, 2)}\n`;
150
153
  }
151
154
 
155
+ function paperPnpmWorkspace(current, buildchainVersion) {
156
+ const entry = `${BUILDCHAIN_PACKAGE_NAME}@${buildchainVersion}`;
157
+ const source = String(current || "");
158
+ const lines = source ? source.replace(/\r\n/g, "\n").split("\n") : [];
159
+ if (lines.at(-1) === "") lines.pop();
160
+ const keyLines = lines
161
+ .map((line, index) =>
162
+ /^minimumReleaseAgeExclude:\s*(?:#.*)?$/.test(line) ? index : -1,
163
+ )
164
+ .filter((index) => index >= 0);
165
+ const unsupportedKey = lines.some(
166
+ (line) =>
167
+ /^minimumReleaseAgeExclude\s*:/.test(line) &&
168
+ !/^minimumReleaseAgeExclude:\s*(?:#.*)?$/.test(line),
169
+ );
170
+ if (unsupportedKey || keyLines.length > 1) {
171
+ throw new Error(
172
+ "paper migration requires minimumReleaseAgeExclude to be one top-level block sequence",
173
+ );
174
+ }
175
+ if (keyLines.length === 0) {
176
+ const prefix = lines.length > 0 ? [...lines, ""] : [];
177
+ return `${[...prefix, "minimumReleaseAgeExclude:", ` - '${entry}'`].join(
178
+ "\n",
179
+ )}\n`;
180
+ }
181
+ const keyIndex = keyLines[0];
182
+ let blockEnd = lines.length;
183
+ for (let index = keyIndex + 1; index < lines.length; index += 1) {
184
+ if (/^[^\s#]/.test(lines[index])) {
185
+ blockEnd = index;
186
+ break;
187
+ }
188
+ }
189
+ const retained = [];
190
+ for (const line of lines.slice(keyIndex + 1, blockEnd)) {
191
+ if (!line.trim() || /^\s*#/.test(line)) {
192
+ retained.push(line);
193
+ continue;
194
+ }
195
+ const item = line.match(/^\s*-\s+(.+?)\s*(?:#.*)?$/);
196
+ if (!item) {
197
+ throw new Error(
198
+ "paper migration requires minimumReleaseAgeExclude to contain scalar package entries",
199
+ );
200
+ }
201
+ const value = item[1]
202
+ .trim()
203
+ .replace(/^'(.*)'$/, "$1")
204
+ .replace(/^"(.*)"$/, "$1");
205
+ if (!value.startsWith(`${BUILDCHAIN_PACKAGE_NAME}@`)) retained.push(line);
206
+ }
207
+ return `${[
208
+ ...lines.slice(0, keyIndex + 1),
209
+ ...retained,
210
+ ` - '${entry}'`,
211
+ ...lines.slice(blockEnd),
212
+ ].join("\n")}\n`;
213
+ }
214
+
152
215
  function existingFileFact(cwd, relativePath) {
153
216
  const filePath = path.resolve(cwd, relativePath);
154
217
  if (!fs.existsSync(filePath) || !fs.statSync(filePath).isFile()) {
@@ -604,6 +667,7 @@ function scaffoldFiles({
604
667
  [PAPER_PATHS.buildWorkflow, buildWorkflow],
605
668
  [PAPER_PATHS.verifyWorkflow, verifyWorkflow],
606
669
  [PAPER_PATHS.releaseWorkflow, releaseWorkflow],
670
+ [PAPER_PATHS.pnpmWorkspace, paperPnpmWorkspace("", buildchainVersion)],
607
671
  [PAPER_PATHS.provisioningAuthority, jsonText(provisioningAuthority)],
608
672
  ...agentEntry,
609
673
  [
@@ -925,12 +989,20 @@ function migrationFiles({
925
989
  currentPackage.value,
926
990
  runtimeIdentity.version,
927
991
  );
992
+ const pnpmWorkspacePath = path.resolve(cwd, PAPER_PATHS.pnpmWorkspace);
993
+ const pnpmWorkspace = paperPnpmWorkspace(
994
+ fs.existsSync(pnpmWorkspacePath)
995
+ ? fs.readFileSync(pnpmWorkspacePath, "utf8")
996
+ : "",
997
+ runtimeIdentity.version,
998
+ );
928
999
  const files = new Map([
929
1000
  [PAPER_PATHS.contractLock, contractLockText],
930
1001
  [PAPER_PATHS.versionPin, `${runtimeIdentity.version}\n`],
931
1002
  [PAPER_PATHS.buildWorkflow, buildWorkflow],
932
1003
  [PAPER_PATHS.verifyWorkflow, verifyWorkflow],
933
1004
  [PAPER_PATHS.releaseWorkflow, releaseWorkflow],
1005
+ [PAPER_PATHS.pnpmWorkspace, pnpmWorkspace],
934
1006
  [PAPER_PATHS.provisioningAuthority, jsonText(provisioningAuthority)],
935
1007
  ...agentEntry,
936
1008
  ["package.json", jsonText(packageJson)],
@@ -1,4 +1,5 @@
1
1
  import { spawnSync } from "node:child_process";
2
+ import fs from "node:fs";
2
3
  import path from "node:path";
3
4
  import {
4
5
  PAPER_FLEET_AUDIT_CONTRACT,
@@ -17,6 +18,7 @@ import {
17
18
  planPaperMigration,
18
19
  planPaperScaffold,
19
20
  planPaperFleetUpdate,
21
+ paperFleetTransitionWorkspace,
20
22
  writePaperFleetUpdate,
21
23
  writePaperMigration,
22
24
  writePaperScaffold,
@@ -467,9 +469,26 @@ function runFleetAudit(options) {
467
469
  function refreshFleetLocks(result) {
468
470
  for (const entry of result.results || []) {
469
471
  if (!entry.ok) continue;
470
- const lock = commandResult("pnpm", ["install", "--lockfile-only"], {
471
- cwd: entry.cwd,
472
- });
472
+ const workspacePath = path.resolve(entry.cwd, "pnpm-workspace.yaml");
473
+ const lockPath = path.resolve(entry.cwd, "pnpm-lock.yaml");
474
+ const finalWorkspace = fs.readFileSync(workspacePath, "utf8");
475
+ const transitionWorkspace = paperFleetTransitionWorkspace(
476
+ finalWorkspace,
477
+ fs.existsSync(lockPath) ? fs.readFileSync(lockPath, "utf8") : "",
478
+ );
479
+ let lock;
480
+ try {
481
+ if (transitionWorkspace !== finalWorkspace) {
482
+ fs.writeFileSync(workspacePath, transitionWorkspace);
483
+ }
484
+ lock = commandResult("pnpm", ["install", "--lockfile-only"], {
485
+ cwd: entry.cwd,
486
+ });
487
+ } finally {
488
+ if (fs.readFileSync(workspacePath, "utf8") !== finalWorkspace) {
489
+ fs.writeFileSync(workspacePath, finalWorkspace);
490
+ }
491
+ }
473
492
  if (lock.ok) continue;
474
493
  return {
475
494
  ...result,