Skip to content

Commit e69c27e

Browse files
authored
Merge branch 'main' into rfc/vp-hooks
2 parents c346d60 + 9b57c4b commit e69c27e

File tree

119 files changed

+2549
-1148
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

119 files changed

+2549
-1148
lines changed

.github/renovate.json

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,28 @@
1111
],
1212
"packageRules": [
1313
{
14-
"matchPackageNames": ["vitest-dev"],
14+
"description": "Ignore selected npm package updates",
15+
"matchManagers": ["npm"],
16+
"matchPackageNames": [
17+
"rolldown",
18+
"/^oxc-.*/",
19+
"@oxc-node/*",
20+
"@oxc-project/*",
21+
"@vitejs/devtools",
22+
"oxfmt",
23+
"oxlint",
24+
"oxlint-tsgolint",
25+
"tsdown",
26+
"vite",
27+
"vitest",
28+
"vitest-dev"
29+
],
30+
"enabled": false
31+
},
32+
{
33+
"description": "Ignore oxc crate updates",
34+
"matchManagers": ["cargo"],
35+
"matchPackageNames": ["/^oxc([_-].*)?$/"],
1536
"enabled": false
1637
},
1738
{

.github/scripts/upgrade-deps.mjs

Lines changed: 227 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,29 @@ import fs from 'node:fs';
22
import path from 'node:path';
33

44
const ROOT = process.cwd();
5+
const META_DIR = process.env.UPGRADE_DEPS_META_DIR;
6+
7+
const isFullSha = (s) => /^[0-9a-f]{40}$/.test(s);
8+
9+
/** @type {Map<string, { old: string | null, new: string, tag?: string }>} */
10+
const changes = new Map();
11+
12+
function recordChange(name, oldValue, newValue, tag) {
13+
const entry = { old: oldValue ?? null, new: newValue };
14+
if (tag) {
15+
entry.tag = tag;
16+
}
17+
changes.set(name, entry);
18+
if (oldValue !== newValue) {
19+
console.log(` ${name}: ${oldValue ?? '(unset)'} -> ${newValue}`);
20+
} else {
21+
console.log(` ${name}: ${newValue} (unchanged)`);
22+
}
23+
}
524

625
// ============ GitHub API ============
7-
async function getLatestTagCommit(owner, repo) {
8-
const res = await fetch(`https://api.github.com/repos/${owner}/${repo}/tags`, {
26+
async function getLatestTag(owner, repo) {
27+
const res = await fetch(`https://api.github.com/repos/${owner}/${repo}/tags?per_page=1`, {
928
headers: {
1029
Authorization: `token ${process.env.GITHUB_TOKEN}`,
1130
Accept: 'application/vnd.github.v3+json',
@@ -18,11 +37,11 @@ async function getLatestTagCommit(owner, repo) {
1837
if (!Array.isArray(tags) || !tags.length) {
1938
throw new Error(`No tags found for ${owner}/${repo}`);
2039
}
21-
if (!tags[0]?.commit?.sha) {
22-
throw new Error(`Invalid tag structure for ${owner}/${repo}: missing commit SHA`);
40+
if (!tags[0]?.commit?.sha || !tags[0]?.name) {
41+
throw new Error(`Invalid tag structure for ${owner}/${repo}: missing SHA or name`);
2342
}
24-
console.log(`${repo} -> ${tags[0].name}`);
25-
return tags[0].commit.sha;
43+
console.log(`${repo} -> ${tags[0].name} (${tags[0].commit.sha.slice(0, 7)})`);
44+
return { sha: tags[0].commit.sha, tag: tags[0].name };
2645
}
2746

2847
// ============ npm Registry ============
@@ -45,11 +64,16 @@ async function updateUpstreamVersions() {
4564
const filePath = path.join(ROOT, 'packages/tools/.upstream-versions.json');
4665
const data = JSON.parse(fs.readFileSync(filePath, 'utf8'));
4766

48-
// rolldown -> rolldown/rolldown
49-
data.rolldown.hash = await getLatestTagCommit('rolldown', 'rolldown');
50-
51-
// vite -> vitejs/vite
52-
data['vite'].hash = await getLatestTagCommit('vitejs', 'vite');
67+
const oldRolldownHash = data.rolldown.hash;
68+
const oldViteHash = data['vite'].hash;
69+
const [rolldown, vite] = await Promise.all([
70+
getLatestTag('rolldown', 'rolldown'),
71+
getLatestTag('vitejs', 'vite'),
72+
]);
73+
data.rolldown.hash = rolldown.sha;
74+
data['vite'].hash = vite.sha;
75+
recordChange('rolldown', oldRolldownHash, rolldown.sha, rolldown.tag);
76+
recordChange('vite', oldViteHash, vite.sha, vite.tag);
5377

5478
fs.writeFileSync(filePath, JSON.stringify(data, null, 2) + '\n');
5579
console.log('Updated .upstream-versions.json');
@@ -60,39 +84,96 @@ async function updatePnpmWorkspace(versions) {
6084
const filePath = path.join(ROOT, 'pnpm-workspace.yaml');
6185
let content = fs.readFileSync(filePath, 'utf8');
6286

63-
// Update vitest-dev override (handle pre-release versions like -beta.1, -rc.0)
64-
// Handle both quoted ('npm:vitest@^...') and unquoted (npm:vitest@^...) forms
65-
content = content.replace(
66-
/vitest-dev: '?npm:vitest@\^[\d.]+(-[\w.]+)?'?/,
67-
`vitest-dev: 'npm:vitest@^${versions.vitest}'`,
68-
);
69-
70-
// Update tsdown in catalog (handle pre-release versions)
71-
content = content.replace(/tsdown: \^[\d.]+(-[\w.]+)?/, `tsdown: ^${versions.tsdown}`);
72-
73-
// Update @oxc-node/cli in catalog
74-
content = content.replace(
75-
/'@oxc-node\/cli': \^[\d.]+(-[\w.]+)?/,
76-
`'@oxc-node/cli': ^${versions.oxcNodeCli}`,
77-
);
78-
79-
// Update @oxc-node/core in catalog
80-
content = content.replace(
81-
/'@oxc-node\/core': \^[\d.]+(-[\w.]+)?/,
82-
`'@oxc-node/core': ^${versions.oxcNodeCore}`,
83-
);
84-
85-
// Update oxfmt in catalog
86-
content = content.replace(/oxfmt: =[\d.]+(-[\w.]+)?/, `oxfmt: =${versions.oxfmt}`);
87-
88-
// Update oxlint in catalog (but not oxlint-tsgolint)
89-
content = content.replace(/oxlint: =[\d.]+(-[\w.]+)?\n/, `oxlint: =${versions.oxlint}\n`);
87+
// oxlint's trailing \n in the pattern disambiguates from oxlint-tsgolint.
88+
const entries = [
89+
{
90+
name: 'vitest',
91+
pattern: /vitest-dev: npm:vitest@\^([\d.]+(?:-[\w.]+)?)/,
92+
replacement: `vitest-dev: npm:vitest@^${versions.vitest}`,
93+
newVersion: versions.vitest,
94+
},
95+
{
96+
name: 'tsdown',
97+
pattern: /tsdown: \^([\d.]+(?:-[\w.]+)?)/,
98+
replacement: `tsdown: ^${versions.tsdown}`,
99+
newVersion: versions.tsdown,
100+
},
101+
{
102+
name: '@oxc-node/cli',
103+
pattern: /'@oxc-node\/cli': \^([\d.]+(?:-[\w.]+)?)/,
104+
replacement: `'@oxc-node/cli': ^${versions.oxcNodeCli}`,
105+
newVersion: versions.oxcNodeCli,
106+
},
107+
{
108+
name: '@oxc-node/core',
109+
pattern: /'@oxc-node\/core': \^([\d.]+(?:-[\w.]+)?)/,
110+
replacement: `'@oxc-node/core': ^${versions.oxcNodeCore}`,
111+
newVersion: versions.oxcNodeCore,
112+
},
113+
{
114+
name: 'oxfmt',
115+
pattern: /oxfmt: =([\d.]+(?:-[\w.]+)?)/,
116+
replacement: `oxfmt: =${versions.oxfmt}`,
117+
newVersion: versions.oxfmt,
118+
},
119+
{
120+
name: 'oxlint',
121+
pattern: /oxlint: =([\d.]+(?:-[\w.]+)?)\n/,
122+
replacement: `oxlint: =${versions.oxlint}\n`,
123+
newVersion: versions.oxlint,
124+
},
125+
{
126+
name: 'oxlint-tsgolint',
127+
pattern: /oxlint-tsgolint: =([\d.]+(?:-[\w.]+)?)/,
128+
replacement: `oxlint-tsgolint: =${versions.oxlintTsgolint}`,
129+
newVersion: versions.oxlintTsgolint,
130+
},
131+
{
132+
name: '@oxc-project/runtime',
133+
pattern: /'@oxc-project\/runtime': =([\d.]+(?:-[\w.]+)?)/,
134+
replacement: `'@oxc-project/runtime': =${versions.oxcProjectRuntime}`,
135+
newVersion: versions.oxcProjectRuntime,
136+
},
137+
{
138+
name: '@oxc-project/types',
139+
pattern: /'@oxc-project\/types': =([\d.]+(?:-[\w.]+)?)/,
140+
replacement: `'@oxc-project/types': =${versions.oxcProjectTypes}`,
141+
newVersion: versions.oxcProjectTypes,
142+
},
143+
{
144+
name: 'oxc-minify',
145+
pattern: /oxc-minify: =([\d.]+(?:-[\w.]+)?)/,
146+
replacement: `oxc-minify: =${versions.oxcMinify}`,
147+
newVersion: versions.oxcMinify,
148+
},
149+
{
150+
name: 'oxc-parser',
151+
pattern: /oxc-parser: =([\d.]+(?:-[\w.]+)?)/,
152+
replacement: `oxc-parser: =${versions.oxcParser}`,
153+
newVersion: versions.oxcParser,
154+
},
155+
{
156+
name: 'oxc-transform',
157+
pattern: /oxc-transform: =([\d.]+(?:-[\w.]+)?)/,
158+
replacement: `oxc-transform: =${versions.oxcTransform}`,
159+
newVersion: versions.oxcTransform,
160+
},
161+
];
90162

91-
// Update oxlint-tsgolint in catalog
92-
content = content.replace(
93-
/oxlint-tsgolint: =[\d.]+(-[\w.]+)?/,
94-
`oxlint-tsgolint: =${versions.oxlintTsgolint}`,
95-
);
163+
for (const { name, pattern, replacement, newVersion } of entries) {
164+
let oldVersion;
165+
content = content.replace(pattern, (_match, captured) => {
166+
oldVersion = captured;
167+
return replacement;
168+
});
169+
if (oldVersion === undefined) {
170+
throw new Error(
171+
`Failed to match ${name} in pnpm-workspace.yaml — the pattern ${pattern} is stale, ` +
172+
`please update it in .github/scripts/upgrade-deps.mjs`,
173+
);
174+
}
175+
recordChange(name, oldVersion, newVersion);
176+
}
96177

97178
fs.writeFileSync(filePath, content);
98179
console.log('Updated pnpm-workspace.yaml');
@@ -129,15 +210,93 @@ async function updateCorePackage(devtoolsVersion) {
129210
const filePath = path.join(ROOT, 'packages/core/package.json');
130211
const pkg = JSON.parse(fs.readFileSync(filePath, 'utf8'));
131212

132-
// Update @vitejs/devtools in devDependencies
133-
if (pkg.devDependencies?.['@vitejs/devtools']) {
134-
pkg.devDependencies['@vitejs/devtools'] = `^${devtoolsVersion}`;
213+
const currentDevtools = pkg.devDependencies?.['@vitejs/devtools'];
214+
if (!currentDevtools) {
215+
return;
135216
}
217+
pkg.devDependencies['@vitejs/devtools'] = `^${devtoolsVersion}`;
218+
recordChange('@vitejs/devtools', currentDevtools.replace(/^[\^~]/, ''), devtoolsVersion);
136219

137220
fs.writeFileSync(filePath, JSON.stringify(pkg, null, 2) + '\n');
138221
console.log('Updated packages/core/package.json');
139222
}
140223

224+
// ============ Write metadata files for PR description ============
225+
function writeMetaFiles() {
226+
if (!META_DIR) {
227+
return;
228+
}
229+
230+
fs.mkdirSync(META_DIR, { recursive: true });
231+
232+
const versionsObj = Object.fromEntries(changes);
233+
fs.writeFileSync(
234+
path.join(META_DIR, 'versions.json'),
235+
JSON.stringify(versionsObj, null, 2) + '\n',
236+
);
237+
238+
const changed = [...changes.entries()].filter(([, v]) => v.old !== v.new);
239+
const unchanged = [...changes.entries()].filter(([, v]) => v.old === v.new);
240+
241+
const formatVersion = (v) => {
242+
if (v.tag) {
243+
return `${v.tag} (${v.new.slice(0, 7)})`;
244+
}
245+
if (isFullSha(v.new)) {
246+
return v.new.slice(0, 7);
247+
}
248+
return v.new;
249+
};
250+
const formatOld = (v) => {
251+
if (!v.old) {
252+
return '(unset)';
253+
}
254+
if (isFullSha(v.old)) {
255+
return v.old.slice(0, 7);
256+
}
257+
return v.old;
258+
};
259+
260+
const commitLines = ['feat(deps): upgrade upstream dependencies', ''];
261+
if (changed.length) {
262+
for (const [name, v] of changed) {
263+
commitLines.push(`- ${name}: ${formatOld(v)} -> ${formatVersion(v)}`);
264+
}
265+
} else {
266+
commitLines.push('- no version changes detected');
267+
}
268+
commitLines.push('');
269+
fs.writeFileSync(path.join(META_DIR, 'commit-message.txt'), commitLines.join('\n'));
270+
271+
const bodyLines = ['## Summary', ''];
272+
if (changed.length) {
273+
bodyLines.push('Automated daily upgrade of upstream dependencies.');
274+
} else {
275+
bodyLines.push('Automated daily upgrade run — no upstream version changes detected.');
276+
}
277+
bodyLines.push('', '## Dependency updates', '');
278+
if (changed.length) {
279+
bodyLines.push('| Package | From | To |');
280+
bodyLines.push('| --- | --- | --- |');
281+
for (const [name, v] of changed) {
282+
bodyLines.push(`| \`${name}\` | \`${formatOld(v)}\` | \`${formatVersion(v)}\` |`);
283+
}
284+
} else {
285+
bodyLines.push('_No version changes._');
286+
}
287+
if (unchanged.length) {
288+
bodyLines.push('', '<details><summary>Unchanged dependencies</summary>', '');
289+
for (const [name, v] of unchanged) {
290+
bodyLines.push(`- \`${name}\`: \`${formatVersion(v)}\``);
291+
}
292+
bodyLines.push('', '</details>');
293+
}
294+
bodyLines.push('', '## Code changes', '', '_No additional code changes recorded._', '');
295+
fs.writeFileSync(path.join(META_DIR, 'pr-body.md'), bodyLines.join('\n'));
296+
297+
console.log(`Wrote metadata files to ${META_DIR}`);
298+
}
299+
141300
console.log('Fetching latest versions…');
142301

143302
const [
@@ -149,6 +308,11 @@ const [
149308
oxfmtVersion,
150309
oxlintVersion,
151310
oxlintTsgolintVersion,
311+
oxcProjectRuntimeVersion,
312+
oxcProjectTypesVersion,
313+
oxcMinifyVersion,
314+
oxcParserVersion,
315+
oxcTransformVersion,
152316
] = await Promise.all([
153317
getLatestNpmVersion('vitest'),
154318
getLatestNpmVersion('tsdown'),
@@ -158,6 +322,11 @@ const [
158322
getLatestNpmVersion('oxfmt'),
159323
getLatestNpmVersion('oxlint'),
160324
getLatestNpmVersion('oxlint-tsgolint'),
325+
getLatestNpmVersion('@oxc-project/runtime'),
326+
getLatestNpmVersion('@oxc-project/types'),
327+
getLatestNpmVersion('oxc-minify'),
328+
getLatestNpmVersion('oxc-parser'),
329+
getLatestNpmVersion('oxc-transform'),
161330
]);
162331

163332
console.log(`vitest: ${vitestVersion}`);
@@ -168,6 +337,11 @@ console.log(`@oxc-node/core: ${oxcNodeCoreVersion}`);
168337
console.log(`oxfmt: ${oxfmtVersion}`);
169338
console.log(`oxlint: ${oxlintVersion}`);
170339
console.log(`oxlint-tsgolint: ${oxlintTsgolintVersion}`);
340+
console.log(`@oxc-project/runtime: ${oxcProjectRuntimeVersion}`);
341+
console.log(`@oxc-project/types: ${oxcProjectTypesVersion}`);
342+
console.log(`oxc-minify: ${oxcMinifyVersion}`);
343+
console.log(`oxc-parser: ${oxcParserVersion}`);
344+
console.log(`oxc-transform: ${oxcTransformVersion}`);
171345

172346
await updateUpstreamVersions();
173347
await updatePnpmWorkspace({
@@ -178,8 +352,15 @@ await updatePnpmWorkspace({
178352
oxfmt: oxfmtVersion,
179353
oxlint: oxlintVersion,
180354
oxlintTsgolint: oxlintTsgolintVersion,
355+
oxcProjectRuntime: oxcProjectRuntimeVersion,
356+
oxcProjectTypes: oxcProjectTypesVersion,
357+
oxcMinify: oxcMinifyVersion,
358+
oxcParser: oxcParserVersion,
359+
oxcTransform: oxcTransformVersion,
181360
});
182361
await updateTestPackage(vitestVersion);
183362
await updateCorePackage(devtoolsVersion);
184363

364+
writeMetaFiles();
365+
185366
console.log('Done!');

.github/workflows/ci.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,7 @@ jobs:
168168
# cargo clippy --all-targets --all-features -- -D warnings
169169
# RUSTDOCFLAGS='-D warnings' cargo doc --no-deps --document-private-items
170170
171-
- uses: crate-ci/typos@02ea592e44b3a53c302f697cddca7641cd051c3d # v1.45.0
171+
- uses: crate-ci/typos@cf5f1c29a8ac336af8568821ec41919923b05a83 # v1.45.1
172172
with:
173173
files: .
174174

0 commit comments

Comments
 (0)