Skip to content

Commit 65b8d9e

Browse files
oratisclaude
andcommitted
fix(vscode): keep @types/vscode at the engine floor, and pin it there
The typescript group swept `@types/vscode` from ^1.85.0 to ^1.125.0 along with typescript-eslint, and `vsce package` refused the build: ERROR @types/vscode ^1.125.0 greater than engines.vscode ^1.85.0 That check is right. `engines.vscode` is the OLDEST editor this extension supports; types newer than it let a call added in a later VS Code typecheck cleanly and then fail on the editor we promised to run on. Taking the bump means dropping every VS Code between 1.85 and 1.125, which is a support decision, not a dependency update. typescript-eslint ^8.67.0 is kept — it was the half of the group that had nothing wrong with it. Pinned exactly rather than restored to `^1.85.0`: the caret was already resolving to 1.120.0 on main, so the compiler was seeing 35 minor versions of API the extension does not claim to support. Verified the floor is honest — `apps/vscode` typechecks against exactly 1.85.0 with no errors — so the pin costs nothing and makes the declaration enforceable. Guarded twice: dependabot is told to ignore the dependency, with the reason written down, and `scripts/vscode-types-engine.test.ts` fails the unit suite in seconds rather than waiting for `release:check` to fail minutes into a full workspace build. release:check exits 0; VSIX packages at 199.19 KB. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
1 parent 816ef02 commit 65b8d9e

4 files changed

Lines changed: 80 additions & 6 deletions

File tree

.github/dependabot.yml

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,18 @@ updates:
1212
interval: weekly
1313
day: monday
1414
open-pull-requests-limit: 5
15+
ignore:
16+
# `@types/vscode` tracks `engines.vscode`, not the latest release, and is
17+
# pinned exactly (no caret) so the compiler enforces the floor instead of
18+
# merely declaring it. `engines.vscode` is the OLDEST editor the extension
19+
# supports; types newer than that let a call added in a later VS Code
20+
# typecheck cleanly and then fail on the editor we promised to run on.
21+
# `vsce package` refuses the mismatch outright:
22+
# ERROR @types/vscode ^1.125.0 greater than engines.vscode ^1.85.0
23+
# Taking such a bump means dropping every VS Code in between — a support
24+
# decision, not a dependency update. Raise `engines.vscode` deliberately
25+
# and move the types with it, together.
26+
- dependency-name: '@types/vscode'
1527
groups:
1628
typescript:
1729
patterns:

apps/vscode/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,7 @@
124124
},
125125
"devDependencies": {
126126
"@types/node": "^22.10.0",
127-
"@types/vscode": "^1.125.0",
127+
"@types/vscode": "1.85.0",
128128
"@vscode/vsce": "^3.9.2",
129129
"esbuild": "^0.21.5",
130130
"typescript": "^5.7.0",

pnpm-lock.yaml

Lines changed: 5 additions & 5 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
// `@types/vscode` may never be newer than `engines.vscode`.
2+
//
3+
// `engines.vscode` states the OLDEST VS Code the extension supports. The types
4+
// have to match that floor, not the newest release: compiling against 1.125's
5+
// API surface while claiming to run on 1.85 lets an editor-version-gated call
6+
// typecheck cleanly and then throw `undefined is not a function` on the older
7+
// editor nobody tested.
8+
//
9+
// `vsce package` already enforces this and refuses to build:
10+
//
11+
// ERROR @types/vscode ^1.125.0 greater than engines.vscode ^1.85.0
12+
//
13+
// but only inside `pnpm release:check`, several minutes into CI and after a
14+
// full workspace build. A dependency bot proposing the newer types (#262) is
15+
// the ordinary way this happens, so catch it in the unit suite where the
16+
// message arrives in seconds — and where it names the reason rather than the
17+
// symptom.
18+
//
19+
// Fixing it is not "take the bump": raising `engines.vscode` drops every VS
20+
// Code between the two versions, which is a support decision to make on
21+
// purpose. Move both together when you make it.
22+
23+
import { readFileSync } from 'node:fs';
24+
import { resolve } from 'node:path';
25+
import { describe, expect, it } from 'vitest';
26+
27+
const root = resolve(import.meta.dirname, '..');
28+
const pkg = JSON.parse(readFileSync(resolve(root, 'apps/vscode/package.json'), 'utf8')) as {
29+
engines: { vscode: string };
30+
devDependencies: Record<string, string>;
31+
};
32+
33+
/** `^1.85.0` → `[1, 85, 0]`. Ranges here are always a caret over an exact version. */
34+
function floor(range: string): number[] {
35+
const match = /(\d+)\.(\d+)\.(\d+)/.exec(range);
36+
if (!match) throw new Error(`cannot read a version out of ${JSON.stringify(range)}`);
37+
return [Number(match[1]), Number(match[2]), Number(match[3])];
38+
}
39+
40+
function compare(a: number[], b: number[]): number {
41+
for (let i = 0; i < 3; i++) {
42+
const diff = (a[i] ?? 0) - (b[i] ?? 0);
43+
if (diff !== 0) return diff;
44+
}
45+
return 0;
46+
}
47+
48+
describe('the VS Code extension', () => {
49+
it('does not compile against a newer API than it claims to run on', () => {
50+
const engine = pkg.engines.vscode;
51+
const types = pkg.devDependencies['@types/vscode'];
52+
expect(types, 'apps/vscode must declare @types/vscode').toBeTypeOf('string');
53+
54+
expect(
55+
compare(floor(types!), floor(engine)),
56+
`@types/vscode ${types} is newer than engines.vscode ${engine}. ` +
57+
`The types must match the oldest supported editor, so either pin them back ` +
58+
`or raise engines.vscode deliberately — raising it drops support for every ` +
59+
`VS Code in between.`,
60+
).toBeLessThanOrEqual(0);
61+
});
62+
});

0 commit comments

Comments
 (0)