@releasekit/publish 0.2.0 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -0
- package/dist/{chunk-H7AKSLZP.js → chunk-PJUNQA6B.js} +634 -137
- package/dist/cli.d.ts +9 -0
- package/dist/cli.js +5 -3
- package/dist/index.d.ts +9 -165
- package/dist/index.js +1 -1
- package/package.json +7 -12
- package/dist/cli.cjs +0 -1311
- package/dist/cli.d.cts +0 -1
- package/dist/index.cjs +0 -1322
- package/dist/index.d.cts +0 -165
|
@@ -1,5 +1,456 @@
|
|
|
1
|
-
//
|
|
2
|
-
import
|
|
1
|
+
// ../core/dist/index.js
|
|
2
|
+
import chalk from "chalk";
|
|
3
|
+
var LOG_LEVELS = {
|
|
4
|
+
error: 0,
|
|
5
|
+
warn: 1,
|
|
6
|
+
info: 2,
|
|
7
|
+
debug: 3,
|
|
8
|
+
trace: 4
|
|
9
|
+
};
|
|
10
|
+
var PREFIXES = {
|
|
11
|
+
error: "[ERROR]",
|
|
12
|
+
warn: "[WARN]",
|
|
13
|
+
info: "[INFO]",
|
|
14
|
+
debug: "[DEBUG]",
|
|
15
|
+
trace: "[TRACE]"
|
|
16
|
+
};
|
|
17
|
+
var COLORS = {
|
|
18
|
+
error: chalk.red,
|
|
19
|
+
warn: chalk.yellow,
|
|
20
|
+
info: chalk.blue,
|
|
21
|
+
debug: chalk.gray,
|
|
22
|
+
trace: chalk.dim
|
|
23
|
+
};
|
|
24
|
+
var currentLevel = "info";
|
|
25
|
+
var quietMode = false;
|
|
26
|
+
function setLogLevel(level) {
|
|
27
|
+
currentLevel = level;
|
|
28
|
+
}
|
|
29
|
+
function setJsonMode(_json) {
|
|
30
|
+
}
|
|
31
|
+
function shouldLog(level) {
|
|
32
|
+
if (quietMode && level !== "error") return false;
|
|
33
|
+
return LOG_LEVELS[level] <= LOG_LEVELS[currentLevel];
|
|
34
|
+
}
|
|
35
|
+
function log(message, level = "info") {
|
|
36
|
+
if (!shouldLog(level)) return;
|
|
37
|
+
const formatted = COLORS[level](`${PREFIXES[level]} ${message}`);
|
|
38
|
+
console.error(formatted);
|
|
39
|
+
}
|
|
40
|
+
function warn(message) {
|
|
41
|
+
log(message, "warn");
|
|
42
|
+
}
|
|
43
|
+
function info(message) {
|
|
44
|
+
log(message, "info");
|
|
45
|
+
}
|
|
46
|
+
function success(message) {
|
|
47
|
+
if (!shouldLog("info")) return;
|
|
48
|
+
console.error(chalk.green(`[SUCCESS] ${message}`));
|
|
49
|
+
}
|
|
50
|
+
function debug(message) {
|
|
51
|
+
log(message, "debug");
|
|
52
|
+
}
|
|
53
|
+
var ReleaseKitError = class _ReleaseKitError extends Error {
|
|
54
|
+
constructor(message) {
|
|
55
|
+
super(message);
|
|
56
|
+
this.name = this.constructor.name;
|
|
57
|
+
}
|
|
58
|
+
logError() {
|
|
59
|
+
log(this.message, "error");
|
|
60
|
+
if (this.suggestions.length > 0) {
|
|
61
|
+
log("\nSuggested solutions:", "info");
|
|
62
|
+
for (const [i, suggestion] of this.suggestions.entries()) {
|
|
63
|
+
log(`${i + 1}. ${suggestion}`, "info");
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
static isReleaseKitError(error2) {
|
|
68
|
+
return error2 instanceof _ReleaseKitError;
|
|
69
|
+
}
|
|
70
|
+
};
|
|
71
|
+
var EXIT_CODES = {
|
|
72
|
+
SUCCESS: 0,
|
|
73
|
+
GENERAL_ERROR: 1,
|
|
74
|
+
CONFIG_ERROR: 2,
|
|
75
|
+
INPUT_ERROR: 3,
|
|
76
|
+
TEMPLATE_ERROR: 4,
|
|
77
|
+
LLM_ERROR: 5,
|
|
78
|
+
GITHUB_ERROR: 6,
|
|
79
|
+
GIT_ERROR: 7,
|
|
80
|
+
VERSION_ERROR: 8,
|
|
81
|
+
PUBLISH_ERROR: 9
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
// ../config/dist/index.js
|
|
85
|
+
import * as fs from "fs";
|
|
86
|
+
import * as path from "path";
|
|
87
|
+
import * as TOML from "smol-toml";
|
|
88
|
+
import * as fs3 from "fs";
|
|
89
|
+
import * as path3 from "path";
|
|
90
|
+
import { z as z2 } from "zod";
|
|
91
|
+
import { z } from "zod";
|
|
92
|
+
import * as fs2 from "fs";
|
|
93
|
+
import * as os from "os";
|
|
94
|
+
import * as path2 from "path";
|
|
95
|
+
function parseCargoToml(cargoPath) {
|
|
96
|
+
const content = fs.readFileSync(cargoPath, "utf-8");
|
|
97
|
+
return TOML.parse(content);
|
|
98
|
+
}
|
|
99
|
+
var ConfigError = class extends ReleaseKitError {
|
|
100
|
+
code = "CONFIG_ERROR";
|
|
101
|
+
suggestions;
|
|
102
|
+
constructor(message, suggestions) {
|
|
103
|
+
super(message);
|
|
104
|
+
this.suggestions = suggestions ?? [
|
|
105
|
+
"Check that releasekit.config.json exists and is valid JSON",
|
|
106
|
+
"Run with --verbose for more details"
|
|
107
|
+
];
|
|
108
|
+
}
|
|
109
|
+
};
|
|
110
|
+
function mergeGitConfig(topLevel, packageLevel) {
|
|
111
|
+
if (!topLevel && !packageLevel) return void 0;
|
|
112
|
+
const base = topLevel ?? {
|
|
113
|
+
remote: "origin",
|
|
114
|
+
branch: "main",
|
|
115
|
+
pushMethod: "auto"
|
|
116
|
+
};
|
|
117
|
+
if (!packageLevel) return base;
|
|
118
|
+
return {
|
|
119
|
+
remote: packageLevel.remote ?? base.remote,
|
|
120
|
+
branch: packageLevel.branch ?? base.branch,
|
|
121
|
+
pushMethod: packageLevel.pushMethod ?? base.pushMethod,
|
|
122
|
+
httpsTokenEnv: packageLevel.httpsTokenEnv ?? base.httpsTokenEnv,
|
|
123
|
+
push: packageLevel.push,
|
|
124
|
+
skipHooks: packageLevel.skipHooks ?? base.skipHooks
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
var MAX_JSONC_LENGTH = 1e5;
|
|
128
|
+
function parseJsonc(content) {
|
|
129
|
+
if (content.length > MAX_JSONC_LENGTH) {
|
|
130
|
+
throw new Error(`JSONC content too long: ${content.length} characters (max ${MAX_JSONC_LENGTH})`);
|
|
131
|
+
}
|
|
132
|
+
try {
|
|
133
|
+
return JSON.parse(content);
|
|
134
|
+
} catch {
|
|
135
|
+
const cleaned = content.replace(/\/\/[^\r\n]{0,10000}$/gm, "").replace(/\/\*[\s\S]{0,50000}?\*\//g, "").trim();
|
|
136
|
+
return JSON.parse(cleaned);
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
var GitConfigSchema = z.object({
|
|
140
|
+
remote: z.string().default("origin"),
|
|
141
|
+
branch: z.string().default("main"),
|
|
142
|
+
pushMethod: z.enum(["auto", "ssh", "https"]).default("auto"),
|
|
143
|
+
/**
|
|
144
|
+
* Optional env var name containing a GitHub token for HTTPS pushes.
|
|
145
|
+
* When set, publish steps can use this token without mutating git remotes.
|
|
146
|
+
*/
|
|
147
|
+
httpsTokenEnv: z.string().optional(),
|
|
148
|
+
push: z.boolean().optional(),
|
|
149
|
+
skipHooks: z.boolean().optional()
|
|
150
|
+
});
|
|
151
|
+
var MonorepoConfigSchema = z.object({
|
|
152
|
+
mode: z.enum(["root", "packages", "both"]).optional(),
|
|
153
|
+
rootPath: z.string().optional(),
|
|
154
|
+
packagesPath: z.string().optional(),
|
|
155
|
+
mainPackage: z.string().optional()
|
|
156
|
+
});
|
|
157
|
+
var BranchPatternSchema = z.object({
|
|
158
|
+
pattern: z.string(),
|
|
159
|
+
releaseType: z.enum(["major", "minor", "patch", "prerelease"])
|
|
160
|
+
});
|
|
161
|
+
var VersionCargoConfigSchema = z.object({
|
|
162
|
+
enabled: z.boolean().default(true),
|
|
163
|
+
paths: z.array(z.string()).optional()
|
|
164
|
+
});
|
|
165
|
+
var VersionConfigSchema = z.object({
|
|
166
|
+
tagTemplate: z.string().default("v{version}"),
|
|
167
|
+
packageSpecificTags: z.boolean().default(false),
|
|
168
|
+
preset: z.string().default("conventional"),
|
|
169
|
+
sync: z.boolean().default(true),
|
|
170
|
+
packages: z.array(z.string()).default([]),
|
|
171
|
+
mainPackage: z.string().optional(),
|
|
172
|
+
updateInternalDependencies: z.enum(["major", "minor", "patch", "no-internal-update"]).default("minor"),
|
|
173
|
+
skip: z.array(z.string()).optional(),
|
|
174
|
+
commitMessage: z.string().optional(),
|
|
175
|
+
versionStrategy: z.enum(["branchPattern", "commitMessage"]).default("commitMessage"),
|
|
176
|
+
branchPatterns: z.array(BranchPatternSchema).optional(),
|
|
177
|
+
defaultReleaseType: z.enum(["major", "minor", "patch", "prerelease"]).optional(),
|
|
178
|
+
mismatchStrategy: z.enum(["error", "warn", "ignore", "prefer-package", "prefer-git"]).default("warn"),
|
|
179
|
+
versionPrefix: z.string().default(""),
|
|
180
|
+
prereleaseIdentifier: z.string().optional(),
|
|
181
|
+
strictReachable: z.boolean().default(false),
|
|
182
|
+
cargo: VersionCargoConfigSchema.optional()
|
|
183
|
+
});
|
|
184
|
+
var NpmConfigSchema = z.object({
|
|
185
|
+
enabled: z.boolean().default(true),
|
|
186
|
+
auth: z.enum(["auto", "oidc", "token"]).default("auto"),
|
|
187
|
+
provenance: z.boolean().default(true),
|
|
188
|
+
access: z.enum(["public", "restricted"]).default("public"),
|
|
189
|
+
registry: z.string().default("https://registry.npmjs.org"),
|
|
190
|
+
copyFiles: z.array(z.string()).default(["LICENSE"]),
|
|
191
|
+
tag: z.string().default("latest")
|
|
192
|
+
});
|
|
193
|
+
var CargoPublishConfigSchema = z.object({
|
|
194
|
+
enabled: z.boolean().default(false),
|
|
195
|
+
noVerify: z.boolean().default(false),
|
|
196
|
+
publishOrder: z.array(z.string()).default([]),
|
|
197
|
+
clean: z.boolean().default(false)
|
|
198
|
+
});
|
|
199
|
+
var PublishGitConfigSchema = z.object({
|
|
200
|
+
push: z.boolean().default(true),
|
|
201
|
+
pushMethod: z.enum(["auto", "ssh", "https"]).optional(),
|
|
202
|
+
remote: z.string().optional(),
|
|
203
|
+
branch: z.string().optional(),
|
|
204
|
+
httpsTokenEnv: z.string().optional(),
|
|
205
|
+
skipHooks: z.boolean().optional()
|
|
206
|
+
});
|
|
207
|
+
var GitHubReleaseConfigSchema = z.object({
|
|
208
|
+
enabled: z.boolean().default(true),
|
|
209
|
+
draft: z.boolean().default(true),
|
|
210
|
+
perPackage: z.boolean().default(true),
|
|
211
|
+
prerelease: z.union([z.literal("auto"), z.boolean()]).default("auto"),
|
|
212
|
+
/**
|
|
213
|
+
* Controls how release notes are sourced for GitHub releases.
|
|
214
|
+
* - 'auto': Use RELEASE_NOTES.md if it exists, then per-package changelog
|
|
215
|
+
* data from the version output, then GitHub's auto-generated notes.
|
|
216
|
+
* - 'github': Always use GitHub's auto-generated notes.
|
|
217
|
+
* - 'none': No notes body.
|
|
218
|
+
* - Any other string: Treated as a file path to read notes from.
|
|
219
|
+
*/
|
|
220
|
+
releaseNotes: z.union([z.literal("auto"), z.literal("github"), z.literal("none"), z.string()]).default("auto")
|
|
221
|
+
});
|
|
222
|
+
var VerifyRegistryConfigSchema = z.object({
|
|
223
|
+
enabled: z.boolean().default(true),
|
|
224
|
+
maxAttempts: z.number().int().positive().default(5),
|
|
225
|
+
initialDelay: z.number().int().positive().default(15e3),
|
|
226
|
+
backoffMultiplier: z.number().positive().default(2)
|
|
227
|
+
});
|
|
228
|
+
var VerifyConfigSchema = z.object({
|
|
229
|
+
npm: VerifyRegistryConfigSchema.default({
|
|
230
|
+
enabled: true,
|
|
231
|
+
maxAttempts: 5,
|
|
232
|
+
initialDelay: 15e3,
|
|
233
|
+
backoffMultiplier: 2
|
|
234
|
+
}),
|
|
235
|
+
cargo: VerifyRegistryConfigSchema.default({
|
|
236
|
+
enabled: true,
|
|
237
|
+
maxAttempts: 10,
|
|
238
|
+
initialDelay: 3e4,
|
|
239
|
+
backoffMultiplier: 2
|
|
240
|
+
})
|
|
241
|
+
});
|
|
242
|
+
var PublishConfigSchema = z.object({
|
|
243
|
+
git: PublishGitConfigSchema.optional(),
|
|
244
|
+
npm: NpmConfigSchema.default({
|
|
245
|
+
enabled: true,
|
|
246
|
+
auth: "auto",
|
|
247
|
+
provenance: true,
|
|
248
|
+
access: "public",
|
|
249
|
+
registry: "https://registry.npmjs.org",
|
|
250
|
+
copyFiles: ["LICENSE"],
|
|
251
|
+
tag: "latest"
|
|
252
|
+
}),
|
|
253
|
+
cargo: CargoPublishConfigSchema.default({
|
|
254
|
+
enabled: false,
|
|
255
|
+
noVerify: false,
|
|
256
|
+
publishOrder: [],
|
|
257
|
+
clean: false
|
|
258
|
+
}),
|
|
259
|
+
githubRelease: GitHubReleaseConfigSchema.default({
|
|
260
|
+
enabled: true,
|
|
261
|
+
draft: true,
|
|
262
|
+
perPackage: true,
|
|
263
|
+
prerelease: "auto",
|
|
264
|
+
releaseNotes: "auto"
|
|
265
|
+
}),
|
|
266
|
+
verify: VerifyConfigSchema.default({
|
|
267
|
+
npm: {
|
|
268
|
+
enabled: true,
|
|
269
|
+
maxAttempts: 5,
|
|
270
|
+
initialDelay: 15e3,
|
|
271
|
+
backoffMultiplier: 2
|
|
272
|
+
},
|
|
273
|
+
cargo: {
|
|
274
|
+
enabled: true,
|
|
275
|
+
maxAttempts: 10,
|
|
276
|
+
initialDelay: 3e4,
|
|
277
|
+
backoffMultiplier: 2
|
|
278
|
+
}
|
|
279
|
+
})
|
|
280
|
+
});
|
|
281
|
+
var TemplateConfigSchema = z.object({
|
|
282
|
+
path: z.string().optional(),
|
|
283
|
+
engine: z.enum(["handlebars", "liquid", "ejs"]).optional()
|
|
284
|
+
});
|
|
285
|
+
var OutputConfigSchema = z.object({
|
|
286
|
+
format: z.enum(["markdown", "github-release", "json"]),
|
|
287
|
+
file: z.string().optional(),
|
|
288
|
+
options: z.record(z.string(), z.unknown()).optional(),
|
|
289
|
+
templates: TemplateConfigSchema.optional()
|
|
290
|
+
});
|
|
291
|
+
var LLMOptionsSchema = z.object({
|
|
292
|
+
timeout: z.number().optional(),
|
|
293
|
+
maxTokens: z.number().optional(),
|
|
294
|
+
temperature: z.number().optional()
|
|
295
|
+
});
|
|
296
|
+
var LLMRetryConfigSchema = z.object({
|
|
297
|
+
maxAttempts: z.number().int().positive().optional(),
|
|
298
|
+
initialDelay: z.number().nonnegative().optional(),
|
|
299
|
+
maxDelay: z.number().positive().optional(),
|
|
300
|
+
backoffFactor: z.number().positive().optional()
|
|
301
|
+
});
|
|
302
|
+
var LLMTasksConfigSchema = z.object({
|
|
303
|
+
summarize: z.boolean().optional(),
|
|
304
|
+
enhance: z.boolean().optional(),
|
|
305
|
+
categorize: z.boolean().optional(),
|
|
306
|
+
releaseNotes: z.boolean().optional()
|
|
307
|
+
});
|
|
308
|
+
var LLMCategorySchema = z.object({
|
|
309
|
+
name: z.string(),
|
|
310
|
+
description: z.string(),
|
|
311
|
+
scopes: z.array(z.string()).optional()
|
|
312
|
+
});
|
|
313
|
+
var ScopeRulesSchema = z.object({
|
|
314
|
+
allowed: z.array(z.string()).optional(),
|
|
315
|
+
caseSensitive: z.boolean().default(false),
|
|
316
|
+
invalidScopeAction: z.enum(["remove", "keep", "fallback"]).default("remove"),
|
|
317
|
+
fallbackScope: z.string().optional()
|
|
318
|
+
});
|
|
319
|
+
var ScopeConfigSchema = z.object({
|
|
320
|
+
mode: z.enum(["restricted", "packages", "none", "unrestricted"]).default("unrestricted"),
|
|
321
|
+
rules: ScopeRulesSchema.optional()
|
|
322
|
+
});
|
|
323
|
+
var LLMPromptOverridesSchema = z.object({
|
|
324
|
+
enhance: z.string().optional(),
|
|
325
|
+
categorize: z.string().optional(),
|
|
326
|
+
enhanceAndCategorize: z.string().optional(),
|
|
327
|
+
summarize: z.string().optional(),
|
|
328
|
+
releaseNotes: z.string().optional()
|
|
329
|
+
});
|
|
330
|
+
var LLMPromptsConfigSchema = z.object({
|
|
331
|
+
instructions: LLMPromptOverridesSchema.optional(),
|
|
332
|
+
templates: LLMPromptOverridesSchema.optional()
|
|
333
|
+
});
|
|
334
|
+
var LLMConfigSchema = z.object({
|
|
335
|
+
provider: z.string(),
|
|
336
|
+
model: z.string(),
|
|
337
|
+
baseURL: z.string().optional(),
|
|
338
|
+
apiKey: z.string().optional(),
|
|
339
|
+
options: LLMOptionsSchema.optional(),
|
|
340
|
+
concurrency: z.number().int().positive().optional(),
|
|
341
|
+
retry: LLMRetryConfigSchema.optional(),
|
|
342
|
+
tasks: LLMTasksConfigSchema.optional(),
|
|
343
|
+
categories: z.array(LLMCategorySchema).optional(),
|
|
344
|
+
style: z.string().optional(),
|
|
345
|
+
scopes: ScopeConfigSchema.optional(),
|
|
346
|
+
prompts: LLMPromptsConfigSchema.optional()
|
|
347
|
+
});
|
|
348
|
+
var NotesInputConfigSchema = z.object({
|
|
349
|
+
source: z.string().optional(),
|
|
350
|
+
file: z.string().optional()
|
|
351
|
+
});
|
|
352
|
+
var NotesConfigSchema = z.object({
|
|
353
|
+
input: NotesInputConfigSchema.optional(),
|
|
354
|
+
output: z.array(OutputConfigSchema).default([{ format: "markdown", file: "CHANGELOG.md" }]),
|
|
355
|
+
monorepo: MonorepoConfigSchema.optional(),
|
|
356
|
+
templates: TemplateConfigSchema.optional(),
|
|
357
|
+
llm: LLMConfigSchema.optional(),
|
|
358
|
+
updateStrategy: z.enum(["prepend", "regenerate"]).default("prepend")
|
|
359
|
+
});
|
|
360
|
+
var ReleaseKitConfigSchema = z.object({
|
|
361
|
+
git: GitConfigSchema.optional(),
|
|
362
|
+
monorepo: MonorepoConfigSchema.optional(),
|
|
363
|
+
version: VersionConfigSchema.optional(),
|
|
364
|
+
publish: PublishConfigSchema.optional(),
|
|
365
|
+
notes: NotesConfigSchema.optional()
|
|
366
|
+
});
|
|
367
|
+
var MAX_INPUT_LENGTH = 1e4;
|
|
368
|
+
function substituteVariables(value) {
|
|
369
|
+
if (value.length > MAX_INPUT_LENGTH) {
|
|
370
|
+
throw new Error(`Input too long: ${value.length} characters (max ${MAX_INPUT_LENGTH})`);
|
|
371
|
+
}
|
|
372
|
+
const envPattern = /\{env:([^}]{1,1000})\}/g;
|
|
373
|
+
const filePattern = /\{file:([^}]{1,1000})\}/g;
|
|
374
|
+
let result = value;
|
|
375
|
+
result = result.replace(envPattern, (_, varName) => {
|
|
376
|
+
return process.env[varName] ?? "";
|
|
377
|
+
});
|
|
378
|
+
result = result.replace(filePattern, (_, filePath) => {
|
|
379
|
+
const expandedPath = filePath.startsWith("~") ? path2.join(os.homedir(), filePath.slice(1)) : filePath;
|
|
380
|
+
try {
|
|
381
|
+
return fs2.readFileSync(expandedPath, "utf-8").trim();
|
|
382
|
+
} catch {
|
|
383
|
+
return "";
|
|
384
|
+
}
|
|
385
|
+
});
|
|
386
|
+
return result;
|
|
387
|
+
}
|
|
388
|
+
var SOLE_REFERENCE_PATTERN = /^\{(?:env|file):[^}]+\}$/;
|
|
389
|
+
function substituteInObject(obj) {
|
|
390
|
+
if (typeof obj === "string") {
|
|
391
|
+
const result = substituteVariables(obj);
|
|
392
|
+
if (result === "" && SOLE_REFERENCE_PATTERN.test(obj)) {
|
|
393
|
+
return void 0;
|
|
394
|
+
}
|
|
395
|
+
return result;
|
|
396
|
+
}
|
|
397
|
+
if (Array.isArray(obj)) {
|
|
398
|
+
return obj.map((item) => substituteInObject(item));
|
|
399
|
+
}
|
|
400
|
+
if (obj && typeof obj === "object") {
|
|
401
|
+
const result = {};
|
|
402
|
+
for (const [key, value] of Object.entries(obj)) {
|
|
403
|
+
result[key] = substituteInObject(value);
|
|
404
|
+
}
|
|
405
|
+
return result;
|
|
406
|
+
}
|
|
407
|
+
return obj;
|
|
408
|
+
}
|
|
409
|
+
var AUTH_DIR = path2.join(os.homedir(), ".config", "releasekit");
|
|
410
|
+
var AUTH_FILE = path2.join(AUTH_DIR, "auth.json");
|
|
411
|
+
var CONFIG_FILE = "releasekit.config.json";
|
|
412
|
+
function loadConfigFile(configPath) {
|
|
413
|
+
if (!fs3.existsSync(configPath)) {
|
|
414
|
+
return {};
|
|
415
|
+
}
|
|
416
|
+
try {
|
|
417
|
+
const content = fs3.readFileSync(configPath, "utf-8");
|
|
418
|
+
const parsed = parseJsonc(content);
|
|
419
|
+
const substituted = substituteInObject(parsed);
|
|
420
|
+
return ReleaseKitConfigSchema.parse(substituted);
|
|
421
|
+
} catch (error) {
|
|
422
|
+
if (error instanceof z2.ZodError) {
|
|
423
|
+
const issues = error.issues.map((i) => ` ${i.path.join(".")}: ${i.message}`).join("\n");
|
|
424
|
+
throw new ConfigError(`Config validation errors:
|
|
425
|
+
${issues}`);
|
|
426
|
+
}
|
|
427
|
+
if (error instanceof SyntaxError) {
|
|
428
|
+
throw new ConfigError(`Invalid JSON in config file: ${error.message}`);
|
|
429
|
+
}
|
|
430
|
+
throw error;
|
|
431
|
+
}
|
|
432
|
+
}
|
|
433
|
+
function loadConfig(options) {
|
|
434
|
+
const cwd = options?.cwd ?? process.cwd();
|
|
435
|
+
const configPath = options?.configPath ?? path3.join(cwd, CONFIG_FILE);
|
|
436
|
+
return loadConfigFile(configPath);
|
|
437
|
+
}
|
|
438
|
+
function loadPublishConfig(options) {
|
|
439
|
+
const config = loadConfig(options);
|
|
440
|
+
if (!config.publish) return void 0;
|
|
441
|
+
const mergedGit = mergeGitConfig(config.git, config.publish.git);
|
|
442
|
+
return {
|
|
443
|
+
...config.publish,
|
|
444
|
+
git: mergedGit ? {
|
|
445
|
+
push: mergedGit.push ?? true,
|
|
446
|
+
pushMethod: mergedGit.pushMethod,
|
|
447
|
+
remote: mergedGit.remote,
|
|
448
|
+
branch: mergedGit.branch,
|
|
449
|
+
httpsTokenEnv: mergedGit.httpsTokenEnv,
|
|
450
|
+
skipHooks: mergedGit.skipHooks
|
|
451
|
+
} : void 0
|
|
452
|
+
};
|
|
453
|
+
}
|
|
3
454
|
|
|
4
455
|
// src/types.ts
|
|
5
456
|
function getDefaultConfig() {
|
|
@@ -30,9 +481,9 @@ function getDefaultConfig() {
|
|
|
30
481
|
githubRelease: {
|
|
31
482
|
enabled: true,
|
|
32
483
|
draft: true,
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
484
|
+
perPackage: true,
|
|
485
|
+
prerelease: "auto",
|
|
486
|
+
releaseNotes: "auto"
|
|
36
487
|
},
|
|
37
488
|
verify: {
|
|
38
489
|
npm: {
|
|
@@ -80,10 +531,9 @@ function toPublishConfig(config) {
|
|
|
80
531
|
githubRelease: {
|
|
81
532
|
enabled: config.githubRelease?.enabled ?? defaults.githubRelease.enabled,
|
|
82
533
|
draft: config.githubRelease?.draft ?? defaults.githubRelease.draft,
|
|
83
|
-
generateNotes: config.githubRelease?.generateNotes ?? defaults.githubRelease.generateNotes,
|
|
84
534
|
perPackage: config.githubRelease?.perPackage ?? defaults.githubRelease.perPackage,
|
|
85
535
|
prerelease: config.githubRelease?.prerelease ?? defaults.githubRelease.prerelease,
|
|
86
|
-
|
|
536
|
+
releaseNotes: config.githubRelease?.releaseNotes ?? defaults.githubRelease.releaseNotes
|
|
87
537
|
},
|
|
88
538
|
verify: {
|
|
89
539
|
npm: {
|
|
@@ -103,7 +553,7 @@ function toPublishConfig(config) {
|
|
|
103
553
|
}
|
|
104
554
|
|
|
105
555
|
// src/config.ts
|
|
106
|
-
function
|
|
556
|
+
function loadConfig2(options) {
|
|
107
557
|
const baseConfig = loadPublishConfig(options);
|
|
108
558
|
return toPublishConfig(baseConfig);
|
|
109
559
|
}
|
|
@@ -112,7 +562,6 @@ function getDefaultConfig2() {
|
|
|
112
562
|
}
|
|
113
563
|
|
|
114
564
|
// src/errors/index.ts
|
|
115
|
-
import { ReleaseKitError } from "@releasekit/core";
|
|
116
565
|
var BasePublishError = class _BasePublishError extends ReleaseKitError {
|
|
117
566
|
code;
|
|
118
567
|
suggestions;
|
|
@@ -251,7 +700,6 @@ function createPublishError(code, details) {
|
|
|
251
700
|
|
|
252
701
|
// src/utils/exec.ts
|
|
253
702
|
import { execFile } from "child_process";
|
|
254
|
-
import { debug, info } from "@releasekit/core";
|
|
255
703
|
function redactArg(arg) {
|
|
256
704
|
try {
|
|
257
705
|
const url = new URL(arg);
|
|
@@ -339,15 +787,14 @@ async function detectGitPushMethod(remote, cwd) {
|
|
|
339
787
|
}
|
|
340
788
|
|
|
341
789
|
// src/utils/cargo.ts
|
|
342
|
-
import * as
|
|
343
|
-
import
|
|
344
|
-
import * as TOML from "smol-toml";
|
|
790
|
+
import * as fs4 from "fs";
|
|
791
|
+
import * as TOML2 from "smol-toml";
|
|
345
792
|
function updateCargoVersion(cargoPath, newVersion) {
|
|
346
793
|
try {
|
|
347
794
|
const cargo = parseCargoToml(cargoPath);
|
|
348
795
|
if (cargo.package) {
|
|
349
796
|
cargo.package.version = newVersion;
|
|
350
|
-
|
|
797
|
+
fs4.writeFileSync(cargoPath, TOML2.stringify(cargo));
|
|
351
798
|
}
|
|
352
799
|
} catch (error) {
|
|
353
800
|
throw createPublishError(
|
|
@@ -384,11 +831,11 @@ function getDistTag(version, defaultTag = "latest") {
|
|
|
384
831
|
}
|
|
385
832
|
|
|
386
833
|
// src/utils/package-manager.ts
|
|
387
|
-
import * as
|
|
388
|
-
import * as
|
|
834
|
+
import * as fs5 from "fs";
|
|
835
|
+
import * as path4 from "path";
|
|
389
836
|
function detectPackageManager(cwd) {
|
|
390
|
-
if (
|
|
391
|
-
if (
|
|
837
|
+
if (fs5.existsSync(path4.join(cwd, "pnpm-lock.yaml"))) return "pnpm";
|
|
838
|
+
if (fs5.existsSync(path4.join(cwd, "yarn.lock"))) return "yarn";
|
|
392
839
|
return "npm";
|
|
393
840
|
}
|
|
394
841
|
function buildPublishCommand(pm, packageName, _packageDir, options) {
|
|
@@ -413,25 +860,24 @@ function buildViewCommand(pm, packageName, version) {
|
|
|
413
860
|
}
|
|
414
861
|
|
|
415
862
|
// src/stages/cargo-publish.ts
|
|
416
|
-
import * as
|
|
417
|
-
import * as
|
|
418
|
-
import { debug as debug2, success, warn } from "@releasekit/core";
|
|
863
|
+
import * as fs6 from "fs";
|
|
864
|
+
import * as path5 from "path";
|
|
419
865
|
async function runCargoPublishStage(ctx) {
|
|
420
866
|
const { input, config, cliOptions, cwd } = ctx;
|
|
421
867
|
const dryRun = cliOptions.dryRun;
|
|
422
868
|
if (!config.cargo.enabled) {
|
|
423
|
-
|
|
869
|
+
debug("Cargo publishing disabled in config");
|
|
424
870
|
return;
|
|
425
871
|
}
|
|
426
872
|
if (!hasCargoAuth() && !dryRun) {
|
|
427
873
|
throw createPublishError("CARGO_AUTH_ERROR" /* CARGO_AUTH_ERROR */, "CARGO_REGISTRY_TOKEN not set");
|
|
428
874
|
}
|
|
429
875
|
const crates = findCrates(
|
|
430
|
-
input.updates.map((u) => ({ dir:
|
|
876
|
+
input.updates.map((u) => ({ dir: path5.dirname(path5.resolve(cwd, u.filePath)), ...u })),
|
|
431
877
|
cwd
|
|
432
878
|
);
|
|
433
879
|
if (crates.length === 0) {
|
|
434
|
-
|
|
880
|
+
debug("No Cargo crates found to publish");
|
|
435
881
|
return;
|
|
436
882
|
}
|
|
437
883
|
const ordered = orderCrates(crates, config.cargo.publishOrder);
|
|
@@ -480,8 +926,8 @@ async function runCargoPublishStage(ctx) {
|
|
|
480
926
|
function findCrates(updates, _cwd) {
|
|
481
927
|
const crates = [];
|
|
482
928
|
for (const update of updates) {
|
|
483
|
-
const cargoPath =
|
|
484
|
-
if (!
|
|
929
|
+
const cargoPath = path5.join(update.dir, "Cargo.toml");
|
|
930
|
+
if (!fs6.existsSync(cargoPath)) {
|
|
485
931
|
continue;
|
|
486
932
|
}
|
|
487
933
|
try {
|
|
@@ -529,9 +975,9 @@ function topologicalSort(crates) {
|
|
|
529
975
|
}
|
|
530
976
|
for (const crate of crates) {
|
|
531
977
|
for (const depPath of crate.pathDeps) {
|
|
532
|
-
const resolvedDir =
|
|
978
|
+
const resolvedDir = path5.resolve(crate.dir, depPath);
|
|
533
979
|
for (const other of crates) {
|
|
534
|
-
if (
|
|
980
|
+
if (path5.resolve(other.dir) === resolvedDir && nameSet.has(other.name)) {
|
|
535
981
|
graph.get(crate.name)?.push(other.name);
|
|
536
982
|
}
|
|
537
983
|
}
|
|
@@ -573,19 +1019,21 @@ function topologicalSort(crates) {
|
|
|
573
1019
|
}
|
|
574
1020
|
|
|
575
1021
|
// src/stages/git-commit.ts
|
|
576
|
-
import * as
|
|
577
|
-
import { info as info2, success as success2 } from "@releasekit/core";
|
|
1022
|
+
import * as path6 from "path";
|
|
578
1023
|
async function runGitCommitStage(ctx) {
|
|
579
1024
|
const { input, config, cliOptions, cwd } = ctx;
|
|
580
1025
|
const dryRun = cliOptions.dryRun;
|
|
581
1026
|
const skipHooks = config.git.skipHooks ?? false;
|
|
582
1027
|
if (!input.commitMessage) {
|
|
583
|
-
|
|
1028
|
+
info("No commit message provided, skipping git commit");
|
|
584
1029
|
return;
|
|
585
1030
|
}
|
|
586
|
-
const filePaths = input.updates.map((u) =>
|
|
1031
|
+
const filePaths = input.updates.map((u) => path6.resolve(cwd, u.filePath));
|
|
1032
|
+
if (ctx.additionalFiles) {
|
|
1033
|
+
filePaths.push(...ctx.additionalFiles.map((f) => path6.resolve(cwd, f)));
|
|
1034
|
+
}
|
|
587
1035
|
if (filePaths.length === 0) {
|
|
588
|
-
|
|
1036
|
+
info("No files to commit");
|
|
589
1037
|
return;
|
|
590
1038
|
}
|
|
591
1039
|
try {
|
|
@@ -613,7 +1061,7 @@ async function runGitCommitStage(ctx) {
|
|
|
613
1061
|
});
|
|
614
1062
|
ctx.output.git.committed = true;
|
|
615
1063
|
if (!dryRun) {
|
|
616
|
-
|
|
1064
|
+
success("Created git commit");
|
|
617
1065
|
}
|
|
618
1066
|
} catch (error) {
|
|
619
1067
|
throw createPublishError(
|
|
@@ -631,7 +1079,7 @@ async function runGitCommitStage(ctx) {
|
|
|
631
1079
|
});
|
|
632
1080
|
ctx.output.git.tags.push(tag);
|
|
633
1081
|
if (!dryRun) {
|
|
634
|
-
|
|
1082
|
+
success(`Created tag: ${tag}`);
|
|
635
1083
|
}
|
|
636
1084
|
} catch (error) {
|
|
637
1085
|
throw createPublishError(
|
|
@@ -643,7 +1091,6 @@ async function runGitCommitStage(ctx) {
|
|
|
643
1091
|
}
|
|
644
1092
|
|
|
645
1093
|
// src/stages/git-push.ts
|
|
646
|
-
import { info as info3, success as success3 } from "@releasekit/core";
|
|
647
1094
|
function toGithubAuthedUrl(remoteUrl, token) {
|
|
648
1095
|
try {
|
|
649
1096
|
const url = new URL(remoteUrl);
|
|
@@ -660,11 +1107,11 @@ async function runGitPushStage(ctx) {
|
|
|
660
1107
|
const { config, cliOptions, cwd, output } = ctx;
|
|
661
1108
|
const dryRun = cliOptions.dryRun;
|
|
662
1109
|
if (!config.git.push) {
|
|
663
|
-
|
|
1110
|
+
info("Git push disabled in config, skipping");
|
|
664
1111
|
return;
|
|
665
1112
|
}
|
|
666
1113
|
if (!output.git.committed && output.git.tags.length === 0) {
|
|
667
|
-
|
|
1114
|
+
info("Nothing to push (no commits or tags created)");
|
|
668
1115
|
return;
|
|
669
1116
|
}
|
|
670
1117
|
const { remote, branch } = config.git;
|
|
@@ -703,7 +1150,7 @@ async function runGitPushStage(ctx) {
|
|
|
703
1150
|
}
|
|
704
1151
|
ctx.output.git.pushed = true;
|
|
705
1152
|
if (!dryRun) {
|
|
706
|
-
|
|
1153
|
+
success(`Pushed to ${remote}/${branch}`);
|
|
707
1154
|
}
|
|
708
1155
|
} catch (error) {
|
|
709
1156
|
throw createPublishError(
|
|
@@ -714,28 +1161,75 @@ async function runGitPushStage(ctx) {
|
|
|
714
1161
|
}
|
|
715
1162
|
|
|
716
1163
|
// src/stages/github-release.ts
|
|
717
|
-
import * as
|
|
718
|
-
|
|
1164
|
+
import * as fs7 from "fs";
|
|
1165
|
+
function resolveNotes(notesSetting, tag, changelogs, pipelineNotes) {
|
|
1166
|
+
if (notesSetting === "none") {
|
|
1167
|
+
return { useGithubNotes: false };
|
|
1168
|
+
}
|
|
1169
|
+
if (notesSetting === "github") {
|
|
1170
|
+
return { useGithubNotes: true };
|
|
1171
|
+
}
|
|
1172
|
+
if (notesSetting !== "auto") {
|
|
1173
|
+
const body = readFileIfExists(notesSetting);
|
|
1174
|
+
if (body) return { body, useGithubNotes: false };
|
|
1175
|
+
debug(`Notes file not found: ${notesSetting}, falling back to GitHub auto-notes`);
|
|
1176
|
+
return { useGithubNotes: true };
|
|
1177
|
+
}
|
|
1178
|
+
if (pipelineNotes) {
|
|
1179
|
+
const body = findNotesForTag(tag, pipelineNotes);
|
|
1180
|
+
if (body) return { body, useGithubNotes: false };
|
|
1181
|
+
}
|
|
1182
|
+
const packageBody = formatChangelogForTag(tag, changelogs);
|
|
1183
|
+
if (packageBody) {
|
|
1184
|
+
return { body: packageBody, useGithubNotes: false };
|
|
1185
|
+
}
|
|
1186
|
+
return { useGithubNotes: true };
|
|
1187
|
+
}
|
|
1188
|
+
function isVersionOnlyTag(tag) {
|
|
1189
|
+
return /^v?\d+\.\d+\.\d+/.test(tag);
|
|
1190
|
+
}
|
|
1191
|
+
function findNotesForTag(tag, notes) {
|
|
1192
|
+
for (const [packageName, body] of Object.entries(notes)) {
|
|
1193
|
+
if (tag.startsWith(`${packageName}@`) && body.trim()) {
|
|
1194
|
+
return body;
|
|
1195
|
+
}
|
|
1196
|
+
}
|
|
1197
|
+
const entries = Object.values(notes).filter((b) => b.trim());
|
|
1198
|
+
if (entries.length === 1 && isVersionOnlyTag(tag)) return entries[0];
|
|
1199
|
+
return void 0;
|
|
1200
|
+
}
|
|
1201
|
+
function readFileIfExists(filePath) {
|
|
1202
|
+
try {
|
|
1203
|
+
const content = fs7.readFileSync(filePath, "utf-8").trim();
|
|
1204
|
+
return content || void 0;
|
|
1205
|
+
} catch {
|
|
1206
|
+
return void 0;
|
|
1207
|
+
}
|
|
1208
|
+
}
|
|
1209
|
+
function formatChangelogForTag(tag, changelogs) {
|
|
1210
|
+
if (changelogs.length === 0) return void 0;
|
|
1211
|
+
const changelog = changelogs.find((c) => tag.startsWith(`${c.packageName}@`));
|
|
1212
|
+
const target = changelog ?? (changelogs.length === 1 && isVersionOnlyTag(tag) ? changelogs[0] : void 0);
|
|
1213
|
+
if (!target || target.entries.length === 0) return void 0;
|
|
1214
|
+
const lines = [];
|
|
1215
|
+
for (const entry of target.entries) {
|
|
1216
|
+
const scope = entry.scope ? `**${entry.scope}:** ` : "";
|
|
1217
|
+
lines.push(`- ${scope}${entry.description}`);
|
|
1218
|
+
}
|
|
1219
|
+
return lines.join("\n");
|
|
1220
|
+
}
|
|
719
1221
|
async function runGithubReleaseStage(ctx) {
|
|
720
1222
|
const { config, cliOptions, output } = ctx;
|
|
721
1223
|
const dryRun = cliOptions.dryRun;
|
|
722
1224
|
if (!config.githubRelease.enabled) {
|
|
723
|
-
|
|
1225
|
+
debug("GitHub releases disabled in config");
|
|
724
1226
|
return;
|
|
725
1227
|
}
|
|
726
1228
|
const tags = output.git.tags.length > 0 ? output.git.tags : ctx.input.tags;
|
|
727
1229
|
if (tags.length === 0) {
|
|
728
|
-
|
|
1230
|
+
info("No tags available for GitHub release");
|
|
729
1231
|
return;
|
|
730
1232
|
}
|
|
731
|
-
let notesBody;
|
|
732
|
-
if (config.githubRelease.notesFile) {
|
|
733
|
-
try {
|
|
734
|
-
notesBody = fs4.readFileSync(config.githubRelease.notesFile, "utf-8");
|
|
735
|
-
} catch {
|
|
736
|
-
debug3(`Could not read notes file: ${config.githubRelease.notesFile}`);
|
|
737
|
-
}
|
|
738
|
-
}
|
|
739
1233
|
const firstTag = tags[0];
|
|
740
1234
|
if (!firstTag) return;
|
|
741
1235
|
const tagsToRelease = config.githubRelease.perPackage ? tags : [firstTag];
|
|
@@ -758,9 +1252,15 @@ async function runGithubReleaseStage(ctx) {
|
|
|
758
1252
|
if (isPreRel) {
|
|
759
1253
|
ghArgs.push("--prerelease");
|
|
760
1254
|
}
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
1255
|
+
const { body, useGithubNotes } = resolveNotes(
|
|
1256
|
+
config.githubRelease.releaseNotes,
|
|
1257
|
+
tag,
|
|
1258
|
+
ctx.input.changelogs,
|
|
1259
|
+
ctx.releaseNotes
|
|
1260
|
+
);
|
|
1261
|
+
if (body) {
|
|
1262
|
+
ghArgs.push("--notes", body);
|
|
1263
|
+
} else if (useGithubNotes) {
|
|
764
1264
|
ghArgs.push("--generate-notes");
|
|
765
1265
|
}
|
|
766
1266
|
try {
|
|
@@ -773,35 +1273,33 @@ async function runGithubReleaseStage(ctx) {
|
|
|
773
1273
|
result.url = execResult.stdout.trim();
|
|
774
1274
|
}
|
|
775
1275
|
if (!dryRun) {
|
|
776
|
-
|
|
1276
|
+
success(`Created GitHub release for ${tag}`);
|
|
777
1277
|
}
|
|
778
1278
|
} catch (error) {
|
|
779
1279
|
result.reason = error instanceof Error ? error.message : String(error);
|
|
780
|
-
|
|
1280
|
+
warn(`Failed to create GitHub release for ${tag}: ${result.reason}`);
|
|
781
1281
|
}
|
|
782
1282
|
ctx.output.githubReleases.push(result);
|
|
783
1283
|
}
|
|
784
1284
|
}
|
|
785
1285
|
|
|
786
1286
|
// src/stages/npm-publish.ts
|
|
787
|
-
import * as
|
|
788
|
-
import * as
|
|
789
|
-
import { debug as debug5, info as info5, success as success5, warn as warn3 } from "@releasekit/core";
|
|
1287
|
+
import * as fs9 from "fs";
|
|
1288
|
+
import * as path8 from "path";
|
|
790
1289
|
|
|
791
1290
|
// src/utils/npm-env.ts
|
|
792
|
-
import * as
|
|
793
|
-
import * as
|
|
794
|
-
import * as
|
|
795
|
-
import { debug as debug4 } from "@releasekit/core";
|
|
1291
|
+
import * as fs8 from "fs";
|
|
1292
|
+
import * as os2 from "os";
|
|
1293
|
+
import * as path7 from "path";
|
|
796
1294
|
function writeTempNpmrc(contents) {
|
|
797
|
-
const dir =
|
|
798
|
-
const npmrcPath =
|
|
799
|
-
|
|
1295
|
+
const dir = fs8.mkdtempSync(path7.join(os2.tmpdir(), "releasekit-npmrc-"));
|
|
1296
|
+
const npmrcPath = path7.join(dir, ".npmrc");
|
|
1297
|
+
fs8.writeFileSync(npmrcPath, contents, "utf-8");
|
|
800
1298
|
return {
|
|
801
1299
|
npmrcPath,
|
|
802
1300
|
cleanup: () => {
|
|
803
1301
|
try {
|
|
804
|
-
|
|
1302
|
+
fs8.rmSync(dir, { recursive: true, force: true });
|
|
805
1303
|
} catch {
|
|
806
1304
|
}
|
|
807
1305
|
}
|
|
@@ -829,7 +1327,7 @@ function createNpmSubprocessIsolation(options) {
|
|
|
829
1327
|
}
|
|
830
1328
|
lines.push("");
|
|
831
1329
|
const { npmrcPath, cleanup } = writeTempNpmrc(lines.join("\n"));
|
|
832
|
-
|
|
1330
|
+
debug(`Using isolated npm userconfig: ${npmrcPath}`);
|
|
833
1331
|
const isOidc = authMethod === "oidc";
|
|
834
1332
|
return {
|
|
835
1333
|
env: {
|
|
@@ -859,7 +1357,7 @@ async function runNpmPublishStage(ctx) {
|
|
|
859
1357
|
const { input, config, cliOptions, cwd } = ctx;
|
|
860
1358
|
const dryRun = cliOptions.dryRun;
|
|
861
1359
|
if (!config.npm.enabled) {
|
|
862
|
-
|
|
1360
|
+
info("NPM publishing disabled in config");
|
|
863
1361
|
return;
|
|
864
1362
|
}
|
|
865
1363
|
const authMethod = config.npm.auth === "auto" ? detectNpmAuth() : config.npm.auth;
|
|
@@ -880,16 +1378,16 @@ async function runNpmPublishStage(ctx) {
|
|
|
880
1378
|
success: false,
|
|
881
1379
|
skipped: false
|
|
882
1380
|
};
|
|
883
|
-
const pkgJsonPath =
|
|
1381
|
+
const pkgJsonPath = path8.resolve(cwd, update.filePath);
|
|
884
1382
|
try {
|
|
885
|
-
const pkgContent =
|
|
1383
|
+
const pkgContent = fs9.readFileSync(pkgJsonPath, "utf-8");
|
|
886
1384
|
const pkgJson = JSON.parse(pkgContent);
|
|
887
1385
|
if (pkgJson.private) {
|
|
888
1386
|
result.skipped = true;
|
|
889
1387
|
result.success = true;
|
|
890
1388
|
result.reason = "Package is private";
|
|
891
1389
|
ctx.output.npm.push(result);
|
|
892
|
-
|
|
1390
|
+
debug(`Skipping private package: ${update.packageName}`);
|
|
893
1391
|
continue;
|
|
894
1392
|
}
|
|
895
1393
|
} catch {
|
|
@@ -918,11 +1416,11 @@ async function runNpmPublishStage(ctx) {
|
|
|
918
1416
|
result.success = true;
|
|
919
1417
|
result.reason = "Already published";
|
|
920
1418
|
ctx.output.npm.push(result);
|
|
921
|
-
|
|
1419
|
+
warn(`${update.packageName}@${update.newVersion} is already published, skipping`);
|
|
922
1420
|
continue;
|
|
923
1421
|
}
|
|
924
1422
|
const distTag = getDistTag(update.newVersion, config.npm.tag);
|
|
925
|
-
const pkgDir =
|
|
1423
|
+
const pkgDir = path8.dirname(path8.resolve(cwd, update.filePath));
|
|
926
1424
|
const { file: pubFile, args: pubArgs } = buildPublishCommand(ctx.packageManager, update.packageName, pkgDir, {
|
|
927
1425
|
access: config.npm.access,
|
|
928
1426
|
tag: distTag,
|
|
@@ -938,11 +1436,11 @@ async function runNpmPublishStage(ctx) {
|
|
|
938
1436
|
});
|
|
939
1437
|
result.success = true;
|
|
940
1438
|
if (!dryRun) {
|
|
941
|
-
|
|
1439
|
+
success(`Published ${update.packageName}@${update.newVersion} to npm`);
|
|
942
1440
|
}
|
|
943
1441
|
} catch (error) {
|
|
944
1442
|
result.reason = error instanceof Error ? error.message : String(error);
|
|
945
|
-
|
|
1443
|
+
warn(`Failed to publish ${update.packageName}: ${result.reason}`);
|
|
946
1444
|
}
|
|
947
1445
|
ctx.output.npm.push(result);
|
|
948
1446
|
}
|
|
@@ -952,32 +1450,31 @@ async function runNpmPublishStage(ctx) {
|
|
|
952
1450
|
}
|
|
953
1451
|
|
|
954
1452
|
// src/stages/prepare.ts
|
|
955
|
-
import * as
|
|
956
|
-
import * as
|
|
957
|
-
import { debug as debug6, info as info6 } from "@releasekit/core";
|
|
1453
|
+
import * as fs10 from "fs";
|
|
1454
|
+
import * as path9 from "path";
|
|
958
1455
|
async function runPrepareStage(ctx) {
|
|
959
1456
|
const { input, config, cliOptions, cwd } = ctx;
|
|
960
1457
|
if (config.npm.enabled && config.npm.copyFiles.length > 0) {
|
|
961
1458
|
for (const update of input.updates) {
|
|
962
|
-
const pkgDir =
|
|
1459
|
+
const pkgDir = path9.dirname(path9.resolve(cwd, update.filePath));
|
|
963
1460
|
for (const file of config.npm.copyFiles) {
|
|
964
|
-
const src =
|
|
965
|
-
const dest =
|
|
966
|
-
if (!
|
|
967
|
-
|
|
1461
|
+
const src = path9.resolve(cwd, file);
|
|
1462
|
+
const dest = path9.join(pkgDir, file);
|
|
1463
|
+
if (!fs10.existsSync(src)) {
|
|
1464
|
+
debug(`Source file not found, skipping copy: ${src}`);
|
|
968
1465
|
continue;
|
|
969
1466
|
}
|
|
970
|
-
if (
|
|
971
|
-
|
|
1467
|
+
if (path9.resolve(path9.dirname(src)) === path9.resolve(pkgDir)) {
|
|
1468
|
+
debug(`Skipping copy of ${file} - same directory as source`);
|
|
972
1469
|
continue;
|
|
973
1470
|
}
|
|
974
1471
|
if (cliOptions.dryRun) {
|
|
975
|
-
|
|
1472
|
+
info(`[DRY RUN] Would copy ${src} \u2192 ${dest}`);
|
|
976
1473
|
continue;
|
|
977
1474
|
}
|
|
978
1475
|
try {
|
|
979
|
-
|
|
980
|
-
|
|
1476
|
+
fs10.copyFileSync(src, dest);
|
|
1477
|
+
debug(`Copied ${file} \u2192 ${pkgDir}`);
|
|
981
1478
|
} catch (error) {
|
|
982
1479
|
throw createPublishError(
|
|
983
1480
|
"FILE_COPY_ERROR" /* FILE_COPY_ERROR */,
|
|
@@ -989,26 +1486,22 @@ async function runPrepareStage(ctx) {
|
|
|
989
1486
|
}
|
|
990
1487
|
if (config.cargo.enabled) {
|
|
991
1488
|
for (const update of input.updates) {
|
|
992
|
-
const pkgDir =
|
|
993
|
-
const cargoPath =
|
|
994
|
-
if (!
|
|
1489
|
+
const pkgDir = path9.dirname(path9.resolve(cwd, update.filePath));
|
|
1490
|
+
const cargoPath = path9.join(pkgDir, "Cargo.toml");
|
|
1491
|
+
if (!fs10.existsSync(cargoPath)) {
|
|
995
1492
|
continue;
|
|
996
1493
|
}
|
|
997
1494
|
if (cliOptions.dryRun) {
|
|
998
|
-
|
|
1495
|
+
info(`[DRY RUN] Would update ${cargoPath} to version ${update.newVersion}`);
|
|
999
1496
|
continue;
|
|
1000
1497
|
}
|
|
1001
1498
|
updateCargoVersion(cargoPath, update.newVersion);
|
|
1002
|
-
|
|
1499
|
+
debug(`Updated ${cargoPath} to version ${update.newVersion}`);
|
|
1003
1500
|
}
|
|
1004
1501
|
}
|
|
1005
1502
|
}
|
|
1006
1503
|
|
|
1007
|
-
// src/stages/verify.ts
|
|
1008
|
-
import { debug as debug8, info as info7, success as success6, warn as warn4 } from "@releasekit/core";
|
|
1009
|
-
|
|
1010
1504
|
// src/utils/retry.ts
|
|
1011
|
-
import { debug as debug7 } from "@releasekit/core";
|
|
1012
1505
|
async function withRetry(fn, options, shouldRetry) {
|
|
1013
1506
|
let lastError;
|
|
1014
1507
|
let delay = options.initialDelay;
|
|
@@ -1021,7 +1514,7 @@ async function withRetry(fn, options, shouldRetry) {
|
|
|
1021
1514
|
throw error;
|
|
1022
1515
|
}
|
|
1023
1516
|
if (attempt < options.maxAttempts) {
|
|
1024
|
-
|
|
1517
|
+
debug(`Attempt ${attempt}/${options.maxAttempts} failed, retrying in ${delay}ms...`);
|
|
1025
1518
|
await sleep(delay);
|
|
1026
1519
|
delay = Math.floor(delay * options.backoffMultiplier);
|
|
1027
1520
|
}
|
|
@@ -1047,7 +1540,7 @@ async function runVerifyStage(ctx) {
|
|
|
1047
1540
|
attempts: 0
|
|
1048
1541
|
};
|
|
1049
1542
|
if (cliOptions.dryRun) {
|
|
1050
|
-
|
|
1543
|
+
info(`[DRY RUN] Would verify ${pkg.packageName}@${pkg.version} on npm`);
|
|
1051
1544
|
result.verified = true;
|
|
1052
1545
|
ctx.output.verification.push(result);
|
|
1053
1546
|
continue;
|
|
@@ -1063,12 +1556,12 @@ async function runVerifyStage(ctx) {
|
|
|
1063
1556
|
if (viewResult.exitCode !== 0 || !viewResult.stdout.trim()) {
|
|
1064
1557
|
throw new Error(`${pkg.packageName}@${pkg.version} not yet available on npm`);
|
|
1065
1558
|
}
|
|
1066
|
-
|
|
1559
|
+
debug(`Verified ${pkg.packageName}@${pkg.version} on npm`);
|
|
1067
1560
|
}, config.verify.npm);
|
|
1068
1561
|
result.verified = true;
|
|
1069
|
-
|
|
1562
|
+
success(`Verified ${pkg.packageName}@${pkg.version} on npm`);
|
|
1070
1563
|
} catch {
|
|
1071
|
-
|
|
1564
|
+
warn(`Failed to verify ${pkg.packageName}@${pkg.version} on npm after ${result.attempts} attempts`);
|
|
1072
1565
|
}
|
|
1073
1566
|
ctx.output.verification.push(result);
|
|
1074
1567
|
}
|
|
@@ -1084,7 +1577,7 @@ async function runVerifyStage(ctx) {
|
|
|
1084
1577
|
attempts: 0
|
|
1085
1578
|
};
|
|
1086
1579
|
if (cliOptions.dryRun) {
|
|
1087
|
-
|
|
1580
|
+
info(`[DRY RUN] Would verify ${crate.packageName}@${crate.version} on crates.io`);
|
|
1088
1581
|
result.verified = true;
|
|
1089
1582
|
ctx.output.verification.push(result);
|
|
1090
1583
|
continue;
|
|
@@ -1096,12 +1589,12 @@ async function runVerifyStage(ctx) {
|
|
|
1096
1589
|
if (!response.ok) {
|
|
1097
1590
|
throw new Error(`${crate.packageName}@${crate.version} not yet available on crates.io`);
|
|
1098
1591
|
}
|
|
1099
|
-
|
|
1592
|
+
debug(`Verified ${crate.packageName}@${crate.version} on crates.io`);
|
|
1100
1593
|
}, config.verify.cargo);
|
|
1101
1594
|
result.verified = true;
|
|
1102
|
-
|
|
1595
|
+
success(`Verified ${crate.packageName}@${crate.version} on crates.io`);
|
|
1103
1596
|
} catch {
|
|
1104
|
-
|
|
1597
|
+
warn(`Failed to verify ${crate.packageName}@${crate.version} on crates.io after ${result.attempts} attempts`);
|
|
1105
1598
|
}
|
|
1106
1599
|
ctx.output.verification.push(result);
|
|
1107
1600
|
}
|
|
@@ -1136,6 +1629,8 @@ async function runPipeline(input, config, options) {
|
|
|
1136
1629
|
cliOptions: options,
|
|
1137
1630
|
packageManager: detectPackageManager(cwd),
|
|
1138
1631
|
cwd,
|
|
1632
|
+
releaseNotes: options.releaseNotes,
|
|
1633
|
+
additionalFiles: options.additionalFiles,
|
|
1139
1634
|
output: {
|
|
1140
1635
|
dryRun: options.dryRun,
|
|
1141
1636
|
git: { committed: false, tags: [], pushed: false },
|
|
@@ -1179,41 +1674,40 @@ async function runPipeline(input, config, options) {
|
|
|
1179
1674
|
}
|
|
1180
1675
|
|
|
1181
1676
|
// src/stages/input.ts
|
|
1182
|
-
import * as
|
|
1183
|
-
import {
|
|
1184
|
-
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
originalType: z.string().optional()
|
|
1677
|
+
import * as fs11 from "fs";
|
|
1678
|
+
import { z as z3 } from "zod";
|
|
1679
|
+
var VersionChangelogEntrySchema = z3.object({
|
|
1680
|
+
type: z3.string(),
|
|
1681
|
+
description: z3.string(),
|
|
1682
|
+
issueIds: z3.array(z3.string()).optional(),
|
|
1683
|
+
scope: z3.string().optional(),
|
|
1684
|
+
originalType: z3.string().optional()
|
|
1191
1685
|
});
|
|
1192
|
-
var VersionPackageChangelogSchema =
|
|
1193
|
-
packageName:
|
|
1194
|
-
version:
|
|
1195
|
-
previousVersion:
|
|
1196
|
-
revisionRange:
|
|
1197
|
-
repoUrl:
|
|
1198
|
-
entries:
|
|
1686
|
+
var VersionPackageChangelogSchema = z3.object({
|
|
1687
|
+
packageName: z3.string(),
|
|
1688
|
+
version: z3.string(),
|
|
1689
|
+
previousVersion: z3.string().nullable(),
|
|
1690
|
+
revisionRange: z3.string(),
|
|
1691
|
+
repoUrl: z3.string().nullable(),
|
|
1692
|
+
entries: z3.array(VersionChangelogEntrySchema)
|
|
1199
1693
|
});
|
|
1200
|
-
var VersionPackageUpdateSchema =
|
|
1201
|
-
packageName:
|
|
1202
|
-
newVersion:
|
|
1203
|
-
filePath:
|
|
1694
|
+
var VersionPackageUpdateSchema = z3.object({
|
|
1695
|
+
packageName: z3.string(),
|
|
1696
|
+
newVersion: z3.string(),
|
|
1697
|
+
filePath: z3.string()
|
|
1204
1698
|
});
|
|
1205
|
-
var VersionOutputSchema =
|
|
1206
|
-
dryRun:
|
|
1207
|
-
updates:
|
|
1208
|
-
changelogs:
|
|
1209
|
-
commitMessage:
|
|
1210
|
-
tags:
|
|
1699
|
+
var VersionOutputSchema = z3.object({
|
|
1700
|
+
dryRun: z3.boolean(),
|
|
1701
|
+
updates: z3.array(VersionPackageUpdateSchema),
|
|
1702
|
+
changelogs: z3.array(VersionPackageChangelogSchema),
|
|
1703
|
+
commitMessage: z3.string().optional(),
|
|
1704
|
+
tags: z3.array(z3.string())
|
|
1211
1705
|
});
|
|
1212
1706
|
async function parseInput(inputPath) {
|
|
1213
1707
|
let raw;
|
|
1214
1708
|
if (inputPath) {
|
|
1215
1709
|
try {
|
|
1216
|
-
raw =
|
|
1710
|
+
raw = fs11.readFileSync(inputPath, "utf-8");
|
|
1217
1711
|
} catch {
|
|
1218
1712
|
throw createPublishError("INPUT_PARSE_ERROR" /* INPUT_PARSE_ERROR */, `Could not read file: ${inputPath}`);
|
|
1219
1713
|
}
|
|
@@ -1233,7 +1727,7 @@ async function parseInput(inputPath) {
|
|
|
1233
1727
|
${issues}`);
|
|
1234
1728
|
}
|
|
1235
1729
|
if (result.data.updates.length === 0) {
|
|
1236
|
-
|
|
1730
|
+
info("No package updates in version output \u2014 pipeline will be a no-op");
|
|
1237
1731
|
}
|
|
1238
1732
|
return result.data;
|
|
1239
1733
|
}
|
|
@@ -1246,7 +1740,11 @@ async function readStdin() {
|
|
|
1246
1740
|
}
|
|
1247
1741
|
|
|
1248
1742
|
export {
|
|
1249
|
-
|
|
1743
|
+
setLogLevel,
|
|
1744
|
+
setJsonMode,
|
|
1745
|
+
EXIT_CODES,
|
|
1746
|
+
parseCargoToml,
|
|
1747
|
+
loadConfig2 as loadConfig,
|
|
1250
1748
|
getDefaultConfig2 as getDefaultConfig,
|
|
1251
1749
|
BasePublishError,
|
|
1252
1750
|
PublishError,
|
|
@@ -1255,7 +1753,6 @@ export {
|
|
|
1255
1753
|
createPublishError,
|
|
1256
1754
|
detectNpmAuth,
|
|
1257
1755
|
hasCargoAuth,
|
|
1258
|
-
parseCargoToml,
|
|
1259
1756
|
updateCargoVersion,
|
|
1260
1757
|
extractPathDeps,
|
|
1261
1758
|
isPrerelease,
|