Skip to content

Commit 8962f7f

Browse files
committed
feat: add version bumping script to manage monorepo versioning
1 parent ef02e5b commit 8962f7f

File tree

2 files changed

+108
-1
lines changed

2 files changed

+108
-1
lines changed

package.json

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,10 @@
88
"dev": "pnpm --filter @telagent/node start",
99
"build": "pnpm -r build",
1010
"test": "pnpm -r test",
11-
"typecheck": "pnpm -r typecheck"
11+
"typecheck": "pnpm -r typecheck",
12+
"version:patch": "node scripts/bump-version.mjs patch",
13+
"version:minor": "node scripts/bump-version.mjs minor",
14+
"version:major": "node scripts/bump-version.mjs major"
1215
},
1316
"engines": {
1417
"node": ">=22 <25",

scripts/bump-version.mjs

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
#!/usr/bin/env node
2+
/**
3+
* bump-version.mjs — bump the version across the entire monorepo.
4+
*
5+
* Usage:
6+
* node scripts/bump-version.mjs patch # 0.2.0 → 0.2.1
7+
* node scripts/bump-version.mjs minor # 0.2.0 → 0.3.0
8+
* node scripts/bump-version.mjs major # 0.2.0 → 1.0.0
9+
* node scripts/bump-version.mjs 1.5.0 # explicit version
10+
*/
11+
12+
import { readFileSync, writeFileSync } from 'node:fs';
13+
import { resolve, dirname } from 'node:path';
14+
import { fileURLToPath } from 'node:url';
15+
import { execSync } from 'node:child_process';
16+
17+
const __dirname = dirname(fileURLToPath(import.meta.url));
18+
const ROOT = resolve(__dirname, '..');
19+
20+
// ── helpers ──────────────────────────────────────────────────────────────────
21+
22+
function readJson(path) {
23+
return JSON.parse(readFileSync(path, 'utf8'));
24+
}
25+
26+
function writeJson(path, obj) {
27+
writeFileSync(path, JSON.stringify(obj, null, 2) + '\n', 'utf8');
28+
}
29+
30+
function bumpSemver(current, bump) {
31+
const [major, minor, patch] = current.split('.').map(Number);
32+
switch (bump) {
33+
case 'major': return `${major + 1}.0.0`;
34+
case 'minor': return `${major}.${minor + 1}.0`;
35+
case 'patch': return `${major}.${minor}.${patch + 1}`;
36+
default:
37+
// validate it looks like a semver
38+
if (!/^\d+\.\d+\.\d+/.test(bump)) {
39+
console.error(`ERROR: "${bump}" is not a valid bump type (patch|minor|major) or semver string.`);
40+
process.exit(1);
41+
}
42+
return bump;
43+
}
44+
}
45+
46+
// ── collect package.json paths ───────────────────────────────────────────────
47+
48+
// Parse package globs from pnpm-workspace.yaml (simple line-based, no full YAML parser needed)
49+
const raw = readFileSync(resolve(ROOT, 'pnpm-workspace.yaml'), 'utf8');
50+
const globs = raw
51+
.split('\n')
52+
.filter(l => l.trim().startsWith('-'))
53+
.map(l => l.replace(/^\s*-\s*['"]?/, '').replace(/['"]?\s*$/, '').trim());
54+
55+
const paths = [resolve(ROOT, 'package.json')];
56+
57+
for (const glob of globs) {
58+
// Only handle simple "packages/*" style globs (replace * with actual dirs)
59+
const base = glob.replace(/\/\*.*$/, '');
60+
const { readdirSync, statSync } = await import('node:fs');
61+
let entries;
62+
try {
63+
entries = readdirSync(resolve(ROOT, base));
64+
} catch {
65+
continue;
66+
}
67+
for (const entry of entries) {
68+
const pkgJson = resolve(ROOT, base, entry, 'package.json');
69+
try {
70+
statSync(pkgJson);
71+
paths.push(pkgJson);
72+
} catch {
73+
// no package.json in this entry
74+
}
75+
}
76+
}
77+
78+
// ── main ─────────────────────────────────────────────────────────────────────
79+
80+
const bump = process.argv[2];
81+
if (!bump) {
82+
console.error('Usage: node scripts/bump-version.mjs <patch|minor|major|x.y.z>');
83+
process.exit(1);
84+
}
85+
86+
const rootPkg = readJson(paths[0]);
87+
const current = rootPkg.version;
88+
const next = bumpSemver(current, bump);
89+
90+
console.log(`\nBumping version: ${current}${next}\n`);
91+
92+
for (const pkgPath of paths) {
93+
const pkg = readJson(pkgPath);
94+
if (!pkg.version) continue;
95+
pkg.version = next;
96+
writeJson(pkgPath, pkg);
97+
const rel = pkgPath.replace(ROOT + '/', '');
98+
console.log(` ✓ ${rel}`);
99+
}
100+
101+
console.log(`\nDone. All packages updated to ${next}.`);
102+
console.log(`\nNext steps:`);
103+
console.log(` git add -A && git commit -m "chore: bump version to ${next}"`);
104+
console.log(` git tag v${next}`);

0 commit comments

Comments
 (0)