Skip to content

Commit bda3267

Browse files
author
Bastian Jakobs
committed
chore: update release workflow to automatically update CHANGELOG.md and add changelog script
1 parent 9b08d5b commit bda3267

File tree

4 files changed

+188
-3
lines changed

4 files changed

+188
-3
lines changed

.github/workflows/publish.yml

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,10 +54,19 @@ jobs:
5454
git config user.email "github-actions[bot]@users.noreply.github.com"
5555
5656
- name: Bump version
57-
run: "npm version ${{ github.event.inputs.version }} -m 'chore: release v%s'"
57+
run: npm version ${{ github.event.inputs.version }} -m 'chore: release v%s' --no-git-tag-version
5858

59-
- name: Push changes
59+
- name: Update changelog
6060
run: |
61+
NEW_VERSION=$(node -p "require('./package.json').version")
62+
node scripts/update-changelog.js $NEW_VERSION
63+
64+
- name: Commit and push changes
65+
run: |
66+
NEW_VERSION=$(node -p "require('./package.json').version")
67+
git add CHANGELOG.md package.json
68+
git commit -m "chore: release v${NEW_VERSION}"
69+
git tag "v${NEW_VERSION}"
6170
git push
6271
git push --tags
6372

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,8 @@
5555
"type-check": "vue-tsc --build",
5656
"lint": "eslint",
5757
"lint:fix": "eslint --fix",
58-
"prepublishOnly": "pnpm run test:unit run && pnpm run build"
58+
"prepublishOnly": "pnpm run test:unit run && pnpm run build",
59+
"changelog:update": "node scripts/update-changelog.js"
5960
},
6061
"dependencies": {
6162
"vue": "^3.5.22"

scripts/README.md

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
# Scripts
2+
3+
This directory contains utility scripts for the project.
4+
5+
## update-changelog.js
6+
7+
Automatically updates the `CHANGELOG.md` file when creating a new release.
8+
9+
### What it does
10+
11+
1. Converts the `[Unreleased]` section to a new version entry with today's date
12+
2. Creates a new empty `[Unreleased]` section
13+
3. Updates version comparison links at the bottom of the changelog
14+
15+
### Usage
16+
17+
#### Manual Usage
18+
19+
```bash
20+
# Update changelog for a specific version
21+
node scripts/update-changelog.js 1.1.8
22+
23+
# Or use the npm script
24+
pnpm changelog:update 1.1.8
25+
```
26+
27+
#### Automatic Usage (GitHub Actions)
28+
29+
The script is automatically executed during the release workflow (`.github/workflows/publish.yml`) when you trigger a release:
30+
31+
1. Go to GitHub Actions
32+
2. Select "Release and Publish" workflow
33+
3. Click "Run workflow"
34+
4. Choose version bump type (patch/minor/major)
35+
5. The workflow will:
36+
- Run tests
37+
- Build the library
38+
- Bump version in package.json
39+
- **Update CHANGELOG.md automatically**
40+
- Commit and tag the changes
41+
- Publish to NPM
42+
- Create GitHub release
43+
44+
### Requirements
45+
46+
- The `[Unreleased]` section must contain changes
47+
- Version must follow semantic versioning (e.g., 1.2.3)
48+
49+
### Example
50+
51+
Before:
52+
```markdown
53+
## [Unreleased]
54+
55+
### Fixed
56+
- Bug fix description
57+
58+
## [1.1.7] - 2025-10-20
59+
```
60+
61+
After running `node scripts/update-changelog.js 1.1.8`:
62+
```markdown
63+
## [Unreleased]
64+
65+
## [1.1.8] - 2025-10-23
66+
67+
### Fixed
68+
- Bug fix description
69+
70+
## [1.1.7] - 2025-10-20
71+
```
72+
73+
The version links at the bottom are also updated automatically.

scripts/update-changelog.js

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
#!/usr/bin/env node
2+
3+
import fs from 'node:fs'
4+
import path from 'node:path'
5+
import process from 'node:process'
6+
import { fileURLToPath } from 'node:url'
7+
8+
const __filename = fileURLToPath(import.meta.url)
9+
const __dirname = path.dirname(__filename)
10+
11+
const CHANGELOG_PATH = path.join(__dirname, '../CHANGELOG.md')
12+
13+
/**
14+
* Updates the CHANGELOG.md file by:
15+
* 1. Converting [Unreleased] section to a new version entry
16+
* 2. Adding today's date
17+
* 3. Creating a new empty [Unreleased] section
18+
* 4. Updating version comparison links at the bottom
19+
*
20+
* @param {string} version - The new version number (e.g., "1.1.8")
21+
*/
22+
function updateChangelog(version) {
23+
try {
24+
// Read current changelog
25+
const changelog = fs.readFileSync(CHANGELOG_PATH, 'utf-8')
26+
27+
// Get today's date in YYYY-MM-DD format
28+
const date = new Date().toISOString().split('T')[0]
29+
30+
// Check if there's actually content in the Unreleased section
31+
const unreleasedPattern = /## \[Unreleased\]\n([\s\S]*?)\n## \[/
32+
const unreleasedMatch = changelog.match(unreleasedPattern)
33+
if (!unreleasedMatch || !unreleasedMatch[1].trim()) {
34+
console.error('❌ Error: No unreleased changes found in CHANGELOG.md')
35+
console.error('Please add changes to the [Unreleased] section before creating a release.')
36+
process.exit(1)
37+
}
38+
39+
// Replace [Unreleased] header with new version and create new empty [Unreleased] section
40+
let updatedChangelog = changelog.replace(
41+
'## [Unreleased]',
42+
`## [Unreleased]\n\n## [${version}] - ${date}`,
43+
)
44+
45+
// Update version comparison links at the bottom
46+
// Find the [Unreleased] link pattern
47+
const linkPattern = /\[Unreleased\]: (.+)\/compare\/v(.+)\.\.\.HEAD/
48+
const unreleasedLinkMatch = updatedChangelog.match(linkPattern)
49+
50+
if (unreleasedLinkMatch) {
51+
const repoUrl = unreleasedLinkMatch[1]
52+
const previousVersion = unreleasedLinkMatch[2]
53+
54+
// Update the [Unreleased] link to point to new version
55+
updatedChangelog = updatedChangelog.replace(
56+
linkPattern,
57+
`[Unreleased]: ${repoUrl}/compare/v${version}...HEAD`,
58+
)
59+
60+
// Add new version comparison link right after [Unreleased]
61+
const newVersionLink = `[${version}]: ${repoUrl}/compare/v${previousVersion}...v${version}`
62+
updatedChangelog = updatedChangelog.replace(
63+
`[Unreleased]: ${repoUrl}/compare/v${version}...HEAD`,
64+
`[Unreleased]: ${repoUrl}/compare/v${version}...HEAD\n${newVersionLink}`,
65+
)
66+
}
67+
else {
68+
console.warn('⚠️ Warning: Could not find version comparison links. Please update them manually.')
69+
}
70+
71+
// Write updated changelog
72+
fs.writeFileSync(CHANGELOG_PATH, updatedChangelog)
73+
74+
console.log(`✅ Successfully updated CHANGELOG.md for version ${version}`)
75+
console.log(` - Date: ${date}`)
76+
console.log(` - Created new [${version}] section`)
77+
console.log(` - Updated version comparison links`)
78+
}
79+
catch (error) {
80+
console.error('❌ Error updating changelog:', error.message)
81+
process.exit(1)
82+
}
83+
}
84+
85+
// Main execution
86+
const version = process.argv[2]
87+
88+
if (!version) {
89+
console.error('❌ Error: Please provide a version number')
90+
console.error('Usage: node update-changelog.js <version>')
91+
console.error('Example: node update-changelog.js 1.1.8')
92+
process.exit(1)
93+
}
94+
95+
// Validate version format (basic semver check)
96+
if (!/^\d+\.\d+\.\d+$/.test(version)) {
97+
console.error(`❌ Error: Invalid version format: ${version}`)
98+
console.error('Version must follow semantic versioning (e.g., 1.2.3)')
99+
process.exit(1)
100+
}
101+
102+
updateChangelog(version)

0 commit comments

Comments
 (0)