Skip to content

Commit 542711c

Browse files
committed
fix(changelog): prevent duplicate changelog entries
- Improved changelog update logic - Handles existing entries for same version - Places new entries after header - Uses separator for better placement - Improved logging for duplicate entries
1 parent 42a93f4 commit 542711c

6 files changed

Lines changed: 76 additions & 13 deletions

File tree

CHANGELOG.md

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
21
# 📦 Changelog for Universal Version Bump
32

43
All notable changes for each version of the Ambient Music extension.
@@ -10,7 +9,7 @@ All notable changes for each version of the Ambient Music extension.
109
### Added
1110

1211
- add changelog generation
13-
- version bumpupdated this taj54/[email protected]
12+
- version bumpupdated this taj54/[email protected]
1413

1514
### Changed
1615

@@ -42,6 +41,11 @@ All notable changes for each version of the Ambient Music extension.
4241

4342
- **changelog:** Strip prefixes like `feat:` and `fix:` from changelog entries.
4443

44+
### Added
45+
46+
- **changelog:** Prevent duplicate changelog entries for the same version.
47+
- **changelog:** Place new changelog entries after the header in `CHANGELOG.md`.
48+
4549
## v0.9.0 2025 08 25
4650

4751
### Added

dist/index.js

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
/**
2-
* universal-version-bump v0.9.2
2+
* universal-version-bump v0.9.3
33
* Universal Version Bump
44
*
55
* Description: A GitHub Action to automatically bump versions across any app (Node, Python, PHP, Docker, etc.)
66
* Author: Taj <[email protected]>
77
* Homepage: https://github.com/taj54/universal-version-bump#readme
88
* License: MIT
9-
* Generated on Tue, 26 Aug 2025 10:43:40 GMT
9+
* Generated on Tue, 26 Aug 2025 13:13:01 GMT
1010
*/
1111
require('./sourcemap-register.js');/******/ (() => { // webpackBootstrap
1212
/******/ var __webpack_modules__ = ({
@@ -32997,8 +32997,26 @@ class ChangelogService {
3299732997
async updateChangelog(changelogContent) {
3299832998
const changelogPath = 'CHANGELOG.md';
3299932999
const existingChangelog = await this.fileHandler.readFile(changelogPath);
33000-
const newChangelog = changelogContent + existingChangelog;
33001-
await this.fileHandler.writeFile(changelogPath, newChangelog);
33000+
const versionMatch = changelogContent.match(/## v(\d+\.\d+\.\d+)/);
33001+
if (versionMatch) {
33002+
const newVersion = versionMatch[0];
33003+
if (existingChangelog.includes(newVersion)) {
33004+
console.log(`Changelog for version ${newVersion} already exists. Skipping.`);
33005+
return;
33006+
}
33007+
}
33008+
const separator = '\n---\n\n';
33009+
const headerIndex = existingChangelog.indexOf(separator);
33010+
if (headerIndex !== -1) {
33011+
const header = existingChangelog.substring(0, headerIndex + separator.length);
33012+
const restOfChangelog = existingChangelog.substring(headerIndex + separator.length);
33013+
const newChangelog = header + changelogContent + restOfChangelog;
33014+
await this.fileHandler.writeFile(changelogPath, newChangelog);
33015+
}
33016+
else {
33017+
const newChangelog = changelogContent + existingChangelog;
33018+
await this.fileHandler.writeFile(changelogPath, newChangelog);
33019+
}
3300233020
}
3300333021
}
3300433022
exports.ChangelogService = ChangelogService;

dist/index.js.map

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,4 +53,4 @@
5353
"vitest": "^3.2.4",
5454
"yaml": "^2.8.1"
5555
}
56-
}
56+
}

src/services/changelogService.ts

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,26 @@ export class ChangelogService {
8181
async updateChangelog(changelogContent: string): Promise<void> {
8282
const changelogPath = 'CHANGELOG.md';
8383
const existingChangelog = await this.fileHandler.readFile(changelogPath);
84-
const newChangelog = changelogContent + existingChangelog;
85-
await this.fileHandler.writeFile(changelogPath, newChangelog);
84+
const versionMatch = changelogContent.match(/## v(\d+\.\d+\.\d+)/);
85+
if (versionMatch) {
86+
const newVersion = versionMatch[0];
87+
if (existingChangelog.includes(newVersion)) {
88+
console.log(`Changelog for version ${newVersion} already exists. Skipping.`);
89+
return;
90+
}
91+
}
92+
93+
const separator = '\n---\n\n';
94+
const headerIndex = existingChangelog.indexOf(separator);
95+
96+
if (headerIndex !== -1) {
97+
const header = existingChangelog.substring(0, headerIndex + separator.length);
98+
const restOfChangelog = existingChangelog.substring(headerIndex + separator.length);
99+
const newChangelog = header + changelogContent + restOfChangelog;
100+
await this.fileHandler.writeFile(changelogPath, newChangelog);
101+
} else {
102+
const newChangelog = changelogContent + existingChangelog;
103+
await this.fileHandler.writeFile(changelogPath, newChangelog);
104+
}
86105
}
87106
}

tests/services/changelogService.test.ts

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -64,12 +64,34 @@ describe('ChangelogService', () => {
6464
});
6565

6666
it('should update the changelog file', async () => {
67-
const readFileSpy = vi.spyOn(fileHandler, 'readFile').mockResolvedValue('existing content');
67+
const existingChangelogWithHeader = '# Header\n\n---\n\nexisting content';
68+
const newContent = 'new content';
69+
const expectedContent = '# Header\n\n---\n\nnew contentexisting content';
70+
71+
const readFileSpy = vi
72+
.spyOn(fileHandler, 'readFile')
73+
.mockResolvedValue(existingChangelogWithHeader);
74+
const writeFileSpy = vi.spyOn(fileHandler, 'writeFile').mockResolvedValue();
75+
76+
await changelogService.updateChangelog(newContent);
77+
78+
expect(readFileSpy).toHaveBeenCalledWith('CHANGELOG.md');
79+
expect(writeFileSpy).toHaveBeenCalledWith('CHANGELOG.md', expectedContent);
80+
});
81+
82+
it('should not update the changelog file if the version already exists', async () => {
83+
const existingChangelog = '## v1.1.0 2025-08-26\n\n### Added\n\n- existing feature\n\n';
84+
const readFileSpy = vi.spyOn(fileHandler, 'readFile').mockResolvedValue(existingChangelog);
6885
const writeFileSpy = vi.spyOn(fileHandler, 'writeFile').mockResolvedValue();
86+
const consoleSpy = vi.spyOn(console, 'log').mockImplementation(() => {});
6987

70-
await changelogService.updateChangelog('new content');
88+
const newChangelog = '## v1.1.0 2025-08-26\n\n### Fixed\n\n- a bug fix\n\n';
89+
await changelogService.updateChangelog(newChangelog);
7190

7291
expect(readFileSpy).toHaveBeenCalledWith('CHANGELOG.md');
73-
expect(writeFileSpy).toHaveBeenCalledWith('CHANGELOG.md', 'new contentexisting content');
92+
expect(writeFileSpy).not.toHaveBeenCalled();
93+
expect(consoleSpy).toHaveBeenCalledWith(
94+
'Changelog for version ## v1.1.0 already exists. Skipping.',
95+
);
7496
});
7597
});

0 commit comments

Comments
 (0)