@releasekit/version 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENCE.md +7 -0
- package/README.md +307 -0
- package/dist/baseError-IKMJCSYK.js +6 -0
- package/dist/baseError-ZCZHF6A2.js +7 -0
- package/dist/chunk-6CLV2DJG.js +2166 -0
- package/dist/chunk-7GDPUNML.js +128 -0
- package/dist/chunk-GLFC564Q.js +2174 -0
- package/dist/chunk-GQLJ7JQY.js +18 -0
- package/dist/chunk-KZDV4EBO.js +2170 -0
- package/dist/chunk-WEP3ACTS.js +2125 -0
- package/dist/cli.cjs +2313 -0
- package/dist/cli.d.cts +4 -0
- package/dist/cli.d.ts +4 -0
- package/dist/cli.js +105 -0
- package/dist/index.cjs +2228 -0
- package/dist/index.d.cts +209 -0
- package/dist/index.d.ts +209 -0
- package/dist/index.js +30 -0
- package/docs/CI_CD_INTEGRATION.md +197 -0
- package/docs/versioning.md +501 -0
- package/package.json +80 -0
- package/version.schema.json +148 -0
|
@@ -0,0 +1,501 @@
|
|
|
1
|
+
# Versioning Strategies and Concepts
|
|
2
|
+
|
|
3
|
+
`package-versioner` offers flexible ways to determine the next version for your project based on its history and your configuration.
|
|
4
|
+
|
|
5
|
+
## How the Next Version is Calculated
|
|
6
|
+
|
|
7
|
+
There are two primary methods the tool uses to decide the version bump (e.g., patch, minor, major), configured via the `versionStrategy` option in `version.config.json`:
|
|
8
|
+
|
|
9
|
+
### 1. Conventional Commits (`versionStrategy: "conventional"`)
|
|
10
|
+
|
|
11
|
+
This is the default strategy. `package-versioner` analyzes Git commit messages since the last Git tag that follows semver patterns. It uses the [conventional-commits](https://www.conventionalcommits.org/) specification to determine the bump:
|
|
12
|
+
|
|
13
|
+
- **Patch Bump (e.g., 1.2.3 -> 1.2.4):** Triggered by `fix:` commit types.
|
|
14
|
+
- **Minor Bump (e.g., 1.2.3 -> 1.3.0):** Triggered by `feat:` commit types.
|
|
15
|
+
- **Major Bump (e.g., 1.2.3 -> 2.0.0):** Triggered by commits with `BREAKING CHANGE:` in the footer or `feat!:`, `fix!:` etc. in the header.
|
|
16
|
+
|
|
17
|
+
The specific preset used for analysis (e.g., "angular", "conventional") can be set using the `preset` option in `version.config.json`.
|
|
18
|
+
|
|
19
|
+
**Format:** `<type>(<scope>): <subject>`
|
|
20
|
+
|
|
21
|
+
`<scope>` is optional.
|
|
22
|
+
|
|
23
|
+
**Example Commit Types:**
|
|
24
|
+
|
|
25
|
+
- `feat:` (new feature for the user)
|
|
26
|
+
- `fix:` (bug fix for the user)
|
|
27
|
+
- `docs:` (changes to the documentation)
|
|
28
|
+
- `style:` (formatting, missing semi-colons, etc; no production code change)
|
|
29
|
+
- `refactor:` (refactoring production code, e.g. renaming a variable)
|
|
30
|
+
- `test:` (adding missing tests, refactoring tests; no production code change)
|
|
31
|
+
- `chore:` (updating build tasks etc; no production code change)
|
|
32
|
+
|
|
33
|
+
**References:**
|
|
34
|
+
|
|
35
|
+
- [https://www.conventionalcommits.org/](https://www.conventionalcommits.org/)
|
|
36
|
+
- [https://github.com/conventional-changelog/conventional-changelog](https://github.com/conventional-changelog/conventional-changelog)
|
|
37
|
+
|
|
38
|
+
### 2. Branch Pattern (`versionStrategy: "branchPattern"`)
|
|
39
|
+
|
|
40
|
+
This strategy uses the name of the current Git branch (or the most recently merged branch matching a pattern, if applicable) to determine the version bump.
|
|
41
|
+
|
|
42
|
+
You define patterns in the `branchPattern` array in `version.config.json`. Each pattern is a string like `"prefix:bumptype"`.
|
|
43
|
+
|
|
44
|
+
**Example `version.config.json`:**
|
|
45
|
+
|
|
46
|
+
```json
|
|
47
|
+
{
|
|
48
|
+
"versionStrategy": "branchPattern",
|
|
49
|
+
"branchPattern": [
|
|
50
|
+
"feature:minor",
|
|
51
|
+
"hotfix:patch",
|
|
52
|
+
"fix:patch",
|
|
53
|
+
"release:major"
|
|
54
|
+
],
|
|
55
|
+
"baseBranch": "main"
|
|
56
|
+
}
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
**How it works:**
|
|
60
|
+
|
|
61
|
+
1. The tool checks the current branch name.
|
|
62
|
+
2. It might also look for the most recently merged branch into `baseBranch` that matches any pattern in `branchPattern`.
|
|
63
|
+
3. It compares the relevant branch name (current or last merged) against the prefixes in `branchPattern`.
|
|
64
|
+
4. If a match is found (e.g., current branch is `feature/add-login`), it applies the corresponding bump type (`minor` in this case).
|
|
65
|
+
|
|
66
|
+
This allows you to enforce version bumps based on your branching workflow (e.g., all branches starting with `feature/` result in a minor bump).
|
|
67
|
+
|
|
68
|
+
## Package Type Support
|
|
69
|
+
|
|
70
|
+
`package-versioner` supports both JavaScript/TypeScript projects using `package.json` and Rust projects using `Cargo.toml`:
|
|
71
|
+
|
|
72
|
+
### JavaScript/TypeScript Projects
|
|
73
|
+
|
|
74
|
+
For JavaScript/TypeScript projects, the tool looks for and updates the `version` field in `package.json` files according to the versioning strategies described above.
|
|
75
|
+
|
|
76
|
+
### Rust Projects
|
|
77
|
+
|
|
78
|
+
For Rust projects, the tool looks for and updates the `package.version` field in `Cargo.toml` files using the same versioning strategies.
|
|
79
|
+
|
|
80
|
+
### Mixed Projects with Both Manifests
|
|
81
|
+
|
|
82
|
+
When both `package.json` and `Cargo.toml` exist in the same directory, `package-versioner` will:
|
|
83
|
+
|
|
84
|
+
1. Update both manifest files independently with the same calculated version
|
|
85
|
+
2. First check `package.json` for the current version (when no tags exist)
|
|
86
|
+
3. Fall back to checking `Cargo.toml` only if `package.json` doesn't exist or doesn't have a version
|
|
87
|
+
|
|
88
|
+
This allows you to maintain consistent versioning across JavaScript and Rust components in the same package.
|
|
89
|
+
|
|
90
|
+
## Version Source Selection
|
|
91
|
+
|
|
92
|
+
`package-versioner` uses a smart version source selection strategy to determine the base version for calculating the next version:
|
|
93
|
+
|
|
94
|
+
1. First, it checks for Git tags:
|
|
95
|
+
- In normal mode: Uses the latest reachable tag, falling back to unreachable tags if needed
|
|
96
|
+
- In strict mode (`--strict-reachable`): Only uses reachable tags
|
|
97
|
+
|
|
98
|
+
2. Then, it checks manifest files (package.json, Cargo.toml):
|
|
99
|
+
- Reads version from package.json if it exists
|
|
100
|
+
- Falls back to Cargo.toml if package.json doesn't exist or has no version
|
|
101
|
+
|
|
102
|
+
3. Finally, it compares the versions:
|
|
103
|
+
- If both Git tag and manifest versions exist, it uses the newer version
|
|
104
|
+
- If the versions are equal, it prefers the Git tag for better history tracking
|
|
105
|
+
- If only one source has a version, it uses that
|
|
106
|
+
- If no version is found, it uses the default initial version (0.1.0)
|
|
107
|
+
|
|
108
|
+
This strategy ensures that:
|
|
109
|
+
- Version numbers never go backwards
|
|
110
|
+
- Git history is respected when possible
|
|
111
|
+
- Manifest files are considered as valid version sources
|
|
112
|
+
- The tool always has a valid base version to work from
|
|
113
|
+
|
|
114
|
+
For example:
|
|
115
|
+
```
|
|
116
|
+
Scenario 1:
|
|
117
|
+
- Git tag: v1.0.0
|
|
118
|
+
- package.json: 1.1.0
|
|
119
|
+
Result: Uses 1.1.0 as base (package.json is newer)
|
|
120
|
+
|
|
121
|
+
Scenario 2:
|
|
122
|
+
- Git tag: v1.0.0
|
|
123
|
+
- package.json: 1.0.0
|
|
124
|
+
Result: Uses v1.0.0 as base (versions equal, prefer Git)
|
|
125
|
+
|
|
126
|
+
Scenario 3:
|
|
127
|
+
- Git tag: unreachable v2.0.0
|
|
128
|
+
- package.json: 1.0.0
|
|
129
|
+
Result: Uses 2.0.0 as base in normal mode (unreachable tag is newer)
|
|
130
|
+
Uses 1.0.0 as base in strict mode (unreachable tag ignored)
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
### Version Mismatch Detection
|
|
134
|
+
|
|
135
|
+
When Git tags and manifest versions diverge significantly, it can lead to unexpected version bumps. A common scenario is when a release is reverted but its Git tag is not deleted — the tool sees the tag as the latest version and bumps from there.
|
|
136
|
+
|
|
137
|
+
For example:
|
|
138
|
+
```
|
|
139
|
+
- Git tag: v1.0.0 (from a reverted release)
|
|
140
|
+
- package.json: 1.0.0-beta.3
|
|
141
|
+
- Without mismatch detection: Uses v1.0.0 as base, next release bumps to v2.0.0
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
The `mismatchStrategy` option controls how these situations are handled:
|
|
145
|
+
|
|
146
|
+
| Strategy | Behavior |
|
|
147
|
+
|----------|----------|
|
|
148
|
+
| `"error"` (default) | Throws an error and stops execution, forcing the user to resolve the mismatch |
|
|
149
|
+
| `"warn"` | Logs a warning describing the mismatch, then continues with the higher version |
|
|
150
|
+
| `"prefer-package"` | Uses the package.json version as the base when a mismatch is detected |
|
|
151
|
+
| `"prefer-git"` | Uses the git tag version as the base when a mismatch is detected |
|
|
152
|
+
| `"ignore"` | Silently continues with the higher version (pre-v0.9.4 behavior) |
|
|
153
|
+
|
|
154
|
+
Mismatches are detected in the following cases:
|
|
155
|
+
- Git tag is a stable release but package.json is a prerelease of the same major version (e.g., tag `1.0.0` vs package `1.0.0-beta.3`)
|
|
156
|
+
- Git tag is ahead by a major or minor version (e.g., tag `2.0.0` vs package `1.0.0`)
|
|
157
|
+
- Git tag is a prerelease but package.json is a stable release (e.g., tag `1.0.0-beta.1` vs package `1.0.0`)
|
|
158
|
+
|
|
159
|
+
Configure it in `version.config.json`:
|
|
160
|
+
```json
|
|
161
|
+
{
|
|
162
|
+
"mismatchStrategy": "prefer-package"
|
|
163
|
+
}
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
## Package Targeting in Monorepos
|
|
167
|
+
|
|
168
|
+
When working with monorepos, you can control which packages are processed for versioning using the `packages` configuration option. This provides flexible targeting with support for various pattern types.
|
|
169
|
+
|
|
170
|
+
### Targeting Patterns
|
|
171
|
+
|
|
172
|
+
#### Exact Package Names
|
|
173
|
+
Target specific packages by their exact names:
|
|
174
|
+
```json
|
|
175
|
+
{
|
|
176
|
+
"packages": ["@mycompany/core", "@mycompany/utils", "standalone-package"]
|
|
177
|
+
}
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
#### Scope Wildcards
|
|
181
|
+
Target all packages within a specific scope:
|
|
182
|
+
```json
|
|
183
|
+
{
|
|
184
|
+
"packages": ["@mycompany/*"]
|
|
185
|
+
}
|
|
186
|
+
```
|
|
187
|
+
This will match all packages whose names start with `@mycompany/`.
|
|
188
|
+
|
|
189
|
+
#### Global Wildcard
|
|
190
|
+
Target all packages in the workspace:
|
|
191
|
+
```json
|
|
192
|
+
{
|
|
193
|
+
"packages": ["*"]
|
|
194
|
+
}
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
#### Mixed Patterns
|
|
198
|
+
Target different types of packages using a combination of patterns:
|
|
199
|
+
```json
|
|
200
|
+
{
|
|
201
|
+
"packages": ["@mycompany/*", "@utils/logger", "legacy-package"]
|
|
202
|
+
}
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
### Skip Patterns
|
|
206
|
+
|
|
207
|
+
The `skip` configuration option allows you to exclude specific packages from versioning using the same pattern matching capabilities as package targeting.
|
|
208
|
+
|
|
209
|
+
#### Pattern Types
|
|
210
|
+
|
|
211
|
+
1. **Exact Package Names**
|
|
212
|
+
```json
|
|
213
|
+
{
|
|
214
|
+
"skip": ["@internal/docs", "test-utils"]
|
|
215
|
+
}
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
2. **Scope Wildcards**
|
|
219
|
+
```json
|
|
220
|
+
{
|
|
221
|
+
"skip": ["@internal/*"]
|
|
222
|
+
}
|
|
223
|
+
```
|
|
224
|
+
This will skip all packages whose names start with `@internal/`.
|
|
225
|
+
|
|
226
|
+
3. **Path Patterns**
|
|
227
|
+
```json
|
|
228
|
+
{
|
|
229
|
+
"skip": ["packages/**/test-*", "examples/**/*"]
|
|
230
|
+
}
|
|
231
|
+
```
|
|
232
|
+
This will skip packages matching the specified path patterns.
|
|
233
|
+
|
|
234
|
+
4. **Mixed Patterns**
|
|
235
|
+
```json
|
|
236
|
+
{
|
|
237
|
+
"skip": ["@internal/*", "test-*", "packages/examples/**/*"]
|
|
238
|
+
}
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
#### Skip Pattern Priority
|
|
242
|
+
|
|
243
|
+
Skip patterns take precedence over include patterns. If a package matches both a pattern in `packages` and a pattern in `skip`, it will be excluded from versioning.
|
|
244
|
+
|
|
245
|
+
Example:
|
|
246
|
+
```json
|
|
247
|
+
{
|
|
248
|
+
"packages": ["@company/*"],
|
|
249
|
+
"skip": ["@company/internal-*"]
|
|
250
|
+
}
|
|
251
|
+
```
|
|
252
|
+
In this case, all packages under the `@company` scope will be versioned except those starting with `@company/internal-`.
|
|
253
|
+
|
|
254
|
+
### Behaviour
|
|
255
|
+
|
|
256
|
+
- **When `packages` is specified**: Only packages matching those patterns will be processed for versioning
|
|
257
|
+
- **When `packages` is empty or not specified**: All workspace packages will be processed
|
|
258
|
+
- **Error handling**: If no packages match the specified patterns, a warning is displayed
|
|
259
|
+
|
|
260
|
+
### Excluding Packages
|
|
261
|
+
|
|
262
|
+
Use the `skip` option to exclude specific packages from processing:
|
|
263
|
+
```json
|
|
264
|
+
{
|
|
265
|
+
"packages": ["@mycompany/*"],
|
|
266
|
+
"skip": ["@mycompany/deprecated-package"]
|
|
267
|
+
}
|
|
268
|
+
```
|
|
269
|
+
|
|
270
|
+
This configuration will process all packages in the `@mycompany` scope except for `@mycompany/deprecated-package`.
|
|
271
|
+
|
|
272
|
+
**Note**: Your workspace configuration (pnpm-workspace.yaml, package.json workspaces, etc.) determines which packages are available in your workspace, but the `packages` option directly controls which ones get versioned.
|
|
273
|
+
|
|
274
|
+
## Tag Templates and Configuration
|
|
275
|
+
|
|
276
|
+
`package-versioner` provides flexible configuration for how Git tags are formatted, allowing you to customize the tag structure for both single package repositories and monorepos.
|
|
277
|
+
|
|
278
|
+
### Tag Template Configuration
|
|
279
|
+
|
|
280
|
+
You can customize how tags are formatted using the following configuration options in `version.config.json`:
|
|
281
|
+
|
|
282
|
+
```json
|
|
283
|
+
{
|
|
284
|
+
"versionPrefix": "v",
|
|
285
|
+
"tagTemplate": "${prefix}${version}",
|
|
286
|
+
"packageSpecificTags": false
|
|
287
|
+
}
|
|
288
|
+
```
|
|
289
|
+
|
|
290
|
+
- **versionPrefix**: The prefix used for all version numbers in tags (default: `"v"`)
|
|
291
|
+
- **tagTemplate**: The template for Git tags (default: `"${prefix}${version}"`)
|
|
292
|
+
- **packageSpecificTags**: Whether to enable package-specific tagging behaviour (default: `false`)
|
|
293
|
+
|
|
294
|
+
### Available Template Variables
|
|
295
|
+
|
|
296
|
+
The tag template supports the following variables:
|
|
297
|
+
|
|
298
|
+
- `${prefix}`: Replaced with the value of `versionPrefix`
|
|
299
|
+
- `${version}`: Replaced with the calculated version number
|
|
300
|
+
- `${packageName}`: Replaced with the package name (only populated when `packageSpecificTags` is `true`)
|
|
301
|
+
|
|
302
|
+
### How Package-Specific Tagging Works
|
|
303
|
+
|
|
304
|
+
The `packageSpecificTags` option controls whether the `${packageName}` variable is populated in your template:
|
|
305
|
+
|
|
306
|
+
- **When `packageSpecificTags` is `false`**: The `${packageName}` variable is empty, so use templates like `${prefix}${version}`
|
|
307
|
+
- **When `packageSpecificTags` is `true`**: The `${packageName}` variable contains the actual package name
|
|
308
|
+
|
|
309
|
+
### Examples
|
|
310
|
+
|
|
311
|
+
#### Global Versioning (Default)
|
|
312
|
+
```json
|
|
313
|
+
{
|
|
314
|
+
"versionPrefix": "v",
|
|
315
|
+
"tagTemplate": "${prefix}${version}",
|
|
316
|
+
"packageSpecificTags": false
|
|
317
|
+
}
|
|
318
|
+
```
|
|
319
|
+
This produces tags like `v1.2.3` for all packages.
|
|
320
|
+
|
|
321
|
+
#### Package-Specific Versioning
|
|
322
|
+
```json
|
|
323
|
+
{
|
|
324
|
+
"versionPrefix": "v",
|
|
325
|
+
"tagTemplate": "${packageName}@${prefix}${version}",
|
|
326
|
+
"packageSpecificTags": true
|
|
327
|
+
}
|
|
328
|
+
```
|
|
329
|
+
This produces tags like `@scope/package-name@v1.2.3` for each package.
|
|
330
|
+
|
|
331
|
+
#### Custom Tag Format Examples
|
|
332
|
+
```json
|
|
333
|
+
{
|
|
334
|
+
"versionPrefix": "",
|
|
335
|
+
"tagTemplate": "release-${version}",
|
|
336
|
+
"packageSpecificTags": false
|
|
337
|
+
}
|
|
338
|
+
```
|
|
339
|
+
This would produce tags like `release-1.2.3` instead of `v1.2.3`.
|
|
340
|
+
|
|
341
|
+
```json
|
|
342
|
+
{
|
|
343
|
+
"versionPrefix": "v",
|
|
344
|
+
"tagTemplate": "${packageName}-${prefix}${version}",
|
|
345
|
+
"packageSpecificTags": true
|
|
346
|
+
}
|
|
347
|
+
```
|
|
348
|
+
This would produce package tags like `@scope/package-name-v1.2.3` instead of `@scope/package-name@v1.2.3`.
|
|
349
|
+
|
|
350
|
+
### Behaviour in Different Modes
|
|
351
|
+
|
|
352
|
+
- **Synced Mode with Single Package**: When `packageSpecificTags` is `true`, the package name is used even though all packages are versioned together
|
|
353
|
+
- **Synced Mode with Multiple Packages**: Package names are not used regardless of the `packageSpecificTags` setting
|
|
354
|
+
- **Async Mode**: Each package gets its own tag when `packageSpecificTags` is enabled
|
|
355
|
+
|
|
356
|
+
## Troubleshooting Template Configuration
|
|
357
|
+
|
|
358
|
+
`package-versioner` provides helpful warnings when template configurations don't match your project setup. Here are common issues and their solutions:
|
|
359
|
+
|
|
360
|
+
### Template Contains ${packageName} but No Package Name Available
|
|
361
|
+
|
|
362
|
+
If you see this warning, it means your template includes `${packageName}` but the tool cannot determine a package name for the current context.
|
|
363
|
+
|
|
364
|
+
**Example Warning:**
|
|
365
|
+
```
|
|
366
|
+
Warning: Your tagTemplate contains ${packageName} but no package name is available.
|
|
367
|
+
This will result in an empty package name in the tag (e.g., "@v1.0.0" instead of "my-package@v1.0.0").
|
|
368
|
+
|
|
369
|
+
To fix this:
|
|
370
|
+
• If using sync mode: Set "packageSpecificTags": true in your config to enable package names in tags
|
|
371
|
+
• If you want global tags: Remove ${packageName} from your tagTemplate (e.g., use "${prefix}${version}")
|
|
372
|
+
• If using single/async mode: Ensure your package.json has a valid "name" field
|
|
373
|
+
```
|
|
374
|
+
|
|
375
|
+
**Solutions:**
|
|
376
|
+
|
|
377
|
+
1. **For Synced Mode with Package Names**: Enable package-specific tags
|
|
378
|
+
```json
|
|
379
|
+
{
|
|
380
|
+
"sync": true,
|
|
381
|
+
"packageSpecificTags": true,
|
|
382
|
+
"tagTemplate": "${packageName}@${prefix}${version}"
|
|
383
|
+
}
|
|
384
|
+
```
|
|
385
|
+
|
|
386
|
+
2. **For Global Tags**: Remove `${packageName}` from your template
|
|
387
|
+
```json
|
|
388
|
+
{
|
|
389
|
+
"tagTemplate": "${prefix}${version}",
|
|
390
|
+
"packageSpecificTags": false
|
|
391
|
+
}
|
|
392
|
+
```
|
|
393
|
+
|
|
394
|
+
3. **For Single/Async Mode**: Ensure your `package.json` has a valid `name` field
|
|
395
|
+
```json
|
|
396
|
+
{
|
|
397
|
+
"name": "my-package",
|
|
398
|
+
"version": "1.0.0"
|
|
399
|
+
}
|
|
400
|
+
```
|
|
401
|
+
|
|
402
|
+
### Common Template Patterns
|
|
403
|
+
|
|
404
|
+
Here are some common template patterns and when to use them:
|
|
405
|
+
|
|
406
|
+
| Pattern | Use Case | Example Output |
|
|
407
|
+
|---------|----------|----------------|
|
|
408
|
+
| `"${prefix}${version}"` | Global versioning, all packages get same tag | `v1.2.3` |
|
|
409
|
+
| `"${packageName}@${prefix}${version}"` | Package-specific versioning | `@scope/package@v1.2.3` |
|
|
410
|
+
| `"release-${version}"` | Custom release format | `release-1.2.3` |
|
|
411
|
+
| `"${packageName}-${version}"` | Simple package versioning | `@scope/package-1.2.3` |
|
|
412
|
+
|
|
413
|
+
### Commit Message Templates
|
|
414
|
+
|
|
415
|
+
The same principles apply to `commitMessage` templates. If your commit message template includes `${packageName}`, ensure that package names are available in your current mode:
|
|
416
|
+
|
|
417
|
+
```json
|
|
418
|
+
{
|
|
419
|
+
"commitMessage": "chore: release ${packageName}@${version}",
|
|
420
|
+
"packageSpecificTags": true
|
|
421
|
+
}
|
|
422
|
+
```
|
|
423
|
+
|
|
424
|
+
For global commit messages, use templates without `${packageName}`:
|
|
425
|
+
```json
|
|
426
|
+
{
|
|
427
|
+
"commitMessage": "chore: release ${version}"
|
|
428
|
+
}
|
|
429
|
+
```
|
|
430
|
+
|
|
431
|
+
## Monorepo Versioning Modes
|
|
432
|
+
|
|
433
|
+
While primarily used for single packages now, `package-versioner` retains options for monorepo workflows, controlled mainly by the `sync` flag in `version.config.json`.
|
|
434
|
+
|
|
435
|
+
### Sync Mode (`sync: true`)
|
|
436
|
+
|
|
437
|
+
This is the default if the `sync` flag is present and true.
|
|
438
|
+
|
|
439
|
+
- **Behaviour:** The tool calculates **one** version bump based on the overall history (or branch pattern). This single new version is applied to **all** packages within the repository (or just the root `package.json` if not a structured monorepo). A single Git tag is created.
|
|
440
|
+
- **Tag Behaviour:**
|
|
441
|
+
- In **multi-package monorepos**: Creates global tags like `v1.2.3` regardless of `packageSpecificTags` setting
|
|
442
|
+
- In **single-package repositories**: Respects the `packageSpecificTags` setting - can create either `v1.2.3` or `package-name@v1.2.3`
|
|
443
|
+
- **Use Case:** Suitable for monorepos where all packages are tightly coupled and released together with the same version number. Also the effective mode for single-package repositories.
|
|
444
|
+
|
|
445
|
+
### Async Mode (`sync: false`)
|
|
446
|
+
|
|
447
|
+
*(Note: This mode relies heavily on monorepo tooling and structure, like `pnpm workspaces` and correctly configured package dependencies.)*
|
|
448
|
+
|
|
449
|
+
- **Behaviour (Default - No `-t` flag):** The tool analyzes commits to determine which specific packages within the monorepo have changed since the last relevant commit/tag.
|
|
450
|
+
- It calculates an appropriate version bump **independently for each changed package** based on the commits affecting that package.
|
|
451
|
+
- Only the `package.json` files of the changed packages are updated.
|
|
452
|
+
- A **single commit** is created grouping all the version bumps, using the commit message template. **No Git tags are created** in this mode.
|
|
453
|
+
- **Use Case:** Suitable for monorepos where packages are versioned independently, but a single commit represents the batch of updates for traceability.
|
|
454
|
+
|
|
455
|
+
- **Behaviour (Targeted - With `-t` flag):** When using the `-t, --target <targets>` flag:
|
|
456
|
+
- Only the specified packages (respecting the `skip` list) are considered for versioning.
|
|
457
|
+
- It calculates an appropriate version bump **independently for each targeted package** based on its commit history.
|
|
458
|
+
- The `package.json` file of each successfully updated targeted package is modified.
|
|
459
|
+
- An **individual Git tag** (e.g., `packageName@1.2.3`) is created **for each successfully updated package** immediately after its version is bumped.
|
|
460
|
+
- Finally, a **single commit** is created including all the updated `package.json` files, using a summary commit message (e.g., `chore(release): pkg-a, pkg-b 1.2.3 [skip-ci]`).
|
|
461
|
+
- **Important:** Only package-specific tags are created. The global tag (e.g., `v1.2.3`) is **not** automatically generated in this mode. If your release process (like GitHub Releases) depends on a global tag, you'll need to create it manually in your CI/CD script *after* `package-versioner` completes.
|
|
462
|
+
- **Use Case:** Releasing specific packages independently while still tagging each released package individually.
|
|
463
|
+
|
|
464
|
+
## Prerelease Handling
|
|
465
|
+
|
|
466
|
+
`package-versioner` provides flexible handling for prerelease versions, allowing both creation of prereleases and promotion to stable releases.
|
|
467
|
+
|
|
468
|
+
### Creating Prereleases
|
|
469
|
+
|
|
470
|
+
Use the `--prerelease` flag with an identifier to create a prerelease version:
|
|
471
|
+
|
|
472
|
+
```bash
|
|
473
|
+
# Create a beta prerelease
|
|
474
|
+
npx package-versioner --bump minor --prerelease beta
|
|
475
|
+
# Result: 1.0.0 -> 1.1.0-beta.0
|
|
476
|
+
```
|
|
477
|
+
|
|
478
|
+
You can also set a default prerelease identifier in your `version.config.json`:
|
|
479
|
+
|
|
480
|
+
```json
|
|
481
|
+
{
|
|
482
|
+
"prereleaseIdentifier": "beta"
|
|
483
|
+
}
|
|
484
|
+
```
|
|
485
|
+
|
|
486
|
+
### Promoting Prereleases to Stable Releases
|
|
487
|
+
|
|
488
|
+
When using standard bump types (`major`, `minor`, `patch`) with the `--bump` flag on a prerelease version, `package-versioner` will automatically clean the prerelease identifier:
|
|
489
|
+
|
|
490
|
+
```bash
|
|
491
|
+
# Starting from version 1.0.0-beta.1
|
|
492
|
+
npx package-versioner --bump major
|
|
493
|
+
# Result: 1.0.0-beta.1 -> 2.0.0 (not 2.0.0-beta.0)
|
|
494
|
+
```
|
|
495
|
+
|
|
496
|
+
This intuitive behaviour means you don't need to use an empty prerelease identifier (`--prerelease ""`) to promote a prerelease to a stable version. Simply specify the standard bump type and the tool will automatically produce a clean version number.
|
|
497
|
+
|
|
498
|
+
This applies to all standard bump types:
|
|
499
|
+
- `--bump major`: 1.0.0-beta.1 -> 2.0.0
|
|
500
|
+
- `--bump minor`: 1.0.0-beta.1 -> 1.1.0
|
|
501
|
+
- `--bump patch`: 1.0.0-beta.1 -> 1.0.1
|
package/package.json
ADDED
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@releasekit/version",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "A lightweight yet powerful CLI tool for automated semantic versioning based on Git history and conventional commits.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/index.cjs",
|
|
7
|
+
"module": "./dist/index.js",
|
|
8
|
+
"types": "./dist/index.d.ts",
|
|
9
|
+
"exports": {
|
|
10
|
+
".": {
|
|
11
|
+
"import": {
|
|
12
|
+
"types": "./dist/index.d.ts",
|
|
13
|
+
"default": "./dist/index.js"
|
|
14
|
+
},
|
|
15
|
+
"require": {
|
|
16
|
+
"types": "./dist/index.d.cts",
|
|
17
|
+
"default": "./dist/index.cjs"
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
},
|
|
21
|
+
"bin": {
|
|
22
|
+
"releasekit-version": "./dist/cli.js"
|
|
23
|
+
},
|
|
24
|
+
"scripts": {
|
|
25
|
+
"build": "tsup src/index.ts src/cli.ts --format esm,cjs --dts",
|
|
26
|
+
"dev": "tsup src/index.ts src/cli.ts --format esm,cjs --watch --dts",
|
|
27
|
+
"clean": "rm -rf dist coverage .turbo",
|
|
28
|
+
"test": "vitest run --dir test/unit",
|
|
29
|
+
"test:unit": "vitest run --coverage --dir test/unit",
|
|
30
|
+
"test:coverage": "vitest run --coverage --dir test/unit",
|
|
31
|
+
"lint": "biome check .",
|
|
32
|
+
"typecheck": "tsc --noEmit"
|
|
33
|
+
},
|
|
34
|
+
"keywords": ["version", "semver", "git", "package"],
|
|
35
|
+
"author": {
|
|
36
|
+
"name": "Sam Maister",
|
|
37
|
+
"email": "goosewobbler@protonmail.com"
|
|
38
|
+
},
|
|
39
|
+
"repository": {
|
|
40
|
+
"type": "git",
|
|
41
|
+
"url": "https://github.com/goosewobbler/releasekit",
|
|
42
|
+
"directory": "packages/version"
|
|
43
|
+
},
|
|
44
|
+
"license": "MIT",
|
|
45
|
+
"files": ["dist", "docs", "version.schema.json"],
|
|
46
|
+
"publishConfig": {
|
|
47
|
+
"access": "public"
|
|
48
|
+
},
|
|
49
|
+
"dependencies": {
|
|
50
|
+
"@manypkg/get-packages": "^3.1.0",
|
|
51
|
+
"@releasekit/config": "workspace:*",
|
|
52
|
+
"@releasekit/core": "workspace:*",
|
|
53
|
+
"@types/micromatch": "^4.0.10",
|
|
54
|
+
"chalk": "catalog:",
|
|
55
|
+
"commander": "catalog:",
|
|
56
|
+
"conventional-changelog-angular": "^8.1.0",
|
|
57
|
+
"conventional-changelog-conventional-commits": "npm:conventional-changelog-conventionalcommits@^9.0.0",
|
|
58
|
+
"conventional-changelog-conventionalcommits": "^9.1.0",
|
|
59
|
+
"conventional-commits-filter": "^5.0.0",
|
|
60
|
+
"conventional-recommended-bump": "^11.2.0",
|
|
61
|
+
"figlet": "^1.10.0",
|
|
62
|
+
"git-semver-tags": "^8.0.0",
|
|
63
|
+
"micromatch": "^4.0.8",
|
|
64
|
+
"semver": "catalog:",
|
|
65
|
+
"smol-toml": "catalog:"
|
|
66
|
+
},
|
|
67
|
+
"devDependencies": {
|
|
68
|
+
"@biomejs/biome": "catalog:",
|
|
69
|
+
"@types/figlet": "^1.5.5",
|
|
70
|
+
"@types/node": "catalog:",
|
|
71
|
+
"@types/semver": "catalog:",
|
|
72
|
+
"@vitest/coverage-v8": "catalog:",
|
|
73
|
+
"tsup": "catalog:",
|
|
74
|
+
"typescript": "catalog:",
|
|
75
|
+
"vitest": "catalog:"
|
|
76
|
+
},
|
|
77
|
+
"engines": {
|
|
78
|
+
"node": ">=18 || >=20"
|
|
79
|
+
}
|
|
80
|
+
}
|