-
Notifications
You must be signed in to change notification settings - Fork 226
Add script for retrieving original source location #2037
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,125 @@ | ||
| /** | ||
| * This scripts helps finding the original source file and line number for a | ||
| * given file and line number in the compiled extension. It currently only | ||
| * works with released extensions. | ||
| * | ||
| * Usage: npx ts-node scripts/source-map.ts <version-number> <filename>:<line>:<column> | ||
| * 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" | ||
| */ | ||
|
|
||
| import { spawnSync } from "child_process"; | ||
| import { basename, resolve } from "path"; | ||
| import { pathExists, readJSON } from "fs-extra"; | ||
| import { SourceMapConsumer } from "source-map"; | ||
|
|
||
| if (process.argv.length !== 4) { | ||
| console.error( | ||
| "Expected 2 arguments - the version number and the filename:line number", | ||
| ); | ||
| } | ||
|
|
||
| const versionNumber = process.argv[2].startsWith("v") | ||
| ? process.argv[2] | ||
| : `v${process.argv[2]}`; | ||
| const filenameAndLine = process.argv[3]; | ||
|
|
||
| async function extractSourceMap() { | ||
| const sourceMapsDirectory = resolve( | ||
| __dirname, | ||
| "..", | ||
| "artifacts", | ||
| "source-maps", | ||
| versionNumber, | ||
| ); | ||
|
|
||
| if (!(await pathExists(sourceMapsDirectory))) { | ||
| console.log("Downloading source maps..."); | ||
|
|
||
| const workflowRuns = runGhJSON<WorkflowRunListItem[]>([ | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. So, this will only work for as long as the workflow runs are still available from actions. Ideally, we can publish the source map as part of the release process and download the release artifact instead.
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Definitely! We'd probably need to create a ZIP file and upload it as a release asset. I think we can do this in a follow-up PR. |
||
| "run", | ||
| "list", | ||
| "--workflow", | ||
| "release.yml", | ||
| "--branch", | ||
| versionNumber, | ||
| "--json", | ||
| "databaseId,number", | ||
| ]); | ||
|
|
||
| if (workflowRuns.length !== 1) { | ||
| throw new Error( | ||
| `Expected exactly one workflow run for ${versionNumber}, got ${workflowRuns.length}`, | ||
| ); | ||
| } | ||
|
|
||
| const workflowRun = workflowRuns[0]; | ||
|
|
||
| runGh([ | ||
| "run", | ||
| "download", | ||
| workflowRun.databaseId.toString(), | ||
| "--name", | ||
| "vscode-codeql-sourcemaps", | ||
| "--dir", | ||
| sourceMapsDirectory, | ||
| ]); | ||
| } | ||
|
|
||
| const [filename, line, column] = filenameAndLine.split(":", 3); | ||
|
|
||
| const fileBasename = basename(filename); | ||
|
|
||
| const sourcemapName = `${fileBasename}.map`; | ||
| const sourcemapPath = resolve(sourceMapsDirectory, sourcemapName); | ||
|
|
||
| if (!(await pathExists(sourcemapPath))) { | ||
| throw new Error(`No source map found for ${fileBasename}`); | ||
| } | ||
|
|
||
| const rawSourceMap = await readJSON(sourcemapPath); | ||
|
|
||
| const originalPosition = await SourceMapConsumer.with( | ||
| rawSourceMap, | ||
| null, | ||
| async function (consumer) { | ||
| return consumer.originalPositionFor({ | ||
| line: parseInt(line), | ||
| column: parseInt(column), | ||
| }); | ||
| }, | ||
| ); | ||
|
|
||
| if (!originalPosition.source) { | ||
| throw new Error(`No source found for ${filenameAndLine}`); | ||
| } | ||
|
|
||
| const originalFilename = resolve(filename, "..", originalPosition.source); | ||
|
|
||
| console.log( | ||
| `${originalFilename}:${originalPosition.line}:${originalPosition.column}`, | ||
| ); | ||
| } | ||
|
|
||
| extractSourceMap().catch((e: unknown) => { | ||
| console.error(e); | ||
| process.exit(2); | ||
| }); | ||
|
|
||
| function runGh(args: readonly string[]): string { | ||
| const gh = spawnSync("gh", args); | ||
| if (gh.status !== 0) { | ||
| throw new Error( | ||
| `Failed to get the source map for ${versionNumber}: ${gh.stderr}`, | ||
| ); | ||
| } | ||
| return gh.stdout.toString("utf-8"); | ||
| } | ||
|
|
||
| function runGhJSON<T>(args: readonly string[]): T { | ||
| return JSON.parse(runGh(args)); | ||
| } | ||
|
|
||
| type WorkflowRunListItem = { | ||
| databaseId: number; | ||
| number: number; | ||
| }; | ||
Uh oh!
There was an error while loading. Please reload this page.