@williamthorsen/release-kit 14.2.2 โ 14.2.3
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/.meta/changelog.json +50 -0
- package/.readyup/kits/default.js +135 -145
- package/.readyup/kits/npm-auto-publish.js +179 -180
- package/.readyup/manifest.json +31 -17
- package/CHANGELOG.md +16 -0
- package/README.md +7 -1
- package/dist/esm/applyChangelogOverrides.d.ts +50 -0
- package/dist/esm/applyChangelogOverrides.js +162 -0
- package/dist/esm/attachChangelogDiagnostics.d.ts +1 -1
- package/dist/esm/bin/release-kit.js +6 -238
- package/dist/esm/buildChangelogEntries.d.ts +20 -31
- package/dist/esm/buildChangelogEntries.js +71 -188
- package/dist/esm/buildChangelogItem.d.ts +56 -0
- package/dist/esm/buildChangelogItem.js +119 -0
- package/dist/esm/buildReleasedResult.d.ts +20 -0
- package/dist/esm/buildReleasedResult.js +78 -0
- package/dist/esm/changelogJsonUtils.d.ts +1 -1
- package/dist/esm/changelogOverrides.d.ts +29 -143
- package/dist/esm/changelogOverrides.js +35 -467
- package/dist/esm/configSchema.d.ts +225 -0
- package/dist/esm/configSchema.js +103 -0
- package/dist/esm/decideDirectReleases.d.ts +30 -0
- package/dist/esm/decideDirectReleases.js +66 -0
- package/dist/esm/defineConfig.d.ts +2 -2
- package/dist/esm/deriveReleaseNotesConfig.d.ts +2 -1
- package/dist/esm/deriveReleaseNotesConfig.js +1 -1
- package/dist/esm/formatPrepareFiles.d.ts +11 -0
- package/dist/esm/formatPrepareFiles.js +55 -0
- package/dist/esm/formatPrepareWarnings.d.ts +26 -0
- package/dist/esm/formatPrepareWarnings.js +72 -0
- package/dist/esm/help/initHelp.d.ts +4 -0
- package/dist/esm/help/initHelp.js +31 -0
- package/dist/esm/help/overridesHelp.d.ts +4 -0
- package/dist/esm/help/overridesHelp.js +32 -0
- package/dist/esm/help/releaseStepsHelp.d.ts +12 -0
- package/dist/esm/help/releaseStepsHelp.js +91 -0
- package/dist/esm/help/syncLabelsHelp.d.ts +8 -0
- package/dist/esm/help/syncLabelsHelp.js +55 -0
- package/dist/esm/help/usage.d.ts +2 -0
- package/dist/esm/help/usage.js +29 -0
- package/dist/esm/index.d.ts +1 -1
- package/dist/esm/index.js +1 -1
- package/dist/esm/loadChangelogOverrides.d.ts +31 -0
- package/dist/esm/loadChangelogOverrides.js +138 -0
- package/dist/esm/loadConfig.d.ts +0 -40
- package/dist/esm/loadConfig.js +0 -240
- package/dist/esm/loadValidatedConfig.d.ts +1 -1
- package/dist/esm/mergeConfig.d.ts +41 -0
- package/dist/esm/mergeConfig.js +118 -0
- package/dist/esm/monorepoConfigAssertions.d.ts +49 -0
- package/dist/esm/monorepoConfigAssertions.js +126 -0
- package/dist/esm/planChangelogFiles.d.ts +16 -0
- package/dist/esm/planChangelogFiles.js +41 -0
- package/dist/esm/prepareArgs.d.ts +55 -0
- package/dist/esm/prepareArgs.js +69 -0
- package/dist/esm/prepareCommand.d.ts +0 -48
- package/dist/esm/prepareCommand.js +6 -73
- package/dist/esm/prepareComposite.d.ts +16 -0
- package/dist/esm/prepareComposite.js +39 -0
- package/dist/esm/prepareRunContext.d.ts +38 -0
- package/dist/esm/prepareRunContext.js +39 -0
- package/dist/esm/prepareTarget.d.ts +2 -7
- package/dist/esm/prepareTarget.js +2 -118
- package/dist/esm/previewTagPrefixes.d.ts +1 -1
- package/dist/esm/releasePrepareTargets.js +13 -205
- package/dist/esm/reportPrepare.js +3 -125
- package/dist/esm/resolveCommandTags.d.ts +1 -1
- package/dist/esm/resolveCommandTags.js +2 -1
- package/dist/esm/resolveReleaseDeclaration.d.ts +2 -1
- package/dist/esm/resolveReleaseTargets.d.ts +2 -1
- package/dist/esm/resolveReleaseTargets.js +2 -1
- package/dist/esm/sync-labels/generateCommand.d.ts +1 -1
- package/dist/esm/sync-labels/resolveLabels.d.ts +1 -1
- package/dist/esm/topologicalSort.d.ts +12 -0
- package/dist/esm/topologicalSort.js +60 -0
- package/dist/esm/types.d.ts +1 -225
- package/dist/esm/types.js +1 -103
- package/dist/esm/validateAllChangelogOverrides.d.ts +56 -0
- package/dist/esm/validateAllChangelogOverrides.js +138 -0
- package/dist/esm/validateConfig.d.ts +1 -1
- package/dist/esm/validateConfig.js +7 -9
- package/dist/esm/validateOverridesCommand.d.ts +1 -1
- package/dist/esm/validateOverridesCommand.js +2 -1
- package/package.json +2 -2
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/** @noformat -- @generated. Do not edit. Compiled by rdy. */
|
|
2
2
|
/* eslint-disable */
|
|
3
|
-
export const __readyupVersion = "0.
|
|
3
|
+
export const __readyupVersion = "0.42.0";
|
|
4
4
|
|
|
5
5
|
|
|
6
6
|
// .readyup/kits/npm-auto-publish.ts
|
|
@@ -13,16 +13,10 @@ import {
|
|
|
13
13
|
fileContains,
|
|
14
14
|
fileExists,
|
|
15
15
|
getJsonValue,
|
|
16
|
-
isRecord as isRecord2,
|
|
17
16
|
readFile,
|
|
18
17
|
readJsonFile
|
|
19
18
|
} from "readyup/check-utils";
|
|
20
19
|
|
|
21
|
-
// src/init/hasProvenance.ts
|
|
22
|
-
function hasProvenance(workflowContent) {
|
|
23
|
-
return /^[^#]*provenance:\s*['"]?true['"]?/im.test(workflowContent);
|
|
24
|
-
}
|
|
25
|
-
|
|
26
20
|
// src/npmRegistry.ts
|
|
27
21
|
import { execFileSync } from "node:child_process";
|
|
28
22
|
|
|
@@ -87,10 +81,169 @@ function runNpmJson(args) {
|
|
|
87
81
|
}
|
|
88
82
|
}
|
|
89
83
|
|
|
90
|
-
// .readyup/
|
|
84
|
+
// .readyup/lib/npm-trust.ts
|
|
85
|
+
import { isRecord as isRecord2 } from "readyup/check-utils";
|
|
86
|
+
|
|
87
|
+
// src/init/hasProvenance.ts
|
|
88
|
+
function hasProvenance(workflowContent) {
|
|
89
|
+
return /^[^#]*provenance:\s*['"]?true['"]?/im.test(workflowContent);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// .readyup/lib/npm-trust.ts
|
|
91
93
|
var OTP_ERROR_CODE = "EOTP";
|
|
92
94
|
var PUBLISH_WORKFLOW_FILE = "publish.yaml";
|
|
93
95
|
var NO_GITHUB_REMOTE_FIX = "Add an origin remote that points to the GitHub repo, then run this check again";
|
|
96
|
+
function classifyNpmAuth(result) {
|
|
97
|
+
if (result.exitOk) {
|
|
98
|
+
return { status: "authenticated" };
|
|
99
|
+
}
|
|
100
|
+
const error = readNpmError(result.stdout);
|
|
101
|
+
if (error === void 0) {
|
|
102
|
+
return { status: "unreachable", detail: "The npm registry query failed without a readable error payload" };
|
|
103
|
+
}
|
|
104
|
+
if (AUTH_ERROR_CODES.has(error.code)) {
|
|
105
|
+
return { status: "unauthenticated", detail: `The npm registry rejected the session (${error.code})` };
|
|
106
|
+
}
|
|
107
|
+
if (UNREACHABLE_ERROR_CODES.has(error.code)) {
|
|
108
|
+
return { status: "unreachable", detail: `Cannot reach the npm registry (${error.code})` };
|
|
109
|
+
}
|
|
110
|
+
return { status: "unreachable", detail: `The npm registry query failed (${error.code}): ${error.summary}` };
|
|
111
|
+
}
|
|
112
|
+
function classifyProvenanceSetting(workflowContent, visibility) {
|
|
113
|
+
if (workflowContent === void 0) {
|
|
114
|
+
return {
|
|
115
|
+
ok: false,
|
|
116
|
+
detail: "Cannot read .github/workflows/publish.yaml",
|
|
117
|
+
fix: "Check the file's permissions"
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
if (typeof visibility !== "string") {
|
|
121
|
+
return { ok: false, detail: visibility.detail, fix: NO_GITHUB_REMOTE_FIX };
|
|
122
|
+
}
|
|
123
|
+
if (visibility === "unknown") {
|
|
124
|
+
return {
|
|
125
|
+
ok: false,
|
|
126
|
+
detail: "The GitHub CLI could not report the repo's visibility",
|
|
127
|
+
fix: "Install and authenticate the GitHub CLI: gh auth login"
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
const provenance = hasProvenance(workflowContent);
|
|
131
|
+
if (visibility === "public" && !provenance) {
|
|
132
|
+
return {
|
|
133
|
+
ok: false,
|
|
134
|
+
detail: "The repo is public and publish.yaml does not set provenance: true",
|
|
135
|
+
fix: "Set provenance: true in .github/workflows/publish.yaml; public repos should generate provenance attestations"
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
if (visibility === "private" && provenance) {
|
|
139
|
+
return {
|
|
140
|
+
ok: false,
|
|
141
|
+
detail: "The repo is private and publish.yaml sets provenance: true",
|
|
142
|
+
fix: "Make the GitHub repo public; OIDC publishing with provenance requires a public repo"
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
return { ok: true };
|
|
146
|
+
}
|
|
147
|
+
function classifyTrustCapability(auth, probe) {
|
|
148
|
+
if (auth.status !== "authenticated") {
|
|
149
|
+
return { ok: false, detail: auth.detail };
|
|
150
|
+
}
|
|
151
|
+
return probe?.status === "unanswerable" ? { ok: false, detail: probe.detail } : { ok: true };
|
|
152
|
+
}
|
|
153
|
+
function classifyTrustQuery(result, expectedRepo, expectedFile) {
|
|
154
|
+
if (!result.exitOk) {
|
|
155
|
+
const error = readNpmError(result.stdout);
|
|
156
|
+
if (error === void 0) {
|
|
157
|
+
return { status: "error", detail: "The npm trust query failed without a readable error payload" };
|
|
158
|
+
}
|
|
159
|
+
if (error.code === "E404") {
|
|
160
|
+
return { status: "not-configured" };
|
|
161
|
+
}
|
|
162
|
+
if (AUTH_ERROR_CODES.has(error.code) || error.code === OTP_ERROR_CODE) {
|
|
163
|
+
return {
|
|
164
|
+
status: "unanswerable",
|
|
165
|
+
detail: `The npm session cannot answer trust queries (${error.code}): ${error.summary}`
|
|
166
|
+
};
|
|
167
|
+
}
|
|
168
|
+
if (UNREACHABLE_ERROR_CODES.has(error.code)) {
|
|
169
|
+
return { status: "unanswerable", detail: `Cannot reach the npm registry (${error.code})` };
|
|
170
|
+
}
|
|
171
|
+
return { status: "error", detail: `The npm trust query failed (${error.code}): ${error.summary}` };
|
|
172
|
+
}
|
|
173
|
+
const relationships = readTrustRelationships(result.stdout);
|
|
174
|
+
if (relationships === void 0) {
|
|
175
|
+
return { status: "error", detail: "The npm trust query returned a payload that this check cannot read" };
|
|
176
|
+
}
|
|
177
|
+
if (relationships.length === 0) {
|
|
178
|
+
return { status: "not-configured" };
|
|
179
|
+
}
|
|
180
|
+
if (!expectedRepo.ok) {
|
|
181
|
+
return {
|
|
182
|
+
status: "error",
|
|
183
|
+
detail: `Cannot compare the trusted publisher with this repo; found ${describeTrustRelationships(relationships)}`
|
|
184
|
+
};
|
|
185
|
+
}
|
|
186
|
+
const isMatch = relationships.some(
|
|
187
|
+
(relationship) => relationship.type === "github" && relationship.repository === expectedRepo.value && relationship.file === expectedFile
|
|
188
|
+
);
|
|
189
|
+
return isMatch ? { status: "configured" } : {
|
|
190
|
+
status: "mismatched",
|
|
191
|
+
detail: `Expected github ${expectedRepo.value} (${expectedFile}); found ${describeTrustRelationships(relationships)}`
|
|
192
|
+
};
|
|
193
|
+
}
|
|
194
|
+
function describeNpmPackageLookup(lookup) {
|
|
195
|
+
if (lookup.status === "published") {
|
|
196
|
+
return { ok: true };
|
|
197
|
+
}
|
|
198
|
+
if (lookup.status === "unpublished") {
|
|
199
|
+
return { ok: false, detail: "The npm registry does not list this package" };
|
|
200
|
+
}
|
|
201
|
+
return {
|
|
202
|
+
ok: false,
|
|
203
|
+
detail: lookup.detail,
|
|
204
|
+
fix: "Restore access to the npm registry, then run this check again"
|
|
205
|
+
};
|
|
206
|
+
}
|
|
207
|
+
function describeTrustedPublisher(result, packageName, ownerRepo) {
|
|
208
|
+
if (result.status === "configured") {
|
|
209
|
+
return { ok: true };
|
|
210
|
+
}
|
|
211
|
+
const detail = result.status === "not-configured" ? "The npm registry does not list any trusted publisher for this package" : result.detail;
|
|
212
|
+
return ownerRepo.ok ? { ok: false, detail, fix: formatTrustCommand(packageName, ownerRepo.value) } : { ok: false, detail: `${detail}. ${ownerRepo.detail}`, fix: NO_GITHUB_REMOTE_FIX };
|
|
213
|
+
}
|
|
214
|
+
function formatTrustCommand(packageName, ownerRepo) {
|
|
215
|
+
return `Run: npm trust github ${packageName} --repo ${ownerRepo} --file ${PUBLISH_WORKFLOW_FILE}`;
|
|
216
|
+
}
|
|
217
|
+
function parseGitHubOwnerRepo(url) {
|
|
218
|
+
const match = /git@github\.com:(.+?)(?:\.git)?$/.exec(url) ?? /github\.com\/(.+?)(?:\.git)?$/.exec(url);
|
|
219
|
+
const ownerRepo = match?.[1];
|
|
220
|
+
return ownerRepo === void 0 ? { ok: false, detail: `The origin remote does not point to GitHub: ${url}` } : { ok: true, value: ownerRepo };
|
|
221
|
+
}
|
|
222
|
+
function describeTrustRelationships(relationships) {
|
|
223
|
+
return relationships.map((relationship) => {
|
|
224
|
+
const type = typeof relationship.type === "string" ? relationship.type : "(unknown)";
|
|
225
|
+
const repository = typeof relationship.repository === "string" ? relationship.repository : "(unknown)";
|
|
226
|
+
const file = typeof relationship.file === "string" ? relationship.file : "(unknown)";
|
|
227
|
+
return `${type} ${repository} (${file})`;
|
|
228
|
+
}).join(", ");
|
|
229
|
+
}
|
|
230
|
+
function readTrustRelationships(stdout) {
|
|
231
|
+
let parsed;
|
|
232
|
+
try {
|
|
233
|
+
parsed = JSON.parse(stdout);
|
|
234
|
+
} catch {
|
|
235
|
+
return void 0;
|
|
236
|
+
}
|
|
237
|
+
if (Array.isArray(parsed)) {
|
|
238
|
+
return parsed.filter((entry) => isRecord2(entry) && "type" in entry);
|
|
239
|
+
}
|
|
240
|
+
if (!isRecord2(parsed)) {
|
|
241
|
+
return void 0;
|
|
242
|
+
}
|
|
243
|
+
return "type" in parsed ? [parsed] : [];
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
// .readyup/kits/npm-auto-publish.ts
|
|
94
247
|
var repoChecklist = defineRdyChecklist({
|
|
95
248
|
name: "repo",
|
|
96
249
|
checks: [
|
|
@@ -139,25 +292,28 @@ var packagesChecklist = defineRdyChecklist({
|
|
|
139
292
|
fix: "Ensure pnpm-workspace.yaml lists package globs, or that a root package.json exists"
|
|
140
293
|
}
|
|
141
294
|
],
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
295
|
+
checks: [
|
|
296
|
+
{
|
|
297
|
+
name: "Repo publishes at least one package",
|
|
298
|
+
skip: () => skipIfNothingPublishable(),
|
|
299
|
+
check: () => true,
|
|
300
|
+
// Built when the checklist runs, so that the kit declares the same checks wherever it is imported. The session
|
|
301
|
+
// gate is a sibling of the workspace rows, not their parent, so a session that cannot answer trust queries
|
|
302
|
+
// suppresses only the trusted-publisher rows and leaves the package.json checks reporting.
|
|
303
|
+
checks: () => [
|
|
304
|
+
buildSessionCheck(),
|
|
305
|
+
...discoverWorkspaces({ filter: belongsInPackagesChecklist }).map(
|
|
306
|
+
(workspace) => buildWorkspaceCheck(workspace)
|
|
307
|
+
)
|
|
308
|
+
]
|
|
149
309
|
}
|
|
150
|
-
|
|
151
|
-
sessionCheck,
|
|
152
|
-
...discoverWorkspaces({ filter: belongsInPackagesChecklist }).map((workspace) => buildWorkspaceCheck(workspace))
|
|
153
|
-
];
|
|
154
|
-
}
|
|
310
|
+
]
|
|
155
311
|
});
|
|
156
312
|
var npm_auto_publish_default = defineRdyKit({
|
|
157
313
|
fixLocation: "inline",
|
|
158
|
-
// The release that introduced `
|
|
159
|
-
//
|
|
160
|
-
minReadyupVersion: "0.
|
|
314
|
+
// The release that introduced a function-valued `checks`, which builds the per-package rows. An older runner rejects
|
|
315
|
+
// it when validating the kit.
|
|
316
|
+
minReadyupVersion: "0.42.0",
|
|
161
317
|
checklists: [repoChecklist, packagesChecklist]
|
|
162
318
|
});
|
|
163
319
|
function belongsInPackagesChecklist(workspace) {
|
|
@@ -166,7 +322,6 @@ function belongsInPackagesChecklist(workspace) {
|
|
|
166
322
|
function buildSessionCheck() {
|
|
167
323
|
return {
|
|
168
324
|
name: "npm session can answer trust queries",
|
|
169
|
-
skip: () => skipIfNothingPublishable(),
|
|
170
325
|
check: () => {
|
|
171
326
|
const capability = getCachedTrustCapability();
|
|
172
327
|
return capability.ok ? { ok: true } : { ok: false, detail: capability.detail };
|
|
@@ -247,135 +402,6 @@ function checkProvenanceMatchesVisibility() {
|
|
|
247
402
|
}
|
|
248
403
|
return classifyProvenanceSetting(content, visibility);
|
|
249
404
|
}
|
|
250
|
-
function classifyNpmAuth(result) {
|
|
251
|
-
if (result.exitOk) {
|
|
252
|
-
return { status: "authenticated" };
|
|
253
|
-
}
|
|
254
|
-
const error = readNpmError(result.stdout);
|
|
255
|
-
if (error === void 0) {
|
|
256
|
-
return { status: "unreachable", detail: "The npm registry query failed without a readable error payload" };
|
|
257
|
-
}
|
|
258
|
-
if (AUTH_ERROR_CODES.has(error.code)) {
|
|
259
|
-
return { status: "unauthenticated", detail: `The npm registry rejected the session (${error.code})` };
|
|
260
|
-
}
|
|
261
|
-
if (UNREACHABLE_ERROR_CODES.has(error.code)) {
|
|
262
|
-
return { status: "unreachable", detail: `Cannot reach the npm registry (${error.code})` };
|
|
263
|
-
}
|
|
264
|
-
return { status: "unreachable", detail: `The npm registry query failed (${error.code}): ${error.summary}` };
|
|
265
|
-
}
|
|
266
|
-
function classifyProvenanceSetting(workflowContent, visibility) {
|
|
267
|
-
if (workflowContent === void 0) {
|
|
268
|
-
return {
|
|
269
|
-
ok: false,
|
|
270
|
-
detail: "Cannot read .github/workflows/publish.yaml",
|
|
271
|
-
fix: "Check the file's permissions"
|
|
272
|
-
};
|
|
273
|
-
}
|
|
274
|
-
if (typeof visibility !== "string") {
|
|
275
|
-
return { ok: false, detail: visibility.detail, fix: NO_GITHUB_REMOTE_FIX };
|
|
276
|
-
}
|
|
277
|
-
if (visibility === "unknown") {
|
|
278
|
-
return {
|
|
279
|
-
ok: false,
|
|
280
|
-
detail: "The GitHub CLI could not report the repo's visibility",
|
|
281
|
-
fix: "Install and authenticate the GitHub CLI: gh auth login"
|
|
282
|
-
};
|
|
283
|
-
}
|
|
284
|
-
const provenance = hasProvenance(workflowContent);
|
|
285
|
-
if (visibility === "public" && !provenance) {
|
|
286
|
-
return {
|
|
287
|
-
ok: false,
|
|
288
|
-
detail: "The repo is public and publish.yaml does not set provenance: true",
|
|
289
|
-
fix: "Set provenance: true in .github/workflows/publish.yaml; public repos should generate provenance attestations"
|
|
290
|
-
};
|
|
291
|
-
}
|
|
292
|
-
if (visibility === "private" && provenance) {
|
|
293
|
-
return {
|
|
294
|
-
ok: false,
|
|
295
|
-
detail: "The repo is private and publish.yaml sets provenance: true",
|
|
296
|
-
fix: "Make the GitHub repo public; OIDC publishing with provenance requires a public repo"
|
|
297
|
-
};
|
|
298
|
-
}
|
|
299
|
-
return { ok: true };
|
|
300
|
-
}
|
|
301
|
-
function classifyTrustCapability(auth, probe) {
|
|
302
|
-
if (auth.status !== "authenticated") {
|
|
303
|
-
return { ok: false, detail: auth.detail };
|
|
304
|
-
}
|
|
305
|
-
return probe?.status === "unanswerable" ? { ok: false, detail: probe.detail } : { ok: true };
|
|
306
|
-
}
|
|
307
|
-
function classifyTrustQuery(result, expectedRepo, expectedFile) {
|
|
308
|
-
if (!result.exitOk) {
|
|
309
|
-
const error = readNpmError(result.stdout);
|
|
310
|
-
if (error === void 0) {
|
|
311
|
-
return { status: "error", detail: "The npm trust query failed without a readable error payload" };
|
|
312
|
-
}
|
|
313
|
-
if (error.code === "E404") {
|
|
314
|
-
return { status: "not-configured" };
|
|
315
|
-
}
|
|
316
|
-
if (AUTH_ERROR_CODES.has(error.code) || error.code === OTP_ERROR_CODE) {
|
|
317
|
-
return {
|
|
318
|
-
status: "unanswerable",
|
|
319
|
-
detail: `The npm session cannot answer trust queries (${error.code}): ${error.summary}`
|
|
320
|
-
};
|
|
321
|
-
}
|
|
322
|
-
if (UNREACHABLE_ERROR_CODES.has(error.code)) {
|
|
323
|
-
return { status: "unanswerable", detail: `Cannot reach the npm registry (${error.code})` };
|
|
324
|
-
}
|
|
325
|
-
return { status: "error", detail: `The npm trust query failed (${error.code}): ${error.summary}` };
|
|
326
|
-
}
|
|
327
|
-
const relationships = readTrustRelationships(result.stdout);
|
|
328
|
-
if (relationships === void 0) {
|
|
329
|
-
return { status: "error", detail: "The npm trust query returned a payload that this check cannot read" };
|
|
330
|
-
}
|
|
331
|
-
if (relationships.length === 0) {
|
|
332
|
-
return { status: "not-configured" };
|
|
333
|
-
}
|
|
334
|
-
if (!expectedRepo.ok) {
|
|
335
|
-
return {
|
|
336
|
-
status: "error",
|
|
337
|
-
detail: `Cannot compare the trusted publisher with this repo; found ${describeTrustRelationships(relationships)}`
|
|
338
|
-
};
|
|
339
|
-
}
|
|
340
|
-
const isMatch = relationships.some(
|
|
341
|
-
(relationship) => relationship.type === "github" && relationship.repository === expectedRepo.value && relationship.file === expectedFile
|
|
342
|
-
);
|
|
343
|
-
return isMatch ? { status: "configured" } : {
|
|
344
|
-
status: "mismatched",
|
|
345
|
-
detail: `Expected github ${expectedRepo.value} (${expectedFile}); found ${describeTrustRelationships(relationships)}`
|
|
346
|
-
};
|
|
347
|
-
}
|
|
348
|
-
function describeNpmPackageLookup(lookup) {
|
|
349
|
-
if (lookup.status === "published") {
|
|
350
|
-
return { ok: true };
|
|
351
|
-
}
|
|
352
|
-
if (lookup.status === "unpublished") {
|
|
353
|
-
return { ok: false, detail: "The npm registry does not list this package" };
|
|
354
|
-
}
|
|
355
|
-
return {
|
|
356
|
-
ok: false,
|
|
357
|
-
detail: lookup.detail,
|
|
358
|
-
fix: "Restore access to the npm registry, then run this check again"
|
|
359
|
-
};
|
|
360
|
-
}
|
|
361
|
-
function describeTrustedPublisher(result, packageName, ownerRepo) {
|
|
362
|
-
if (result.status === "configured") {
|
|
363
|
-
return { ok: true };
|
|
364
|
-
}
|
|
365
|
-
const detail = result.status === "not-configured" ? "The npm registry does not list any trusted publisher for this package" : result.detail;
|
|
366
|
-
return ownerRepo.ok ? { ok: false, detail, fix: formatTrustCommand(packageName, ownerRepo.value) } : { ok: false, detail: `${detail}. ${ownerRepo.detail}`, fix: NO_GITHUB_REMOTE_FIX };
|
|
367
|
-
}
|
|
368
|
-
function describeTrustRelationships(relationships) {
|
|
369
|
-
return relationships.map((relationship) => {
|
|
370
|
-
const type = typeof relationship.type === "string" ? relationship.type : "(unknown)";
|
|
371
|
-
const repository = typeof relationship.repository === "string" ? relationship.repository : "(unknown)";
|
|
372
|
-
const file = typeof relationship.file === "string" ? relationship.file : "(unknown)";
|
|
373
|
-
return `${type} ${repository} (${file})`;
|
|
374
|
-
}).join(", ");
|
|
375
|
-
}
|
|
376
|
-
function formatTrustCommand(packageName, ownerRepo) {
|
|
377
|
-
return `Run: npm trust github ${packageName} --repo ${ownerRepo} --file ${PUBLISH_WORKFLOW_FILE}`;
|
|
378
|
-
}
|
|
379
405
|
var getCachedNpmAuthStatus = /* @__PURE__ */ (() => {
|
|
380
406
|
let cached;
|
|
381
407
|
return () => cached ??= classifyNpmAuth(runNpmJson(["whoami", "--json"]));
|
|
@@ -422,11 +448,6 @@ function isRepoPrivate(ownerRepo) {
|
|
|
422
448
|
}).trim();
|
|
423
449
|
return result === "true";
|
|
424
450
|
}
|
|
425
|
-
function parseGitHubOwnerRepo(url) {
|
|
426
|
-
const match = /git@github\.com:(.+?)(?:\.git)?$/.exec(url) ?? /github\.com\/(.+?)(?:\.git)?$/.exec(url);
|
|
427
|
-
const ownerRepo = match?.[1];
|
|
428
|
-
return ownerRepo === void 0 ? { ok: false, detail: `The origin remote does not point to GitHub: ${url}` } : { ok: true, value: ownerRepo };
|
|
429
|
-
}
|
|
430
451
|
function probeTrustQuery() {
|
|
431
452
|
const probeName = selectProbeName();
|
|
432
453
|
return probeName === void 0 ? void 0 : getTrustQueryResult(probeName);
|
|
@@ -435,21 +456,6 @@ function readPublishRegistry(workspace) {
|
|
|
435
456
|
const registry = getJsonValue(workspace.packageJson, "publishConfig", "registry");
|
|
436
457
|
return typeof registry === "string" ? registry : void 0;
|
|
437
458
|
}
|
|
438
|
-
function readTrustRelationships(stdout) {
|
|
439
|
-
let parsed;
|
|
440
|
-
try {
|
|
441
|
-
parsed = JSON.parse(stdout);
|
|
442
|
-
} catch {
|
|
443
|
-
return void 0;
|
|
444
|
-
}
|
|
445
|
-
if (Array.isArray(parsed)) {
|
|
446
|
-
return parsed.filter((entry) => isRecord2(entry) && "type" in entry);
|
|
447
|
-
}
|
|
448
|
-
if (!isRecord2(parsed)) {
|
|
449
|
-
return void 0;
|
|
450
|
-
}
|
|
451
|
-
return "type" in parsed ? [parsed] : [];
|
|
452
|
-
}
|
|
453
459
|
function resolveOwnerRepo() {
|
|
454
460
|
let url;
|
|
455
461
|
try {
|
|
@@ -477,15 +483,8 @@ function skipIfNotPublishable(workspace) {
|
|
|
477
483
|
}
|
|
478
484
|
export {
|
|
479
485
|
buildWorkspaceCheck,
|
|
480
|
-
classifyNpmAuth,
|
|
481
|
-
classifyProvenanceSetting,
|
|
482
|
-
classifyTrustCapability,
|
|
483
|
-
classifyTrustQuery,
|
|
484
486
|
npm_auto_publish_default as default,
|
|
485
|
-
describeNpmPackageLookup,
|
|
486
|
-
describeTrustedPublisher,
|
|
487
487
|
packagesChecklist,
|
|
488
|
-
parseGitHubOwnerRepo,
|
|
489
488
|
selectProbeName,
|
|
490
489
|
skipIfNotPublishable,
|
|
491
490
|
skipIfNothingPublishable
|
package/.readyup/manifest.json
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
"checklist": "release-kit",
|
|
8
8
|
"checks": [
|
|
9
9
|
"@williamthorsen/release-kit in devDependencies",
|
|
10
|
-
"@williamthorsen/release-kit >= 14.2.
|
|
10
|
+
"@williamthorsen/release-kit >= 14.2.3",
|
|
11
11
|
"release.yaml workflow exists",
|
|
12
12
|
"release.yaml matches template",
|
|
13
13
|
"release.yaml does not reference deprecated tag ref",
|
|
@@ -43,12 +43,27 @@
|
|
|
43
43
|
"esbuildVersion": "0.28.2",
|
|
44
44
|
"inputs": [
|
|
45
45
|
{
|
|
46
|
-
"hash": "
|
|
46
|
+
"hash": "ad3666b8",
|
|
47
47
|
"kind": "module",
|
|
48
48
|
"path": "kits/default.ts"
|
|
49
49
|
},
|
|
50
50
|
{
|
|
51
|
-
"hash": "
|
|
51
|
+
"hash": "45fc235f",
|
|
52
|
+
"kind": "module",
|
|
53
|
+
"path": "lib/changelog-checks.ts"
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
"hash": "be2c2cb3",
|
|
57
|
+
"kind": "module",
|
|
58
|
+
"path": "lib/config-checks.ts"
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
"hash": "290731d6",
|
|
62
|
+
"kind": "module",
|
|
63
|
+
"path": "lib/workflow-hashes.ts"
|
|
64
|
+
},
|
|
65
|
+
{
|
|
66
|
+
"hash": "b89073b8",
|
|
52
67
|
"kind": "inline",
|
|
53
68
|
"path": "../package.json",
|
|
54
69
|
"paths": [
|
|
@@ -83,10 +98,10 @@
|
|
|
83
98
|
],
|
|
84
99
|
"name": "default",
|
|
85
100
|
"path": "kits/default.js",
|
|
86
|
-
"readyupVersion": "0.
|
|
101
|
+
"readyupVersion": "0.42.0",
|
|
87
102
|
"source": "kits/default.ts",
|
|
88
|
-
"sourceHash": "
|
|
89
|
-
"targetHash": "
|
|
103
|
+
"sourceHash": "ad3666b8",
|
|
104
|
+
"targetHash": "9f5a50d9"
|
|
90
105
|
},
|
|
91
106
|
{
|
|
92
107
|
"checklistChecks": [
|
|
@@ -104,13 +119,7 @@
|
|
|
104
119
|
"checks": [
|
|
105
120
|
"packageManager field starts with \"pnpm\"",
|
|
106
121
|
"At least one workspace discovered",
|
|
107
|
-
"
|
|
108
|
-
"@williamthorsen/release-kit",
|
|
109
|
-
"repository field exists",
|
|
110
|
-
"publishConfig.access is \"public\"",
|
|
111
|
-
"published to npm",
|
|
112
|
-
"trusted publisher configured",
|
|
113
|
-
"files field exists"
|
|
122
|
+
"Repo publishes at least one package"
|
|
114
123
|
]
|
|
115
124
|
}
|
|
116
125
|
],
|
|
@@ -121,10 +130,15 @@
|
|
|
121
130
|
"esbuildVersion": "0.28.2",
|
|
122
131
|
"inputs": [
|
|
123
132
|
{
|
|
124
|
-
"hash": "
|
|
133
|
+
"hash": "682fdd4a",
|
|
125
134
|
"kind": "module",
|
|
126
135
|
"path": "kits/npm-auto-publish.ts"
|
|
127
136
|
},
|
|
137
|
+
{
|
|
138
|
+
"hash": "05215737",
|
|
139
|
+
"kind": "module",
|
|
140
|
+
"path": "lib/npm-trust.ts"
|
|
141
|
+
},
|
|
128
142
|
{
|
|
129
143
|
"hash": "d360febf",
|
|
130
144
|
"kind": "module",
|
|
@@ -143,10 +157,10 @@
|
|
|
143
157
|
],
|
|
144
158
|
"name": "npm-auto-publish",
|
|
145
159
|
"path": "kits/npm-auto-publish.js",
|
|
146
|
-
"readyupVersion": "0.
|
|
160
|
+
"readyupVersion": "0.42.0",
|
|
147
161
|
"source": "kits/npm-auto-publish.ts",
|
|
148
|
-
"sourceHash": "
|
|
149
|
-
"targetHash": "
|
|
162
|
+
"sourceHash": "682fdd4a",
|
|
163
|
+
"targetHash": "04adb134"
|
|
150
164
|
}
|
|
151
165
|
]
|
|
152
166
|
}
|
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,22 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
|
|
5
|
+
## 14.2.3 โ 2026-10-18
|
|
6
|
+
|
|
7
|
+
### ๐ Bug fixes
|
|
8
|
+
|
|
9
|
+
- Fixes the issue that the manifest of the `npm-auto-publish` kit recorded a different list of checks depending on the directory from which `rdy compile` ran, by declaring one fixed check, "Repo publishes at least one package", under which `rdy run` builds the npm session check and the per-package rows. (#1081)
|
|
10
|
+
|
|
11
|
+
### โป๏ธ Refactoring
|
|
12
|
+
|
|
13
|
+
- Splits `types.ts`, `loadConfig.ts`, `changelogOverrides.ts`, and `buildChangelogEntries.ts` to bring each under the 300-line `max-lines` limit, moving the config zod schemas into `configSchema.ts`, config merging into `mergeConfig.ts`, the cross-target checks into `monorepoConfigAssertions.ts`, override parsing, application, and repo-wide validation into `loadChangelogOverrides.ts`, `applyChangelogOverrides.ts`, and `validateAllChangelogOverrides.ts`, and changelog-item construction into `buildChangelogItem.ts`. (#1067)
|
|
14
|
+
- Splits the `release-kit` bin, the `prepare` pipeline (`prepareCommand`, `prepareTarget`, `releasePrepareTargets`, and `reportPrepare`), and the `default` and `npm-auto-publish` readyup kits into smaller modules under `src`, `src/help`, and `.readyup/lib`, and recompiles the kit bundles without changing their check lists. (#1069)
|
|
15
|
+
- Rewrites the code that the new and widened rules in `eslint-plugin-unicorn` 78 report, mostly by changing `flatMap` callbacks to return a single value rather than a one-element array. (#1072)
|
|
16
|
+
|
|
17
|
+
### ๐งช Tests
|
|
18
|
+
|
|
19
|
+
- Splits the `release-kit` unit tests for `releasePrepareTargets`, `reportPrepare`, `prepareCommand`, `publishCommand`, `parseCommitMessage`, and `validateConfig` into `<subject>.<aspect>.unit.test.ts` files that each stay under the `max-lines` limit, and moves the mocks and fixtures that the split files share into modules under `src/test-utils/`. (#1066)
|
|
20
|
+
|
|
5
21
|
## 14.2.2 โ 2026-10-17
|
|
6
22
|
|
|
7
23
|
### ๐ฆ Dependencies
|
package/README.md
CHANGED
|
@@ -6,7 +6,13 @@ Version-bumping and changelog-generation toolkit for release workflows.
|
|
|
6
6
|
|
|
7
7
|
Provides a self-contained CLI that auto-discovers workspaces from `pnpm-workspace.yaml`, parses conventional commits, determines version bumps, updates `package.json` files, and generates changelogs from the same commit history that decides each bump (with optional [editorial overrides](docs/editorial-overrides.md)).
|
|
8
8
|
|
|
9
|
-
<!-- section:release-notes
|
|
9
|
+
<!-- section:release-notes -->
|
|
10
|
+
## Release notes โ v14.2.3 (2026-10-18)
|
|
11
|
+
|
|
12
|
+
### ๐ Bug fixes
|
|
13
|
+
|
|
14
|
+
- Fixes the issue that the manifest of the `npm-auto-publish` kit recorded a different list of checks depending on the directory from which `rdy compile` ran, by declaring one fixed check, "Repo publishes at least one package", under which `rdy run` builds the npm session check and the per-package rows. (#1081)
|
|
15
|
+
<!-- /section:release-notes -->
|
|
10
16
|
|
|
11
17
|
## Installation
|
|
12
18
|
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import type { ChangelogEntry, ChangelogOverride } from './types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Applies overrides to changelog entries, returning new entries without mutating the input.
|
|
4
|
+
*
|
|
5
|
+
* Each key's hash prefix is matched against the distinct `ChangelogItem.hash` values:
|
|
6
|
+
* - No match: The key is unmatched in this batch, and this function doesn't emit a warning.
|
|
7
|
+
* - One match: A bare key resolves to every item of that commit, and an ordinal key `<hash>:<n>` to the items whose
|
|
8
|
+
* `entry` is `n`. A key that doesn't resolve to any item is unmatched, so an ordinal key on a title-derived item
|
|
9
|
+
* goes stale.
|
|
10
|
+
* - Several matches: an error (ambiguous prefix).
|
|
11
|
+
*
|
|
12
|
+
* Two more conditions are errors, and the keys involved apply nowhere: a bare key that sets `description` or `body` on a
|
|
13
|
+
* commit with several items, and two keys that resolve to the same item.
|
|
14
|
+
*
|
|
15
|
+
* `matchedKeys` lists the keys that resolved to at least one item without error. The caller computes stale-key
|
|
16
|
+
* warnings, because in a monorepo a key may target a commit in another workspace: A key unmatched in one batch is not
|
|
17
|
+
* necessarily stale.
|
|
18
|
+
*
|
|
19
|
+
* An override whose audience is `'skip'` removes its item, and a section left empty is dropped; an entry left without
|
|
20
|
+
* sections is kept. An item without a `hash`, such as a synthetic propagation item, passes through unmatched. Errors
|
|
21
|
+
* are returned rather than thrown, and the caller decides whether to abort.
|
|
22
|
+
*/
|
|
23
|
+
export declare function applyChangelogOverrides(entries: ChangelogEntry[], overrides: Map<string, ChangelogOverride>): {
|
|
24
|
+
entries: ChangelogEntry[];
|
|
25
|
+
warnings: string[];
|
|
26
|
+
errors: string[];
|
|
27
|
+
matchedKeys: string[];
|
|
28
|
+
};
|
|
29
|
+
/** Formats the warning for an override key that did not match any item in the changelog. */
|
|
30
|
+
export declare function formatStaleOverrideKeyWarning(key: string): string;
|
|
31
|
+
/** Collects, for each hash, the distinct `entry` positions of the items that have it. */
|
|
32
|
+
export declare function indexItemPositions(items: readonly {
|
|
33
|
+
hash?: string | undefined;
|
|
34
|
+
entry?: number | undefined;
|
|
35
|
+
}[]): Map<string, Set<number | undefined>>;
|
|
36
|
+
/**
|
|
37
|
+
* Resolves one override key against the commits' entry positions. `positions` lists the targeted items' `entry` values,
|
|
38
|
+
* ascending, with `undefined` standing for a title-derived item; it is empty when the key doesn't target any item of
|
|
39
|
+
* the commit.
|
|
40
|
+
*/
|
|
41
|
+
export declare function resolveOverrideKey(overrideKey: string, positionsByHash: Map<string, Set<number | undefined>>): {
|
|
42
|
+
kind: 'none';
|
|
43
|
+
} | {
|
|
44
|
+
kind: 'ambiguous';
|
|
45
|
+
hashes: string[];
|
|
46
|
+
} | {
|
|
47
|
+
kind: 'items';
|
|
48
|
+
hash: string;
|
|
49
|
+
positions: (number | undefined)[];
|
|
50
|
+
};
|