Skip to content

Commit e969425

Browse files
authored
Chore add version bumper (#5101)
* chore: add version-bump for changesets * fix: issue with version-bump.ts
1 parent fe89200 commit e969425

File tree

5 files changed

+87
-48
lines changed

5 files changed

+87
-48
lines changed

.github/workflows/changesets-release-pr.yml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,13 +46,14 @@ jobs:
4646
with:
4747
commit: "chore(release): version packages"
4848
title: "chore(release): version packages"
49+
version: npm run ci:version
4950
env:
5051
GITHUB_TOKEN: ${{ steps.generate-token.outputs.token }}
5152
HUSKY: 0 # Disable Husky hooks in CI
5253

5354
- name: 🆙 Publish
5455
if: steps.changesets.outputs.hasChangesets == 'false'
5556
run: |
56-
npx --no tsx scripts/github/changesets-publish.ts
57+
npx --no tsx scripts/github/publish.ts
5758
env:
5859
GITHUB_TOKEN: ${{ steps.generate-token.outputs.token }}

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,9 +49,10 @@
4949
"build": "npm run build --workspace=scripts",
5050
"build-outputs": "npm run build-outputs --workspace=scripts",
5151
"build-showcases": "npm run build-showcases --workspace=scripts",
52+
"changeset": "changeset",
53+
"ci:version": "changeset version && tsx scripts/github/changesets/version-bump.ts",
5254
"clean": "git clean -dfx --exclude=.env",
5355
"codestyle": "prettier . --write",
54-
"changeset": "changeset",
5556
"commit:updated-snapshots": "git diff --name-only --diff-filter=M | xargs git add && git commit --message 'test: updated snapshots'",
5657
"dev": "npm run dev --workspace=scripts",
5758
"generate:component": "npm run generate:component --workspace=@db-ux/core-components",
Lines changed: 2 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
/* eslint-disable @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-return,@typescript-eslint/no-unsafe-assignment */
22

3-
import { globSync } from 'glob';
43
import { execSync } from 'node:child_process';
54
import fs from 'node:fs';
65
import os from 'node:os';
76
import path from 'node:path';
87
import { fileURLToPath } from 'node:url';
8+
import { extractChangelogForVersion, findChangelogFiles } from './utils.js';
99

1010
const __filename = fileURLToPath(import.meta.url);
1111
const __dirname = path.dirname(__filename);
@@ -38,58 +38,14 @@ function getVersion(): string {
3838
return pkg.version;
3939
}
4040

41-
function tagExists(tag: string): boolean {
42-
const tags = run(`git tag --list "${tag}"`);
43-
return tags.split('\n').includes(tag);
44-
}
45-
46-
/**
47-
* Find all CHANGELOG.md files in the repo, excluding node_modules, using glob.
48-
*/
49-
function findChangelogFiles(repoRoot: string): string[] {
50-
return globSync('**/CHANGELOG.md', {
51-
cwd: repoRoot,
52-
ignore: ['**/node_modules/**'],
53-
absolute: true
54-
});
55-
}
56-
57-
/**
58-
* Extracts the first changelog section (from the first '##' header to the next '##' or end of file).
59-
* This is useful for extracting the latest release notes, regardless of version string.
60-
*/
61-
function extractChangelogForVersion(changelog: string): string {
62-
// Find the index of the first '##' header
63-
const firstHeader = /^##\s.*$/m.exec(changelog);
64-
if (!firstHeader) {
65-
// No '##' header found, return empty string
66-
return '';
67-
}
68-
69-
const startIdx = firstHeader.index;
70-
71-
// Find the index of the second '##' header after the first
72-
const rest = changelog.slice(startIdx + firstHeader[0].length);
73-
const secondHeader = /^##\s.*$/m.exec(rest);
74-
if (secondHeader) {
75-
// Second '##' found: return content from first to second header
76-
const endIdx = startIdx + firstHeader[0].length + secondHeader.index;
77-
return changelog.slice(startIdx, endIdx).trim();
78-
}
79-
80-
// Only one '##' header: return from first header to end of file
81-
return changelog.slice(startIdx).trim();
82-
}
83-
8441
function getFirstHeadline(changelog: string): string {
8542
// Match first line starting with # or ## (allow whitespace)
8643
const match = /^\s*#+\s+(.+)$/m.exec(changelog);
8744
return match ? match[1].trim() : '';
8845
}
8946

9047
function getReleaseNotes(): string {
91-
const version = getVersion();
92-
const repoRoot = path.resolve(__dirname, '../../');
48+
const repoRoot = path.resolve(__dirname, '../../../');
9349
const changelogFiles = findChangelogFiles(repoRoot);
9450
const notes: string[] = [];
9551
for (const file of changelogFiles) {

scripts/github/changesets/utils.ts

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
import { globSync } from 'glob';
2+
3+
/**
4+
* Find all CHANGELOG.md files in the repo, excluding node_modules, using glob.
5+
*/
6+
export function findChangelogFiles(repoRoot: string): string[] {
7+
return globSync('**/CHANGELOG.md', {
8+
cwd: repoRoot,
9+
ignore: ['**/node_modules/**'],
10+
absolute: true
11+
});
12+
}
13+
14+
/**
15+
* Extracts the first changelog section (from the first '##' header to the next '##' or end of file).
16+
* This is useful for extracting the latest release notes, regardless of version string.
17+
*/
18+
export function extractChangelogForVersion(changelog: string): string {
19+
// Find the index of the first '##' header
20+
const firstHeader = /^##\s.*$/m.exec(changelog);
21+
if (!firstHeader) {
22+
// No '##' header found, return empty string
23+
return '';
24+
}
25+
26+
const startIdx = firstHeader.index;
27+
28+
// Find the index of the second '##' header after the first
29+
const rest = changelog.slice(startIdx + firstHeader[0].length);
30+
const secondHeader = /^##\s.*$/m.exec(rest);
31+
if (secondHeader) {
32+
// Second '##' found: return content from first to second header
33+
const endIdx = startIdx + firstHeader[0].length + secondHeader.index;
34+
return changelog.slice(startIdx, endIdx).trim();
35+
}
36+
37+
// Only one '##' header: return from first header to end of file
38+
return changelog.slice(startIdx).trim();
39+
}
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
import fs from 'node:fs';
2+
import path from 'node:path';
3+
import { fileURLToPath } from 'node:url';
4+
import { extractChangelogForVersion, findChangelogFiles } from './utils.js';
5+
6+
const __filename = fileURLToPath(import.meta.url);
7+
const __dirname = path.dirname(__filename);
8+
9+
/**
10+
* Ensures that each changelog file has content after the latest section headline.
11+
* If not, adds an italicized 'version bump' note after the headline.
12+
*/
13+
export function ensureChangelogHasContent() {
14+
const repoRoot = path.resolve(__dirname, '../../../');
15+
const changelogFiles = findChangelogFiles(repoRoot);
16+
for (const file of changelogFiles) {
17+
const content = fs.readFileSync(file, 'utf8');
18+
const latestSection = extractChangelogForVersion(content);
19+
if (!latestSection) continue; // No section found, skip
20+
21+
// Find the first '##' header
22+
const headerMatch = /^##\s.*$/m.exec(latestSection);
23+
if (!headerMatch) continue;
24+
const header = headerMatch[0];
25+
const afterHeader = latestSection.slice(header.length).trim();
26+
27+
// If no content after header, add italicized 'version bump'
28+
if (!afterHeader) {
29+
// Find the position of the first '##' header in the file
30+
const fileHeaderMatch = /^##\s.*$/m.exec(content);
31+
if (!fileHeaderMatch) continue;
32+
const insertPos = fileHeaderMatch.index + fileHeaderMatch[0].length;
33+
const newContent =
34+
content.slice(0, insertPos) +
35+
'\n\n*version bump*\n' +
36+
content.slice(insertPos);
37+
fs.writeFileSync(file, newContent, 'utf8');
38+
}
39+
}
40+
}
41+
42+
ensureChangelogHasContent();

0 commit comments

Comments
 (0)