@kungfu-tech/buildchain 3.0.9-alpha.0 → 3.0.9-alpha.10
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 +9 -1
- package/contracts/dev-delivery-authority-v2.schema.json +253 -0
- package/contracts/fixtures/kfd-adopter-release-v1/kfd-4-perspective.json +16 -0
- package/contracts/fixtures/kfd-adopter-release-v1/kfd-4-replay.json +57 -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/contracts/release-cut-v1.schema.json +1 -0
- package/contracts/release-train-transition-v1.schema.json +1 -0
- package/dist/site/agent-index.json +1 -0
- package/dist/site/artifact-schemas.json +2 -0
- package/dist/site/buildchain-contract.json +91 -32
- package/dist/site/buildchain-site.json +353 -45
- package/dist/site/capability-registry.json +7 -6
- package/dist/site/cli-registry.json +41 -2
- package/dist/site/controller-registry.json +8 -4
- package/dist/site/kfd-claims.json +193 -9
- package/dist/site/kfd-upstream-aggregate.json +9 -9
- package/dist/site/manual-registry.json +26 -10
- package/dist/site/node-api-registry.json +8012 -4574
- package/dist/site/page-registry.json +331 -31
- package/dist/site/public-surface-audit.json +353 -8
- package/dist/site/publication-registry.json +4 -4
- package/dist/site/release-passport-check-manifest.json +1 -0
- package/dist/site/release-provenance.json +12 -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 +22 -14
- package/dist/site/workflow-registry.json +15 -7
- 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 +200 -13
- 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 +164 -27
- package/docs/kfd-support.md +7 -2
- package/docs/next-development-transition.md +119 -0
- package/docs/node-api-reference.md +464 -277
- package/docs/release-governance.md +10 -7
- package/docs/release-passport.md +15 -2
- package/docs/release-train.md +46 -4
- package/docs/reusable-build-surface.md +26 -9
- package/docs/runtime-train-validation.md +6 -0
- package/docs/versioning.md +6 -2
- package/package.json +21 -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 +118 -0
- package/packages/core/buildchain-compatibility-proof.js +54 -0
- package/packages/core/buildchain-contract.js +7 -0
- package/packages/core/buildchain-delivery-bootstrap.js +240 -0
- package/packages/core/buildchain-delivery-infrastructure.js +164 -0
- package/packages/core/channel-candidate.js +8 -0
- package/packages/core/channel-promotion-baseline.js +52 -0
- package/packages/core/controller-evidence.js +2 -1
- 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 +141 -48
- 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/release-blocker-priority.js +192 -0
- package/packages/core/release-passport-contract.js +10 -6
- package/packages/core/release-passport.js +29 -12
- package/packages/core/release-train.js +220 -0
- 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-channel-router.mjs +18 -2
- package/scripts/buildchain-cli-help.mjs +9 -2
- package/scripts/buildchain-contract-lock.mjs +11 -1
- package/scripts/check-internal-architecture.mjs +1 -0
- package/scripts/check-inventory.mjs +14 -3
- 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 +47 -5
- package/scripts/dev-pr-delivery-warrant.mjs +19 -14
- package/scripts/generate-buildchain-kfd-witnesses.mjs +88 -94
- package/scripts/generate-channel-build-workflow.mjs +82 -31
- 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/promotion-channel-router.mjs +5 -3
- package/scripts/release-candidate-tail-reseal.mjs +426 -0
- package/scripts/release-train-self-dogfood.mjs +579 -0
- package/scripts/runtime-ref-core.mjs +4 -17
- package/scripts/seal-artifact-signing-requests.mjs +7 -4
- package/scripts/site-capability-metadata.mjs +23 -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
|
@@ -28,7 +28,169 @@ function priorOwnershipPlan(plan) {
|
|
|
28
28
|
};
|
|
29
29
|
}
|
|
30
30
|
|
|
31
|
-
function
|
|
31
|
+
function assertRunMatchesPolicy(policy, run, jobs, jobCount, artifactCount) {
|
|
32
|
+
if (policy === "unused") {
|
|
33
|
+
if (jobCount !== 0 || artifactCount !== 0) {
|
|
34
|
+
throw new Error(
|
|
35
|
+
`macOS campaign run ${run.id} already has jobs or artifacts`,
|
|
36
|
+
);
|
|
37
|
+
}
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
if (policy === "preflight-failure") {
|
|
41
|
+
const jobList = jobs.jobs || [];
|
|
42
|
+
const failedJobs = jobList.filter((job) => job.conclusion === "failure");
|
|
43
|
+
const nonFailedJobs = jobList.filter((job) => job.conclusion !== "failure");
|
|
44
|
+
const hasJitLabel = jobList.some((job) =>
|
|
45
|
+
(job.labels || []).some((label) =>
|
|
46
|
+
String(label.name || label).startsWith(MACOS_JIT_RUNNER_LABEL_PREFIX),
|
|
47
|
+
),
|
|
48
|
+
);
|
|
49
|
+
if (
|
|
50
|
+
run.status !== "completed" ||
|
|
51
|
+
run.conclusion !== "failure" ||
|
|
52
|
+
jobCount === 0 ||
|
|
53
|
+
artifactCount === 0 ||
|
|
54
|
+
jobList.some((job) => job.status !== "completed") ||
|
|
55
|
+
failedJobs.length !== 1 ||
|
|
56
|
+
!String(failedJobs[0].name || "").endsWith(" / Trust gate") ||
|
|
57
|
+
nonFailedJobs.some((job) => job.conclusion !== "skipped") ||
|
|
58
|
+
hasJitLabel
|
|
59
|
+
) {
|
|
60
|
+
throw new Error(
|
|
61
|
+
`macOS campaign run ${run.id} is not an exact preflight Trust gate failure`,
|
|
62
|
+
);
|
|
63
|
+
}
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
if (
|
|
67
|
+
run.status !== "completed" ||
|
|
68
|
+
run.conclusion !== "failure" ||
|
|
69
|
+
jobCount === 0 ||
|
|
70
|
+
artifactCount === 0 ||
|
|
71
|
+
(jobs.jobs || []).some((job) => job.status !== "completed")
|
|
72
|
+
) {
|
|
73
|
+
throw new Error(
|
|
74
|
+
`macOS campaign run ${run.id} is not a terminal failed run with retained evidence`,
|
|
75
|
+
);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
function assertExactStartupFailure(run, jobCount, artifactCount) {
|
|
80
|
+
if (
|
|
81
|
+
run.status !== "completed" ||
|
|
82
|
+
run.conclusion !== "startup_failure" ||
|
|
83
|
+
jobCount !== 0 ||
|
|
84
|
+
artifactCount !== 0
|
|
85
|
+
) {
|
|
86
|
+
throw new Error(
|
|
87
|
+
`macOS campaign run ${run.id} is not an exact startup failure`,
|
|
88
|
+
);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
function assertExactSuccessfulRun(run, jobs, jobCount, artifactCount) {
|
|
93
|
+
if (
|
|
94
|
+
run.status !== "completed" ||
|
|
95
|
+
run.conclusion !== "success" ||
|
|
96
|
+
jobCount === 0 ||
|
|
97
|
+
artifactCount === 0 ||
|
|
98
|
+
(jobs.jobs || []).some((job) => job.status !== "completed")
|
|
99
|
+
) {
|
|
100
|
+
throw new Error(
|
|
101
|
+
`macOS campaign run ${run.id} is not a terminal successful run with retained evidence`,
|
|
102
|
+
);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
function classifyCampaignRun(plan, run) {
|
|
107
|
+
const startupFailure = plan.github.startupFailureRuns.find(
|
|
108
|
+
({ runId }) => runId === String(run.id),
|
|
109
|
+
);
|
|
110
|
+
const historicalTerminalFailure =
|
|
111
|
+
plan.github.historicalTerminalFailureRuns.find(
|
|
112
|
+
({ runId }) => runId === String(run.id),
|
|
113
|
+
);
|
|
114
|
+
const historicalPreflightFailure =
|
|
115
|
+
plan.github.historicalPreflightFailureRuns.find(
|
|
116
|
+
({ runId }) => runId === String(run.id),
|
|
117
|
+
);
|
|
118
|
+
const preflightFailure = plan.github.preflightFailureRunIds.includes(
|
|
119
|
+
String(run.id),
|
|
120
|
+
);
|
|
121
|
+
const successfulRun = plan.github.successfulRunIds.includes(String(run.id));
|
|
122
|
+
return {
|
|
123
|
+
startupFailure,
|
|
124
|
+
historicalTerminalFailure,
|
|
125
|
+
historicalPreflightFailure,
|
|
126
|
+
successfulRun,
|
|
127
|
+
expectedSourceSha:
|
|
128
|
+
startupFailure?.sourceSha ||
|
|
129
|
+
historicalTerminalFailure?.sourceSha ||
|
|
130
|
+
historicalPreflightFailure?.sourceSha ||
|
|
131
|
+
plan.previousSource.sha,
|
|
132
|
+
classification: startupFailure
|
|
133
|
+
? "startup-failure"
|
|
134
|
+
: historicalTerminalFailure
|
|
135
|
+
? "historical-terminal-failure"
|
|
136
|
+
: historicalPreflightFailure
|
|
137
|
+
? "historical-preflight-failure"
|
|
138
|
+
: successfulRun
|
|
139
|
+
? "successful-run"
|
|
140
|
+
: preflightFailure
|
|
141
|
+
? "preflight-failure"
|
|
142
|
+
: plan.github.priorRunPolicy,
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
function exactReceiptInventory(receipts, classification, withSource = false) {
|
|
147
|
+
return receipts
|
|
148
|
+
.filter((receipt) => receipt.classification === classification)
|
|
149
|
+
.map((receipt) =>
|
|
150
|
+
withSource
|
|
151
|
+
? { runId: receipt.runId, sourceSha: receipt.sourceSha }
|
|
152
|
+
: receipt.runId,
|
|
153
|
+
)
|
|
154
|
+
.sort(
|
|
155
|
+
(left, right) =>
|
|
156
|
+
Number(withSource ? left.runId : left) -
|
|
157
|
+
Number(withSource ? right.runId : right),
|
|
158
|
+
);
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
function assertExactReceiptInventories(plan, receipts) {
|
|
162
|
+
if (plan.github.priorRunPolicy === "unused") return;
|
|
163
|
+
const inventories = [
|
|
164
|
+
["terminal-failure", plan.github.terminalFailureRunIds, false],
|
|
165
|
+
["preflight-failure", plan.github.preflightFailureRunIds, false],
|
|
166
|
+
["successful-run", plan.github.successfulRunIds, false],
|
|
167
|
+
["startup-failure", plan.github.startupFailureRuns, true],
|
|
168
|
+
[
|
|
169
|
+
"historical-terminal-failure",
|
|
170
|
+
plan.github.historicalTerminalFailureRuns,
|
|
171
|
+
true,
|
|
172
|
+
],
|
|
173
|
+
[
|
|
174
|
+
"historical-preflight-failure",
|
|
175
|
+
plan.github.historicalPreflightFailureRuns,
|
|
176
|
+
true,
|
|
177
|
+
],
|
|
178
|
+
];
|
|
179
|
+
for (const [classification, expected, withSource] of inventories) {
|
|
180
|
+
const observed = exactReceiptInventory(
|
|
181
|
+
receipts,
|
|
182
|
+
classification,
|
|
183
|
+
withSource,
|
|
184
|
+
);
|
|
185
|
+
if (JSON.stringify(observed) !== JSON.stringify(expected)) {
|
|
186
|
+
throw new Error(
|
|
187
|
+
`macOS campaign ${classification} inventory does not match the confirmed runs`,
|
|
188
|
+
);
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
function campaignRunReceipts(plan) {
|
|
32
194
|
const branch = sourceRefName(plan.source.ref);
|
|
33
195
|
const response = ghJson(
|
|
34
196
|
[
|
|
@@ -46,7 +208,8 @@ function campaignRunsWithNoWork(plan) {
|
|
|
46
208
|
}
|
|
47
209
|
const receipts = [];
|
|
48
210
|
for (const run of matching) {
|
|
49
|
-
|
|
211
|
+
const classification = classifyCampaignRun(plan, run);
|
|
212
|
+
if (run.head_sha !== classification.expectedSourceSha) {
|
|
50
213
|
throw new Error(
|
|
51
214
|
`macOS campaign run ${run.id} is bound to an unexpected source`,
|
|
52
215
|
);
|
|
@@ -68,19 +231,41 @@ function campaignRunsWithNoWork(plan) {
|
|
|
68
231
|
const artifactCount = Number(
|
|
69
232
|
artifacts.total_count || (artifacts.artifacts || []).length || 0,
|
|
70
233
|
);
|
|
71
|
-
if (
|
|
72
|
-
|
|
73
|
-
|
|
234
|
+
if (classification.startupFailure) {
|
|
235
|
+
assertExactStartupFailure(run, jobCount, artifactCount);
|
|
236
|
+
} else if (classification.successfulRun) {
|
|
237
|
+
assertExactSuccessfulRun(run, jobs, jobCount, artifactCount);
|
|
238
|
+
} else {
|
|
239
|
+
assertRunMatchesPolicy(
|
|
240
|
+
classification.historicalTerminalFailure
|
|
241
|
+
? "terminal-failure"
|
|
242
|
+
: classification.historicalPreflightFailure
|
|
243
|
+
? "preflight-failure"
|
|
244
|
+
: plan.github.priorRunPolicy,
|
|
245
|
+
run,
|
|
246
|
+
jobs,
|
|
247
|
+
jobCount,
|
|
248
|
+
artifactCount,
|
|
74
249
|
);
|
|
75
250
|
}
|
|
76
251
|
receipts.push({
|
|
77
252
|
runId: String(run.id),
|
|
253
|
+
sourceSha: String(run.head_sha || ""),
|
|
254
|
+
classification: classification.classification,
|
|
78
255
|
status: String(run.status || "unknown"),
|
|
79
256
|
conclusion: String(run.conclusion || ""),
|
|
80
257
|
jobCount,
|
|
81
258
|
artifactCount,
|
|
259
|
+
artifacts: (artifacts.artifacts || []).map((artifact) => ({
|
|
260
|
+
id: String(artifact.id),
|
|
261
|
+
name: String(artifact.name || ""),
|
|
262
|
+
sizeInBytes: Number(artifact.size_in_bytes || 0),
|
|
263
|
+
digest: String(artifact.digest || ""),
|
|
264
|
+
expired: artifact.expired === true,
|
|
265
|
+
})),
|
|
82
266
|
});
|
|
83
267
|
}
|
|
268
|
+
assertExactReceiptInventories(plan, receipts);
|
|
84
269
|
return receipts;
|
|
85
270
|
}
|
|
86
271
|
|
|
@@ -286,8 +471,22 @@ function assertZeroCampaignResidue(plan, profile) {
|
|
|
286
471
|
if (matchingRunners.length !== 0) {
|
|
287
472
|
throw new Error("macOS campaign already has a registered JIT runner");
|
|
288
473
|
}
|
|
289
|
-
const
|
|
290
|
-
|
|
474
|
+
const evidenceObjects = {};
|
|
475
|
+
const historicalTerminalSources =
|
|
476
|
+
plan.github.historicalTerminalFailureRuns.map(({ sourceSha }) => sourceSha);
|
|
477
|
+
const historicalPreflightSources =
|
|
478
|
+
plan.github.historicalPreflightFailureRuns.map(
|
|
479
|
+
({ sourceSha }) => sourceSha,
|
|
480
|
+
);
|
|
481
|
+
const evidenceSources = [
|
|
482
|
+
...new Set([
|
|
483
|
+
plan.previousSource.sha,
|
|
484
|
+
...historicalTerminalSources,
|
|
485
|
+
...historicalPreflightSources,
|
|
486
|
+
plan.source.sha,
|
|
487
|
+
]),
|
|
488
|
+
];
|
|
489
|
+
for (const sourceSha of evidenceSources) {
|
|
291
490
|
const evidence = awsJson(
|
|
292
491
|
plan,
|
|
293
492
|
profile,
|
|
@@ -299,27 +498,44 @@ function assertZeroCampaignResidue(plan, profile) {
|
|
|
299
498
|
"--prefix",
|
|
300
499
|
`macos/${sourceSha}/`,
|
|
301
500
|
"--max-keys",
|
|
302
|
-
"
|
|
501
|
+
"1000",
|
|
303
502
|
"--output",
|
|
304
503
|
"json",
|
|
305
504
|
],
|
|
306
505
|
`macOS campaign evidence inventory for ${sourceSha}`,
|
|
307
506
|
);
|
|
507
|
+
if (evidence.IsTruncated === true) {
|
|
508
|
+
throw new Error(
|
|
509
|
+
`macOS campaign source ${sourceSha} evidence inventory is incomplete`,
|
|
510
|
+
);
|
|
511
|
+
}
|
|
512
|
+
const objects = (evidence.Contents || []).map((object) => ({
|
|
513
|
+
key: String(object.Key || ""),
|
|
514
|
+
size: Number(object.Size || 0),
|
|
515
|
+
etag: String(object.ETag || ""),
|
|
516
|
+
}));
|
|
308
517
|
const count = Number(
|
|
309
518
|
evidence.KeyCount || (evidence.Contents || []).length || 0,
|
|
310
519
|
);
|
|
311
|
-
|
|
520
|
+
const terminalEvidenceSource =
|
|
521
|
+
(sourceSha === plan.previousSource.sha &&
|
|
522
|
+
plan.github.priorRunPolicy === "terminal-failure") ||
|
|
523
|
+
historicalTerminalSources.includes(sourceSha);
|
|
524
|
+
if (
|
|
525
|
+
(!terminalEvidenceSource && count !== 0) ||
|
|
526
|
+
(terminalEvidenceSource && count === 0)
|
|
527
|
+
) {
|
|
312
528
|
throw new Error(
|
|
313
|
-
`macOS campaign source ${sourceSha}
|
|
529
|
+
`macOS campaign source ${sourceSha} bootstrap evidence does not match the rebind policy`,
|
|
314
530
|
);
|
|
315
531
|
}
|
|
316
|
-
|
|
532
|
+
evidenceObjects[sourceSha] = objects;
|
|
317
533
|
}
|
|
318
534
|
return {
|
|
319
|
-
priorRuns:
|
|
535
|
+
priorRuns: campaignRunReceipts(plan),
|
|
320
536
|
jitParameterCount: parameters.length,
|
|
321
537
|
runnerCount: matchingRunners.length,
|
|
322
|
-
|
|
538
|
+
evidenceObjects,
|
|
323
539
|
};
|
|
324
540
|
}
|
|
325
541
|
|
|
@@ -480,7 +696,12 @@ export function executeMacosJitSourceRebind(plan, { profile = "" } = {}) {
|
|
|
480
696
|
schemaVersion: 1,
|
|
481
697
|
contract: AWS_MACOS_JIT_CONTROLLER_CONTRACT,
|
|
482
698
|
kind: "campaign-source-rebind-result",
|
|
483
|
-
status:
|
|
699
|
+
status:
|
|
700
|
+
plan.github.priorRunPolicy === "terminal-failure"
|
|
701
|
+
? "rebound-after-terminal-failure-zero-allocation"
|
|
702
|
+
: plan.github.priorRunPolicy === "preflight-failure"
|
|
703
|
+
? "rebound-after-preflight-failure-zero-allocation"
|
|
704
|
+
: "rebound-zero-allocation",
|
|
484
705
|
repository: plan.repository,
|
|
485
706
|
campaign: plan.campaign,
|
|
486
707
|
previousSource: plan.previousSource,
|
|
@@ -25,6 +25,17 @@ function writeJson(file, value) {
|
|
|
25
25
|
return resolved;
|
|
26
26
|
}
|
|
27
27
|
|
|
28
|
+
export function writeMacosJitQualificationEnvironment(
|
|
29
|
+
githubEnv = process.env.GITHUB_ENV,
|
|
30
|
+
) {
|
|
31
|
+
if (!githubEnv) return false;
|
|
32
|
+
fs.appendFileSync(
|
|
33
|
+
path.resolve(githubEnv),
|
|
34
|
+
"BUILDCHAIN_SIGNING_REQUESTS_ENABLED=false\n",
|
|
35
|
+
);
|
|
36
|
+
return true;
|
|
37
|
+
}
|
|
38
|
+
|
|
28
39
|
export function main() {
|
|
29
40
|
const mode = process.argv[2] || "plan";
|
|
30
41
|
if (mode === "plan") {
|
|
@@ -64,6 +75,7 @@ export function main() {
|
|
|
64
75
|
".buildchain/aws-macos-jit.json",
|
|
65
76
|
result,
|
|
66
77
|
);
|
|
78
|
+
writeMacosJitQualificationEnvironment();
|
|
67
79
|
process.stdout.write(`${output}\n`);
|
|
68
80
|
return result;
|
|
69
81
|
}
|
|
@@ -105,8 +105,24 @@ export function resolveBuildchainChannel({
|
|
|
105
105
|
if (channel !== "auto" && explicitRef.kind !== "override" && channel !== explicitRef.kind) {
|
|
106
106
|
throw new Error(`buildchain-channel=${channel} conflicts with buildchain-ref=${explicitRef.ref}`);
|
|
107
107
|
}
|
|
108
|
-
if (
|
|
109
|
-
|
|
108
|
+
if (explicitRef.kind === "override") {
|
|
109
|
+
const lane = resolveBuildchainChannel({
|
|
110
|
+
requestedChannel: channel,
|
|
111
|
+
requestedRef: "",
|
|
112
|
+
publishChannel,
|
|
113
|
+
eventName,
|
|
114
|
+
gitRef,
|
|
115
|
+
releasePrerelease,
|
|
116
|
+
routerRef: `v${major}`,
|
|
117
|
+
packageVersion,
|
|
118
|
+
});
|
|
119
|
+
return {
|
|
120
|
+
...lane,
|
|
121
|
+
major,
|
|
122
|
+
buildchainRef: explicitRef.ref,
|
|
123
|
+
selectionSource: "explicit-buildchain-ref+channel-evidence",
|
|
124
|
+
reason: `trusted runtime override ${explicitRef.ref} bound to ${lane.channel}`,
|
|
125
|
+
};
|
|
110
126
|
}
|
|
111
127
|
return {
|
|
112
128
|
channel: explicitRef.kind,
|
|
@@ -129,11 +129,18 @@ export const BUILDCHAIN_USAGE = `Usage:
|
|
|
129
129
|
[--from-config | --workflow <required-workflow.yml>...] [--cwd <dir>]
|
|
130
130
|
[--check-response-timeout-minutes <n>]
|
|
131
131
|
[--max-entries-to-build <n>] [--apply]
|
|
132
|
-
buildchain dev warrant <submit|select|heartbeat|recover|close|cancel-queued|observe>
|
|
132
|
+
buildchain dev warrant <submit|select|heartbeat|qualify|recover|close|cancel-queued|observe>
|
|
133
133
|
--repository <owner/repo> --branch <dev/vN/vN.M>
|
|
134
134
|
[--execute] [--output <file>] [--json]
|
|
135
|
-
buildchain dev
|
|
135
|
+
buildchain dev authority <migrate|submit|lease-qualification|heartbeat-qualification|complete-qualification|lease-landing|heartbeat-landing|recover|admit-merge-group|settle|observe>
|
|
136
|
+
--repository <owner/repo> --branch <dev/vN/vN.M>
|
|
137
|
+
[--execute] [--output <file>] [--json]
|
|
138
|
+
buildchain dev proof <source|verify-source|classify|native|verify-native|classify-native|verify-native-reuse|replay|integration|verify-integration>
|
|
136
139
|
[--output <file>] [--json]
|
|
140
|
+
buildchain dev two-phase --repository <owner/repo> --branch <dev/vN/vN.M>
|
|
141
|
+
--pull-request <n> --expected-head <sha>
|
|
142
|
+
--warrant-result <file> [--native-proof <file>]
|
|
143
|
+
[--native-command <command>]
|
|
137
144
|
buildchain log <info|warn|error> --event <name> [--phase <phase>]
|
|
138
145
|
[--component <name>] [--source <name>] [--attribute key=value]...
|
|
139
146
|
[--path <jsonl>] [--json]
|
|
@@ -69,6 +69,10 @@ export function checkBuildchainContractLock({
|
|
|
69
69
|
runtimeSha = env("BUILDCHAIN_RUNTIME_SHA"),
|
|
70
70
|
runtimeClass = env("BUILDCHAIN_RUNTIME_CLASS"),
|
|
71
71
|
compatibilityPolicy = env("BUILDCHAIN_CONTRACT_COMPATIBILITY_POLICY"),
|
|
72
|
+
workflowShellRef = env("BUILDCHAIN_WORKFLOW_SHELL_REF"),
|
|
73
|
+
expectedChannel = env("BUILDCHAIN_EXPECTED_CHANNEL"),
|
|
74
|
+
expectedMajor = env("BUILDCHAIN_EXPECTED_MAJOR"),
|
|
75
|
+
allowOpaqueRuntime = boolEnv("BUILDCHAIN_ALLOW_OPAQUE_RUNTIME"),
|
|
72
76
|
issueMode = env("BUILDCHAIN_CONTRACT_DRIFT_ISSUE_MODE", "compatible-and-breaking"),
|
|
73
77
|
issueBodyPath = env("BUILDCHAIN_CONTRACT_DRIFT_ISSUE_BODY", ".buildchain/contract-drift/issue-body.md"),
|
|
74
78
|
repository = env("GITHUB_REPOSITORY"),
|
|
@@ -84,6 +88,10 @@ export function checkBuildchainContractLock({
|
|
|
84
88
|
runtimeSha,
|
|
85
89
|
runtimeClass,
|
|
86
90
|
compatibilityPolicy,
|
|
91
|
+
workflowShellRef,
|
|
92
|
+
expectedChannel,
|
|
93
|
+
expectedMajor,
|
|
94
|
+
allowOpaqueRuntime,
|
|
87
95
|
});
|
|
88
96
|
const shouldIssue = issueModeAllows(issueMode, evaluation);
|
|
89
97
|
if (shouldIssue) {
|
|
@@ -104,6 +112,8 @@ export function checkBuildchainContractLock({
|
|
|
104
112
|
`- Compatible: \`${evaluation.compatible ? "true" : "false"}\``,
|
|
105
113
|
`- Runtime ref: \`${runtimeRef || "(unknown)"}\``,
|
|
106
114
|
`- Runtime SHA: \`${runtimeSha || "(unknown)"}\``,
|
|
115
|
+
`- Workflow shell ref: \`${workflowShellRef || "(unknown)"}\``,
|
|
116
|
+
evaluation.channelBinding ? `- Bound channel: \`${evaluation.channelBinding.channel || "(unknown)"}\`` : "",
|
|
107
117
|
`- Contract digest: \`${current.contractDigest}\``,
|
|
108
118
|
`- Compatibility digest: \`${current.compatibilityDigest}\``,
|
|
109
119
|
`- Compatibility proof registry: \`${current.compatibilityProofRegistryRoot || "(legacy)"}\``,
|
|
@@ -128,7 +138,7 @@ export function checkBuildchainContractLock({
|
|
|
128
138
|
"current-buildchain-sha": runtimeSha || "",
|
|
129
139
|
});
|
|
130
140
|
if (!evaluation.ok) {
|
|
131
|
-
throw new Error(`Buildchain contract
|
|
141
|
+
throw new Error(`Buildchain contract lock rejected: ${(evaluation.reasons || []).join("; ")}`);
|
|
132
142
|
}
|
|
133
143
|
return { evaluation, current, shouldIssue };
|
|
134
144
|
}
|
|
@@ -131,6 +131,7 @@ function repositoryJavaScriptFiles(root) {
|
|
|
131
131
|
.filter((file) => [".js", ".mjs", ".cjs"].includes(path.extname(file)))
|
|
132
132
|
.filter((file) => !file.startsWith("tests/"))
|
|
133
133
|
.filter((file) => !/(?:^|\/)tests?\//u.test(file))
|
|
134
|
+
.filter((file) => !file.startsWith(".buildchain/"))
|
|
134
135
|
.filter((file) => !/^actions\/[^/]+\/dist\//u.test(file))
|
|
135
136
|
.sort();
|
|
136
137
|
}
|
|
@@ -53,6 +53,10 @@ const requiredPaths = [
|
|
|
53
53
|
"packages/core/homebrew.js",
|
|
54
54
|
"packages/core/artifact-verification-envelope.js",
|
|
55
55
|
"packages/core/anchored-version-material.js",
|
|
56
|
+
"packages/core/next-development-transition.js",
|
|
57
|
+
"packages/core/next-development-controller.js",
|
|
58
|
+
"packages/core/next-development-candidate-reservation.js",
|
|
59
|
+
"packages/core/next-development-projection.js",
|
|
56
60
|
"packages/core/build-facts.js",
|
|
57
61
|
"packages/core/publication-package.js",
|
|
58
62
|
"packages/core/publication-reproducibility.js",
|
|
@@ -75,6 +79,8 @@ const requiredPaths = [
|
|
|
75
79
|
"docs/auditable-demo.md",
|
|
76
80
|
"contracts/auditable-demo-scenario-v1.schema.json",
|
|
77
81
|
"contracts/release-candidate-recovery-v1.schema.json",
|
|
82
|
+
"contracts/next-development-request-v1.schema.json",
|
|
83
|
+
"contracts/next-development-transition-v1.schema.json",
|
|
78
84
|
"contracts/auditable-demo-media-profiles-v1.json",
|
|
79
85
|
"contracts/evidence/auditable-demo-web-delivery-v1.json",
|
|
80
86
|
"contracts/evidence/auditable-demo-responsive-web-delivery-v1.json",
|
|
@@ -86,10 +92,15 @@ const requiredPaths = [
|
|
|
86
92
|
"contracts/fixtures/auditable-demo-responsive-web-delivery-v1/public-projection.json",
|
|
87
93
|
"contracts/fixtures/auditable-demo-responsive-web-delivery-v1/scene.json",
|
|
88
94
|
"docs/release-propagation.md",
|
|
95
|
+
"docs/next-development-transition.md",
|
|
89
96
|
"docs/site-bundle-contract.md",
|
|
90
97
|
"docs/toolkit-observability.md",
|
|
91
98
|
"docs/versioning.md",
|
|
92
99
|
"scripts/release-line-dry-run.mjs",
|
|
100
|
+
"scripts/next-development-transition.mjs",
|
|
101
|
+
"scripts/next-development-self-dogfood.mjs",
|
|
102
|
+
"scripts/next-development-self-dogfood-harness.mjs",
|
|
103
|
+
"scripts/generate-next-development-guidance.mjs",
|
|
93
104
|
"scripts/reconcile-release-governance.mjs",
|
|
94
105
|
"scripts/buildchain-channel-router.mjs",
|
|
95
106
|
"scripts/generate-channel-build-workflow.mjs",
|
|
@@ -215,7 +226,7 @@ const selfDogfoodAlphaEvaluation = evaluateBuildchainContractLock({
|
|
|
215
226
|
}),
|
|
216
227
|
runtimeRef: `v${selfDogfoodMajor}-alpha`,
|
|
217
228
|
runtimeSha: "current-development-contract",
|
|
218
|
-
runtimeClass: "alpha",
|
|
229
|
+
runtimeClass: "alpha", workflowShellRef: `v${selfDogfoodMajor}-alpha`,
|
|
219
230
|
});
|
|
220
231
|
if (
|
|
221
232
|
!canAdmitSelfDogfoodLockEvaluation({
|
|
@@ -304,7 +315,7 @@ if (!promotionOverrideAuthorization.includes("promotion runtime override is only
|
|
|
304
315
|
}
|
|
305
316
|
for (const requiredSnippet of [
|
|
306
317
|
"buildchain-channel:",
|
|
307
|
-
"uses:
|
|
318
|
+
"uses: kungfu-systems/buildchain/.github/workflows/.build.yml@v3-alpha", "uses: kungfu-systems/buildchain/.github/workflows/.build.yml@v3\n",
|
|
308
319
|
"needs.resolve-channel.outputs.buildchain-ref",
|
|
309
320
|
"needs.resolve-channel.outputs.contract-lock-path",
|
|
310
321
|
]) {
|
|
@@ -992,7 +1003,7 @@ for (const forbiddenSnippet of [
|
|
|
992
1003
|
for (const requiredSnippet of [
|
|
993
1004
|
"id-token: write",
|
|
994
1005
|
"actions: write",
|
|
995
|
-
"uses: kungfu-systems/buildchain/.github/workflows/release-candidate-promote.yml@
|
|
1006
|
+
"uses: kungfu-systems/buildchain/.github/workflows/release-candidate-promote.yml@cc6c32845ab5779009aeb48cc34efe65e229fe30\n",
|
|
996
1007
|
"github.event.workflow_run.event == 'push'",
|
|
997
1008
|
"!startsWith(github.event.workflow_run.display_title, 'chore(release): prepare v')",
|
|
998
1009
|
"!startsWith(github.event.workflow_run.display_title, 'chore(release): release v')",
|
|
@@ -20,6 +20,7 @@ import {
|
|
|
20
20
|
candidateFromDecision,
|
|
21
21
|
selectLatestQualifiedSource,
|
|
22
22
|
} from "../packages/core/dev-alpha-candidate-selection.js";
|
|
23
|
+
import { readGitHubNextDevelopmentVersionReservation } from "../packages/core/next-development-candidate-reservation.js";
|
|
23
24
|
|
|
24
25
|
export { reconcileActiveReleaseTrain, selectLatestQualifiedSource };
|
|
25
26
|
|
|
@@ -617,6 +618,7 @@ export async function runDevAlphaCandidatePatrol(
|
|
|
617
618
|
comparison,
|
|
618
619
|
workflowEvidence,
|
|
619
620
|
skippedNewerCommitCount,
|
|
621
|
+
versionReservation,
|
|
620
622
|
qualificationError,
|
|
621
623
|
} = await resolvePatrolSourceInputs({
|
|
622
624
|
client,
|
|
@@ -646,6 +648,7 @@ export async function runDevAlphaCandidatePatrol(
|
|
|
646
648
|
observedSourceHeadSha,
|
|
647
649
|
skippedNewerCommitCount,
|
|
648
650
|
...(targetBaseline ? { targetBaseline } : {}),
|
|
651
|
+
...(versionReservation ? { versionReservation } : {}),
|
|
649
652
|
},
|
|
650
653
|
workflowEvidence,
|
|
651
654
|
requiredWorkflowPaths,
|
|
@@ -992,6 +995,20 @@ export function createGitHubChannelCandidateClient({
|
|
|
992
995
|
targetBranch,
|
|
993
996
|
parseCandidate: managedCandidateFromPullRequest,
|
|
994
997
|
}),
|
|
998
|
+
async readNextDevelopmentVersionReservation({
|
|
999
|
+
reservationSha,
|
|
1000
|
+
candidateSha,
|
|
1001
|
+
targetVersion,
|
|
1002
|
+
}) {
|
|
1003
|
+
return readGitHubNextDevelopmentVersionReservation({
|
|
1004
|
+
api,
|
|
1005
|
+
owner,
|
|
1006
|
+
repo,
|
|
1007
|
+
reservationSha,
|
|
1008
|
+
candidateSha,
|
|
1009
|
+
targetVersion,
|
|
1010
|
+
});
|
|
1011
|
+
},
|
|
995
1012
|
async listCompletedWorkflowRuns(workflowPathValue, sourceBranch) {
|
|
996
1013
|
const runs = [];
|
|
997
1014
|
for (let page = 1; page <= 10; page += 1) {
|
|
@@ -1015,7 +1032,11 @@ export function createGitHubChannelCandidateClient({
|
|
|
1015
1032
|
for (const commit of rows) {
|
|
1016
1033
|
const commitSha = text(commit.sha);
|
|
1017
1034
|
if (commitSha === targetSha) return commits;
|
|
1018
|
-
commits.push(
|
|
1035
|
+
commits.push({
|
|
1036
|
+
sha: commitSha,
|
|
1037
|
+
message: text(commit.commit?.message),
|
|
1038
|
+
parents: (commit.parents || []).map((parent) => text(parent.sha)),
|
|
1039
|
+
});
|
|
1019
1040
|
}
|
|
1020
1041
|
if (rows.length < 100) return commits;
|
|
1021
1042
|
}
|