Skip to content

Commit 1198a05

Browse files
committed
Merge remote-tracking branch 'origin/main' into koesie10/upload-sourcemaps-release
2 parents 483d674 + 2b816f9 commit 1198a05

20 files changed

Lines changed: 805 additions & 321 deletions

CONTRIBUTING.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -228,6 +228,13 @@ Pre-recorded scenarios are stored in `./src/mocks/scenarios`. However, it's poss
228228
1. Double-check the `CHANGELOG.md` contains all desired change comments and has the version to be released with date at the top.
229229
* Go through all recent PRs and make sure they are properly accounted for.
230230
* Make sure all changelog entries have links back to their PR(s) if appropriate.
231+
* For picking the new version number, we default to increasing the patch version number, but make our own judgement about whether a change is big enough to warrant a minor version bump. Common reasons for a minor bump could include:
232+
* Making substantial new features available to all users. This can include lifting a feature flag.
233+
* Breakage in compatibility with recent versions of the CLI.
234+
* Minimum required version of VS Code is increased.
235+
* New telemetry events are added.
236+
* Deprecation or removal of commands.
237+
* Accumulation of many changes, none of which are individually big enough to warrant a minor bump, but which together are. This does not include changes which are purely internal to the extension, such as refactoring, or which are only available behind a feature flag.
231238
1. Double-check that the node version we're using matches the one used for VS Code. If it doesn't, you will then need to update the node version in the following files:
232239
* `.nvmrc` - this will enable `nvm` to automatically switch to the correct node version when you're in the project folder
233240
* `.github/workflows/main.yml` - all the "node-version: <version>" settings

extensions/ql-vscode/docs/test-plan.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -244,7 +244,7 @@ This requires running a MRVA query and seeing the results view.
244244
1. By name
245245
2. By results
246246
3. By stars
247-
4. By last commit
247+
4. By last updated
248248
9. Can filter repos
249249
10. Shows correct statistics
250250
1. Total number of results
Lines changed: 193 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,193 @@
1+
/**
2+
* This scripts helps finding the original source file and line number for a
3+
* given file and line number in the compiled extension. It currently only
4+
* works with released extensions.
5+
*
6+
* Usage: npx ts-node scripts/source-map.ts <version-number> <filename>:<line>:<column>
7+
* For example: npx ts-node scripts/source-map.ts v1.7.8 "/Users/user/.vscode/extensions/github.vscode-codeql-1.7.8/out/extension.js:131164:13"
8+
*
9+
* Alternative usage: npx ts-node scripts/source-map.ts <version-number> <multi-line-stacktrace>
10+
* For example: npx ts-node scripts/source-map.ts v1.7.8 'Error: Failed to find CodeQL distribution.
11+
* at CodeQLCliServer.getCodeQlPath (/Users/user/.vscode/extensions/github.vscode-codeql-1.7.8/out/extension.js:131164:13)
12+
* at CodeQLCliServer.launchProcess (/Users/user/.vscode/extensions/github.vscode-codeql-1.7.8/out/extension.js:131169:24)
13+
* at CodeQLCliServer.runCodeQlCliInternal (/Users/user/.vscode/extensions/github.vscode-codeql-1.7.8/out/extension.js:131194:24)
14+
* at CodeQLCliServer.runJsonCodeQlCliCommand (/Users/user/.vscode/extensions/github.vscode-codeql-1.7.8/out/extension.js:131330:20)
15+
* at CodeQLCliServer.resolveRam (/Users/user/.vscode/extensions/github.vscode-codeql-1.7.8/out/extension.js:131455:12)
16+
* at QueryServerClient2.startQueryServerImpl (/Users/user/.vscode/extensions/github.vscode-codeql-1.7.8/out/extension.js:138618:21)'
17+
*/
18+
19+
import { spawnSync } from "child_process";
20+
import { basename, resolve } from "path";
21+
import { pathExists, readJSON } from "fs-extra";
22+
import { RawSourceMap, SourceMapConsumer } from "source-map";
23+
24+
if (process.argv.length !== 4) {
25+
console.error(
26+
"Expected 2 arguments - the version number and the filename:line number",
27+
);
28+
}
29+
30+
const stackLineRegex =
31+
/at (?<name>.*)? \((?<file>.*):(?<line>\d+):(?<column>\d+)\)/gm;
32+
33+
const versionNumber = process.argv[2].startsWith("v")
34+
? process.argv[2]
35+
: `v${process.argv[2]}`;
36+
const stacktrace = process.argv[3];
37+
38+
async function extractSourceMap() {
39+
const sourceMapsDirectory = resolve(
40+
__dirname,
41+
"..",
42+
"artifacts",
43+
"source-maps",
44+
versionNumber,
45+
);
46+
47+
if (!(await pathExists(sourceMapsDirectory))) {
48+
console.log("Downloading source maps...");
49+
50+
const workflowRuns = runGhJSON<WorkflowRunListItem[]>([
51+
"run",
52+
"list",
53+
"--workflow",
54+
"release.yml",
55+
"--branch",
56+
versionNumber,
57+
"--json",
58+
"databaseId,number",
59+
]);
60+
61+
if (workflowRuns.length !== 1) {
62+
throw new Error(
63+
`Expected exactly one workflow run for ${versionNumber}, got ${workflowRuns.length}`,
64+
);
65+
}
66+
67+
const workflowRun = workflowRuns[0];
68+
69+
runGh([
70+
"run",
71+
"download",
72+
workflowRun.databaseId.toString(),
73+
"--name",
74+
"vscode-codeql-sourcemaps",
75+
"--dir",
76+
sourceMapsDirectory,
77+
]);
78+
}
79+
80+
if (stacktrace.includes("at")) {
81+
const rawSourceMaps = new Map<string, RawSourceMap>();
82+
83+
const mappedStacktrace = await replaceAsync(
84+
stacktrace,
85+
stackLineRegex,
86+
async (match, name, file, line, column) => {
87+
if (!rawSourceMaps.has(file)) {
88+
const rawSourceMap: RawSourceMap = await readJSON(
89+
resolve(sourceMapsDirectory, `${basename(file)}.map`),
90+
);
91+
rawSourceMaps.set(file, rawSourceMap);
92+
}
93+
94+
const originalPosition = await SourceMapConsumer.with(
95+
rawSourceMaps.get(file) as RawSourceMap,
96+
null,
97+
async function (consumer) {
98+
return consumer.originalPositionFor({
99+
line: parseInt(line, 10),
100+
column: parseInt(column, 10),
101+
});
102+
},
103+
);
104+
105+
if (!originalPosition.source) {
106+
return match;
107+
}
108+
109+
const originalFilename = resolve(file, "..", originalPosition.source);
110+
111+
return `at ${originalPosition.name ?? name} (${originalFilename}:${
112+
originalPosition.line
113+
}:${originalPosition.column})`;
114+
},
115+
);
116+
117+
console.log(mappedStacktrace);
118+
} else {
119+
// This means it's just a filename:line:column
120+
const [filename, line, column] = stacktrace.split(":", 3);
121+
122+
const fileBasename = basename(filename);
123+
124+
const sourcemapName = `${fileBasename}.map`;
125+
const sourcemapPath = resolve(sourceMapsDirectory, sourcemapName);
126+
127+
if (!(await pathExists(sourcemapPath))) {
128+
throw new Error(`No source map found for ${fileBasename}`);
129+
}
130+
131+
const rawSourceMap: RawSourceMap = await readJSON(sourcemapPath);
132+
133+
const originalPosition = await SourceMapConsumer.with(
134+
rawSourceMap,
135+
null,
136+
async function (consumer) {
137+
return consumer.originalPositionFor({
138+
line: parseInt(line, 10),
139+
column: parseInt(column, 10),
140+
});
141+
},
142+
);
143+
144+
if (!originalPosition.source) {
145+
throw new Error(`No source found for ${stacktrace}`);
146+
}
147+
148+
const originalFilename = resolve(filename, "..", originalPosition.source);
149+
150+
console.log(
151+
`${originalFilename}:${originalPosition.line}:${originalPosition.column}`,
152+
);
153+
}
154+
}
155+
156+
extractSourceMap().catch((e: unknown) => {
157+
console.error(e);
158+
process.exit(2);
159+
});
160+
161+
function runGh(args: readonly string[]): string {
162+
const gh = spawnSync("gh", args);
163+
if (gh.status !== 0) {
164+
throw new Error(
165+
`Failed to get the source map for ${versionNumber}: ${gh.stderr}`,
166+
);
167+
}
168+
return gh.stdout.toString("utf-8");
169+
}
170+
171+
function runGhJSON<T>(args: readonly string[]): T {
172+
return JSON.parse(runGh(args));
173+
}
174+
175+
type WorkflowRunListItem = {
176+
databaseId: number;
177+
number: number;
178+
};
179+
180+
async function replaceAsync(
181+
str: string,
182+
regex: RegExp,
183+
replacer: (substring: string, ...args: any[]) => Promise<string>,
184+
) {
185+
const promises: Array<Promise<string>> = [];
186+
str.replace(regex, (match, ...args) => {
187+
const promise = replacer(match, ...args);
188+
promises.push(promise);
189+
return match;
190+
});
191+
const data = await Promise.all(promises);
192+
return str.replace(regex, () => data.shift() as string);
193+
}

extensions/ql-vscode/src/config.ts

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -56,15 +56,6 @@ export class Setting {
5656
.getConfiguration(this.parent.qualifiedName)
5757
.update(this.name, value, target);
5858
}
59-
60-
inspect<T>(): InspectionResult<T> | undefined {
61-
if (this.parent === undefined) {
62-
throw new Error("Cannot update the value of a root setting.");
63-
}
64-
return workspace
65-
.getConfiguration(this.parent.qualifiedName)
66-
.inspect(this.name);
67-
}
6859
}
6960

7061
export interface InspectionResult<T> {

0 commit comments

Comments
 (0)