@releasekit/publish 0.3.0-next.4 → 0.3.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-GOBII36Q.js → chunk-GIMIZS5B.js} +645 -129
- package/dist/cli.d.ts +5 -0
- package/dist/cli.js +70 -52
- package/dist/index.d.ts +9 -173
- package/dist/index.js +1 -1
- package/package.json +14 -13
- package/dist/cli.cjs +0 -1369
- package/dist/cli.d.cts +0 -1
- package/dist/index.cjs +0 -1380
- package/dist/index.d.cts +0 -173
|
@@ -1,5 +1,517 @@
|
|
|
1
|
-
//
|
|
2
|
-
import
|
|
1
|
+
// ../core/dist/index.js
|
|
2
|
+
import * as fs from "fs";
|
|
3
|
+
import * as path from "path";
|
|
4
|
+
import { fileURLToPath } from "url";
|
|
5
|
+
import chalk from "chalk";
|
|
6
|
+
function readPackageVersion(importMetaUrl) {
|
|
7
|
+
try {
|
|
8
|
+
const dir = path.dirname(fileURLToPath(importMetaUrl));
|
|
9
|
+
const packageJsonPath = path.resolve(dir, "../package.json");
|
|
10
|
+
const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, "utf-8"));
|
|
11
|
+
return packageJson.version ?? "0.0.0";
|
|
12
|
+
} catch {
|
|
13
|
+
return "0.0.0";
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
var LOG_LEVELS = {
|
|
17
|
+
error: 0,
|
|
18
|
+
warn: 1,
|
|
19
|
+
info: 2,
|
|
20
|
+
debug: 3,
|
|
21
|
+
trace: 4
|
|
22
|
+
};
|
|
23
|
+
var PREFIXES = {
|
|
24
|
+
error: "[ERROR]",
|
|
25
|
+
warn: "[WARN]",
|
|
26
|
+
info: "[INFO]",
|
|
27
|
+
debug: "[DEBUG]",
|
|
28
|
+
trace: "[TRACE]"
|
|
29
|
+
};
|
|
30
|
+
var COLORS = {
|
|
31
|
+
error: chalk.red,
|
|
32
|
+
warn: chalk.yellow,
|
|
33
|
+
info: chalk.blue,
|
|
34
|
+
debug: chalk.gray,
|
|
35
|
+
trace: chalk.dim
|
|
36
|
+
};
|
|
37
|
+
var currentLevel = "info";
|
|
38
|
+
var quietMode = false;
|
|
39
|
+
function setLogLevel(level) {
|
|
40
|
+
currentLevel = level;
|
|
41
|
+
}
|
|
42
|
+
function setJsonMode(_json) {
|
|
43
|
+
}
|
|
44
|
+
function shouldLog(level) {
|
|
45
|
+
if (quietMode && level !== "error") return false;
|
|
46
|
+
return LOG_LEVELS[level] <= LOG_LEVELS[currentLevel];
|
|
47
|
+
}
|
|
48
|
+
function log(message, level = "info") {
|
|
49
|
+
if (!shouldLog(level)) return;
|
|
50
|
+
const formatted = COLORS[level](`${PREFIXES[level]} ${message}`);
|
|
51
|
+
console.error(formatted);
|
|
52
|
+
}
|
|
53
|
+
function warn(message) {
|
|
54
|
+
log(message, "warn");
|
|
55
|
+
}
|
|
56
|
+
function info(message) {
|
|
57
|
+
log(message, "info");
|
|
58
|
+
}
|
|
59
|
+
function success(message) {
|
|
60
|
+
if (!shouldLog("info")) return;
|
|
61
|
+
console.error(chalk.green(`[SUCCESS] ${message}`));
|
|
62
|
+
}
|
|
63
|
+
function debug(message) {
|
|
64
|
+
log(message, "debug");
|
|
65
|
+
}
|
|
66
|
+
var ReleaseKitError = class _ReleaseKitError extends Error {
|
|
67
|
+
constructor(message) {
|
|
68
|
+
super(message);
|
|
69
|
+
this.name = this.constructor.name;
|
|
70
|
+
}
|
|
71
|
+
logError() {
|
|
72
|
+
log(this.message, "error");
|
|
73
|
+
if (this.suggestions.length > 0) {
|
|
74
|
+
log("\nSuggested solutions:", "info");
|
|
75
|
+
for (const [i, suggestion] of this.suggestions.entries()) {
|
|
76
|
+
log(`${i + 1}. ${suggestion}`, "info");
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
static isReleaseKitError(error2) {
|
|
81
|
+
return error2 instanceof _ReleaseKitError;
|
|
82
|
+
}
|
|
83
|
+
};
|
|
84
|
+
var EXIT_CODES = {
|
|
85
|
+
SUCCESS: 0,
|
|
86
|
+
GENERAL_ERROR: 1,
|
|
87
|
+
CONFIG_ERROR: 2,
|
|
88
|
+
INPUT_ERROR: 3,
|
|
89
|
+
TEMPLATE_ERROR: 4,
|
|
90
|
+
LLM_ERROR: 5,
|
|
91
|
+
GITHUB_ERROR: 6,
|
|
92
|
+
GIT_ERROR: 7,
|
|
93
|
+
VERSION_ERROR: 8,
|
|
94
|
+
PUBLISH_ERROR: 9
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
// ../config/dist/index.js
|
|
98
|
+
import * as fs2 from "fs";
|
|
99
|
+
import * as path2 from "path";
|
|
100
|
+
import * as TOML from "smol-toml";
|
|
101
|
+
import * as fs3 from "fs";
|
|
102
|
+
import * as path3 from "path";
|
|
103
|
+
import { z as z2 } from "zod";
|
|
104
|
+
import { z } from "zod";
|
|
105
|
+
import * as fs22 from "fs";
|
|
106
|
+
import * as os from "os";
|
|
107
|
+
import * as path22 from "path";
|
|
108
|
+
function parseCargoToml(cargoPath) {
|
|
109
|
+
const content = fs2.readFileSync(cargoPath, "utf-8");
|
|
110
|
+
return TOML.parse(content);
|
|
111
|
+
}
|
|
112
|
+
var ConfigError = class extends ReleaseKitError {
|
|
113
|
+
code = "CONFIG_ERROR";
|
|
114
|
+
suggestions;
|
|
115
|
+
constructor(message, suggestions) {
|
|
116
|
+
super(message);
|
|
117
|
+
this.suggestions = suggestions ?? [
|
|
118
|
+
"Check that releasekit.config.json exists and is valid JSON",
|
|
119
|
+
"Run with --verbose for more details"
|
|
120
|
+
];
|
|
121
|
+
}
|
|
122
|
+
};
|
|
123
|
+
function mergeGitConfig(topLevel, packageLevel) {
|
|
124
|
+
if (!topLevel && !packageLevel) return void 0;
|
|
125
|
+
const base = topLevel ?? {
|
|
126
|
+
remote: "origin",
|
|
127
|
+
branch: "main",
|
|
128
|
+
pushMethod: "auto"
|
|
129
|
+
};
|
|
130
|
+
if (!packageLevel) return base;
|
|
131
|
+
return {
|
|
132
|
+
remote: packageLevel.remote ?? base.remote,
|
|
133
|
+
branch: packageLevel.branch ?? base.branch,
|
|
134
|
+
pushMethod: packageLevel.pushMethod ?? base.pushMethod,
|
|
135
|
+
httpsTokenEnv: packageLevel.httpsTokenEnv ?? base.httpsTokenEnv,
|
|
136
|
+
push: packageLevel.push,
|
|
137
|
+
skipHooks: packageLevel.skipHooks ?? base.skipHooks
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
var MAX_JSONC_LENGTH = 1e5;
|
|
141
|
+
function parseJsonc(content) {
|
|
142
|
+
if (content.length > MAX_JSONC_LENGTH) {
|
|
143
|
+
throw new Error(`JSONC content too long: ${content.length} characters (max ${MAX_JSONC_LENGTH})`);
|
|
144
|
+
}
|
|
145
|
+
try {
|
|
146
|
+
return JSON.parse(content);
|
|
147
|
+
} catch {
|
|
148
|
+
const cleaned = content.replace(/\/\/[^\r\n]{0,10000}$/gm, "").replace(/\/\*[\s\S]{0,50000}?\*\//g, "").trim();
|
|
149
|
+
return JSON.parse(cleaned);
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
var GitConfigSchema = z.object({
|
|
153
|
+
remote: z.string().default("origin"),
|
|
154
|
+
branch: z.string().default("main"),
|
|
155
|
+
pushMethod: z.enum(["auto", "ssh", "https"]).default("auto"),
|
|
156
|
+
/**
|
|
157
|
+
* Optional env var name containing a GitHub token for HTTPS pushes.
|
|
158
|
+
* When set, publish steps can use this token without mutating git remotes.
|
|
159
|
+
*/
|
|
160
|
+
httpsTokenEnv: z.string().optional(),
|
|
161
|
+
push: z.boolean().optional(),
|
|
162
|
+
skipHooks: z.boolean().optional()
|
|
163
|
+
});
|
|
164
|
+
var MonorepoConfigSchema = z.object({
|
|
165
|
+
mode: z.enum(["root", "packages", "both"]).optional(),
|
|
166
|
+
rootPath: z.string().optional(),
|
|
167
|
+
packagesPath: z.string().optional(),
|
|
168
|
+
mainPackage: z.string().optional()
|
|
169
|
+
});
|
|
170
|
+
var BranchPatternSchema = z.object({
|
|
171
|
+
pattern: z.string(),
|
|
172
|
+
releaseType: z.enum(["major", "minor", "patch", "prerelease"])
|
|
173
|
+
});
|
|
174
|
+
var VersionCargoConfigSchema = z.object({
|
|
175
|
+
enabled: z.boolean().default(true),
|
|
176
|
+
paths: z.array(z.string()).optional()
|
|
177
|
+
});
|
|
178
|
+
var VersionConfigSchema = z.object({
|
|
179
|
+
tagTemplate: z.string().default("v{version}"),
|
|
180
|
+
packageSpecificTags: z.boolean().default(false),
|
|
181
|
+
preset: z.string().default("conventional"),
|
|
182
|
+
sync: z.boolean().default(true),
|
|
183
|
+
packages: z.array(z.string()).default([]),
|
|
184
|
+
mainPackage: z.string().optional(),
|
|
185
|
+
updateInternalDependencies: z.enum(["major", "minor", "patch", "no-internal-update"]).default("minor"),
|
|
186
|
+
skip: z.array(z.string()).optional(),
|
|
187
|
+
commitMessage: z.string().optional(),
|
|
188
|
+
versionStrategy: z.enum(["branchPattern", "commitMessage"]).default("commitMessage"),
|
|
189
|
+
branchPatterns: z.array(BranchPatternSchema).optional(),
|
|
190
|
+
defaultReleaseType: z.enum(["major", "minor", "patch", "prerelease"]).optional(),
|
|
191
|
+
mismatchStrategy: z.enum(["error", "warn", "ignore", "prefer-package", "prefer-git"]).default("warn"),
|
|
192
|
+
versionPrefix: z.string().default(""),
|
|
193
|
+
prereleaseIdentifier: z.string().optional(),
|
|
194
|
+
strictReachable: z.boolean().default(false),
|
|
195
|
+
cargo: VersionCargoConfigSchema.optional()
|
|
196
|
+
});
|
|
197
|
+
var NpmConfigSchema = z.object({
|
|
198
|
+
enabled: z.boolean().default(true),
|
|
199
|
+
auth: z.enum(["auto", "oidc", "token"]).default("auto"),
|
|
200
|
+
provenance: z.boolean().default(true),
|
|
201
|
+
access: z.enum(["public", "restricted"]).default("public"),
|
|
202
|
+
registry: z.string().default("https://registry.npmjs.org"),
|
|
203
|
+
copyFiles: z.array(z.string()).default(["LICENSE"]),
|
|
204
|
+
tag: z.string().default("latest")
|
|
205
|
+
});
|
|
206
|
+
var CargoPublishConfigSchema = z.object({
|
|
207
|
+
enabled: z.boolean().default(false),
|
|
208
|
+
noVerify: z.boolean().default(false),
|
|
209
|
+
publishOrder: z.array(z.string()).default([]),
|
|
210
|
+
clean: z.boolean().default(false)
|
|
211
|
+
});
|
|
212
|
+
var PublishGitConfigSchema = z.object({
|
|
213
|
+
push: z.boolean().default(true),
|
|
214
|
+
pushMethod: z.enum(["auto", "ssh", "https"]).optional(),
|
|
215
|
+
remote: z.string().optional(),
|
|
216
|
+
branch: z.string().optional(),
|
|
217
|
+
httpsTokenEnv: z.string().optional(),
|
|
218
|
+
skipHooks: z.boolean().optional()
|
|
219
|
+
});
|
|
220
|
+
var GitHubReleaseConfigSchema = z.object({
|
|
221
|
+
enabled: z.boolean().default(true),
|
|
222
|
+
draft: z.boolean().default(true),
|
|
223
|
+
perPackage: z.boolean().default(true),
|
|
224
|
+
prerelease: z.union([z.literal("auto"), z.boolean()]).default("auto"),
|
|
225
|
+
/**
|
|
226
|
+
* Controls how release notes are sourced for GitHub releases.
|
|
227
|
+
* - 'auto': Use RELEASE_NOTES.md if it exists, then per-package changelog
|
|
228
|
+
* data from the version output, then GitHub's auto-generated notes.
|
|
229
|
+
* - 'github': Always use GitHub's auto-generated notes.
|
|
230
|
+
* - 'none': No notes body.
|
|
231
|
+
* - Any other string: Treated as a file path to read notes from.
|
|
232
|
+
*/
|
|
233
|
+
releaseNotes: z.union([z.literal("auto"), z.literal("github"), z.literal("none"), z.string()]).default("auto")
|
|
234
|
+
});
|
|
235
|
+
var VerifyRegistryConfigSchema = z.object({
|
|
236
|
+
enabled: z.boolean().default(true),
|
|
237
|
+
maxAttempts: z.number().int().positive().default(5),
|
|
238
|
+
initialDelay: z.number().int().positive().default(15e3),
|
|
239
|
+
backoffMultiplier: z.number().positive().default(2)
|
|
240
|
+
});
|
|
241
|
+
var VerifyConfigSchema = z.object({
|
|
242
|
+
npm: VerifyRegistryConfigSchema.default({
|
|
243
|
+
enabled: true,
|
|
244
|
+
maxAttempts: 5,
|
|
245
|
+
initialDelay: 15e3,
|
|
246
|
+
backoffMultiplier: 2
|
|
247
|
+
}),
|
|
248
|
+
cargo: VerifyRegistryConfigSchema.default({
|
|
249
|
+
enabled: true,
|
|
250
|
+
maxAttempts: 10,
|
|
251
|
+
initialDelay: 3e4,
|
|
252
|
+
backoffMultiplier: 2
|
|
253
|
+
})
|
|
254
|
+
});
|
|
255
|
+
var PublishConfigSchema = z.object({
|
|
256
|
+
git: PublishGitConfigSchema.optional(),
|
|
257
|
+
npm: NpmConfigSchema.default({
|
|
258
|
+
enabled: true,
|
|
259
|
+
auth: "auto",
|
|
260
|
+
provenance: true,
|
|
261
|
+
access: "public",
|
|
262
|
+
registry: "https://registry.npmjs.org",
|
|
263
|
+
copyFiles: ["LICENSE"],
|
|
264
|
+
tag: "latest"
|
|
265
|
+
}),
|
|
266
|
+
cargo: CargoPublishConfigSchema.default({
|
|
267
|
+
enabled: false,
|
|
268
|
+
noVerify: false,
|
|
269
|
+
publishOrder: [],
|
|
270
|
+
clean: false
|
|
271
|
+
}),
|
|
272
|
+
githubRelease: GitHubReleaseConfigSchema.default({
|
|
273
|
+
enabled: true,
|
|
274
|
+
draft: true,
|
|
275
|
+
perPackage: true,
|
|
276
|
+
prerelease: "auto",
|
|
277
|
+
releaseNotes: "auto"
|
|
278
|
+
}),
|
|
279
|
+
verify: VerifyConfigSchema.default({
|
|
280
|
+
npm: {
|
|
281
|
+
enabled: true,
|
|
282
|
+
maxAttempts: 5,
|
|
283
|
+
initialDelay: 15e3,
|
|
284
|
+
backoffMultiplier: 2
|
|
285
|
+
},
|
|
286
|
+
cargo: {
|
|
287
|
+
enabled: true,
|
|
288
|
+
maxAttempts: 10,
|
|
289
|
+
initialDelay: 3e4,
|
|
290
|
+
backoffMultiplier: 2
|
|
291
|
+
}
|
|
292
|
+
})
|
|
293
|
+
});
|
|
294
|
+
var TemplateConfigSchema = z.object({
|
|
295
|
+
path: z.string().optional(),
|
|
296
|
+
engine: z.enum(["handlebars", "liquid", "ejs"]).optional()
|
|
297
|
+
});
|
|
298
|
+
var OutputConfigSchema = z.object({
|
|
299
|
+
format: z.enum(["markdown", "github-release", "json"]),
|
|
300
|
+
file: z.string().optional(),
|
|
301
|
+
options: z.record(z.string(), z.unknown()).optional(),
|
|
302
|
+
templates: TemplateConfigSchema.optional()
|
|
303
|
+
});
|
|
304
|
+
var LLMOptionsSchema = z.object({
|
|
305
|
+
timeout: z.number().optional(),
|
|
306
|
+
maxTokens: z.number().optional(),
|
|
307
|
+
temperature: z.number().optional()
|
|
308
|
+
});
|
|
309
|
+
var LLMRetryConfigSchema = z.object({
|
|
310
|
+
maxAttempts: z.number().int().positive().optional(),
|
|
311
|
+
initialDelay: z.number().nonnegative().optional(),
|
|
312
|
+
maxDelay: z.number().positive().optional(),
|
|
313
|
+
backoffFactor: z.number().positive().optional()
|
|
314
|
+
});
|
|
315
|
+
var LLMTasksConfigSchema = z.object({
|
|
316
|
+
summarize: z.boolean().optional(),
|
|
317
|
+
enhance: z.boolean().optional(),
|
|
318
|
+
categorize: z.boolean().optional(),
|
|
319
|
+
releaseNotes: z.boolean().optional()
|
|
320
|
+
});
|
|
321
|
+
var LLMCategorySchema = z.object({
|
|
322
|
+
name: z.string(),
|
|
323
|
+
description: z.string(),
|
|
324
|
+
scopes: z.array(z.string()).optional()
|
|
325
|
+
});
|
|
326
|
+
var ScopeRulesSchema = z.object({
|
|
327
|
+
allowed: z.array(z.string()).optional(),
|
|
328
|
+
caseSensitive: z.boolean().default(false),
|
|
329
|
+
invalidScopeAction: z.enum(["remove", "keep", "fallback"]).default("remove"),
|
|
330
|
+
fallbackScope: z.string().optional()
|
|
331
|
+
});
|
|
332
|
+
var ScopeConfigSchema = z.object({
|
|
333
|
+
mode: z.enum(["restricted", "packages", "none", "unrestricted"]).default("unrestricted"),
|
|
334
|
+
rules: ScopeRulesSchema.optional()
|
|
335
|
+
});
|
|
336
|
+
var LLMPromptOverridesSchema = z.object({
|
|
337
|
+
enhance: z.string().optional(),
|
|
338
|
+
categorize: z.string().optional(),
|
|
339
|
+
enhanceAndCategorize: z.string().optional(),
|
|
340
|
+
summarize: z.string().optional(),
|
|
341
|
+
releaseNotes: z.string().optional()
|
|
342
|
+
});
|
|
343
|
+
var LLMPromptsConfigSchema = z.object({
|
|
344
|
+
instructions: LLMPromptOverridesSchema.optional(),
|
|
345
|
+
templates: LLMPromptOverridesSchema.optional()
|
|
346
|
+
});
|
|
347
|
+
var LLMConfigSchema = z.object({
|
|
348
|
+
provider: z.string(),
|
|
349
|
+
model: z.string(),
|
|
350
|
+
baseURL: z.string().optional(),
|
|
351
|
+
apiKey: z.string().optional(),
|
|
352
|
+
options: LLMOptionsSchema.optional(),
|
|
353
|
+
concurrency: z.number().int().positive().optional(),
|
|
354
|
+
retry: LLMRetryConfigSchema.optional(),
|
|
355
|
+
tasks: LLMTasksConfigSchema.optional(),
|
|
356
|
+
categories: z.array(LLMCategorySchema).optional(),
|
|
357
|
+
style: z.string().optional(),
|
|
358
|
+
scopes: ScopeConfigSchema.optional(),
|
|
359
|
+
prompts: LLMPromptsConfigSchema.optional()
|
|
360
|
+
});
|
|
361
|
+
var NotesInputConfigSchema = z.object({
|
|
362
|
+
source: z.string().optional(),
|
|
363
|
+
file: z.string().optional()
|
|
364
|
+
});
|
|
365
|
+
var NotesConfigSchema = z.object({
|
|
366
|
+
input: NotesInputConfigSchema.optional(),
|
|
367
|
+
output: z.array(OutputConfigSchema).default([{ format: "markdown", file: "CHANGELOG.md" }]),
|
|
368
|
+
monorepo: MonorepoConfigSchema.optional(),
|
|
369
|
+
templates: TemplateConfigSchema.optional(),
|
|
370
|
+
llm: LLMConfigSchema.optional(),
|
|
371
|
+
updateStrategy: z.enum(["prepend", "regenerate"]).default("prepend")
|
|
372
|
+
});
|
|
373
|
+
var CILabelsConfigSchema = z.object({
|
|
374
|
+
stable: z.string().default("release:stable"),
|
|
375
|
+
prerelease: z.string().default("release:prerelease"),
|
|
376
|
+
skip: z.string().default("release:skip"),
|
|
377
|
+
major: z.string().default("release:major"),
|
|
378
|
+
minor: z.string().default("release:minor"),
|
|
379
|
+
patch: z.string().default("release:patch")
|
|
380
|
+
});
|
|
381
|
+
var CIConfigSchema = z.object({
|
|
382
|
+
releaseStrategy: z.enum(["manual", "direct", "standing-pr", "scheduled"]).default("direct"),
|
|
383
|
+
releaseTrigger: z.enum(["commit", "label"]).default("label"),
|
|
384
|
+
prPreview: z.boolean().default(true),
|
|
385
|
+
autoRelease: z.boolean().default(false),
|
|
386
|
+
/**
|
|
387
|
+
* Commit message prefixes that should not trigger a release.
|
|
388
|
+
* Defaults to `['chore: release ']` to match the release commit template
|
|
389
|
+
* (`chore: release ${packageName} v${version}`) and provide a
|
|
390
|
+
* secondary loop-prevention guard alongside `[skip ci]`.
|
|
391
|
+
*/
|
|
392
|
+
skipPatterns: z.array(z.string()).default(["chore: release "]),
|
|
393
|
+
minChanges: z.number().int().positive().default(1),
|
|
394
|
+
labels: CILabelsConfigSchema.default({
|
|
395
|
+
stable: "release:stable",
|
|
396
|
+
prerelease: "release:prerelease",
|
|
397
|
+
skip: "release:skip",
|
|
398
|
+
major: "release:major",
|
|
399
|
+
minor: "release:minor",
|
|
400
|
+
patch: "release:patch"
|
|
401
|
+
})
|
|
402
|
+
});
|
|
403
|
+
var ReleaseCIConfigSchema = z.object({
|
|
404
|
+
skipPatterns: z.array(z.string().min(1)).optional(),
|
|
405
|
+
minChanges: z.number().int().positive().optional(),
|
|
406
|
+
/** Set to `false` to disable GitHub release creation in CI. */
|
|
407
|
+
githubRelease: z.literal(false).optional(),
|
|
408
|
+
/** Set to `false` to disable changelog generation in CI. */
|
|
409
|
+
notes: z.literal(false).optional()
|
|
410
|
+
});
|
|
411
|
+
var ReleaseConfigSchema = z.object({
|
|
412
|
+
/**
|
|
413
|
+
* Optional steps to enable. The version step always runs; only 'notes' and
|
|
414
|
+
* 'publish' can be opted out. Omitting a step is equivalent to --skip-<step>.
|
|
415
|
+
*/
|
|
416
|
+
steps: z.array(z.enum(["notes", "publish"])).min(1).optional(),
|
|
417
|
+
ci: ReleaseCIConfigSchema.optional()
|
|
418
|
+
});
|
|
419
|
+
var ReleaseKitConfigSchema = z.object({
|
|
420
|
+
git: GitConfigSchema.optional(),
|
|
421
|
+
monorepo: MonorepoConfigSchema.optional(),
|
|
422
|
+
version: VersionConfigSchema.optional(),
|
|
423
|
+
publish: PublishConfigSchema.optional(),
|
|
424
|
+
notes: NotesConfigSchema.optional(),
|
|
425
|
+
ci: CIConfigSchema.optional(),
|
|
426
|
+
release: ReleaseConfigSchema.optional()
|
|
427
|
+
});
|
|
428
|
+
var MAX_INPUT_LENGTH = 1e4;
|
|
429
|
+
function substituteVariables(value) {
|
|
430
|
+
if (value.length > MAX_INPUT_LENGTH) {
|
|
431
|
+
throw new Error(`Input too long: ${value.length} characters (max ${MAX_INPUT_LENGTH})`);
|
|
432
|
+
}
|
|
433
|
+
const envPattern = /\{env:([^}]{1,1000})\}/g;
|
|
434
|
+
const filePattern = /\{file:([^}]{1,1000})\}/g;
|
|
435
|
+
let result = value;
|
|
436
|
+
result = result.replace(envPattern, (_, varName) => {
|
|
437
|
+
return process.env[varName] ?? "";
|
|
438
|
+
});
|
|
439
|
+
result = result.replace(filePattern, (_, filePath) => {
|
|
440
|
+
const expandedPath = filePath.startsWith("~") ? path22.join(os.homedir(), filePath.slice(1)) : filePath;
|
|
441
|
+
try {
|
|
442
|
+
return fs22.readFileSync(expandedPath, "utf-8").trim();
|
|
443
|
+
} catch {
|
|
444
|
+
return "";
|
|
445
|
+
}
|
|
446
|
+
});
|
|
447
|
+
return result;
|
|
448
|
+
}
|
|
449
|
+
var SOLE_REFERENCE_PATTERN = /^\{(?:env|file):[^}]+\}$/;
|
|
450
|
+
function substituteInObject(obj) {
|
|
451
|
+
if (typeof obj === "string") {
|
|
452
|
+
const result = substituteVariables(obj);
|
|
453
|
+
if (result === "" && SOLE_REFERENCE_PATTERN.test(obj)) {
|
|
454
|
+
return void 0;
|
|
455
|
+
}
|
|
456
|
+
return result;
|
|
457
|
+
}
|
|
458
|
+
if (Array.isArray(obj)) {
|
|
459
|
+
return obj.map((item) => substituteInObject(item));
|
|
460
|
+
}
|
|
461
|
+
if (obj && typeof obj === "object") {
|
|
462
|
+
const result = {};
|
|
463
|
+
for (const [key, value] of Object.entries(obj)) {
|
|
464
|
+
result[key] = substituteInObject(value);
|
|
465
|
+
}
|
|
466
|
+
return result;
|
|
467
|
+
}
|
|
468
|
+
return obj;
|
|
469
|
+
}
|
|
470
|
+
var AUTH_DIR = path22.join(os.homedir(), ".config", "releasekit");
|
|
471
|
+
var AUTH_FILE = path22.join(AUTH_DIR, "auth.json");
|
|
472
|
+
var CONFIG_FILE = "releasekit.config.json";
|
|
473
|
+
function loadConfigFile(configPath) {
|
|
474
|
+
if (!fs3.existsSync(configPath)) {
|
|
475
|
+
return {};
|
|
476
|
+
}
|
|
477
|
+
try {
|
|
478
|
+
const content = fs3.readFileSync(configPath, "utf-8");
|
|
479
|
+
const parsed = parseJsonc(content);
|
|
480
|
+
const substituted = substituteInObject(parsed);
|
|
481
|
+
return ReleaseKitConfigSchema.parse(substituted);
|
|
482
|
+
} catch (error) {
|
|
483
|
+
if (error instanceof z2.ZodError) {
|
|
484
|
+
const issues = error.issues.map((i) => ` ${i.path.join(".")}: ${i.message}`).join("\n");
|
|
485
|
+
throw new ConfigError(`Config validation errors:
|
|
486
|
+
${issues}`);
|
|
487
|
+
}
|
|
488
|
+
if (error instanceof SyntaxError) {
|
|
489
|
+
throw new ConfigError(`Invalid JSON in config file: ${error.message}`);
|
|
490
|
+
}
|
|
491
|
+
throw error;
|
|
492
|
+
}
|
|
493
|
+
}
|
|
494
|
+
function loadConfig(options) {
|
|
495
|
+
const cwd = options?.cwd ?? process.cwd();
|
|
496
|
+
const configPath = options?.configPath ?? path3.join(cwd, CONFIG_FILE);
|
|
497
|
+
return loadConfigFile(configPath);
|
|
498
|
+
}
|
|
499
|
+
function loadPublishConfig(options) {
|
|
500
|
+
const config = loadConfig(options);
|
|
501
|
+
if (!config.publish) return void 0;
|
|
502
|
+
const mergedGit = mergeGitConfig(config.git, config.publish.git);
|
|
503
|
+
return {
|
|
504
|
+
...config.publish,
|
|
505
|
+
git: mergedGit ? {
|
|
506
|
+
push: mergedGit.push ?? true,
|
|
507
|
+
pushMethod: mergedGit.pushMethod,
|
|
508
|
+
remote: mergedGit.remote,
|
|
509
|
+
branch: mergedGit.branch,
|
|
510
|
+
httpsTokenEnv: mergedGit.httpsTokenEnv,
|
|
511
|
+
skipHooks: mergedGit.skipHooks
|
|
512
|
+
} : void 0
|
|
513
|
+
};
|
|
514
|
+
}
|
|
3
515
|
|
|
4
516
|
// src/types.ts
|
|
5
517
|
function getDefaultConfig() {
|
|
@@ -23,7 +535,7 @@ function getDefaultConfig() {
|
|
|
23
535
|
push: true,
|
|
24
536
|
pushMethod: "auto",
|
|
25
537
|
remote: "origin",
|
|
26
|
-
branch:
|
|
538
|
+
branch: void 0,
|
|
27
539
|
httpsTokenEnv: void 0,
|
|
28
540
|
skipHooks: false
|
|
29
541
|
},
|
|
@@ -102,7 +614,7 @@ function toPublishConfig(config) {
|
|
|
102
614
|
}
|
|
103
615
|
|
|
104
616
|
// src/config.ts
|
|
105
|
-
function
|
|
617
|
+
function loadConfig2(options) {
|
|
106
618
|
const baseConfig = loadPublishConfig(options);
|
|
107
619
|
return toPublishConfig(baseConfig);
|
|
108
620
|
}
|
|
@@ -111,7 +623,6 @@ function getDefaultConfig2() {
|
|
|
111
623
|
}
|
|
112
624
|
|
|
113
625
|
// src/errors/index.ts
|
|
114
|
-
import { ReleaseKitError } from "@releasekit/core";
|
|
115
626
|
var BasePublishError = class _BasePublishError extends ReleaseKitError {
|
|
116
627
|
code;
|
|
117
628
|
suggestions;
|
|
@@ -250,7 +761,6 @@ function createPublishError(code, details) {
|
|
|
250
761
|
|
|
251
762
|
// src/utils/exec.ts
|
|
252
763
|
import { execFile } from "child_process";
|
|
253
|
-
import { debug, info } from "@releasekit/core";
|
|
254
764
|
function redactArg(arg) {
|
|
255
765
|
try {
|
|
256
766
|
const url = new URL(arg);
|
|
@@ -270,7 +780,7 @@ async function execCommand(file, args, options = {}) {
|
|
|
270
780
|
return { stdout: "", stderr: "", exitCode: 0 };
|
|
271
781
|
}
|
|
272
782
|
debug(`Executing: ${displayCommand}`);
|
|
273
|
-
return new Promise((
|
|
783
|
+
return new Promise((resolve6, reject) => {
|
|
274
784
|
execFile(
|
|
275
785
|
file,
|
|
276
786
|
args,
|
|
@@ -289,7 +799,7 @@ async function execCommand(file, args, options = {}) {
|
|
|
289
799
|
})
|
|
290
800
|
);
|
|
291
801
|
} else {
|
|
292
|
-
|
|
802
|
+
resolve6({
|
|
293
803
|
stdout: stdout.toString(),
|
|
294
804
|
stderr: stderr.toString(),
|
|
295
805
|
exitCode: 0
|
|
@@ -338,15 +848,14 @@ async function detectGitPushMethod(remote, cwd) {
|
|
|
338
848
|
}
|
|
339
849
|
|
|
340
850
|
// src/utils/cargo.ts
|
|
341
|
-
import * as
|
|
342
|
-
import
|
|
343
|
-
import * as TOML from "smol-toml";
|
|
851
|
+
import * as fs4 from "fs";
|
|
852
|
+
import * as TOML2 from "smol-toml";
|
|
344
853
|
function updateCargoVersion(cargoPath, newVersion) {
|
|
345
854
|
try {
|
|
346
855
|
const cargo = parseCargoToml(cargoPath);
|
|
347
856
|
if (cargo.package) {
|
|
348
857
|
cargo.package.version = newVersion;
|
|
349
|
-
|
|
858
|
+
fs4.writeFileSync(cargoPath, TOML2.stringify(cargo));
|
|
350
859
|
}
|
|
351
860
|
} catch (error) {
|
|
352
861
|
throw createPublishError(
|
|
@@ -383,11 +892,11 @@ function getDistTag(version, defaultTag = "latest") {
|
|
|
383
892
|
}
|
|
384
893
|
|
|
385
894
|
// src/utils/package-manager.ts
|
|
386
|
-
import * as
|
|
387
|
-
import * as
|
|
895
|
+
import * as fs5 from "fs";
|
|
896
|
+
import * as path4 from "path";
|
|
388
897
|
function detectPackageManager(cwd) {
|
|
389
|
-
if (
|
|
390
|
-
if (
|
|
898
|
+
if (fs5.existsSync(path4.join(cwd, "pnpm-lock.yaml"))) return "pnpm";
|
|
899
|
+
if (fs5.existsSync(path4.join(cwd, "yarn.lock"))) return "yarn";
|
|
391
900
|
return "npm";
|
|
392
901
|
}
|
|
393
902
|
function buildPublishCommand(pm, packageName, _packageDir, options) {
|
|
@@ -412,25 +921,24 @@ function buildViewCommand(pm, packageName, version) {
|
|
|
412
921
|
}
|
|
413
922
|
|
|
414
923
|
// src/stages/cargo-publish.ts
|
|
415
|
-
import * as
|
|
416
|
-
import * as
|
|
417
|
-
import { debug as debug2, success, warn } from "@releasekit/core";
|
|
924
|
+
import * as fs6 from "fs";
|
|
925
|
+
import * as path5 from "path";
|
|
418
926
|
async function runCargoPublishStage(ctx) {
|
|
419
927
|
const { input, config, cliOptions, cwd } = ctx;
|
|
420
928
|
const dryRun = cliOptions.dryRun;
|
|
421
929
|
if (!config.cargo.enabled) {
|
|
422
|
-
|
|
930
|
+
debug("Cargo publishing disabled in config");
|
|
423
931
|
return;
|
|
424
932
|
}
|
|
425
933
|
if (!hasCargoAuth() && !dryRun) {
|
|
426
934
|
throw createPublishError("CARGO_AUTH_ERROR" /* CARGO_AUTH_ERROR */, "CARGO_REGISTRY_TOKEN not set");
|
|
427
935
|
}
|
|
428
936
|
const crates = findCrates(
|
|
429
|
-
input.updates.map((u) => ({ dir:
|
|
937
|
+
input.updates.map((u) => ({ dir: path5.dirname(path5.resolve(cwd, u.filePath)), ...u })),
|
|
430
938
|
cwd
|
|
431
939
|
);
|
|
432
940
|
if (crates.length === 0) {
|
|
433
|
-
|
|
941
|
+
debug("No Cargo crates found to publish");
|
|
434
942
|
return;
|
|
435
943
|
}
|
|
436
944
|
const ordered = orderCrates(crates, config.cargo.publishOrder);
|
|
@@ -479,8 +987,8 @@ async function runCargoPublishStage(ctx) {
|
|
|
479
987
|
function findCrates(updates, _cwd) {
|
|
480
988
|
const crates = [];
|
|
481
989
|
for (const update of updates) {
|
|
482
|
-
const cargoPath =
|
|
483
|
-
if (!
|
|
990
|
+
const cargoPath = path5.join(update.dir, "Cargo.toml");
|
|
991
|
+
if (!fs6.existsSync(cargoPath)) {
|
|
484
992
|
continue;
|
|
485
993
|
}
|
|
486
994
|
try {
|
|
@@ -528,9 +1036,9 @@ function topologicalSort(crates) {
|
|
|
528
1036
|
}
|
|
529
1037
|
for (const crate of crates) {
|
|
530
1038
|
for (const depPath of crate.pathDeps) {
|
|
531
|
-
const resolvedDir =
|
|
1039
|
+
const resolvedDir = path5.resolve(crate.dir, depPath);
|
|
532
1040
|
for (const other of crates) {
|
|
533
|
-
if (
|
|
1041
|
+
if (path5.resolve(other.dir) === resolvedDir && nameSet.has(other.name)) {
|
|
534
1042
|
graph.get(crate.name)?.push(other.name);
|
|
535
1043
|
}
|
|
536
1044
|
}
|
|
@@ -572,22 +1080,21 @@ function topologicalSort(crates) {
|
|
|
572
1080
|
}
|
|
573
1081
|
|
|
574
1082
|
// src/stages/git-commit.ts
|
|
575
|
-
import * as
|
|
576
|
-
import { info as info2, success as success2 } from "@releasekit/core";
|
|
1083
|
+
import * as path6 from "path";
|
|
577
1084
|
async function runGitCommitStage(ctx) {
|
|
578
1085
|
const { input, config, cliOptions, cwd } = ctx;
|
|
579
1086
|
const dryRun = cliOptions.dryRun;
|
|
580
1087
|
const skipHooks = config.git.skipHooks ?? false;
|
|
581
1088
|
if (!input.commitMessage) {
|
|
582
|
-
|
|
1089
|
+
info("No commit message provided, skipping git commit");
|
|
583
1090
|
return;
|
|
584
1091
|
}
|
|
585
|
-
const filePaths = input.updates.map((u) =>
|
|
1092
|
+
const filePaths = input.updates.map((u) => path6.resolve(cwd, u.filePath));
|
|
586
1093
|
if (ctx.additionalFiles) {
|
|
587
|
-
filePaths.push(...ctx.additionalFiles.map((f) =>
|
|
1094
|
+
filePaths.push(...ctx.additionalFiles.map((f) => path6.resolve(cwd, f)));
|
|
588
1095
|
}
|
|
589
1096
|
if (filePaths.length === 0) {
|
|
590
|
-
|
|
1097
|
+
info("No files to commit");
|
|
591
1098
|
return;
|
|
592
1099
|
}
|
|
593
1100
|
try {
|
|
@@ -615,7 +1122,7 @@ async function runGitCommitStage(ctx) {
|
|
|
615
1122
|
});
|
|
616
1123
|
ctx.output.git.committed = true;
|
|
617
1124
|
if (!dryRun) {
|
|
618
|
-
|
|
1125
|
+
success("Created git commit");
|
|
619
1126
|
}
|
|
620
1127
|
} catch (error) {
|
|
621
1128
|
throw createPublishError(
|
|
@@ -633,7 +1140,7 @@ async function runGitCommitStage(ctx) {
|
|
|
633
1140
|
});
|
|
634
1141
|
ctx.output.git.tags.push(tag);
|
|
635
1142
|
if (!dryRun) {
|
|
636
|
-
|
|
1143
|
+
success(`Created tag: ${tag}`);
|
|
637
1144
|
}
|
|
638
1145
|
} catch (error) {
|
|
639
1146
|
throw createPublishError(
|
|
@@ -645,7 +1152,6 @@ async function runGitCommitStage(ctx) {
|
|
|
645
1152
|
}
|
|
646
1153
|
|
|
647
1154
|
// src/stages/git-push.ts
|
|
648
|
-
import { info as info3, success as success3 } from "@releasekit/core";
|
|
649
1155
|
function toGithubAuthedUrl(remoteUrl, token) {
|
|
650
1156
|
try {
|
|
651
1157
|
const url = new URL(remoteUrl);
|
|
@@ -662,14 +1168,14 @@ async function runGitPushStage(ctx) {
|
|
|
662
1168
|
const { config, cliOptions, cwd, output } = ctx;
|
|
663
1169
|
const dryRun = cliOptions.dryRun;
|
|
664
1170
|
if (!config.git.push) {
|
|
665
|
-
|
|
1171
|
+
info("Git push disabled in config, skipping");
|
|
666
1172
|
return;
|
|
667
1173
|
}
|
|
668
1174
|
if (!output.git.committed && output.git.tags.length === 0) {
|
|
669
|
-
|
|
1175
|
+
info("Nothing to push (no commits or tags created)");
|
|
670
1176
|
return;
|
|
671
1177
|
}
|
|
672
|
-
const { remote
|
|
1178
|
+
const { remote } = config.git;
|
|
673
1179
|
let pushMethod = config.git.pushMethod;
|
|
674
1180
|
if (pushMethod === "auto") {
|
|
675
1181
|
try {
|
|
@@ -689,7 +1195,19 @@ async function runGitPushStage(ctx) {
|
|
|
689
1195
|
pushRemote = authed;
|
|
690
1196
|
}
|
|
691
1197
|
}
|
|
1198
|
+
let branch;
|
|
692
1199
|
if (output.git.committed) {
|
|
1200
|
+
branch = config.git.branch;
|
|
1201
|
+
if (!branch) {
|
|
1202
|
+
const revResult = await execCommand("git", ["rev-parse", "--abbrev-ref", "HEAD"], { cwd, dryRun: false });
|
|
1203
|
+
branch = revResult.stdout.trim();
|
|
1204
|
+
if (branch === "HEAD") {
|
|
1205
|
+
throw createPublishError(
|
|
1206
|
+
"GIT_PUSH_ERROR" /* GIT_PUSH_ERROR */,
|
|
1207
|
+
"Cannot push: repository is in a detached HEAD state. Set git.branch in your config or pass --branch <name>."
|
|
1208
|
+
);
|
|
1209
|
+
}
|
|
1210
|
+
}
|
|
693
1211
|
await execCommand("git", ["push", pushRemote, branch], {
|
|
694
1212
|
cwd,
|
|
695
1213
|
dryRun,
|
|
@@ -705,9 +1223,12 @@ async function runGitPushStage(ctx) {
|
|
|
705
1223
|
}
|
|
706
1224
|
ctx.output.git.pushed = true;
|
|
707
1225
|
if (!dryRun) {
|
|
708
|
-
|
|
1226
|
+
success(`Pushed to ${remote}${branch ? `/${branch}` : ""}`);
|
|
709
1227
|
}
|
|
710
1228
|
} catch (error) {
|
|
1229
|
+
if (error instanceof PublishError) {
|
|
1230
|
+
throw error;
|
|
1231
|
+
}
|
|
711
1232
|
throw createPublishError(
|
|
712
1233
|
"GIT_PUSH_ERROR" /* GIT_PUSH_ERROR */,
|
|
713
1234
|
`${error instanceof Error ? error.message : String(error)}`
|
|
@@ -716,8 +1237,7 @@ async function runGitPushStage(ctx) {
|
|
|
716
1237
|
}
|
|
717
1238
|
|
|
718
1239
|
// src/stages/github-release.ts
|
|
719
|
-
import * as
|
|
720
|
-
import { debug as debug3, info as info4, success as success4, warn as warn2 } from "@releasekit/core";
|
|
1240
|
+
import * as fs7 from "fs";
|
|
721
1241
|
function resolveNotes(notesSetting, tag, changelogs, pipelineNotes) {
|
|
722
1242
|
if (notesSetting === "none") {
|
|
723
1243
|
return { useGithubNotes: false };
|
|
@@ -728,7 +1248,7 @@ function resolveNotes(notesSetting, tag, changelogs, pipelineNotes) {
|
|
|
728
1248
|
if (notesSetting !== "auto") {
|
|
729
1249
|
const body = readFileIfExists(notesSetting);
|
|
730
1250
|
if (body) return { body, useGithubNotes: false };
|
|
731
|
-
|
|
1251
|
+
debug(`Notes file not found: ${notesSetting}, falling back to GitHub auto-notes`);
|
|
732
1252
|
return { useGithubNotes: true };
|
|
733
1253
|
}
|
|
734
1254
|
if (pipelineNotes) {
|
|
@@ -756,7 +1276,7 @@ function findNotesForTag(tag, notes) {
|
|
|
756
1276
|
}
|
|
757
1277
|
function readFileIfExists(filePath) {
|
|
758
1278
|
try {
|
|
759
|
-
const content =
|
|
1279
|
+
const content = fs7.readFileSync(filePath, "utf-8").trim();
|
|
760
1280
|
return content || void 0;
|
|
761
1281
|
} catch {
|
|
762
1282
|
return void 0;
|
|
@@ -778,12 +1298,12 @@ async function runGithubReleaseStage(ctx) {
|
|
|
778
1298
|
const { config, cliOptions, output } = ctx;
|
|
779
1299
|
const dryRun = cliOptions.dryRun;
|
|
780
1300
|
if (!config.githubRelease.enabled) {
|
|
781
|
-
|
|
1301
|
+
debug("GitHub releases disabled in config");
|
|
782
1302
|
return;
|
|
783
1303
|
}
|
|
784
1304
|
const tags = output.git.tags.length > 0 ? output.git.tags : ctx.input.tags;
|
|
785
1305
|
if (tags.length === 0) {
|
|
786
|
-
|
|
1306
|
+
info("No tags available for GitHub release");
|
|
787
1307
|
return;
|
|
788
1308
|
}
|
|
789
1309
|
const firstTag = tags[0];
|
|
@@ -829,35 +1349,33 @@ async function runGithubReleaseStage(ctx) {
|
|
|
829
1349
|
result.url = execResult.stdout.trim();
|
|
830
1350
|
}
|
|
831
1351
|
if (!dryRun) {
|
|
832
|
-
|
|
1352
|
+
success(`Created GitHub release for ${tag}`);
|
|
833
1353
|
}
|
|
834
1354
|
} catch (error) {
|
|
835
1355
|
result.reason = error instanceof Error ? error.message : String(error);
|
|
836
|
-
|
|
1356
|
+
warn(`Failed to create GitHub release for ${tag}: ${result.reason}`);
|
|
837
1357
|
}
|
|
838
1358
|
ctx.output.githubReleases.push(result);
|
|
839
1359
|
}
|
|
840
1360
|
}
|
|
841
1361
|
|
|
842
1362
|
// src/stages/npm-publish.ts
|
|
843
|
-
import * as
|
|
844
|
-
import * as
|
|
845
|
-
import { debug as debug5, info as info5, success as success5, warn as warn3 } from "@releasekit/core";
|
|
1363
|
+
import * as fs9 from "fs";
|
|
1364
|
+
import * as path8 from "path";
|
|
846
1365
|
|
|
847
1366
|
// src/utils/npm-env.ts
|
|
848
|
-
import * as
|
|
849
|
-
import * as
|
|
850
|
-
import * as
|
|
851
|
-
import { debug as debug4 } from "@releasekit/core";
|
|
1367
|
+
import * as fs8 from "fs";
|
|
1368
|
+
import * as os2 from "os";
|
|
1369
|
+
import * as path7 from "path";
|
|
852
1370
|
function writeTempNpmrc(contents) {
|
|
853
|
-
const dir =
|
|
854
|
-
const npmrcPath =
|
|
855
|
-
|
|
1371
|
+
const dir = fs8.mkdtempSync(path7.join(os2.tmpdir(), "releasekit-npmrc-"));
|
|
1372
|
+
const npmrcPath = path7.join(dir, ".npmrc");
|
|
1373
|
+
fs8.writeFileSync(npmrcPath, contents, "utf-8");
|
|
856
1374
|
return {
|
|
857
1375
|
npmrcPath,
|
|
858
1376
|
cleanup: () => {
|
|
859
1377
|
try {
|
|
860
|
-
|
|
1378
|
+
fs8.rmSync(dir, { recursive: true, force: true });
|
|
861
1379
|
} catch {
|
|
862
1380
|
}
|
|
863
1381
|
}
|
|
@@ -885,7 +1403,7 @@ function createNpmSubprocessIsolation(options) {
|
|
|
885
1403
|
}
|
|
886
1404
|
lines.push("");
|
|
887
1405
|
const { npmrcPath, cleanup } = writeTempNpmrc(lines.join("\n"));
|
|
888
|
-
|
|
1406
|
+
debug(`Using isolated npm userconfig: ${npmrcPath}`);
|
|
889
1407
|
const isOidc = authMethod === "oidc";
|
|
890
1408
|
return {
|
|
891
1409
|
env: {
|
|
@@ -915,7 +1433,7 @@ async function runNpmPublishStage(ctx) {
|
|
|
915
1433
|
const { input, config, cliOptions, cwd } = ctx;
|
|
916
1434
|
const dryRun = cliOptions.dryRun;
|
|
917
1435
|
if (!config.npm.enabled) {
|
|
918
|
-
|
|
1436
|
+
info("NPM publishing disabled in config");
|
|
919
1437
|
return;
|
|
920
1438
|
}
|
|
921
1439
|
const authMethod = config.npm.auth === "auto" ? detectNpmAuth() : config.npm.auth;
|
|
@@ -936,16 +1454,16 @@ async function runNpmPublishStage(ctx) {
|
|
|
936
1454
|
success: false,
|
|
937
1455
|
skipped: false
|
|
938
1456
|
};
|
|
939
|
-
const pkgJsonPath =
|
|
1457
|
+
const pkgJsonPath = path8.resolve(cwd, update.filePath);
|
|
940
1458
|
try {
|
|
941
|
-
const pkgContent =
|
|
1459
|
+
const pkgContent = fs9.readFileSync(pkgJsonPath, "utf-8");
|
|
942
1460
|
const pkgJson = JSON.parse(pkgContent);
|
|
943
1461
|
if (pkgJson.private) {
|
|
944
1462
|
result.skipped = true;
|
|
945
1463
|
result.success = true;
|
|
946
1464
|
result.reason = "Package is private";
|
|
947
1465
|
ctx.output.npm.push(result);
|
|
948
|
-
|
|
1466
|
+
debug(`Skipping private package: ${update.packageName}`);
|
|
949
1467
|
continue;
|
|
950
1468
|
}
|
|
951
1469
|
} catch {
|
|
@@ -974,11 +1492,11 @@ async function runNpmPublishStage(ctx) {
|
|
|
974
1492
|
result.success = true;
|
|
975
1493
|
result.reason = "Already published";
|
|
976
1494
|
ctx.output.npm.push(result);
|
|
977
|
-
|
|
1495
|
+
warn(`${update.packageName}@${update.newVersion} is already published, skipping`);
|
|
978
1496
|
continue;
|
|
979
1497
|
}
|
|
980
1498
|
const distTag = getDistTag(update.newVersion, config.npm.tag);
|
|
981
|
-
const pkgDir =
|
|
1499
|
+
const pkgDir = path8.dirname(path8.resolve(cwd, update.filePath));
|
|
982
1500
|
const { file: pubFile, args: pubArgs } = buildPublishCommand(ctx.packageManager, update.packageName, pkgDir, {
|
|
983
1501
|
access: config.npm.access,
|
|
984
1502
|
tag: distTag,
|
|
@@ -994,11 +1512,11 @@ async function runNpmPublishStage(ctx) {
|
|
|
994
1512
|
});
|
|
995
1513
|
result.success = true;
|
|
996
1514
|
if (!dryRun) {
|
|
997
|
-
|
|
1515
|
+
success(`Published ${update.packageName}@${update.newVersion} to npm`);
|
|
998
1516
|
}
|
|
999
1517
|
} catch (error) {
|
|
1000
1518
|
result.reason = error instanceof Error ? error.message : String(error);
|
|
1001
|
-
|
|
1519
|
+
warn(`Failed to publish ${update.packageName}: ${result.reason}`);
|
|
1002
1520
|
}
|
|
1003
1521
|
ctx.output.npm.push(result);
|
|
1004
1522
|
}
|
|
@@ -1008,32 +1526,31 @@ async function runNpmPublishStage(ctx) {
|
|
|
1008
1526
|
}
|
|
1009
1527
|
|
|
1010
1528
|
// src/stages/prepare.ts
|
|
1011
|
-
import * as
|
|
1012
|
-
import * as
|
|
1013
|
-
import { debug as debug6, info as info6 } from "@releasekit/core";
|
|
1529
|
+
import * as fs10 from "fs";
|
|
1530
|
+
import * as path9 from "path";
|
|
1014
1531
|
async function runPrepareStage(ctx) {
|
|
1015
1532
|
const { input, config, cliOptions, cwd } = ctx;
|
|
1016
1533
|
if (config.npm.enabled && config.npm.copyFiles.length > 0) {
|
|
1017
1534
|
for (const update of input.updates) {
|
|
1018
|
-
const pkgDir =
|
|
1535
|
+
const pkgDir = path9.dirname(path9.resolve(cwd, update.filePath));
|
|
1019
1536
|
for (const file of config.npm.copyFiles) {
|
|
1020
|
-
const src =
|
|
1021
|
-
const dest =
|
|
1022
|
-
if (!
|
|
1023
|
-
|
|
1537
|
+
const src = path9.resolve(cwd, file);
|
|
1538
|
+
const dest = path9.join(pkgDir, file);
|
|
1539
|
+
if (!fs10.existsSync(src)) {
|
|
1540
|
+
debug(`Source file not found, skipping copy: ${src}`);
|
|
1024
1541
|
continue;
|
|
1025
1542
|
}
|
|
1026
|
-
if (
|
|
1027
|
-
|
|
1543
|
+
if (path9.resolve(path9.dirname(src)) === path9.resolve(pkgDir)) {
|
|
1544
|
+
debug(`Skipping copy of ${file} - same directory as source`);
|
|
1028
1545
|
continue;
|
|
1029
1546
|
}
|
|
1030
1547
|
if (cliOptions.dryRun) {
|
|
1031
|
-
|
|
1548
|
+
info(`[DRY RUN] Would copy ${src} \u2192 ${dest}`);
|
|
1032
1549
|
continue;
|
|
1033
1550
|
}
|
|
1034
1551
|
try {
|
|
1035
|
-
|
|
1036
|
-
|
|
1552
|
+
fs10.copyFileSync(src, dest);
|
|
1553
|
+
debug(`Copied ${file} \u2192 ${pkgDir}`);
|
|
1037
1554
|
} catch (error) {
|
|
1038
1555
|
throw createPublishError(
|
|
1039
1556
|
"FILE_COPY_ERROR" /* FILE_COPY_ERROR */,
|
|
@@ -1045,26 +1562,22 @@ async function runPrepareStage(ctx) {
|
|
|
1045
1562
|
}
|
|
1046
1563
|
if (config.cargo.enabled) {
|
|
1047
1564
|
for (const update of input.updates) {
|
|
1048
|
-
const pkgDir =
|
|
1049
|
-
const cargoPath =
|
|
1050
|
-
if (!
|
|
1565
|
+
const pkgDir = path9.dirname(path9.resolve(cwd, update.filePath));
|
|
1566
|
+
const cargoPath = path9.join(pkgDir, "Cargo.toml");
|
|
1567
|
+
if (!fs10.existsSync(cargoPath)) {
|
|
1051
1568
|
continue;
|
|
1052
1569
|
}
|
|
1053
1570
|
if (cliOptions.dryRun) {
|
|
1054
|
-
|
|
1571
|
+
info(`[DRY RUN] Would update ${cargoPath} to version ${update.newVersion}`);
|
|
1055
1572
|
continue;
|
|
1056
1573
|
}
|
|
1057
1574
|
updateCargoVersion(cargoPath, update.newVersion);
|
|
1058
|
-
|
|
1575
|
+
debug(`Updated ${cargoPath} to version ${update.newVersion}`);
|
|
1059
1576
|
}
|
|
1060
1577
|
}
|
|
1061
1578
|
}
|
|
1062
1579
|
|
|
1063
|
-
// src/stages/verify.ts
|
|
1064
|
-
import { debug as debug8, info as info7, success as success6, warn as warn4 } from "@releasekit/core";
|
|
1065
|
-
|
|
1066
1580
|
// src/utils/retry.ts
|
|
1067
|
-
import { debug as debug7 } from "@releasekit/core";
|
|
1068
1581
|
async function withRetry(fn, options, shouldRetry) {
|
|
1069
1582
|
let lastError;
|
|
1070
1583
|
let delay = options.initialDelay;
|
|
@@ -1077,7 +1590,7 @@ async function withRetry(fn, options, shouldRetry) {
|
|
|
1077
1590
|
throw error;
|
|
1078
1591
|
}
|
|
1079
1592
|
if (attempt < options.maxAttempts) {
|
|
1080
|
-
|
|
1593
|
+
debug(`Attempt ${attempt}/${options.maxAttempts} failed, retrying in ${delay}ms...`);
|
|
1081
1594
|
await sleep(delay);
|
|
1082
1595
|
delay = Math.floor(delay * options.backoffMultiplier);
|
|
1083
1596
|
}
|
|
@@ -1086,7 +1599,7 @@ async function withRetry(fn, options, shouldRetry) {
|
|
|
1086
1599
|
throw lastError;
|
|
1087
1600
|
}
|
|
1088
1601
|
function sleep(ms) {
|
|
1089
|
-
return new Promise((
|
|
1602
|
+
return new Promise((resolve6) => setTimeout(resolve6, ms));
|
|
1090
1603
|
}
|
|
1091
1604
|
|
|
1092
1605
|
// src/stages/verify.ts
|
|
@@ -1103,7 +1616,7 @@ async function runVerifyStage(ctx) {
|
|
|
1103
1616
|
attempts: 0
|
|
1104
1617
|
};
|
|
1105
1618
|
if (cliOptions.dryRun) {
|
|
1106
|
-
|
|
1619
|
+
info(`[DRY RUN] Would verify ${pkg.packageName}@${pkg.version} on npm`);
|
|
1107
1620
|
result.verified = true;
|
|
1108
1621
|
ctx.output.verification.push(result);
|
|
1109
1622
|
continue;
|
|
@@ -1119,12 +1632,12 @@ async function runVerifyStage(ctx) {
|
|
|
1119
1632
|
if (viewResult.exitCode !== 0 || !viewResult.stdout.trim()) {
|
|
1120
1633
|
throw new Error(`${pkg.packageName}@${pkg.version} not yet available on npm`);
|
|
1121
1634
|
}
|
|
1122
|
-
|
|
1635
|
+
debug(`Verified ${pkg.packageName}@${pkg.version} on npm`);
|
|
1123
1636
|
}, config.verify.npm);
|
|
1124
1637
|
result.verified = true;
|
|
1125
|
-
|
|
1638
|
+
success(`Verified ${pkg.packageName}@${pkg.version} on npm`);
|
|
1126
1639
|
} catch {
|
|
1127
|
-
|
|
1640
|
+
warn(`Failed to verify ${pkg.packageName}@${pkg.version} on npm after ${result.attempts} attempts`);
|
|
1128
1641
|
}
|
|
1129
1642
|
ctx.output.verification.push(result);
|
|
1130
1643
|
}
|
|
@@ -1140,7 +1653,7 @@ async function runVerifyStage(ctx) {
|
|
|
1140
1653
|
attempts: 0
|
|
1141
1654
|
};
|
|
1142
1655
|
if (cliOptions.dryRun) {
|
|
1143
|
-
|
|
1656
|
+
info(`[DRY RUN] Would verify ${crate.packageName}@${crate.version} on crates.io`);
|
|
1144
1657
|
result.verified = true;
|
|
1145
1658
|
ctx.output.verification.push(result);
|
|
1146
1659
|
continue;
|
|
@@ -1152,12 +1665,12 @@ async function runVerifyStage(ctx) {
|
|
|
1152
1665
|
if (!response.ok) {
|
|
1153
1666
|
throw new Error(`${crate.packageName}@${crate.version} not yet available on crates.io`);
|
|
1154
1667
|
}
|
|
1155
|
-
|
|
1668
|
+
debug(`Verified ${crate.packageName}@${crate.version} on crates.io`);
|
|
1156
1669
|
}, config.verify.cargo);
|
|
1157
1670
|
result.verified = true;
|
|
1158
|
-
|
|
1671
|
+
success(`Verified ${crate.packageName}@${crate.version} on crates.io`);
|
|
1159
1672
|
} catch {
|
|
1160
|
-
|
|
1673
|
+
warn(`Failed to verify ${crate.packageName}@${crate.version} on crates.io after ${result.attempts} attempts`);
|
|
1161
1674
|
}
|
|
1162
1675
|
ctx.output.verification.push(result);
|
|
1163
1676
|
}
|
|
@@ -1237,41 +1750,40 @@ async function runPipeline(input, config, options) {
|
|
|
1237
1750
|
}
|
|
1238
1751
|
|
|
1239
1752
|
// src/stages/input.ts
|
|
1240
|
-
import * as
|
|
1241
|
-
import {
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
|
|
1248
|
-
originalType: z.string().optional()
|
|
1753
|
+
import * as fs11 from "fs";
|
|
1754
|
+
import { z as z3 } from "zod";
|
|
1755
|
+
var VersionChangelogEntrySchema = z3.object({
|
|
1756
|
+
type: z3.string(),
|
|
1757
|
+
description: z3.string(),
|
|
1758
|
+
issueIds: z3.array(z3.string()).optional(),
|
|
1759
|
+
scope: z3.string().optional(),
|
|
1760
|
+
originalType: z3.string().optional()
|
|
1249
1761
|
});
|
|
1250
|
-
var VersionPackageChangelogSchema =
|
|
1251
|
-
packageName:
|
|
1252
|
-
version:
|
|
1253
|
-
previousVersion:
|
|
1254
|
-
revisionRange:
|
|
1255
|
-
repoUrl:
|
|
1256
|
-
entries:
|
|
1762
|
+
var VersionPackageChangelogSchema = z3.object({
|
|
1763
|
+
packageName: z3.string(),
|
|
1764
|
+
version: z3.string(),
|
|
1765
|
+
previousVersion: z3.string().nullable(),
|
|
1766
|
+
revisionRange: z3.string(),
|
|
1767
|
+
repoUrl: z3.string().nullable(),
|
|
1768
|
+
entries: z3.array(VersionChangelogEntrySchema)
|
|
1257
1769
|
});
|
|
1258
|
-
var VersionPackageUpdateSchema =
|
|
1259
|
-
packageName:
|
|
1260
|
-
newVersion:
|
|
1261
|
-
filePath:
|
|
1770
|
+
var VersionPackageUpdateSchema = z3.object({
|
|
1771
|
+
packageName: z3.string(),
|
|
1772
|
+
newVersion: z3.string(),
|
|
1773
|
+
filePath: z3.string()
|
|
1262
1774
|
});
|
|
1263
|
-
var VersionOutputSchema =
|
|
1264
|
-
dryRun:
|
|
1265
|
-
updates:
|
|
1266
|
-
changelogs:
|
|
1267
|
-
commitMessage:
|
|
1268
|
-
tags:
|
|
1775
|
+
var VersionOutputSchema = z3.object({
|
|
1776
|
+
dryRun: z3.boolean(),
|
|
1777
|
+
updates: z3.array(VersionPackageUpdateSchema),
|
|
1778
|
+
changelogs: z3.array(VersionPackageChangelogSchema),
|
|
1779
|
+
commitMessage: z3.string().optional(),
|
|
1780
|
+
tags: z3.array(z3.string())
|
|
1269
1781
|
});
|
|
1270
1782
|
async function parseInput(inputPath) {
|
|
1271
1783
|
let raw;
|
|
1272
1784
|
if (inputPath) {
|
|
1273
1785
|
try {
|
|
1274
|
-
raw =
|
|
1786
|
+
raw = fs11.readFileSync(inputPath, "utf-8");
|
|
1275
1787
|
} catch {
|
|
1276
1788
|
throw createPublishError("INPUT_PARSE_ERROR" /* INPUT_PARSE_ERROR */, `Could not read file: ${inputPath}`);
|
|
1277
1789
|
}
|
|
@@ -1291,7 +1803,7 @@ async function parseInput(inputPath) {
|
|
|
1291
1803
|
${issues}`);
|
|
1292
1804
|
}
|
|
1293
1805
|
if (result.data.updates.length === 0) {
|
|
1294
|
-
|
|
1806
|
+
info("No package updates in version output \u2014 pipeline will be a no-op");
|
|
1295
1807
|
}
|
|
1296
1808
|
return result.data;
|
|
1297
1809
|
}
|
|
@@ -1304,7 +1816,12 @@ async function readStdin() {
|
|
|
1304
1816
|
}
|
|
1305
1817
|
|
|
1306
1818
|
export {
|
|
1307
|
-
|
|
1819
|
+
readPackageVersion,
|
|
1820
|
+
setLogLevel,
|
|
1821
|
+
setJsonMode,
|
|
1822
|
+
EXIT_CODES,
|
|
1823
|
+
parseCargoToml,
|
|
1824
|
+
loadConfig2 as loadConfig,
|
|
1308
1825
|
getDefaultConfig2 as getDefaultConfig,
|
|
1309
1826
|
BasePublishError,
|
|
1310
1827
|
PublishError,
|
|
@@ -1313,7 +1830,6 @@ export {
|
|
|
1313
1830
|
createPublishError,
|
|
1314
1831
|
detectNpmAuth,
|
|
1315
1832
|
hasCargoAuth,
|
|
1316
|
-
parseCargoToml,
|
|
1317
1833
|
updateCargoVersion,
|
|
1318
1834
|
extractPathDeps,
|
|
1319
1835
|
isPrerelease,
|