Skip to content

Commit 51ed6a5

Browse files
committed
chore: automate version bumps via sync-version.ts and runtime import
Extends scripts/sync-version.ts to cover every file with a hardcoded version string — JSON manifests (package-lock, claw, openclaw-plugin, ama_fitting), test constants (test_claw_mcp_transport.ts), and doc references (README, DEXBOT_COMPARISON, FUND_MOVEMENT_AND_ACCOUNTING, EVOLUTION). Future bumps: edit root package.json, run sync-version.ts, commit + tag. claw/modules/skill_utils.ts now imports DEXBOT_VERSION from root package.json at runtime instead of a hardcoded string, permanently removing it from the sync list. package-lock.json was still at 1.0.0 — caught and bumped to 1.0.1.
1 parent f0c4990 commit 51ed6a5

3 files changed

Lines changed: 164 additions & 64 deletions

File tree

claw/modules/skill_utils.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ const { getStorage } = require('../../modules/storage');
22
const storage = getStorage();
33
const { path } = require('../../modules/path_api');
44
const { PATHS } = require('../../modules/paths');
5+
const { version: DEXBOT_VERSION } = require('../../package.json');
56

67
export function normalizeRepoRoot(variableName: string, repoRoot?: string) {
78
return path.resolve(repoRoot || PATHS.CLAW.DIR);
@@ -48,7 +49,7 @@ export function buildSkillTomlLines(skillName: string, description: string, tags
4849
'[skill]',
4950
`name = "${skillName}"`,
5051
`description = "${description}"`,
51-
'version = "1.0.1"',
52+
`version = "${DEXBOT_VERSION}"`,
5253
`tags = [${tags.map(t => JSON.stringify(t)).join(', ')}]`
5354
];
5455

package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

scripts/sync-version.ts

Lines changed: 160 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -1,90 +1,189 @@
11
#!/usr/bin/env node
22
/**
3-
* Sync DEXBot2-owned package/plugin manifest versions from root package.json.
3+
* Sync DEXBot2-owned manifest versions and hardcoded version strings
4+
* from root package.json.
45
*
5-
* package.json has to remain the source of truth because npm requires a literal
6-
* JSON version field.
6+
* package.json has to remain the source of truth because npm requires
7+
* a literal JSON version field.
8+
*
9+
* Usage:
10+
* npx tsx scripts/sync-version.ts # write changes
11+
* npx tsx scripts/sync-version.ts --check # exit 1 if any mismatch
712
*/
813

914
const fs = require('fs');
1015
const path = require('path');
1116
const { PATHS } = require('../modules/paths');
12-
const { readJSON } = require('../modules/utils/fs_utils');
17+
const ROOT = PATHS.PROJECT_ROOT;
1318

14-
const rootPackagePath = path.join(PATHS.PROJECT_ROOT, 'package.json');
15-
const rootPackage = readJson(rootPackagePath);
19+
const rootPackage = JSON.parse(fs.readFileSync(path.join(ROOT, 'package.json'), 'utf8'));
1620
const targetVersion = rootPackage.version;
1721
const checkOnly = process.argv.includes('--check');
1822

1923
if (!targetVersion) {
20-
throw new Error('Root package.json is missing a version field');
24+
throw new Error('Root package.json is missing a version field');
25+
}
26+
27+
interface Target {
28+
file: string;
29+
update: (content: string, version: string) => string | null;
2130
}
2231

23-
const targets = [
24-
{
25-
file: 'package-lock.json',
26-
update(json: any) {
27-
json.version = targetVersion;
28-
if (json.packages && json.packages['']) {
29-
json.packages[''].version = targetVersion;
30-
}
31-
}
32+
const targets: Target[] = [
33+
// ── JSON manifests ──────────────────────────────────────────
34+
{
35+
file: 'package-lock.json',
36+
update(content, version) {
37+
const json = JSON.parse(content);
38+
if (json.version === version && json.packages?.['']?.version === version) return null;
39+
json.version = version;
40+
if (json.packages?.['']) json.packages[''].version = version;
41+
return JSON.stringify(json, null, 2) + '\n';
42+
},
43+
},
44+
{
45+
file: 'claw/package.json',
46+
update(content, version) {
47+
const json = JSON.parse(content);
48+
if (json.version === version) return null;
49+
json.version = version;
50+
return JSON.stringify(json, null, 2) + '\n';
51+
},
52+
},
53+
{
54+
file: 'claw/runtimes/openclaw-plugin/package.json',
55+
update(content, version) {
56+
const json = JSON.parse(content);
57+
if (json.version === version) return null;
58+
json.version = version;
59+
return JSON.stringify(json, null, 2) + '\n';
3260
},
33-
{
34-
file: 'claw/package.json',
35-
update(json: any) {
36-
json.version = targetVersion;
37-
}
61+
},
62+
{
63+
file: 'claw/runtimes/openclaw-plugin/openclaw.plugin.json',
64+
update(content, version) {
65+
const json = JSON.parse(content);
66+
if (json.version === version) return null;
67+
json.version = version;
68+
return JSON.stringify(json, null, 2) + '\n';
3869
},
39-
{
40-
file: 'claw/runtimes/openclaw-plugin/package.json',
41-
update(json: any) {
42-
json.version = targetVersion;
43-
}
70+
},
71+
{
72+
file: 'analysis/ama_fitting/package.json',
73+
update(content, version) {
74+
const json = JSON.parse(content);
75+
if (json.version === version) return null;
76+
json.version = version;
77+
return JSON.stringify(json, null, 2) + '\n';
78+
},
79+
},
80+
81+
// ── Source files (regex replacements) ──────────────────────
82+
{
83+
file: 'claw/tests/test_claw_mcp_transport.ts',
84+
update(content, version) {
85+
const replaced = content.replace(
86+
/(version: )'\d+\.\d+\.\d+'/g,
87+
`$1'${version}'`,
88+
);
89+
return replaced !== content ? replaced : null;
90+
},
91+
},
92+
93+
// ── Doc files (regex replacements) ─────────────────────────
94+
{
95+
file: 'docs/README.md',
96+
update(content, version) {
97+
let result = content;
98+
result = result.replace(
99+
/(v)\d+\.\d+\.\d+( is the current release)/g,
100+
`$1${version}$2`,
101+
);
102+
result = result.replace(
103+
/(through the v)\d+\.\d+\.\d+( stable release)/g,
104+
`$1${version}$2`,
105+
);
106+
return result !== content ? result : null;
44107
},
45-
{
46-
file: 'claw/runtimes/openclaw-plugin/openclaw.plugin.json',
47-
update(json: any) {
48-
json.version = targetVersion;
49-
}
50-
}
108+
},
109+
{
110+
file: 'docs/DEXBOT_COMPARISON.md',
111+
update(content, version) {
112+
let result = content;
113+
// DEXBot2 prose reference (not DEXBot Python's v1.0.0)
114+
result = result.replace(
115+
/(DEXBot2 \(TypeScript, v)\d+\.\d+\.\d+\)/g,
116+
`$1${version})`,
117+
);
118+
// DEXBot2 table cells — v-prefixed cells in the right column
119+
result = result.replace(
120+
/(\|\s+v)\d+\.\d+\.\d+(\s+\|)/g,
121+
`$1${version}$2`,
122+
);
123+
return result !== content ? result : null;
124+
},
125+
},
126+
{
127+
file: 'docs/FUND_MOVEMENT_AND_ACCOUNTING.md',
128+
update(content, version) {
129+
const replaced = content.replace(
130+
/(DEXBot2 v)\d+\.\d+\.\d+( release)/g,
131+
`$1${version}$2`,
132+
);
133+
return replaced !== content ? replaced : null;
134+
},
135+
},
136+
{
137+
file: 'docs/EVOLUTION.md',
138+
update(content, version) {
139+
const replaced = content.replace(
140+
/(through the current )\d+\.\d+\.\d+( stable release)/g,
141+
`$1${version}$2`,
142+
);
143+
return replaced !== content ? replaced : null;
144+
},
145+
},
51146
];
52147

53-
const mismatches: any[] = [];
148+
// ── Execute ─────────────────────────────────────────────────
149+
const mismatches: string[] = [];
54150

55151
for (const target of targets) {
56-
const filePath = path.join(PATHS.PROJECT_ROOT, target.file);
57-
const beforeText = fs.readFileSync(filePath, 'utf8');
58-
const json = JSON.parse(beforeText);
59-
target.update(json);
60-
const afterText = `${JSON.stringify(json, null, 2)}\n`;
152+
const filePath = path.join(ROOT, target.file);
153+
154+
let content: string;
155+
try {
156+
content = fs.readFileSync(filePath, 'utf8');
157+
} catch {
158+
console.error(`[SKIP] ${target.file} — not found`);
159+
continue;
160+
}
61161

62-
if (beforeText !== afterText) {
63-
mismatches.push(target.file);
64-
if (!checkOnly) {
65-
fs.writeFileSync(filePath, afterText);
66-
}
67-
}
162+
const updated = target.update(content, targetVersion);
163+
164+
if (updated === null) {
165+
continue; // no change needed
166+
}
167+
168+
mismatches.push(target.file);
169+
if (!checkOnly) {
170+
fs.writeFileSync(filePath, updated);
171+
}
68172
}
69173

70174
if (mismatches.length > 0) {
71-
if (checkOnly) {
72-
console.error(`Version mismatch with root package.json (${targetVersion}):`);
73-
for (const file of mismatches) {
74-
console.error(`- ${file}`);
75-
}
76-
process.exit(1);
77-
}
175+
if (checkOnly) {
176+
console.error(
177+
`Version mismatch with root package.json (${targetVersion}):`,
178+
);
179+
for (const file of mismatches) console.error(` - ${file}`);
180+
process.exit(1);
181+
}
78182

79-
console.log(`Synced ${mismatches.length} manifest(s) to ${targetVersion}:`);
80-
for (const file of mismatches) {
81-
console.log(`- ${file}`);
82-
}
183+
console.log(
184+
`Synced ${mismatches.length} file(s) to ${targetVersion}:`,
185+
);
186+
for (const file of mismatches) console.log(` - ${file}`);
83187
} else {
84-
console.log(`All DEXBot2-owned manifests already match ${targetVersion}.`);
85-
}
86-
87-
function readJson(filePath: any) {
88-
return readJSON(filePath);
188+
console.log(`All files already match version ${targetVersion}.`);
89189
}
90-
export {};

0 commit comments

Comments
 (0)