@kungfu-tech/buildchain 2.8.8-alpha.6 → 2.8.8-alpha.7
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/dist/site/buildchain-contract.json +6 -6
- package/dist/site/buildchain-site.json +44 -9
- package/dist/site/kfd-claims.json +13 -1
- package/dist/site/manual-registry.json +3 -3
- package/dist/site/node-api-registry.json +10 -4
- package/dist/site/page-registry.json +11 -6
- package/dist/site/release-provenance.json +1 -0
- package/dist/site/site-manifest.json +33 -3
- package/docs/release-passport.md +4 -0
- package/docs/site-bundle-contract.md +28 -0
- package/docs/web-surface-deployments.md +26 -0
- package/package.json +2 -1
- package/packages/core/index.js +6 -0
- package/packages/core/release-passport.js +20 -1
- package/packages/core/surface-manifest.js +87 -0
- package/scripts/check-inventory.mjs +26 -0
- package/scripts/generate-site-bundle.mjs +32 -0
- package/scripts/web-surface-core.mjs +19 -0
- package/scripts/web-surface.mjs +10 -0
|
@@ -123,6 +123,9 @@ if (rootPackage.exports?.["./release-passport"] !== "./packages/core/release-pas
|
|
|
123
123
|
if (rootPackage.exports?.["./release-propagation"] !== "./packages/core/release-propagation.js") {
|
|
124
124
|
throw new Error("root package must export @kungfu-tech/buildchain/release-propagation");
|
|
125
125
|
}
|
|
126
|
+
if (rootPackage.exports?.["./surface-manifest"] !== "./packages/core/surface-manifest.js") {
|
|
127
|
+
throw new Error("root package must export @kungfu-tech/buildchain/surface-manifest");
|
|
128
|
+
}
|
|
126
129
|
if (rootPackage.exports?.["./buildchain-kfd-claims"] !== "./packages/core/buildchain-kfd-claims.js") {
|
|
127
130
|
throw new Error("root package must export @kungfu-tech/buildchain/buildchain-kfd-claims");
|
|
128
131
|
}
|
|
@@ -193,9 +196,18 @@ if (!coreIndexSource.includes("KFD2_RELEASE_TRUST_PASSPORT_CONTRACT")) {
|
|
|
193
196
|
if (!coreIndexSource.includes("KFD2_TRUST_PROOF_CONTRACT")) {
|
|
194
197
|
throw new Error("packages/core/index.js must export KFD-2 trust proof contract");
|
|
195
198
|
}
|
|
199
|
+
if (!coreIndexSource.includes("createSurfaceTimestampPolicy")) {
|
|
200
|
+
throw new Error("packages/core/index.js must export surface manifest timestamp policy APIs");
|
|
201
|
+
}
|
|
196
202
|
if (siteBundle.contract !== "kungfu-buildchain-site-bundle") {
|
|
197
203
|
throw new Error("buildchain-site.json must expose the Buildchain site bundle contract");
|
|
198
204
|
}
|
|
205
|
+
if (siteBundle.package?.version !== rootPackage.version) {
|
|
206
|
+
throw new Error("buildchain-site.json package.version must match package.json version");
|
|
207
|
+
}
|
|
208
|
+
if (siteManifest.package?.version !== rootPackage.version) {
|
|
209
|
+
throw new Error("site-manifest.json package.version must match package.json version");
|
|
210
|
+
}
|
|
199
211
|
if (siteBundle.source?.homepageTextSource !== "README.md") {
|
|
200
212
|
throw new Error("buildchain-site.json source.homepageTextSource must be README.md");
|
|
201
213
|
}
|
|
@@ -241,6 +253,20 @@ if (siteBundle.pageRegistry?.path !== "page-registry.json" || siteBundle.pageReg
|
|
|
241
253
|
if (!siteManifest.facts?.includes("page-registry.json") || !siteBundle.entrypoints?.includes("page-registry.json")) {
|
|
242
254
|
throw new Error("site bundle entrypoints must include page-registry.json");
|
|
243
255
|
}
|
|
256
|
+
for (const [name, manifest] of [["buildchain-site.json", siteBundle], ["site-manifest.json", siteManifest]]) {
|
|
257
|
+
if (!manifest.generatedAt) {
|
|
258
|
+
throw new Error(`${name} must expose generatedAt`);
|
|
259
|
+
}
|
|
260
|
+
if (manifest.timestampPolicy === "ci-injected" && manifest.generatedAt === "1970-01-01T00:00:00.000Z") {
|
|
261
|
+
throw new Error(`${name} must not use epoch generatedAt when timestampPolicy=ci-injected`);
|
|
262
|
+
}
|
|
263
|
+
if (!manifest.timestampPolicy || !manifest.reproducible || !Array.isArray(manifest.deterministicInputs)) {
|
|
264
|
+
throw new Error(`${name} must expose the Buildchain surface timestamp/reproducibility policy`);
|
|
265
|
+
}
|
|
266
|
+
if (manifest.timestampPolicyDetails?.contract !== "kungfu-buildchain-surface-timestamp-policy") {
|
|
267
|
+
throw new Error(`${name} must expose timestampPolicyDetails.contract`);
|
|
268
|
+
}
|
|
269
|
+
}
|
|
244
270
|
function immediateReadmes(dir) {
|
|
245
271
|
const absoluteDir = path.join(root, dir);
|
|
246
272
|
if (!fs.existsSync(absoluteDir)) return [];
|
|
@@ -8,6 +8,7 @@ import {
|
|
|
8
8
|
BUILDCHAIN_AGENT_MANUALS,
|
|
9
9
|
createBuildchainKfdClaimRegistry,
|
|
10
10
|
} from "../packages/core/buildchain-kfd-claims.js";
|
|
11
|
+
import { createSurfaceTimestampPolicy } from "../packages/core/surface-manifest.js";
|
|
11
12
|
|
|
12
13
|
const SITE_BUNDLE_CONTRACT = "kungfu-buildchain-site-bundle";
|
|
13
14
|
const README_PATH = "README.md";
|
|
@@ -31,6 +32,10 @@ function stableJson(value) {
|
|
|
31
32
|
return `${JSON.stringify(value, null, 2)}\n`;
|
|
32
33
|
}
|
|
33
34
|
|
|
35
|
+
function env(name) {
|
|
36
|
+
return String(process.env[name] || "").trim();
|
|
37
|
+
}
|
|
38
|
+
|
|
34
39
|
function sha256File(rel) {
|
|
35
40
|
const filePath = path.join(root, rel);
|
|
36
41
|
return fs.existsSync(filePath) && fs.statSync(filePath).isFile()
|
|
@@ -215,6 +220,30 @@ function buildSiteBundle() {
|
|
|
215
220
|
const readme = parseReadme(readText(README_PATH));
|
|
216
221
|
const docs = BUILDCHAIN_AGENT_MANUALS.map((manual) => docEntry(manual.id, manual.title, manual.path, manual.plane));
|
|
217
222
|
const pages = buildSitePages();
|
|
223
|
+
const generatedAtInput = env("BUILDCHAIN_SITE_GENERATED_AT") || env("BUILDCHAIN_SURFACE_GENERATED_AT");
|
|
224
|
+
const publishedAtInput = env("BUILDCHAIN_SITE_PUBLISHED_AT") || env("BUILDCHAIN_SURFACE_PUBLISHED_AT");
|
|
225
|
+
const timestampPolicyInput = env("BUILDCHAIN_SITE_TIMESTAMP_POLICY") || env("BUILDCHAIN_SURFACE_TIMESTAMP_POLICY");
|
|
226
|
+
const sourceRevisionInput =
|
|
227
|
+
env("BUILDCHAIN_SOURCE_SHA") ||
|
|
228
|
+
(generatedAtInput || publishedAtInput || timestampPolicyInput ? env("GITHUB_SHA") : "");
|
|
229
|
+
const timestampPolicy = createSurfaceTimestampPolicy({
|
|
230
|
+
generatedAt: generatedAtInput,
|
|
231
|
+
publishedAt: publishedAtInput,
|
|
232
|
+
sourceDateEpoch: env("SOURCE_DATE_EPOCH") || "0",
|
|
233
|
+
sourceRevision: sourceRevisionInput,
|
|
234
|
+
timestampPolicy: timestampPolicyInput,
|
|
235
|
+
deterministicInputs: [
|
|
236
|
+
"README.md",
|
|
237
|
+
"docs/*.md",
|
|
238
|
+
"actions/*/README.md",
|
|
239
|
+
"fixtures/*/README.md",
|
|
240
|
+
"packages/core/README.md",
|
|
241
|
+
"package.json#exports",
|
|
242
|
+
"tests/buildchain-inventory.json",
|
|
243
|
+
],
|
|
244
|
+
timestampFieldsParticipateInArtifactDigest: true,
|
|
245
|
+
artifactDigestScope: "npm package dist/site JSON files",
|
|
246
|
+
});
|
|
218
247
|
|
|
219
248
|
const cliRegistry = {
|
|
220
249
|
schemaVersion: 1,
|
|
@@ -438,6 +467,7 @@ function buildSiteBundle() {
|
|
|
438
467
|
const siteManifest = {
|
|
439
468
|
schemaVersion: 1,
|
|
440
469
|
contract: "kungfu-buildchain-site-manifest",
|
|
470
|
+
...timestampPolicy,
|
|
441
471
|
product: {
|
|
442
472
|
name: "Buildchain",
|
|
443
473
|
formalName: "Buildchain by Kungfu",
|
|
@@ -445,6 +475,7 @@ function buildSiteBundle() {
|
|
|
445
475
|
},
|
|
446
476
|
package: {
|
|
447
477
|
name: packageJson.name,
|
|
478
|
+
version: packageJson.version,
|
|
448
479
|
versionSource: "package.json#version",
|
|
449
480
|
},
|
|
450
481
|
entrypoint: "buildchain-site.json",
|
|
@@ -549,6 +580,7 @@ function buildSiteBundle() {
|
|
|
549
580
|
const siteBundle = {
|
|
550
581
|
schemaVersion: 1,
|
|
551
582
|
contract: SITE_BUNDLE_CONTRACT,
|
|
583
|
+
...timestampPolicy,
|
|
552
584
|
product: siteManifest.product,
|
|
553
585
|
package: siteManifest.package,
|
|
554
586
|
source: {
|
|
@@ -5,6 +5,7 @@ import fs from "node:fs";
|
|
|
5
5
|
import os from "node:os";
|
|
6
6
|
import path from "node:path";
|
|
7
7
|
import { loadBuildchainConfig, validateBuildchainConfig } from "../packages/core/buildchain-config.js";
|
|
8
|
+
import { createSurfaceTimestampPolicy } from "../packages/core/surface-manifest.js";
|
|
8
9
|
|
|
9
10
|
const DEFAULT_RETENTION = Object.freeze({
|
|
10
11
|
preview: {
|
|
@@ -609,9 +610,27 @@ export function createWebSurfaceDeploymentManifest({
|
|
|
609
610
|
deployConfig,
|
|
610
611
|
});
|
|
611
612
|
const primaryBinding = surfaceBindings[0];
|
|
613
|
+
const timestampPolicy = createSurfaceTimestampPolicy({
|
|
614
|
+
generatedAt: deployedAt,
|
|
615
|
+
publishedAt: deployedAt,
|
|
616
|
+
sourceRevision: sourceSha,
|
|
617
|
+
timestampPolicy: "ci-injected",
|
|
618
|
+
deterministicInputs: [
|
|
619
|
+
"web-surface artifact content",
|
|
620
|
+
"buildchain.toml web-surface channels/deploy/surfaces",
|
|
621
|
+
"sourceSha",
|
|
622
|
+
"artifactHash",
|
|
623
|
+
"deployment channel",
|
|
624
|
+
"deployment alias",
|
|
625
|
+
],
|
|
626
|
+
timestampFields: ["generatedAt", "publishedAt", "deployedAt"],
|
|
627
|
+
timestampFieldsParticipateInArtifactDigest: false,
|
|
628
|
+
artifactDigestScope: "web-surface artifactHash excludes deployment manifest timestamps",
|
|
629
|
+
});
|
|
612
630
|
return {
|
|
613
631
|
schemaVersion: 1,
|
|
614
632
|
contract: "kungfu-buildchain-web-surface-deployment",
|
|
633
|
+
...timestampPolicy,
|
|
615
634
|
site: config.project.site || config.project.name || "",
|
|
616
635
|
channel,
|
|
617
636
|
alias,
|
package/scripts/web-surface.mjs
CHANGED
|
@@ -77,6 +77,10 @@ export function webSurfaceCli() {
|
|
|
77
77
|
"alias",
|
|
78
78
|
process.env.BUILDCHAIN_WEB_SURFACE_ALIAS || defaultWebSurfaceAlias({ channel, sourceSha, pullNumber }),
|
|
79
79
|
);
|
|
80
|
+
const generatedAt = readArg(
|
|
81
|
+
"generated-at",
|
|
82
|
+
process.env.BUILDCHAIN_SITE_GENERATED_AT || process.env.BUILDCHAIN_SURFACE_GENERATED_AT || "",
|
|
83
|
+
);
|
|
80
84
|
const result = planWebSurfaceDeploy({
|
|
81
85
|
cwd,
|
|
82
86
|
channel,
|
|
@@ -89,6 +93,7 @@ export function webSurfaceCli() {
|
|
|
89
93
|
rollbackPointer: readArg("rollback-pointer", process.env.BUILDCHAIN_ROLLBACK_REF || ""),
|
|
90
94
|
rollbackLimitations: readArg("rollback-limitations", process.env.BUILDCHAIN_ROLLBACK_LIMITATIONS || ""),
|
|
91
95
|
dryRun: readBooleanArg("dry-run", true),
|
|
96
|
+
...(generatedAt ? { deployedAt: generatedAt } : {}),
|
|
92
97
|
});
|
|
93
98
|
const outputResult = mode === "manifest" ? result.manifest : result;
|
|
94
99
|
writeJson(outputResult, output);
|
|
@@ -111,6 +116,10 @@ export function webSurfaceCli() {
|
|
|
111
116
|
"alias",
|
|
112
117
|
process.env.BUILDCHAIN_WEB_SURFACE_ALIAS || defaultWebSurfaceAlias({ channel, sourceSha, pullNumber }),
|
|
113
118
|
);
|
|
119
|
+
const publishedAt = readArg(
|
|
120
|
+
"published-at",
|
|
121
|
+
process.env.BUILDCHAIN_SITE_PUBLISHED_AT || process.env.BUILDCHAIN_SURFACE_PUBLISHED_AT || "",
|
|
122
|
+
);
|
|
114
123
|
const result = applyWebSurfaceDeploy({
|
|
115
124
|
cwd,
|
|
116
125
|
channel,
|
|
@@ -122,6 +131,7 @@ export function webSurfaceCli() {
|
|
|
122
131
|
dryRun: readBooleanArg("dry-run", true),
|
|
123
132
|
actor: readArg("actor", process.env.GITHUB_ACTOR || ""),
|
|
124
133
|
runId: readArg("run-id", process.env.GITHUB_RUN_ID || ""),
|
|
134
|
+
...(publishedAt ? { appliedAt: publishedAt } : {}),
|
|
125
135
|
});
|
|
126
136
|
writeJson(result, output);
|
|
127
137
|
writeGitHubOutputs({
|