@releasekit/version 0.2.0-next.9 → 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.
@@ -1,16 +1,355 @@
1
1
  import {
2
- BaseVersionError
3
- } from "./chunk-GQLJ7JQY.js";
2
+ BaseVersionError,
3
+ ReleaseKitError
4
+ } from "./chunk-PVBHVUZB.js";
4
5
  import {
5
6
  execAsync,
6
7
  execSync
7
8
  } from "./chunk-LMPZV35Z.js";
8
9
 
9
- // src/config.ts
10
- import { loadVersionConfig } from "@releasekit/config";
10
+ // ../config/dist/index.js
11
+ import * as fs from "fs";
12
+ import * as path from "path";
13
+ import * as TOML from "smol-toml";
14
+ import * as fs3 from "fs";
15
+ import * as path3 from "path";
16
+ import { z as z2 } from "zod";
17
+ import { z } from "zod";
18
+ import * as fs2 from "fs";
19
+ import * as os from "os";
20
+ import * as path2 from "path";
21
+ function parseCargoToml(cargoPath) {
22
+ const content = fs.readFileSync(cargoPath, "utf-8");
23
+ return TOML.parse(content);
24
+ }
25
+ function isCargoToml(filePath) {
26
+ return path.basename(filePath) === "Cargo.toml";
27
+ }
28
+ var ConfigError = class extends ReleaseKitError {
29
+ code = "CONFIG_ERROR";
30
+ suggestions;
31
+ constructor(message, suggestions) {
32
+ super(message);
33
+ this.suggestions = suggestions ?? [
34
+ "Check that releasekit.config.json exists and is valid JSON",
35
+ "Run with --verbose for more details"
36
+ ];
37
+ }
38
+ };
39
+ var MAX_JSONC_LENGTH = 1e5;
40
+ function parseJsonc(content) {
41
+ if (content.length > MAX_JSONC_LENGTH) {
42
+ throw new Error(`JSONC content too long: ${content.length} characters (max ${MAX_JSONC_LENGTH})`);
43
+ }
44
+ try {
45
+ return JSON.parse(content);
46
+ } catch {
47
+ const cleaned = content.replace(/\/\/[^\r\n]{0,10000}$/gm, "").replace(/\/\*[\s\S]{0,50000}?\*\//g, "").trim();
48
+ return JSON.parse(cleaned);
49
+ }
50
+ }
51
+ var GitConfigSchema = z.object({
52
+ remote: z.string().default("origin"),
53
+ branch: z.string().default("main"),
54
+ pushMethod: z.enum(["auto", "ssh", "https"]).default("auto"),
55
+ /**
56
+ * Optional env var name containing a GitHub token for HTTPS pushes.
57
+ * When set, publish steps can use this token without mutating git remotes.
58
+ */
59
+ httpsTokenEnv: z.string().optional(),
60
+ push: z.boolean().optional(),
61
+ skipHooks: z.boolean().optional()
62
+ });
63
+ var MonorepoConfigSchema = z.object({
64
+ mode: z.enum(["root", "packages", "both"]).optional(),
65
+ rootPath: z.string().optional(),
66
+ packagesPath: z.string().optional(),
67
+ mainPackage: z.string().optional()
68
+ });
69
+ var BranchPatternSchema = z.object({
70
+ pattern: z.string(),
71
+ releaseType: z.enum(["major", "minor", "patch", "prerelease"])
72
+ });
73
+ var VersionCargoConfigSchema = z.object({
74
+ enabled: z.boolean().default(true),
75
+ paths: z.array(z.string()).optional()
76
+ });
77
+ var VersionConfigSchema = z.object({
78
+ tagTemplate: z.string().default("v{version}"),
79
+ packageSpecificTags: z.boolean().default(false),
80
+ preset: z.string().default("conventional"),
81
+ sync: z.boolean().default(true),
82
+ packages: z.array(z.string()).default([]),
83
+ mainPackage: z.string().optional(),
84
+ updateInternalDependencies: z.enum(["major", "minor", "patch", "no-internal-update"]).default("minor"),
85
+ skip: z.array(z.string()).optional(),
86
+ commitMessage: z.string().optional(),
87
+ versionStrategy: z.enum(["branchPattern", "commitMessage"]).default("commitMessage"),
88
+ branchPatterns: z.array(BranchPatternSchema).optional(),
89
+ defaultReleaseType: z.enum(["major", "minor", "patch", "prerelease"]).optional(),
90
+ mismatchStrategy: z.enum(["error", "warn", "ignore", "prefer-package", "prefer-git"]).default("warn"),
91
+ versionPrefix: z.string().default(""),
92
+ prereleaseIdentifier: z.string().optional(),
93
+ strictReachable: z.boolean().default(false),
94
+ cargo: VersionCargoConfigSchema.optional()
95
+ });
96
+ var NpmConfigSchema = z.object({
97
+ enabled: z.boolean().default(true),
98
+ auth: z.enum(["auto", "oidc", "token"]).default("auto"),
99
+ provenance: z.boolean().default(true),
100
+ access: z.enum(["public", "restricted"]).default("public"),
101
+ registry: z.string().default("https://registry.npmjs.org"),
102
+ copyFiles: z.array(z.string()).default(["LICENSE"]),
103
+ tag: z.string().default("latest")
104
+ });
105
+ var CargoPublishConfigSchema = z.object({
106
+ enabled: z.boolean().default(false),
107
+ noVerify: z.boolean().default(false),
108
+ publishOrder: z.array(z.string()).default([]),
109
+ clean: z.boolean().default(false)
110
+ });
111
+ var PublishGitConfigSchema = z.object({
112
+ push: z.boolean().default(true),
113
+ pushMethod: z.enum(["auto", "ssh", "https"]).optional(),
114
+ remote: z.string().optional(),
115
+ branch: z.string().optional(),
116
+ httpsTokenEnv: z.string().optional(),
117
+ skipHooks: z.boolean().optional()
118
+ });
119
+ var GitHubReleaseConfigSchema = z.object({
120
+ enabled: z.boolean().default(true),
121
+ draft: z.boolean().default(true),
122
+ perPackage: z.boolean().default(true),
123
+ prerelease: z.union([z.literal("auto"), z.boolean()]).default("auto"),
124
+ /**
125
+ * Controls how release notes are sourced for GitHub releases.
126
+ * - 'auto': Use RELEASE_NOTES.md if it exists, then per-package changelog
127
+ * data from the version output, then GitHub's auto-generated notes.
128
+ * - 'github': Always use GitHub's auto-generated notes.
129
+ * - 'none': No notes body.
130
+ * - Any other string: Treated as a file path to read notes from.
131
+ */
132
+ releaseNotes: z.union([z.literal("auto"), z.literal("github"), z.literal("none"), z.string()]).default("auto")
133
+ });
134
+ var VerifyRegistryConfigSchema = z.object({
135
+ enabled: z.boolean().default(true),
136
+ maxAttempts: z.number().int().positive().default(5),
137
+ initialDelay: z.number().int().positive().default(15e3),
138
+ backoffMultiplier: z.number().positive().default(2)
139
+ });
140
+ var VerifyConfigSchema = z.object({
141
+ npm: VerifyRegistryConfigSchema.default({
142
+ enabled: true,
143
+ maxAttempts: 5,
144
+ initialDelay: 15e3,
145
+ backoffMultiplier: 2
146
+ }),
147
+ cargo: VerifyRegistryConfigSchema.default({
148
+ enabled: true,
149
+ maxAttempts: 10,
150
+ initialDelay: 3e4,
151
+ backoffMultiplier: 2
152
+ })
153
+ });
154
+ var PublishConfigSchema = z.object({
155
+ git: PublishGitConfigSchema.optional(),
156
+ npm: NpmConfigSchema.default({
157
+ enabled: true,
158
+ auth: "auto",
159
+ provenance: true,
160
+ access: "public",
161
+ registry: "https://registry.npmjs.org",
162
+ copyFiles: ["LICENSE"],
163
+ tag: "latest"
164
+ }),
165
+ cargo: CargoPublishConfigSchema.default({
166
+ enabled: false,
167
+ noVerify: false,
168
+ publishOrder: [],
169
+ clean: false
170
+ }),
171
+ githubRelease: GitHubReleaseConfigSchema.default({
172
+ enabled: true,
173
+ draft: true,
174
+ perPackage: true,
175
+ prerelease: "auto",
176
+ releaseNotes: "auto"
177
+ }),
178
+ verify: VerifyConfigSchema.default({
179
+ npm: {
180
+ enabled: true,
181
+ maxAttempts: 5,
182
+ initialDelay: 15e3,
183
+ backoffMultiplier: 2
184
+ },
185
+ cargo: {
186
+ enabled: true,
187
+ maxAttempts: 10,
188
+ initialDelay: 3e4,
189
+ backoffMultiplier: 2
190
+ }
191
+ })
192
+ });
193
+ var TemplateConfigSchema = z.object({
194
+ path: z.string().optional(),
195
+ engine: z.enum(["handlebars", "liquid", "ejs"]).optional()
196
+ });
197
+ var OutputConfigSchema = z.object({
198
+ format: z.enum(["markdown", "github-release", "json"]),
199
+ file: z.string().optional(),
200
+ options: z.record(z.string(), z.unknown()).optional(),
201
+ templates: TemplateConfigSchema.optional()
202
+ });
203
+ var LLMOptionsSchema = z.object({
204
+ timeout: z.number().optional(),
205
+ maxTokens: z.number().optional(),
206
+ temperature: z.number().optional()
207
+ });
208
+ var LLMRetryConfigSchema = z.object({
209
+ maxAttempts: z.number().int().positive().optional(),
210
+ initialDelay: z.number().nonnegative().optional(),
211
+ maxDelay: z.number().positive().optional(),
212
+ backoffFactor: z.number().positive().optional()
213
+ });
214
+ var LLMTasksConfigSchema = z.object({
215
+ summarize: z.boolean().optional(),
216
+ enhance: z.boolean().optional(),
217
+ categorize: z.boolean().optional(),
218
+ releaseNotes: z.boolean().optional()
219
+ });
220
+ var LLMCategorySchema = z.object({
221
+ name: z.string(),
222
+ description: z.string(),
223
+ scopes: z.array(z.string()).optional()
224
+ });
225
+ var ScopeRulesSchema = z.object({
226
+ allowed: z.array(z.string()).optional(),
227
+ caseSensitive: z.boolean().default(false),
228
+ invalidScopeAction: z.enum(["remove", "keep", "fallback"]).default("remove"),
229
+ fallbackScope: z.string().optional()
230
+ });
231
+ var ScopeConfigSchema = z.object({
232
+ mode: z.enum(["restricted", "packages", "none", "unrestricted"]).default("unrestricted"),
233
+ rules: ScopeRulesSchema.optional()
234
+ });
235
+ var LLMPromptOverridesSchema = z.object({
236
+ enhance: z.string().optional(),
237
+ categorize: z.string().optional(),
238
+ enhanceAndCategorize: z.string().optional(),
239
+ summarize: z.string().optional(),
240
+ releaseNotes: z.string().optional()
241
+ });
242
+ var LLMPromptsConfigSchema = z.object({
243
+ instructions: LLMPromptOverridesSchema.optional(),
244
+ templates: LLMPromptOverridesSchema.optional()
245
+ });
246
+ var LLMConfigSchema = z.object({
247
+ provider: z.string(),
248
+ model: z.string(),
249
+ baseURL: z.string().optional(),
250
+ apiKey: z.string().optional(),
251
+ options: LLMOptionsSchema.optional(),
252
+ concurrency: z.number().int().positive().optional(),
253
+ retry: LLMRetryConfigSchema.optional(),
254
+ tasks: LLMTasksConfigSchema.optional(),
255
+ categories: z.array(LLMCategorySchema).optional(),
256
+ style: z.string().optional(),
257
+ scopes: ScopeConfigSchema.optional(),
258
+ prompts: LLMPromptsConfigSchema.optional()
259
+ });
260
+ var NotesInputConfigSchema = z.object({
261
+ source: z.string().optional(),
262
+ file: z.string().optional()
263
+ });
264
+ var NotesConfigSchema = z.object({
265
+ input: NotesInputConfigSchema.optional(),
266
+ output: z.array(OutputConfigSchema).default([{ format: "markdown", file: "CHANGELOG.md" }]),
267
+ monorepo: MonorepoConfigSchema.optional(),
268
+ templates: TemplateConfigSchema.optional(),
269
+ llm: LLMConfigSchema.optional(),
270
+ updateStrategy: z.enum(["prepend", "regenerate"]).default("prepend")
271
+ });
272
+ var ReleaseKitConfigSchema = z.object({
273
+ git: GitConfigSchema.optional(),
274
+ monorepo: MonorepoConfigSchema.optional(),
275
+ version: VersionConfigSchema.optional(),
276
+ publish: PublishConfigSchema.optional(),
277
+ notes: NotesConfigSchema.optional()
278
+ });
279
+ var MAX_INPUT_LENGTH = 1e4;
280
+ function substituteVariables(value) {
281
+ if (value.length > MAX_INPUT_LENGTH) {
282
+ throw new Error(`Input too long: ${value.length} characters (max ${MAX_INPUT_LENGTH})`);
283
+ }
284
+ const envPattern = /\{env:([^}]{1,1000})\}/g;
285
+ const filePattern = /\{file:([^}]{1,1000})\}/g;
286
+ let result = value;
287
+ result = result.replace(envPattern, (_, varName) => {
288
+ return process.env[varName] ?? "";
289
+ });
290
+ result = result.replace(filePattern, (_, filePath) => {
291
+ const expandedPath = filePath.startsWith("~") ? path2.join(os.homedir(), filePath.slice(1)) : filePath;
292
+ try {
293
+ return fs2.readFileSync(expandedPath, "utf-8").trim();
294
+ } catch {
295
+ return "";
296
+ }
297
+ });
298
+ return result;
299
+ }
300
+ var SOLE_REFERENCE_PATTERN = /^\{(?:env|file):[^}]+\}$/;
301
+ function substituteInObject(obj) {
302
+ if (typeof obj === "string") {
303
+ const result = substituteVariables(obj);
304
+ if (result === "" && SOLE_REFERENCE_PATTERN.test(obj)) {
305
+ return void 0;
306
+ }
307
+ return result;
308
+ }
309
+ if (Array.isArray(obj)) {
310
+ return obj.map((item) => substituteInObject(item));
311
+ }
312
+ if (obj && typeof obj === "object") {
313
+ const result = {};
314
+ for (const [key, value] of Object.entries(obj)) {
315
+ result[key] = substituteInObject(value);
316
+ }
317
+ return result;
318
+ }
319
+ return obj;
320
+ }
321
+ var AUTH_DIR = path2.join(os.homedir(), ".config", "releasekit");
322
+ var AUTH_FILE = path2.join(AUTH_DIR, "auth.json");
323
+ var CONFIG_FILE = "releasekit.config.json";
324
+ function loadConfigFile(configPath) {
325
+ if (!fs3.existsSync(configPath)) {
326
+ return {};
327
+ }
328
+ try {
329
+ const content = fs3.readFileSync(configPath, "utf-8");
330
+ const parsed = parseJsonc(content);
331
+ const substituted = substituteInObject(parsed);
332
+ return ReleaseKitConfigSchema.parse(substituted);
333
+ } catch (error) {
334
+ if (error instanceof z2.ZodError) {
335
+ const issues = error.issues.map((i) => ` ${i.path.join(".")}: ${i.message}`).join("\n");
336
+ throw new ConfigError(`Config validation errors:
337
+ ${issues}`);
338
+ }
339
+ if (error instanceof SyntaxError) {
340
+ throw new ConfigError(`Invalid JSON in config file: ${error.message}`);
341
+ }
342
+ throw error;
343
+ }
344
+ }
345
+ function loadConfig(options) {
346
+ const cwd3 = options?.cwd ?? process.cwd();
347
+ const configPath = options?.configPath ?? path3.join(cwd3, CONFIG_FILE);
348
+ return loadConfigFile(configPath);
349
+ }
11
350
 
12
351
  // src/types.ts
13
- function toVersionConfig(config) {
352
+ function toVersionConfig(config, gitConfig) {
14
353
  if (!config) {
15
354
  return {
16
355
  tagTemplate: "v{version}",
@@ -19,7 +358,8 @@ function toVersionConfig(config) {
19
358
  sync: true,
20
359
  packages: [],
21
360
  updateInternalDependencies: "minor",
22
- versionPrefix: ""
361
+ versionPrefix: "",
362
+ baseBranch: gitConfig?.branch
23
363
  };
24
364
  }
25
365
  return {
@@ -38,19 +378,18 @@ function toVersionConfig(config) {
38
378
  releaseType: bp.releaseType
39
379
  })),
40
380
  defaultReleaseType: config.defaultReleaseType,
41
- skipHooks: config.skipHooks,
42
381
  mismatchStrategy: config.mismatchStrategy,
43
382
  versionPrefix: config.versionPrefix ?? "",
44
383
  prereleaseIdentifier: config.prereleaseIdentifier,
45
- baseBranch: config.baseBranch,
384
+ baseBranch: gitConfig?.branch,
46
385
  cargo: config.cargo
47
386
  };
48
387
  }
49
388
 
50
389
  // src/config.ts
51
- function loadConfig(options) {
52
- const versionConfig = loadVersionConfig(options);
53
- return toVersionConfig(versionConfig);
390
+ function loadConfig2(options) {
391
+ const fullConfig = loadConfig(options);
392
+ return toVersionConfig(fullConfig.version, fullConfig.git);
54
393
  }
55
394
 
56
395
  // src/errors/versionError.ts
@@ -183,14 +522,11 @@ function log(message, level = "info") {
183
522
  default:
184
523
  chalkFn = chalk.blue;
185
524
  }
525
+ const formattedMessage = level === "debug" ? `[DEBUG] ${message}` : message;
186
526
  if (isJsonOutputMode()) {
187
- if (level === "error") {
188
- chalkFn(message);
189
- console.error(message);
190
- }
527
+ console.error(chalkFn(formattedMessage));
191
528
  return;
192
529
  }
193
- const formattedMessage = level === "debug" ? `[DEBUG] ${message}` : message;
194
530
  if (level === "error") {
195
531
  console.error(chalkFn(formattedMessage));
196
532
  } else {
@@ -204,24 +540,8 @@ import { Bumper } from "conventional-recommended-bump";
204
540
  import semver3 from "semver";
205
541
 
206
542
  // src/git/repository.ts
207
- import { existsSync, statSync } from "fs";
208
- import { join } from "path";
209
- function isGitRepository(directory) {
210
- const gitDir = join(directory, ".git");
211
- if (!existsSync(gitDir)) {
212
- return false;
213
- }
214
- const stats = statSync(gitDir);
215
- if (!stats.isDirectory()) {
216
- return false;
217
- }
218
- try {
219
- execSync("git", ["rev-parse", "--is-inside-work-tree"], { cwd: directory });
220
- return true;
221
- } catch (_error) {
222
- return false;
223
- }
224
- }
543
+ import { existsSync as existsSync3, statSync } from "fs";
544
+ import { join as join3 } from "path";
225
545
  function getCurrentBranch() {
226
546
  const result = execSync("git", ["rev-parse", "--abbrev-ref", "HEAD"]);
227
547
  return result.toString().trim();
@@ -275,8 +595,8 @@ To fix this:
275
595
  let result = template.replace(/\$\{version\}/g, version).replace(/\$\{packageName\}/g, packageName || "");
276
596
  if (additionalContext) {
277
597
  for (const [key, value] of Object.entries(additionalContext)) {
278
- const placeholder = `\${${key}}`;
279
- result = result.replace(new RegExp(placeholder.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"), "g"), value);
598
+ const placeholder = `${key ? `\${${key}}` : ""}`;
599
+ result = result.replace(new RegExp(escapeRegExp(placeholder), "g"), value);
280
600
  }
281
601
  }
282
602
  return result;
@@ -474,16 +794,15 @@ async function getLatestTagForPackage(packageName, versionPrefix, options) {
474
794
  }
475
795
 
476
796
  // src/utils/manifestHelpers.ts
477
- import fs2 from "fs";
478
- import path2 from "path";
797
+ import fs5 from "fs";
798
+ import path5 from "path";
479
799
 
480
800
  // src/cargo/cargoHandler.ts
481
- import fs from "fs";
482
- import path from "path";
483
- import { isCargoToml, parseCargoToml } from "@releasekit/config";
484
- import * as TOML from "smol-toml";
801
+ import fs4 from "fs";
802
+ import path4 from "path";
803
+ import * as TOML2 from "smol-toml";
485
804
  function getCargoInfo(cargoPath) {
486
- if (!fs.existsSync(cargoPath)) {
805
+ if (!fs4.existsSync(cargoPath)) {
487
806
  log(`Cargo.toml file not found at: ${cargoPath}`, "error");
488
807
  throw new Error(`Cargo.toml file not found at: ${cargoPath}`);
489
808
  }
@@ -497,7 +816,7 @@ function getCargoInfo(cargoPath) {
497
816
  name: cargo.package.name,
498
817
  version: cargo.package.version || "0.0.0",
499
818
  path: cargoPath,
500
- dir: path.dirname(cargoPath),
819
+ dir: path4.dirname(cargoPath),
501
820
  content: cargo
502
821
  };
503
822
  } catch (error) {
@@ -522,8 +841,8 @@ function updateCargoVersion(cargoPath, version, dryRun = false) {
522
841
  } else {
523
842
  cargo.package.version = version;
524
843
  }
525
- const updatedContent = TOML.stringify(cargo);
526
- fs.writeFileSync(cargoPath, updatedContent);
844
+ const updatedContent = TOML2.stringify(cargo);
845
+ fs4.writeFileSync(cargoPath, updatedContent);
527
846
  }
528
847
  addPackageUpdate(packageName, version, cargoPath);
529
848
  log(`${dryRun ? "[DRY RUN] Would update" : "Updated"} Cargo.toml at ${cargoPath} to version ${version}`, "success");
@@ -538,11 +857,11 @@ function updateCargoVersion(cargoPath, version, dryRun = false) {
538
857
 
539
858
  // src/utils/manifestHelpers.ts
540
859
  function getVersionFromManifests(packageDir) {
541
- const packageJsonPath = path2.join(packageDir, "package.json");
542
- const cargoTomlPath = path2.join(packageDir, "Cargo.toml");
543
- if (fs2.existsSync(packageJsonPath)) {
860
+ const packageJsonPath = path5.join(packageDir, "package.json");
861
+ const cargoTomlPath = path5.join(packageDir, "Cargo.toml");
862
+ if (fs5.existsSync(packageJsonPath)) {
544
863
  try {
545
- const packageJson = JSON.parse(fs2.readFileSync(packageJsonPath, "utf-8"));
864
+ const packageJson = JSON.parse(fs5.readFileSync(packageJsonPath, "utf-8"));
546
865
  if (packageJson.version) {
547
866
  log(`Found version ${packageJson.version} in package.json`, "debug");
548
867
  return {
@@ -558,7 +877,7 @@ function getVersionFromManifests(packageDir) {
558
877
  log(`Error reading package.json: ${errMsg}`, "warning");
559
878
  }
560
879
  }
561
- if (fs2.existsSync(cargoTomlPath)) {
880
+ if (fs5.existsSync(cargoTomlPath)) {
562
881
  try {
563
882
  const cargoInfo = getCargoInfo(cargoTomlPath);
564
883
  if (cargoInfo.version) {
@@ -585,18 +904,17 @@ function getVersionFromManifests(packageDir) {
585
904
  }
586
905
 
587
906
  // src/utils/versionUtils.ts
588
- import fs3 from "fs";
589
- import { parseCargoToml as parseCargoToml2 } from "@releasekit/config";
907
+ import fs6 from "fs";
590
908
  import semver2 from "semver";
591
909
 
592
910
  // src/git/tagVerification.ts
593
- function verifyTag(tagName, cwd4) {
911
+ function verifyTag(tagName, cwd3) {
594
912
  if (!tagName || tagName.trim() === "") {
595
913
  return { exists: false, reachable: false, error: "Empty tag name" };
596
914
  }
597
915
  try {
598
916
  execSync("git", ["rev-parse", "--verify", tagName], {
599
- cwd: cwd4,
917
+ cwd: cwd3,
600
918
  stdio: "ignore"
601
919
  });
602
920
  return { exists: true, reachable: true };
@@ -693,11 +1011,11 @@ var VersionMismatchError = class extends Error {
693
1011
  this.name = "VersionMismatchError";
694
1012
  }
695
1013
  };
696
- async function getBestVersionSource(tagName, packageVersion, cwd4, mismatchStrategy = "error", strictReachable = false) {
1014
+ async function getBestVersionSource(tagName, packageVersion, cwd3, mismatchStrategy = "error", strictReachable = false) {
697
1015
  if (!tagName?.trim()) {
698
1016
  return packageVersion ? { source: "package", version: packageVersion, reason: "No git tag provided" } : { source: "initial", version: "0.1.0", reason: "No git tag or package version available" };
699
1017
  }
700
- const verification = verifyTag(tagName, cwd4);
1018
+ const verification = verifyTag(tagName, cwd3);
701
1019
  if (!verification.exists || !verification.reachable) {
702
1020
  if (strictReachable) {
703
1021
  throw new Error(
@@ -962,20 +1280,89 @@ async function calculateVersion(config, options) {
962
1280
  }
963
1281
 
964
1282
  // src/package/packageProcessor.ts
965
- import * as fs5 from "fs";
966
- import path4 from "path";
967
- import { exit } from "process";
1283
+ import * as fs8 from "fs";
1284
+ import path7 from "path";
968
1285
 
969
1286
  // src/changelog/commitParser.ts
970
1287
  var CONVENTIONAL_COMMIT_REGEX = /^(\w+)(?:\(([^)]+)\))?(!)?: (.+)(?:\n\n([\s\S]*))?/;
971
1288
  var BREAKING_CHANGE_REGEX = /BREAKING CHANGE: ([\s\S]+?)(?:\n\n|$)/;
1289
+ function extractAllChangelogEntriesWithHash(projectDir, revisionRange) {
1290
+ try {
1291
+ const args = ["log", revisionRange, "--pretty=format:%H|||%B---COMMIT_DELIMITER---", "--no-merges"];
1292
+ const output = execSync("git", args, { cwd: projectDir, encoding: "utf8" }).toString();
1293
+ const commits = output.split("---COMMIT_DELIMITER---").filter((commit) => commit.trim() !== "");
1294
+ return commits.map((commit) => {
1295
+ const [hash, ...messageParts] = commit.split("|||");
1296
+ const message = messageParts.join("|||").trim();
1297
+ const entry = parseCommitMessage(message);
1298
+ if (entry && hash) {
1299
+ return { hash: hash.trim(), entry };
1300
+ }
1301
+ return null;
1302
+ }).filter((item) => item !== null);
1303
+ } catch (error) {
1304
+ const errorMessage = error instanceof Error ? error.message : String(error);
1305
+ log(`Error extracting all commits with hash: ${errorMessage}`, "error");
1306
+ return [];
1307
+ }
1308
+ }
1309
+ function commitTouchesAnyPackage(projectDir, commitHash, packageDirs, sharedPackageDirs = []) {
1310
+ try {
1311
+ const output = execSync("git", ["diff-tree", "--no-commit-id", "--name-only", "-r", commitHash], {
1312
+ cwd: projectDir,
1313
+ encoding: "utf8"
1314
+ }).toString().trim();
1315
+ if (!output) {
1316
+ return false;
1317
+ }
1318
+ const changedFiles = output.split("\n");
1319
+ return changedFiles.some((file) => {
1320
+ return packageDirs.some((pkgDir) => {
1321
+ if (sharedPackageDirs.some((sharedDir) => pkgDir.includes(sharedDir))) {
1322
+ return false;
1323
+ }
1324
+ const normalizedFile = file.replace(/\\/g, "/");
1325
+ const normalizedPkgDir = pkgDir.replace(/\\/g, "/").replace(/^\.\//, "");
1326
+ return normalizedFile.startsWith(normalizedPkgDir);
1327
+ });
1328
+ });
1329
+ } catch (error) {
1330
+ log(
1331
+ `Error checking if commit ${commitHash} touches packages: ${error instanceof Error ? error.message : String(error)}`,
1332
+ "debug"
1333
+ );
1334
+ return false;
1335
+ }
1336
+ }
1337
+ function extractRepoLevelChangelogEntries(projectDir, revisionRange, packageDirs, sharedPackageDirs = []) {
1338
+ try {
1339
+ const allCommits = extractAllChangelogEntriesWithHash(projectDir, revisionRange);
1340
+ const repoLevelCommits = allCommits.filter((commit) => {
1341
+ const touchesPackage = commitTouchesAnyPackage(projectDir, commit.hash, packageDirs, sharedPackageDirs);
1342
+ return !touchesPackage;
1343
+ });
1344
+ if (repoLevelCommits.length > 0) {
1345
+ log(
1346
+ `Found ${repoLevelCommits.length} repo-level commit(s) (including shared packages: ${sharedPackageDirs.join(", ")})`,
1347
+ "debug"
1348
+ );
1349
+ }
1350
+ return repoLevelCommits.map((c) => c.entry);
1351
+ } catch (error) {
1352
+ log(`Error extracting repo-level commits: ${error instanceof Error ? error.message : String(error)}`, "warning");
1353
+ return [];
1354
+ }
1355
+ }
972
1356
  function extractChangelogEntriesFromCommits(projectDir, revisionRange) {
1357
+ return extractCommitsFromGitLog(projectDir, revisionRange, true);
1358
+ }
1359
+ function extractCommitsFromGitLog(projectDir, revisionRange, filterToPath) {
973
1360
  try {
974
- const output = execSync(
975
- "git",
976
- ["log", revisionRange, "--pretty=format:%B---COMMIT_DELIMITER---", "--no-merges", "--", "."],
977
- { cwd: projectDir, encoding: "utf8" }
978
- ).toString();
1361
+ const args = ["log", revisionRange, "--pretty=format:%B---COMMIT_DELIMITER---", "--no-merges"];
1362
+ if (filterToPath) {
1363
+ args.push("--", ".");
1364
+ }
1365
+ const output = execSync("git", args, { cwd: projectDir, encoding: "utf8" }).toString();
979
1366
  const commits = output.split("---COMMIT_DELIMITER---").filter((commit) => commit.trim() !== "");
980
1367
  return commits.map((commit) => parseCommitMessage(commit)).filter((entry) => entry !== null);
981
1368
  } catch (error) {
@@ -1068,168 +1455,6 @@ function extractIssueIds(body) {
1068
1455
  return issueIds;
1069
1456
  }
1070
1457
 
1071
- // src/git/commands.ts
1072
- import { cwd as cwd2 } from "process";
1073
-
1074
- // src/errors/gitError.ts
1075
- var GitError = class extends BaseVersionError {
1076
- };
1077
- function createGitError(code, details) {
1078
- const messages = {
1079
- ["NOT_GIT_REPO" /* NOT_GIT_REPO */]: "Not a git repository",
1080
- ["GIT_PROCESS_ERROR" /* GIT_PROCESS_ERROR */]: "Failed to create new version",
1081
- ["NO_FILES" /* NO_FILES */]: "No files specified for commit",
1082
- ["NO_COMMIT_MESSAGE" /* NO_COMMIT_MESSAGE */]: "Commit message is required",
1083
- ["GIT_ERROR" /* GIT_ERROR */]: "Git operation failed",
1084
- ["TAG_ALREADY_EXISTS" /* TAG_ALREADY_EXISTS */]: "Git tag already exists"
1085
- };
1086
- const suggestions = {
1087
- ["NOT_GIT_REPO" /* NOT_GIT_REPO */]: [
1088
- "Initialize git repository with: git init",
1089
- "Ensure you are in the correct directory"
1090
- ],
1091
- ["TAG_ALREADY_EXISTS" /* TAG_ALREADY_EXISTS */]: [
1092
- "Delete the existing tag: git tag -d <tag-name>",
1093
- "Use a different version by incrementing manually",
1094
- "Check if this version was already released"
1095
- ],
1096
- ["GIT_PROCESS_ERROR" /* GIT_PROCESS_ERROR */]: void 0,
1097
- ["NO_FILES" /* NO_FILES */]: void 0,
1098
- ["NO_COMMIT_MESSAGE" /* NO_COMMIT_MESSAGE */]: void 0,
1099
- ["GIT_ERROR" /* GIT_ERROR */]: void 0
1100
- };
1101
- const baseMessage = messages[code];
1102
- const fullMessage = details ? `${baseMessage}: ${details}` : baseMessage;
1103
- return new GitError(fullMessage, code, suggestions[code]);
1104
- }
1105
-
1106
- // src/git/commands.ts
1107
- async function gitAdd(files) {
1108
- return execAsync("git", ["add", ...files]);
1109
- }
1110
- async function gitCommit(options) {
1111
- const args = ["commit"];
1112
- if (options.amend) {
1113
- args.push("--amend");
1114
- }
1115
- if (options.author) {
1116
- args.push("--author", options.author);
1117
- }
1118
- if (options.date) {
1119
- args.push("--date", options.date);
1120
- }
1121
- if (options.skipHooks) {
1122
- args.push("--no-verify");
1123
- }
1124
- args.push("-m", options.message);
1125
- return execAsync("git", args);
1126
- }
1127
- async function createGitTag(options) {
1128
- const { tag, message = "" } = options;
1129
- const args = ["tag", "-a", "-m", message, tag];
1130
- try {
1131
- return await execAsync("git", args);
1132
- } catch (error) {
1133
- const errorMessage = error instanceof Error ? error.message : String(error);
1134
- if (errorMessage.includes("already exists")) {
1135
- throw createGitError(
1136
- "TAG_ALREADY_EXISTS" /* TAG_ALREADY_EXISTS */,
1137
- `Tag '${tag}' already exists in the repository. Please use a different version or delete the existing tag first.`
1138
- );
1139
- }
1140
- throw createGitError("GIT_ERROR" /* GIT_ERROR */, errorMessage);
1141
- }
1142
- }
1143
- async function gitProcess(options) {
1144
- const { files, nextTag, commitMessage, skipHooks, dryRun } = options;
1145
- if (!isGitRepository(cwd2())) {
1146
- throw createGitError("NOT_GIT_REPO" /* NOT_GIT_REPO */);
1147
- }
1148
- try {
1149
- if (!dryRun) {
1150
- await gitAdd(files);
1151
- await gitCommit({
1152
- message: commitMessage,
1153
- skipHooks
1154
- });
1155
- if (nextTag) {
1156
- const tagMessage = `New Version ${nextTag} generated at ${(/* @__PURE__ */ new Date()).toISOString()}`;
1157
- await createGitTag({
1158
- tag: nextTag,
1159
- message: tagMessage
1160
- });
1161
- }
1162
- } else {
1163
- log("[DRY RUN] Would add files:", "info");
1164
- for (const file of files) {
1165
- log(` - ${file}`, "info");
1166
- }
1167
- log(`[DRY RUN] Would commit with message: "${commitMessage}"`, "info");
1168
- if (nextTag) {
1169
- log(`[DRY RUN] Would create tag: ${nextTag}`, "info");
1170
- }
1171
- }
1172
- } catch (err) {
1173
- const errorMessage = err instanceof Error ? err.message : String(err);
1174
- if (errorMessage.includes("already exists") && nextTag) {
1175
- log(`Tag '${nextTag}' already exists in the repository.`, "error");
1176
- throw createGitError(
1177
- "TAG_ALREADY_EXISTS" /* TAG_ALREADY_EXISTS */,
1178
- `Tag '${nextTag}' already exists in the repository. Please use a different version or delete the existing tag first.`
1179
- );
1180
- }
1181
- log(`Git process error: ${errorMessage}`, "error");
1182
- if (err instanceof Error && err.stack) {
1183
- console.error("Git process stack trace:");
1184
- console.error(err.stack);
1185
- }
1186
- throw createGitError("GIT_PROCESS_ERROR" /* GIT_PROCESS_ERROR */, errorMessage);
1187
- }
1188
- }
1189
- async function createGitCommitAndTag(files, nextTag, commitMessage, skipHooks, dryRun) {
1190
- try {
1191
- if (!files || files.length === 0) {
1192
- throw createGitError("NO_FILES" /* NO_FILES */);
1193
- }
1194
- if (!commitMessage) {
1195
- throw createGitError("NO_COMMIT_MESSAGE" /* NO_COMMIT_MESSAGE */);
1196
- }
1197
- setCommitMessage(commitMessage);
1198
- if (nextTag) {
1199
- addTag(nextTag);
1200
- }
1201
- await gitProcess({
1202
- files,
1203
- nextTag,
1204
- commitMessage,
1205
- skipHooks,
1206
- dryRun
1207
- });
1208
- if (!dryRun) {
1209
- log(`Created tag: ${nextTag}`, "success");
1210
- }
1211
- } catch (error) {
1212
- if (error instanceof GitError) {
1213
- throw error;
1214
- }
1215
- const errorMessage = error instanceof Error ? error.message : String(error);
1216
- log(`Failed to create git commit and tag: ${errorMessage}`, "error");
1217
- if (error instanceof Error) {
1218
- console.error("Git operation error details:");
1219
- console.error(error.stack || error.message);
1220
- if (errorMessage.includes("Command failed:")) {
1221
- const cmdOutput = errorMessage.split("Command failed:")[1];
1222
- if (cmdOutput) {
1223
- console.error("Git command output:", cmdOutput.trim());
1224
- }
1225
- }
1226
- } else {
1227
- console.error("Unknown git error:", error);
1228
- }
1229
- throw new GitError(`Git operation failed: ${errorMessage}`, "GIT_ERROR" /* GIT_ERROR */);
1230
- }
1231
- }
1232
-
1233
1458
  // src/utils/packageMatching.ts
1234
1459
  import micromatch from "micromatch";
1235
1460
  function matchesPackageTarget(packageName, target) {
@@ -1264,20 +1489,20 @@ function shouldProcessPackage(packageName, skip = []) {
1264
1489
  }
1265
1490
 
1266
1491
  // src/package/packageManagement.ts
1267
- import fs4 from "fs";
1268
- import path3 from "path";
1492
+ import fs7 from "fs";
1493
+ import path6 from "path";
1269
1494
  function updatePackageVersion(packagePath, version, dryRun = false) {
1270
1495
  if (isCargoToml(packagePath)) {
1271
1496
  updateCargoVersion(packagePath, version, dryRun);
1272
1497
  return;
1273
1498
  }
1274
1499
  try {
1275
- const packageContent = fs4.readFileSync(packagePath, "utf8");
1500
+ const packageContent = fs7.readFileSync(packagePath, "utf8");
1276
1501
  const packageJson = JSON.parse(packageContent);
1277
1502
  const packageName = packageJson.name;
1278
1503
  if (!dryRun) {
1279
1504
  packageJson.version = version;
1280
- fs4.writeFileSync(packagePath, `${JSON.stringify(packageJson, null, 2)}
1505
+ fs7.writeFileSync(packagePath, `${JSON.stringify(packageJson, null, 2)}
1281
1506
  `);
1282
1507
  }
1283
1508
  addPackageUpdate(packageName, version, packagePath);
@@ -1301,7 +1526,6 @@ var PackageProcessor = class {
1301
1526
  tagTemplate;
1302
1527
  commitMessageTemplate;
1303
1528
  dryRun;
1304
- skipHooks;
1305
1529
  getLatestTag;
1306
1530
  config;
1307
1531
  // Config for version calculation
@@ -1312,7 +1536,6 @@ var PackageProcessor = class {
1312
1536
  this.tagTemplate = options.tagTemplate;
1313
1537
  this.commitMessageTemplate = options.commitMessageTemplate || "";
1314
1538
  this.dryRun = options.dryRun || false;
1315
- this.skipHooks = options.skipHooks || false;
1316
1539
  this.getLatestTag = options.getLatestTag;
1317
1540
  this.config = options.config;
1318
1541
  this.fullConfig = options.fullConfig;
@@ -1415,6 +1638,19 @@ var PackageProcessor = class {
1415
1638
  revisionRange = "HEAD";
1416
1639
  }
1417
1640
  changelogEntries = extractChangelogEntriesFromCommits(pkgPath, revisionRange);
1641
+ const allPackageDirs = packages.map((p) => p.dir);
1642
+ const sharedPackageNames = ["config", "core", "@releasekit/config", "@releasekit/core"];
1643
+ const sharedPackageDirs = packages.filter((p) => sharedPackageNames.includes(p.packageJson.name)).map((p) => p.dir);
1644
+ const repoLevelEntries = extractRepoLevelChangelogEntries(
1645
+ pkgPath,
1646
+ revisionRange,
1647
+ allPackageDirs,
1648
+ sharedPackageDirs
1649
+ );
1650
+ if (repoLevelEntries.length > 0) {
1651
+ log(`Adding ${repoLevelEntries.length} repo-level commit(s) to ${name} changelog`, "debug");
1652
+ changelogEntries = [...repoLevelEntries, ...changelogEntries];
1653
+ }
1418
1654
  if (changelogEntries.length === 0) {
1419
1655
  changelogEntries = [
1420
1656
  {
@@ -1434,9 +1670,9 @@ var PackageProcessor = class {
1434
1670
  }
1435
1671
  let repoUrl;
1436
1672
  try {
1437
- const packageJsonPath2 = path4.join(pkgPath, "package.json");
1438
- if (fs5.existsSync(packageJsonPath2)) {
1439
- const packageJson = JSON.parse(fs5.readFileSync(packageJsonPath2, "utf8"));
1673
+ const packageJsonPath2 = path7.join(pkgPath, "package.json");
1674
+ if (fs8.existsSync(packageJsonPath2)) {
1675
+ const packageJson = JSON.parse(fs8.readFileSync(packageJsonPath2, "utf8"));
1440
1676
  if (packageJson.repository) {
1441
1677
  if (typeof packageJson.repository === "string") {
1442
1678
  repoUrl = packageJson.repository;
@@ -1462,8 +1698,8 @@ var PackageProcessor = class {
1462
1698
  repoUrl: repoUrl || null,
1463
1699
  entries: changelogEntries
1464
1700
  });
1465
- const packageJsonPath = path4.join(pkgPath, "package.json");
1466
- if (fs5.existsSync(packageJsonPath)) {
1701
+ const packageJsonPath = path7.join(pkgPath, "package.json");
1702
+ if (fs8.existsSync(packageJsonPath)) {
1467
1703
  updatePackageVersion(packageJsonPath, nextVersion, this.dryRun);
1468
1704
  }
1469
1705
  const cargoEnabled = this.fullConfig.cargo?.enabled !== false;
@@ -1473,9 +1709,9 @@ var PackageProcessor = class {
1473
1709
  log(`Cargo paths config for ${name}: ${JSON.stringify(cargoPaths)}`, "debug");
1474
1710
  if (cargoPaths && cargoPaths.length > 0) {
1475
1711
  for (const cargoPath of cargoPaths) {
1476
- const resolvedCargoPath = path4.resolve(pkgPath, cargoPath, "Cargo.toml");
1712
+ const resolvedCargoPath = path7.resolve(pkgPath, cargoPath, "Cargo.toml");
1477
1713
  log(`Checking cargo path for ${name}: ${resolvedCargoPath}`, "debug");
1478
- if (fs5.existsSync(resolvedCargoPath)) {
1714
+ if (fs8.existsSync(resolvedCargoPath)) {
1479
1715
  log(`Found Cargo.toml for ${name} at ${resolvedCargoPath}, updating...`, "debug");
1480
1716
  updatePackageVersion(resolvedCargoPath, nextVersion, this.dryRun);
1481
1717
  } else {
@@ -1483,9 +1719,9 @@ var PackageProcessor = class {
1483
1719
  }
1484
1720
  }
1485
1721
  } else {
1486
- const cargoTomlPath = path4.join(pkgPath, "Cargo.toml");
1722
+ const cargoTomlPath = path7.join(pkgPath, "Cargo.toml");
1487
1723
  log(`Checking default cargo path for ${name}: ${cargoTomlPath}`, "debug");
1488
- if (fs5.existsSync(cargoTomlPath)) {
1724
+ if (fs8.existsSync(cargoTomlPath)) {
1489
1725
  log(`Found Cargo.toml for ${name} at ${cargoTomlPath}, updating...`, "debug");
1490
1726
  updatePackageVersion(cargoTomlPath, nextVersion, this.dryRun);
1491
1727
  } else {
@@ -1502,19 +1738,12 @@ var PackageProcessor = class {
1502
1738
  this.tagTemplate,
1503
1739
  this.fullConfig.packageSpecificTags
1504
1740
  );
1505
- const tagMessage = `chore(release): ${name} ${nextVersion}`;
1506
1741
  addTag(packageTag);
1507
1742
  tags.push(packageTag);
1508
- if (!this.dryRun) {
1509
- try {
1510
- await createGitTag({ tag: packageTag, message: tagMessage });
1511
- log(`Created tag: ${packageTag}`, "success");
1512
- } catch (tagError) {
1513
- log(`Failed to create tag ${packageTag} for ${name}: ${tagError.message}`, "error");
1514
- log(tagError.stack || "No stack trace available", "error");
1515
- }
1516
- } else {
1743
+ if (this.dryRun) {
1517
1744
  log(`[DRY RUN] Would create tag: ${packageTag}`, "info");
1745
+ } else {
1746
+ log(`Version ${nextVersion} prepared (tag: ${packageTag})`, "success");
1518
1747
  }
1519
1748
  updatedPackagesInfo.push({ name, version: nextVersion, path: pkgPath });
1520
1749
  }
@@ -1522,34 +1751,15 @@ var PackageProcessor = class {
1522
1751
  log("No packages required a version update.", "info");
1523
1752
  return { updatedPackages: [], tags };
1524
1753
  }
1525
- const filesToCommit = [];
1526
- for (const info of updatedPackagesInfo) {
1527
- const packageJsonPath = path4.join(info.path, "package.json");
1528
- if (fs5.existsSync(packageJsonPath)) {
1529
- filesToCommit.push(packageJsonPath);
1530
- }
1531
- const cargoEnabled = this.fullConfig.cargo?.enabled !== false;
1532
- if (cargoEnabled) {
1533
- const cargoPaths = this.fullConfig.cargo?.paths;
1534
- if (cargoPaths && cargoPaths.length > 0) {
1535
- for (const cargoPath of cargoPaths) {
1536
- const resolvedCargoPath = path4.resolve(info.path, cargoPath, "Cargo.toml");
1537
- if (fs5.existsSync(resolvedCargoPath)) {
1538
- filesToCommit.push(resolvedCargoPath);
1539
- }
1540
- }
1541
- } else {
1542
- const cargoTomlPath = path4.join(info.path, "Cargo.toml");
1543
- if (fs5.existsSync(cargoTomlPath)) {
1544
- filesToCommit.push(cargoTomlPath);
1545
- }
1546
- }
1547
- }
1548
- }
1549
1754
  const packageNames = updatedPackagesInfo.map((p) => p.name).join(", ");
1550
1755
  const representativeVersion = updatedPackagesInfo[0]?.version || "multiple";
1551
1756
  let commitMessage = this.commitMessageTemplate || "chore(release): publish packages";
1552
- const placeholderRegex = /\$\{[^}]+\}/;
1757
+ const MAX_COMMIT_MSG_LENGTH = 1e4;
1758
+ if (commitMessage.length > MAX_COMMIT_MSG_LENGTH) {
1759
+ log("Commit message template too long, truncating", "warning");
1760
+ commitMessage = commitMessage.slice(0, MAX_COMMIT_MSG_LENGTH);
1761
+ }
1762
+ const placeholderRegex = /\$\{[^{}$]{1,1000}\}/;
1553
1763
  if (updatedPackagesInfo.length === 1 && placeholderRegex.test(commitMessage)) {
1554
1764
  const packageName = updatedPackagesInfo[0].name;
1555
1765
  commitMessage = formatCommitMessage(commitMessage, representativeVersion, packageName);
@@ -1557,21 +1767,7 @@ var PackageProcessor = class {
1557
1767
  commitMessage = `chore(release): ${packageNames} ${representativeVersion}`;
1558
1768
  }
1559
1769
  setCommitMessage(commitMessage);
1560
- if (!this.dryRun) {
1561
- try {
1562
- await gitAdd(filesToCommit);
1563
- await gitCommit({ message: commitMessage, skipHooks: this.skipHooks });
1564
- log(`Created commit for targeted release: ${packageNames}`, "success");
1565
- } catch (commitError) {
1566
- log("Failed to create commit for targeted release.", "error");
1567
- console.error(commitError);
1568
- exit(1);
1569
- }
1570
- } else {
1571
- log("[DRY RUN] Would add files:", "info");
1572
- for (const file of filesToCommit) {
1573
- log(` - ${file}`, "info");
1574
- }
1770
+ if (this.dryRun) {
1575
1771
  log(`[DRY RUN] Would commit with message: "${commitMessage}"`, "info");
1576
1772
  }
1577
1773
  return {
@@ -1583,8 +1779,8 @@ var PackageProcessor = class {
1583
1779
  };
1584
1780
 
1585
1781
  // src/core/versionStrategies.ts
1586
- import fs6 from "fs";
1587
- import * as path5 from "path";
1782
+ import fs9 from "fs";
1783
+ import * as path8 from "path";
1588
1784
  function shouldProcessPackage2(pkg, config) {
1589
1785
  const pkgName = pkg.packageJson.name;
1590
1786
  return shouldProcessPackage(pkgName, config.skip);
@@ -1598,15 +1794,15 @@ function updateCargoFiles(packageDir, version, cargoConfig, dryRun = false) {
1598
1794
  const cargoPaths = cargoConfig?.paths;
1599
1795
  if (cargoPaths && cargoPaths.length > 0) {
1600
1796
  for (const cargoPath of cargoPaths) {
1601
- const resolvedCargoPath = path5.resolve(packageDir, cargoPath, "Cargo.toml");
1602
- if (fs6.existsSync(resolvedCargoPath)) {
1797
+ const resolvedCargoPath = path8.resolve(packageDir, cargoPath, "Cargo.toml");
1798
+ if (fs9.existsSync(resolvedCargoPath)) {
1603
1799
  updatePackageVersion(resolvedCargoPath, version, dryRun);
1604
1800
  updatedFiles.push(resolvedCargoPath);
1605
1801
  }
1606
1802
  }
1607
1803
  } else {
1608
- const cargoTomlPath = path5.join(packageDir, "Cargo.toml");
1609
- if (fs6.existsSync(cargoTomlPath)) {
1804
+ const cargoTomlPath = path8.join(packageDir, "Cargo.toml");
1805
+ if (fs9.existsSync(cargoTomlPath)) {
1610
1806
  updatePackageVersion(cargoTomlPath, version, dryRun);
1611
1807
  updatedFiles.push(cargoTomlPath);
1612
1808
  }
@@ -1624,7 +1820,6 @@ function createSyncStrategy(config) {
1624
1820
  commitMessage = `chore(release): v\${version}`,
1625
1821
  prereleaseIdentifier,
1626
1822
  dryRun,
1627
- skipHooks,
1628
1823
  mainPackage
1629
1824
  } = config;
1630
1825
  const formattedPrefix = formatVersionPrefix(versionPrefix || "v");
@@ -1677,8 +1872,8 @@ function createSyncStrategy(config) {
1677
1872
  const processedPaths = /* @__PURE__ */ new Set();
1678
1873
  try {
1679
1874
  if (packages.root) {
1680
- const rootPkgPath = path5.join(packages.root, "package.json");
1681
- if (fs6.existsSync(rootPkgPath)) {
1875
+ const rootPkgPath = path8.join(packages.root, "package.json");
1876
+ if (fs9.existsSync(rootPkgPath)) {
1682
1877
  updatePackageVersion(rootPkgPath, nextVersion, dryRun);
1683
1878
  files.push(rootPkgPath);
1684
1879
  updatedPackages.push("root");
@@ -1697,7 +1892,7 @@ function createSyncStrategy(config) {
1697
1892
  if (!shouldProcessPackage2(pkg, config)) {
1698
1893
  continue;
1699
1894
  }
1700
- const packageJsonPath = path5.join(pkg.dir, "package.json");
1895
+ const packageJsonPath = path8.join(pkg.dir, "package.json");
1701
1896
  if (processedPaths.has(packageJsonPath)) {
1702
1897
  continue;
1703
1898
  }
@@ -1774,7 +1969,13 @@ function createSyncStrategy(config) {
1774
1969
  config.packageSpecificTags || false
1775
1970
  );
1776
1971
  const formattedCommitMessage = formatCommitMessage(commitMessage, nextVersion, commitPackageName, void 0);
1777
- await createGitCommitAndTag(files, nextTag, formattedCommitMessage, skipHooks, dryRun);
1972
+ addTag(nextTag);
1973
+ setCommitMessage(formattedCommitMessage);
1974
+ if (!dryRun) {
1975
+ log(`Version ${nextVersion} prepared (tag: ${nextTag})`, "success");
1976
+ } else {
1977
+ log(`Would create tag: ${nextTag}`, "info");
1978
+ }
1778
1979
  } catch (error) {
1779
1980
  if (BaseVersionError.isVersionError(error)) {
1780
1981
  log(`Synced Strategy failed: ${error.message} (${error.code})`, "error");
@@ -1789,14 +1990,7 @@ function createSyncStrategy(config) {
1789
1990
  function createSingleStrategy(config) {
1790
1991
  return async (packages) => {
1791
1992
  try {
1792
- const {
1793
- mainPackage,
1794
- versionPrefix,
1795
- tagTemplate,
1796
- commitMessage = `chore(release): \${version}`,
1797
- dryRun,
1798
- skipHooks
1799
- } = config;
1993
+ const { mainPackage, versionPrefix, tagTemplate, commitMessage = `chore(release): \${version}`, dryRun } = config;
1800
1994
  let packageName;
1801
1995
  if (mainPackage) {
1802
1996
  packageName = mainPackage;
@@ -1880,9 +2074,9 @@ function createSingleStrategy(config) {
1880
2074
  }
1881
2075
  let repoUrl;
1882
2076
  try {
1883
- const packageJsonPath2 = path5.join(pkgPath, "package.json");
1884
- if (fs6.existsSync(packageJsonPath2)) {
1885
- const packageJson = JSON.parse(fs6.readFileSync(packageJsonPath2, "utf8"));
2077
+ const packageJsonPath2 = path8.join(pkgPath, "package.json");
2078
+ if (fs9.existsSync(packageJsonPath2)) {
2079
+ const packageJson = JSON.parse(fs9.readFileSync(packageJsonPath2, "utf8"));
1886
2080
  if (packageJson.repository) {
1887
2081
  if (typeof packageJson.repository === "string") {
1888
2082
  repoUrl = packageJson.repository;
@@ -1908,7 +2102,7 @@ function createSingleStrategy(config) {
1908
2102
  repoUrl: repoUrl || null,
1909
2103
  entries: changelogEntries
1910
2104
  });
1911
- const packageJsonPath = path5.join(pkgPath, "package.json");
2105
+ const packageJsonPath = path8.join(pkgPath, "package.json");
1912
2106
  updatePackageVersion(packageJsonPath, nextVersion, dryRun);
1913
2107
  const filesToCommit = [packageJsonPath];
1914
2108
  const cargoFiles = updateCargoFiles(pkgPath, nextVersion, config.cargo, dryRun);
@@ -1916,9 +2110,10 @@ function createSingleStrategy(config) {
1916
2110
  log(`Updated package ${packageName} to version ${nextVersion}`, "success");
1917
2111
  const tagName = formatTag(nextVersion, formattedPrefix, packageName, tagTemplate, config.packageSpecificTags);
1918
2112
  const commitMsg = formatCommitMessage(commitMessage, nextVersion, packageName);
2113
+ addTag(tagName);
2114
+ setCommitMessage(commitMsg);
1919
2115
  if (!dryRun) {
1920
- await createGitCommitAndTag(filesToCommit, tagName, commitMsg, skipHooks, dryRun);
1921
- log(`Created tag: ${tagName}`, "success");
2116
+ log(`Version ${nextVersion} prepared (tag: ${tagName})`, "success");
1922
2117
  } else {
1923
2118
  log(`Would create tag: ${tagName}`, "info");
1924
2119
  }
@@ -1943,7 +2138,6 @@ function createAsyncStrategy(config) {
1943
2138
  tagTemplate: config.tagTemplate,
1944
2139
  commitMessageTemplate: config.commitMessage || "",
1945
2140
  dryRun: config.dryRun || false,
1946
- skipHooks: config.skipHooks || false,
1947
2141
  getLatestTag: dependencies.getLatestTag,
1948
2142
  fullConfig: config,
1949
2143
  // Extract common version configuration properties
@@ -2006,11 +2200,15 @@ function createStrategyMap(config) {
2006
2200
  }
2007
2201
 
2008
2202
  // src/core/versionEngine.ts
2009
- import { cwd as cwd3 } from "process";
2203
+ import { cwd as cwd2 } from "process";
2010
2204
  import { getPackagesSync } from "@manypkg/get-packages";
2011
2205
 
2206
+ // src/errors/gitError.ts
2207
+ var GitError = class extends BaseVersionError {
2208
+ };
2209
+
2012
2210
  // src/utils/packageFiltering.ts
2013
- import path6 from "path";
2211
+ import path9 from "path";
2014
2212
  import micromatch2 from "micromatch";
2015
2213
  function filterPackagesByConfig(packages, configTargets, workspaceRoot) {
2016
2214
  if (configTargets.length === 0) {
@@ -2036,7 +2234,7 @@ function filterByDirectoryPattern(packages, pattern, workspaceRoot) {
2036
2234
  }
2037
2235
  const normalizedPattern = pattern.replace(/\\/g, "/");
2038
2236
  return packages.filter((pkg) => {
2039
- const relativePath = path6.relative(workspaceRoot, pkg.dir);
2237
+ const relativePath = path9.relative(workspaceRoot, pkg.dir);
2040
2238
  const normalizedRelativePath = relativePath.replace(/\\/g, "/");
2041
2239
  if (normalizedPattern === normalizedRelativePath) {
2042
2240
  return true;
@@ -2114,13 +2312,13 @@ var VersionEngine = class {
2114
2312
  if (this.workspaceCache) {
2115
2313
  return this.workspaceCache;
2116
2314
  }
2117
- const pkgsResult = getPackagesSync(cwd3());
2315
+ const pkgsResult = getPackagesSync(cwd2());
2118
2316
  if (!pkgsResult || !pkgsResult.packages) {
2119
2317
  throw createVersionError("PACKAGES_NOT_FOUND" /* PACKAGES_NOT_FOUND */);
2120
2318
  }
2121
2319
  if (!pkgsResult.root) {
2122
2320
  log("Root path is undefined in packages result, setting to current working directory", "warning");
2123
- pkgsResult.root = cwd3();
2321
+ pkgsResult.root = cwd2();
2124
2322
  }
2125
2323
  if (this.config.packages && this.config.packages.length > 0) {
2126
2324
  const originalCount = pkgsResult.packages.length;
@@ -2184,7 +2382,7 @@ var VersionEngine = class {
2184
2382
  };
2185
2383
 
2186
2384
  export {
2187
- loadConfig,
2385
+ loadConfig2 as loadConfig,
2188
2386
  VersionErrorCode,
2189
2387
  createVersionError,
2190
2388
  enableJsonOutput,