@releasekit/publish 0.3.0-next.3 → 0.3.0
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 +2 -0
- package/dist/cli.js +0 -62
- package/package.json +14 -13
- package/dist/chunk-GOBII36Q.js +0 -1324
- package/dist/cli.cjs +0 -1369
- package/dist/cli.d.cts +0 -1
- package/dist/cli.d.ts +0 -1
- package/dist/index.cjs +0 -1380
- package/dist/index.d.cts +0 -173
- package/dist/index.d.ts +0 -173
- package/dist/index.js +0 -38
package/dist/chunk-GOBII36Q.js
DELETED
|
@@ -1,1324 +0,0 @@
|
|
|
1
|
-
// src/config.ts
|
|
2
|
-
import { loadPublishConfig } from "@releasekit/config";
|
|
3
|
-
|
|
4
|
-
// src/types.ts
|
|
5
|
-
function getDefaultConfig() {
|
|
6
|
-
return {
|
|
7
|
-
npm: {
|
|
8
|
-
enabled: true,
|
|
9
|
-
auth: "auto",
|
|
10
|
-
provenance: true,
|
|
11
|
-
access: "public",
|
|
12
|
-
registry: "https://registry.npmjs.org",
|
|
13
|
-
copyFiles: ["LICENSE"],
|
|
14
|
-
tag: "latest"
|
|
15
|
-
},
|
|
16
|
-
cargo: {
|
|
17
|
-
enabled: false,
|
|
18
|
-
noVerify: false,
|
|
19
|
-
publishOrder: [],
|
|
20
|
-
clean: false
|
|
21
|
-
},
|
|
22
|
-
git: {
|
|
23
|
-
push: true,
|
|
24
|
-
pushMethod: "auto",
|
|
25
|
-
remote: "origin",
|
|
26
|
-
branch: "main",
|
|
27
|
-
httpsTokenEnv: void 0,
|
|
28
|
-
skipHooks: false
|
|
29
|
-
},
|
|
30
|
-
githubRelease: {
|
|
31
|
-
enabled: true,
|
|
32
|
-
draft: true,
|
|
33
|
-
perPackage: true,
|
|
34
|
-
prerelease: "auto",
|
|
35
|
-
releaseNotes: "auto"
|
|
36
|
-
},
|
|
37
|
-
verify: {
|
|
38
|
-
npm: {
|
|
39
|
-
enabled: true,
|
|
40
|
-
maxAttempts: 5,
|
|
41
|
-
initialDelay: 15e3,
|
|
42
|
-
backoffMultiplier: 2
|
|
43
|
-
},
|
|
44
|
-
cargo: {
|
|
45
|
-
enabled: true,
|
|
46
|
-
maxAttempts: 10,
|
|
47
|
-
initialDelay: 3e4,
|
|
48
|
-
backoffMultiplier: 2
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
};
|
|
52
|
-
}
|
|
53
|
-
function toPublishConfig(config) {
|
|
54
|
-
const defaults = getDefaultConfig();
|
|
55
|
-
if (!config) return defaults;
|
|
56
|
-
return {
|
|
57
|
-
npm: {
|
|
58
|
-
enabled: config.npm?.enabled ?? defaults.npm.enabled,
|
|
59
|
-
auth: config.npm?.auth ?? defaults.npm.auth,
|
|
60
|
-
provenance: config.npm?.provenance ?? defaults.npm.provenance,
|
|
61
|
-
access: config.npm?.access ?? defaults.npm.access,
|
|
62
|
-
registry: config.npm?.registry ?? defaults.npm.registry,
|
|
63
|
-
copyFiles: config.npm?.copyFiles ?? defaults.npm.copyFiles,
|
|
64
|
-
tag: config.npm?.tag ?? defaults.npm.tag
|
|
65
|
-
},
|
|
66
|
-
cargo: {
|
|
67
|
-
enabled: config.cargo?.enabled ?? defaults.cargo.enabled,
|
|
68
|
-
noVerify: config.cargo?.noVerify ?? defaults.cargo.noVerify,
|
|
69
|
-
publishOrder: config.cargo?.publishOrder ?? defaults.cargo.publishOrder,
|
|
70
|
-
clean: config.cargo?.clean ?? defaults.cargo.clean
|
|
71
|
-
},
|
|
72
|
-
git: config.git ? {
|
|
73
|
-
push: config.git.push ?? defaults.git.push,
|
|
74
|
-
pushMethod: config.git.pushMethod ?? defaults.git.pushMethod,
|
|
75
|
-
remote: config.git.remote ?? defaults.git.remote,
|
|
76
|
-
branch: config.git.branch ?? defaults.git.branch,
|
|
77
|
-
httpsTokenEnv: config.git.httpsTokenEnv ?? defaults.git.httpsTokenEnv,
|
|
78
|
-
skipHooks: config.git.skipHooks ?? defaults.git.skipHooks
|
|
79
|
-
} : defaults.git,
|
|
80
|
-
githubRelease: {
|
|
81
|
-
enabled: config.githubRelease?.enabled ?? defaults.githubRelease.enabled,
|
|
82
|
-
draft: config.githubRelease?.draft ?? defaults.githubRelease.draft,
|
|
83
|
-
perPackage: config.githubRelease?.perPackage ?? defaults.githubRelease.perPackage,
|
|
84
|
-
prerelease: config.githubRelease?.prerelease ?? defaults.githubRelease.prerelease,
|
|
85
|
-
releaseNotes: config.githubRelease?.releaseNotes ?? defaults.githubRelease.releaseNotes
|
|
86
|
-
},
|
|
87
|
-
verify: {
|
|
88
|
-
npm: {
|
|
89
|
-
enabled: config.verify?.npm?.enabled ?? defaults.verify.npm.enabled,
|
|
90
|
-
maxAttempts: config.verify?.npm?.maxAttempts ?? defaults.verify.npm.maxAttempts,
|
|
91
|
-
initialDelay: config.verify?.npm?.initialDelay ?? defaults.verify.npm.initialDelay,
|
|
92
|
-
backoffMultiplier: config.verify?.npm?.backoffMultiplier ?? defaults.verify.npm.backoffMultiplier
|
|
93
|
-
},
|
|
94
|
-
cargo: {
|
|
95
|
-
enabled: config.verify?.cargo?.enabled ?? defaults.verify.cargo.enabled,
|
|
96
|
-
maxAttempts: config.verify?.cargo?.maxAttempts ?? defaults.verify.cargo.maxAttempts,
|
|
97
|
-
initialDelay: config.verify?.cargo?.initialDelay ?? defaults.verify.cargo.initialDelay,
|
|
98
|
-
backoffMultiplier: config.verify?.cargo?.backoffMultiplier ?? defaults.verify.cargo.backoffMultiplier
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
};
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
// src/config.ts
|
|
105
|
-
function loadConfig(options) {
|
|
106
|
-
const baseConfig = loadPublishConfig(options);
|
|
107
|
-
return toPublishConfig(baseConfig);
|
|
108
|
-
}
|
|
109
|
-
function getDefaultConfig2() {
|
|
110
|
-
return toPublishConfig(void 0);
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
// src/errors/index.ts
|
|
114
|
-
import { ReleaseKitError } from "@releasekit/core";
|
|
115
|
-
var BasePublishError = class _BasePublishError extends ReleaseKitError {
|
|
116
|
-
code;
|
|
117
|
-
suggestions;
|
|
118
|
-
constructor(message, code, suggestions) {
|
|
119
|
-
super(message);
|
|
120
|
-
this.code = code;
|
|
121
|
-
this.suggestions = suggestions ?? [];
|
|
122
|
-
}
|
|
123
|
-
static isPublishError(error) {
|
|
124
|
-
return error instanceof _BasePublishError;
|
|
125
|
-
}
|
|
126
|
-
};
|
|
127
|
-
var PublishError = class extends BasePublishError {
|
|
128
|
-
};
|
|
129
|
-
var PipelineError = class extends BasePublishError {
|
|
130
|
-
partialOutput;
|
|
131
|
-
failedStage;
|
|
132
|
-
cause;
|
|
133
|
-
constructor(message, failedStage, partialOutput, cause) {
|
|
134
|
-
super(message, "PIPELINE_STAGE_ERROR" /* PIPELINE_STAGE_ERROR */, [
|
|
135
|
-
"Check the partial output for results from stages that completed before the failure",
|
|
136
|
-
"Use --json to get structured error output with partial results"
|
|
137
|
-
]);
|
|
138
|
-
this.failedStage = failedStage;
|
|
139
|
-
this.partialOutput = partialOutput;
|
|
140
|
-
this.cause = cause;
|
|
141
|
-
}
|
|
142
|
-
};
|
|
143
|
-
var PublishErrorCode = /* @__PURE__ */ ((PublishErrorCode2) => {
|
|
144
|
-
PublishErrorCode2["INPUT_PARSE_ERROR"] = "INPUT_PARSE_ERROR";
|
|
145
|
-
PublishErrorCode2["INPUT_VALIDATION_ERROR"] = "INPUT_VALIDATION_ERROR";
|
|
146
|
-
PublishErrorCode2["CONFIG_ERROR"] = "CONFIG_ERROR";
|
|
147
|
-
PublishErrorCode2["GIT_COMMIT_ERROR"] = "GIT_COMMIT_ERROR";
|
|
148
|
-
PublishErrorCode2["GIT_TAG_ERROR"] = "GIT_TAG_ERROR";
|
|
149
|
-
PublishErrorCode2["GIT_PUSH_ERROR"] = "GIT_PUSH_ERROR";
|
|
150
|
-
PublishErrorCode2["NPM_PUBLISH_ERROR"] = "NPM_PUBLISH_ERROR";
|
|
151
|
-
PublishErrorCode2["NPM_AUTH_ERROR"] = "NPM_AUTH_ERROR";
|
|
152
|
-
PublishErrorCode2["CARGO_PUBLISH_ERROR"] = "CARGO_PUBLISH_ERROR";
|
|
153
|
-
PublishErrorCode2["CARGO_AUTH_ERROR"] = "CARGO_AUTH_ERROR";
|
|
154
|
-
PublishErrorCode2["VERIFICATION_FAILED"] = "VERIFICATION_FAILED";
|
|
155
|
-
PublishErrorCode2["GITHUB_RELEASE_ERROR"] = "GITHUB_RELEASE_ERROR";
|
|
156
|
-
PublishErrorCode2["FILE_COPY_ERROR"] = "FILE_COPY_ERROR";
|
|
157
|
-
PublishErrorCode2["CARGO_TOML_ERROR"] = "CARGO_TOML_ERROR";
|
|
158
|
-
PublishErrorCode2["PIPELINE_STAGE_ERROR"] = "PIPELINE_STAGE_ERROR";
|
|
159
|
-
return PublishErrorCode2;
|
|
160
|
-
})(PublishErrorCode || {});
|
|
161
|
-
function createPublishError(code, details) {
|
|
162
|
-
const messages = {
|
|
163
|
-
["INPUT_PARSE_ERROR" /* INPUT_PARSE_ERROR */]: "Failed to parse version output",
|
|
164
|
-
["INPUT_VALIDATION_ERROR" /* INPUT_VALIDATION_ERROR */]: "Version output validation failed",
|
|
165
|
-
["CONFIG_ERROR" /* CONFIG_ERROR */]: "Invalid publish configuration",
|
|
166
|
-
["GIT_COMMIT_ERROR" /* GIT_COMMIT_ERROR */]: "Failed to create git commit",
|
|
167
|
-
["GIT_TAG_ERROR" /* GIT_TAG_ERROR */]: "Failed to create git tag",
|
|
168
|
-
["GIT_PUSH_ERROR" /* GIT_PUSH_ERROR */]: "Failed to push to remote",
|
|
169
|
-
["NPM_PUBLISH_ERROR" /* NPM_PUBLISH_ERROR */]: "Failed to publish to npm",
|
|
170
|
-
["NPM_AUTH_ERROR" /* NPM_AUTH_ERROR */]: "NPM authentication failed",
|
|
171
|
-
["CARGO_PUBLISH_ERROR" /* CARGO_PUBLISH_ERROR */]: "Failed to publish to crates.io",
|
|
172
|
-
["CARGO_AUTH_ERROR" /* CARGO_AUTH_ERROR */]: "Cargo authentication failed",
|
|
173
|
-
["VERIFICATION_FAILED" /* VERIFICATION_FAILED */]: "Package verification failed",
|
|
174
|
-
["GITHUB_RELEASE_ERROR" /* GITHUB_RELEASE_ERROR */]: "Failed to create GitHub release",
|
|
175
|
-
["FILE_COPY_ERROR" /* FILE_COPY_ERROR */]: "Failed to copy files",
|
|
176
|
-
["CARGO_TOML_ERROR" /* CARGO_TOML_ERROR */]: "Failed to update Cargo.toml",
|
|
177
|
-
["PIPELINE_STAGE_ERROR" /* PIPELINE_STAGE_ERROR */]: "Pipeline stage failed"
|
|
178
|
-
};
|
|
179
|
-
const suggestions = {
|
|
180
|
-
["INPUT_PARSE_ERROR" /* INPUT_PARSE_ERROR */]: [
|
|
181
|
-
"Ensure the input is valid JSON from @releasekit/version --json",
|
|
182
|
-
"Check that stdin is piped correctly or --input path is valid"
|
|
183
|
-
],
|
|
184
|
-
["INPUT_VALIDATION_ERROR" /* INPUT_VALIDATION_ERROR */]: [
|
|
185
|
-
"Ensure the input matches the expected VersionOutput schema",
|
|
186
|
-
"Run @releasekit/version with --json to generate valid output"
|
|
187
|
-
],
|
|
188
|
-
["CONFIG_ERROR" /* CONFIG_ERROR */]: [
|
|
189
|
-
"Validate publish.config.json syntax",
|
|
190
|
-
"Check configuration against the schema",
|
|
191
|
-
"Review documentation for valid configuration options"
|
|
192
|
-
],
|
|
193
|
-
["GIT_COMMIT_ERROR" /* GIT_COMMIT_ERROR */]: [
|
|
194
|
-
"Ensure there are staged changes to commit",
|
|
195
|
-
"Check git user.name and user.email are configured",
|
|
196
|
-
"Verify you have write access to the repository"
|
|
197
|
-
],
|
|
198
|
-
["GIT_TAG_ERROR" /* GIT_TAG_ERROR */]: [
|
|
199
|
-
"Check if the tag already exists: git tag -l <tag>",
|
|
200
|
-
"Delete existing tag if needed: git tag -d <tag>"
|
|
201
|
-
],
|
|
202
|
-
["GIT_PUSH_ERROR" /* GIT_PUSH_ERROR */]: [
|
|
203
|
-
"Verify remote repository access",
|
|
204
|
-
"Check SSH key or deploy key configuration",
|
|
205
|
-
"Ensure the branch is not protected or you have push access"
|
|
206
|
-
],
|
|
207
|
-
["NPM_PUBLISH_ERROR" /* NPM_PUBLISH_ERROR */]: [
|
|
208
|
-
"Check npm registry availability",
|
|
209
|
-
"Verify package name is not already taken by another owner",
|
|
210
|
-
"Ensure package version has not already been published"
|
|
211
|
-
],
|
|
212
|
-
["NPM_AUTH_ERROR" /* NPM_AUTH_ERROR */]: [
|
|
213
|
-
"Set NPM_TOKEN environment variable for token-based auth",
|
|
214
|
-
"Enable OIDC trusted publishing in GitHub Actions for provenance",
|
|
215
|
-
"Run npm login for local publishing"
|
|
216
|
-
],
|
|
217
|
-
["CARGO_PUBLISH_ERROR" /* CARGO_PUBLISH_ERROR */]: [
|
|
218
|
-
"Check crates.io registry availability",
|
|
219
|
-
"Verify crate name ownership on crates.io",
|
|
220
|
-
"Ensure Cargo.toml metadata is complete (description, license, etc.)"
|
|
221
|
-
],
|
|
222
|
-
["CARGO_AUTH_ERROR" /* CARGO_AUTH_ERROR */]: [
|
|
223
|
-
"Set CARGO_REGISTRY_TOKEN environment variable",
|
|
224
|
-
"Generate a token at https://crates.io/settings/tokens"
|
|
225
|
-
],
|
|
226
|
-
["VERIFICATION_FAILED" /* VERIFICATION_FAILED */]: [
|
|
227
|
-
"Registry propagation may take longer than expected",
|
|
228
|
-
"Try increasing verify.maxAttempts or verify.initialDelay in config",
|
|
229
|
-
"Check registry status pages for outages"
|
|
230
|
-
],
|
|
231
|
-
["GITHUB_RELEASE_ERROR" /* GITHUB_RELEASE_ERROR */]: [
|
|
232
|
-
"Ensure gh CLI is installed and authenticated",
|
|
233
|
-
"Verify GITHUB_TOKEN has contents:write permission",
|
|
234
|
-
"Check that the tag exists in the remote repository"
|
|
235
|
-
],
|
|
236
|
-
["FILE_COPY_ERROR" /* FILE_COPY_ERROR */]: ["Verify the source file exists in the project root", "Check file permissions"],
|
|
237
|
-
["CARGO_TOML_ERROR" /* CARGO_TOML_ERROR */]: [
|
|
238
|
-
"Ensure Cargo.toml exists and is valid TOML",
|
|
239
|
-
"Check that the [package] section has a version field"
|
|
240
|
-
],
|
|
241
|
-
["PIPELINE_STAGE_ERROR" /* PIPELINE_STAGE_ERROR */]: [
|
|
242
|
-
"Check the partial output for results from stages that completed before the failure",
|
|
243
|
-
"Use --json to get structured error output with partial results"
|
|
244
|
-
]
|
|
245
|
-
};
|
|
246
|
-
const baseMessage = messages[code];
|
|
247
|
-
const fullMessage = details ? `${baseMessage}: ${details}` : baseMessage;
|
|
248
|
-
return new PublishError(fullMessage, code, suggestions[code]);
|
|
249
|
-
}
|
|
250
|
-
|
|
251
|
-
// src/utils/exec.ts
|
|
252
|
-
import { execFile } from "child_process";
|
|
253
|
-
import { debug, info } from "@releasekit/core";
|
|
254
|
-
function redactArg(arg) {
|
|
255
|
-
try {
|
|
256
|
-
const url = new URL(arg);
|
|
257
|
-
if (url.username || url.password) {
|
|
258
|
-
url.username = url.username ? "***" : "";
|
|
259
|
-
url.password = url.password ? "***" : "";
|
|
260
|
-
return url.toString();
|
|
261
|
-
}
|
|
262
|
-
} catch {
|
|
263
|
-
}
|
|
264
|
-
return arg;
|
|
265
|
-
}
|
|
266
|
-
async function execCommand(file, args, options = {}) {
|
|
267
|
-
const displayCommand = options.label ?? [file, ...args.map(redactArg)].join(" ");
|
|
268
|
-
if (options.dryRun) {
|
|
269
|
-
info(`[DRY RUN] Would execute: ${displayCommand}`);
|
|
270
|
-
return { stdout: "", stderr: "", exitCode: 0 };
|
|
271
|
-
}
|
|
272
|
-
debug(`Executing: ${displayCommand}`);
|
|
273
|
-
return new Promise((resolve5, reject) => {
|
|
274
|
-
execFile(
|
|
275
|
-
file,
|
|
276
|
-
args,
|
|
277
|
-
{
|
|
278
|
-
maxBuffer: 1024 * 1024 * 10,
|
|
279
|
-
cwd: options.cwd,
|
|
280
|
-
env: options.env ? { ...process.env, ...options.env } : void 0
|
|
281
|
-
},
|
|
282
|
-
(error, stdout, stderr) => {
|
|
283
|
-
if (error) {
|
|
284
|
-
reject(
|
|
285
|
-
Object.assign(new Error(error.message), {
|
|
286
|
-
stdout: stdout.toString(),
|
|
287
|
-
stderr: stderr.toString(),
|
|
288
|
-
exitCode: error.code ?? 1
|
|
289
|
-
})
|
|
290
|
-
);
|
|
291
|
-
} else {
|
|
292
|
-
resolve5({
|
|
293
|
-
stdout: stdout.toString(),
|
|
294
|
-
stderr: stderr.toString(),
|
|
295
|
-
exitCode: 0
|
|
296
|
-
});
|
|
297
|
-
}
|
|
298
|
-
}
|
|
299
|
-
);
|
|
300
|
-
});
|
|
301
|
-
}
|
|
302
|
-
async function execCommandSafe(file, args, options = {}) {
|
|
303
|
-
try {
|
|
304
|
-
return await execCommand(file, args, options);
|
|
305
|
-
} catch (error) {
|
|
306
|
-
if (error && typeof error === "object" && "stdout" in error) {
|
|
307
|
-
const execError = error;
|
|
308
|
-
return {
|
|
309
|
-
stdout: execError.stdout ?? "",
|
|
310
|
-
stderr: execError.stderr ?? "",
|
|
311
|
-
exitCode: execError.exitCode ?? 1
|
|
312
|
-
};
|
|
313
|
-
}
|
|
314
|
-
return { stdout: "", stderr: error instanceof Error ? error.message : String(error), exitCode: 1 };
|
|
315
|
-
}
|
|
316
|
-
}
|
|
317
|
-
|
|
318
|
-
// src/utils/auth.ts
|
|
319
|
-
function detectNpmAuth() {
|
|
320
|
-
if (process.env.ACTIONS_ID_TOKEN_REQUEST_URL) {
|
|
321
|
-
return "oidc";
|
|
322
|
-
}
|
|
323
|
-
if (process.env.NPM_TOKEN || process.env.NODE_AUTH_TOKEN) {
|
|
324
|
-
return "token";
|
|
325
|
-
}
|
|
326
|
-
return null;
|
|
327
|
-
}
|
|
328
|
-
function hasCargoAuth() {
|
|
329
|
-
return !!process.env.CARGO_REGISTRY_TOKEN;
|
|
330
|
-
}
|
|
331
|
-
async function detectGitPushMethod(remote, cwd) {
|
|
332
|
-
const result = await execCommand("git", ["remote", "get-url", remote], { cwd });
|
|
333
|
-
const url = result.stdout.trim();
|
|
334
|
-
if (url.startsWith("git@") || url.startsWith("ssh://")) {
|
|
335
|
-
return "ssh";
|
|
336
|
-
}
|
|
337
|
-
return "https";
|
|
338
|
-
}
|
|
339
|
-
|
|
340
|
-
// src/utils/cargo.ts
|
|
341
|
-
import * as fs from "fs";
|
|
342
|
-
import { parseCargoToml } from "@releasekit/config";
|
|
343
|
-
import * as TOML from "smol-toml";
|
|
344
|
-
function updateCargoVersion(cargoPath, newVersion) {
|
|
345
|
-
try {
|
|
346
|
-
const cargo = parseCargoToml(cargoPath);
|
|
347
|
-
if (cargo.package) {
|
|
348
|
-
cargo.package.version = newVersion;
|
|
349
|
-
fs.writeFileSync(cargoPath, TOML.stringify(cargo));
|
|
350
|
-
}
|
|
351
|
-
} catch (error) {
|
|
352
|
-
throw createPublishError(
|
|
353
|
-
"CARGO_TOML_ERROR" /* CARGO_TOML_ERROR */,
|
|
354
|
-
`${cargoPath}: ${error instanceof Error ? error.message : String(error)}`
|
|
355
|
-
);
|
|
356
|
-
}
|
|
357
|
-
}
|
|
358
|
-
function extractPathDeps(manifest) {
|
|
359
|
-
const pathDeps = [];
|
|
360
|
-
const deps = manifest.dependencies;
|
|
361
|
-
if (deps) {
|
|
362
|
-
for (const dep of Object.values(deps)) {
|
|
363
|
-
if (dep && typeof dep === "object" && "path" in dep) {
|
|
364
|
-
pathDeps.push(dep.path);
|
|
365
|
-
}
|
|
366
|
-
}
|
|
367
|
-
}
|
|
368
|
-
return pathDeps;
|
|
369
|
-
}
|
|
370
|
-
|
|
371
|
-
// src/utils/semver.ts
|
|
372
|
-
import semver from "semver";
|
|
373
|
-
function isPrerelease(version) {
|
|
374
|
-
return semver.prerelease(version) !== null;
|
|
375
|
-
}
|
|
376
|
-
function getDistTag(version, defaultTag = "latest") {
|
|
377
|
-
const pre = semver.prerelease(version);
|
|
378
|
-
if (pre && pre.length > 0) {
|
|
379
|
-
const identifier = pre[0];
|
|
380
|
-
return typeof identifier === "string" ? identifier : "next";
|
|
381
|
-
}
|
|
382
|
-
return defaultTag;
|
|
383
|
-
}
|
|
384
|
-
|
|
385
|
-
// src/utils/package-manager.ts
|
|
386
|
-
import * as fs2 from "fs";
|
|
387
|
-
import * as path from "path";
|
|
388
|
-
function detectPackageManager(cwd) {
|
|
389
|
-
if (fs2.existsSync(path.join(cwd, "pnpm-lock.yaml"))) return "pnpm";
|
|
390
|
-
if (fs2.existsSync(path.join(cwd, "yarn.lock"))) return "yarn";
|
|
391
|
-
return "npm";
|
|
392
|
-
}
|
|
393
|
-
function buildPublishCommand(pm, packageName, _packageDir, options) {
|
|
394
|
-
const args = ["publish"];
|
|
395
|
-
let file;
|
|
396
|
-
if (pm === "pnpm") {
|
|
397
|
-
file = "pnpm";
|
|
398
|
-
args.push("--filter", packageName, "--access", options.access, "--tag", options.tag);
|
|
399
|
-
if (options.noGitChecks) args.push("--no-git-checks");
|
|
400
|
-
} else {
|
|
401
|
-
file = "npm";
|
|
402
|
-
args.push("--access", options.access, "--tag", options.tag);
|
|
403
|
-
}
|
|
404
|
-
if (options.provenance) {
|
|
405
|
-
args.push("--provenance");
|
|
406
|
-
}
|
|
407
|
-
return { file, args };
|
|
408
|
-
}
|
|
409
|
-
function buildViewCommand(pm, packageName, version) {
|
|
410
|
-
const file = pm === "pnpm" ? "pnpm" : "npm";
|
|
411
|
-
return { file, args: ["view", `${packageName}@${version}`, "version", "--json"] };
|
|
412
|
-
}
|
|
413
|
-
|
|
414
|
-
// src/stages/cargo-publish.ts
|
|
415
|
-
import * as fs3 from "fs";
|
|
416
|
-
import * as path2 from "path";
|
|
417
|
-
import { debug as debug2, success, warn } from "@releasekit/core";
|
|
418
|
-
async function runCargoPublishStage(ctx) {
|
|
419
|
-
const { input, config, cliOptions, cwd } = ctx;
|
|
420
|
-
const dryRun = cliOptions.dryRun;
|
|
421
|
-
if (!config.cargo.enabled) {
|
|
422
|
-
debug2("Cargo publishing disabled in config");
|
|
423
|
-
return;
|
|
424
|
-
}
|
|
425
|
-
if (!hasCargoAuth() && !dryRun) {
|
|
426
|
-
throw createPublishError("CARGO_AUTH_ERROR" /* CARGO_AUTH_ERROR */, "CARGO_REGISTRY_TOKEN not set");
|
|
427
|
-
}
|
|
428
|
-
const crates = findCrates(
|
|
429
|
-
input.updates.map((u) => ({ dir: path2.dirname(path2.resolve(cwd, u.filePath)), ...u })),
|
|
430
|
-
cwd
|
|
431
|
-
);
|
|
432
|
-
if (crates.length === 0) {
|
|
433
|
-
debug2("No Cargo crates found to publish");
|
|
434
|
-
return;
|
|
435
|
-
}
|
|
436
|
-
const ordered = orderCrates(crates, config.cargo.publishOrder);
|
|
437
|
-
for (const crate of ordered) {
|
|
438
|
-
const result = {
|
|
439
|
-
packageName: crate.name,
|
|
440
|
-
version: crate.version,
|
|
441
|
-
registry: "cargo",
|
|
442
|
-
success: false,
|
|
443
|
-
skipped: false
|
|
444
|
-
};
|
|
445
|
-
const searchResult = await execCommandSafe("cargo", ["search", crate.name, "--limit", "1"], { cwd, dryRun: false });
|
|
446
|
-
if (searchResult.exitCode === 0 && searchResult.stdout.includes(`"${crate.version}"`)) {
|
|
447
|
-
result.alreadyPublished = true;
|
|
448
|
-
result.skipped = true;
|
|
449
|
-
result.success = true;
|
|
450
|
-
result.reason = "Already published on crates.io";
|
|
451
|
-
ctx.output.cargo.push(result);
|
|
452
|
-
warn(`${crate.name}@${crate.version} is already published on crates.io, skipping`);
|
|
453
|
-
continue;
|
|
454
|
-
}
|
|
455
|
-
if (config.cargo.clean) {
|
|
456
|
-
await execCommand("cargo", ["clean"], { cwd: crate.dir, dryRun, label: `cargo clean (${crate.name})` });
|
|
457
|
-
}
|
|
458
|
-
const publishArgs = ["publish", "--manifest-path", crate.manifestPath];
|
|
459
|
-
if (config.cargo.noVerify) {
|
|
460
|
-
publishArgs.push("--no-verify");
|
|
461
|
-
}
|
|
462
|
-
try {
|
|
463
|
-
await execCommand("cargo", publishArgs, {
|
|
464
|
-
cwd,
|
|
465
|
-
dryRun,
|
|
466
|
-
label: `cargo publish ${crate.name}@${crate.version}`
|
|
467
|
-
});
|
|
468
|
-
result.success = true;
|
|
469
|
-
if (!dryRun) {
|
|
470
|
-
success(`Published ${crate.name}@${crate.version} to crates.io`);
|
|
471
|
-
}
|
|
472
|
-
} catch (error) {
|
|
473
|
-
result.reason = error instanceof Error ? error.message : String(error);
|
|
474
|
-
warn(`Failed to publish ${crate.name}: ${result.reason}`);
|
|
475
|
-
}
|
|
476
|
-
ctx.output.cargo.push(result);
|
|
477
|
-
}
|
|
478
|
-
}
|
|
479
|
-
function findCrates(updates, _cwd) {
|
|
480
|
-
const crates = [];
|
|
481
|
-
for (const update of updates) {
|
|
482
|
-
const cargoPath = path2.join(update.dir, "Cargo.toml");
|
|
483
|
-
if (!fs3.existsSync(cargoPath)) {
|
|
484
|
-
continue;
|
|
485
|
-
}
|
|
486
|
-
try {
|
|
487
|
-
const cargo = parseCargoToml(cargoPath);
|
|
488
|
-
if (!cargo.package?.name) {
|
|
489
|
-
continue;
|
|
490
|
-
}
|
|
491
|
-
const pathDeps = extractPathDeps(cargo);
|
|
492
|
-
crates.push({
|
|
493
|
-
name: cargo.package.name,
|
|
494
|
-
version: update.newVersion,
|
|
495
|
-
dir: update.dir,
|
|
496
|
-
manifestPath: cargoPath,
|
|
497
|
-
pathDeps
|
|
498
|
-
});
|
|
499
|
-
} catch {
|
|
500
|
-
}
|
|
501
|
-
}
|
|
502
|
-
return crates;
|
|
503
|
-
}
|
|
504
|
-
function orderCrates(crates, explicitOrder) {
|
|
505
|
-
if (explicitOrder.length > 0) {
|
|
506
|
-
const ordered = [];
|
|
507
|
-
const byName = new Map(crates.map((c) => [c.name, c]));
|
|
508
|
-
for (const name of explicitOrder) {
|
|
509
|
-
const crate = byName.get(name);
|
|
510
|
-
if (crate) {
|
|
511
|
-
ordered.push(crate);
|
|
512
|
-
byName.delete(name);
|
|
513
|
-
}
|
|
514
|
-
}
|
|
515
|
-
for (const crate of byName.values()) {
|
|
516
|
-
ordered.push(crate);
|
|
517
|
-
}
|
|
518
|
-
return ordered;
|
|
519
|
-
}
|
|
520
|
-
return topologicalSort(crates);
|
|
521
|
-
}
|
|
522
|
-
function topologicalSort(crates) {
|
|
523
|
-
const nameSet = new Set(crates.map((c) => c.name));
|
|
524
|
-
const graph = /* @__PURE__ */ new Map();
|
|
525
|
-
const crateMap = new Map(crates.map((c) => [c.name, c]));
|
|
526
|
-
for (const crate of crates) {
|
|
527
|
-
graph.set(crate.name, []);
|
|
528
|
-
}
|
|
529
|
-
for (const crate of crates) {
|
|
530
|
-
for (const depPath of crate.pathDeps) {
|
|
531
|
-
const resolvedDir = path2.resolve(crate.dir, depPath);
|
|
532
|
-
for (const other of crates) {
|
|
533
|
-
if (path2.resolve(other.dir) === resolvedDir && nameSet.has(other.name)) {
|
|
534
|
-
graph.get(crate.name)?.push(other.name);
|
|
535
|
-
}
|
|
536
|
-
}
|
|
537
|
-
}
|
|
538
|
-
}
|
|
539
|
-
const inDegree = /* @__PURE__ */ new Map();
|
|
540
|
-
for (const name of nameSet) {
|
|
541
|
-
inDegree.set(name, 0);
|
|
542
|
-
}
|
|
543
|
-
for (const deps of graph.values()) {
|
|
544
|
-
for (const dep of deps) {
|
|
545
|
-
inDegree.set(dep, (inDegree.get(dep) ?? 0) + 1);
|
|
546
|
-
}
|
|
547
|
-
}
|
|
548
|
-
const queue = [];
|
|
549
|
-
for (const [name, degree] of inDegree) {
|
|
550
|
-
if (degree === 0) {
|
|
551
|
-
queue.push(name);
|
|
552
|
-
}
|
|
553
|
-
}
|
|
554
|
-
const result = [];
|
|
555
|
-
while (queue.length > 0) {
|
|
556
|
-
const name = queue.shift();
|
|
557
|
-
if (!name) break;
|
|
558
|
-
const crate = crateMap.get(name);
|
|
559
|
-
if (crate) {
|
|
560
|
-
result.push(crate);
|
|
561
|
-
}
|
|
562
|
-
for (const dep of graph.get(name) ?? []) {
|
|
563
|
-
const newDegree = (inDegree.get(dep) ?? 1) - 1;
|
|
564
|
-
inDegree.set(dep, newDegree);
|
|
565
|
-
if (newDegree === 0) {
|
|
566
|
-
queue.push(dep);
|
|
567
|
-
}
|
|
568
|
-
}
|
|
569
|
-
}
|
|
570
|
-
result.reverse();
|
|
571
|
-
return result;
|
|
572
|
-
}
|
|
573
|
-
|
|
574
|
-
// src/stages/git-commit.ts
|
|
575
|
-
import * as path3 from "path";
|
|
576
|
-
import { info as info2, success as success2 } from "@releasekit/core";
|
|
577
|
-
async function runGitCommitStage(ctx) {
|
|
578
|
-
const { input, config, cliOptions, cwd } = ctx;
|
|
579
|
-
const dryRun = cliOptions.dryRun;
|
|
580
|
-
const skipHooks = config.git.skipHooks ?? false;
|
|
581
|
-
if (!input.commitMessage) {
|
|
582
|
-
info2("No commit message provided, skipping git commit");
|
|
583
|
-
return;
|
|
584
|
-
}
|
|
585
|
-
const filePaths = input.updates.map((u) => path3.resolve(cwd, u.filePath));
|
|
586
|
-
if (ctx.additionalFiles) {
|
|
587
|
-
filePaths.push(...ctx.additionalFiles.map((f) => path3.resolve(cwd, f)));
|
|
588
|
-
}
|
|
589
|
-
if (filePaths.length === 0) {
|
|
590
|
-
info2("No files to commit");
|
|
591
|
-
return;
|
|
592
|
-
}
|
|
593
|
-
try {
|
|
594
|
-
await execCommand("git", ["add", ...filePaths], {
|
|
595
|
-
cwd,
|
|
596
|
-
dryRun,
|
|
597
|
-
label: `git add ${filePaths.length} file(s)`
|
|
598
|
-
});
|
|
599
|
-
} catch (error) {
|
|
600
|
-
throw createPublishError(
|
|
601
|
-
"GIT_COMMIT_ERROR" /* GIT_COMMIT_ERROR */,
|
|
602
|
-
`git add failed: ${error instanceof Error ? error.message : String(error)}`
|
|
603
|
-
);
|
|
604
|
-
}
|
|
605
|
-
const commitArgs = ["commit"];
|
|
606
|
-
if (skipHooks) {
|
|
607
|
-
commitArgs.push("--no-verify");
|
|
608
|
-
}
|
|
609
|
-
commitArgs.push("-m", input.commitMessage);
|
|
610
|
-
try {
|
|
611
|
-
await execCommand("git", commitArgs, {
|
|
612
|
-
cwd,
|
|
613
|
-
dryRun,
|
|
614
|
-
label: `git commit -m "${input.commitMessage}"`
|
|
615
|
-
});
|
|
616
|
-
ctx.output.git.committed = true;
|
|
617
|
-
if (!dryRun) {
|
|
618
|
-
success2("Created git commit");
|
|
619
|
-
}
|
|
620
|
-
} catch (error) {
|
|
621
|
-
throw createPublishError(
|
|
622
|
-
"GIT_COMMIT_ERROR" /* GIT_COMMIT_ERROR */,
|
|
623
|
-
`git commit failed: ${error instanceof Error ? error.message : String(error)}`
|
|
624
|
-
);
|
|
625
|
-
}
|
|
626
|
-
for (const tag of input.tags) {
|
|
627
|
-
try {
|
|
628
|
-
const tagMessage = `Release ${tag}`;
|
|
629
|
-
await execCommand("git", ["tag", "-a", tag, "-m", tagMessage], {
|
|
630
|
-
cwd,
|
|
631
|
-
dryRun,
|
|
632
|
-
label: `git tag ${tag}`
|
|
633
|
-
});
|
|
634
|
-
ctx.output.git.tags.push(tag);
|
|
635
|
-
if (!dryRun) {
|
|
636
|
-
success2(`Created tag: ${tag}`);
|
|
637
|
-
}
|
|
638
|
-
} catch (error) {
|
|
639
|
-
throw createPublishError(
|
|
640
|
-
"GIT_TAG_ERROR" /* GIT_TAG_ERROR */,
|
|
641
|
-
`Failed to create tag ${tag}: ${error instanceof Error ? error.message : String(error)}`
|
|
642
|
-
);
|
|
643
|
-
}
|
|
644
|
-
}
|
|
645
|
-
}
|
|
646
|
-
|
|
647
|
-
// src/stages/git-push.ts
|
|
648
|
-
import { info as info3, success as success3 } from "@releasekit/core";
|
|
649
|
-
function toGithubAuthedUrl(remoteUrl, token) {
|
|
650
|
-
try {
|
|
651
|
-
const url = new URL(remoteUrl);
|
|
652
|
-
if (url.protocol !== "https:") return void 0;
|
|
653
|
-
if (url.host !== "github.com") return void 0;
|
|
654
|
-
url.username = "x-access-token";
|
|
655
|
-
url.password = token;
|
|
656
|
-
return url.toString();
|
|
657
|
-
} catch {
|
|
658
|
-
return void 0;
|
|
659
|
-
}
|
|
660
|
-
}
|
|
661
|
-
async function runGitPushStage(ctx) {
|
|
662
|
-
const { config, cliOptions, cwd, output } = ctx;
|
|
663
|
-
const dryRun = cliOptions.dryRun;
|
|
664
|
-
if (!config.git.push) {
|
|
665
|
-
info3("Git push disabled in config, skipping");
|
|
666
|
-
return;
|
|
667
|
-
}
|
|
668
|
-
if (!output.git.committed && output.git.tags.length === 0) {
|
|
669
|
-
info3("Nothing to push (no commits or tags created)");
|
|
670
|
-
return;
|
|
671
|
-
}
|
|
672
|
-
const { remote, branch } = config.git;
|
|
673
|
-
let pushMethod = config.git.pushMethod;
|
|
674
|
-
if (pushMethod === "auto") {
|
|
675
|
-
try {
|
|
676
|
-
pushMethod = await detectGitPushMethod(remote, cwd);
|
|
677
|
-
} catch {
|
|
678
|
-
pushMethod = "https";
|
|
679
|
-
}
|
|
680
|
-
}
|
|
681
|
-
const httpsTokenEnv = config.git.httpsTokenEnv;
|
|
682
|
-
const httpsToken = httpsTokenEnv ? process.env[httpsTokenEnv] : void 0;
|
|
683
|
-
try {
|
|
684
|
-
let pushRemote = remote;
|
|
685
|
-
if (pushMethod === "https" && httpsToken) {
|
|
686
|
-
const remoteUrlResult = await execCommand("git", ["remote", "get-url", remote], { cwd, dryRun: false });
|
|
687
|
-
const authed = toGithubAuthedUrl(remoteUrlResult.stdout.trim(), httpsToken);
|
|
688
|
-
if (authed) {
|
|
689
|
-
pushRemote = authed;
|
|
690
|
-
}
|
|
691
|
-
}
|
|
692
|
-
if (output.git.committed) {
|
|
693
|
-
await execCommand("git", ["push", pushRemote, branch], {
|
|
694
|
-
cwd,
|
|
695
|
-
dryRun,
|
|
696
|
-
label: `git push ${remote} ${branch}`
|
|
697
|
-
});
|
|
698
|
-
}
|
|
699
|
-
if (output.git.tags.length > 0) {
|
|
700
|
-
await execCommand("git", ["push", pushRemote, "--tags"], {
|
|
701
|
-
cwd,
|
|
702
|
-
dryRun,
|
|
703
|
-
label: `git push ${remote} --tags`
|
|
704
|
-
});
|
|
705
|
-
}
|
|
706
|
-
ctx.output.git.pushed = true;
|
|
707
|
-
if (!dryRun) {
|
|
708
|
-
success3(`Pushed to ${remote}/${branch}`);
|
|
709
|
-
}
|
|
710
|
-
} catch (error) {
|
|
711
|
-
throw createPublishError(
|
|
712
|
-
"GIT_PUSH_ERROR" /* GIT_PUSH_ERROR */,
|
|
713
|
-
`${error instanceof Error ? error.message : String(error)}`
|
|
714
|
-
);
|
|
715
|
-
}
|
|
716
|
-
}
|
|
717
|
-
|
|
718
|
-
// src/stages/github-release.ts
|
|
719
|
-
import * as fs4 from "fs";
|
|
720
|
-
import { debug as debug3, info as info4, success as success4, warn as warn2 } from "@releasekit/core";
|
|
721
|
-
function resolveNotes(notesSetting, tag, changelogs, pipelineNotes) {
|
|
722
|
-
if (notesSetting === "none") {
|
|
723
|
-
return { useGithubNotes: false };
|
|
724
|
-
}
|
|
725
|
-
if (notesSetting === "github") {
|
|
726
|
-
return { useGithubNotes: true };
|
|
727
|
-
}
|
|
728
|
-
if (notesSetting !== "auto") {
|
|
729
|
-
const body = readFileIfExists(notesSetting);
|
|
730
|
-
if (body) return { body, useGithubNotes: false };
|
|
731
|
-
debug3(`Notes file not found: ${notesSetting}, falling back to GitHub auto-notes`);
|
|
732
|
-
return { useGithubNotes: true };
|
|
733
|
-
}
|
|
734
|
-
if (pipelineNotes) {
|
|
735
|
-
const body = findNotesForTag(tag, pipelineNotes);
|
|
736
|
-
if (body) return { body, useGithubNotes: false };
|
|
737
|
-
}
|
|
738
|
-
const packageBody = formatChangelogForTag(tag, changelogs);
|
|
739
|
-
if (packageBody) {
|
|
740
|
-
return { body: packageBody, useGithubNotes: false };
|
|
741
|
-
}
|
|
742
|
-
return { useGithubNotes: true };
|
|
743
|
-
}
|
|
744
|
-
function isVersionOnlyTag(tag) {
|
|
745
|
-
return /^v?\d+\.\d+\.\d+/.test(tag);
|
|
746
|
-
}
|
|
747
|
-
function findNotesForTag(tag, notes) {
|
|
748
|
-
for (const [packageName, body] of Object.entries(notes)) {
|
|
749
|
-
if (tag.startsWith(`${packageName}@`) && body.trim()) {
|
|
750
|
-
return body;
|
|
751
|
-
}
|
|
752
|
-
}
|
|
753
|
-
const entries = Object.values(notes).filter((b) => b.trim());
|
|
754
|
-
if (entries.length === 1 && isVersionOnlyTag(tag)) return entries[0];
|
|
755
|
-
return void 0;
|
|
756
|
-
}
|
|
757
|
-
function readFileIfExists(filePath) {
|
|
758
|
-
try {
|
|
759
|
-
const content = fs4.readFileSync(filePath, "utf-8").trim();
|
|
760
|
-
return content || void 0;
|
|
761
|
-
} catch {
|
|
762
|
-
return void 0;
|
|
763
|
-
}
|
|
764
|
-
}
|
|
765
|
-
function formatChangelogForTag(tag, changelogs) {
|
|
766
|
-
if (changelogs.length === 0) return void 0;
|
|
767
|
-
const changelog = changelogs.find((c) => tag.startsWith(`${c.packageName}@`));
|
|
768
|
-
const target = changelog ?? (changelogs.length === 1 && isVersionOnlyTag(tag) ? changelogs[0] : void 0);
|
|
769
|
-
if (!target || target.entries.length === 0) return void 0;
|
|
770
|
-
const lines = [];
|
|
771
|
-
for (const entry of target.entries) {
|
|
772
|
-
const scope = entry.scope ? `**${entry.scope}:** ` : "";
|
|
773
|
-
lines.push(`- ${scope}${entry.description}`);
|
|
774
|
-
}
|
|
775
|
-
return lines.join("\n");
|
|
776
|
-
}
|
|
777
|
-
async function runGithubReleaseStage(ctx) {
|
|
778
|
-
const { config, cliOptions, output } = ctx;
|
|
779
|
-
const dryRun = cliOptions.dryRun;
|
|
780
|
-
if (!config.githubRelease.enabled) {
|
|
781
|
-
debug3("GitHub releases disabled in config");
|
|
782
|
-
return;
|
|
783
|
-
}
|
|
784
|
-
const tags = output.git.tags.length > 0 ? output.git.tags : ctx.input.tags;
|
|
785
|
-
if (tags.length === 0) {
|
|
786
|
-
info4("No tags available for GitHub release");
|
|
787
|
-
return;
|
|
788
|
-
}
|
|
789
|
-
const firstTag = tags[0];
|
|
790
|
-
if (!firstTag) return;
|
|
791
|
-
const tagsToRelease = config.githubRelease.perPackage ? tags : [firstTag];
|
|
792
|
-
for (const tag of tagsToRelease) {
|
|
793
|
-
const MAX_TAG_LENGTH = 1e3;
|
|
794
|
-
const truncatedTag = tag.length > MAX_TAG_LENGTH ? tag.slice(0, MAX_TAG_LENGTH) : tag;
|
|
795
|
-
const versionMatch = truncatedTag.match(/(\d{1,20}\.\d{1,20}\.\d{1,20}(?:[-+.]?[a-zA-Z0-9.-]{0,100})?)$/);
|
|
796
|
-
const version = versionMatch?.[1] ?? "";
|
|
797
|
-
const isPreRel = config.githubRelease.prerelease === "auto" ? version ? isPrerelease(version) : false : config.githubRelease.prerelease;
|
|
798
|
-
const result = {
|
|
799
|
-
tag,
|
|
800
|
-
draft: config.githubRelease.draft,
|
|
801
|
-
prerelease: isPreRel,
|
|
802
|
-
success: false
|
|
803
|
-
};
|
|
804
|
-
const ghArgs = ["release", "create", tag];
|
|
805
|
-
if (config.githubRelease.draft) {
|
|
806
|
-
ghArgs.push("--draft");
|
|
807
|
-
}
|
|
808
|
-
if (isPreRel) {
|
|
809
|
-
ghArgs.push("--prerelease");
|
|
810
|
-
}
|
|
811
|
-
const { body, useGithubNotes } = resolveNotes(
|
|
812
|
-
config.githubRelease.releaseNotes,
|
|
813
|
-
tag,
|
|
814
|
-
ctx.input.changelogs,
|
|
815
|
-
ctx.releaseNotes
|
|
816
|
-
);
|
|
817
|
-
if (body) {
|
|
818
|
-
ghArgs.push("--notes", body);
|
|
819
|
-
} else if (useGithubNotes) {
|
|
820
|
-
ghArgs.push("--generate-notes");
|
|
821
|
-
}
|
|
822
|
-
try {
|
|
823
|
-
const execResult = await execCommand("gh", ghArgs, {
|
|
824
|
-
dryRun,
|
|
825
|
-
label: `gh release create ${tag}`
|
|
826
|
-
});
|
|
827
|
-
result.success = true;
|
|
828
|
-
if (!dryRun && execResult.stdout.trim()) {
|
|
829
|
-
result.url = execResult.stdout.trim();
|
|
830
|
-
}
|
|
831
|
-
if (!dryRun) {
|
|
832
|
-
success4(`Created GitHub release for ${tag}`);
|
|
833
|
-
}
|
|
834
|
-
} catch (error) {
|
|
835
|
-
result.reason = error instanceof Error ? error.message : String(error);
|
|
836
|
-
warn2(`Failed to create GitHub release for ${tag}: ${result.reason}`);
|
|
837
|
-
}
|
|
838
|
-
ctx.output.githubReleases.push(result);
|
|
839
|
-
}
|
|
840
|
-
}
|
|
841
|
-
|
|
842
|
-
// src/stages/npm-publish.ts
|
|
843
|
-
import * as fs6 from "fs";
|
|
844
|
-
import * as path5 from "path";
|
|
845
|
-
import { debug as debug5, info as info5, success as success5, warn as warn3 } from "@releasekit/core";
|
|
846
|
-
|
|
847
|
-
// src/utils/npm-env.ts
|
|
848
|
-
import * as fs5 from "fs";
|
|
849
|
-
import * as os from "os";
|
|
850
|
-
import * as path4 from "path";
|
|
851
|
-
import { debug as debug4 } from "@releasekit/core";
|
|
852
|
-
function writeTempNpmrc(contents) {
|
|
853
|
-
const dir = fs5.mkdtempSync(path4.join(os.tmpdir(), "releasekit-npmrc-"));
|
|
854
|
-
const npmrcPath = path4.join(dir, ".npmrc");
|
|
855
|
-
fs5.writeFileSync(npmrcPath, contents, "utf-8");
|
|
856
|
-
return {
|
|
857
|
-
npmrcPath,
|
|
858
|
-
cleanup: () => {
|
|
859
|
-
try {
|
|
860
|
-
fs5.rmSync(dir, { recursive: true, force: true });
|
|
861
|
-
} catch {
|
|
862
|
-
}
|
|
863
|
-
}
|
|
864
|
-
};
|
|
865
|
-
}
|
|
866
|
-
function createNpmSubprocessIsolation(options) {
|
|
867
|
-
const { authMethod, registryUrl } = options;
|
|
868
|
-
const baseEnv = {};
|
|
869
|
-
if (!authMethod) return { env: baseEnv, cleanup: () => {
|
|
870
|
-
} };
|
|
871
|
-
const token = process.env.NPM_TOKEN ?? process.env.NODE_AUTH_TOKEN;
|
|
872
|
-
const registryHost = (() => {
|
|
873
|
-
try {
|
|
874
|
-
return new URL(registryUrl).host;
|
|
875
|
-
} catch {
|
|
876
|
-
return "registry.npmjs.org";
|
|
877
|
-
}
|
|
878
|
-
})();
|
|
879
|
-
const lines = [`registry=${registryUrl}`];
|
|
880
|
-
if (authMethod === "oidc") {
|
|
881
|
-
lines.push("always-auth=false");
|
|
882
|
-
}
|
|
883
|
-
if (authMethod === "token" && token) {
|
|
884
|
-
lines.push(`//${registryHost}/:_authToken=${token}`);
|
|
885
|
-
}
|
|
886
|
-
lines.push("");
|
|
887
|
-
const { npmrcPath, cleanup } = writeTempNpmrc(lines.join("\n"));
|
|
888
|
-
debug4(`Using isolated npm userconfig: ${npmrcPath}`);
|
|
889
|
-
const isOidc = authMethod === "oidc";
|
|
890
|
-
return {
|
|
891
|
-
env: {
|
|
892
|
-
...baseEnv,
|
|
893
|
-
// Ensure npm and tools that read npm_config_* pick up our temp file
|
|
894
|
-
NPM_CONFIG_USERCONFIG: npmrcPath,
|
|
895
|
-
npm_config_userconfig: npmrcPath,
|
|
896
|
-
// Auth-specific hardening
|
|
897
|
-
...isOidc ? {
|
|
898
|
-
// Prevent setup-node's always-auth from forcing token lookups
|
|
899
|
-
NPM_CONFIG_ALWAYS_AUTH: "false",
|
|
900
|
-
npm_config_always_auth: "false",
|
|
901
|
-
// Explicitly prevent token-based publishing from being selected implicitly
|
|
902
|
-
NODE_AUTH_TOKEN: void 0,
|
|
903
|
-
NPM_TOKEN: void 0
|
|
904
|
-
} : {
|
|
905
|
-
// Ensure CLIs that expect NODE_AUTH_TOKEN can still work
|
|
906
|
-
NODE_AUTH_TOKEN: token
|
|
907
|
-
}
|
|
908
|
-
},
|
|
909
|
-
cleanup
|
|
910
|
-
};
|
|
911
|
-
}
|
|
912
|
-
|
|
913
|
-
// src/stages/npm-publish.ts
|
|
914
|
-
async function runNpmPublishStage(ctx) {
|
|
915
|
-
const { input, config, cliOptions, cwd } = ctx;
|
|
916
|
-
const dryRun = cliOptions.dryRun;
|
|
917
|
-
if (!config.npm.enabled) {
|
|
918
|
-
info5("NPM publishing disabled in config");
|
|
919
|
-
return;
|
|
920
|
-
}
|
|
921
|
-
const authMethod = config.npm.auth === "auto" ? detectNpmAuth() : config.npm.auth;
|
|
922
|
-
if (!authMethod && !dryRun) {
|
|
923
|
-
throw createPublishError("NPM_AUTH_ERROR" /* NPM_AUTH_ERROR */, "No NPM authentication method detected");
|
|
924
|
-
}
|
|
925
|
-
const useProvenance = config.npm.provenance && authMethod === "oidc";
|
|
926
|
-
const npmIsolation = createNpmSubprocessIsolation({
|
|
927
|
-
authMethod,
|
|
928
|
-
registryUrl: config.npm.registry
|
|
929
|
-
});
|
|
930
|
-
try {
|
|
931
|
-
for (const update of input.updates) {
|
|
932
|
-
const result = {
|
|
933
|
-
packageName: update.packageName,
|
|
934
|
-
version: update.newVersion,
|
|
935
|
-
registry: "npm",
|
|
936
|
-
success: false,
|
|
937
|
-
skipped: false
|
|
938
|
-
};
|
|
939
|
-
const pkgJsonPath = path5.resolve(cwd, update.filePath);
|
|
940
|
-
try {
|
|
941
|
-
const pkgContent = fs6.readFileSync(pkgJsonPath, "utf-8");
|
|
942
|
-
const pkgJson = JSON.parse(pkgContent);
|
|
943
|
-
if (pkgJson.private) {
|
|
944
|
-
result.skipped = true;
|
|
945
|
-
result.success = true;
|
|
946
|
-
result.reason = "Package is private";
|
|
947
|
-
ctx.output.npm.push(result);
|
|
948
|
-
debug5(`Skipping private package: ${update.packageName}`);
|
|
949
|
-
continue;
|
|
950
|
-
}
|
|
951
|
-
} catch {
|
|
952
|
-
if (update.filePath.endsWith("Cargo.toml")) {
|
|
953
|
-
result.skipped = true;
|
|
954
|
-
result.success = true;
|
|
955
|
-
result.reason = "Not an npm package";
|
|
956
|
-
ctx.output.npm.push(result);
|
|
957
|
-
continue;
|
|
958
|
-
}
|
|
959
|
-
}
|
|
960
|
-
const { file: viewFile, args: viewArgs } = buildViewCommand(
|
|
961
|
-
ctx.packageManager,
|
|
962
|
-
update.packageName,
|
|
963
|
-
update.newVersion
|
|
964
|
-
);
|
|
965
|
-
const viewResult = await execCommandSafe(viewFile, viewArgs, {
|
|
966
|
-
cwd,
|
|
967
|
-
dryRun: false,
|
|
968
|
-
// Always check, even in dry-run
|
|
969
|
-
env: npmIsolation.env
|
|
970
|
-
});
|
|
971
|
-
if (viewResult.exitCode === 0 && viewResult.stdout.trim()) {
|
|
972
|
-
result.alreadyPublished = true;
|
|
973
|
-
result.skipped = true;
|
|
974
|
-
result.success = true;
|
|
975
|
-
result.reason = "Already published";
|
|
976
|
-
ctx.output.npm.push(result);
|
|
977
|
-
warn3(`${update.packageName}@${update.newVersion} is already published, skipping`);
|
|
978
|
-
continue;
|
|
979
|
-
}
|
|
980
|
-
const distTag = getDistTag(update.newVersion, config.npm.tag);
|
|
981
|
-
const pkgDir = path5.dirname(path5.resolve(cwd, update.filePath));
|
|
982
|
-
const { file: pubFile, args: pubArgs } = buildPublishCommand(ctx.packageManager, update.packageName, pkgDir, {
|
|
983
|
-
access: config.npm.access,
|
|
984
|
-
tag: distTag,
|
|
985
|
-
provenance: useProvenance,
|
|
986
|
-
noGitChecks: true
|
|
987
|
-
});
|
|
988
|
-
try {
|
|
989
|
-
await execCommand(pubFile, pubArgs, {
|
|
990
|
-
cwd,
|
|
991
|
-
dryRun,
|
|
992
|
-
label: `npm publish ${update.packageName}@${update.newVersion}`,
|
|
993
|
-
env: npmIsolation.env
|
|
994
|
-
});
|
|
995
|
-
result.success = true;
|
|
996
|
-
if (!dryRun) {
|
|
997
|
-
success5(`Published ${update.packageName}@${update.newVersion} to npm`);
|
|
998
|
-
}
|
|
999
|
-
} catch (error) {
|
|
1000
|
-
result.reason = error instanceof Error ? error.message : String(error);
|
|
1001
|
-
warn3(`Failed to publish ${update.packageName}: ${result.reason}`);
|
|
1002
|
-
}
|
|
1003
|
-
ctx.output.npm.push(result);
|
|
1004
|
-
}
|
|
1005
|
-
} finally {
|
|
1006
|
-
npmIsolation.cleanup();
|
|
1007
|
-
}
|
|
1008
|
-
}
|
|
1009
|
-
|
|
1010
|
-
// src/stages/prepare.ts
|
|
1011
|
-
import * as fs7 from "fs";
|
|
1012
|
-
import * as path6 from "path";
|
|
1013
|
-
import { debug as debug6, info as info6 } from "@releasekit/core";
|
|
1014
|
-
async function runPrepareStage(ctx) {
|
|
1015
|
-
const { input, config, cliOptions, cwd } = ctx;
|
|
1016
|
-
if (config.npm.enabled && config.npm.copyFiles.length > 0) {
|
|
1017
|
-
for (const update of input.updates) {
|
|
1018
|
-
const pkgDir = path6.dirname(path6.resolve(cwd, update.filePath));
|
|
1019
|
-
for (const file of config.npm.copyFiles) {
|
|
1020
|
-
const src = path6.resolve(cwd, file);
|
|
1021
|
-
const dest = path6.join(pkgDir, file);
|
|
1022
|
-
if (!fs7.existsSync(src)) {
|
|
1023
|
-
debug6(`Source file not found, skipping copy: ${src}`);
|
|
1024
|
-
continue;
|
|
1025
|
-
}
|
|
1026
|
-
if (path6.resolve(path6.dirname(src)) === path6.resolve(pkgDir)) {
|
|
1027
|
-
debug6(`Skipping copy of ${file} - same directory as source`);
|
|
1028
|
-
continue;
|
|
1029
|
-
}
|
|
1030
|
-
if (cliOptions.dryRun) {
|
|
1031
|
-
info6(`[DRY RUN] Would copy ${src} \u2192 ${dest}`);
|
|
1032
|
-
continue;
|
|
1033
|
-
}
|
|
1034
|
-
try {
|
|
1035
|
-
fs7.copyFileSync(src, dest);
|
|
1036
|
-
debug6(`Copied ${file} \u2192 ${pkgDir}`);
|
|
1037
|
-
} catch (error) {
|
|
1038
|
-
throw createPublishError(
|
|
1039
|
-
"FILE_COPY_ERROR" /* FILE_COPY_ERROR */,
|
|
1040
|
-
`Failed to copy ${src} to ${dest}: ${error instanceof Error ? error.message : String(error)}`
|
|
1041
|
-
);
|
|
1042
|
-
}
|
|
1043
|
-
}
|
|
1044
|
-
}
|
|
1045
|
-
}
|
|
1046
|
-
if (config.cargo.enabled) {
|
|
1047
|
-
for (const update of input.updates) {
|
|
1048
|
-
const pkgDir = path6.dirname(path6.resolve(cwd, update.filePath));
|
|
1049
|
-
const cargoPath = path6.join(pkgDir, "Cargo.toml");
|
|
1050
|
-
if (!fs7.existsSync(cargoPath)) {
|
|
1051
|
-
continue;
|
|
1052
|
-
}
|
|
1053
|
-
if (cliOptions.dryRun) {
|
|
1054
|
-
info6(`[DRY RUN] Would update ${cargoPath} to version ${update.newVersion}`);
|
|
1055
|
-
continue;
|
|
1056
|
-
}
|
|
1057
|
-
updateCargoVersion(cargoPath, update.newVersion);
|
|
1058
|
-
debug6(`Updated ${cargoPath} to version ${update.newVersion}`);
|
|
1059
|
-
}
|
|
1060
|
-
}
|
|
1061
|
-
}
|
|
1062
|
-
|
|
1063
|
-
// src/stages/verify.ts
|
|
1064
|
-
import { debug as debug8, info as info7, success as success6, warn as warn4 } from "@releasekit/core";
|
|
1065
|
-
|
|
1066
|
-
// src/utils/retry.ts
|
|
1067
|
-
import { debug as debug7 } from "@releasekit/core";
|
|
1068
|
-
async function withRetry(fn, options, shouldRetry) {
|
|
1069
|
-
let lastError;
|
|
1070
|
-
let delay = options.initialDelay;
|
|
1071
|
-
for (let attempt = 1; attempt <= options.maxAttempts; attempt++) {
|
|
1072
|
-
try {
|
|
1073
|
-
return await fn();
|
|
1074
|
-
} catch (error) {
|
|
1075
|
-
lastError = error;
|
|
1076
|
-
if (shouldRetry && !shouldRetry(error)) {
|
|
1077
|
-
throw error;
|
|
1078
|
-
}
|
|
1079
|
-
if (attempt < options.maxAttempts) {
|
|
1080
|
-
debug7(`Attempt ${attempt}/${options.maxAttempts} failed, retrying in ${delay}ms...`);
|
|
1081
|
-
await sleep(delay);
|
|
1082
|
-
delay = Math.floor(delay * options.backoffMultiplier);
|
|
1083
|
-
}
|
|
1084
|
-
}
|
|
1085
|
-
}
|
|
1086
|
-
throw lastError;
|
|
1087
|
-
}
|
|
1088
|
-
function sleep(ms) {
|
|
1089
|
-
return new Promise((resolve5) => setTimeout(resolve5, ms));
|
|
1090
|
-
}
|
|
1091
|
-
|
|
1092
|
-
// src/stages/verify.ts
|
|
1093
|
-
async function runVerifyStage(ctx) {
|
|
1094
|
-
const { config, cliOptions, output, cwd } = ctx;
|
|
1095
|
-
if (config.verify.npm.enabled) {
|
|
1096
|
-
const published = output.npm.filter((r) => r.success && !r.skipped && !r.alreadyPublished);
|
|
1097
|
-
for (const pkg of published) {
|
|
1098
|
-
const result = {
|
|
1099
|
-
packageName: pkg.packageName,
|
|
1100
|
-
version: pkg.version,
|
|
1101
|
-
registry: "npm",
|
|
1102
|
-
verified: false,
|
|
1103
|
-
attempts: 0
|
|
1104
|
-
};
|
|
1105
|
-
if (cliOptions.dryRun) {
|
|
1106
|
-
info7(`[DRY RUN] Would verify ${pkg.packageName}@${pkg.version} on npm`);
|
|
1107
|
-
result.verified = true;
|
|
1108
|
-
ctx.output.verification.push(result);
|
|
1109
|
-
continue;
|
|
1110
|
-
}
|
|
1111
|
-
try {
|
|
1112
|
-
await withRetry(async () => {
|
|
1113
|
-
result.attempts++;
|
|
1114
|
-
const { file: viewFile, args: viewArgs } = buildViewCommand(ctx.packageManager, pkg.packageName, pkg.version);
|
|
1115
|
-
const viewResult = await execCommandSafe(viewFile, viewArgs, {
|
|
1116
|
-
cwd,
|
|
1117
|
-
dryRun: false
|
|
1118
|
-
});
|
|
1119
|
-
if (viewResult.exitCode !== 0 || !viewResult.stdout.trim()) {
|
|
1120
|
-
throw new Error(`${pkg.packageName}@${pkg.version} not yet available on npm`);
|
|
1121
|
-
}
|
|
1122
|
-
debug8(`Verified ${pkg.packageName}@${pkg.version} on npm`);
|
|
1123
|
-
}, config.verify.npm);
|
|
1124
|
-
result.verified = true;
|
|
1125
|
-
success6(`Verified ${pkg.packageName}@${pkg.version} on npm`);
|
|
1126
|
-
} catch {
|
|
1127
|
-
warn4(`Failed to verify ${pkg.packageName}@${pkg.version} on npm after ${result.attempts} attempts`);
|
|
1128
|
-
}
|
|
1129
|
-
ctx.output.verification.push(result);
|
|
1130
|
-
}
|
|
1131
|
-
}
|
|
1132
|
-
if (config.verify.cargo.enabled) {
|
|
1133
|
-
const published = output.cargo.filter((r) => r.success && !r.skipped && !r.alreadyPublished);
|
|
1134
|
-
for (const crate of published) {
|
|
1135
|
-
const result = {
|
|
1136
|
-
packageName: crate.packageName,
|
|
1137
|
-
version: crate.version,
|
|
1138
|
-
registry: "cargo",
|
|
1139
|
-
verified: false,
|
|
1140
|
-
attempts: 0
|
|
1141
|
-
};
|
|
1142
|
-
if (cliOptions.dryRun) {
|
|
1143
|
-
info7(`[DRY RUN] Would verify ${crate.packageName}@${crate.version} on crates.io`);
|
|
1144
|
-
result.verified = true;
|
|
1145
|
-
ctx.output.verification.push(result);
|
|
1146
|
-
continue;
|
|
1147
|
-
}
|
|
1148
|
-
try {
|
|
1149
|
-
await withRetry(async () => {
|
|
1150
|
-
result.attempts++;
|
|
1151
|
-
const response = await fetch(`https://crates.io/api/v1/crates/${crate.packageName}/${crate.version}`);
|
|
1152
|
-
if (!response.ok) {
|
|
1153
|
-
throw new Error(`${crate.packageName}@${crate.version} not yet available on crates.io`);
|
|
1154
|
-
}
|
|
1155
|
-
debug8(`Verified ${crate.packageName}@${crate.version} on crates.io`);
|
|
1156
|
-
}, config.verify.cargo);
|
|
1157
|
-
result.verified = true;
|
|
1158
|
-
success6(`Verified ${crate.packageName}@${crate.version} on crates.io`);
|
|
1159
|
-
} catch {
|
|
1160
|
-
warn4(`Failed to verify ${crate.packageName}@${crate.version} on crates.io after ${result.attempts} attempts`);
|
|
1161
|
-
}
|
|
1162
|
-
ctx.output.verification.push(result);
|
|
1163
|
-
}
|
|
1164
|
-
}
|
|
1165
|
-
}
|
|
1166
|
-
|
|
1167
|
-
// src/pipeline/index.ts
|
|
1168
|
-
function inferStageName(error) {
|
|
1169
|
-
if (error instanceof BasePublishError) {
|
|
1170
|
-
const codeToStage = {
|
|
1171
|
-
FILE_COPY_ERROR: "prepare",
|
|
1172
|
-
CARGO_TOML_ERROR: "prepare",
|
|
1173
|
-
GIT_COMMIT_ERROR: "git-commit",
|
|
1174
|
-
GIT_TAG_ERROR: "git-commit",
|
|
1175
|
-
NPM_PUBLISH_ERROR: "npm-publish",
|
|
1176
|
-
NPM_AUTH_ERROR: "npm-publish",
|
|
1177
|
-
CARGO_PUBLISH_ERROR: "cargo-publish",
|
|
1178
|
-
CARGO_AUTH_ERROR: "cargo-publish",
|
|
1179
|
-
VERIFICATION_FAILED: "verify",
|
|
1180
|
-
GIT_PUSH_ERROR: "git-push",
|
|
1181
|
-
GITHUB_RELEASE_ERROR: "github-release"
|
|
1182
|
-
};
|
|
1183
|
-
return codeToStage[error.code] ?? "unknown";
|
|
1184
|
-
}
|
|
1185
|
-
return "unknown";
|
|
1186
|
-
}
|
|
1187
|
-
async function runPipeline(input, config, options) {
|
|
1188
|
-
const cwd = process.cwd();
|
|
1189
|
-
const ctx = {
|
|
1190
|
-
input,
|
|
1191
|
-
config,
|
|
1192
|
-
cliOptions: options,
|
|
1193
|
-
packageManager: detectPackageManager(cwd),
|
|
1194
|
-
cwd,
|
|
1195
|
-
releaseNotes: options.releaseNotes,
|
|
1196
|
-
additionalFiles: options.additionalFiles,
|
|
1197
|
-
output: {
|
|
1198
|
-
dryRun: options.dryRun,
|
|
1199
|
-
git: { committed: false, tags: [], pushed: false },
|
|
1200
|
-
npm: [],
|
|
1201
|
-
cargo: [],
|
|
1202
|
-
verification: [],
|
|
1203
|
-
githubReleases: []
|
|
1204
|
-
}
|
|
1205
|
-
};
|
|
1206
|
-
try {
|
|
1207
|
-
await runPrepareStage(ctx);
|
|
1208
|
-
if (options.skipGitCommit && !options.skipGit) {
|
|
1209
|
-
ctx.output.git.committed = !!input.commitMessage;
|
|
1210
|
-
ctx.output.git.tags = [...input.tags];
|
|
1211
|
-
} else if (!options.skipGit) {
|
|
1212
|
-
await runGitCommitStage(ctx);
|
|
1213
|
-
}
|
|
1214
|
-
if (!options.skipPublish) {
|
|
1215
|
-
if (options.registry === "all" || options.registry === "npm") {
|
|
1216
|
-
await runNpmPublishStage(ctx);
|
|
1217
|
-
}
|
|
1218
|
-
if (options.registry === "all" || options.registry === "cargo") {
|
|
1219
|
-
await runCargoPublishStage(ctx);
|
|
1220
|
-
}
|
|
1221
|
-
}
|
|
1222
|
-
if (!options.skipVerification && !options.skipPublish) {
|
|
1223
|
-
await runVerifyStage(ctx);
|
|
1224
|
-
}
|
|
1225
|
-
if (!options.skipGit) {
|
|
1226
|
-
await runGitPushStage(ctx);
|
|
1227
|
-
}
|
|
1228
|
-
if (!options.skipGithubRelease) {
|
|
1229
|
-
await runGithubReleaseStage(ctx);
|
|
1230
|
-
}
|
|
1231
|
-
} catch (error) {
|
|
1232
|
-
const stageName = inferStageName(error);
|
|
1233
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
1234
|
-
throw new PipelineError(message, stageName, ctx.output, error instanceof Error ? error : void 0);
|
|
1235
|
-
}
|
|
1236
|
-
return ctx.output;
|
|
1237
|
-
}
|
|
1238
|
-
|
|
1239
|
-
// src/stages/input.ts
|
|
1240
|
-
import * as fs8 from "fs";
|
|
1241
|
-
import { info as info8 } from "@releasekit/core";
|
|
1242
|
-
import { z } from "zod";
|
|
1243
|
-
var VersionChangelogEntrySchema = z.object({
|
|
1244
|
-
type: z.string(),
|
|
1245
|
-
description: z.string(),
|
|
1246
|
-
issueIds: z.array(z.string()).optional(),
|
|
1247
|
-
scope: z.string().optional(),
|
|
1248
|
-
originalType: z.string().optional()
|
|
1249
|
-
});
|
|
1250
|
-
var VersionPackageChangelogSchema = z.object({
|
|
1251
|
-
packageName: z.string(),
|
|
1252
|
-
version: z.string(),
|
|
1253
|
-
previousVersion: z.string().nullable(),
|
|
1254
|
-
revisionRange: z.string(),
|
|
1255
|
-
repoUrl: z.string().nullable(),
|
|
1256
|
-
entries: z.array(VersionChangelogEntrySchema)
|
|
1257
|
-
});
|
|
1258
|
-
var VersionPackageUpdateSchema = z.object({
|
|
1259
|
-
packageName: z.string(),
|
|
1260
|
-
newVersion: z.string(),
|
|
1261
|
-
filePath: z.string()
|
|
1262
|
-
});
|
|
1263
|
-
var VersionOutputSchema = z.object({
|
|
1264
|
-
dryRun: z.boolean(),
|
|
1265
|
-
updates: z.array(VersionPackageUpdateSchema),
|
|
1266
|
-
changelogs: z.array(VersionPackageChangelogSchema),
|
|
1267
|
-
commitMessage: z.string().optional(),
|
|
1268
|
-
tags: z.array(z.string())
|
|
1269
|
-
});
|
|
1270
|
-
async function parseInput(inputPath) {
|
|
1271
|
-
let raw;
|
|
1272
|
-
if (inputPath) {
|
|
1273
|
-
try {
|
|
1274
|
-
raw = fs8.readFileSync(inputPath, "utf-8");
|
|
1275
|
-
} catch {
|
|
1276
|
-
throw createPublishError("INPUT_PARSE_ERROR" /* INPUT_PARSE_ERROR */, `Could not read file: ${inputPath}`);
|
|
1277
|
-
}
|
|
1278
|
-
} else {
|
|
1279
|
-
raw = await readStdin();
|
|
1280
|
-
}
|
|
1281
|
-
let parsed;
|
|
1282
|
-
try {
|
|
1283
|
-
parsed = JSON.parse(raw);
|
|
1284
|
-
} catch {
|
|
1285
|
-
throw createPublishError("INPUT_PARSE_ERROR" /* INPUT_PARSE_ERROR */, "Input is not valid JSON");
|
|
1286
|
-
}
|
|
1287
|
-
const result = VersionOutputSchema.safeParse(parsed);
|
|
1288
|
-
if (!result.success) {
|
|
1289
|
-
const issues = result.error.issues.map((i) => ` ${i.path.join(".")}: ${i.message}`).join("\n");
|
|
1290
|
-
throw createPublishError("INPUT_VALIDATION_ERROR" /* INPUT_VALIDATION_ERROR */, `Schema validation failed:
|
|
1291
|
-
${issues}`);
|
|
1292
|
-
}
|
|
1293
|
-
if (result.data.updates.length === 0) {
|
|
1294
|
-
info8("No package updates in version output \u2014 pipeline will be a no-op");
|
|
1295
|
-
}
|
|
1296
|
-
return result.data;
|
|
1297
|
-
}
|
|
1298
|
-
async function readStdin() {
|
|
1299
|
-
const chunks = [];
|
|
1300
|
-
for await (const chunk of process.stdin) {
|
|
1301
|
-
chunks.push(chunk);
|
|
1302
|
-
}
|
|
1303
|
-
return chunks.join("");
|
|
1304
|
-
}
|
|
1305
|
-
|
|
1306
|
-
export {
|
|
1307
|
-
loadConfig,
|
|
1308
|
-
getDefaultConfig2 as getDefaultConfig,
|
|
1309
|
-
BasePublishError,
|
|
1310
|
-
PublishError,
|
|
1311
|
-
PipelineError,
|
|
1312
|
-
PublishErrorCode,
|
|
1313
|
-
createPublishError,
|
|
1314
|
-
detectNpmAuth,
|
|
1315
|
-
hasCargoAuth,
|
|
1316
|
-
parseCargoToml,
|
|
1317
|
-
updateCargoVersion,
|
|
1318
|
-
extractPathDeps,
|
|
1319
|
-
isPrerelease,
|
|
1320
|
-
getDistTag,
|
|
1321
|
-
detectPackageManager,
|
|
1322
|
-
runPipeline,
|
|
1323
|
-
parseInput
|
|
1324
|
-
};
|