-
Notifications
You must be signed in to change notification settings - Fork 6
Expand file tree
/
Copy pathversion.js
More file actions
151 lines (135 loc) · 5.37 KB
/
Copy pathversion.js
File metadata and controls
151 lines (135 loc) · 5.37 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
/**
* @license
* Copyright 2025 Google LLC
* SPDX-License-Identifier: Apache-2.0
*/
import { execSync } from 'node:child_process';
import {
existsSync,
readFileSync,
readdirSync,
rmSync,
writeFileSync,
} from 'node:fs';
import { join, resolve } from 'node:path';
// A script to handle versioning and ensure all related changes are in a single, atomic commit.
function run(command) {
console.log(`> ${command}`);
execSync(command, { stdio: 'inherit' });
}
function readJson(filePath) {
return JSON.parse(readFileSync(filePath, 'utf-8'));
}
function writeJson(filePath, data) {
writeFileSync(filePath, JSON.stringify(data, null, 2) + '\n');
}
// 1. Get the version from the command line arguments.
const versionType = process.argv[2];
if (!versionType) {
console.error('Error: No version specified.');
console.error(
'Usage: npm run version <version> (e.g., 1.2.3 or patch|minor|major|prerelease)',
);
process.exit(1);
}
// 2. Bump the version in the root and all workspace package.json files.
run(`npm version ${versionType} --no-git-tag-version --allow-same-version`);
// 3. Get all workspaces and filter out the one we don't want to version.
// We intend to maintain sdk and mobile-mcp versions independently.
const workspacesToExclude = ['@qwen-code/sdk', '@qwen-code/mobile-mcp'];
let lsOutput;
try {
lsOutput = JSON.parse(
execSync('npm ls --workspaces --json --depth=0').toString(),
);
} catch (e) {
// `npm ls` can exit with a non-zero status code if there are issues
// with dependencies, but it will still produce the JSON output we need.
// We'll try to parse the stdout from the error object.
if (e.stdout) {
console.warn(
'Warning: `npm ls` exited with a non-zero status code. Attempting to proceed with the output.',
);
try {
lsOutput = JSON.parse(e.stdout.toString());
} catch (parseError) {
console.error(
'Error: Failed to parse JSON from `npm ls` output even after `npm ls` failed.',
);
console.error('npm ls stderr:', e.stderr.toString());
console.error('Parse error:', parseError);
process.exit(1);
}
} else {
console.error('Error: `npm ls` failed with no output.');
console.error(e.stderr?.toString() || e);
process.exit(1);
}
}
const allWorkspaces = Object.keys(lsOutput.dependencies || {});
const workspacesToVersion = allWorkspaces.filter(
(wsName) => !workspacesToExclude.includes(wsName),
);
for (const workspaceName of workspacesToVersion) {
run(
`npm version ${versionType} --workspace ${workspaceName} --no-git-tag-version --allow-same-version`,
);
}
// 4. Get the new version number from the root package.json
const rootPackageJsonPath = resolve(process.cwd(), 'package.json');
const newVersion = readJson(rootPackageJsonPath).version;
// 5. Update the sandboxImageUri in the root package.json
const rootPackageJson = readJson(rootPackageJsonPath);
if (rootPackageJson.config?.sandboxImageUri) {
rootPackageJson.config.sandboxImageUri =
rootPackageJson.config.sandboxImageUri.replace(/:.*$/, `:${newVersion}`);
console.log(`Updated sandboxImageUri in root to use version ${newVersion}`);
writeJson(rootPackageJsonPath, rootPackageJson);
}
// 6. Update the sandboxImageUri in the cli package.json
const cliPackageJsonPath = resolve(process.cwd(), 'packages/cli/package.json');
const cliPackageJson = readJson(cliPackageJsonPath);
if (cliPackageJson.config?.sandboxImageUri) {
cliPackageJson.config.sandboxImageUri =
cliPackageJson.config.sandboxImageUri.replace(/:.*$/, `:${newVersion}`);
console.log(
`Updated sandboxImageUri in cli package to use version ${newVersion}`,
);
writeJson(cliPackageJsonPath, cliPackageJson);
}
// 7. Pin channel adapters' semver dependency on @qwen-code/channel-base to
// the exact new version. A caret range like ^0.21.0 does not match a
// prerelease bump (e.g. 0.21.1-preview.0), so npm would replace the workspace
// link with the stale registry package and the release build would compile
// against outdated types.
const channelsDir = resolve(process.cwd(), 'packages/channels');
for (const entry of readdirSync(channelsDir)) {
const pkgPath = join(channelsDir, entry, 'package.json');
if (!existsSync(pkgPath)) continue;
const pkg = readJson(pkgPath);
const dep = pkg.dependencies?.['@qwen-code/channel-base'];
if (dep && !dep.startsWith('file:')) {
pkg.dependencies['@qwen-code/channel-base'] = newVersion;
writeJson(pkgPath, pkg);
console.log(
`Pinned @qwen-code/channel-base to ${newVersion} in ${pkg.name}`,
);
}
}
// 8. Refresh node_modules and package-lock.json against the pinned exact
// versions so the adapters resolve channel-base to the workspace link again.
// --ignore-scripts prevents the root `prepare` lifecycle from triggering a
// redundant full build that fails with TS5055 when dist/ already exists from
// the initial `npm ci` install.
run('npm install --ignore-scripts');
// 9. The per-workspace `npm version` reifies above nested a stale registry
// copy of channel-base under each adapter while ranges briefly mismatched.
// The install above cleans both lockfiles but can leave that directory on
// disk, where it shadows the workspace link during tsc. Remove it.
for (const entry of readdirSync(channelsDir)) {
rmSync(join(channelsDir, entry, 'node_modules', '@qwen-code'), {
recursive: true,
force: true,
});
}
console.log(`Successfully bumped versions to v${newVersion}.`);