@kungfu-tech/buildchain 3.0.4-alpha.2 → 3.0.4-alpha.3
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/bin/buildchain.mjs +126 -72
- package/bin/internal/trust-release-cli.mjs +15 -537
- package/bin/internal/trust-release-command-handlers.mjs +14 -0
- package/bin/internal/trust-release-inspection-handlers.mjs +175 -0
- package/bin/internal/trust-release-release-handlers.mjs +317 -0
- package/bin/internal/trust-release-verification-handlers.mjs +306 -0
- package/dist/site/buildchain-contract.json +35 -24
- package/dist/site/buildchain-site.json +22 -10
- package/dist/site/controller-registry.json +16 -3
- package/dist/site/kfd-claims.json +9 -7
- package/dist/site/kfd-upstream-aggregate.json +1 -1
- package/dist/site/manual-registry.json +2 -2
- package/dist/site/node-api-registry.json +7 -7
- package/dist/site/page-registry.json +9 -4
- package/dist/site/public-surface-audit.json +56 -8
- package/dist/site/publication-registry.json +4 -4
- package/dist/site/release-model.json +7 -0
- package/dist/site/site-manifest.json +6 -6
- package/dist/site/workflow-registry.json +13 -5
- package/docs/MAP.md +1 -1
- package/docs/release-propagation.md +166 -8
- package/package.json +1 -1
- package/packages/core/buildchain-kfd-claims.js +1 -1
- package/packages/core/controller-evidence.js +8 -1
- package/packages/core/index.js +1 -13
- package/packages/core/paper-npm-bootstrap.js +492 -0
- package/packages/core/paper.js +271 -669
- package/packages/core/public-surface-cli.js +12 -1
- package/packages/core/release-passport.js +67 -71
- package/packages/core/release-propagation-common.js +64 -0
- package/packages/core/release-propagation-execution-profile.js +59 -0
- package/packages/core/release-propagation-release.js +196 -0
- package/packages/core/release-propagation-stage-evidence.js +364 -0
- package/packages/core/release-propagation-work-capture.js +64 -0
- package/packages/core/release-propagation-work-constants.js +34 -0
- package/packages/core/release-propagation-work-control.js +203 -0
- package/packages/core/release-propagation-work-transitions.js +145 -0
- package/packages/core/release-propagation-work.js +517 -0
- package/packages/core/release-propagation.js +34 -158
- package/scripts/aws-windows-jit-controller-core.mjs +269 -0
- package/scripts/aws-windows-jit-controller.mjs +502 -0
- package/scripts/check-internal-architecture.mjs +178 -52
- package/scripts/check-maintainability.mjs +76 -17
- package/scripts/generate-site-bundle.mjs +16 -7
- package/scripts/maintainability-metrics.mjs +24 -4
- package/scripts/release-propagation.mjs +126 -0
- package/scripts/resolve-artifact-transfer-mode.mjs +117 -0
- package/scripts/web-surface-core.mjs +46 -207
- package/scripts/web-surface-routing.mjs +286 -0
|
@@ -0,0 +1,286 @@
|
|
|
1
|
+
import fs from "node:fs";
|
|
2
|
+
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
|
|
5
|
+
function classifyPreviewAlias(alias) {
|
|
6
|
+
if (/^pr-\d+$/.test(alias)) {
|
|
7
|
+
return {
|
|
8
|
+
kind: "pr",
|
|
9
|
+
mutable: true,
|
|
10
|
+
retentionClass: "preview-pr-ephemeral",
|
|
11
|
+
retentionKey: "pr_days",
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
if (/^sha-[0-9a-f]{6,40}$/i.test(alias)) {
|
|
15
|
+
return {
|
|
16
|
+
kind: "sha",
|
|
17
|
+
mutable: false,
|
|
18
|
+
retentionClass: "preview-sha-immutable",
|
|
19
|
+
retentionKey: "sha_days",
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
return {
|
|
23
|
+
kind: "custom",
|
|
24
|
+
mutable: true,
|
|
25
|
+
retentionClass: "preview-custom-ephemeral",
|
|
26
|
+
retentionKey: "pr_days",
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function resolveChannelUrl(channel, alias) {
|
|
31
|
+
if (channel.urlPattern) {
|
|
32
|
+
if (!alias) {
|
|
33
|
+
throw new Error(`channel ${channel.name} requires alias for url_pattern`);
|
|
34
|
+
}
|
|
35
|
+
return channel.urlPattern.replaceAll("{alias}", alias);
|
|
36
|
+
}
|
|
37
|
+
return channel.url;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function resolvePathOnlyUrl(channel, sourcePath, alias) {
|
|
41
|
+
const base = resolveChannelUrl(channel, alias);
|
|
42
|
+
const url = new URL(base);
|
|
43
|
+
const normalizedPath = normalizeSurfacePath(sourcePath);
|
|
44
|
+
if (normalizedPath === "/") {
|
|
45
|
+
return `${url.origin}/`;
|
|
46
|
+
}
|
|
47
|
+
return new URL(
|
|
48
|
+
normalizedPath.replace(/^\//, ""),
|
|
49
|
+
`${url.origin}/`,
|
|
50
|
+
).toString();
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function resolveSurfaceUrl({ surface, channel, channelName, alias }) {
|
|
54
|
+
if (channelName === "preview" && surface.previewUrlPattern) {
|
|
55
|
+
if (!alias) {
|
|
56
|
+
throw new Error(
|
|
57
|
+
`surface ${surface.name} requires alias for preview_url_pattern`,
|
|
58
|
+
);
|
|
59
|
+
}
|
|
60
|
+
return surface.previewUrlPattern.replaceAll("{alias}", alias);
|
|
61
|
+
}
|
|
62
|
+
if (channelName === "staging" && surface.stagingUrl) {
|
|
63
|
+
return surface.stagingUrl;
|
|
64
|
+
}
|
|
65
|
+
if (channelName === "production" && surface.productionUrl) {
|
|
66
|
+
return surface.productionUrl;
|
|
67
|
+
}
|
|
68
|
+
if (surface.pathOnly) {
|
|
69
|
+
return resolvePathOnlyUrl(channel, surface.path, alias);
|
|
70
|
+
}
|
|
71
|
+
const key =
|
|
72
|
+
channelName === "preview" ? "preview_url_pattern" : `${channelName}_url`;
|
|
73
|
+
throw new Error(
|
|
74
|
+
`surfaces.${surface.name}.${key} is required for channel ${channelName}`,
|
|
75
|
+
);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
function manifestPrefixFor(deployConfig) {
|
|
79
|
+
return deployConfig.manifest_prefix || ".buildchain/deployments";
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
function objectPrefixFor(deployConfig, alias) {
|
|
83
|
+
if (Object.hasOwn(deployConfig, "prefix")) {
|
|
84
|
+
return normalizeS3Key(deployConfig.prefix);
|
|
85
|
+
}
|
|
86
|
+
return alias || "preview";
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
function normalizeSurfacePath(value) {
|
|
90
|
+
const normalized = `/${String(value || "/").replace(/^\/+/, "")}`.replace(
|
|
91
|
+
/\/{2,}/g,
|
|
92
|
+
"/",
|
|
93
|
+
);
|
|
94
|
+
if (normalized === "/") {
|
|
95
|
+
return normalized;
|
|
96
|
+
}
|
|
97
|
+
return normalized.endsWith("/") ? normalized : `${normalized}/`;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
function surfaceDeployConfig(deployConfig, surfaceName) {
|
|
101
|
+
const overrides = deployConfig.surfaces?.[surfaceName];
|
|
102
|
+
if (!overrides || typeof overrides !== "object" || Array.isArray(overrides)) {
|
|
103
|
+
return deployConfig;
|
|
104
|
+
}
|
|
105
|
+
return {
|
|
106
|
+
...deployConfig,
|
|
107
|
+
...overrides,
|
|
108
|
+
cacheControl:
|
|
109
|
+
deployConfig.cacheControl || overrides.cacheControl
|
|
110
|
+
? {
|
|
111
|
+
...(deployConfig.cacheControl || {}),
|
|
112
|
+
...(overrides.cacheControl || {}),
|
|
113
|
+
}
|
|
114
|
+
: undefined,
|
|
115
|
+
surfaces: deployConfig.surfaces,
|
|
116
|
+
secretRefs: [
|
|
117
|
+
...new Set([
|
|
118
|
+
...(deployConfig.secretRefs || []),
|
|
119
|
+
...(Array.isArray(overrides.secretRefs) ? overrides.secretRefs : []),
|
|
120
|
+
]),
|
|
121
|
+
],
|
|
122
|
+
artifactPath: overrides.artifactPath || deployConfig.artifactPath,
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
function surfaceObjectPrefixFor({ deployConfig, surface, alias }) {
|
|
127
|
+
const effective = surfaceDeployConfig(deployConfig, surface.name);
|
|
128
|
+
if (Object.hasOwn(effective, "prefix")) {
|
|
129
|
+
return normalizeS3Key(effective.prefix);
|
|
130
|
+
}
|
|
131
|
+
const root = objectPrefixFor(deployConfig, alias);
|
|
132
|
+
const surfacePath = normalizeS3Key(surface.path);
|
|
133
|
+
if (!surfacePath) {
|
|
134
|
+
return root;
|
|
135
|
+
}
|
|
136
|
+
return joinS3Key(root, surfacePath);
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
function normalizeS3Key(value) {
|
|
140
|
+
return String(value || "")
|
|
141
|
+
.replace(/^\/+/, "")
|
|
142
|
+
.replace(/\/{2,}/g, "/")
|
|
143
|
+
.replace(/\/+$/, "");
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
function joinS3Key(...parts) {
|
|
147
|
+
return normalizeS3Key(parts.filter(Boolean).join("/"));
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
function joinUrlPath(...parts) {
|
|
151
|
+
const raw = parts.join("/");
|
|
152
|
+
const normalized = normalizeS3Key(raw);
|
|
153
|
+
if (!normalized) {
|
|
154
|
+
return "/";
|
|
155
|
+
}
|
|
156
|
+
return raw.endsWith("/") ? `/${normalized}/` : `/${normalized}`;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
function urlWithPath(baseUrl, requestPath) {
|
|
160
|
+
const url = new URL(baseUrl);
|
|
161
|
+
url.pathname = joinUrlPath(requestPath);
|
|
162
|
+
url.search = "";
|
|
163
|
+
url.hash = "";
|
|
164
|
+
return url.toString();
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
function s3Uri(bucket, key = "") {
|
|
168
|
+
if (!bucket) {
|
|
169
|
+
throw new Error("aws-s3-cloudfront adapter requires a bucket or target");
|
|
170
|
+
}
|
|
171
|
+
const normalizedKey = normalizeS3Key(key);
|
|
172
|
+
return normalizedKey ? `s3://${bucket}/${normalizedKey}` : `s3://${bucket}`;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
function cdnPath(value) {
|
|
176
|
+
const normalized = normalizeS3Key(value);
|
|
177
|
+
return normalized ? `/${normalized}` : "/";
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
function cdnWildcardPath(value) {
|
|
181
|
+
const normalized = normalizeS3Key(value);
|
|
182
|
+
return normalized ? `/${normalized}/*` : "/*";
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
function viewerWildcardPath(binding) {
|
|
186
|
+
try {
|
|
187
|
+
return cdnWildcardPath(new URL(binding.url).pathname);
|
|
188
|
+
} catch {
|
|
189
|
+
return cdnWildcardPath(binding.objectPrefix);
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
function surfaceArtifactPrefix(binding) {
|
|
194
|
+
return normalizeS3Key(binding.sourcePath);
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
function surfaceArtifactRootFor({ artifactRoot, binding }) {
|
|
198
|
+
const prefix = normalizeS3Key(
|
|
199
|
+
binding.artifactPathPrefix || surfaceArtifactPrefix(binding),
|
|
200
|
+
);
|
|
201
|
+
const root = prefix ? path.join(artifactRoot, prefix) : artifactRoot;
|
|
202
|
+
if (fs.existsSync(root)) {
|
|
203
|
+
return root;
|
|
204
|
+
}
|
|
205
|
+
return artifactRoot;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
function syncStaticArtifactArgs({
|
|
209
|
+
artifactRoot,
|
|
210
|
+
bucket,
|
|
211
|
+
objectPrefix,
|
|
212
|
+
deleteExcludes = [],
|
|
213
|
+
cacheControl = "",
|
|
214
|
+
}) {
|
|
215
|
+
const args = [
|
|
216
|
+
"s3",
|
|
217
|
+
"sync",
|
|
218
|
+
artifactRoot,
|
|
219
|
+
s3Uri(bucket, objectPrefix),
|
|
220
|
+
"--delete",
|
|
221
|
+
];
|
|
222
|
+
if (!objectPrefix) {
|
|
223
|
+
args.push("--exclude", ".buildchain/*");
|
|
224
|
+
}
|
|
225
|
+
for (const pattern of deleteExcludes) {
|
|
226
|
+
args.push("--exclude", pattern);
|
|
227
|
+
}
|
|
228
|
+
if (cacheControl) {
|
|
229
|
+
args.push("--cache-control", cacheControl);
|
|
230
|
+
}
|
|
231
|
+
return args;
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
function mutableCacheControlArgs({
|
|
235
|
+
artifactRoot,
|
|
236
|
+
bucket,
|
|
237
|
+
objectPrefix,
|
|
238
|
+
cacheControl = "",
|
|
239
|
+
excludePatterns = [],
|
|
240
|
+
}) {
|
|
241
|
+
if (!cacheControl) return [];
|
|
242
|
+
const args = [
|
|
243
|
+
"s3",
|
|
244
|
+
"cp",
|
|
245
|
+
artifactRoot,
|
|
246
|
+
s3Uri(bucket, objectPrefix),
|
|
247
|
+
"--recursive",
|
|
248
|
+
"--exclude",
|
|
249
|
+
"*",
|
|
250
|
+
"--include",
|
|
251
|
+
"*.html",
|
|
252
|
+
"--include",
|
|
253
|
+
"*.json",
|
|
254
|
+
"--include",
|
|
255
|
+
"*.xml",
|
|
256
|
+
];
|
|
257
|
+
for (const pattern of excludePatterns) {
|
|
258
|
+
args.push("--exclude", pattern);
|
|
259
|
+
}
|
|
260
|
+
args.push("--cache-control", cacheControl);
|
|
261
|
+
return args;
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
export {
|
|
265
|
+
classifyPreviewAlias,
|
|
266
|
+
resolveChannelUrl,
|
|
267
|
+
resolvePathOnlyUrl,
|
|
268
|
+
resolveSurfaceUrl,
|
|
269
|
+
manifestPrefixFor,
|
|
270
|
+
objectPrefixFor,
|
|
271
|
+
normalizeSurfacePath,
|
|
272
|
+
surfaceDeployConfig,
|
|
273
|
+
surfaceObjectPrefixFor,
|
|
274
|
+
normalizeS3Key,
|
|
275
|
+
joinS3Key,
|
|
276
|
+
joinUrlPath,
|
|
277
|
+
urlWithPath,
|
|
278
|
+
s3Uri,
|
|
279
|
+
cdnPath,
|
|
280
|
+
cdnWildcardPath,
|
|
281
|
+
viewerWildcardPath,
|
|
282
|
+
surfaceArtifactPrefix,
|
|
283
|
+
surfaceArtifactRootFor,
|
|
284
|
+
syncStaticArtifactArgs,
|
|
285
|
+
mutableCacheControlArgs,
|
|
286
|
+
};
|