@kungfu-tech/buildchain 0.0.0-bootstrap.0 → 2.0.13-alpha.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/README.md +262 -0
- package/bin/buildchain.mjs +222 -0
- package/docs/cli.md +124 -0
- package/docs/lifecycle-protocol.md +422 -0
- package/docs/publish-transaction.md +285 -0
- package/docs/reusable-build-surface.md +350 -0
- package/docs/web-surface-deployments.md +211 -0
- package/package.json +52 -1
- package/packages/core/README.md +15 -0
- package/packages/core/buildchain-config.js +721 -0
- package/packages/core/index.js +40 -0
- package/packages/core/package-manager.js +291 -0
- package/packages/core/publish-transaction.js +418 -0
- package/packages/core/release-line-dry-run.js +296 -0
- package/scripts/aggregate-build-summary.mjs +88 -0
- package/scripts/build-contract-core.mjs +731 -0
- package/scripts/check-inventory.mjs +325 -0
- package/scripts/init-repo.mjs +316 -0
- package/scripts/npm-publish-dry-run.mjs +176 -0
- package/scripts/npm-publish-transaction.mjs +268 -0
- package/scripts/publish-source-ref-resolver.mjs +113 -0
- package/scripts/release-line-dry-run.mjs +53 -0
- package/scripts/release-line-policy.mjs +141 -0
- package/scripts/release-transaction.mjs +212 -0
- package/scripts/resolve-build-contract.mjs +63 -0
- package/scripts/resolve-publish-gate.mjs +33 -0
- package/scripts/resolve-publish-source.mjs +99 -0
- package/scripts/run-lifecycle-core.mjs +162 -0
- package/scripts/run-lifecycle.mjs +40 -0
- package/scripts/strip-trailing-whitespace.mjs +14 -0
- package/scripts/tsup-action.config.mjs +19 -0
- package/scripts/verify-publish-source-lock.mjs +37 -0
- package/scripts/verify-release-pr.mjs +34 -0
- package/scripts/web-surface-core.mjs +382 -0
- package/scripts/web-surface.mjs +112 -0
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
export {
|
|
2
|
+
discoverConfiguredVersionStateFiles,
|
|
3
|
+
getLifecycleStage,
|
|
4
|
+
getVersionStrategy,
|
|
5
|
+
loadBuildchainConfig,
|
|
6
|
+
loadConfiguredAnchorManifest,
|
|
7
|
+
normalizeBuildchainConfig,
|
|
8
|
+
normalizeLifecycleStage,
|
|
9
|
+
runLifecycleStage,
|
|
10
|
+
updateConfiguredVersionStateContents,
|
|
11
|
+
validateBuildchainConfig,
|
|
12
|
+
} from "./buildchain-config.js";
|
|
13
|
+
|
|
14
|
+
export {
|
|
15
|
+
assertPackageManager,
|
|
16
|
+
commandForKungfuUpgrade,
|
|
17
|
+
commandForRunScript,
|
|
18
|
+
commandForVersion,
|
|
19
|
+
detectLockfile,
|
|
20
|
+
detectPackageManager,
|
|
21
|
+
getWorkspaceInfo,
|
|
22
|
+
shellJoin,
|
|
23
|
+
} from "./package-manager.js";
|
|
24
|
+
|
|
25
|
+
export {
|
|
26
|
+
createReleaseTransaction,
|
|
27
|
+
defaultPublishEvidencePath,
|
|
28
|
+
defaultReleaseStatePath,
|
|
29
|
+
planTransactionRecovery,
|
|
30
|
+
readPublishEvidence,
|
|
31
|
+
readReleaseTransaction,
|
|
32
|
+
transitionReleaseTransaction,
|
|
33
|
+
validatePublishEvidence,
|
|
34
|
+
writeReleaseTransaction,
|
|
35
|
+
} from "./publish-transaction.js";
|
|
36
|
+
|
|
37
|
+
export {
|
|
38
|
+
explainReleaseLineDryRun,
|
|
39
|
+
formatReleaseLineDryRun,
|
|
40
|
+
} from "./release-line-dry-run.js";
|
|
@@ -0,0 +1,291 @@
|
|
|
1
|
+
import fs from "node:fs";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
|
|
4
|
+
const KNOWN_MANAGERS = new Set(["pnpm", "yarn", "npm"]);
|
|
5
|
+
|
|
6
|
+
function readJsonIfExists(filePath) {
|
|
7
|
+
if (!fs.existsSync(filePath)) {
|
|
8
|
+
return null;
|
|
9
|
+
}
|
|
10
|
+
return JSON.parse(fs.readFileSync(filePath, "utf8"));
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
function parsePackageManager(value) {
|
|
14
|
+
const match = String(value || "").match(/^(pnpm|yarn|npm)(?:@|$)/);
|
|
15
|
+
return match ? match[1] : null;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export function assertPackageManager(manager) {
|
|
19
|
+
if (!KNOWN_MANAGERS.has(manager)) {
|
|
20
|
+
throw new Error(`Unsupported package manager: ${manager}`);
|
|
21
|
+
}
|
|
22
|
+
return manager;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export function detectPackageManager(cwd = process.cwd()) {
|
|
26
|
+
const envValue = process.env.BUILDCHAIN_PACKAGE_MANAGER;
|
|
27
|
+
const envManager = parsePackageManager(envValue);
|
|
28
|
+
if (envValue && !envManager) {
|
|
29
|
+
throw new Error(`Unsupported package manager from BUILDCHAIN_PACKAGE_MANAGER: ${envValue}`);
|
|
30
|
+
}
|
|
31
|
+
if (envManager) {
|
|
32
|
+
return { name: envManager, reason: "BUILDCHAIN_PACKAGE_MANAGER" };
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const pkg = readJsonIfExists(path.join(cwd, "package.json"));
|
|
36
|
+
const declared = parsePackageManager(pkg?.packageManager);
|
|
37
|
+
if (declared) {
|
|
38
|
+
return { name: declared, reason: "packageManager", packageManager: pkg.packageManager };
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
const lockfiles = [
|
|
42
|
+
["pnpm", "pnpm-lock.yaml"],
|
|
43
|
+
["yarn", "yarn.lock"],
|
|
44
|
+
["npm", "package-lock.json"],
|
|
45
|
+
["npm", "npm-shrinkwrap.json"],
|
|
46
|
+
];
|
|
47
|
+
for (const [name, lockfile] of lockfiles) {
|
|
48
|
+
if (fs.existsSync(path.join(cwd, lockfile))) {
|
|
49
|
+
return { name, reason: "lockfile", lockfile };
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
throw new Error(
|
|
54
|
+
"Unable to detect package manager. Add packageManager to package.json or commit a supported lockfile.",
|
|
55
|
+
);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export function commandForRunScript(manager, script) {
|
|
59
|
+
assertPackageManager(manager);
|
|
60
|
+
if (manager === "pnpm") {
|
|
61
|
+
return { cmd: "pnpm", args: ["run", script] };
|
|
62
|
+
}
|
|
63
|
+
if (manager === "npm") {
|
|
64
|
+
return { cmd: "npm", args: ["run", script] };
|
|
65
|
+
}
|
|
66
|
+
return { cmd: "yarn", args: ["run", script] };
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
export function commandForVersion(manager, keyword, options = {}) {
|
|
70
|
+
assertPackageManager(manager);
|
|
71
|
+
const args = [];
|
|
72
|
+
if (manager === "yarn") {
|
|
73
|
+
args.push("version", `--${keyword}`);
|
|
74
|
+
} else {
|
|
75
|
+
args.push("version", keyword);
|
|
76
|
+
}
|
|
77
|
+
args.push(...(options.preid ? ["--preid", options.preid] : []));
|
|
78
|
+
args.push(...(options.message ? ["--message", options.message] : []));
|
|
79
|
+
args.push(...(options.tag === false ? ["--no-git-tag-version"] : []));
|
|
80
|
+
return { cmd: manager, args };
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
export function shellJoin(command) {
|
|
84
|
+
return [command.cmd, ...command.args].map((part) => {
|
|
85
|
+
const value = String(part);
|
|
86
|
+
return /^[A-Za-z0-9_./:@=+-]+$/.test(value) ? value : JSON.stringify(value);
|
|
87
|
+
}).join(" ");
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
export function commandForKungfuUpgrade(manager, scope = "@kungfu-trader") {
|
|
91
|
+
assertPackageManager(manager);
|
|
92
|
+
if (manager === "pnpm") {
|
|
93
|
+
return {
|
|
94
|
+
primary: shellJoin({
|
|
95
|
+
cmd: "pnpm",
|
|
96
|
+
args: ["update", "--recursive", "--filter", `${scope}/*`, "--ignore-scripts"],
|
|
97
|
+
}),
|
|
98
|
+
fallback: "pnpm install --ignore-scripts --lockfile-only",
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
if (manager === "npm") {
|
|
102
|
+
return {
|
|
103
|
+
primary: shellJoin({ cmd: "npm", args: ["update", "--workspaces", "--ignore-scripts"] }),
|
|
104
|
+
fallback: "npm install --ignore-scripts --package-lock-only --dry-run",
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
return {
|
|
108
|
+
primary: shellJoin({ cmd: "yarn", args: ["upgrade", "--scope", scope, "--ignore-scripts"] }),
|
|
109
|
+
fallback: shellJoin({ cmd: "yarn", args: ["install", "-scope", scope, "--ignore-scripts", "--force", "--dry-run"] }),
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
function normalizeWorkspacePatterns(config) {
|
|
114
|
+
if (!config) {
|
|
115
|
+
return [];
|
|
116
|
+
}
|
|
117
|
+
if (Array.isArray(config.workspaces)) {
|
|
118
|
+
return config.workspaces;
|
|
119
|
+
}
|
|
120
|
+
if (Array.isArray(config.workspaces?.packages)) {
|
|
121
|
+
return config.workspaces.packages;
|
|
122
|
+
}
|
|
123
|
+
if (Array.isArray(config.packages)) {
|
|
124
|
+
return config.packages;
|
|
125
|
+
}
|
|
126
|
+
return [];
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
function readPnpmWorkspacePatterns(cwd) {
|
|
130
|
+
const filePath = path.join(cwd, "pnpm-workspace.yaml");
|
|
131
|
+
if (!fs.existsSync(filePath)) {
|
|
132
|
+
return [];
|
|
133
|
+
}
|
|
134
|
+
const patterns = [];
|
|
135
|
+
let inPackages = false;
|
|
136
|
+
for (const line of fs.readFileSync(filePath, "utf8").split(/\r?\n/)) {
|
|
137
|
+
if (/^\s*packages\s*:\s*$/.test(line)) {
|
|
138
|
+
inPackages = true;
|
|
139
|
+
continue;
|
|
140
|
+
}
|
|
141
|
+
if (inPackages && /^\S/.test(line)) {
|
|
142
|
+
break;
|
|
143
|
+
}
|
|
144
|
+
const match = inPackages && line.match(/^\s*-\s*["']?([^"']+)["']?\s*$/);
|
|
145
|
+
if (match) {
|
|
146
|
+
patterns.push(match[1]);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
return patterns;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
function posixRelative(cwd, item) {
|
|
153
|
+
return path.relative(cwd, item).split(path.sep).join("/");
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
function expandWorkspacePattern(cwd, pattern) {
|
|
157
|
+
if (!pattern || pattern.startsWith("!")) {
|
|
158
|
+
return [];
|
|
159
|
+
}
|
|
160
|
+
const normalized = pattern.replace(/\/package\.json$/, "");
|
|
161
|
+
const parts = normalized.split("/");
|
|
162
|
+
const wildcardIndex = parts.indexOf("*");
|
|
163
|
+
if (wildcardIndex === -1) {
|
|
164
|
+
const packageJson = path.join(cwd, normalized, "package.json");
|
|
165
|
+
return fs.existsSync(packageJson) ? [path.dirname(packageJson)] : [];
|
|
166
|
+
}
|
|
167
|
+
const prefix = parts.slice(0, wildcardIndex).join("/");
|
|
168
|
+
const suffix = parts.slice(wildcardIndex + 1).join("/");
|
|
169
|
+
const baseDir = path.join(cwd, prefix);
|
|
170
|
+
if (!fs.existsSync(baseDir)) {
|
|
171
|
+
return [];
|
|
172
|
+
}
|
|
173
|
+
return fs
|
|
174
|
+
.readdirSync(baseDir, { withFileTypes: true })
|
|
175
|
+
.filter((entry) => entry.isDirectory())
|
|
176
|
+
.map((entry) => path.join(baseDir, entry.name, suffix))
|
|
177
|
+
.filter((dir) => fs.existsSync(path.join(dir, "package.json")));
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
export function getWorkspaceInfo(cwd = process.cwd()) {
|
|
181
|
+
const packageConfig = readJsonIfExists(path.join(cwd, "package.json"));
|
|
182
|
+
const lernaConfig = readJsonIfExists(path.join(cwd, "lerna.json"));
|
|
183
|
+
const patterns = [
|
|
184
|
+
...normalizeWorkspacePatterns(packageConfig),
|
|
185
|
+
...normalizeWorkspacePatterns(lernaConfig),
|
|
186
|
+
...readPnpmWorkspacePatterns(cwd),
|
|
187
|
+
];
|
|
188
|
+
const info = {};
|
|
189
|
+
const seen = new Set();
|
|
190
|
+
for (const pattern of patterns) {
|
|
191
|
+
for (const packageDir of expandWorkspacePattern(cwd, pattern)) {
|
|
192
|
+
const location = posixRelative(cwd, packageDir);
|
|
193
|
+
if (seen.has(location)) {
|
|
194
|
+
continue;
|
|
195
|
+
}
|
|
196
|
+
seen.add(location);
|
|
197
|
+
const config = readJsonIfExists(path.join(packageDir, "package.json"));
|
|
198
|
+
if (config?.name) {
|
|
199
|
+
info[config.name] = { location };
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
return info;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
export function detectLockfile(cwd = process.cwd()) {
|
|
207
|
+
for (const lockfile of ["pnpm-lock.yaml", "yarn.lock", "package-lock.json", "npm-shrinkwrap.json"]) {
|
|
208
|
+
const filePath = path.join(cwd, lockfile);
|
|
209
|
+
if (fs.existsSync(filePath)) {
|
|
210
|
+
return { lockfile, filePath };
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
return null;
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
function mapSetIfKungfu(acc, name, version) {
|
|
217
|
+
if (name && version && name.startsWith("@kungfu-trader/")) {
|
|
218
|
+
acc.set(name, version);
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
export function getYarnLockInfo(content) {
|
|
223
|
+
if (!content) {
|
|
224
|
+
return undefined;
|
|
225
|
+
}
|
|
226
|
+
const acc = new Map();
|
|
227
|
+
for (const block of content.split(/\n(?=\S)/)) {
|
|
228
|
+
const header = block.split(/\r?\n/, 1)[0] || "";
|
|
229
|
+
const nameMatch = header.match(/@kungfu-trader\/([^@,\s:"]+)/);
|
|
230
|
+
const versionMatch = block.match(/^\s+version\s+"?([^"\s]+)"?/m);
|
|
231
|
+
mapSetIfKungfu(acc, nameMatch && `@kungfu-trader/${nameMatch[1]}`, versionMatch?.[1]);
|
|
232
|
+
}
|
|
233
|
+
return acc;
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
export function getPnpmLockInfo(content) {
|
|
237
|
+
const acc = new Map();
|
|
238
|
+
const pattern = /@kungfu-trader\/([^@\s:'")]+)@([^:\s'")]+)/g;
|
|
239
|
+
for (const match of content.matchAll(pattern)) {
|
|
240
|
+
mapSetIfKungfu(acc, `@kungfu-trader/${match[1]}`, match[2].split("(")[0]);
|
|
241
|
+
}
|
|
242
|
+
return acc;
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
function visitNpmDependencyTree(acc, deps = {}) {
|
|
246
|
+
for (const [name, value] of Object.entries(deps || {})) {
|
|
247
|
+
mapSetIfKungfu(acc, name, value?.version);
|
|
248
|
+
visitNpmDependencyTree(acc, value?.dependencies);
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
export function getNpmLockInfo(content) {
|
|
253
|
+
const json = JSON.parse(content);
|
|
254
|
+
const acc = new Map();
|
|
255
|
+
for (const [key, value] of Object.entries(json.packages || {})) {
|
|
256
|
+
const match = key.match(/node_modules\/(@kungfu-trader\/[^/]+)$/);
|
|
257
|
+
mapSetIfKungfu(acc, match?.[1], value?.version);
|
|
258
|
+
}
|
|
259
|
+
visitNpmDependencyTree(acc, json.dependencies);
|
|
260
|
+
return acc;
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
export function getCurrentLockInfo(cwd = process.cwd()) {
|
|
264
|
+
const found = detectLockfile(cwd);
|
|
265
|
+
if (!found) {
|
|
266
|
+
return undefined;
|
|
267
|
+
}
|
|
268
|
+
const content = fs.readFileSync(found.filePath, "utf8");
|
|
269
|
+
if (found.lockfile === "yarn.lock") {
|
|
270
|
+
return getYarnLockInfo(content);
|
|
271
|
+
}
|
|
272
|
+
if (found.lockfile === "pnpm-lock.yaml") {
|
|
273
|
+
return getPnpmLockInfo(content);
|
|
274
|
+
}
|
|
275
|
+
return getNpmLockInfo(content);
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
export default {
|
|
279
|
+
assertPackageManager,
|
|
280
|
+
commandForKungfuUpgrade,
|
|
281
|
+
commandForRunScript,
|
|
282
|
+
commandForVersion,
|
|
283
|
+
detectLockfile,
|
|
284
|
+
detectPackageManager,
|
|
285
|
+
getCurrentLockInfo,
|
|
286
|
+
getNpmLockInfo,
|
|
287
|
+
getPnpmLockInfo,
|
|
288
|
+
getWorkspaceInfo,
|
|
289
|
+
getYarnLockInfo,
|
|
290
|
+
shellJoin,
|
|
291
|
+
};
|