package-versioner 0.1.1 → 0.3.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/README.md +36 -3
- package/dist/index.cjs +726 -478
- package/dist/index.js +726 -479
- package/docs/CI_CD_INTEGRATION.md +165 -0
- package/docs/VERSIONING_STRATEGIES.md +96 -0
- package/package.json +6 -5
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
# CI/CD Integration
|
|
2
|
+
|
|
3
|
+
`package-versioner` is designed to work seamlessly in CI/CD pipelines, making it easy to automate versioning as part of your release workflow.
|
|
4
|
+
|
|
5
|
+
## JSON Output Mode
|
|
6
|
+
|
|
7
|
+
For programmatic consumption in CI/CD scripts, `package-versioner` provides a structured JSON output option:
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
# Output results in JSON format
|
|
11
|
+
npx package-versioner --json
|
|
12
|
+
|
|
13
|
+
# Combine with dry-run for planning
|
|
14
|
+
npx package-versioner --dry-run --json
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
This will suppress all normal console output and instead output a single JSON object containing:
|
|
18
|
+
|
|
19
|
+
```json
|
|
20
|
+
{
|
|
21
|
+
"dryRun": false, // Whether this was a dry run
|
|
22
|
+
"updates": [ // Array of packages that were updated
|
|
23
|
+
{
|
|
24
|
+
"packageName": "@scope/package-a", // Package name
|
|
25
|
+
"newVersion": "1.2.3", // New version number
|
|
26
|
+
"filePath": "/path/to/package.json" // Path to the updated package.json
|
|
27
|
+
}
|
|
28
|
+
],
|
|
29
|
+
"commitMessage": "chore(release): v1.2.3", // The commit message that was used
|
|
30
|
+
"tags": [ // Array of tags that were created
|
|
31
|
+
"v1.2.3" // or package-specific tags in targeted mode
|
|
32
|
+
]
|
|
33
|
+
}
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
### Benefits of JSON Output
|
|
37
|
+
|
|
38
|
+
The structured JSON output provides several advantages for CI/CD integration:
|
|
39
|
+
|
|
40
|
+
- **Reliable Parsing**: Unlike text logs that might change format or include ANSI color codes, the JSON structure remains consistent
|
|
41
|
+
- **Programmatic Access**: Easily extract specific values like version numbers for subsequent steps
|
|
42
|
+
- **Conditional Workflows**: Trigger different CI actions based on the presence of updates or specific version changes
|
|
43
|
+
- **Audit Trail**: Store the JSON output as artifacts for version change tracking
|
|
44
|
+
- **Error Handling**: Better detect and respond to versioning issues in your pipeline
|
|
45
|
+
|
|
46
|
+
## Sample CI/CD Integration Patterns
|
|
47
|
+
|
|
48
|
+
Here are some common ways to incorporate `package-versioner` into your CI/CD pipeline:
|
|
49
|
+
|
|
50
|
+
### GitHub Actions Workflow Example
|
|
51
|
+
|
|
52
|
+
```yaml
|
|
53
|
+
name: Release
|
|
54
|
+
|
|
55
|
+
on:
|
|
56
|
+
push:
|
|
57
|
+
branches: [main]
|
|
58
|
+
|
|
59
|
+
jobs:
|
|
60
|
+
version:
|
|
61
|
+
runs-on: ubuntu-latest
|
|
62
|
+
outputs:
|
|
63
|
+
changes_detected: ${{ steps.version.outputs.changes_detected }}
|
|
64
|
+
new_version: ${{ steps.version.outputs.new_version }}
|
|
65
|
+
|
|
66
|
+
steps:
|
|
67
|
+
- uses: actions/checkout@v3
|
|
68
|
+
with:
|
|
69
|
+
fetch-depth: 0 # Important for git history
|
|
70
|
+
|
|
71
|
+
- name: Setup Node.js
|
|
72
|
+
uses: actions/setup-node@v3
|
|
73
|
+
with:
|
|
74
|
+
node-version: '18'
|
|
75
|
+
|
|
76
|
+
- name: Install dependencies
|
|
77
|
+
run: npm ci
|
|
78
|
+
|
|
79
|
+
- name: Determine version
|
|
80
|
+
id: version
|
|
81
|
+
run: |
|
|
82
|
+
# Run in JSON mode for parsing
|
|
83
|
+
VERSION_OUTPUT=$(npx package-versioner --json)
|
|
84
|
+
echo "Version output: $VERSION_OUTPUT"
|
|
85
|
+
|
|
86
|
+
# Use jq to parse the JSON output
|
|
87
|
+
CHANGES_DETECTED=$(echo "$VERSION_OUTPUT" | jq -r '.updates | length > 0')
|
|
88
|
+
echo "changes_detected=$CHANGES_DETECTED" >> $GITHUB_OUTPUT
|
|
89
|
+
|
|
90
|
+
if [ "$CHANGES_DETECTED" = "true" ]; then
|
|
91
|
+
# Extract the first package's new version as representative version
|
|
92
|
+
NEW_VERSION=$(echo "$VERSION_OUTPUT" | jq -r '.updates[0].newVersion')
|
|
93
|
+
echo "new_version=$NEW_VERSION" >> $GITHUB_OUTPUT
|
|
94
|
+
fi
|
|
95
|
+
|
|
96
|
+
publish:
|
|
97
|
+
needs: version
|
|
98
|
+
if: needs.version.outputs.changes_detected == 'true'
|
|
99
|
+
runs-on: ubuntu-latest
|
|
100
|
+
steps:
|
|
101
|
+
# Publishing steps using the detected version
|
|
102
|
+
- run: echo "Would publish version ${{ needs.version.outputs.new_version }}"
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
### GitLab CI Pipeline Example
|
|
106
|
+
|
|
107
|
+
```yaml
|
|
108
|
+
stages:
|
|
109
|
+
- version
|
|
110
|
+
- publish
|
|
111
|
+
|
|
112
|
+
determine_version:
|
|
113
|
+
stage: version
|
|
114
|
+
script:
|
|
115
|
+
- npm ci
|
|
116
|
+
- |
|
|
117
|
+
VERSION_OUTPUT=$(npx package-versioner --json)
|
|
118
|
+
echo "VERSION_OUTPUT=$VERSION_OUTPUT" >> version.env
|
|
119
|
+
|
|
120
|
+
# Parse values for use in later stages
|
|
121
|
+
CHANGES_DETECTED=$(echo "$VERSION_OUTPUT" | jq -r '.updates | length > 0')
|
|
122
|
+
echo "CHANGES_DETECTED=$CHANGES_DETECTED" >> version.env
|
|
123
|
+
|
|
124
|
+
if [ "$CHANGES_DETECTED" = "true" ]; then
|
|
125
|
+
NEW_VERSION=$(echo "$VERSION_OUTPUT" | jq -r '.updates[0].newVersion')
|
|
126
|
+
echo "NEW_VERSION=$NEW_VERSION" >> version.env
|
|
127
|
+
fi
|
|
128
|
+
artifacts:
|
|
129
|
+
reports:
|
|
130
|
+
dotenv: version.env
|
|
131
|
+
|
|
132
|
+
publish:
|
|
133
|
+
stage: publish
|
|
134
|
+
needs: determine_version
|
|
135
|
+
script:
|
|
136
|
+
- echo "Publishing version $NEW_VERSION"
|
|
137
|
+
rules:
|
|
138
|
+
- if: $CHANGES_DETECTED == "true"
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
## Working with Tags in CI
|
|
142
|
+
|
|
143
|
+
When using the targeted mode with `-t` flag, `package-versioner` creates package-specific tags (e.g., `@scope/package-a@1.2.0`) but not a global tag. If your release process needs a global tag, you can add a step to your CI/CD pipeline:
|
|
144
|
+
|
|
145
|
+
```bash
|
|
146
|
+
# Create a global tag based on the representative version
|
|
147
|
+
NEW_VERSION=$(echo "$VERSION_OUTPUT" | jq -r '.updates[0].newVersion')
|
|
148
|
+
git tag -a "v$NEW_VERSION" -m "Release v$NEW_VERSION"
|
|
149
|
+
git push origin "v$NEW_VERSION"
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
## Environment Variables
|
|
153
|
+
|
|
154
|
+
`package-versioner` respects the following environment variables:
|
|
155
|
+
|
|
156
|
+
- `NO_COLOR=1`: Disables colored output in logs (automatically detected in CI environments)
|
|
157
|
+
- `CI=true`: Most CI environments set this automatically, which helps the tool adjust its output behavior
|
|
158
|
+
|
|
159
|
+
## Tips for Reliable CI/CD Integration
|
|
160
|
+
|
|
161
|
+
1. **Always use `--json`** in CI/CD pipelines for consistent output parsing
|
|
162
|
+
2. **Use the `fetch-depth: 0`** option in GitHub Actions (or equivalent in other CIs) to ensure access to the full Git history
|
|
163
|
+
3. **Store the JSON output** as a build artifact for debugging and auditing
|
|
164
|
+
4. **Consider dry runs** in your preview/staging branches to validate version changes before they're applied
|
|
165
|
+
5. **Be mindful of Git credentials** - ensure your CI has proper permissions for creating commits and tags
|
|
@@ -0,0 +1,96 @@
|
|
|
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
|
+
## Monorepo Versioning Modes
|
|
69
|
+
|
|
70
|
+
While primarily used for single packages now, `package-versioner` retains options for monorepo workflows, controlled mainly by the `synced` flag in `version.config.json`.
|
|
71
|
+
|
|
72
|
+
### Synced Mode (`synced: true`)
|
|
73
|
+
|
|
74
|
+
This is the default if the `synced` flag is present and true.
|
|
75
|
+
|
|
76
|
+
- **Behavior:** 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 (e.g., `v1.2.3`).
|
|
77
|
+
- **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.
|
|
78
|
+
|
|
79
|
+
### Async Mode (`synced: false`)
|
|
80
|
+
|
|
81
|
+
*(Note: This mode relies heavily on monorepo tooling and structure, like `pnpm workspaces` and correctly configured package dependencies.)*
|
|
82
|
+
|
|
83
|
+
- **Behavior (Default - No `-t` flag):** The tool analyzes commits to determine which specific packages within the monorepo have changed since the last relevant commit/tag.
|
|
84
|
+
- It calculates an appropriate version bump **independently for each changed package** based on the commits affecting that package.
|
|
85
|
+
- Only the `package.json` files of the changed packages are updated.
|
|
86
|
+
- A **single commit** is created grouping all the version bumps, using the commit message template. **No Git tags are created** in this mode.
|
|
87
|
+
- **Use Case:** Suitable for monorepos where packages are versioned independently, but a single commit represents the batch of updates for traceability.
|
|
88
|
+
|
|
89
|
+
- **Behavior (Targeted - With `-t` flag):** When using the `-t, --target <targets>` flag:
|
|
90
|
+
- Only the specified packages (respecting the `skip` list) are considered for versioning.
|
|
91
|
+
- It calculates an appropriate version bump **independently for each targeted package** based on its commit history.
|
|
92
|
+
- The `package.json` file of each successfully updated targeted package is modified.
|
|
93
|
+
- An **individual Git tag** (e.g., `packageName@1.2.3`) is created **for each successfully updated package** immediately after its version is bumped.
|
|
94
|
+
- 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]`).
|
|
95
|
+
- **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.
|
|
96
|
+
- **Use Case:** Releasing specific packages independently while still tagging each released package individually.
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "package-versioner",
|
|
3
|
-
"description": "A powerful CLI tool for automated semantic versioning based on Git history and conventional commits.
|
|
4
|
-
"version": "0.
|
|
3
|
+
"description": "A lightweight yet powerful CLI tool for automated semantic versioning based on Git history and conventional commits.",
|
|
4
|
+
"version": "0.3.0",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
7
7
|
"module": "./dist/index.mjs",
|
|
@@ -24,6 +24,7 @@
|
|
|
24
24
|
"license": "MIT",
|
|
25
25
|
"files": [
|
|
26
26
|
"dist/**",
|
|
27
|
+
"docs/**",
|
|
27
28
|
"package-versioner.schema.json"
|
|
28
29
|
],
|
|
29
30
|
"bin": {
|
|
@@ -38,11 +39,11 @@
|
|
|
38
39
|
"devDependencies": {
|
|
39
40
|
"@biomejs/biome": "^1.9.4",
|
|
40
41
|
"@types/figlet": "^1.5.5",
|
|
41
|
-
"@types/node": "^22.14.
|
|
42
|
+
"@types/node": "^22.14.1",
|
|
42
43
|
"@types/semver": "^7.3.13",
|
|
43
44
|
"@vitest/coverage-v8": "^3.1.1",
|
|
44
45
|
"husky": "^9.1.7",
|
|
45
|
-
"lint-staged": "^15.5.
|
|
46
|
+
"lint-staged": "^15.5.1",
|
|
46
47
|
"tsup": "^8.4.0",
|
|
47
48
|
"typescript": "^5.8.3",
|
|
48
49
|
"vitest": "^3.1.1"
|
|
@@ -53,7 +54,7 @@
|
|
|
53
54
|
"commander": "^13.1.0",
|
|
54
55
|
"conventional-changelog-angular": "^8.0.0",
|
|
55
56
|
"conventional-recommended-bump": "^11.0.0",
|
|
56
|
-
"figlet": "^1.8.
|
|
57
|
+
"figlet": "^1.8.1",
|
|
57
58
|
"git-semver-tags": "^8.0.0",
|
|
58
59
|
"semver": "^7.7.1"
|
|
59
60
|
},
|