@kungfu-tech/buildchain 3.0.9-alpha.2 → 3.0.9-alpha.4
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/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/buildchain-contract.json +4 -4
- package/dist/site/buildchain-site.json +89 -18
- package/dist/site/capability-registry.json +4 -3
- package/dist/site/kfd-claims.json +65 -5
- package/dist/site/kfd-upstream-aggregate.json +1 -1
- package/dist/site/manual-registry.json +19 -3
- package/dist/site/node-api-registry.json +1017 -37
- package/dist/site/page-registry.json +74 -11
- package/dist/site/public-surface-audit.json +7 -3
- package/dist/site/publication-registry.json +4 -4
- package/dist/site/release-provenance.json +3 -0
- package/dist/site/site-manifest.json +15 -7
- package/dist/site/workflow-registry.json +4 -4
- package/docs/MAP.md +2 -1
- package/docs/aws-us-elastic-runner-burst-plane.md +25 -3
- package/docs/dev-alpha-candidate-patrol.md +8 -0
- package/docs/next-development-transition.md +119 -0
- package/docs/node-api-reference.md +126 -73
- package/docs/versioning.md +1 -1
- package/package.json +8 -3
- package/packages/core/buildchain-agent-manuals.js +1 -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/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-passport-contract.js +1 -1
- package/scripts/aws-macos-jit-controller-core.mjs +109 -4
- package/scripts/aws-macos-jit-controller.mjs +71 -2
- package/scripts/aws-macos-jit-instance-rehydrate.mjs +260 -0
- package/scripts/aws-macos-jit-source-rebind.mjs +71 -14
- package/scripts/check-inventory.mjs +11 -0
- package/scripts/dev-alpha-candidate-patrol.mjs +22 -1
- package/scripts/generate-next-development-guidance.mjs +49 -0
- package/scripts/generate-site-bundle.mjs +2 -0
- package/scripts/init-repo.mjs +119 -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/site-capability-metadata.mjs +3 -0
- package/scripts/stable-candidate-qualification.mjs +7 -7
|
@@ -28,7 +28,29 @@ function priorOwnershipPlan(plan) {
|
|
|
28
28
|
};
|
|
29
29
|
}
|
|
30
30
|
|
|
31
|
-
function
|
|
31
|
+
function assertRunMatchesPolicy(plan, run, jobs, jobCount, artifactCount) {
|
|
32
|
+
if (plan.github.priorRunPolicy === "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 (
|
|
41
|
+
run.status !== "completed" ||
|
|
42
|
+
run.conclusion !== "failure" ||
|
|
43
|
+
jobCount === 0 ||
|
|
44
|
+
artifactCount === 0 ||
|
|
45
|
+
(jobs.jobs || []).some((job) => job.status !== "completed")
|
|
46
|
+
) {
|
|
47
|
+
throw new Error(
|
|
48
|
+
`macOS campaign run ${run.id} is not a terminal failed run with retained evidence`,
|
|
49
|
+
);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function campaignRunReceipts(plan) {
|
|
32
54
|
const branch = sourceRefName(plan.source.ref);
|
|
33
55
|
const response = ghJson(
|
|
34
56
|
[
|
|
@@ -68,19 +90,35 @@ function campaignRunsWithNoWork(plan) {
|
|
|
68
90
|
const artifactCount = Number(
|
|
69
91
|
artifacts.total_count || (artifacts.artifacts || []).length || 0,
|
|
70
92
|
);
|
|
71
|
-
|
|
72
|
-
throw new Error(
|
|
73
|
-
`macOS campaign run ${run.id} already has jobs or artifacts`,
|
|
74
|
-
);
|
|
75
|
-
}
|
|
93
|
+
assertRunMatchesPolicy(plan, run, jobs, jobCount, artifactCount);
|
|
76
94
|
receipts.push({
|
|
77
95
|
runId: String(run.id),
|
|
78
96
|
status: String(run.status || "unknown"),
|
|
79
97
|
conclusion: String(run.conclusion || ""),
|
|
80
98
|
jobCount,
|
|
81
99
|
artifactCount,
|
|
100
|
+
artifacts: (artifacts.artifacts || []).map((artifact) => ({
|
|
101
|
+
id: String(artifact.id),
|
|
102
|
+
name: String(artifact.name || ""),
|
|
103
|
+
sizeInBytes: Number(artifact.size_in_bytes || 0),
|
|
104
|
+
digest: String(artifact.digest || ""),
|
|
105
|
+
expired: artifact.expired === true,
|
|
106
|
+
})),
|
|
82
107
|
});
|
|
83
108
|
}
|
|
109
|
+
if (plan.github.priorRunPolicy === "terminal-failure") {
|
|
110
|
+
const observed = receipts
|
|
111
|
+
.map((receipt) => receipt.runId)
|
|
112
|
+
.sort((left, right) => Number(left) - Number(right));
|
|
113
|
+
if (
|
|
114
|
+
JSON.stringify(observed) !==
|
|
115
|
+
JSON.stringify(plan.github.terminalFailureRunIds)
|
|
116
|
+
) {
|
|
117
|
+
throw new Error(
|
|
118
|
+
"macOS campaign terminal failed run inventory does not match the confirmed run ids",
|
|
119
|
+
);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
84
122
|
return receipts;
|
|
85
123
|
}
|
|
86
124
|
|
|
@@ -286,7 +324,7 @@ function assertZeroCampaignResidue(plan, profile) {
|
|
|
286
324
|
if (matchingRunners.length !== 0) {
|
|
287
325
|
throw new Error("macOS campaign already has a registered JIT runner");
|
|
288
326
|
}
|
|
289
|
-
const
|
|
327
|
+
const evidenceObjects = {};
|
|
290
328
|
for (const sourceSha of [plan.previousSource.sha, plan.source.sha]) {
|
|
291
329
|
const evidence = awsJson(
|
|
292
330
|
plan,
|
|
@@ -299,27 +337,43 @@ function assertZeroCampaignResidue(plan, profile) {
|
|
|
299
337
|
"--prefix",
|
|
300
338
|
`macos/${sourceSha}/`,
|
|
301
339
|
"--max-keys",
|
|
302
|
-
"
|
|
340
|
+
"1000",
|
|
303
341
|
"--output",
|
|
304
342
|
"json",
|
|
305
343
|
],
|
|
306
344
|
`macOS campaign evidence inventory for ${sourceSha}`,
|
|
307
345
|
);
|
|
346
|
+
if (evidence.IsTruncated === true) {
|
|
347
|
+
throw new Error(
|
|
348
|
+
`macOS campaign source ${sourceSha} evidence inventory is incomplete`,
|
|
349
|
+
);
|
|
350
|
+
}
|
|
351
|
+
const objects = (evidence.Contents || []).map((object) => ({
|
|
352
|
+
key: String(object.Key || ""),
|
|
353
|
+
size: Number(object.Size || 0),
|
|
354
|
+
etag: String(object.ETag || ""),
|
|
355
|
+
}));
|
|
308
356
|
const count = Number(
|
|
309
357
|
evidence.KeyCount || (evidence.Contents || []).length || 0,
|
|
310
358
|
);
|
|
311
|
-
|
|
359
|
+
const previousTerminalEvidence =
|
|
360
|
+
sourceSha === plan.previousSource.sha &&
|
|
361
|
+
plan.github.priorRunPolicy === "terminal-failure";
|
|
362
|
+
if (
|
|
363
|
+
(!previousTerminalEvidence && count !== 0) ||
|
|
364
|
+
(previousTerminalEvidence && count === 0)
|
|
365
|
+
) {
|
|
312
366
|
throw new Error(
|
|
313
|
-
`macOS campaign source ${sourceSha}
|
|
367
|
+
`macOS campaign source ${sourceSha} bootstrap evidence does not match the rebind policy`,
|
|
314
368
|
);
|
|
315
369
|
}
|
|
316
|
-
|
|
370
|
+
evidenceObjects[sourceSha] = objects;
|
|
317
371
|
}
|
|
318
372
|
return {
|
|
319
|
-
priorRuns:
|
|
373
|
+
priorRuns: campaignRunReceipts(plan),
|
|
320
374
|
jitParameterCount: parameters.length,
|
|
321
375
|
runnerCount: matchingRunners.length,
|
|
322
|
-
|
|
376
|
+
evidenceObjects,
|
|
323
377
|
};
|
|
324
378
|
}
|
|
325
379
|
|
|
@@ -480,7 +534,10 @@ export function executeMacosJitSourceRebind(plan, { profile = "" } = {}) {
|
|
|
480
534
|
schemaVersion: 1,
|
|
481
535
|
contract: AWS_MACOS_JIT_CONTROLLER_CONTRACT,
|
|
482
536
|
kind: "campaign-source-rebind-result",
|
|
483
|
-
status:
|
|
537
|
+
status:
|
|
538
|
+
plan.github.priorRunPolicy === "terminal-failure"
|
|
539
|
+
? "rebound-after-terminal-failure-zero-allocation"
|
|
540
|
+
: "rebound-zero-allocation",
|
|
484
541
|
repository: plan.repository,
|
|
485
542
|
campaign: plan.campaign,
|
|
486
543
|
previousSource: plan.previousSource,
|
|
@@ -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",
|
|
@@ -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
|
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import fs from "node:fs";
|
|
4
|
+
import path from "node:path";
|
|
5
|
+
import { pathToFileURL } from "node:url";
|
|
6
|
+
|
|
7
|
+
import { nextDevelopmentManual } from "../packages/core/next-development-projection.js";
|
|
8
|
+
|
|
9
|
+
export const NEXT_DEVELOPMENT_MANUAL_PATH =
|
|
10
|
+
"docs/next-development-transition.md";
|
|
11
|
+
|
|
12
|
+
export function generateNextDevelopmentGuidance({
|
|
13
|
+
cwd = process.cwd(),
|
|
14
|
+
check = false,
|
|
15
|
+
} = {}) {
|
|
16
|
+
const target = path.resolve(cwd, NEXT_DEVELOPMENT_MANUAL_PATH);
|
|
17
|
+
const expected = nextDevelopmentManual();
|
|
18
|
+
const current = fs.existsSync(target) ? fs.readFileSync(target, "utf8") : "";
|
|
19
|
+
if (check) {
|
|
20
|
+
if (current !== expected) {
|
|
21
|
+
throw new Error(
|
|
22
|
+
`${NEXT_DEVELOPMENT_MANUAL_PATH} drifted from its contract source`,
|
|
23
|
+
);
|
|
24
|
+
}
|
|
25
|
+
return { ok: true, changed: false, path: NEXT_DEVELOPMENT_MANUAL_PATH };
|
|
26
|
+
}
|
|
27
|
+
fs.mkdirSync(path.dirname(target), { recursive: true });
|
|
28
|
+
if (current !== expected) fs.writeFileSync(target, expected);
|
|
29
|
+
return {
|
|
30
|
+
ok: true,
|
|
31
|
+
changed: current !== expected,
|
|
32
|
+
path: NEXT_DEVELOPMENT_MANUAL_PATH,
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
if (
|
|
37
|
+
process.argv[1] &&
|
|
38
|
+
import.meta.url === pathToFileURL(process.argv[1]).href
|
|
39
|
+
) {
|
|
40
|
+
try {
|
|
41
|
+
const result = generateNextDevelopmentGuidance({
|
|
42
|
+
check: process.argv.includes("--check"),
|
|
43
|
+
});
|
|
44
|
+
process.stdout.write(`${JSON.stringify(result)}\n`);
|
|
45
|
+
} catch (error) {
|
|
46
|
+
process.stderr.write(`next-development guidance: ${error.message}\n`);
|
|
47
|
+
process.exitCode = 1;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
@@ -368,6 +368,7 @@ const manualMetaById = new Map(Object.entries({
|
|
|
368
368
|
"release-activation-transaction": { capabilityGroup: "release-passport-trust", audience: ["release-operator", "agent"], maturity: "preview", order: 125 },
|
|
369
369
|
"release-candidate": { capabilityGroup: "reusable-build", audience: ["release-operator", "consumer"], maturity: "stable", order: 130 },
|
|
370
370
|
"release-train": { capabilityGroup: "governance-versioning", audience: ["release-operator", "consumer", "agent"], maturity: "preview", order: 132 },
|
|
371
|
+
"next-development-transition": { capabilityGroup: "governance-versioning", audience: ["release-operator", "consumer", "agent"], maturity: "preview", order: 133 },
|
|
371
372
|
"stable-candidate-patrol": { capabilityGroup: "governance-versioning", audience: ["release-operator", "consumer"], maturity: "preview", order: 135 },
|
|
372
373
|
"dev-qualification-patrol": { capabilityGroup: "governance-versioning", audience: ["release-operator", "consumer", "agent"], maturity: "preview", order: 136 },
|
|
373
374
|
"dev-alpha-candidate-patrol": { capabilityGroup: "governance-versioning", audience: ["release-operator", "consumer", "agent"], maturity: "preview", order: 137 },
|
|
@@ -733,6 +734,7 @@ function buildSiteBundle() {
|
|
|
733
734
|
"docs/reusable-build-surface.md",
|
|
734
735
|
"docs/release-candidate.md",
|
|
735
736
|
"docs/release-train.md",
|
|
737
|
+
"docs/next-development-transition.md",
|
|
736
738
|
"docs/stable-candidate-patrol.md",
|
|
737
739
|
"docs/dev-qualification-patrol.md",
|
|
738
740
|
"docs/dev-alpha-candidate-patrol.md",
|
package/scripts/init-repo.mjs
CHANGED
|
@@ -3,21 +3,35 @@ import fs from "node:fs";
|
|
|
3
3
|
import path from "node:path";
|
|
4
4
|
import { pathToFileURL } from "node:url";
|
|
5
5
|
import { BUILDCHAIN_CONFIG_PATH } from "../packages/core/buildchain-layout.js";
|
|
6
|
-
import {
|
|
6
|
+
import {
|
|
7
|
+
detectPackageManager,
|
|
8
|
+
assertPackageManager,
|
|
9
|
+
} from "../packages/core/package-manager.js";
|
|
7
10
|
import {
|
|
8
11
|
PUBLICATION_REHEARSAL_WORKFLOW_PATH,
|
|
9
12
|
appendPublicationRehearsalToml,
|
|
10
13
|
mergePublicationRehearsalAgentInstructions,
|
|
11
14
|
publicationRehearsalWorkflow,
|
|
12
15
|
} from "../packages/core/publication-rehearsal-projection.js";
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
16
|
+
import {
|
|
17
|
+
appendNextDevelopmentToml,
|
|
18
|
+
mergeNextDevelopmentAgentInstructions,
|
|
19
|
+
nextDevelopmentWorkflowHeader,
|
|
20
|
+
} from "../packages/core/next-development-projection.js";
|
|
21
|
+
|
|
22
|
+
const BUILDCHAIN_WORKFLOW_REF =
|
|
23
|
+
"kungfu-systems/buildchain/.github/workflows/.build.yml@v3";
|
|
24
|
+
const DEFAULT_PUBLICATION_LATEX_IMAGE =
|
|
25
|
+
"ghcr.io/kungfu-systems/build-images/latex-pdf-builder";
|
|
26
|
+
const DEFAULT_PUBLICATION_LATEX_DIGEST =
|
|
27
|
+
"sha256:c20f3809e96836c1c78e97c76939d12f1de3fed0ea9b7c40c43332ec2ea480f8";
|
|
28
|
+
const DEFAULT_PUBLICATION_LATEX_COMMAND =
|
|
29
|
+
"latexmk -pdf -outdir=_build paper/main.tex";
|
|
18
30
|
|
|
19
31
|
function posixPath(value) {
|
|
20
|
-
return String(value || "")
|
|
32
|
+
return String(value || "")
|
|
33
|
+
.split(path.sep)
|
|
34
|
+
.join("/");
|
|
21
35
|
}
|
|
22
36
|
|
|
23
37
|
function repoName(cwd) {
|
|
@@ -282,34 +296,42 @@ command = "make check"
|
|
|
282
296
|
}
|
|
283
297
|
|
|
284
298
|
function infraContractDesiredJson(cwd) {
|
|
285
|
-
return `${JSON.stringify(
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
299
|
+
return `${JSON.stringify(
|
|
300
|
+
{
|
|
301
|
+
service: repoName(cwd),
|
|
302
|
+
environment: "staging",
|
|
303
|
+
resources: [
|
|
304
|
+
{
|
|
305
|
+
kind: "static-site",
|
|
306
|
+
name: repoName(cwd),
|
|
307
|
+
desiredState: {
|
|
308
|
+
hostname: "staging.example.com",
|
|
309
|
+
accessControl: "managed-network",
|
|
310
|
+
owner: "platform",
|
|
311
|
+
},
|
|
296
312
|
},
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
313
|
+
],
|
|
314
|
+
},
|
|
315
|
+
null,
|
|
316
|
+
2,
|
|
317
|
+
)}\n`;
|
|
300
318
|
}
|
|
301
319
|
|
|
302
320
|
function infraContractOutputsJson(cwd) {
|
|
303
|
-
return `${JSON.stringify(
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
321
|
+
return `${JSON.stringify(
|
|
322
|
+
{
|
|
323
|
+
service: repoName(cwd),
|
|
324
|
+
environment: "staging",
|
|
325
|
+
observedMode: "manual-observed",
|
|
326
|
+
outputs: {
|
|
327
|
+
hostname: "staging.example.com",
|
|
328
|
+
distributionId: "observed-distribution-id",
|
|
329
|
+
bucket: "observed-bucket-name",
|
|
330
|
+
},
|
|
311
331
|
},
|
|
312
|
-
|
|
332
|
+
null,
|
|
333
|
+
2,
|
|
334
|
+
)}\n`;
|
|
313
335
|
}
|
|
314
336
|
|
|
315
337
|
function workflowArtifactPaths(type) {
|
|
@@ -333,7 +355,7 @@ function workflowArtifactPaths(type) {
|
|
|
333
355
|
}
|
|
334
356
|
|
|
335
357
|
function publicationWorkflowYaml() {
|
|
336
|
-
return
|
|
358
|
+
return `${nextDevelopmentWorkflowHeader()}name: Build
|
|
337
359
|
|
|
338
360
|
on:
|
|
339
361
|
workflow_dispatch:
|
|
@@ -365,7 +387,7 @@ jobs:
|
|
|
365
387
|
}
|
|
366
388
|
|
|
367
389
|
function workflowYaml({ type, runnerPreset, artifactName }) {
|
|
368
|
-
return
|
|
390
|
+
return `${nextDevelopmentWorkflowHeader()}name: Build
|
|
369
391
|
|
|
370
392
|
on:
|
|
371
393
|
workflow_dispatch:
|
|
@@ -400,7 +422,9 @@ jobs:
|
|
|
400
422
|
|
|
401
423
|
function writeIfAllowed(filePath, content, { force }) {
|
|
402
424
|
if (fs.existsSync(filePath) && !force) {
|
|
403
|
-
throw new Error(
|
|
425
|
+
throw new Error(
|
|
426
|
+
`${posixPath(filePath)} already exists; pass --force to overwrite`,
|
|
427
|
+
);
|
|
404
428
|
}
|
|
405
429
|
fs.mkdirSync(path.dirname(filePath), { recursive: true });
|
|
406
430
|
fs.writeFileSync(filePath, content);
|
|
@@ -408,7 +432,9 @@ function writeIfAllowed(filePath, content, { force }) {
|
|
|
408
432
|
}
|
|
409
433
|
|
|
410
434
|
function writeManagedAgentEntry(filePath, current) {
|
|
411
|
-
const content =
|
|
435
|
+
const content = mergeNextDevelopmentAgentInstructions(
|
|
436
|
+
mergePublicationRehearsalAgentInstructions(current),
|
|
437
|
+
);
|
|
412
438
|
fs.mkdirSync(path.dirname(filePath), { recursive: true });
|
|
413
439
|
fs.writeFileSync(filePath, content);
|
|
414
440
|
return filePath;
|
|
@@ -424,27 +450,33 @@ export function initBuildchainRepo({
|
|
|
424
450
|
} = {}) {
|
|
425
451
|
const resolvedCwd = path.resolve(cwd);
|
|
426
452
|
const manager = detectOrDefaultPackageManager(resolvedCwd, packageManager);
|
|
427
|
-
const toml =
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
453
|
+
const toml = appendNextDevelopmentToml(
|
|
454
|
+
appendPublicationRehearsalToml(
|
|
455
|
+
(() => {
|
|
456
|
+
if (type === "package") {
|
|
457
|
+
return packageToml(resolvedCwd, manager);
|
|
458
|
+
}
|
|
459
|
+
if (type === "native") {
|
|
460
|
+
return nativeToml(resolvedCwd);
|
|
461
|
+
}
|
|
462
|
+
if (type === "web-surface") {
|
|
463
|
+
return webSurfaceToml(resolvedCwd);
|
|
464
|
+
}
|
|
465
|
+
if (type === "infra-contract") {
|
|
466
|
+
return infraContractToml(resolvedCwd);
|
|
467
|
+
}
|
|
468
|
+
if (type === "publication-artifact") {
|
|
469
|
+
return publicationArtifactToml(resolvedCwd);
|
|
470
|
+
}
|
|
471
|
+
if (type === "anchored-package") {
|
|
472
|
+
return anchoredPackageToml(resolvedCwd, manager);
|
|
473
|
+
}
|
|
474
|
+
throw new Error(
|
|
475
|
+
"init --type must be one of package, native, web-surface, infra-contract, publication-artifact, or anchored-package",
|
|
476
|
+
);
|
|
477
|
+
})(),
|
|
478
|
+
),
|
|
479
|
+
);
|
|
448
480
|
|
|
449
481
|
const agentsPath = path.join(resolvedCwd, "AGENTS.md");
|
|
450
482
|
const currentAgents = fs.existsSync(agentsPath)
|
|
@@ -452,7 +484,9 @@ export function initBuildchainRepo({
|
|
|
452
484
|
: "";
|
|
453
485
|
|
|
454
486
|
const written = [
|
|
455
|
-
writeIfAllowed(path.join(resolvedCwd, BUILDCHAIN_CONFIG_PATH), toml, {
|
|
487
|
+
writeIfAllowed(path.join(resolvedCwd, BUILDCHAIN_CONFIG_PATH), toml, {
|
|
488
|
+
force,
|
|
489
|
+
}),
|
|
456
490
|
writeIfAllowed(
|
|
457
491
|
path.join(resolvedCwd, ".github", "workflows", "build.yml"),
|
|
458
492
|
type === "publication-artifact"
|
|
@@ -472,14 +506,31 @@ export function initBuildchainRepo({
|
|
|
472
506
|
writeManagedAgentEntry(agentsPath, currentAgents),
|
|
473
507
|
];
|
|
474
508
|
|
|
475
|
-
if (
|
|
476
|
-
|
|
509
|
+
if (
|
|
510
|
+
type === "anchored-package" &&
|
|
511
|
+
!fs.existsSync(path.join(resolvedCwd, "release.json"))
|
|
512
|
+
) {
|
|
513
|
+
written.push(
|
|
514
|
+
writeIfAllowed(
|
|
515
|
+
path.join(resolvedCwd, "release.json"),
|
|
516
|
+
'{\n "upstream": "",\n "version": "0.0.0"\n}\n',
|
|
517
|
+
{ force },
|
|
518
|
+
),
|
|
519
|
+
);
|
|
477
520
|
}
|
|
478
521
|
|
|
479
522
|
if (type === "infra-contract") {
|
|
480
523
|
written.push(
|
|
481
|
-
writeIfAllowed(
|
|
482
|
-
|
|
524
|
+
writeIfAllowed(
|
|
525
|
+
path.join(resolvedCwd, "infra", "desired.json"),
|
|
526
|
+
infraContractDesiredJson(resolvedCwd),
|
|
527
|
+
{ force },
|
|
528
|
+
),
|
|
529
|
+
writeIfAllowed(
|
|
530
|
+
path.join(resolvedCwd, "infra", "outputs.json"),
|
|
531
|
+
infraContractOutputsJson(resolvedCwd),
|
|
532
|
+
{ force },
|
|
533
|
+
),
|
|
483
534
|
);
|
|
484
535
|
}
|
|
485
536
|
|
|
@@ -489,7 +540,9 @@ export function initBuildchainRepo({
|
|
|
489
540
|
cwd: resolvedCwd,
|
|
490
541
|
packageManager: manager,
|
|
491
542
|
workflowRef: BUILDCHAIN_WORKFLOW_REF,
|
|
492
|
-
written: written.map((filePath) =>
|
|
543
|
+
written: written.map((filePath) =>
|
|
544
|
+
posixPath(path.relative(resolvedCwd, filePath)),
|
|
545
|
+
),
|
|
493
546
|
};
|
|
494
547
|
}
|
|
495
548
|
|
|
@@ -501,7 +554,11 @@ function readArg(name, fallback = "") {
|
|
|
501
554
|
return process.argv[index + 1] || "";
|
|
502
555
|
}
|
|
503
556
|
|
|
504
|
-
if (
|
|
557
|
+
if (
|
|
558
|
+
!process.env.BUILDCHAIN_EMBEDDED_ENTRYPOINT &&
|
|
559
|
+
process.argv[1] &&
|
|
560
|
+
import.meta.url === pathToFileURL(process.argv[1]).href
|
|
561
|
+
) {
|
|
505
562
|
try {
|
|
506
563
|
const result = initBuildchainRepo({
|
|
507
564
|
cwd: readArg("cwd", process.cwd()),
|