@kungfu-tech/buildchain 2.4.8-alpha.0 → 2.4.8
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/README.md +7 -0
- package/docs/reusable-build-surface.md +39 -0
- package/package.json +1 -1
- package/packages/core/release-candidate.js +26 -2
- package/packages/core/release-passport.js +5 -0
- package/scripts/check-inventory.mjs +4 -0
- package/scripts/generate-release-candidate-passport.mjs +1 -1
- package/scripts/release-candidate-resolver.mjs +1 -0
package/README.md
CHANGED
|
@@ -150,6 +150,9 @@ The active reusable workflow surfaces are:
|
|
|
150
150
|
|
|
151
151
|
- `.github/workflows/.build.yml` for deterministic multi-platform build and
|
|
152
152
|
artifact contracts;
|
|
153
|
+
- `.github/workflows/release-candidate-promote.yml` for post-merge
|
|
154
|
+
promote-only publication from a PR-stage release candidate, without a second
|
|
155
|
+
heavy build;
|
|
153
156
|
- `.github/workflows/.web-surface.yml` for preview, staging, production, and
|
|
154
157
|
cleanup plans for site/app repositories;
|
|
155
158
|
- `.github/workflows/buildchain-ref-promotion.yml` for protected release
|
|
@@ -168,6 +171,10 @@ uses: kungfu-systems/buildchain/actions/validate-config@v2
|
|
|
168
171
|
uses: kungfu-systems/buildchain/.github/workflows/.build.yml@v2
|
|
169
172
|
```
|
|
170
173
|
|
|
174
|
+
```yaml
|
|
175
|
+
uses: kungfu-systems/buildchain/.github/workflows/release-candidate-promote.yml@v2
|
|
176
|
+
```
|
|
177
|
+
|
|
171
178
|
## Release Model
|
|
172
179
|
|
|
173
180
|
Buildchain treats a reviewed branch merge as release intent:
|
|
@@ -359,6 +359,45 @@ If the branch tip no longer matches the manifest SHA, the publish job must fail
|
|
|
359
359
|
closed. Moving a gate branch creates a new publish decision and should produce a
|
|
360
360
|
new build run.
|
|
361
361
|
|
|
362
|
+
## Release Candidate Promote-Only
|
|
363
|
+
|
|
364
|
+
For native package sets, the PR build is the only heavy build. When a PR targets
|
|
365
|
+
`alpha/<line>` or `release/<line>`, `.build.yml` uploads a release-candidate
|
|
366
|
+
bundle next to the platform artifacts. The bundle contains:
|
|
367
|
+
|
|
368
|
+
- `release-candidate.passport.json`;
|
|
369
|
+
- the aggregate `build-summary.json`;
|
|
370
|
+
- copied platform manifest evidence for the built platforms.
|
|
371
|
+
|
|
372
|
+
The passport records two separate source identities:
|
|
373
|
+
|
|
374
|
+
- `builtSourceSha` / `builtSourceTreeSha`: the PR-stage source that produced the
|
|
375
|
+
artifacts, usually the PR merge ref;
|
|
376
|
+
- `promotionChannelSha` / `promotionChannelTreeSha`: the post-merge channel
|
|
377
|
+
commit used for publish authority.
|
|
378
|
+
|
|
379
|
+
The reusable promote wrapper resolves the merged PR, finds exactly one matching
|
|
380
|
+
PR-stage release-candidate artifact, downloads it, compares the built tree with
|
|
381
|
+
the promotion channel tree, locks `publish-gate/{alpha,release,major}` to the
|
|
382
|
+
promotion channel commit, and then calls `actions/promote-buildchain-ref` with
|
|
383
|
+
`promote-only-release-candidate: "true"`. It does not call `.build.yml`, does
|
|
384
|
+
not create a matrix, and must fail before publish if the RC evidence is missing
|
|
385
|
+
or ambiguous.
|
|
386
|
+
|
|
387
|
+
```yaml
|
|
388
|
+
jobs:
|
|
389
|
+
promote:
|
|
390
|
+
uses: kungfu-systems/buildchain/.github/workflows/release-candidate-promote.yml@v2
|
|
391
|
+
with:
|
|
392
|
+
channel: alpha
|
|
393
|
+
target-ref: alpha/v22/v22.22
|
|
394
|
+
artifact-name: libnode
|
|
395
|
+
package-manager: npm
|
|
396
|
+
publish-target: npm
|
|
397
|
+
runner-preset: github-hosted
|
|
398
|
+
trusted-publishing: true
|
|
399
|
+
```
|
|
400
|
+
|
|
362
401
|
Custom publish jobs can also repeat the channel-ref preflight:
|
|
363
402
|
|
|
364
403
|
```yaml
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kungfu-tech/buildchain",
|
|
3
|
-
"version": "2.4.8
|
|
3
|
+
"version": "2.4.8",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "Buildchain Release Passport, release governance, CLI toolkit, and site facts.",
|
|
6
6
|
"repository": "https://github.com/kungfu-systems/buildchain",
|
|
@@ -80,6 +80,26 @@ function normalizePlatformEntry(platform = {}, index = 0) {
|
|
|
80
80
|
};
|
|
81
81
|
}
|
|
82
82
|
|
|
83
|
+
function inferVersionFromReleaseManifest(buildSummary = {}) {
|
|
84
|
+
const raw = buildSummary.publishSource?.releaseManifest || "";
|
|
85
|
+
if (!raw) {
|
|
86
|
+
return "";
|
|
87
|
+
}
|
|
88
|
+
try {
|
|
89
|
+
const manifest = JSON.parse(raw);
|
|
90
|
+
const versions = [
|
|
91
|
+
...new Set(
|
|
92
|
+
(manifest.versionFiles || [])
|
|
93
|
+
.map((file) => optionalString(file.version).trim())
|
|
94
|
+
.filter(Boolean),
|
|
95
|
+
),
|
|
96
|
+
];
|
|
97
|
+
return versions.length === 1 ? versions[0] : "";
|
|
98
|
+
} catch {
|
|
99
|
+
return "";
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
83
103
|
export function createReleaseCandidatePassport({
|
|
84
104
|
repository = "",
|
|
85
105
|
pullRequest = {},
|
|
@@ -96,10 +116,12 @@ export function createReleaseCandidatePassport({
|
|
|
96
116
|
} = {}) {
|
|
97
117
|
const normalizedSummary = buildSummary && typeof buildSummary === "object" ? buildSummary : {};
|
|
98
118
|
const sourceSha = sourceHeadSha || normalizedSummary.publishSource?.sha || normalizedSummary.git?.sha || "";
|
|
119
|
+
const resolvedTreeHash = optionalString(sourceTreeHash || normalizedSummary.git?.treeSha);
|
|
99
120
|
const channel = normalizeTargetChannel(targetChannel)
|
|
100
121
|
|| normalizeTargetChannel(normalizedSummary.publishSource?.channel)
|
|
101
122
|
|| normalizeTargetChannel(normalizedSummary.publishGate?.channel)
|
|
102
123
|
|| normalizeTargetChannel(pullRequest.baseRef);
|
|
124
|
+
const resolvedVersion = version || normalizedSummary.publishSource?.consumerVersion || inferVersionFromReleaseManifest(normalizedSummary);
|
|
103
125
|
const candidate = {
|
|
104
126
|
schemaVersion: 1,
|
|
105
127
|
contract: RELEASE_CANDIDATE_PASSPORT_CONTRACT,
|
|
@@ -114,13 +136,15 @@ export function createReleaseCandidatePassport({
|
|
|
114
136
|
target: {
|
|
115
137
|
channel: nonEmptyString(channel, "targetChannel"),
|
|
116
138
|
ref: optionalString(normalizedSummary.publishSource?.ref || normalizedSummary.git?.ref),
|
|
117
|
-
version: nonEmptyString(
|
|
139
|
+
version: nonEmptyString(resolvedVersion, "version"),
|
|
118
140
|
},
|
|
119
141
|
source: {
|
|
120
142
|
headSha: nonEmptyString(sourceSha, "sourceHeadSha"),
|
|
121
143
|
baseSha: optionalString(baseSha),
|
|
122
144
|
mergeRefSha: optionalString(mergeRefSha || sourceSha),
|
|
123
|
-
treeHash:
|
|
145
|
+
treeHash: resolvedTreeHash,
|
|
146
|
+
builtSourceSha: nonEmptyString(mergeRefSha || sourceSha, "builtSourceSha"),
|
|
147
|
+
builtSourceTreeSha: resolvedTreeHash,
|
|
124
148
|
},
|
|
125
149
|
buildchain: {
|
|
126
150
|
ref: optionalString(buildchain.ref || normalizedSummary.runtime?.ref),
|
|
@@ -576,6 +576,11 @@ export function createReleasePassport({
|
|
|
576
576
|
targetRef,
|
|
577
577
|
releaseSha,
|
|
578
578
|
releaseMaterialSha,
|
|
579
|
+
builtSourceSha: optionalString(release.builtSourceSha || release.built_source_sha),
|
|
580
|
+
builtSourceTreeSha: optionalString(release.builtSourceTreeSha || release.built_source_tree_sha),
|
|
581
|
+
promotionChannelSha: optionalString(release.promotionChannelSha || release.promotion_channel_sha),
|
|
582
|
+
promotionChannelTreeSha: optionalString(release.promotionChannelTreeSha || release.promotion_channel_tree_sha),
|
|
583
|
+
treeEquivalent: release.treeEquivalent === undefined ? undefined : Boolean(release.treeEquivalent),
|
|
579
584
|
publishToolingSha: optionalString(
|
|
580
585
|
release.publishToolingSha ||
|
|
581
586
|
release.publish_tooling_sha ||
|
|
@@ -28,8 +28,11 @@ const requiredPaths = [
|
|
|
28
28
|
"scripts/build-standalone-binary.mjs",
|
|
29
29
|
"scripts/create-release-bundle.mjs",
|
|
30
30
|
"scripts/generate-site-bundle.mjs",
|
|
31
|
+
"scripts/generate-release-candidate-passport.mjs",
|
|
31
32
|
"scripts/npm-publish-dry-run.mjs",
|
|
32
33
|
"scripts/npm-publish-transaction.mjs",
|
|
34
|
+
"scripts/release-candidate-resolver.mjs",
|
|
35
|
+
"scripts/workflow-friction-report.mjs",
|
|
33
36
|
"docs/migration-inventory.md",
|
|
34
37
|
"docs/lifecycle-protocol.md",
|
|
35
38
|
"docs/ownership.md",
|
|
@@ -38,6 +41,7 @@ const requiredPaths = [
|
|
|
38
41
|
".github/actionlint.yaml",
|
|
39
42
|
".github/workflows/self-hosted-runner-smoke.yml",
|
|
40
43
|
".github/workflows/buildchain-ref-promotion.yml",
|
|
44
|
+
".github/workflows/release-candidate-promote.yml",
|
|
41
45
|
".github/workflows/npm-publish.yml",
|
|
42
46
|
".github/workflows/binary-distribution.yml",
|
|
43
47
|
".github/workflows/verify.yml",
|
|
@@ -23,7 +23,7 @@ export function generateReleaseCandidatePassportCli() {
|
|
|
23
23
|
const sourceSha = env("BUILDCHAIN_RC_SOURCE_HEAD_SHA", buildSummary.publishSource?.sha || buildSummary.git?.sha || "");
|
|
24
24
|
const version = env(
|
|
25
25
|
"BUILDCHAIN_RC_VERSION",
|
|
26
|
-
buildSummary.publishSource?.consumerVersion ||
|
|
26
|
+
buildSummary.publishSource?.consumerVersion || "",
|
|
27
27
|
);
|
|
28
28
|
const passport = createReleaseCandidatePassport({
|
|
29
29
|
repository: env("GITHUB_REPOSITORY", buildSummary.git?.repository || ""),
|
|
@@ -294,6 +294,7 @@ export async function resolveReleaseCandidateArtifactsCli() {
|
|
|
294
294
|
"release-candidate-passport-path": result.paths?.passport || "",
|
|
295
295
|
"release-candidate-build-summary-path": result.paths?.buildSummary || "",
|
|
296
296
|
"release-candidate-version": result.version || "",
|
|
297
|
+
"release-candidate-source-sha": result.artifacts?.sourceSha || "",
|
|
297
298
|
"release-candidate-artifact": result.artifacts?.passport || "",
|
|
298
299
|
"release-candidate-build-summary-artifact": result.artifacts?.summary || "",
|
|
299
300
|
"release-candidate-run-id": result.run?.id || "",
|