package-versioner 0.5.1 → 0.5.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -87,7 +87,7 @@ Customize behavior by creating a `version.config.json` file in your project root
87
87
  "versionPrefix": "v",
88
88
  "tagTemplate": "${prefix}${version}",
89
89
  "packageTagTemplate": "${packageName}@${prefix}${version}",
90
- "commitMessage": "chore(release): {{currentTag}} [skip ci]",
90
+ "commitMessage": "chore(release): ${version}",
91
91
  "monorepo": {
92
92
  "synced": true,
93
93
  "skip": [
@@ -99,7 +99,10 @@ Customize behavior by creating a `version.config.json` file in your project root
99
99
  }
100
100
  ```
101
101
 
102
- **Note:** Options like `synced`, `packages`, and `updateInternalDependencies` enable monorepo-specific behaviours. The `tagTemplate` and `packageTagTemplate` allow you to customize how Git tags are formatted for releases.
102
+ **Notes:**
103
+ - Options like `synced`, `packages`, and `updateInternalDependencies` enable monorepo-specific behaviours.
104
+ - The `tagTemplate` and `packageTagTemplate` allow you to customize how Git tags are formatted for releases.
105
+ - The `commitMessage` template can include CI skip tokens like `[skip ci]` if you want to prevent CI runs after version commits (e.g., `"commitMessage": "chore(release): ${version} [skip ci]"`). See [CI/CD Integration](./docs/CI_CD_INTEGRATION.md) for more details.
103
106
 
104
107
  ## How Versioning Works
105
108
 
package/dist/index.cjs CHANGED
@@ -334,7 +334,7 @@ function formatTag(version, versionPrefix, packageName, tagTemplate = "${prefix}
334
334
  const template = packageName ? packageTagTemplate : tagTemplate;
335
335
  return createTemplateString(template, variables);
336
336
  }
337
- function formatTagPrefix(versionPrefix, scope) {
337
+ function formatVersionPrefix(versionPrefix, scope) {
338
338
  if (!versionPrefix) return "";
339
339
  const cleanPrefix = versionPrefix.replace(/\/$/, "");
340
340
  if (scope) {
@@ -395,12 +395,12 @@ async function lastMergeBranchName(branches, baseBranch) {
395
395
  return null;
396
396
  }
397
397
  }
398
- async function getLatestTagForPackage(packageName, tagPrefix) {
398
+ async function getLatestTagForPackage(packageName, versionPrefix) {
399
399
  try {
400
400
  const allTags = await (0, import_git_semver_tags.getSemverTags)({
401
- tagPrefix
401
+ tagPrefix: versionPrefix
402
402
  });
403
- const packageTagPattern = tagPrefix ? new RegExp(`^${escapeRegExp(tagPrefix)}${escapeRegExp(packageName)}@`) : new RegExp(`^${escapeRegExp(packageName)}@`);
403
+ const packageTagPattern = versionPrefix ? new RegExp(`^${escapeRegExp(versionPrefix)}${escapeRegExp(packageName)}@`) : new RegExp(`^${escapeRegExp(packageName)}@`);
404
404
  const packageTags = allTags.filter((tag) => packageTagPattern.test(tag));
405
405
  return packageTags[0] || "";
406
406
  } catch (error) {
@@ -446,11 +446,11 @@ var import_node_process3 = require("process");
446
446
  var import_conventional_recommended_bump = require("conventional-recommended-bump");
447
447
  var import_semver = __toESM(require("semver"), 1);
448
448
  var STANDARD_BUMP_TYPES = ["major", "minor", "patch"];
449
- async function calculateVersion(config, options, forcedType, configPrereleaseIdentifier) {
449
+ async function calculateVersion(config, options) {
450
450
  const { latestTag, type, path: pkgPath, name, branchPattern } = options;
451
451
  const { preset } = config;
452
- const tagPrefix = options.versionPrefix || config.versionPrefix || "v";
453
- const prereleaseIdentifier = options.prereleaseIdentifier || configPrereleaseIdentifier;
452
+ const originalPrefix = options.versionPrefix || "";
453
+ const prereleaseIdentifier = options.prereleaseIdentifier || config.prereleaseIdentifier;
454
454
  const initialVersion = prereleaseIdentifier ? `0.0.1-${prereleaseIdentifier}` : "0.0.1";
455
455
  const hasNoTags = !latestTag || latestTag === "";
456
456
  function determineTagSearchPattern(packageName, prefix) {
@@ -459,9 +459,9 @@ async function calculateVersion(config, options, forcedType, configPrereleaseIde
459
459
  }
460
460
  return prefix;
461
461
  }
462
- const tagSearchPattern = determineTagSearchPattern(name, tagPrefix);
462
+ const tagSearchPattern = determineTagSearchPattern(name, originalPrefix);
463
463
  const escapedTagPattern = escapeRegExp(tagSearchPattern);
464
- const specifiedType = forcedType || type;
464
+ const specifiedType = type;
465
465
  if (specifiedType) {
466
466
  if (hasNoTags) {
467
467
  return getPackageVersionFallback(
@@ -681,7 +681,7 @@ var PackageProcessor = class {
681
681
  for (const pkg of pkgsToConsider) {
682
682
  const name = pkg.packageJson.name;
683
683
  const pkgPath = pkg.dir;
684
- const formattedPrefix = formatTagPrefix(this.versionPrefix);
684
+ const formattedPrefix = formatVersionPrefix(this.versionPrefix);
685
685
  let latestTagResult = "";
686
686
  try {
687
687
  latestTagResult = await getLatestTagForPackage(name, this.versionPrefix);
@@ -713,7 +713,7 @@ var PackageProcessor = class {
713
713
  branchPattern: this.config.branchPattern,
714
714
  baseBranch: this.config.baseBranch,
715
715
  prereleaseIdentifier: this.config.prereleaseIdentifier,
716
- type: this.config.forceType
716
+ type: this.config.type
717
717
  });
718
718
  if (!nextVersion) {
719
719
  continue;
@@ -758,7 +758,6 @@ var PackageProcessor = class {
758
758
  } else {
759
759
  commitMessage = `chore(release): ${packageNames} ${representativeVersion}`;
760
760
  }
761
- commitMessage += " [skip-ci]";
762
761
  setCommitMessage(commitMessage);
763
762
  if (!this.dryRun) {
764
763
  try {
@@ -810,14 +809,15 @@ function createSyncedStrategy(config) {
810
809
  dryRun,
811
810
  skipHooks
812
811
  } = config;
813
- const formattedPrefix = formatTagPrefix(versionPrefix || "v");
812
+ const formattedPrefix = formatVersionPrefix(versionPrefix || "v");
814
813
  const latestTag = await getLatestTag();
815
814
  const nextVersion = await calculateVersion(config, {
816
815
  latestTag,
817
816
  versionPrefix: formattedPrefix,
818
817
  branchPattern,
819
818
  baseBranch,
820
- prereleaseIdentifier
819
+ prereleaseIdentifier,
820
+ type: config.type
821
821
  });
822
822
  if (!nextVersion) {
823
823
  log("No version change needed", "info");
@@ -888,7 +888,7 @@ function createSingleStrategy(config) {
888
888
  throw createVersionError("PACKAGE_NOT_FOUND" /* PACKAGE_NOT_FOUND */, packageName);
889
889
  }
890
890
  const pkgPath = pkg.dir;
891
- const formattedPrefix = formatTagPrefix(versionPrefix || "v");
891
+ const formattedPrefix = formatVersionPrefix(versionPrefix || "v");
892
892
  let latestTagResult = await getLatestTagForPackage(packageName, formattedPrefix);
893
893
  if (!latestTagResult) {
894
894
  const globalTagResult = await getLatestTag();
@@ -901,7 +901,8 @@ function createSingleStrategy(config) {
901
901
  latestTag,
902
902
  versionPrefix: formattedPrefix,
903
903
  path: pkgPath,
904
- name: packageName
904
+ name: packageName,
905
+ type: config.type
905
906
  });
906
907
  } catch (error) {
907
908
  const errorMessage = error instanceof Error ? error.message : String(error);
@@ -958,11 +959,12 @@ function createAsyncStrategy(config) {
958
959
  skipHooks: config.skipHooks || false,
959
960
  getLatestTag: dependencies.getLatestTag,
960
961
  fullConfig: config,
962
+ // Extract common version configuration properties
961
963
  config: {
962
964
  branchPattern: config.branchPattern || [],
963
965
  baseBranch: config.baseBranch || "main",
964
966
  prereleaseIdentifier: config.prereleaseIdentifier,
965
- forceType: config.forceType
967
+ type: config.type
966
968
  }
967
969
  };
968
970
  const packageProcessor = new PackageProcessor(processorOptions);
@@ -1093,7 +1095,7 @@ async function run() {
1093
1095
  ).version(process.env.npm_package_version || "0.0.0").option(
1094
1096
  "-c, --config <path>",
1095
1097
  "Path to config file (defaults to version.config.json in current directory)"
1096
- ).option("-d, --dry-run", "Dry run (no changes made)", false).option("-b, --bump <type>", "Force specific bump type (patch|minor|major)").option("-p, --prerelease [identifier]", "Create prerelease version").option("-s, --synced", "Force synchronized versioning across all packages").option("-j, --json", "Output results as JSON", false).option("-t, --target <packages>", "Comma-delimited list of package names to target").parse(process.argv);
1098
+ ).option("-d, --dry-run", "Dry run (no changes made)", false).option("-b, --bump <type>", "Specify bump type (patch|minor|major)").option("-p, --prerelease [identifier]", "Create prerelease version").option("-s, --synced", "Use synchronized versioning across all packages").option("-j, --json", "Output results as JSON", false).option("-t, --target <packages>", "Comma-delimited list of package names to target").parse(process.argv);
1097
1099
  const options = program.opts();
1098
1100
  if (options.json) {
1099
1101
  enableJsonOutput(options.dryRun);
@@ -1103,7 +1105,7 @@ async function run() {
1103
1105
  log(`Loaded configuration from ${options.config || "version.config.json"}`, "info");
1104
1106
  if (options.dryRun) config.dryRun = true;
1105
1107
  if (options.synced) config.synced = true;
1106
- if (options.bump) config.forceType = options.bump;
1108
+ if (options.bump) config.type = options.bump;
1107
1109
  if (options.prerelease)
1108
1110
  config.prereleaseIdentifier = options.prerelease === true ? "rc" : options.prerelease;
1109
1111
  const cliTargets = options.target ? options.target.split(",").map((t) => t.trim()) : [];
package/dist/index.js CHANGED
@@ -311,7 +311,7 @@ function formatTag(version, versionPrefix, packageName, tagTemplate = "${prefix}
311
311
  const template = packageName ? packageTagTemplate : tagTemplate;
312
312
  return createTemplateString(template, variables);
313
313
  }
314
- function formatTagPrefix(versionPrefix, scope) {
314
+ function formatVersionPrefix(versionPrefix, scope) {
315
315
  if (!versionPrefix) return "";
316
316
  const cleanPrefix = versionPrefix.replace(/\/$/, "");
317
317
  if (scope) {
@@ -372,12 +372,12 @@ async function lastMergeBranchName(branches, baseBranch) {
372
372
  return null;
373
373
  }
374
374
  }
375
- async function getLatestTagForPackage(packageName, tagPrefix) {
375
+ async function getLatestTagForPackage(packageName, versionPrefix) {
376
376
  try {
377
377
  const allTags = await getSemverTags({
378
- tagPrefix
378
+ tagPrefix: versionPrefix
379
379
  });
380
- const packageTagPattern = tagPrefix ? new RegExp(`^${escapeRegExp(tagPrefix)}${escapeRegExp(packageName)}@`) : new RegExp(`^${escapeRegExp(packageName)}@`);
380
+ const packageTagPattern = versionPrefix ? new RegExp(`^${escapeRegExp(versionPrefix)}${escapeRegExp(packageName)}@`) : new RegExp(`^${escapeRegExp(packageName)}@`);
381
381
  const packageTags = allTags.filter((tag) => packageTagPattern.test(tag));
382
382
  return packageTags[0] || "";
383
383
  } catch (error) {
@@ -422,11 +422,11 @@ import { cwd as cwd3 } from "node:process";
422
422
  import { Bumper } from "conventional-recommended-bump";
423
423
  import semver from "semver";
424
424
  var STANDARD_BUMP_TYPES = ["major", "minor", "patch"];
425
- async function calculateVersion(config, options, forcedType, configPrereleaseIdentifier) {
425
+ async function calculateVersion(config, options) {
426
426
  const { latestTag, type, path: pkgPath, name, branchPattern } = options;
427
427
  const { preset } = config;
428
- const tagPrefix = options.versionPrefix || config.versionPrefix || "v";
429
- const prereleaseIdentifier = options.prereleaseIdentifier || configPrereleaseIdentifier;
428
+ const originalPrefix = options.versionPrefix || "";
429
+ const prereleaseIdentifier = options.prereleaseIdentifier || config.prereleaseIdentifier;
430
430
  const initialVersion = prereleaseIdentifier ? `0.0.1-${prereleaseIdentifier}` : "0.0.1";
431
431
  const hasNoTags = !latestTag || latestTag === "";
432
432
  function determineTagSearchPattern(packageName, prefix) {
@@ -435,9 +435,9 @@ async function calculateVersion(config, options, forcedType, configPrereleaseIde
435
435
  }
436
436
  return prefix;
437
437
  }
438
- const tagSearchPattern = determineTagSearchPattern(name, tagPrefix);
438
+ const tagSearchPattern = determineTagSearchPattern(name, originalPrefix);
439
439
  const escapedTagPattern = escapeRegExp(tagSearchPattern);
440
- const specifiedType = forcedType || type;
440
+ const specifiedType = type;
441
441
  if (specifiedType) {
442
442
  if (hasNoTags) {
443
443
  return getPackageVersionFallback(
@@ -657,7 +657,7 @@ var PackageProcessor = class {
657
657
  for (const pkg of pkgsToConsider) {
658
658
  const name = pkg.packageJson.name;
659
659
  const pkgPath = pkg.dir;
660
- const formattedPrefix = formatTagPrefix(this.versionPrefix);
660
+ const formattedPrefix = formatVersionPrefix(this.versionPrefix);
661
661
  let latestTagResult = "";
662
662
  try {
663
663
  latestTagResult = await getLatestTagForPackage(name, this.versionPrefix);
@@ -689,7 +689,7 @@ var PackageProcessor = class {
689
689
  branchPattern: this.config.branchPattern,
690
690
  baseBranch: this.config.baseBranch,
691
691
  prereleaseIdentifier: this.config.prereleaseIdentifier,
692
- type: this.config.forceType
692
+ type: this.config.type
693
693
  });
694
694
  if (!nextVersion) {
695
695
  continue;
@@ -734,7 +734,6 @@ var PackageProcessor = class {
734
734
  } else {
735
735
  commitMessage = `chore(release): ${packageNames} ${representativeVersion}`;
736
736
  }
737
- commitMessage += " [skip-ci]";
738
737
  setCommitMessage(commitMessage);
739
738
  if (!this.dryRun) {
740
739
  try {
@@ -786,14 +785,15 @@ function createSyncedStrategy(config) {
786
785
  dryRun,
787
786
  skipHooks
788
787
  } = config;
789
- const formattedPrefix = formatTagPrefix(versionPrefix || "v");
788
+ const formattedPrefix = formatVersionPrefix(versionPrefix || "v");
790
789
  const latestTag = await getLatestTag();
791
790
  const nextVersion = await calculateVersion(config, {
792
791
  latestTag,
793
792
  versionPrefix: formattedPrefix,
794
793
  branchPattern,
795
794
  baseBranch,
796
- prereleaseIdentifier
795
+ prereleaseIdentifier,
796
+ type: config.type
797
797
  });
798
798
  if (!nextVersion) {
799
799
  log("No version change needed", "info");
@@ -864,7 +864,7 @@ function createSingleStrategy(config) {
864
864
  throw createVersionError("PACKAGE_NOT_FOUND" /* PACKAGE_NOT_FOUND */, packageName);
865
865
  }
866
866
  const pkgPath = pkg.dir;
867
- const formattedPrefix = formatTagPrefix(versionPrefix || "v");
867
+ const formattedPrefix = formatVersionPrefix(versionPrefix || "v");
868
868
  let latestTagResult = await getLatestTagForPackage(packageName, formattedPrefix);
869
869
  if (!latestTagResult) {
870
870
  const globalTagResult = await getLatestTag();
@@ -877,7 +877,8 @@ function createSingleStrategy(config) {
877
877
  latestTag,
878
878
  versionPrefix: formattedPrefix,
879
879
  path: pkgPath,
880
- name: packageName
880
+ name: packageName,
881
+ type: config.type
881
882
  });
882
883
  } catch (error) {
883
884
  const errorMessage = error instanceof Error ? error.message : String(error);
@@ -934,11 +935,12 @@ function createAsyncStrategy(config) {
934
935
  skipHooks: config.skipHooks || false,
935
936
  getLatestTag: dependencies.getLatestTag,
936
937
  fullConfig: config,
938
+ // Extract common version configuration properties
937
939
  config: {
938
940
  branchPattern: config.branchPattern || [],
939
941
  baseBranch: config.baseBranch || "main",
940
942
  prereleaseIdentifier: config.prereleaseIdentifier,
941
- forceType: config.forceType
943
+ type: config.type
942
944
  }
943
945
  };
944
946
  const packageProcessor = new PackageProcessor(processorOptions);
@@ -1069,7 +1071,7 @@ async function run() {
1069
1071
  ).version(process.env.npm_package_version || "0.0.0").option(
1070
1072
  "-c, --config <path>",
1071
1073
  "Path to config file (defaults to version.config.json in current directory)"
1072
- ).option("-d, --dry-run", "Dry run (no changes made)", false).option("-b, --bump <type>", "Force specific bump type (patch|minor|major)").option("-p, --prerelease [identifier]", "Create prerelease version").option("-s, --synced", "Force synchronized versioning across all packages").option("-j, --json", "Output results as JSON", false).option("-t, --target <packages>", "Comma-delimited list of package names to target").parse(process.argv);
1074
+ ).option("-d, --dry-run", "Dry run (no changes made)", false).option("-b, --bump <type>", "Specify bump type (patch|minor|major)").option("-p, --prerelease [identifier]", "Create prerelease version").option("-s, --synced", "Use synchronized versioning across all packages").option("-j, --json", "Output results as JSON", false).option("-t, --target <packages>", "Comma-delimited list of package names to target").parse(process.argv);
1073
1075
  const options = program.opts();
1074
1076
  if (options.json) {
1075
1077
  enableJsonOutput(options.dryRun);
@@ -1079,7 +1081,7 @@ async function run() {
1079
1081
  log(`Loaded configuration from ${options.config || "version.config.json"}`, "info");
1080
1082
  if (options.dryRun) config.dryRun = true;
1081
1083
  if (options.synced) config.synced = true;
1082
- if (options.bump) config.forceType = options.bump;
1084
+ if (options.bump) config.type = options.bump;
1083
1085
  if (options.prerelease)
1084
1086
  config.prereleaseIdentifier = options.prerelease === true ? "rc" : options.prerelease;
1085
1087
  const cliTargets = options.target ? options.target.split(",").map((t) => t.trim()) : [];
@@ -156,6 +156,24 @@ git push origin "v$NEW_VERSION"
156
156
  - `NO_COLOR=1`: Disables colored output in logs (automatically detected in CI environments)
157
157
  - `CI=true`: Most CI environments set this automatically, which helps the tool adjust its output behavior
158
158
 
159
+ ## Skipping CI for Version Commits
160
+
161
+ If you want to prevent additional CI runs when version commits are made, you can include CI skip flags in your commit message template in `version.config.json`:
162
+
163
+ ```json
164
+ {
165
+ "commitMessage": "chore(release): ${version} [skip ci]",
166
+ // other configuration options...
167
+ }
168
+ ```
169
+
170
+ Common CI skip patterns include:
171
+ - `[skip ci]` or `[ci skip]` - Works in GitHub Actions, GitLab CI, CircleCI
172
+ - `[skip-ci]` - Alternative format supported by some CI systems
173
+ - `[no ci]` - Another variant
174
+
175
+ Each CI system might have slightly different syntax, so check your CI provider's documentation for the exact skip token to use.
176
+
159
177
  ## Tips for Reliable CI/CD Integration
160
178
 
161
179
  1. **Always use `--json`** in CI/CD pipelines for consistent output parsing
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "package-versioner",
3
3
  "description": "A lightweight yet powerful CLI tool for automated semantic versioning based on Git history and conventional commits.",
4
- "version": "0.5.1",
4
+ "version": "0.5.3",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
7
7
  "module": "./dist/index.mjs",