@kungfu-tech/buildchain 4.0.2-alpha.37 → 4.0.2-alpha.39
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/AGENTS.md +1 -1
- package/architecture/agent-change-map.md +2 -2
- package/architecture/internal-capabilities.json +2 -2
- package/architecture/maintainability-debt.json +8 -8
- package/architecture/maintainability-policy.json +3 -3
- package/architecture/v4-cross-platform-adopter-qualification.json +1 -1
- package/architecture/v4-floating-consumer-policy.json +1 -1
- package/architecture/v4-next-development-parity.json +2 -2
- package/architecture/v4-release-topology.json +0 -1
- package/architecture/v4-stage-capsule-qualification.json +1 -1
- package/architecture/v4-tail-reseal-parity.json +8 -6
- package/architecture/v4-universal-workflow-train-admission.json +1 -1
- package/architecture/workflow-taxonomy.json +18 -15
- package/contracts/fixtures/v4-tail-reseal-v1/valid.json +1 -1
- package/dist/site/buildchain-contract.json +6 -6
- package/dist/site/buildchain-site.json +67 -26
- package/dist/site/capability-registry.json +2 -2
- package/dist/site/kfd-claims.json +19 -73
- package/dist/site/kfd-upstream-aggregate.json +1 -1
- package/dist/site/manual-registry.json +5 -5
- package/dist/site/node-api-registry.json +30 -30
- package/dist/site/page-registry.json +58 -17
- package/dist/site/public-surface-audit.json +8 -67
- package/dist/site/publication-authority-registry.json +1 -16
- package/dist/site/publication-registry.json +4 -4
- package/dist/site/site-manifest.json +9 -9
- package/dist/site/workflow-registry.json +5 -125
- package/docs/kfd-support.md +26 -2
- package/docs/next-development-transition.md +1 -1
- package/docs/node-api-reference.md +32 -32
- package/docs/release-passport.md +27 -2
- package/docs/v4-adopter-delivery.md +1 -1
- package/docs/v4-stage-capsule.md +1 -1
- package/docs/v4-tail-reseal.md +1 -1
- package/docs/workflow-catalog.md +5 -3
- package/docs/workflow-path-migration.md +109 -0
- package/package.json +1 -1
- package/packages/core/artifact-verification-envelope.js +5 -5
- package/packages/core/kfd-adopter-manifest.js +46 -47
- package/packages/core/next-development-projection.js +1 -1
- package/packages/core/release-passport-contract.js +5 -5
- package/packages/core/release-passport.js +5 -4
- package/scripts/check-v4-floating-consumer-policy-contract.mjs +1 -1
- package/scripts/check-v4-public-dogfood-contract.mjs +4 -4
- package/scripts/check-v4-universal-workflow-bootstrap.mjs +3 -3
- package/scripts/generate-v4-universal-workflow-facades.mjs +4 -3
- package/scripts/v4-universal-workflow-engine.mjs +2 -1
- package/scripts/workflow-taxonomy.mjs +50 -11
|
@@ -12,6 +12,7 @@ const ROLES = ["public", "component", "self"];
|
|
|
12
12
|
const CATEGORIES = ["build", "release", "ops"];
|
|
13
13
|
const SLUG = /^[a-z][a-z0-9]*(?:-[a-z0-9]+)*$/u;
|
|
14
14
|
const WORKFLOW = /^\.github\/workflows\/[.a-z0-9-]+\.ya?ml$/u;
|
|
15
|
+
const VERSION_TOKEN = /(?:^|[.-])v\d+(?:[.-]|$)/iu;
|
|
15
16
|
const PROTECTED = [
|
|
16
17
|
TAXONOMY_PATH,
|
|
17
18
|
"scripts/workflow-taxonomy.mjs",
|
|
@@ -40,6 +41,10 @@ function validateEntryRole(entry, errors) {
|
|
|
40
41
|
errors.push(`${entry.id}: invalid category`);
|
|
41
42
|
if (!SLUG.test(entry.purpose || ""))
|
|
42
43
|
errors.push(`${entry.id}: invalid purpose slug`);
|
|
44
|
+
if (VERSION_TOKEN.test(path.posix.basename(workflowPath(entry))))
|
|
45
|
+
errors.push(
|
|
46
|
+
`${entry.id}: workflow filenames cannot contain version tokens`,
|
|
47
|
+
);
|
|
43
48
|
for (const field of ["summary", "owner", "rationale"]) {
|
|
44
49
|
if (typeof entry[field] !== "string" || !entry[field].trim())
|
|
45
50
|
errors.push(`${entry.id}: missing ${field}`);
|
|
@@ -57,6 +62,15 @@ function validateEntryRole(entry, errors) {
|
|
|
57
62
|
}
|
|
58
63
|
|
|
59
64
|
function validateMigration(policy, entry, declared, errors) {
|
|
65
|
+
if (entry.retiredAlias) {
|
|
66
|
+
if (
|
|
67
|
+
entry.compatibility ||
|
|
68
|
+
entry.retiredAlias.path !== entry.migration?.previousPath ||
|
|
69
|
+
!entry.retiredAlias.reason?.trim() ||
|
|
70
|
+
entry.retiredAlias.migrationGuide !== "docs/workflow-path-migration.md"
|
|
71
|
+
)
|
|
72
|
+
errors.push(`${entry.id}: invalid alias retirement record`);
|
|
73
|
+
}
|
|
60
74
|
if (entry.migration) {
|
|
61
75
|
if (
|
|
62
76
|
!WORKFLOW.test(entry.migration.previousPath || "") ||
|
|
@@ -73,6 +87,10 @@ function validateMigration(policy, entry, declared, errors) {
|
|
|
73
87
|
}
|
|
74
88
|
if (entry.compatibility) {
|
|
75
89
|
const alias = entry.compatibility;
|
|
90
|
+
if (VERSION_TOKEN.test(path.posix.basename(alias.path || "")))
|
|
91
|
+
errors.push(
|
|
92
|
+
`${entry.id}: version-prefixed compatibility aliases are retired`,
|
|
93
|
+
);
|
|
76
94
|
if (entry.role === "self")
|
|
77
95
|
errors.push(
|
|
78
96
|
`${entry.id}: repository event wrappers cannot have duplicate aliases`,
|
|
@@ -167,6 +185,14 @@ function validateWorkflow(root, entry, declared, errors) {
|
|
|
167
185
|
const absolute = path.join(root, file);
|
|
168
186
|
if (!fs.existsSync(absolute) || !fs.lstatSync(absolute).isFile()) return;
|
|
169
187
|
const text = fs.readFileSync(absolute, "utf8");
|
|
188
|
+
if (
|
|
189
|
+
entry.retiredAlias &&
|
|
190
|
+
text.includes("BUILDCHAIN_INVOKED_WORKFLOW:") &&
|
|
191
|
+
!text.includes(`BUILDCHAIN_INVOKED_WORKFLOW: ${file}\n`)
|
|
192
|
+
)
|
|
193
|
+
errors.push(
|
|
194
|
+
`${file}: consumer admission must bind the canonical invoked workflow`,
|
|
195
|
+
);
|
|
170
196
|
const document = parseWorkflowDocument(text);
|
|
171
197
|
if (entry.role === "self")
|
|
172
198
|
validateRepositoryReferences(file, document, text, declared, errors);
|
|
@@ -195,6 +221,13 @@ function validateWorkflow(root, entry, declared, errors) {
|
|
|
195
221
|
);
|
|
196
222
|
}
|
|
197
223
|
for (const call of parseYamlUses(text)) {
|
|
224
|
+
const remote = call.value.match(
|
|
225
|
+
/^kungfu-systems\/buildchain\/(\.github\/workflows\/[^@]+)@/u,
|
|
226
|
+
);
|
|
227
|
+
if (remote && VERSION_TOKEN.test(path.posix.basename(remote[1])))
|
|
228
|
+
errors.push(
|
|
229
|
+
`${file}:${call.line}: retired version-prefixed workflow call ${remote[1]}`,
|
|
230
|
+
);
|
|
198
231
|
const local = call.value.match(/^\.\/(\.github\/workflows\/[^@]+)$/u);
|
|
199
232
|
if (local && !declared.has(local[1]))
|
|
200
233
|
errors.push(
|
|
@@ -276,6 +309,8 @@ export function checkWorkflowTaxonomy(
|
|
|
276
309
|
);
|
|
277
310
|
const observed = new Set(discoverWorkflowFiles(root));
|
|
278
311
|
for (const file of observed) {
|
|
312
|
+
if (VERSION_TOKEN.test(path.posix.basename(file)))
|
|
313
|
+
errors.push(`workflow filenames cannot contain version tokens: ${file}`);
|
|
279
314
|
if (!declared.has(file)) errors.push(`unregistered workflow: ${file}`);
|
|
280
315
|
if (!fs.lstatSync(path.join(root, file)).isFile())
|
|
281
316
|
errors.push(`workflow must be a regular file: ${file}`);
|
|
@@ -334,6 +369,8 @@ export function writeWorkflowSource(root, relative, text) {
|
|
|
334
369
|
(item) =>
|
|
335
370
|
workflowPath(item) === relative || item.compatibility?.path === relative,
|
|
336
371
|
);
|
|
372
|
+
if (policy?.entries.some((item) => item.retiredAlias?.path === relative))
|
|
373
|
+
throw new Error(`${relative}: cannot regenerate a retired workflow alias`);
|
|
337
374
|
const outputs = entry
|
|
338
375
|
? [
|
|
339
376
|
workflowPath(entry),
|
|
@@ -345,19 +382,10 @@ export function writeWorkflowSource(root, relative, text) {
|
|
|
345
382
|
|
|
346
383
|
export function rewriteRepositoryWorkflowPaths(root, text) {
|
|
347
384
|
for (const entry of readWorkflowTaxonomy(root)?.entries || []) {
|
|
348
|
-
if (
|
|
349
|
-
["v4-adopter-delivery", "v4-stage-capsule-canary"].includes(entry.id) &&
|
|
350
|
-
entry.compatibility
|
|
351
|
-
) {
|
|
352
|
-
const canonical = workflowPath(entry);
|
|
353
|
-
const legacy = entry.compatibility.path;
|
|
354
|
-
text = text.replaceAll(
|
|
355
|
-
`BUILDCHAIN_INVOKED_WORKFLOW: ${legacy}\n`,
|
|
356
|
-
`BUILDCHAIN_INVOKED_WORKFLOW: \${{ startsWith(job.workflow_ref, 'kungfu-systems/buildchain/${canonical}@') && '${canonical}' || '${legacy}' }}\n`,
|
|
357
|
-
);
|
|
358
|
-
}
|
|
359
385
|
if (entry.role === "self" && entry.migration)
|
|
360
386
|
text = text.replaceAll(entry.migration.previousPath, workflowPath(entry));
|
|
387
|
+
if (entry.retiredAlias)
|
|
388
|
+
text = text.replaceAll(entry.retiredAlias.path, workflowPath(entry));
|
|
361
389
|
if (entry.id === "build-surface-fixture")
|
|
362
390
|
text = text.replaceAll(
|
|
363
391
|
"build-surface-fixture.yml",
|
|
@@ -367,6 +395,15 @@ export function rewriteRepositoryWorkflowPaths(root, text) {
|
|
|
367
395
|
return text;
|
|
368
396
|
}
|
|
369
397
|
|
|
398
|
+
// Historical inventories and debt ledgers retain their original identity. File
|
|
399
|
+
// access resolves only explicitly retired aliases to the registered implementation.
|
|
400
|
+
export function currentWorkflowPath(root, relative) {
|
|
401
|
+
const entry = readWorkflowTaxonomy(root)?.entries.find(
|
|
402
|
+
(item) => item.retiredAlias?.path === relative,
|
|
403
|
+
);
|
|
404
|
+
return entry ? workflowPath(entry) : relative;
|
|
405
|
+
}
|
|
406
|
+
|
|
370
407
|
export function workflowCompatibilityIdentity(root, relative, text) {
|
|
371
408
|
const entry = readWorkflowTaxonomy(root)?.entries.find(
|
|
372
409
|
(item) => workflowPath(item) === relative && item.compatibility,
|
|
@@ -441,6 +478,8 @@ export function renderWorkflowCatalog(policy) {
|
|
|
441
478
|
"must name an exact migration source with a reason and removal condition.",
|
|
442
479
|
"The policy, generator, checker, tests, required CI chain and CODEOWNERS require",
|
|
443
480
|
"independent `kungfu-origin` review. No wildcard compatibility admission is allowed.",
|
|
481
|
+
"Workflow filenames cannot contain version tokens such as `v4` or `v5`.",
|
|
482
|
+
"Retired aliases cannot be recreated or called; see [path migration](workflow-path-migration.md).",
|
|
444
483
|
"",
|
|
445
484
|
"A role, category or implementation edit must preserve or deliberately update",
|
|
446
485
|
"all related declarations. Run `pnpm run generate:workflows` and",
|