@kungfu-tech/buildchain 4.1.2 → 4.1.3-alpha.1
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/CONTRIBUTING.md +7 -4
- package/architecture/action-taxonomy.json +4 -0
- package/architecture/agent-change-map.md +44 -0
- package/architecture/internal-capabilities.json +56 -0
- package/architecture/maintainability-debt.json +2 -1
- package/architecture/maintainability-policy.json +4 -4
- package/architecture/release-topology.json +14 -1
- package/architecture/universal-workflow-bootstrap.json +13 -2
- package/architecture/universal-workflow-capability-policy.json +14 -8
- package/contracts/promotion-invocation-v1.schema.json +6 -3
- package/contracts/promotion-request-v1.schema.json +6 -3
- package/contracts/release-discussion-v1.schema.json +143 -0
- package/dist/readers/release-discussion.cjs +207 -0
- package/dist/site/buildchain-contract.json +15 -11
- package/dist/site/buildchain-site.json +64 -8
- package/dist/site/capability-registry.json +3 -3
- package/dist/site/kfd-claims.json +95 -9
- package/dist/site/kfd-upstream-aggregate.json +1 -1
- package/dist/site/manual-registry.json +1 -1
- package/dist/site/node-api-registry.json +83 -1
- package/dist/site/page-registry.json +59 -3
- package/dist/site/public-surface-audit.json +53 -7
- package/dist/site/publication-registry.json +4 -4
- package/dist/site/release-provenance.json +2 -1
- package/dist/site/site-manifest.json +5 -5
- package/dist/site/workflow-registry.json +79 -7
- package/docs/node-api-reference.md +9 -0
- package/docs/release-discussions.md +193 -0
- package/package.json +10 -6
- package/packages/core/providers/github/discussions/materials.js +157 -0
- package/packages/core/providers/github/discussions/transport.js +126 -0
- package/packages/core/publication/binary/action.js +21 -7
- package/packages/core/release/discussion/actions.js +65 -0
- package/packages/core/release/discussion/binary.js +103 -0
- package/packages/core/release/discussion/checkpoints.js +282 -0
- package/packages/core/release/discussion/envelope.js +142 -0
- package/packages/core/release/discussion/evidence.js +51 -0
- package/packages/core/release/discussion/presentation.js +92 -0
- package/packages/core/release/discussion/publication.js +123 -0
- package/packages/core/release/discussion/qualification.js +122 -0
- package/packages/core/release/discussion/reader-entry.js +11 -0
- package/packages/core/release/discussion/reader.js +177 -0
- package/packages/core/release/discussion/recovery.js +132 -0
- package/packages/core/release/discussion/session.js +115 -0
- package/packages/core/release/discussion/store.js +166 -0
- package/packages/core/release/discussion/threads.js +83 -0
- package/packages/core/release/github-release.js +3 -1
- package/packages/core/release/promote-candidate/action.js +86 -6
- package/packages/core/release/promote-candidate/preparation.js +106 -0
- package/packages/core/release/promote-candidate/product-provider.js +4 -1
- package/packages/core/release/promote-candidate/provider-settlement.js +36 -23
- package/packages/core/release/promote-candidate/transaction.js +55 -97
- package/packages/core/release/promotion/candidate.js +11 -2
- package/packages/core/release/promotion/qualification.js +5 -2
- package/packages/core/release/promotion-request.js +8 -4
- package/packages/core/workflow/engine/execution.js +5 -1
- package/packages/core/workflow/engine/provider-context.js +2 -0
- package/packages/core/workflow/engine/release-observation.js +1 -0
- package/packages/core/workflow/engine/release-promotion.js +38 -26
- package/packages/core/workflow/universal-workflow-bootstrap.js +1 -0
- package/scripts/build-release-discussion-reader.mjs +34 -0
- package/scripts/inventory/binary.mjs +1 -1
- package/scripts/maintainability-metrics.mjs +1 -0
- package/scripts/site-capability-metadata.mjs +1 -0
|
@@ -1,103 +1,47 @@
|
|
|
1
|
-
import {
|
|
2
|
-
resolveCandidateBuildSummaryPath,
|
|
3
|
-
resolveCandidateProviderInputs,
|
|
4
|
-
resolvePublicationTarget,
|
|
5
|
-
} from "./evidence-inputs.js";
|
|
6
|
-
import {
|
|
7
|
-
assertCandidateEvidenceBinding,
|
|
8
|
-
canonicalChannel,
|
|
9
|
-
observeProtectedPublicationSource,
|
|
10
|
-
} from "./evidence-binding.js";
|
|
11
|
-
import { productProviderRequest } from "./provider-request.js";
|
|
12
|
-
import { createReleaseDocuments } from "./release-documents.js";
|
|
1
|
+
import { prepareCandidatePublication } from "./preparation.js";
|
|
13
2
|
import { applyAndSettle } from "./provider-settlement.js";
|
|
14
|
-
import { read } from "./files.js";
|
|
15
3
|
import { candidatePublicationOutputs } from "./outputs.js";
|
|
16
4
|
import { completePublicationDevelopment } from "./publication-completion.js";
|
|
17
5
|
import {
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
} from "
|
|
21
|
-
import
|
|
6
|
+
readApplyDocuments,
|
|
7
|
+
verifyPublicationSettlement,
|
|
8
|
+
} from "../../publication/settlement/transaction.js";
|
|
9
|
+
import { canonicalChannel } from "./evidence-binding.js";
|
|
10
|
+
import { activateExactPnpm } from "./product-provider.js";
|
|
11
|
+
|
|
22
12
|
export async function promoteReleaseCandidate(
|
|
23
13
|
request,
|
|
24
|
-
{
|
|
25
|
-
) {
|
|
26
|
-
const repository = request["repository"];
|
|
27
|
-
const declaredSourceSha = request["source-sha"];
|
|
28
|
-
const fallbackVersion = request["version"];
|
|
29
|
-
const fallbackTag = request["tag"];
|
|
30
|
-
const channel = request["channel"];
|
|
31
|
-
const expectedTransactionId = request["resume-transaction-id"];
|
|
32
|
-
const candidatePassportPath = request["candidate-passport-path"];
|
|
33
|
-
const buildSummaryPath = resolveCandidateBuildSummaryPath({
|
|
34
|
-
declaredPath: request["candidate-build-summary-path"],
|
|
35
|
-
});
|
|
36
|
-
const candidate = read(candidatePassportPath);
|
|
37
|
-
const stageCapsules = read(request["stage-capsules-path"]);
|
|
38
|
-
const qualification = read(request["publication-qualification-path"]);
|
|
39
|
-
const token = request["token"];
|
|
40
|
-
const publicationTarget = resolvePublicationTarget({
|
|
41
|
-
recoveryReceiptPath: request["recovery-receipt-path"],
|
|
42
|
-
candidate,
|
|
43
|
-
repository,
|
|
44
|
-
channel,
|
|
45
|
-
sourceSha: declaredSourceSha,
|
|
46
|
-
targetRef: request["target-ref"],
|
|
47
|
-
targetSha: request["target-sha"],
|
|
48
|
-
expectedTransactionId,
|
|
49
|
-
});
|
|
50
|
-
const sourceSha = publicationTarget.sourceSha;
|
|
51
|
-
assertCandidateEvidenceBinding({ candidate, stageCapsules, repository });
|
|
52
|
-
const sourceBinding = await observeProtectedPublicationSource({
|
|
53
|
-
octokit,
|
|
54
|
-
repository,
|
|
55
|
-
protectedSourceSha: sourceSha,
|
|
56
|
-
candidate,
|
|
57
|
-
});
|
|
58
|
-
const providerInputs = resolveCandidateProviderInputs({
|
|
59
|
-
recoveryReceiptPath: request["recovery-receipt-path"],
|
|
60
|
-
artifactKind: request["publish-artifact-kind"] || "npm",
|
|
61
|
-
sealedBundleRoot: request["sealed-bundle-root"],
|
|
62
|
-
sealedBundleManifest: request["sealed-bundle-manifest"],
|
|
63
|
-
requiredArtifactsPath: request["required-artifacts-path"],
|
|
64
|
-
publishPackageMain: request["publish-package-main"],
|
|
65
|
-
});
|
|
66
|
-
const providerRequest = productProviderRequest({
|
|
67
|
-
request,
|
|
68
|
-
actor,
|
|
69
|
-
runId,
|
|
14
|
+
{
|
|
70
15
|
octokit,
|
|
71
16
|
mutationOctokit,
|
|
72
|
-
repository,
|
|
73
|
-
targetRef: publicationTarget.targetRef,
|
|
74
|
-
targetSha: publicationTarget.targetSha,
|
|
75
|
-
candidate,
|
|
76
|
-
candidatePassportPath,
|
|
77
|
-
buildSummaryPath,
|
|
78
|
-
qualification,
|
|
79
|
-
providerInputs,
|
|
80
|
-
});
|
|
81
|
-
const publicationPlan = await planProductPublication(providerRequest, {
|
|
82
|
-
fallbackVersion,
|
|
83
|
-
fallbackTag,
|
|
84
|
-
});
|
|
85
|
-
const documents = await createReleaseDocuments({
|
|
86
|
-
request,
|
|
87
17
|
actor,
|
|
88
18
|
runId,
|
|
19
|
+
observe = () => {},
|
|
20
|
+
observeNode = (_node, effect) => effect(),
|
|
21
|
+
},
|
|
22
|
+
) {
|
|
23
|
+
const context = await observeNode("qualification", async () => {
|
|
24
|
+
const prepared = await prepareCandidatePublication(request, {
|
|
25
|
+
octokit,
|
|
26
|
+
mutationOctokit,
|
|
27
|
+
actor,
|
|
28
|
+
runId,
|
|
29
|
+
});
|
|
30
|
+
if (request.retainRecoveryMaterials)
|
|
31
|
+
await request.retainRecoveryMaterials();
|
|
32
|
+
return prepared;
|
|
33
|
+
});
|
|
34
|
+
const {
|
|
89
35
|
repository,
|
|
90
36
|
sourceSha,
|
|
91
|
-
|
|
37
|
+
token,
|
|
92
38
|
channel,
|
|
93
|
-
candidate,
|
|
94
|
-
stageCapsules,
|
|
95
39
|
qualification,
|
|
96
|
-
|
|
40
|
+
providerRequest,
|
|
97
41
|
publicationPlan,
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
}
|
|
42
|
+
documents,
|
|
43
|
+
sourceBinding,
|
|
44
|
+
} = context;
|
|
101
45
|
activateExactPnpm();
|
|
102
46
|
const settlement = await applyAndSettle({
|
|
103
47
|
request,
|
|
@@ -111,20 +55,34 @@ export async function promoteReleaseCandidate(
|
|
|
111
55
|
providerRequest,
|
|
112
56
|
publicationPlan,
|
|
113
57
|
documents,
|
|
58
|
+
observeNode,
|
|
114
59
|
});
|
|
115
|
-
await
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
60
|
+
await observeNode("next-development", () =>
|
|
61
|
+
completePublicationDevelopment({
|
|
62
|
+
repository,
|
|
63
|
+
sourceSha,
|
|
64
|
+
token,
|
|
65
|
+
channel: canonicalChannel(channel),
|
|
66
|
+
settlement,
|
|
67
|
+
documents,
|
|
68
|
+
sourceBinding,
|
|
69
|
+
providerRequest,
|
|
70
|
+
octokit,
|
|
71
|
+
mutationOctokit,
|
|
72
|
+
}),
|
|
73
|
+
);
|
|
127
74
|
const outputs = candidatePublicationOutputs(documents, settlement);
|
|
75
|
+
await observeNode(
|
|
76
|
+
"settlement",
|
|
77
|
+
async () =>
|
|
78
|
+
verifyPublicationSettlement(readApplyDocuments(".buildchain"), {
|
|
79
|
+
repository,
|
|
80
|
+
tag: documents.tag,
|
|
81
|
+
sourceSha: settlement.productProviderResult.publication.releaseSha,
|
|
82
|
+
candidateSha: sourceSha,
|
|
83
|
+
}),
|
|
84
|
+
(status) => status,
|
|
85
|
+
);
|
|
128
86
|
observe(outputs);
|
|
129
87
|
return { documents, settlement, outputs };
|
|
130
88
|
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { recoverDiscussionCandidate } from "../discussion/recovery.js";
|
|
1
2
|
import { resolveReleaseCandidateArtifacts } from "../candidate/resolve.js";
|
|
2
3
|
import { resumeFromCandidateRun } from "../recovery/candidate.js";
|
|
3
4
|
export async function qualifyPromotionCandidate(
|
|
@@ -16,6 +17,7 @@ export async function qualifyPromotionCandidate(
|
|
|
16
17
|
{
|
|
17
18
|
fresh = resolveReleaseCandidateArtifacts,
|
|
18
19
|
recover = resumeFromCandidateRun,
|
|
20
|
+
recoverDiscussion = recoverDiscussionCandidate,
|
|
19
21
|
} = {},
|
|
20
22
|
) {
|
|
21
23
|
const shared = {
|
|
@@ -29,6 +31,15 @@ export async function qualifyPromotionCandidate(
|
|
|
29
31
|
runtimeSha,
|
|
30
32
|
outputDir,
|
|
31
33
|
};
|
|
34
|
+
if (request["resume-discussion-id"])
|
|
35
|
+
return recoverDiscussion({
|
|
36
|
+
discussionId: request["resume-discussion-id"],
|
|
37
|
+
repository,
|
|
38
|
+
token,
|
|
39
|
+
outputDir,
|
|
40
|
+
targetSha: intent["requested-sha"],
|
|
41
|
+
targetRef: intent["target-ref"],
|
|
42
|
+
});
|
|
32
43
|
if (request["resume-candidate-run-id"])
|
|
33
44
|
return recover({
|
|
34
45
|
...shared,
|
|
@@ -52,8 +63,6 @@ export async function qualifyPromotionCandidate(
|
|
|
52
63
|
runtimeRoot,
|
|
53
64
|
recoveryRunId,
|
|
54
65
|
recoveryRunAttempt,
|
|
55
|
-
|
|
56
|
-
|
|
57
66
|
});
|
|
58
67
|
return fresh({
|
|
59
68
|
...shared,
|
|
@@ -24,6 +24,7 @@ export async function qualifyPromotion(
|
|
|
24
24
|
requestedChannel: request.channel,
|
|
25
25
|
dryRun: request["dry-run"],
|
|
26
26
|
resume: Boolean(
|
|
27
|
+
request["resume-discussion-id"] ||
|
|
27
28
|
request["resume-candidate-run-id"] ||
|
|
28
29
|
request["publish-transaction-override"],
|
|
29
30
|
),
|
|
@@ -46,8 +47,10 @@ export async function qualifyPromotion(
|
|
|
46
47
|
);
|
|
47
48
|
const candidateVersion = qualified.candidateVersion || qualified.version,
|
|
48
49
|
publicationVersion = qualified.publicationVersion || qualified.version;
|
|
49
|
-
const recoveredVersion =
|
|
50
|
-
|
|
50
|
+
const recoveredVersion = request["resume-discussion-id"]
|
|
51
|
+
? publicationVersion
|
|
52
|
+
: request["publish-transaction-override"] ||
|
|
53
|
+
request["resume-transaction-id"]
|
|
51
54
|
? await recoverVersion(
|
|
52
55
|
{
|
|
53
56
|
requestedSha: intent["requested-sha"],
|
|
@@ -49,13 +49,17 @@ export function normalizePromotionRequest(value, kind = "request") {
|
|
|
49
49
|
throw new Error(`Unsupported promotion ${kind} schema`);
|
|
50
50
|
result[key] = input;
|
|
51
51
|
}
|
|
52
|
+
if (
|
|
53
|
+
result["resume-discussion-id"] &&
|
|
54
|
+
(result["resume-candidate-run-id"] || result["resume-transaction-id"])
|
|
55
|
+
)
|
|
56
|
+
throw new Error(
|
|
57
|
+
"Discussion recovery cannot be combined with candidate-run or transaction-id recovery",
|
|
58
|
+
);
|
|
52
59
|
return result;
|
|
53
60
|
}
|
|
54
61
|
|
|
55
|
-
export function bindPromotionInvocation(
|
|
56
|
-
requestValue,
|
|
57
|
-
selection,
|
|
58
|
-
) {
|
|
62
|
+
export function bindPromotionInvocation(requestValue, selection) {
|
|
59
63
|
const request = normalizePromotionRequest(requestValue);
|
|
60
64
|
const projected = Object.fromEntries(
|
|
61
65
|
Object.entries(request).filter(([key]) =>
|
|
@@ -6,7 +6,10 @@ import {
|
|
|
6
6
|
import { createReleaseInvocation } from "../../release/release-invocation.js";
|
|
7
7
|
import { executeBootstrapConformance } from "./conformance.js";
|
|
8
8
|
import { executeReleasePromotion } from "./release-promotion.js";
|
|
9
|
+
import { executeReleaseDiscussion } from "../../release/discussion/qualification.js";
|
|
9
10
|
async function capabilityResult(request, admission, context) {
|
|
11
|
+
if (request.capability.id === "release-discussion")
|
|
12
|
+
return executeReleaseDiscussion(request, admission, context);
|
|
10
13
|
if (request.capability.id === "bootstrap-conformance")
|
|
11
14
|
return executeBootstrapConformance(request, admission, context);
|
|
12
15
|
if (request.capability.id === "release-invocation") {
|
|
@@ -61,7 +64,8 @@ export async function executeAdmittedWorkflow(request, admission, context) {
|
|
|
61
64
|
|
|
62
65
|
export function assertResultLineage(admission, result) {
|
|
63
66
|
const { resultRoot, ...body } = result || {};
|
|
64
|
-
if (resultRoot !== contentRoot("universal-workflow-result", body))
|
|
67
|
+
if (resultRoot !== contentRoot("universal-workflow-result", body))
|
|
68
|
+
fail("candidate result root mismatch");
|
|
65
69
|
if (
|
|
66
70
|
result?.schema !== "kungfu-buildchain-v4-universal-workflow-result/v1" ||
|
|
67
71
|
result.requestRoot !== admission.requestRoot ||
|
|
@@ -7,6 +7,8 @@ export function providerExecutionContext({ token, mutationToken, env }) {
|
|
|
7
7
|
apiUrl,
|
|
8
8
|
actor: env.GITHUB_ACTOR,
|
|
9
9
|
runId: env.GITHUB_RUN_ID,
|
|
10
|
+
runAttempt: env.GITHUB_RUN_ATTEMPT,
|
|
11
|
+
runtimeSelection: env.BUILDCHAIN_RUNTIME_SELECTION,
|
|
10
12
|
octokit: token ? getOctokit(token, { baseUrl: apiUrl }) : undefined,
|
|
11
13
|
mutationOctokit:
|
|
12
14
|
mutationToken || token
|
|
@@ -29,6 +29,7 @@ export async function observeReleaseRoute(
|
|
|
29
29
|
targetRef,
|
|
30
30
|
dryRun: inputs["dry-run"] === true,
|
|
31
31
|
resume:
|
|
32
|
+
Boolean(inputs["resume-discussion-id"]) ||
|
|
32
33
|
String(inputs["resume-candidate-run-id"] || "") !== "" ||
|
|
33
34
|
inputs["publish-transaction-override"] === true,
|
|
34
35
|
});
|
|
@@ -6,9 +6,10 @@ import { planReleaseRoute } from "../../release/release-invocation.js";
|
|
|
6
6
|
import { selectRecoveredProductPublicationVersion } from "../universal-workflow-bootstrap.js";
|
|
7
7
|
import { assertDeclarativePromotionInputs } from "../../publication/publication-qualification.js";
|
|
8
8
|
import { normalizePromotionRequest } from "../../release/promotion-request.js";
|
|
9
|
-
import {
|
|
9
|
+
import { qualifyPromotionCandidate } from "../../release/promotion/candidate.js";
|
|
10
10
|
import { materializePublicationIntent } from "../../release/candidate/publication-intent.js";
|
|
11
|
-
import {
|
|
11
|
+
import { publishWithDiscussion } from "../../release/discussion/publication.js";
|
|
12
|
+
import { selectedRecordRuntime } from "../../release/discussion/session.js";
|
|
12
13
|
import {
|
|
13
14
|
observeReleaseRoute,
|
|
14
15
|
observedSourceTimestamp,
|
|
@@ -34,7 +35,9 @@ async function materializeProductPublicationIntent(
|
|
|
34
35
|
const version = String(
|
|
35
36
|
candidate.publicationVersion || candidate.version || "",
|
|
36
37
|
).trim();
|
|
37
|
-
const explicitResume =
|
|
38
|
+
const explicitResume = Boolean(
|
|
39
|
+
inputs["resume-transaction-id"] || inputs["resume-discussion-id"],
|
|
40
|
+
);
|
|
38
41
|
const recovery =
|
|
39
42
|
route.decision !== "Resume" || explicitResume
|
|
40
43
|
? {}
|
|
@@ -45,14 +48,16 @@ async function materializeProductPublicationIntent(
|
|
|
45
48
|
route.channel,
|
|
46
49
|
context,
|
|
47
50
|
);
|
|
48
|
-
const recoveredVersion =
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
51
|
+
const recoveredVersion = inputs["resume-discussion-id"]
|
|
52
|
+
? version
|
|
53
|
+
: selectRecoveredProductPublicationVersion({
|
|
54
|
+
routeDecision: route.decision,
|
|
55
|
+
candidateVersion: version,
|
|
56
|
+
channel: route.channel,
|
|
57
|
+
requestedSha: route.requestedSha,
|
|
58
|
+
explicitResume,
|
|
59
|
+
...recovery,
|
|
60
|
+
});
|
|
56
61
|
materializePublicationIntent({
|
|
57
62
|
repository,
|
|
58
63
|
channel: route.channel,
|
|
@@ -128,24 +133,21 @@ export async function executeReleasePromotion(request, admission, context) {
|
|
|
128
133
|
prepareReleaseConsumerDependencies();
|
|
129
134
|
if (payload.inputs["trusted-publishing"] === true)
|
|
130
135
|
prepareTrustedPublishingNpm();
|
|
131
|
-
const candidate = await
|
|
136
|
+
const candidate = await qualifyPromotionCandidate({
|
|
137
|
+
request: payload.inputs,
|
|
138
|
+
intent: {
|
|
139
|
+
"target-ref": route.targetRef,
|
|
140
|
+
"requested-sha": route.requestedSha,
|
|
141
|
+
channel: route.channel,
|
|
142
|
+
},
|
|
132
143
|
repository,
|
|
133
|
-
targetRef: route.targetRef,
|
|
134
|
-
targetSha: route.requestedSha,
|
|
135
144
|
token: context.token,
|
|
136
145
|
apiUrl: context.apiUrl,
|
|
137
|
-
workflowFile: payload.inputs["release-candidate-workflow-file"],
|
|
138
|
-
workflowName: payload.inputs["release-candidate-workflow-name"],
|
|
139
|
-
artifactName: payload.inputs["artifact-name"],
|
|
140
|
-
artifactPatterns: payload.inputs["artifact-patterns"],
|
|
141
|
-
githubReleasePayloadPatterns:
|
|
142
|
-
payload.inputs["github-release-payload-patterns"],
|
|
143
|
-
requiredArtifactCount: payload.inputs["required-artifact-count"],
|
|
144
|
-
publishArtifactKind: payload.inputs["publish-artifact-kind"],
|
|
145
|
-
publishPackageMain: payload.inputs["publish-package-main"],
|
|
146
146
|
runtimeSha: admission.runtime.sha,
|
|
147
|
-
|
|
148
|
-
|
|
147
|
+
runtimeRoot: context.runtimeRoot,
|
|
148
|
+
recoveryRunId: context.runId,
|
|
149
|
+
recoveryRunAttempt: context.runAttempt,
|
|
150
|
+
outputDir: path.resolve(".buildchain/release-candidate"),
|
|
149
151
|
});
|
|
150
152
|
if (!candidate.enabled)
|
|
151
153
|
fail(candidate.reason || "release candidate is unavailable");
|
|
@@ -203,12 +205,22 @@ export async function executeReleasePromotion(request, admission, context) {
|
|
|
203
205
|
"publish-transaction-override":
|
|
204
206
|
payload.inputs["publish-transaction-override"],
|
|
205
207
|
"resume-transaction-id": payload.inputs["resume-transaction-id"],
|
|
208
|
+
"resume-discussion-id": payload.inputs["resume-discussion-id"],
|
|
209
|
+
"standalone-binary-distribution":
|
|
210
|
+
payload.inputs["standalone-binary-distribution"],
|
|
206
211
|
"artifact-paths": candidate.paths.releaseAssets,
|
|
207
212
|
"state-path": ".buildchain/release-tail/state.json",
|
|
208
213
|
"failure-after-capability":
|
|
209
214
|
payload.inputs["provider-failure-after-capability"],
|
|
210
215
|
};
|
|
211
|
-
const provider = await
|
|
216
|
+
const provider = await publishWithDiscussion(publicationRequest, {
|
|
217
|
+
runtime: selectedRecordRuntime({
|
|
218
|
+
BUILDCHAIN_RUNTIME_SELECTION: context.runtimeSelection,
|
|
219
|
+
BUILDCHAIN_RUNTIME_ROOT: context.runtimeRoot,
|
|
220
|
+
}),
|
|
221
|
+
workspace: process.cwd(),
|
|
222
|
+
runtimeRoot: context.runtimeRoot,
|
|
223
|
+
attempt: `${context.runId}:${context.runAttempt || "1"}:bootstrap`,
|
|
212
224
|
octokit: context.octokit,
|
|
213
225
|
mutationOctokit: context.mutationOctokit,
|
|
214
226
|
actor: context.actor,
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { build } from "tsup";
|
|
2
|
+
import fs from "node:fs";
|
|
3
|
+
import os from "node:os";
|
|
4
|
+
import path from "node:path";
|
|
5
|
+
const check = process.argv.includes("--check");
|
|
6
|
+
const output = check
|
|
7
|
+
? fs.mkdtempSync(path.join(os.tmpdir(), "buildchain-reader-check-"))
|
|
8
|
+
: "dist/readers";
|
|
9
|
+
try {
|
|
10
|
+
await build({
|
|
11
|
+
entry: {
|
|
12
|
+
"release-discussion": "packages/core/release/discussion/reader-entry.js",
|
|
13
|
+
},
|
|
14
|
+
outDir: output,
|
|
15
|
+
format: ["cjs"],
|
|
16
|
+
target: "node24",
|
|
17
|
+
platform: "node",
|
|
18
|
+
splitting: false,
|
|
19
|
+
sourcemap: false,
|
|
20
|
+
minify: false,
|
|
21
|
+
clean: false,
|
|
22
|
+
outExtension: () => ({ js: ".cjs" }),
|
|
23
|
+
silent: true,
|
|
24
|
+
});
|
|
25
|
+
if (
|
|
26
|
+
check &&
|
|
27
|
+
!fs
|
|
28
|
+
.readFileSync(path.join(output, "release-discussion.cjs"))
|
|
29
|
+
.equals(fs.readFileSync("dist/readers/release-discussion.cjs"))
|
|
30
|
+
)
|
|
31
|
+
throw new Error("Historical release reader bundle is stale");
|
|
32
|
+
} finally {
|
|
33
|
+
if (check) fs.rmSync(output, { recursive: true, force: true });
|
|
34
|
+
}
|
|
@@ -32,5 +32,5 @@ export function assertBinaryInventory(root) {
|
|
|
32
32
|
assert.equal(effect["continue-on-error"], undefined);
|
|
33
33
|
const transaction = publish.modules.get("packages/core/publication/binary/transaction.js");
|
|
34
34
|
assert.match(transaction, /validateBinaryCapability\([\s\S]*await client.publish\(/, "Binary effects must follow capability admission");
|
|
35
|
-
assert.match(publish.modules.get("packages/core/publication/binary/action.js"), /verifyCheckoutIdentity\([\s\S]*await publishBinaryAssets\(/);
|
|
35
|
+
assert.match(publish.modules.get("packages/core/publication/binary/action.js"), /verifyCheckoutIdentity\([\s\S]*await observeBinaryDistribution\([\s\S]*publishBinaryAssets\(/);
|
|
36
36
|
}
|
|
@@ -231,6 +231,7 @@ export function nodeApiMeta(exportName) {
|
|
|
231
231
|
"./v4-tail-reseal": { group: "release-passport-trust", summary: "Effect-pure retained Stage Capsule validation and explicit Warrant-, credential-, and release-tail-fenced macOS reseal planning APIs." },
|
|
232
232
|
"./tail-reseal": { group: "release-passport-trust", summary: "Effect-pure retained Stage Capsule validation and explicit Warrant-, credential-, and release-tail-fenced macOS reseal planning APIs." },
|
|
233
233
|
"./v4-tail-reseal-receipt": { group: "release-passport-trust", summary: "Four-platform byte readback, standard candidate Passport binding, and terminal v4 tail-reseal receipt APIs." },
|
|
234
|
+
"./release-discussion-reader": { group: "release-passport-trust", summary: "Standalone historical decoder for append-only release Discussion intent, attempt lineage and recovery handoff." },
|
|
234
235
|
"./tail-reseal-receipt": { group: "release-passport-trust", summary: "Four-platform byte readback, standard candidate Passport binding, and terminal v4 tail-reseal receipt APIs." },
|
|
235
236
|
"./v4-publication-rehearsal": { group: "release-passport-trust", summary: "Content-addressed v4 publication rehearsal capsules, shared production release-tail execution, replay, provider observation, and fail-closed verification APIs." },
|
|
236
237
|
"./publication-rehearsal": { group: "release-passport-trust", summary: "Content-addressed v4 publication rehearsal capsules, shared production release-tail execution, replay, provider observation, and fail-closed verification APIs." },
|