@kungfu-tech/buildchain 3.0.9-alpha.1 → 3.0.9-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/actions/promote-buildchain-ref/README.md +4 -0
- package/bin/buildchain.mjs +9 -1
- package/bin/internal/trust-release-release-handlers.mjs +1 -0
- package/contracts/dev-delivery-authority-v2.schema.json +253 -0
- package/contracts/fixtures/next-development-transition-v1/anchored-manual-waiting.json +47 -0
- package/contracts/fixtures/next-development-transition-v1/semver-auto-planned.json +47 -0
- package/contracts/fixtures/next-development-transition-v1/version-model-cases.json +40 -0
- package/contracts/next-development-request-v1.schema.json +66 -0
- package/contracts/next-development-transition-v1.schema.json +292 -0
- package/dist/site/agent-index.json +1 -0
- package/dist/site/artifact-schemas.json +2 -0
- package/dist/site/buildchain-contract.json +92 -27
- package/dist/site/buildchain-site.json +351 -38
- package/dist/site/capability-registry.json +7 -6
- package/dist/site/cli-registry.json +43 -3
- package/dist/site/controller-registry.json +6 -2
- package/dist/site/kfd-claims.json +223 -12
- package/dist/site/kfd-upstream-aggregate.json +9 -9
- package/dist/site/manual-registry.json +23 -7
- package/dist/site/node-api-registry.json +7926 -4533
- package/dist/site/page-registry.json +332 -27
- package/dist/site/public-surface-audit.json +359 -11
- package/dist/site/publication-registry.json +4 -4
- package/dist/site/release-passport-check-manifest.json +1 -0
- package/dist/site/release-provenance.json +14 -0
- package/dist/site/schemas/dev-delivery-authority-v2.schema.json +442 -0
- package/dist/site/schemas/release-passport-v1.schema.json +3 -0
- package/dist/site/site-manifest.json +19 -11
- package/dist/site/workflow-registry.json +21 -10
- package/docs/MAP.md +5 -2
- package/docs/adopter-delivery-gate.md +106 -0
- package/docs/aws-us-elastic-runner-burst-plane.md +30 -3
- package/docs/cli-reference.md +202 -15
- package/docs/dev-alpha-candidate-patrol.md +8 -0
- package/docs/dev-delivery-qualification-landing-adr.md +137 -0
- package/docs/dev-delivery-warrant.md +149 -22
- package/docs/kfd-support.md +7 -2
- package/docs/next-development-transition.md +119 -0
- package/docs/node-api-reference.md +402 -204
- package/docs/release-governance.md +10 -7
- package/docs/release-passport.md +18 -2
- package/docs/versioning.md +4 -1
- package/package.json +23 -6
- package/packages/core/README.md +25 -0
- package/packages/core/adopter-delivery-gate.js +576 -0
- package/packages/core/adopter-delivery-json.js +66 -0
- package/packages/core/adopter-delivery-passport.js +259 -0
- package/packages/core/adopter-delivery-vectors.js +158 -0
- package/packages/core/adopter-delivery-vectors.json +77 -0
- package/packages/core/artifact-verification-envelope.js +5 -5
- package/packages/core/buildchain-agent-manuals.js +1 -0
- package/packages/core/buildchain-channel-identity.js +2 -3
- package/packages/core/buildchain-compatibility-proof.js +22 -0
- package/packages/core/buildchain-delivery-bootstrap.js +240 -0
- package/packages/core/buildchain-delivery-infrastructure.js +164 -0
- package/packages/core/buildchain-delivery-self-dogfood.js +395 -0
- package/packages/core/channel-candidate.js +8 -0
- package/packages/core/channel-promotion-baseline.js +52 -0
- package/packages/core/dev-alpha-candidate-selection.js +10 -2
- package/packages/core/dev-delivery-authority.js +996 -0
- package/packages/core/dev-delivery-native-proof.js +418 -0
- package/packages/core/dev-delivery-warrant-settlement.js +67 -20
- package/packages/core/dev-delivery-warrant.js +129 -46
- package/packages/core/kfd-adopter-category-driver.js +167 -0
- package/packages/core/kfd-adopter-manifest.js +49 -50
- package/packages/core/legacy-kfd-adopter-driver.js +167 -0
- package/packages/core/next-development-candidate-reservation.js +186 -0
- package/packages/core/next-development-controller.js +726 -0
- package/packages/core/next-development-projection.js +288 -0
- package/packages/core/next-development-transition.js +738 -0
- package/packages/core/paper-agent-entry.js +7 -4
- package/packages/core/paper.js +14 -7
- package/packages/core/published-delivery-authority.js +247 -0
- package/packages/core/release-passport-contract.js +10 -6
- package/packages/core/release-passport.js +37 -13
- package/scripts/aws-macos-jit-controller-core.mjs +239 -4
- package/scripts/aws-macos-jit-controller.mjs +198 -2
- package/scripts/aws-macos-jit-instance-rehydrate.mjs +260 -0
- package/scripts/aws-macos-jit-source-rebind.mjs +235 -14
- package/scripts/aws-macos-jit.mjs +12 -0
- package/scripts/buildchain-cli-help.mjs +10 -2
- package/scripts/check-internal-architecture.mjs +1 -0
- package/scripts/check-inventory.mjs +12 -1
- package/scripts/dev-alpha-candidate-patrol.mjs +22 -1
- package/scripts/dev-delivery-authority.mjs +368 -0
- package/scripts/dev-delivery-native-run.mjs +235 -0
- package/scripts/dev-delivery-proof.mjs +64 -2
- package/scripts/dev-delivery-two-phase-resume.mjs +90 -0
- package/scripts/dev-delivery-two-phase.mjs +577 -0
- package/scripts/dev-delivery-warrant.mjs +48 -6
- package/scripts/dev-pr-delivery-warrant.mjs +19 -14
- package/scripts/generate-buildchain-kfd-witnesses.mjs +2 -2
- package/scripts/generate-channel-build-workflow.mjs +4 -0
- package/scripts/generate-next-development-guidance.mjs +49 -0
- package/scripts/generate-site-bundle.mjs +8 -3
- package/scripts/init-repo.mjs +135 -62
- package/scripts/next-development-self-dogfood-harness.mjs +409 -0
- package/scripts/next-development-self-dogfood.mjs +532 -0
- package/scripts/next-development-transition.mjs +47 -0
- package/scripts/release-candidate-tail-reseal.mjs +426 -0
- package/scripts/seal-artifact-signing-requests.mjs +7 -4
- package/scripts/site-capability-metadata.mjs +25 -1
- package/scripts/stable-candidate-qualification.mjs +7 -7
- package/scripts/workflow-call-contract.mjs +1 -1
- package/templates/native-dev-delivery.yml +86 -0
|
@@ -0,0 +1,395 @@
|
|
|
1
|
+
import { initAdopterManifest } from "@kungfu-tech/kfd/adopter-conformance/toolchain";
|
|
2
|
+
|
|
3
|
+
import { adopterDeliveryGateDigest } from "./adopter-delivery-gate.js";
|
|
4
|
+
import { withPublishedBuildchainDeliveryAuthority } from "./published-delivery-authority.js";
|
|
5
|
+
|
|
6
|
+
export const BUILDCHAIN_DELIVERY_SELF_DOGFOOD_CONTRACT =
|
|
7
|
+
"kungfu-buildchain-delivery-infrastructure-self-dogfood/v1";
|
|
8
|
+
|
|
9
|
+
const ROOT_PATTERN = /^sha256:[0-9a-f]{64}$/;
|
|
10
|
+
const SHA_PATTERN = /^[0-9a-f]{40}$/;
|
|
11
|
+
const BUILDCHAIN_PACKAGE = "@kungfu-tech/buildchain";
|
|
12
|
+
const KFD_PACKAGE = "@kungfu-tech/kfd";
|
|
13
|
+
const PROFILE_REQUIREMENTS = Object.freeze([
|
|
14
|
+
["adopter-identity", ["declaration"]],
|
|
15
|
+
["artifact-readback", ["verification"]],
|
|
16
|
+
["claim-boundary", ["declaration"]],
|
|
17
|
+
["delivery-policy-cut", ["declaration", "verification"]],
|
|
18
|
+
["kfd-cut", ["verification"]],
|
|
19
|
+
["protected-delivery", ["implementation", "review", "verification"]],
|
|
20
|
+
["source-artifact", ["implementation"]],
|
|
21
|
+
]);
|
|
22
|
+
|
|
23
|
+
function exactPackage(value, { name, version = "", root = "", label }) {
|
|
24
|
+
if (
|
|
25
|
+
value?.name !== name ||
|
|
26
|
+
typeof value.version !== "string" ||
|
|
27
|
+
value.version.length === 0 ||
|
|
28
|
+
!ROOT_PATTERN.test(value.artifactRoot ?? "")
|
|
29
|
+
) {
|
|
30
|
+
throw new TypeError(`${label} package identity is incomplete`);
|
|
31
|
+
}
|
|
32
|
+
if (version && value.version !== version) {
|
|
33
|
+
throw new TypeError(`${label} package version does not match its binding`);
|
|
34
|
+
}
|
|
35
|
+
if (root && value.artifactRoot !== root) {
|
|
36
|
+
throw new TypeError(`${label} package root does not match its binding`);
|
|
37
|
+
}
|
|
38
|
+
return structuredClone(value);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function authorityFunctions(authorityRuntime) {
|
|
42
|
+
const names = [
|
|
43
|
+
"createBuildchainDeliveryInfrastructureInstanceManifest",
|
|
44
|
+
"verifyBuildchainDeliveryInfrastructureInstance",
|
|
45
|
+
"createAdopterDeliveryGate",
|
|
46
|
+
"createPackageArtifactProfile",
|
|
47
|
+
"createKfdAdopterCategoryProtocolDriver",
|
|
48
|
+
"qualifyBuildchainDeliveryInfrastructureBootstrap",
|
|
49
|
+
];
|
|
50
|
+
for (const name of names) {
|
|
51
|
+
if (typeof authorityRuntime?.[name] !== "function") {
|
|
52
|
+
throw new TypeError(`authority runtime is missing ${name}`);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
return authorityRuntime;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function passed(value, label) {
|
|
59
|
+
if (value?.status !== "passed") {
|
|
60
|
+
throw new Error(
|
|
61
|
+
`${label} failed closed: ${JSON.stringify(value?.issues ?? [])}`,
|
|
62
|
+
);
|
|
63
|
+
}
|
|
64
|
+
return value;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
function candidateWarrant(candidate) {
|
|
68
|
+
const terminal = candidate?.terminal;
|
|
69
|
+
if (
|
|
70
|
+
candidate?.status !== "merged" ||
|
|
71
|
+
!SHA_PATTERN.test(candidate?.sourceHead ?? "") ||
|
|
72
|
+
!ROOT_PATTERN.test(candidate?.sourceProofRoot ?? "") ||
|
|
73
|
+
terminal?.outcome !== "merged" ||
|
|
74
|
+
!ROOT_PATTERN.test(terminal?.nativeProofRoot ?? "") ||
|
|
75
|
+
!ROOT_PATTERN.test(terminal?.evidenceRoot ?? "")
|
|
76
|
+
) {
|
|
77
|
+
throw new TypeError("candidate Warrant settlement is incomplete");
|
|
78
|
+
}
|
|
79
|
+
return {
|
|
80
|
+
outcome: "merged",
|
|
81
|
+
sourceHead: candidate.sourceHead,
|
|
82
|
+
sourceProofRoot: candidate.sourceProofRoot,
|
|
83
|
+
nativeProofRoot: terminal.nativeProofRoot,
|
|
84
|
+
integrationProofRoot: terminal.evidenceRoot,
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
function deliveryCut() {
|
|
89
|
+
const protocol = {
|
|
90
|
+
id: "kfd.adopter-category/instance-manifest",
|
|
91
|
+
version: "1.0.0",
|
|
92
|
+
};
|
|
93
|
+
protocol.root = adopterDeliveryGateDigest(protocol);
|
|
94
|
+
const profile = {
|
|
95
|
+
id: "kfd.adopter-category/delivery-infrastructure",
|
|
96
|
+
version: "1.0.0",
|
|
97
|
+
};
|
|
98
|
+
profile.root = adopterDeliveryGateDigest({
|
|
99
|
+
...profile,
|
|
100
|
+
requirements: PROFILE_REQUIREMENTS,
|
|
101
|
+
});
|
|
102
|
+
return {
|
|
103
|
+
gateRoot: adopterDeliveryGateDigest({
|
|
104
|
+
protocol,
|
|
105
|
+
profile,
|
|
106
|
+
artifactProfile: {
|
|
107
|
+
id: "buildchain.artifact/package",
|
|
108
|
+
version: "1.0.0",
|
|
109
|
+
},
|
|
110
|
+
}),
|
|
111
|
+
protocol,
|
|
112
|
+
profile,
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
function candidateEvidence({
|
|
117
|
+
source,
|
|
118
|
+
artifact,
|
|
119
|
+
authority,
|
|
120
|
+
warrant,
|
|
121
|
+
kfdRoot,
|
|
122
|
+
observedAt,
|
|
123
|
+
}) {
|
|
124
|
+
const roots = {
|
|
125
|
+
"adopter-identity:declaration": source.root,
|
|
126
|
+
"artifact-readback:verification": artifact.root,
|
|
127
|
+
"claim-boundary:declaration": adopterDeliveryGateDigest({
|
|
128
|
+
qualifying: false,
|
|
129
|
+
selfCertified: false,
|
|
130
|
+
releaseAuthorized: false,
|
|
131
|
+
}),
|
|
132
|
+
"delivery-policy-cut:declaration": authority.gateRoot,
|
|
133
|
+
"delivery-policy-cut:verification": warrant.integrationProofRoot,
|
|
134
|
+
"kfd-cut:verification": kfdRoot,
|
|
135
|
+
"protected-delivery:implementation": artifact.root,
|
|
136
|
+
"protected-delivery:review": warrant.sourceProofRoot,
|
|
137
|
+
"protected-delivery:verification": warrant.nativeProofRoot,
|
|
138
|
+
"source-artifact:implementation": source.root,
|
|
139
|
+
};
|
|
140
|
+
return PROFILE_REQUIREMENTS.flatMap(([requirementId, kinds]) =>
|
|
141
|
+
kinds.map((kind) => ({
|
|
142
|
+
requirementId,
|
|
143
|
+
kind,
|
|
144
|
+
coordinate: `evidence://kungfu-systems/buildchain/${requirementId}/${kind}`,
|
|
145
|
+
root: roots[`${requirementId}:${kind}`],
|
|
146
|
+
observedAt,
|
|
147
|
+
})),
|
|
148
|
+
);
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
export function createBuildchainDeliveryInfrastructureSelfDogfood(
|
|
152
|
+
{
|
|
153
|
+
authorityPackage,
|
|
154
|
+
kfdPackage,
|
|
155
|
+
authority,
|
|
156
|
+
candidate,
|
|
157
|
+
instanceId,
|
|
158
|
+
adopterManifest,
|
|
159
|
+
source,
|
|
160
|
+
artifact,
|
|
161
|
+
release,
|
|
162
|
+
evidence = [],
|
|
163
|
+
warrant,
|
|
164
|
+
transitionEvidence,
|
|
165
|
+
verifiedAt,
|
|
166
|
+
maxAgeSeconds,
|
|
167
|
+
} = {},
|
|
168
|
+
authorityRuntime,
|
|
169
|
+
) {
|
|
170
|
+
const runtime = authorityFunctions(authorityRuntime);
|
|
171
|
+
const boundAuthorityPackage = exactPackage(authorityPackage, {
|
|
172
|
+
name: BUILDCHAIN_PACKAGE,
|
|
173
|
+
version: authority?.version,
|
|
174
|
+
root: authority?.packageRoot,
|
|
175
|
+
label: "Buildchain authority",
|
|
176
|
+
});
|
|
177
|
+
const boundKfdPackage = exactPackage(kfdPackage, {
|
|
178
|
+
name: KFD_PACKAGE,
|
|
179
|
+
version: adopterManifest?.kfdCut?.package?.version,
|
|
180
|
+
root: adopterManifest?.kfdCut?.package?.artifactRoot,
|
|
181
|
+
label: "KFD authority",
|
|
182
|
+
});
|
|
183
|
+
if (candidate?.authorityVersion !== boundAuthorityPackage.version) {
|
|
184
|
+
throw new TypeError(
|
|
185
|
+
"candidate does not name the exact Buildchain N-1 authority",
|
|
186
|
+
);
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
const instanceManifest =
|
|
190
|
+
runtime.createBuildchainDeliveryInfrastructureInstanceManifest({
|
|
191
|
+
instanceId,
|
|
192
|
+
adopterManifest,
|
|
193
|
+
source,
|
|
194
|
+
artifact,
|
|
195
|
+
release,
|
|
196
|
+
evidence,
|
|
197
|
+
});
|
|
198
|
+
const instanceReport = runtime.verifyBuildchainDeliveryInfrastructureInstance(
|
|
199
|
+
instanceManifest,
|
|
200
|
+
{
|
|
201
|
+
adopterManifest,
|
|
202
|
+
verifiedAt,
|
|
203
|
+
maxAgeSeconds,
|
|
204
|
+
},
|
|
205
|
+
);
|
|
206
|
+
if (instanceReport?.valid !== true) {
|
|
207
|
+
throw new Error(
|
|
208
|
+
`delivery-infrastructure instance failed closed: ${JSON.stringify(instanceReport?.issues ?? [])}`,
|
|
209
|
+
);
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
const gateResult = passed(
|
|
213
|
+
runtime
|
|
214
|
+
.createAdopterDeliveryGate({
|
|
215
|
+
drivers: [runtime.createKfdAdopterCategoryProtocolDriver()],
|
|
216
|
+
artifactProfiles: [runtime.createPackageArtifactProfile()],
|
|
217
|
+
})
|
|
218
|
+
.evaluate(
|
|
219
|
+
{
|
|
220
|
+
schemaVersion: 1,
|
|
221
|
+
contract: "kungfu-buildchain-adopter-delivery-request",
|
|
222
|
+
protocol: {
|
|
223
|
+
id: "kfd.adopter-category/instance-manifest",
|
|
224
|
+
version: "1.0.0",
|
|
225
|
+
},
|
|
226
|
+
artifactProfile: {
|
|
227
|
+
id: "buildchain.artifact/package",
|
|
228
|
+
version: "1.0.0",
|
|
229
|
+
},
|
|
230
|
+
project: {
|
|
231
|
+
instanceId,
|
|
232
|
+
adopterId: "kungfu-systems/buildchain",
|
|
233
|
+
},
|
|
234
|
+
artifact: structuredClone(artifact),
|
|
235
|
+
declaration: instanceManifest,
|
|
236
|
+
},
|
|
237
|
+
{ adopterManifest, verifiedAt, maxAgeSeconds },
|
|
238
|
+
),
|
|
239
|
+
"adopter delivery gate",
|
|
240
|
+
);
|
|
241
|
+
const bootstrap = passed(
|
|
242
|
+
runtime.qualifyBuildchainDeliveryInfrastructureBootstrap({
|
|
243
|
+
authority,
|
|
244
|
+
candidate,
|
|
245
|
+
gateResult,
|
|
246
|
+
warrant,
|
|
247
|
+
transitionEvidence,
|
|
248
|
+
}),
|
|
249
|
+
"delivery-infrastructure bootstrap",
|
|
250
|
+
);
|
|
251
|
+
|
|
252
|
+
const result = {
|
|
253
|
+
schemaVersion: 1,
|
|
254
|
+
contract: BUILDCHAIN_DELIVERY_SELF_DOGFOOD_CONTRACT,
|
|
255
|
+
status: "passed",
|
|
256
|
+
authorityRuntime: {
|
|
257
|
+
buildchainPackage: boundAuthorityPackage,
|
|
258
|
+
kfdPackage: boundKfdPackage,
|
|
259
|
+
},
|
|
260
|
+
candidate: structuredClone(candidate),
|
|
261
|
+
roots: {
|
|
262
|
+
adopterManifest: adopterDeliveryGateDigest(adopterManifest),
|
|
263
|
+
instanceManifest: adopterDeliveryGateDigest(instanceManifest),
|
|
264
|
+
instanceReport: adopterDeliveryGateDigest(instanceReport),
|
|
265
|
+
gateResult: gateResult.gateRoot,
|
|
266
|
+
bootstrap: bootstrap.bootstrapRoot,
|
|
267
|
+
warrant: adopterDeliveryGateDigest(warrant),
|
|
268
|
+
},
|
|
269
|
+
instanceManifest,
|
|
270
|
+
instanceReport,
|
|
271
|
+
gateResult,
|
|
272
|
+
bootstrap,
|
|
273
|
+
qualifying: false,
|
|
274
|
+
selfCertified: false,
|
|
275
|
+
releaseAuthorized: false,
|
|
276
|
+
finalAuthority:
|
|
277
|
+
"protected-n-minus-one-runtime-plus-exact-delivery-evidence",
|
|
278
|
+
};
|
|
279
|
+
result.selfDogfoodRoot = adopterDeliveryGateDigest(result);
|
|
280
|
+
return result;
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
export async function createPublishedBuildchainDeliveryInfrastructureSelfDogfood({
|
|
284
|
+
authorityPackages,
|
|
285
|
+
selfDogfood,
|
|
286
|
+
} = {}) {
|
|
287
|
+
return withPublishedBuildchainDeliveryAuthority(
|
|
288
|
+
authorityPackages,
|
|
289
|
+
async ({ packages, authorityRuntime, authorityRoot }) => {
|
|
290
|
+
const result = createBuildchainDeliveryInfrastructureSelfDogfood(
|
|
291
|
+
{
|
|
292
|
+
...structuredClone(selfDogfood ?? {}),
|
|
293
|
+
authorityPackage: packages.buildchain,
|
|
294
|
+
kfdPackage: packages.kfd,
|
|
295
|
+
},
|
|
296
|
+
authorityRuntime,
|
|
297
|
+
);
|
|
298
|
+
return {
|
|
299
|
+
...result,
|
|
300
|
+
publishedAuthorityRoot: authorityRoot,
|
|
301
|
+
};
|
|
302
|
+
},
|
|
303
|
+
);
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
export async function createPublishedBuildchainDeliveryInfrastructureCandidateSelfDogfood({
|
|
307
|
+
authorityPackages,
|
|
308
|
+
authoritySourceCommit,
|
|
309
|
+
candidatePackage,
|
|
310
|
+
warrantCandidate,
|
|
311
|
+
source,
|
|
312
|
+
release,
|
|
313
|
+
verifiedAt,
|
|
314
|
+
maxAgeSeconds = 86400,
|
|
315
|
+
} = {}) {
|
|
316
|
+
if (!SHA_PATTERN.test(authoritySourceCommit ?? "")) {
|
|
317
|
+
throw new TypeError("authority source commit is invalid");
|
|
318
|
+
}
|
|
319
|
+
const artifact = exactPackage(candidatePackage, {
|
|
320
|
+
name: BUILDCHAIN_PACKAGE,
|
|
321
|
+
label: "Buildchain candidate",
|
|
322
|
+
});
|
|
323
|
+
if (
|
|
324
|
+
source?.coordinate !==
|
|
325
|
+
`kungfu-systems/buildchain@${warrantCandidate?.sourceHead ?? ""}` ||
|
|
326
|
+
!ROOT_PATTERN.test(source?.root ?? "") ||
|
|
327
|
+
!ROOT_PATTERN.test(release?.root ?? "")
|
|
328
|
+
) {
|
|
329
|
+
throw new TypeError("candidate source or release binding is incomplete");
|
|
330
|
+
}
|
|
331
|
+
const warrant = candidateWarrant(warrantCandidate);
|
|
332
|
+
const cut = deliveryCut();
|
|
333
|
+
const authority = {
|
|
334
|
+
version: authorityPackages?.buildchain?.version,
|
|
335
|
+
sourceCommit: authoritySourceCommit,
|
|
336
|
+
packageRoot: authorityPackages?.buildchain?.artifactRoot,
|
|
337
|
+
...cut,
|
|
338
|
+
protected: true,
|
|
339
|
+
published: true,
|
|
340
|
+
};
|
|
341
|
+
const candidate = {
|
|
342
|
+
version: artifact.version,
|
|
343
|
+
sourceCommit: warrant.sourceHead,
|
|
344
|
+
packageRoot: artifact.artifactRoot,
|
|
345
|
+
...cut,
|
|
346
|
+
authorityVersion: authority.version,
|
|
347
|
+
};
|
|
348
|
+
const adopterManifest = initAdopterManifest({
|
|
349
|
+
manifestId: `buildchain-delivery-infrastructure-${artifact.version}`,
|
|
350
|
+
adopterId: "kungfu-systems/buildchain",
|
|
351
|
+
artifactKind: "package",
|
|
352
|
+
artifactCoordinate: `${artifact.name}@${artifact.version}`,
|
|
353
|
+
artifactRoot: artifact.artifactRoot,
|
|
354
|
+
scope: "Buildchain delivery infrastructure release candidate self-dogfood",
|
|
355
|
+
packageArtifactRoot: authorityPackages?.kfd?.artifactRoot,
|
|
356
|
+
verifiedAt,
|
|
357
|
+
maxAgeSeconds,
|
|
358
|
+
});
|
|
359
|
+
adopterManifest.releaseBindings.push({
|
|
360
|
+
id: `buildchain-${artifact.version}`,
|
|
361
|
+
artifact: {
|
|
362
|
+
kind: "package",
|
|
363
|
+
coordinate: `${artifact.name}@${artifact.version}`,
|
|
364
|
+
root: artifact.artifactRoot,
|
|
365
|
+
},
|
|
366
|
+
releasePassport: structuredClone(release),
|
|
367
|
+
kfdPackageRoot: authorityPackages.kfd.artifactRoot,
|
|
368
|
+
});
|
|
369
|
+
const evidence = candidateEvidence({
|
|
370
|
+
source,
|
|
371
|
+
artifact: adopterManifest.releaseBindings[0].artifact,
|
|
372
|
+
authority,
|
|
373
|
+
warrant,
|
|
374
|
+
kfdRoot: authorityPackages.kfd.artifactRoot,
|
|
375
|
+
observedAt: verifiedAt,
|
|
376
|
+
});
|
|
377
|
+
const result =
|
|
378
|
+
await createPublishedBuildchainDeliveryInfrastructureSelfDogfood({
|
|
379
|
+
authorityPackages,
|
|
380
|
+
selfDogfood: {
|
|
381
|
+
authority,
|
|
382
|
+
candidate,
|
|
383
|
+
instanceId: `kungfu-systems/buildchain@${artifact.version}`,
|
|
384
|
+
adopterManifest,
|
|
385
|
+
source,
|
|
386
|
+
artifact: adopterManifest.releaseBindings[0].artifact,
|
|
387
|
+
release,
|
|
388
|
+
evidence,
|
|
389
|
+
warrant,
|
|
390
|
+
verifiedAt,
|
|
391
|
+
maxAgeSeconds,
|
|
392
|
+
},
|
|
393
|
+
});
|
|
394
|
+
return { ...result, adopterManifest, deliveryEvidence: evidence };
|
|
395
|
+
}
|
|
@@ -97,6 +97,14 @@ export function decideChannelCandidate(input) {
|
|
|
97
97
|
const sourceSha = sha(input.sourceSha, "sourceSha");
|
|
98
98
|
const targetSha = sha(input.targetSha, "targetSha");
|
|
99
99
|
const selection = normalizeChannelCandidateSelection(input.selection);
|
|
100
|
+
if (
|
|
101
|
+
selection?.versionReservation &&
|
|
102
|
+
selection.versionReservation.candidateSha !== sourceSha
|
|
103
|
+
) {
|
|
104
|
+
throw new Error(
|
|
105
|
+
"selection version reservation must bind the selected source SHA",
|
|
106
|
+
);
|
|
107
|
+
}
|
|
100
108
|
const now = required(input.now || new Date().toISOString(), "now");
|
|
101
109
|
const maxAgeSeconds = Number(input.maxAgeSeconds ?? 7 * 24 * 60 * 60);
|
|
102
110
|
if (!Number.isSafeInteger(maxAgeSeconds) || maxAgeSeconds <= 0) {
|
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
// SPDX-License-Identifier: Apache-2.0
|
|
2
2
|
|
|
3
|
+
import {
|
|
4
|
+
nextDevelopmentPatrolContext,
|
|
5
|
+
normalizeNextDevelopmentVersionReservation,
|
|
6
|
+
} from "./next-development-candidate-reservation.js";
|
|
7
|
+
|
|
3
8
|
const SHA = /^[0-9a-f]{40}$/;
|
|
4
9
|
|
|
5
10
|
function text(value = "") {
|
|
@@ -59,6 +64,18 @@ export function normalizeChannelCandidateSelection(input) {
|
|
|
59
64
|
),
|
|
60
65
|
}
|
|
61
66
|
: {}),
|
|
67
|
+
...(input.versionReservation
|
|
68
|
+
? {
|
|
69
|
+
versionReservation: normalizeNextDevelopmentVersionReservation(
|
|
70
|
+
input.versionReservation,
|
|
71
|
+
{
|
|
72
|
+
reservationSha: input.versionReservation.reservationSha,
|
|
73
|
+
candidateSha: input.versionReservation.candidateSha,
|
|
74
|
+
targetVersion: input.versionReservation.targetVersion,
|
|
75
|
+
},
|
|
76
|
+
),
|
|
77
|
+
}
|
|
78
|
+
: {}),
|
|
62
79
|
};
|
|
63
80
|
}
|
|
64
81
|
|
|
@@ -117,6 +134,7 @@ export async function resolvePatrolSourceInputs({
|
|
|
117
134
|
let comparison = headComparison;
|
|
118
135
|
let workflowEvidence = [];
|
|
119
136
|
let skippedNewerCommitCount = 0;
|
|
137
|
+
let versionReservation;
|
|
120
138
|
let qualificationError;
|
|
121
139
|
if (
|
|
122
140
|
headComparison.status === "ahead" &&
|
|
@@ -130,6 +148,8 @@ export async function resolvePatrolSourceInputs({
|
|
|
130
148
|
),
|
|
131
149
|
]);
|
|
132
150
|
try {
|
|
151
|
+
const { preparations, ignoredSourceShas } =
|
|
152
|
+
nextDevelopmentPatrolContext(sourceHistory);
|
|
133
153
|
const selected = selectQualifiedSource({
|
|
134
154
|
sourceHistory,
|
|
135
155
|
workflowRunsByPath: new Map(
|
|
@@ -141,8 +161,39 @@ export async function resolvePatrolSourceInputs({
|
|
|
141
161
|
requiredWorkflowPaths,
|
|
142
162
|
now: options.now,
|
|
143
163
|
maxAgeSeconds: options.maxAgeSeconds,
|
|
164
|
+
ignoredSourceShas,
|
|
144
165
|
});
|
|
145
166
|
({ sourceSha, skippedNewerCommitCount, workflowEvidence } = selected);
|
|
167
|
+
const selectedIndex = sourceHistory.findIndex((entry) =>
|
|
168
|
+
(typeof entry === "string" ? entry : entry?.sha) === sourceSha,
|
|
169
|
+
);
|
|
170
|
+
const reservation = preparations.find(
|
|
171
|
+
({ index }) => index > selectedIndex,
|
|
172
|
+
)?.preparation;
|
|
173
|
+
if (reservation) {
|
|
174
|
+
if (typeof client.readNextDevelopmentVersionReservation !== "function") {
|
|
175
|
+
throw new Error(
|
|
176
|
+
"candidate follows next-development preparation but reservation readback is unavailable",
|
|
177
|
+
);
|
|
178
|
+
}
|
|
179
|
+
versionReservation = normalizeNextDevelopmentVersionReservation(
|
|
180
|
+
await client.readNextDevelopmentVersionReservation({
|
|
181
|
+
reservationSha: reservation.sha,
|
|
182
|
+
candidateSha: sourceSha,
|
|
183
|
+
targetVersion: reservation.targetVersion,
|
|
184
|
+
}),
|
|
185
|
+
{
|
|
186
|
+
reservationSha: reservation.sha,
|
|
187
|
+
candidateSha: sourceSha,
|
|
188
|
+
targetVersion: reservation.targetVersion,
|
|
189
|
+
},
|
|
190
|
+
);
|
|
191
|
+
if (versionReservation.status !== "current") {
|
|
192
|
+
throw new Error(
|
|
193
|
+
`next-development version reservation is ${versionReservation.status} for candidate ${sourceSha}`,
|
|
194
|
+
);
|
|
195
|
+
}
|
|
196
|
+
}
|
|
146
197
|
if (sourceSha !== observedSourceHeadSha)
|
|
147
198
|
comparison = await client.compare(boundarySha, sourceSha);
|
|
148
199
|
} catch (error) {
|
|
@@ -158,6 +209,7 @@ export async function resolvePatrolSourceInputs({
|
|
|
158
209
|
comparison,
|
|
159
210
|
workflowEvidence,
|
|
160
211
|
skippedNewerCommitCount,
|
|
212
|
+
versionReservation,
|
|
161
213
|
qualificationError,
|
|
162
214
|
};
|
|
163
215
|
}
|
|
@@ -82,7 +82,9 @@ export function selectLatestQualifiedSource({
|
|
|
82
82
|
requiredWorkflowPaths,
|
|
83
83
|
now,
|
|
84
84
|
maxAgeSeconds,
|
|
85
|
+
ignoredSourceShas = [],
|
|
85
86
|
}) {
|
|
87
|
+
const ignored = new Set(ignoredSourceShas);
|
|
86
88
|
const latestByPath = new Map(
|
|
87
89
|
requiredWorkflowPaths.map((workflow) => [
|
|
88
90
|
workflow,
|
|
@@ -90,7 +92,11 @@ export function selectLatestQualifiedSource({
|
|
|
90
92
|
]),
|
|
91
93
|
);
|
|
92
94
|
for (let index = 0; index < sourceHistory.length; index += 1) {
|
|
93
|
-
const sourceSha =
|
|
95
|
+
const sourceSha =
|
|
96
|
+
typeof sourceHistory[index] === "string"
|
|
97
|
+
? sourceHistory[index]
|
|
98
|
+
: sourceHistory[index]?.sha;
|
|
99
|
+
if (ignored.has(sourceSha)) continue;
|
|
94
100
|
const rows = requiredWorkflowPaths.map((workflow) =>
|
|
95
101
|
latestByPath.get(workflow).get(sourceSha),
|
|
96
102
|
);
|
|
@@ -115,7 +121,9 @@ export function selectLatestQualifiedSource({
|
|
|
115
121
|
};
|
|
116
122
|
}
|
|
117
123
|
}
|
|
118
|
-
const staleSuccessfulPair = sourceHistory.some((
|
|
124
|
+
const staleSuccessfulPair = sourceHistory.some((entry) => {
|
|
125
|
+
const sourceSha = typeof entry === "string" ? entry : entry?.sha;
|
|
126
|
+
if (ignored.has(sourceSha)) return false;
|
|
119
127
|
const rows = requiredWorkflowPaths.map((workflow) =>
|
|
120
128
|
latestByPath.get(workflow).get(sourceSha),
|
|
121
129
|
);
|