Compare commits
37 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6d64c8f031 | ||
|
|
1216fce853 | ||
|
|
c598306f49 | ||
|
|
4f8d6e310c | ||
|
|
894eb7046e | ||
|
|
3d6515e807 | ||
|
|
068d461c14 | ||
|
|
8e20d01b4e | ||
|
|
8aaa2492f2 | ||
|
|
c9a649f974 | ||
|
|
f07d9cff9b | ||
|
|
b7bfd9ea85 | ||
|
|
25f0e3ccab | ||
|
|
e19addec60 | ||
|
|
a5bc25e211 | ||
|
|
c90659fd92 | ||
|
|
30b7fe7472 | ||
|
|
d54fbdf4e6 | ||
|
|
6d7b02583d | ||
|
|
51906cbbda | ||
|
|
d3da9d30f4 | ||
|
|
9b9a0cb64a | ||
|
|
1dde5af591 | ||
|
|
4312d35743 | ||
|
|
2dcdbcbd32 | ||
|
|
e8e50c4381 | ||
|
|
0e6d85374f | ||
|
|
54789613dc | ||
|
|
43b3f72a41 | ||
|
|
13742a4e9e | ||
|
|
6bd7f0ae12 | ||
|
|
fc51b336fa | ||
|
|
df16d1ab1d | ||
|
|
b661b2be97 | ||
|
|
2d39bee416 | ||
|
|
56eeb1badb | ||
|
|
d547f81a55 |
2
.github/pull_request_template.md
vendored
2
.github/pull_request_template.md
vendored
@@ -9,4 +9,4 @@ Replace this with a description of the changes your pull request makes.
|
||||
|
||||
- [ ] [CHANGELOG.md](https://github.com/github/vscode-codeql/blob/main/extensions/ql-vscode/CHANGELOG.md) has been updated to incorporate all user visible changes made by this pull request.
|
||||
- [ ] Issues have been created for any UI or other user-facing changes made by this pull request.
|
||||
- [ ] `@github/docs-content-codeql` has been cc'd in all issues for UI or other user-facing changes made by this pull request.
|
||||
- [ ] _[Maintainers only]_ If this pull request makes user-facing changes that require documentation changes, open a corresponding docs pull request in the [github/codeql](https://github.com/github/codeql/tree/main/docs/codeql/codeql-for-visual-studio-code) repo and add the `ready-for-doc-review` label there.
|
||||
|
||||
2
.github/workflows/main.yml
vendored
2
.github/workflows/main.yml
vendored
@@ -135,7 +135,7 @@ jobs:
|
||||
strategy:
|
||||
matrix:
|
||||
os: [ubuntu-latest, windows-latest]
|
||||
version: ['v2.3.3', 'v2.4.6', 'v2.5.9', 'v2.6.3', 'v2.7.3', 'nightly']
|
||||
version: ['v2.3.3', 'v2.4.6', 'v2.5.9', 'v2.6.3', 'v2.7.6', 'nightly']
|
||||
env:
|
||||
CLI_VERSION: ${{ matrix.version }}
|
||||
NIGHTLY_URL: ${{ needs.find-nightly.outputs.url }}
|
||||
|
||||
16
.vscode/launch.json
vendored
16
.vscode/launch.json
vendored
@@ -59,7 +59,9 @@
|
||||
"runtimeExecutable": "${execPath}",
|
||||
"args": [
|
||||
"--extensionDevelopmentPath=${workspaceRoot}/extensions/ql-vscode",
|
||||
"--extensionTestsPath=${workspaceRoot}/extensions/ql-vscode/out/vscode-tests/no-workspace/index"
|
||||
"--extensionTestsPath=${workspaceRoot}/extensions/ql-vscode/out/vscode-tests/no-workspace/index",
|
||||
"--disable-extensions",
|
||||
"--disable-gpu"
|
||||
],
|
||||
"stopOnEntry": false,
|
||||
"sourceMaps": true,
|
||||
@@ -75,6 +77,8 @@
|
||||
"args": [
|
||||
"--extensionDevelopmentPath=${workspaceRoot}/extensions/ql-vscode",
|
||||
"--extensionTestsPath=${workspaceRoot}/extensions/ql-vscode/out/vscode-tests/minimal-workspace/index",
|
||||
"--disable-extensions",
|
||||
"--disable-gpu",
|
||||
"${workspaceRoot}/extensions/ql-vscode/test/data"
|
||||
],
|
||||
"stopOnEntry": false,
|
||||
@@ -91,8 +95,16 @@
|
||||
"args": [
|
||||
"--extensionDevelopmentPath=${workspaceRoot}/extensions/ql-vscode",
|
||||
"--extensionTestsPath=${workspaceRoot}/extensions/ql-vscode/out/vscode-tests/cli-integration/index",
|
||||
"--disable-gpu",
|
||||
"--disable-extension",
|
||||
"eamodio.gitlens",
|
||||
"--disable-extension",
|
||||
"github.codespaces",
|
||||
"--disable-extension",
|
||||
"github.copilot",
|
||||
"${workspaceRoot}/extensions/ql-vscode/src/vscode-tests/cli-integration/data",
|
||||
// Add a path to a checked out instance of the codeql repository so the libraries are
|
||||
// Uncomment the last line and modify the path to a checked out
|
||||
// instance of the codeql repository so the libraries are
|
||||
// available in the workspace for the tests.
|
||||
// "${workspaceRoot}/../codeql"
|
||||
],
|
||||
|
||||
@@ -1,5 +1,10 @@
|
||||
# CodeQL for Visual Studio Code: Changelog
|
||||
|
||||
## 1.5.10 - 25 January 2022
|
||||
|
||||
- Fix a bug where the results view moved column even when it was already visible. [#1070](https://github.com/github/vscode-codeql/pull/1070)
|
||||
- Add packaging-related commands. _CodeQL: Download Packs_ downloads query packs from the package registry that can be run locally, and _CodeQL: Install Pack Dependencies_ installs dependencies for packs in your workspace. [#1076](https://github.com/github/vscode-codeql/pull/1076)
|
||||
|
||||
## 1.5.9 - 17 December 2021
|
||||
|
||||
- Avoid creating a third column when opening the results view. The results view will always open to the right of the active editor, unless the active editor is in the rightmost editor column. In that case open in the leftmost column. [#1037](https://github.com/github/vscode-codeql/pull/1037)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import * as gulp from 'gulp';
|
||||
import { compileTypeScript, watchTypeScript, copyViewCss } from './typescript';
|
||||
import { compileTypeScript, watchTypeScript, copyViewCss, cleanOutput } from './typescript';
|
||||
import { compileTextMateGrammar } from './textmate';
|
||||
import { copyTestData } from './tests';
|
||||
import { compileView } from './webpack';
|
||||
@@ -7,9 +7,12 @@ import { packageExtension } from './package';
|
||||
import { injectAppInsightsKey } from './appInsights';
|
||||
|
||||
export const buildWithoutPackage =
|
||||
gulp.parallel(
|
||||
compileTypeScript, compileTextMateGrammar, compileView, copyTestData, copyViewCss
|
||||
gulp.series(
|
||||
cleanOutput,
|
||||
gulp.parallel(
|
||||
compileTypeScript, compileTextMateGrammar, compileView, copyTestData, copyViewCss
|
||||
)
|
||||
);
|
||||
|
||||
export { compileTextMateGrammar, watchTypeScript, compileTypeScript, copyTestData, injectAppInsightsKey };
|
||||
export { cleanOutput, compileTextMateGrammar, watchTypeScript, compileTypeScript, copyTestData, injectAppInsightsKey };
|
||||
export default gulp.series(buildWithoutPackage, injectAppInsightsKey, packageExtension);
|
||||
|
||||
@@ -2,6 +2,7 @@ import * as colors from 'ansi-colors';
|
||||
import * as gulp from 'gulp';
|
||||
import * as sourcemaps from 'gulp-sourcemaps';
|
||||
import * as ts from 'gulp-typescript';
|
||||
import * as del from 'del';
|
||||
|
||||
function goodReporter(): ts.reporter.Reporter {
|
||||
return {
|
||||
@@ -20,6 +21,10 @@ function goodReporter(): ts.reporter.Reporter {
|
||||
|
||||
const tsProject = ts.createProject('tsconfig.json');
|
||||
|
||||
export function cleanOutput() {
|
||||
return tsProject.projectDirectory ? del(tsProject.projectDirectory + '/out/*') : Promise.resolve();
|
||||
}
|
||||
|
||||
export function compileTypeScript() {
|
||||
return tsProject.src()
|
||||
.pipe(sourcemaps.init())
|
||||
|
||||
185
extensions/ql-vscode/package-lock.json
generated
185
extensions/ql-vscode/package-lock.json
generated
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "vscode-codeql",
|
||||
"version": "1.5.9",
|
||||
"version": "1.5.10",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "vscode-codeql",
|
||||
"version": "1.5.8",
|
||||
"version": "1.5.10",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@octokit/rest": "^18.5.6",
|
||||
@@ -16,7 +16,7 @@
|
||||
"glob-promise": "^3.4.0",
|
||||
"js-yaml": "^3.14.0",
|
||||
"minimist": "~1.2.5",
|
||||
"node-fetch": "~2.6.0",
|
||||
"node-fetch": "~2.6.7",
|
||||
"path-browserify": "^1.0.1",
|
||||
"react": "^16.8.6",
|
||||
"react-dom": "^16.8.6",
|
||||
@@ -40,6 +40,7 @@
|
||||
"@types/chai-as-promised": "~7.1.2",
|
||||
"@types/child-process-promise": "^2.2.1",
|
||||
"@types/classnames": "~2.2.9",
|
||||
"@types/del": "^4.0.0",
|
||||
"@types/fs-extra": "^9.0.6",
|
||||
"@types/glob": "^7.1.1",
|
||||
"@types/google-protobuf": "^3.2.7",
|
||||
@@ -73,6 +74,7 @@
|
||||
"chai": "^4.2.0",
|
||||
"chai-as-promised": "~7.1.1",
|
||||
"css-loader": "~3.1.0",
|
||||
"del": "^6.0.0",
|
||||
"eslint": "~6.8.0",
|
||||
"eslint-plugin-react": "~7.19.0",
|
||||
"glob": "^7.1.4",
|
||||
@@ -503,6 +505,16 @@
|
||||
"integrity": "sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@types/del": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@types/del/-/del-4.0.0.tgz",
|
||||
"integrity": "sha512-LDE5atstX5kKnTobWknpmGHC52DH/tp8pIVsD2SSxaOFqW3AQr0EpdzYIfkZ331xe7l9Vn9NlJsBG6viU3mjBA==",
|
||||
"deprecated": "This is a stub types definition. del provides its own type definitions, so you do not need this installed.",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"del": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/eslint": {
|
||||
"version": "7.2.7",
|
||||
"resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-7.2.7.tgz",
|
||||
@@ -3336,6 +3348,43 @@
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/del": {
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/del/-/del-6.0.0.tgz",
|
||||
"integrity": "sha512-1shh9DQ23L16oXSZKB2JxpL7iMy2E0S9d517ptA1P8iw0alkPtQcrKH7ru31rYtKwF499HkTu+DRzq3TCKDFRQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"globby": "^11.0.1",
|
||||
"graceful-fs": "^4.2.4",
|
||||
"is-glob": "^4.0.1",
|
||||
"is-path-cwd": "^2.2.0",
|
||||
"is-path-inside": "^3.0.2",
|
||||
"p-map": "^4.0.0",
|
||||
"rimraf": "^3.0.2",
|
||||
"slash": "^3.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/del/node_modules/rimraf": {
|
||||
"version": "3.0.2",
|
||||
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
|
||||
"integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"glob": "^7.1.3"
|
||||
},
|
||||
"bin": {
|
||||
"rimraf": "bin.js"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/isaacs"
|
||||
}
|
||||
},
|
||||
"node_modules/delayed-stream": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
|
||||
@@ -5886,6 +5935,24 @@
|
||||
"integrity": "sha1-iVJojF7C/9awPsyF52ngKQMINHA=",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/is-path-cwd": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-2.2.0.tgz",
|
||||
"integrity": "sha512-w942bTcih8fdJPJmQHFzkS76NEP8Kzzvmw92cXsazb8intwLqPibPPdXf4ANdKV3rYMuuQYGIWtvz9JilB3NFQ==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/is-path-inside": {
|
||||
"version": "3.0.3",
|
||||
"resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz",
|
||||
"integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/is-plain-obj": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz",
|
||||
@@ -7611,11 +7678,22 @@
|
||||
}
|
||||
},
|
||||
"node_modules/node-fetch": {
|
||||
"version": "2.6.1",
|
||||
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.1.tgz",
|
||||
"integrity": "sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw==",
|
||||
"version": "2.6.7",
|
||||
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz",
|
||||
"integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==",
|
||||
"dependencies": {
|
||||
"whatwg-url": "^5.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": "4.x || >=6.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"encoding": "^0.1.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"encoding": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/node-releases": {
|
||||
@@ -10373,6 +10451,11 @@
|
||||
"xtend": "~4.0.1"
|
||||
}
|
||||
},
|
||||
"node_modules/tr46": {
|
||||
"version": "0.0.3",
|
||||
"resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz",
|
||||
"integrity": "sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o="
|
||||
},
|
||||
"node_modules/traverse": {
|
||||
"version": "0.3.9",
|
||||
"resolved": "https://registry.npmjs.org/traverse/-/traverse-0.3.9.tgz",
|
||||
@@ -11235,6 +11318,11 @@
|
||||
"node": ">=10.13.0"
|
||||
}
|
||||
},
|
||||
"node_modules/webidl-conversions": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz",
|
||||
"integrity": "sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE="
|
||||
},
|
||||
"node_modules/webpack": {
|
||||
"version": "5.28.0",
|
||||
"resolved": "https://registry.npmjs.org/webpack/-/webpack-5.28.0.tgz",
|
||||
@@ -11546,6 +11634,15 @@
|
||||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/whatwg-url": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz",
|
||||
"integrity": "sha1-lmRU6HZUYuN2RNNib2dCzotwll0=",
|
||||
"dependencies": {
|
||||
"tr46": "~0.0.3",
|
||||
"webidl-conversions": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/which": {
|
||||
"version": "1.3.1",
|
||||
"resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz",
|
||||
@@ -12253,6 +12350,15 @@
|
||||
"integrity": "sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ==",
|
||||
"dev": true
|
||||
},
|
||||
"@types/del": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@types/del/-/del-4.0.0.tgz",
|
||||
"integrity": "sha512-LDE5atstX5kKnTobWknpmGHC52DH/tp8pIVsD2SSxaOFqW3AQr0EpdzYIfkZ331xe7l9Vn9NlJsBG6viU3mjBA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"del": "*"
|
||||
}
|
||||
},
|
||||
"@types/eslint": {
|
||||
"version": "7.2.7",
|
||||
"resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-7.2.7.tgz",
|
||||
@@ -14609,6 +14715,33 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"del": {
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/del/-/del-6.0.0.tgz",
|
||||
"integrity": "sha512-1shh9DQ23L16oXSZKB2JxpL7iMy2E0S9d517ptA1P8iw0alkPtQcrKH7ru31rYtKwF499HkTu+DRzq3TCKDFRQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"globby": "^11.0.1",
|
||||
"graceful-fs": "^4.2.4",
|
||||
"is-glob": "^4.0.1",
|
||||
"is-path-cwd": "^2.2.0",
|
||||
"is-path-inside": "^3.0.2",
|
||||
"p-map": "^4.0.0",
|
||||
"rimraf": "^3.0.2",
|
||||
"slash": "^3.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"rimraf": {
|
||||
"version": "3.0.2",
|
||||
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
|
||||
"integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"glob": "^7.1.3"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"delayed-stream": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
|
||||
@@ -16684,6 +16817,18 @@
|
||||
"integrity": "sha1-iVJojF7C/9awPsyF52ngKQMINHA=",
|
||||
"dev": true
|
||||
},
|
||||
"is-path-cwd": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-2.2.0.tgz",
|
||||
"integrity": "sha512-w942bTcih8fdJPJmQHFzkS76NEP8Kzzvmw92cXsazb8intwLqPibPPdXf4ANdKV3rYMuuQYGIWtvz9JilB3NFQ==",
|
||||
"dev": true
|
||||
},
|
||||
"is-path-inside": {
|
||||
"version": "3.0.3",
|
||||
"resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz",
|
||||
"integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==",
|
||||
"dev": true
|
||||
},
|
||||
"is-plain-obj": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz",
|
||||
@@ -18055,9 +18200,12 @@
|
||||
}
|
||||
},
|
||||
"node-fetch": {
|
||||
"version": "2.6.1",
|
||||
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.1.tgz",
|
||||
"integrity": "sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw=="
|
||||
"version": "2.6.7",
|
||||
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz",
|
||||
"integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==",
|
||||
"requires": {
|
||||
"whatwg-url": "^5.0.0"
|
||||
}
|
||||
},
|
||||
"node-releases": {
|
||||
"version": "1.1.71",
|
||||
@@ -20275,6 +20423,11 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"tr46": {
|
||||
"version": "0.0.3",
|
||||
"resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz",
|
||||
"integrity": "sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o="
|
||||
},
|
||||
"traverse": {
|
||||
"version": "0.3.9",
|
||||
"resolved": "https://registry.npmjs.org/traverse/-/traverse-0.3.9.tgz",
|
||||
@@ -20959,6 +21112,11 @@
|
||||
"graceful-fs": "^4.1.2"
|
||||
}
|
||||
},
|
||||
"webidl-conversions": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz",
|
||||
"integrity": "sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE="
|
||||
},
|
||||
"webpack": {
|
||||
"version": "5.28.0",
|
||||
"resolved": "https://registry.npmjs.org/webpack/-/webpack-5.28.0.tgz",
|
||||
@@ -21168,6 +21326,15 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"whatwg-url": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz",
|
||||
"integrity": "sha1-lmRU6HZUYuN2RNNib2dCzotwll0=",
|
||||
"requires": {
|
||||
"tr46": "~0.0.3",
|
||||
"webidl-conversions": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"which": {
|
||||
"version": "1.3.1",
|
||||
"resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz",
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
"description": "CodeQL for Visual Studio Code",
|
||||
"author": "GitHub",
|
||||
"private": true,
|
||||
"version": "1.5.9",
|
||||
"version": "1.5.10",
|
||||
"publisher": "GitHub",
|
||||
"license": "MIT",
|
||||
"icon": "media/VS-marketplace-CodeQL-icon.png",
|
||||
@@ -19,7 +19,8 @@
|
||||
"Programming Languages"
|
||||
],
|
||||
"extensionDependencies": [
|
||||
"hbenl.vscode-test-explorer"
|
||||
"hbenl.vscode-test-explorer",
|
||||
"ms-vscode.test-adapter-converter"
|
||||
],
|
||||
"capabilities": {
|
||||
"untrustedWorkspaces": {
|
||||
@@ -289,6 +290,10 @@
|
||||
"command": "codeQL.runRemoteQuery",
|
||||
"title": "CodeQL: Run Remote Query"
|
||||
},
|
||||
{
|
||||
"command": "codeQL.showFakeRemoteQueryResults",
|
||||
"title": "CodeQL: [Internal] Show fake remote query results"
|
||||
},
|
||||
{
|
||||
"command": "codeQL.runQueries",
|
||||
"title": "CodeQL: Run Queries in Selected Files"
|
||||
@@ -369,6 +374,14 @@
|
||||
"command": "codeQL.clearCache",
|
||||
"title": "CodeQL: Clear Cache"
|
||||
},
|
||||
{
|
||||
"command": "codeQL.installPackDependencies",
|
||||
"title": "CodeQL: Install Pack Dependencies"
|
||||
},
|
||||
{
|
||||
"command": "codeQL.downloadPacks",
|
||||
"title": "CodeQL: Download Packs"
|
||||
},
|
||||
{
|
||||
"command": "codeQLDatabases.setCurrentDatabase",
|
||||
"title": "Set Current Database"
|
||||
@@ -751,6 +764,10 @@
|
||||
"command": "codeQL.runRemoteQuery",
|
||||
"when": "config.codeQL.canary && editorLangId == ql && resourceExtname == .ql"
|
||||
},
|
||||
{
|
||||
"command": "codeQL.showFakeRemoteQueryResults",
|
||||
"when": "config.codeQL.canary"
|
||||
},
|
||||
{
|
||||
"command": "codeQL.runQueries",
|
||||
"when": "false"
|
||||
@@ -992,7 +1009,7 @@
|
||||
"glob-promise": "^3.4.0",
|
||||
"js-yaml": "^3.14.0",
|
||||
"minimist": "~1.2.5",
|
||||
"node-fetch": "~2.6.0",
|
||||
"node-fetch": "~2.6.7",
|
||||
"path-browserify": "^1.0.1",
|
||||
"react": "^16.8.6",
|
||||
"react-dom": "^16.8.6",
|
||||
@@ -1016,6 +1033,7 @@
|
||||
"@types/chai-as-promised": "~7.1.2",
|
||||
"@types/child-process-promise": "^2.2.1",
|
||||
"@types/classnames": "~2.2.9",
|
||||
"@types/del": "^4.0.0",
|
||||
"@types/fs-extra": "^9.0.6",
|
||||
"@types/glob": "^7.1.1",
|
||||
"@types/google-protobuf": "^3.2.7",
|
||||
@@ -1049,6 +1067,7 @@
|
||||
"chai": "^4.2.0",
|
||||
"chai-as-promised": "~7.1.1",
|
||||
"css-loader": "~3.1.0",
|
||||
"del": "^6.0.0",
|
||||
"eslint": "~6.8.0",
|
||||
"eslint-plugin-react": "~7.19.0",
|
||||
"glob": "^7.1.4",
|
||||
|
||||
@@ -845,6 +845,14 @@ export class CodeQLCliServer implements Disposable {
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Downloads a specified pack.
|
||||
* @param packs The `<package-scope/name[@version]>` of the packs to download.
|
||||
*/
|
||||
async packDownload(packs: string[]) {
|
||||
return this.runJsonCodeQlCliCommand(['pack', 'download'], packs, 'Downloading packs');
|
||||
}
|
||||
|
||||
async packInstall(dir: string) {
|
||||
return this.runJsonCodeQlCliCommand(['pack', 'install'], [dir], 'Installing pack dependencies');
|
||||
}
|
||||
@@ -1191,6 +1199,11 @@ export class CliVersionConstraint {
|
||||
*/
|
||||
public static CLI_VERSION_WITH_OLD_EVAL_STATS = new SemVer('2.7.4');
|
||||
|
||||
/**
|
||||
* CLI version where packaging was introduced.
|
||||
*/
|
||||
public static CLI_VERSION_WITH_PACKAGING = new SemVer('2.6.0');
|
||||
|
||||
constructor(private readonly cli: CodeQLCliServer) {
|
||||
/**/
|
||||
}
|
||||
@@ -1242,4 +1255,8 @@ export class CliVersionConstraint {
|
||||
async supportsOldEvalStats() {
|
||||
return this.isVersionAtLeast(CliVersionConstraint.CLI_VERSION_WITH_OLD_EVAL_STATS);
|
||||
}
|
||||
|
||||
async supportsPackaging() {
|
||||
return this.isVersionAtLeast(CliVersionConstraint.CLI_VERSION_WITH_PACKAGING);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -141,7 +141,7 @@ export class CompareInterfaceManager extends DisposableObject {
|
||||
panel.webview.html = getHtmlForWebview(
|
||||
panel.webview,
|
||||
scriptPathOnDisk,
|
||||
stylesheetPathOnDisk
|
||||
[stylesheetPathOnDisk]
|
||||
);
|
||||
panel.webview.onDidReceiveMessage(
|
||||
async (e) => this.handleMsgFromView(e),
|
||||
|
||||
@@ -81,6 +81,10 @@ import { Credentials } from './authentication';
|
||||
import { RemoteQueriesManager } from './remote-queries/remote-queries-manager';
|
||||
import { RemoteQuery } from './remote-queries/remote-query';
|
||||
import { URLSearchParams } from 'url';
|
||||
import { RemoteQueriesInterfaceManager } from './remote-queries/remote-queries-interface';
|
||||
import { sampleRemoteQuery, sampleRemoteQueryResult } from './remote-queries/sample-data';
|
||||
import { handleDownloadPacks, handleInstallPackDependencies } from './packaging';
|
||||
import { AnalysesResultsManager } from './remote-queries/analyses-results-manager';
|
||||
|
||||
/**
|
||||
* extension.ts
|
||||
@@ -812,6 +816,13 @@ async function activateWithInstalledDistribution(
|
||||
await rqm.monitorRemoteQuery(query, token);
|
||||
}));
|
||||
|
||||
ctx.subscriptions.push(
|
||||
commandRunner('codeQL.showFakeRemoteQueryResults', async () => {
|
||||
const analysisResultsManager = new AnalysesResultsManager(ctx, logger);
|
||||
const rqim = new RemoteQueriesInterfaceManager(ctx, logger, analysisResultsManager);
|
||||
await rqim.showResults(sampleRemoteQuery, sampleRemoteQueryResult);
|
||||
}));
|
||||
|
||||
ctx.subscriptions.push(
|
||||
commandRunner(
|
||||
'codeQL.openReferencedFile',
|
||||
@@ -914,6 +925,26 @@ async function activateWithInstalledDistribution(
|
||||
}
|
||||
}));
|
||||
|
||||
ctx.subscriptions.push(
|
||||
commandRunnerWithProgress('codeQL.installPackDependencies', async (
|
||||
progress: ProgressCallback
|
||||
) =>
|
||||
await handleInstallPackDependencies(cliServer, progress),
|
||||
{
|
||||
title: 'Installing pack dependencies',
|
||||
}
|
||||
));
|
||||
|
||||
ctx.subscriptions.push(
|
||||
commandRunnerWithProgress('codeQL.downloadPacks', async (
|
||||
progress: ProgressCallback
|
||||
) =>
|
||||
await handleDownloadPacks(cliServer, progress),
|
||||
{
|
||||
title: 'Downloading packs',
|
||||
}
|
||||
));
|
||||
|
||||
commands.registerCommand('codeQL.showLogs', () => {
|
||||
logger.show();
|
||||
});
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import * as crypto from 'crypto';
|
||||
import * as os from 'os';
|
||||
import {
|
||||
Uri,
|
||||
Location,
|
||||
@@ -117,13 +118,19 @@ export function tryResolveLocation(
|
||||
export function getHtmlForWebview(
|
||||
webview: Webview,
|
||||
scriptUriOnDisk: Uri,
|
||||
stylesheetUriOnDisk: Uri
|
||||
stylesheetUrisOnDisk: Uri[],
|
||||
): string {
|
||||
// Convert the on-disk URIs into webview URIs.
|
||||
const scriptWebviewUri = webview.asWebviewUri(scriptUriOnDisk);
|
||||
const stylesheetWebviewUri = webview.asWebviewUri(stylesheetUriOnDisk);
|
||||
const stylesheetWebviewUris = stylesheetUrisOnDisk.map(stylesheetUriOnDisk =>
|
||||
webview.asWebviewUri(stylesheetUriOnDisk));
|
||||
|
||||
// Use a nonce in the content security policy to uniquely identify the above resources.
|
||||
const nonce = getNonce();
|
||||
|
||||
const stylesheetsHtmlLines = stylesheetWebviewUris.map(stylesheetWebviewUri =>
|
||||
`<link nonce="${nonce}" rel="stylesheet" href="${stylesheetWebviewUri}">`);
|
||||
|
||||
/*
|
||||
* Content security policy:
|
||||
* default-src: allow nothing by default.
|
||||
@@ -137,7 +144,7 @@ export function getHtmlForWebview(
|
||||
<head>
|
||||
<meta http-equiv="Content-Security-Policy"
|
||||
content="default-src 'none'; script-src 'nonce-${nonce}'; style-src 'nonce-${nonce}'; connect-src ${webview.cspSource};">
|
||||
<link nonce="${nonce}" rel="stylesheet" href="${stylesheetWebviewUri}">
|
||||
${stylesheetsHtmlLines.join(` ${os.EOL}`)}
|
||||
</head>
|
||||
<body>
|
||||
<div id=root>
|
||||
|
||||
@@ -193,7 +193,7 @@ export class InterfaceManager extends DisposableObject {
|
||||
panel.webview.html = getHtmlForWebview(
|
||||
panel.webview,
|
||||
scriptPathOnDisk,
|
||||
stylesheetPathOnDisk
|
||||
[stylesheetPathOnDisk]
|
||||
);
|
||||
panel.webview.onDidReceiveMessage(
|
||||
async (e) => this.handleMsgFromView(e),
|
||||
@@ -379,27 +379,29 @@ export class InterfaceManager extends DisposableObject {
|
||||
|
||||
const panel = this.getPanel();
|
||||
await this.waitForPanelLoaded();
|
||||
if (forceReveal === WebviewReveal.Forced) {
|
||||
panel.reveal(undefined, true);
|
||||
} else if (!panel.visible) {
|
||||
// The results panel exists, (`.getPanel()` guarantees it) but
|
||||
// is not visible; it's in a not-currently-viewed tab. Show a
|
||||
// more asynchronous message to not so abruptly interrupt
|
||||
// user's workflow by immediately revealing the panel.
|
||||
const showButton = 'View Results';
|
||||
const queryName = results.queryName;
|
||||
const resultPromise = vscode.window.showInformationMessage(
|
||||
`Finished running query ${queryName.length > 0 ? ` "${queryName}"` : ''
|
||||
}.`,
|
||||
showButton
|
||||
);
|
||||
// Address this click asynchronously so we still update the
|
||||
// query history immediately.
|
||||
void resultPromise.then((result) => {
|
||||
if (result === showButton) {
|
||||
panel.reveal();
|
||||
}
|
||||
});
|
||||
if (!panel.visible) {
|
||||
if (forceReveal === WebviewReveal.Forced) {
|
||||
panel.reveal(undefined, true);
|
||||
} else {
|
||||
// The results panel exists, (`.getPanel()` guarantees it) but
|
||||
// is not visible; it's in a not-currently-viewed tab. Show a
|
||||
// more asynchronous message to not so abruptly interrupt
|
||||
// user's workflow by immediately revealing the panel.
|
||||
const showButton = 'View Results';
|
||||
const queryName = results.queryName;
|
||||
const resultPromise = vscode.window.showInformationMessage(
|
||||
`Finished running query ${queryName.length > 0 ? ` "${queryName}"` : ''
|
||||
}.`,
|
||||
showButton
|
||||
);
|
||||
// Address this click asynchronously so we still update the
|
||||
// query history immediately.
|
||||
void resultPromise.then((result) => {
|
||||
if (result === showButton) {
|
||||
panel.reveal();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Note that the resultSetSchemas will return offsets for the default (unsorted) page,
|
||||
|
||||
146
extensions/ql-vscode/src/packaging.ts
Normal file
146
extensions/ql-vscode/src/packaging.ts
Normal file
@@ -0,0 +1,146 @@
|
||||
import { CliVersionConstraint, CodeQLCliServer } from './cli';
|
||||
import {
|
||||
getOnDiskWorkspaceFolders,
|
||||
showAndLogErrorMessage,
|
||||
showAndLogInformationMessage,
|
||||
} from './helpers';
|
||||
import { QuickPickItem, window } from 'vscode';
|
||||
import { ProgressCallback, UserCancellationException } from './commandRunner';
|
||||
import { logger } from './logging';
|
||||
|
||||
const QUERY_PACKS = [
|
||||
'codeql/cpp-queries',
|
||||
'codeql/csharp-queries',
|
||||
'codeql/go-queries',
|
||||
'codeql/java-queries',
|
||||
'codeql/javascript-queries',
|
||||
'codeql/python-queries',
|
||||
'codeql/ruby-queries',
|
||||
'codeql/csharp-solorigate-queries',
|
||||
'codeql/javascript-experimental-atm-queries',
|
||||
];
|
||||
|
||||
/**
|
||||
* Prompts user to choose packs to download, and downloads them.
|
||||
*
|
||||
* @param cliServer The CLI server.
|
||||
* @param progress A progress callback.
|
||||
*/
|
||||
export async function handleDownloadPacks(
|
||||
cliServer: CodeQLCliServer,
|
||||
progress: ProgressCallback,
|
||||
): Promise<void> {
|
||||
if (!(await cliServer.cliConstraints.supportsPackaging())) {
|
||||
throw new Error(`Packaging commands are not supported by this version of CodeQL. Please upgrade to v${CliVersionConstraint.CLI_VERSION_WITH_PACKAGING
|
||||
} or later.`);
|
||||
}
|
||||
progress({
|
||||
message: 'Choose packs to download',
|
||||
step: 1,
|
||||
maxStep: 2,
|
||||
});
|
||||
let packsToDownload: string[] = [];
|
||||
const queryPackOption = 'Download all core query packs';
|
||||
const customPackOption = 'Download custom specified pack';
|
||||
const quickpick = await window.showQuickPick(
|
||||
[queryPackOption, customPackOption],
|
||||
{ ignoreFocusOut: true }
|
||||
);
|
||||
if (quickpick === queryPackOption) {
|
||||
packsToDownload = QUERY_PACKS;
|
||||
} else if (quickpick === customPackOption) {
|
||||
const customPack = await window.showInputBox({
|
||||
prompt:
|
||||
'Enter the <package-scope/name[@version]> of the pack to download',
|
||||
ignoreFocusOut: true,
|
||||
});
|
||||
if (customPack) {
|
||||
packsToDownload.push(customPack);
|
||||
} else {
|
||||
throw new UserCancellationException('No pack specified.');
|
||||
}
|
||||
}
|
||||
if (packsToDownload?.length > 0) {
|
||||
progress({
|
||||
message: 'Downloading packs. This may take a few minutes.',
|
||||
step: 2,
|
||||
maxStep: 2,
|
||||
});
|
||||
try {
|
||||
await cliServer.packDownload(packsToDownload);
|
||||
void showAndLogInformationMessage('Finished downloading packs.');
|
||||
} catch (error) {
|
||||
void showAndLogErrorMessage(
|
||||
'Unable to download all packs. See log for more details.'
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
interface QLPackQuickPickItem extends QuickPickItem {
|
||||
packRootDir: string[];
|
||||
}
|
||||
|
||||
/**
|
||||
* Prompts user to choose packs to install, and installs them.
|
||||
*
|
||||
* @param cliServer The CLI server.
|
||||
* @param progress A progress callback.
|
||||
*/
|
||||
export async function handleInstallPackDependencies(
|
||||
cliServer: CodeQLCliServer,
|
||||
progress: ProgressCallback,
|
||||
): Promise<void> {
|
||||
if (!(await cliServer.cliConstraints.supportsPackaging())) {
|
||||
throw new Error(`Packaging commands are not supported by this version of CodeQL. Please upgrade to v${CliVersionConstraint.CLI_VERSION_WITH_PACKAGING
|
||||
} or later.`);
|
||||
}
|
||||
progress({
|
||||
message: 'Choose packs to install dependencies for',
|
||||
step: 1,
|
||||
maxStep: 2,
|
||||
});
|
||||
const workspacePacks = await cliServer.resolveQlpacks(getOnDiskWorkspaceFolders());
|
||||
const quickPickItems = Object.entries(workspacePacks).map<QLPackQuickPickItem>(([key, value]) => ({
|
||||
label: key,
|
||||
packRootDir: value,
|
||||
}));
|
||||
const packsToInstall = await window.showQuickPick(quickPickItems, {
|
||||
placeHolder: 'Select packs to install dependencies for',
|
||||
canPickMany: true,
|
||||
ignoreFocusOut: true,
|
||||
});
|
||||
const numberOfPacks = packsToInstall?.length || 0;
|
||||
if (packsToInstall && numberOfPacks > 0) {
|
||||
const failedPacks = [];
|
||||
const errors = [];
|
||||
// Start at 1 because we already have the first step
|
||||
let count = 1;
|
||||
for (const pack of packsToInstall) {
|
||||
count++;
|
||||
progress({
|
||||
message: `Installing dependencies for ${pack.label}`,
|
||||
step: count,
|
||||
maxStep: numberOfPacks + 1,
|
||||
});
|
||||
try {
|
||||
for (const dir of pack.packRootDir) {
|
||||
await cliServer.packInstall(dir);
|
||||
}
|
||||
} catch (error) {
|
||||
failedPacks.push(pack.label);
|
||||
errors.push(error);
|
||||
}
|
||||
}
|
||||
if (failedPacks.length > 0) {
|
||||
void logger.log(`Errors:\n${errors.join('\n')}`);
|
||||
throw new Error(
|
||||
`Unable to install pack dependencies for: ${failedPacks.join(', ')}. See log for more details.`
|
||||
);
|
||||
} else {
|
||||
void showAndLogInformationMessage('Finished installing pack dependencies.');
|
||||
}
|
||||
} else {
|
||||
throw new UserCancellationException('No packs selected.');
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
import * as sarif from 'sarif';
|
||||
import { DownloadLink } from '../remote-queries/download-link';
|
||||
import { RemoteQueryResult } from '../remote-queries/shared/remote-query-result';
|
||||
import { AnalysisResults } from '../remote-queries/shared/analysis-result';
|
||||
import { AnalysisSummary, RemoteQueryResult } from '../remote-queries/shared/remote-query-result';
|
||||
import { RawResultSet, ResultRow, ResultSetSchema, Column, ResolvableLocationValue } from './bqrs-cli-types';
|
||||
|
||||
/**
|
||||
@@ -377,10 +377,12 @@ export type FromRemoteQueriesMessage =
|
||||
| RemoteQueryErrorMessage
|
||||
| OpenFileMsg
|
||||
| OpenVirtualFileMsg
|
||||
| RemoteQueryDownloadLinkClickedMessage;
|
||||
| RemoteQueryDownloadAnalysisResultsMessage
|
||||
| RemoteQueryDownloadAllAnalysesResultsMessage;
|
||||
|
||||
export type ToRemoteQueriesMessage =
|
||||
| SetRemoteQueryResultMessage;
|
||||
| SetRemoteQueryResultMessage
|
||||
| SetAnalysesResultsMessage;
|
||||
|
||||
export interface RemoteQueryLoadedMessage {
|
||||
t: 'remoteQueryLoaded';
|
||||
@@ -391,12 +393,22 @@ export interface SetRemoteQueryResultMessage {
|
||||
queryResult: RemoteQueryResult
|
||||
}
|
||||
|
||||
export interface SetAnalysesResultsMessage {
|
||||
t: 'setAnalysesResults';
|
||||
analysesResults: AnalysisResults[];
|
||||
}
|
||||
|
||||
export interface RemoteQueryErrorMessage {
|
||||
t: 'remoteQueryError';
|
||||
error: string;
|
||||
}
|
||||
|
||||
export interface RemoteQueryDownloadLinkClickedMessage {
|
||||
t: 'remoteQueryDownloadLinkClicked';
|
||||
downloadLink: DownloadLink;
|
||||
export interface RemoteQueryDownloadAnalysisResultsMessage {
|
||||
t: 'remoteQueryDownloadAnalysisResults';
|
||||
analysisSummary: AnalysisSummary
|
||||
}
|
||||
|
||||
export interface RemoteQueryDownloadAllAnalysesResultsMessage {
|
||||
t: 'remoteQueryDownloadAllAnalysesResults';
|
||||
analysisSummaries: AnalysisSummary[];
|
||||
}
|
||||
|
||||
@@ -0,0 +1,94 @@
|
||||
import { ExtensionContext } from 'vscode';
|
||||
import { Credentials } from '../authentication';
|
||||
import { Logger } from '../logging';
|
||||
import { downloadArtifactFromLink } from './gh-actions-api-client';
|
||||
import * as path from 'path';
|
||||
import * as fs from 'fs-extra';
|
||||
import { AnalysisSummary } from './shared/remote-query-result';
|
||||
import * as sarif from 'sarif';
|
||||
import { AnalysisResults, QueryResult } from './shared/analysis-result';
|
||||
|
||||
export class AnalysesResultsManager {
|
||||
// Store for the results of various analyses for a single remote query.
|
||||
private readonly analysesResults: AnalysisResults[];
|
||||
|
||||
constructor(
|
||||
private readonly ctx: ExtensionContext,
|
||||
private readonly logger: Logger,
|
||||
) {
|
||||
this.analysesResults = [];
|
||||
}
|
||||
|
||||
public async downloadAnalysisResults(
|
||||
analysisSummary: AnalysisSummary,
|
||||
): Promise<void> {
|
||||
if (this.analysesResults.some(x => x.nwo === analysisSummary.nwo)) {
|
||||
// We already have the results for this analysis, don't download again.
|
||||
return;
|
||||
}
|
||||
|
||||
const credentials = await Credentials.initialize(this.ctx);
|
||||
|
||||
void this.logger.log(`Downloading and processing results for ${analysisSummary.nwo}`);
|
||||
|
||||
await this.downloadSingleAnalysisResults(analysisSummary, credentials);
|
||||
}
|
||||
|
||||
public async downloadAllResults(
|
||||
analysisSummaries: AnalysisSummary[],
|
||||
): Promise<void> {
|
||||
const credentials = await Credentials.initialize(this.ctx);
|
||||
|
||||
void this.logger.log('Downloading and processing all results');
|
||||
|
||||
for (const analysis of analysisSummaries) {
|
||||
await this.downloadSingleAnalysisResults(analysis, credentials);
|
||||
}
|
||||
}
|
||||
|
||||
public getAnalysesResults(): AnalysisResults[] {
|
||||
return [...this.analysesResults];
|
||||
}
|
||||
|
||||
private async downloadSingleAnalysisResults(
|
||||
analysis: AnalysisSummary,
|
||||
credentials: Credentials
|
||||
): Promise<void> {
|
||||
const artifactPath = await downloadArtifactFromLink(credentials, analysis.downloadLink);
|
||||
|
||||
let analysisResults: AnalysisResults;
|
||||
|
||||
if (path.extname(artifactPath) === '.sarif') {
|
||||
const queryResults = await this.readResults(artifactPath);
|
||||
analysisResults = { nwo: analysis.nwo, results: queryResults };
|
||||
} else {
|
||||
void this.logger.log('Cannot download results. Only alert and path queries are fully supported.');
|
||||
analysisResults = { nwo: analysis.nwo, results: [] };
|
||||
}
|
||||
|
||||
this.analysesResults.push(analysisResults);
|
||||
}
|
||||
|
||||
private async readResults(filePath: string): Promise<QueryResult[]> {
|
||||
const queryResults: QueryResult[] = [];
|
||||
|
||||
const sarifContents = await fs.readFile(filePath, 'utf8');
|
||||
const sarifLog = JSON.parse(sarifContents) as sarif.Log;
|
||||
|
||||
// Read the sarif file and extract information that we want to display
|
||||
// in the UI. For now we're only getting the message texts but we'll gradually
|
||||
// extract more information based on the UX we want to build.
|
||||
|
||||
sarifLog.runs?.forEach(run => {
|
||||
run?.results?.forEach(result => {
|
||||
if (result?.message?.text) {
|
||||
queryResults.push({
|
||||
message: result.message.text
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
return queryResults;
|
||||
}
|
||||
}
|
||||
@@ -154,13 +154,30 @@ async function listWorkflowRunArtifacts(
|
||||
workflowRunId: number
|
||||
) {
|
||||
const octokit = await credentials.getOctokit();
|
||||
const response = await octokit.rest.actions.listWorkflowRunArtifacts({
|
||||
owner,
|
||||
repo,
|
||||
run_id: workflowRunId,
|
||||
});
|
||||
|
||||
return response.data.artifacts;
|
||||
// There are limits on the number of artifacts that are returned by the API
|
||||
// so we use paging to make sure we retrieve all of them.
|
||||
let morePages = true;
|
||||
let pageNum = 1;
|
||||
const allArtifacts = [];
|
||||
|
||||
while (morePages) {
|
||||
const response = await octokit.rest.actions.listWorkflowRunArtifacts({
|
||||
owner,
|
||||
repo,
|
||||
run_id: workflowRunId,
|
||||
per_page: 100,
|
||||
page: pageNum
|
||||
});
|
||||
|
||||
allArtifacts.push(...response.data.artifacts);
|
||||
pageNum++;
|
||||
if (response.data.artifacts.length < 100) {
|
||||
morePages = false;
|
||||
}
|
||||
}
|
||||
|
||||
return allArtifacts;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -7,27 +7,26 @@ import {
|
||||
workspace,
|
||||
} from 'vscode';
|
||||
import * as path from 'path';
|
||||
import * as vscode from 'vscode';
|
||||
import * as fs from 'fs-extra';
|
||||
|
||||
import { tmpDir } from '../run-queries';
|
||||
import {
|
||||
ToRemoteQueriesMessage,
|
||||
FromRemoteQueriesMessage,
|
||||
RemoteQueryDownloadLinkClickedMessage,
|
||||
RemoteQueryDownloadAnalysisResultsMessage,
|
||||
RemoteQueryDownloadAllAnalysesResultsMessage,
|
||||
} from '../pure/interface-types';
|
||||
import { Logger } from '../logging';
|
||||
import { getHtmlForWebview } from '../interface-utils';
|
||||
import { assertNever } from '../pure/helpers-pure';
|
||||
import { AnalysisResult, RemoteQueryResult } from './remote-query-result';
|
||||
import { AnalysisSummary, RemoteQueryResult } from './remote-query-result';
|
||||
import { RemoteQuery } from './remote-query';
|
||||
import { RemoteQueryResult as RemoteQueryResultViewModel } from './shared/remote-query-result';
|
||||
import { AnalysisResult as AnalysisResultViewModel } from './shared/remote-query-result';
|
||||
import { downloadArtifactFromLink } from './gh-actions-api-client';
|
||||
import { Credentials } from '../authentication';
|
||||
import { showAndLogWarningMessage, showInformationMessageWithAction } from '../helpers';
|
||||
import { AnalysisSummary as AnalysisResultViewModel } from './shared/remote-query-result';
|
||||
import { showAndLogWarningMessage } from '../helpers';
|
||||
import { URLSearchParams } from 'url';
|
||||
import { SHOW_QUERY_TEXT_MSG } from '../query-history';
|
||||
import { AnalysesResultsManager } from './analyses-results-manager';
|
||||
import { AnalysisResults } from './shared/analysis-result';
|
||||
|
||||
export class RemoteQueriesInterfaceManager {
|
||||
private panel: WebviewPanel | undefined;
|
||||
@@ -35,8 +34,9 @@ export class RemoteQueriesInterfaceManager {
|
||||
private panelLoadedCallBacks: (() => void)[] = [];
|
||||
|
||||
constructor(
|
||||
private ctx: ExtensionContext,
|
||||
private logger: Logger,
|
||||
private readonly ctx: ExtensionContext,
|
||||
private readonly logger: Logger,
|
||||
private readonly analysesResultsManager: AnalysesResultsManager
|
||||
) {
|
||||
this.panelLoadedCallBacks.push(() => {
|
||||
void logger.log('Remote queries view loaded');
|
||||
@@ -63,10 +63,10 @@ export class RemoteQueriesInterfaceManager {
|
||||
*/
|
||||
private buildViewModel(query: RemoteQuery, queryResult: RemoteQueryResult): RemoteQueryResultViewModel {
|
||||
const queryFileName = path.basename(query.queryFilePath);
|
||||
const totalResultCount = queryResult.analysisResults.reduce((acc, cur) => acc + cur.resultCount, 0);
|
||||
const totalResultCount = queryResult.analysisSummaries.reduce((acc, cur) => acc + cur.resultCount, 0);
|
||||
const executionDuration = this.getDuration(queryResult.executionEndTime, query.executionStartTime);
|
||||
const analysisResults = this.buildAnalysisResults(queryResult.analysisResults);
|
||||
const affectedRepositories = queryResult.analysisResults.filter(r => r.resultCount > 0);
|
||||
const analysisSummaries = this.buildAnalysisSummaries(queryResult.analysisSummaries);
|
||||
const affectedRepositories = queryResult.analysisSummaries.filter(r => r.resultCount > 0);
|
||||
|
||||
return {
|
||||
queryTitle: query.queryName,
|
||||
@@ -79,7 +79,7 @@ export class RemoteQueriesInterfaceManager {
|
||||
executionTimestamp: this.formatDate(query.executionStartTime),
|
||||
executionDuration: executionDuration,
|
||||
downloadLink: queryResult.allResultsDownloadLink,
|
||||
results: analysisResults
|
||||
analysisSummaries: analysisSummaries
|
||||
};
|
||||
}
|
||||
|
||||
@@ -112,6 +112,10 @@ export class RemoteQueriesInterfaceManager {
|
||||
ctx.asAbsolutePath('out/remoteQueriesView.js')
|
||||
);
|
||||
|
||||
const baseStylesheetUriOnDisk = Uri.file(
|
||||
ctx.asAbsolutePath('out/remote-queries/view/baseStyles.css')
|
||||
);
|
||||
|
||||
const stylesheetPathOnDisk = Uri.file(
|
||||
ctx.asAbsolutePath('out/remote-queries/view/remoteQueries.css')
|
||||
);
|
||||
@@ -119,7 +123,7 @@ export class RemoteQueriesInterfaceManager {
|
||||
panel.webview.html = getHtmlForWebview(
|
||||
panel.webview,
|
||||
scriptPathOnDisk,
|
||||
stylesheetPathOnDisk
|
||||
[baseStylesheetUriOnDisk, stylesheetPathOnDisk]
|
||||
);
|
||||
panel.webview.onDidReceiveMessage(
|
||||
async (e) => this.handleMsgFromView(e),
|
||||
@@ -185,30 +189,32 @@ export class RemoteQueriesInterfaceManager {
|
||||
case 'openVirtualFile':
|
||||
await this.openVirtualFile(msg.queryText);
|
||||
break;
|
||||
case 'remoteQueryDownloadLinkClicked':
|
||||
await this.handleDownloadLinkClicked(msg);
|
||||
case 'remoteQueryDownloadAnalysisResults':
|
||||
await this.downloadAnalysisResults(msg);
|
||||
break;
|
||||
case 'remoteQueryDownloadAllAnalysesResults':
|
||||
await this.downloadAllAnalysesResults(msg);
|
||||
break;
|
||||
default:
|
||||
assertNever(msg);
|
||||
}
|
||||
}
|
||||
|
||||
private async handleDownloadLinkClicked(msg: RemoteQueryDownloadLinkClickedMessage): Promise<void> {
|
||||
const credentials = await Credentials.initialize(this.ctx);
|
||||
private async downloadAnalysisResults(msg: RemoteQueryDownloadAnalysisResultsMessage): Promise<void> {
|
||||
await this.analysesResultsManager.downloadAnalysisResults(msg.analysisSummary);
|
||||
await this.setAnalysisResults(this.analysesResultsManager.getAnalysesResults());
|
||||
}
|
||||
|
||||
const filePath = await downloadArtifactFromLink(credentials, msg.downloadLink);
|
||||
const isDir = (await fs.stat(filePath)).isDirectory();
|
||||
const message = `Result file saved at ${filePath}`;
|
||||
if (isDir) {
|
||||
await vscode.window.showInformationMessage(message);
|
||||
}
|
||||
else {
|
||||
const shouldOpenResults = await showInformationMessageWithAction(message, 'Open');
|
||||
if (shouldOpenResults) {
|
||||
const textDocument = await vscode.workspace.openTextDocument(filePath);
|
||||
await vscode.window.showTextDocument(textDocument, vscode.ViewColumn.One);
|
||||
}
|
||||
}
|
||||
private async downloadAllAnalysesResults(msg: RemoteQueryDownloadAllAnalysesResultsMessage): Promise<void> {
|
||||
await this.analysesResultsManager.downloadAllResults(msg.analysisSummaries);
|
||||
await this.setAnalysisResults(this.analysesResultsManager.getAnalysesResults());
|
||||
}
|
||||
|
||||
private async setAnalysisResults(analysesResults: AnalysisResults[]): Promise<void> {
|
||||
await this.postMessage({
|
||||
t: 'setAnalysesResults',
|
||||
analysesResults: analysesResults
|
||||
});
|
||||
}
|
||||
|
||||
private postMessage(msg: ToRemoteQueriesMessage): Thenable<boolean> {
|
||||
@@ -259,16 +265,16 @@ export class RemoteQueriesInterfaceManager {
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds up a list of analysis results, in a data structure tailored to the view.
|
||||
* @param analysisResults The results of a specific analysis.
|
||||
* Builds up a list of analysis summaries, in a data structure tailored to the view.
|
||||
* @param analysisSummaries The summaries of a specific analyses.
|
||||
* @returns A fully created view model.
|
||||
*/
|
||||
private buildAnalysisResults(analysisResults: AnalysisResult[]): AnalysisResultViewModel[] {
|
||||
const filteredAnalysisResults = analysisResults.filter(r => r.resultCount > 0);
|
||||
private buildAnalysisSummaries(analysisSummaries: AnalysisSummary[]): AnalysisResultViewModel[] {
|
||||
const filteredAnalysisSummaries = analysisSummaries.filter(r => r.resultCount > 0);
|
||||
|
||||
const sortedAnalysisResults = filteredAnalysisResults.sort((a, b) => b.resultCount - a.resultCount);
|
||||
const sortedAnalysisSummaries = filteredAnalysisSummaries.sort((a, b) => b.resultCount - a.resultCount);
|
||||
|
||||
return sortedAnalysisResults.map((analysisResult) => ({
|
||||
return sortedAnalysisSummaries.map((analysisResult) => ({
|
||||
nwo: analysisResult.nwo,
|
||||
resultCount: analysisResult.resultCount,
|
||||
downloadLink: analysisResult.downloadLink,
|
||||
|
||||
@@ -12,15 +12,18 @@ import { getRemoteQueryIndex } from './gh-actions-api-client';
|
||||
import { RemoteQueryResultIndex } from './remote-query-result-index';
|
||||
import { RemoteQueryResult } from './remote-query-result';
|
||||
import { DownloadLink } from './download-link';
|
||||
import { AnalysesResultsManager } from './analyses-results-manager';
|
||||
|
||||
export class RemoteQueriesManager {
|
||||
private readonly remoteQueriesMonitor: RemoteQueriesMonitor;
|
||||
private readonly analysesResultsManager: AnalysesResultsManager;
|
||||
|
||||
constructor(
|
||||
private readonly ctx: ExtensionContext,
|
||||
private readonly logger: Logger,
|
||||
private readonly cliServer: CodeQLCliServer
|
||||
) {
|
||||
this.analysesResultsManager = new AnalysesResultsManager(ctx, logger);
|
||||
this.remoteQueriesMonitor = new RemoteQueriesMonitor(ctx, logger);
|
||||
}
|
||||
|
||||
@@ -62,12 +65,12 @@ export class RemoteQueriesManager {
|
||||
|
||||
const queryResult = this.mapQueryResult(executionEndTime, resultIndex);
|
||||
|
||||
const totalResultCount = queryResult.analysisResults.reduce((acc, cur) => acc + cur.resultCount, 0);
|
||||
const totalResultCount = queryResult.analysisSummaries.reduce((acc, cur) => acc + cur.resultCount, 0);
|
||||
const message = `Query "${query.queryName}" run on ${query.repositories.length} repositories and returned ${totalResultCount} results`;
|
||||
|
||||
const shouldOpenView = await showInformationMessageWithAction(message, 'View');
|
||||
if (shouldOpenView) {
|
||||
const rqim = new RemoteQueriesInterfaceManager(this.ctx, this.logger);
|
||||
const rqim = new RemoteQueriesInterfaceManager(this.ctx, this.logger, this.analysesResultsManager);
|
||||
await rqim.showResults(query, queryResult);
|
||||
}
|
||||
} else if (queryResult.status === 'CompletedUnsuccessfully') {
|
||||
@@ -79,7 +82,7 @@ export class RemoteQueriesManager {
|
||||
}
|
||||
|
||||
private mapQueryResult(executionEndTime: Date, resultIndex: RemoteQueryResultIndex): RemoteQueryResult {
|
||||
const analysisResults = resultIndex.items.map(item => ({
|
||||
const analysisSummaries = resultIndex.items.map(item => ({
|
||||
nwo: item.nwo,
|
||||
resultCount: item.resultCount,
|
||||
fileSizeInBytes: item.sarifFileSize ? item.sarifFileSize : item.bqrsFileSize,
|
||||
@@ -92,7 +95,7 @@ export class RemoteQueriesManager {
|
||||
|
||||
return {
|
||||
executionEndTime,
|
||||
analysisResults,
|
||||
analysisSummaries,
|
||||
allResultsDownloadLink: {
|
||||
id: resultIndex.allResultsArtifactId.toString(),
|
||||
urlPath: `${resultIndex.artifactsUrlPath}/${resultIndex.allResultsArtifactId}`
|
||||
|
||||
@@ -30,6 +30,8 @@ export class RemoteQueriesMonitor {
|
||||
let attemptCount = 0;
|
||||
|
||||
while (attemptCount <= RemoteQueriesMonitor.maxAttemptCount) {
|
||||
await this.sleep(RemoteQueriesMonitor.sleepTime);
|
||||
|
||||
if (cancellationToken && cancellationToken.isCancellationRequested) {
|
||||
return { status: 'Cancelled' };
|
||||
}
|
||||
@@ -44,7 +46,6 @@ export class RemoteQueriesMonitor {
|
||||
return workflowStatus;
|
||||
}
|
||||
|
||||
await this.sleep(RemoteQueriesMonitor.sleepTime);
|
||||
attemptCount++;
|
||||
}
|
||||
|
||||
|
||||
@@ -2,11 +2,11 @@ import { DownloadLink } from './download-link';
|
||||
|
||||
export interface RemoteQueryResult {
|
||||
executionEndTime: Date;
|
||||
analysisResults: AnalysisResult[];
|
||||
analysisSummaries: AnalysisSummary[];
|
||||
allResultsDownloadLink: DownloadLink;
|
||||
}
|
||||
|
||||
export interface AnalysisResult {
|
||||
export interface AnalysisSummary {
|
||||
nwo: string,
|
||||
resultCount: number,
|
||||
downloadLink: DownloadLink,
|
||||
|
||||
86
extensions/ql-vscode/src/remote-queries/sample-data.ts
Normal file
86
extensions/ql-vscode/src/remote-queries/sample-data.ts
Normal file
@@ -0,0 +1,86 @@
|
||||
import { RemoteQuery } from './remote-query';
|
||||
import { RemoteQueryResult } from './remote-query-result';
|
||||
|
||||
export const sampleRemoteQuery: RemoteQuery = {
|
||||
queryName: 'Inefficient regular expression',
|
||||
queryFilePath: '/Users/foo/dev/vscode-codeql-starter/ql/javascript/ql/src/Performance/ReDoS.ql',
|
||||
queryText: '/**\n * @name Inefficient regular expression\n * @description A regular expression that requires exponential time to match certain inputs\n * can be a performance bottleneck, and may be vulnerable to denial-of-service\n * attacks.\n * @kind problem\n * @problem.severity error\n * @security-severity 7.5\n * @precision high\n * @id js/redos\n * @tags security\n * external/cwe/cwe-1333\n * external/cwe/cwe-730\n * external/cwe/cwe-400\n */\n\nimport javascript\nimport semmle.javascript.security.performance.ReDoSUtil\nimport semmle.javascript.security.performance.ExponentialBackTracking\n\nfrom RegExpTerm t, string pump, State s, string prefixMsg\nwhere hasReDoSResult(t, pump, s, prefixMsg)\nselect t,\n "This part of the regular expression may cause exponential backtracking on strings " + prefixMsg +\n "containing many repetitions of \'" + pump + "\'."\n',
|
||||
controllerRepository: {
|
||||
owner: 'big-corp',
|
||||
name: 'controller-repo'
|
||||
},
|
||||
repositories: [
|
||||
{
|
||||
owner: 'big-corp',
|
||||
name: 'repo1'
|
||||
},
|
||||
{
|
||||
owner: 'big-corp',
|
||||
name: 'repo2'
|
||||
},
|
||||
{
|
||||
owner: 'big-corp',
|
||||
name: 'repo3'
|
||||
},
|
||||
{
|
||||
owner: 'big-corp',
|
||||
name: 'repo4'
|
||||
},
|
||||
{
|
||||
owner: 'big-corp',
|
||||
name: 'repo5'
|
||||
}
|
||||
],
|
||||
executionStartTime: new Date('2022-01-06T17:02:15.026Z'),
|
||||
actionsWorkflowRunId: 1662757118
|
||||
};
|
||||
|
||||
export const sampleRemoteQueryResult: RemoteQueryResult = {
|
||||
executionEndTime: new Date('2022-01-06T17:04:37.026Z'),
|
||||
allResultsDownloadLink: {
|
||||
id: '137697018',
|
||||
urlPath: '/repos/big-corp/controller-repo/actions/artifacts/137697018'
|
||||
},
|
||||
analysisSummaries: [
|
||||
{
|
||||
nwo: 'big-corp/repo1',
|
||||
resultCount: 85,
|
||||
fileSizeInBytes: 14123,
|
||||
downloadLink: {
|
||||
id: '137697017',
|
||||
urlPath: '/repos/big-corp/controller-repo/actions/artifacts/137697017',
|
||||
innerFilePath: 'results.sarif'
|
||||
}
|
||||
},
|
||||
{
|
||||
nwo: 'big-corp/repo2',
|
||||
resultCount: 20,
|
||||
fileSizeInBytes: 8698,
|
||||
downloadLink: {
|
||||
id: '137697018',
|
||||
urlPath: '/repos/big-corp/controller-repo/actions/artifacts/137697018',
|
||||
innerFilePath: 'results.sarif'
|
||||
}
|
||||
},
|
||||
{
|
||||
nwo: 'big-corp/repo3',
|
||||
resultCount: 8,
|
||||
fileSizeInBytes: 4123,
|
||||
downloadLink: {
|
||||
id: '137697019',
|
||||
urlPath: '/repos/big-corp/controller-repo/actions/artifacts/137697019',
|
||||
innerFilePath: 'results.sarif'
|
||||
}
|
||||
},
|
||||
{
|
||||
nwo: 'big-corp/repo4',
|
||||
resultCount: 3,
|
||||
fileSizeInBytes: 3313,
|
||||
downloadLink: {
|
||||
id: '137697020',
|
||||
urlPath: '/repos/big-corp/controller-repo/actions/artifacts/137697020',
|
||||
innerFilePath: 'results.sarif'
|
||||
}
|
||||
}
|
||||
]
|
||||
};
|
||||
@@ -0,0 +1,8 @@
|
||||
export interface AnalysisResults {
|
||||
nwo: string;
|
||||
results: QueryResult[];
|
||||
}
|
||||
|
||||
export interface QueryResult {
|
||||
message?: string;
|
||||
}
|
||||
@@ -11,10 +11,10 @@ export interface RemoteQueryResult {
|
||||
executionTimestamp: string;
|
||||
executionDuration: string;
|
||||
downloadLink: DownloadLink;
|
||||
results: AnalysisResult[]
|
||||
analysisSummaries: AnalysisSummary[]
|
||||
}
|
||||
|
||||
export interface AnalysisResult {
|
||||
export interface AnalysisSummary {
|
||||
nwo: string,
|
||||
resultCount: number,
|
||||
downloadLink: DownloadLink,
|
||||
|
||||
9
extensions/ql-vscode/src/remote-queries/view/Badge.tsx
Normal file
9
extensions/ql-vscode/src/remote-queries/view/Badge.tsx
Normal file
@@ -0,0 +1,9 @@
|
||||
import * as React from 'react';
|
||||
|
||||
const Badge = ({ text }: { text: string }) => (
|
||||
<span className="vscode-codeql__badge-container">
|
||||
<span className="vscode-codeql__badge">{text}</span>
|
||||
</span>
|
||||
);
|
||||
|
||||
export default Badge;
|
||||
@@ -0,0 +1,11 @@
|
||||
import * as React from 'react';
|
||||
import * as octicons from '../../view/octicons';
|
||||
|
||||
const DownloadButton = ({ text, onClick }: { text: string, onClick: () => void }) => (
|
||||
<a className="vscode-codeql__download-button"
|
||||
onClick={onClick}>
|
||||
{octicons.download}{text}
|
||||
</a>
|
||||
);
|
||||
|
||||
export default DownloadButton;
|
||||
@@ -1,12 +1,18 @@
|
||||
import * as React from 'react';
|
||||
import { useEffect, useState } from 'react';
|
||||
import * as Rdom from 'react-dom';
|
||||
import { SetRemoteQueryResultMessage } from '../../pure/interface-types';
|
||||
import { AnalysisResult, RemoteQueryResult } from '../shared/remote-query-result';
|
||||
import { ToRemoteQueriesMessage } from '../../pure/interface-types';
|
||||
import { AnalysisSummary, RemoteQueryResult } from '../shared/remote-query-result';
|
||||
import * as octicons from '../../view/octicons';
|
||||
|
||||
import { vscode } from '../../view/vscode-api';
|
||||
import { DownloadLink } from '../download-link';
|
||||
|
||||
import SectionTitle from './SectionTitle';
|
||||
import VerticalSpace from './VerticalSpace';
|
||||
import Badge from './Badge';
|
||||
import ViewTitle from './ViewTitle';
|
||||
import DownloadButton from './DownloadButton';
|
||||
import { AnalysisResults } from '../shared/analysis-result';
|
||||
|
||||
const numOfReposInContractedMode = 10;
|
||||
|
||||
@@ -24,58 +30,165 @@ const emptyQueryResult: RemoteQueryResult = {
|
||||
id: '',
|
||||
urlPath: '',
|
||||
},
|
||||
results: []
|
||||
analysisSummaries: []
|
||||
};
|
||||
|
||||
const download = (link: DownloadLink) => {
|
||||
const downloadAnalysisResults = (analysisSummary: AnalysisSummary) => {
|
||||
vscode.postMessage({
|
||||
t: 'remoteQueryDownloadLinkClicked',
|
||||
downloadLink: link
|
||||
t: 'remoteQueryDownloadAnalysisResults',
|
||||
analysisSummary
|
||||
});
|
||||
};
|
||||
|
||||
const AnalysisResultItem = (props: AnalysisResult) => (
|
||||
const downloadAllAnalysesResults = (query: RemoteQueryResult) => {
|
||||
vscode.postMessage({
|
||||
t: 'remoteQueryDownloadAllAnalysesResults',
|
||||
analysisSummaries: query.analysisSummaries
|
||||
});
|
||||
};
|
||||
|
||||
const openQueryFile = (queryResult: RemoteQueryResult) => {
|
||||
vscode.postMessage({
|
||||
t: 'openFile',
|
||||
filePath: queryResult.queryFilePath
|
||||
});
|
||||
};
|
||||
|
||||
const openQueryTextVirtualFile = (queryResult: RemoteQueryResult) => {
|
||||
vscode.postMessage({
|
||||
t: 'openVirtualFile',
|
||||
queryText: queryResult.queryText
|
||||
});
|
||||
};
|
||||
|
||||
const QueryInfo = (queryResult: RemoteQueryResult) => (
|
||||
<>
|
||||
<VerticalSpace />
|
||||
{queryResult.totalResultCount} results in {queryResult.totalRepositoryCount} repositories
|
||||
({queryResult.executionDuration}), {queryResult.executionTimestamp}
|
||||
<VerticalSpace />
|
||||
<span className="vscode-codeql__query-file">{octicons.file}
|
||||
<a className="vscode-codeql__query-file-link" href="#" onClick={() => openQueryFile(queryResult)}>
|
||||
{queryResult.queryFileName}
|
||||
</a>
|
||||
</span>
|
||||
<span>{octicons.codeSquare}
|
||||
<a className="vscode-codeql__query-file-link" href="#" onClick={() => openQueryTextVirtualFile(queryResult)}>
|
||||
query
|
||||
</a>
|
||||
</span>
|
||||
</>
|
||||
);
|
||||
|
||||
const SummaryTitleWithResults = (queryResult: RemoteQueryResult) => (
|
||||
<div className="vscode-codeql__query-summary-container">
|
||||
<SectionTitle text={`Repositories with results (${queryResult.affectedRepositoryCount}):`} />
|
||||
<DownloadButton
|
||||
text="Download all"
|
||||
onClick={() => downloadAllAnalysesResults(queryResult)} />
|
||||
</div>
|
||||
);
|
||||
|
||||
const SummaryTitleNoResults = () => (
|
||||
<div className="vscode-codeql__query-summary-container">
|
||||
<SectionTitle text="No results found" />
|
||||
</div>
|
||||
);
|
||||
|
||||
const SummaryItem = (props: AnalysisSummary) => (
|
||||
<span>
|
||||
<span className="vscode-codeql__analysis-item">{octicons.repo}</span>
|
||||
<span className="vscode-codeql__analysis-item">{props.nwo}</span>
|
||||
<span className="vscode-codeql__analysis-item vscode-codeql__badge-container">
|
||||
<span className="vscode-codeql__badge">{props.resultCount}</span>
|
||||
</span>
|
||||
<span className="vscode-codeql__analysis-item"><Badge text={props.resultCount.toString()} /></span>
|
||||
<span className="vscode-codeql__analysis-item">
|
||||
<a
|
||||
className="vscode-codeql__download-link"
|
||||
onClick={() => download(props.downloadLink)}>
|
||||
{octicons.download}{props.fileSize}
|
||||
</a>
|
||||
<DownloadButton
|
||||
text={props.fileSize}
|
||||
onClick={() => downloadAnalysisResults(props)} />
|
||||
</span>
|
||||
</span>
|
||||
);
|
||||
const Summary = (queryResult: RemoteQueryResult) => {
|
||||
const [repoListExpanded, setRepoListExpanded] = useState(false);
|
||||
const numOfReposToShow = repoListExpanded ? queryResult.analysisSummaries.length : numOfReposInContractedMode;
|
||||
|
||||
const SummaryWithResults = (queryResult: RemoteQueryResult) => (
|
||||
<div className="vscode-codeql__query-summary-container">
|
||||
<h2 className="vscode-codeql__query-summary-title">Repositories with results ({queryResult.affectedRepositoryCount}):</h2>
|
||||
<a className="vscode-codeql__summary-download-link vscode-codeql__download-link"
|
||||
onClick={() => download(queryResult.downloadLink)}>
|
||||
{octicons.download}Download all
|
||||
</a>
|
||||
</div>
|
||||
);
|
||||
return (
|
||||
<>
|
||||
{
|
||||
queryResult.affectedRepositoryCount === 0
|
||||
? <SummaryTitleNoResults />
|
||||
: <SummaryTitleWithResults {...queryResult} />
|
||||
}
|
||||
|
||||
const SummaryNoResults = () => (
|
||||
<div className="vscode-codeql__query-summary-container">
|
||||
<h2 className="vscode-codeql__query-summary-title">No results found</h2>
|
||||
</div>
|
||||
);
|
||||
<ul className="vscode-codeql__analysis-summaries-list">
|
||||
{queryResult.analysisSummaries.slice(0, numOfReposToShow).map((summary, i) =>
|
||||
<li key={summary.nwo} className="vscode-codeql__analysis-summaries-list-item">
|
||||
<SummaryItem {...summary} />
|
||||
</li>
|
||||
)}
|
||||
</ul>
|
||||
{
|
||||
queryResult.analysisSummaries.length > numOfReposInContractedMode &&
|
||||
<button className="vscode-codeql__expand-button" onClick={() => setRepoListExpanded(!repoListExpanded)}>
|
||||
{repoListExpanded ? (<span>View less</span>) : (<span>View all</span>)}
|
||||
</button>
|
||||
}
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
const AnalysesResultsTitle = ({ totalAnalysesResults, totalResults }: { totalAnalysesResults: number, totalResults: number }) => {
|
||||
if (totalAnalysesResults === totalResults) {
|
||||
return <SectionTitle text={`${totalAnalysesResults} results`} />;
|
||||
}
|
||||
|
||||
return <SectionTitle text={`${totalAnalysesResults}/${totalResults} results`} />;
|
||||
};
|
||||
|
||||
const AnalysesResultsDescription = ({ totalAnalysesResults, totalResults }: { totalAnalysesResults: number, totalResults: number }) => {
|
||||
if (totalAnalysesResults < totalResults) {
|
||||
return <>
|
||||
<VerticalSpace />
|
||||
Some results haven't been downloaded automatically because of their size or because enough were downloaded already.
|
||||
Download them manually from the list above if you want to see them here.
|
||||
</>;
|
||||
}
|
||||
|
||||
return <></>;
|
||||
};
|
||||
|
||||
const AnalysesResults = ({ analysesResults, totalResults }: { analysesResults: AnalysisResults[], totalResults: number }) => {
|
||||
const totalAnalysesResults = analysesResults.reduce((acc, curr) => acc + curr.results.length, 0);
|
||||
|
||||
if (totalResults === 0) {
|
||||
return <></>;
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<VerticalSpace />
|
||||
<VerticalSpace />
|
||||
<AnalysesResultsTitle
|
||||
totalAnalysesResults={totalAnalysesResults}
|
||||
totalResults={totalResults} />
|
||||
<AnalysesResultsDescription
|
||||
totalAnalysesResults={totalAnalysesResults}
|
||||
totalResults={totalResults} />
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export function RemoteQueries(): JSX.Element {
|
||||
const [queryResult, setQueryResult] = useState<RemoteQueryResult>(emptyQueryResult);
|
||||
const [analysesResults, setAnalysesResults] = useState<AnalysisResults[]>([]);
|
||||
|
||||
useEffect(() => {
|
||||
window.addEventListener('message', (evt: MessageEvent) => {
|
||||
if (evt.origin === window.origin) {
|
||||
const msg: SetRemoteQueryResultMessage = evt.data;
|
||||
const msg: ToRemoteQueriesMessage = evt.data;
|
||||
if (msg.t === 'setRemoteQueryResult') {
|
||||
setQueryResult(msg.queryResult);
|
||||
} else if (msg.t === 'setAnalysesResults') {
|
||||
setAnalysesResults(msg.analysesResults);
|
||||
}
|
||||
} else {
|
||||
// sanitize origin
|
||||
@@ -89,63 +202,12 @@ export function RemoteQueries(): JSX.Element {
|
||||
return <div>Waiting for results to load.</div>;
|
||||
}
|
||||
|
||||
const [repoListExpanded, setRepoListExpanded] = useState(false);
|
||||
const numOfReposToShow = repoListExpanded ? queryResult.results.length : numOfReposInContractedMode;
|
||||
|
||||
const openQueryFile = () => {
|
||||
vscode.postMessage({
|
||||
t: 'openFile',
|
||||
filePath: queryResult.queryFilePath
|
||||
});
|
||||
};
|
||||
|
||||
const openQueryTextVirtualFile = () => {
|
||||
vscode.postMessage({
|
||||
t: 'openVirtualFile',
|
||||
queryText: queryResult.queryText
|
||||
});
|
||||
};
|
||||
|
||||
try {
|
||||
return <div className="vscode-codeql__remote-queries-view">
|
||||
<h1 className="vscode-codeql__query-title">{queryResult.queryTitle}</h1>
|
||||
|
||||
<p className="vscode-codeql__paragraph">
|
||||
{queryResult.totalResultCount} results in {queryResult.totalRepositoryCount} repositories
|
||||
({queryResult.executionDuration}), {queryResult.executionTimestamp}
|
||||
</p>
|
||||
<p className="vscode-codeql__paragraph">
|
||||
<span className="vscode-codeql__query-file">{octicons.file}
|
||||
<a className="vscode-codeql__query-file-link" href="#" onClick={openQueryFile}>
|
||||
{queryResult.queryFileName}
|
||||
</a>
|
||||
</span>
|
||||
<span>{octicons.codeSquare}
|
||||
<a className="vscode-codeql__query-file-link" href="#" onClick={openQueryTextVirtualFile}>
|
||||
query
|
||||
</a>
|
||||
</span>
|
||||
</p>
|
||||
|
||||
{
|
||||
queryResult.affectedRepositoryCount === 0
|
||||
? <SummaryNoResults />
|
||||
: <SummaryWithResults {...queryResult} />
|
||||
}
|
||||
|
||||
<ul className="vscode-codeql__results-list">
|
||||
{queryResult.results.slice(0, numOfReposToShow).map((result, i) =>
|
||||
<li key={result.nwo} className="vscode-codeql__results-list-item">
|
||||
<AnalysisResultItem {...result} />
|
||||
</li>
|
||||
)}
|
||||
</ul>
|
||||
{
|
||||
queryResult.results.length > numOfReposInContractedMode &&
|
||||
<button className="vscode-codeql__expand-button" onClick={() => setRepoListExpanded(!repoListExpanded)}>
|
||||
{repoListExpanded ? (<span>View less</span>) : (<span>View all</span>)}
|
||||
</button>
|
||||
}
|
||||
return <div>
|
||||
<ViewTitle title={queryResult.queryTitle} />
|
||||
<QueryInfo {...queryResult} />
|
||||
<Summary {...queryResult} />
|
||||
<AnalysesResults analysesResults={analysesResults} totalResults={queryResult.totalResultCount} />
|
||||
</div>;
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
import * as React from 'react';
|
||||
|
||||
const SectionTitle = ({ text }: { text: string }) => (
|
||||
<h2 className="vscode-codeql__section-title">{text}</h2>
|
||||
);
|
||||
|
||||
export default SectionTitle;
|
||||
@@ -0,0 +1,7 @@
|
||||
import * as React from 'react';
|
||||
|
||||
const VerticalSpace = () => (
|
||||
<div className="vscode-codeql__vertical-space" />
|
||||
);
|
||||
|
||||
export default VerticalSpace;
|
||||
@@ -0,0 +1,7 @@
|
||||
import * as React from 'react';
|
||||
|
||||
const ViewTitle = ({ title }: { title: string }) => (
|
||||
<h1 className="vscode-codeql__view-title">{title}</h1>
|
||||
);
|
||||
|
||||
export default ViewTitle;
|
||||
75
extensions/ql-vscode/src/remote-queries/view/baseStyles.css
Normal file
75
extensions/ql-vscode/src/remote-queries/view/baseStyles.css
Normal file
@@ -0,0 +1,75 @@
|
||||
body {
|
||||
font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Helvetica, Arial,
|
||||
sans-serif, Apple Color Emoji, Segoe UI Emoji;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* SectionTitle component */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
.vscode-codeql__section-title {
|
||||
font-size: medium;
|
||||
font-weight: 500;
|
||||
padding: 0 0.5em 0 0;
|
||||
margin: 0;
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* ViewTitle component */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
.vscode-codeql__view-title {
|
||||
font-size: large;
|
||||
margin-bottom: 0.5em;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* VerticalSpace component */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
.vscode-codeql__vertical-space {
|
||||
flex: 0 0 auto;
|
||||
height: 0.5rem;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* Badge component */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
.vscode-codeql__badge-container {
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
min-height: 100vh;
|
||||
padding-left: 0.2em;
|
||||
}
|
||||
|
||||
.vscode-codeql__badge {
|
||||
display: inline-block;
|
||||
min-width: 1.5em;
|
||||
padding: 0.3em;
|
||||
border-radius: 35%;
|
||||
font-size: x-small;
|
||||
text-align: center;
|
||||
background: var(--vscode-badge-background);
|
||||
color: var(--vscode-badge-foreground);
|
||||
border-color: var(--vscode-badge-background);
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* DownloadButton component */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
.vscode-codeql__download-button {
|
||||
display: inline-block;
|
||||
font-size: x-small;
|
||||
text-decoration: none;
|
||||
cursor: pointer;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.vscode-codeql__download-button svg {
|
||||
fill: var(--vscode-textLink-foreground);
|
||||
}
|
||||
@@ -1,29 +1,3 @@
|
||||
.vscode-codeql__remote-queries-view {
|
||||
font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Helvetica, Arial,
|
||||
sans-serif, Apple Color Emoji, Segoe UI Emoji;
|
||||
}
|
||||
|
||||
.vscode-codeql__paragraph {
|
||||
margin: 0.5em 0 0.5em 0;
|
||||
}
|
||||
|
||||
.vscode-codeql__download-link {
|
||||
display: inline-block;
|
||||
font-size: x-small;
|
||||
text-decoration: none;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.vscode-codeql__download-link svg {
|
||||
fill: var(--vscode-textLink-foreground);
|
||||
}
|
||||
|
||||
.vscode-codeql__query-title {
|
||||
font-size: large;
|
||||
margin-bottom: 0.5em;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.octicon {
|
||||
fill: var(--vscode-editor-foreground);
|
||||
height: 1.2em;
|
||||
@@ -54,26 +28,13 @@
|
||||
padding-top: 1.5em;
|
||||
}
|
||||
|
||||
.vscode-codeql__query-summary-title {
|
||||
font-size: medium;
|
||||
font-weight: 500;
|
||||
padding: 0 0.5em 0 0;
|
||||
margin: 0;
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.vscode-codeql__summary-download-link {
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.vscode-codeql__results-list {
|
||||
.vscode-codeql__analysis-summaries-list {
|
||||
list-style-type: none;
|
||||
margin: 0;
|
||||
padding: 0.5em 0 0 0;
|
||||
}
|
||||
|
||||
.vscode-codeql__results-list-item {
|
||||
.vscode-codeql__analysis-summaries-list-item {
|
||||
margin-top: 0.5em;
|
||||
}
|
||||
|
||||
@@ -81,25 +42,6 @@
|
||||
padding-right: 0.1em;
|
||||
}
|
||||
|
||||
.vscode-codeql__badge-container {
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
min-height: 100vh;
|
||||
padding-left: 0.2em;
|
||||
}
|
||||
|
||||
.vscode-codeql__badge {
|
||||
display: inline-block;
|
||||
min-width: 1.5em;
|
||||
padding: 0.3em;
|
||||
border-radius: 35%;
|
||||
font-size: x-small;
|
||||
text-align: center;
|
||||
background: var(--vscode-badge-background);
|
||||
color: var(--vscode-badge-foreground);
|
||||
border-color: var(--vscode-badge-background);
|
||||
}
|
||||
|
||||
.vscode-codeql__expand-button {
|
||||
background: none;
|
||||
color: var(--vscode-textLink-foreground);
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
name: foo/bar
|
||||
version: 0.0.0
|
||||
dependencies:
|
||||
foo/baz: '*'
|
||||
@@ -0,0 +1,128 @@
|
||||
import * as sinon from 'sinon';
|
||||
import { extensions, window } from 'vscode';
|
||||
import 'mocha';
|
||||
import * as path from 'path';
|
||||
|
||||
import * as pq from 'proxyquire';
|
||||
|
||||
import { CliVersionConstraint, CodeQLCliServer } from '../../cli';
|
||||
import { CodeQLExtensionInterface } from '../../extension';
|
||||
import { expect } from 'chai';
|
||||
|
||||
const proxyquire = pq.noPreserveCache();
|
||||
|
||||
describe('Packaging commands', function() {
|
||||
let sandbox: sinon.SinonSandbox;
|
||||
|
||||
// up to 3 minutes per test
|
||||
this.timeout(3 * 60 * 1000);
|
||||
|
||||
let cli: CodeQLCliServer;
|
||||
let progress: sinon.SinonSpy;
|
||||
let quickPickSpy: sinon.SinonStub;
|
||||
let inputBoxSpy: sinon.SinonStub;
|
||||
let showAndLogErrorMessageSpy: sinon.SinonStub;
|
||||
let showAndLogInformationMessageSpy: sinon.SinonStub;
|
||||
let mod: any;
|
||||
|
||||
beforeEach(async function() {
|
||||
sandbox = sinon.createSandbox();
|
||||
|
||||
const extension = await extensions
|
||||
.getExtension<CodeQLExtensionInterface | Record<string, never>>(
|
||||
'GitHub.vscode-codeql'
|
||||
)!
|
||||
.activate();
|
||||
if ('cliServer' in extension) {
|
||||
cli = extension.cliServer;
|
||||
} else {
|
||||
throw new Error(
|
||||
'Extension not initialized. Make sure cli is downloaded and installed properly.'
|
||||
);
|
||||
}
|
||||
if (!(await cli.cliConstraints.supportsPackaging())) {
|
||||
console.log(`Packaging commands are not supported on CodeQL CLI v${CliVersionConstraint.CLI_VERSION_WITH_PACKAGING
|
||||
}. Skipping this test.`);
|
||||
this.skip();
|
||||
}
|
||||
progress = sandbox.spy();
|
||||
quickPickSpy = sandbox.stub(window, 'showQuickPick');
|
||||
inputBoxSpy = sandbox.stub(window, 'showInputBox');
|
||||
showAndLogErrorMessageSpy = sandbox.stub();
|
||||
showAndLogInformationMessageSpy = sandbox.stub();
|
||||
mod = proxyquire('../../packaging', {
|
||||
'./helpers': {
|
||||
showAndLogErrorMessage: showAndLogErrorMessageSpy,
|
||||
showAndLogInformationMessage: showAndLogInformationMessageSpy,
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
sandbox.restore();
|
||||
});
|
||||
|
||||
it('should download all core query packs', async () => {
|
||||
quickPickSpy.resolves('Download all core query packs');
|
||||
|
||||
await mod.handleDownloadPacks(cli, progress);
|
||||
expect(showAndLogInformationMessageSpy.firstCall.args[0]).to.contain(
|
||||
'Finished downloading packs.'
|
||||
);
|
||||
});
|
||||
|
||||
it('should download valid user-specified pack', async () => {
|
||||
quickPickSpy.resolves('Download custom specified pack');
|
||||
inputBoxSpy.resolves('codeql/csharp-solorigate-queries');
|
||||
|
||||
await mod.handleDownloadPacks(cli, progress);
|
||||
expect(showAndLogInformationMessageSpy.firstCall.args[0]).to.contain(
|
||||
'Finished downloading packs.'
|
||||
);
|
||||
});
|
||||
|
||||
it('should show error when downloading invalid user-specified pack', async () => {
|
||||
quickPickSpy.resolves('Download custom specified pack');
|
||||
inputBoxSpy.resolves('foo/not-a-real-pack@0.0.1');
|
||||
|
||||
await mod.handleDownloadPacks(cli, progress);
|
||||
|
||||
expect(showAndLogErrorMessageSpy.firstCall.args[0]).to.contain(
|
||||
'Unable to download all packs.'
|
||||
);
|
||||
});
|
||||
|
||||
it('should install valid workspace pack', async () => {
|
||||
const rootDir = path.join(__dirname, '../../../src/vscode-tests/cli-integration/data');
|
||||
quickPickSpy.resolves([
|
||||
{
|
||||
label: 'integration-test-queries-javascript',
|
||||
packRootDir: [rootDir],
|
||||
},
|
||||
]);
|
||||
|
||||
await mod.handleInstallPackDependencies(cli, progress);
|
||||
expect(showAndLogInformationMessageSpy.firstCall.args[0]).to.contain(
|
||||
'Finished installing pack dependencies.'
|
||||
);
|
||||
});
|
||||
|
||||
it('should throw an error when installing invalid workspace pack', async () => {
|
||||
const rootDir = path.join(__dirname, '../../../src/vscode-tests/cli-integration/data-invalid-pack');
|
||||
quickPickSpy.resolves([
|
||||
{
|
||||
label: 'foo/bar',
|
||||
packRootDir: [rootDir],
|
||||
},
|
||||
]);
|
||||
|
||||
try {
|
||||
// expect this to throw an error
|
||||
await mod.handleInstallPackDependencies(cli, progress);
|
||||
// This line should not be reached
|
||||
expect(true).to.be.false;
|
||||
} catch (error) {
|
||||
expect(error.message).to.contain('Unable to install pack dependencies');
|
||||
}
|
||||
});
|
||||
});
|
||||
@@ -44,7 +44,7 @@ const _10MB = _1MB * 10;
|
||||
|
||||
// CLI version to test. Hard code the latest as default. And be sure
|
||||
// to update the env if it is not otherwise set.
|
||||
const CLI_VERSION = process.env.CLI_VERSION || 'v2.7.3';
|
||||
const CLI_VERSION = process.env.CLI_VERSION || 'v2.7.6';
|
||||
process.env.CLI_VERSION = CLI_VERSION;
|
||||
|
||||
// Base dir where CLIs will be downloaded into
|
||||
|
||||
@@ -482,8 +482,8 @@ describe('databases', () => {
|
||||
|
||||
});
|
||||
|
||||
describe.only('findSourceArchive', function() {
|
||||
// not sure why, but some of these tests take more than two second to run.
|
||||
describe('findSourceArchive', function() {
|
||||
// not sure why, but some of these tests take more than two seconds to run.
|
||||
this.timeout(5000);
|
||||
|
||||
['src', 'output/src_archive'].forEach(name => {
|
||||
|
||||
@@ -25,11 +25,11 @@ describe('run-remote-query', function() {
|
||||
showInputBoxSpy = sandbox.stub(window, 'showInputBox');
|
||||
getRemoteRepositoryListsSpy = sandbox.stub();
|
||||
showAndLogErrorMessageSpy = sandbox.stub();
|
||||
mod = proxyquire('../../run-remote-query', {
|
||||
'./config': {
|
||||
mod = proxyquire('../../remote-queries/run-remote-query', {
|
||||
'../config': {
|
||||
getRemoteRepositoryLists: getRemoteRepositoryListsSpy
|
||||
},
|
||||
'./helpers': {
|
||||
'../helpers': {
|
||||
showAndLogErrorMessage: showAndLogErrorMessageSpy
|
||||
},
|
||||
});
|
||||
@@ -134,12 +134,12 @@ describe('run-remote-query', function() {
|
||||
logSpy = sandbox.stub();
|
||||
showAndLogErrorMessageSpy = sandbox.stub();
|
||||
showInformationMessageWithActionSpy = sandbox.stub();
|
||||
mod = proxyquire('../../run-remote-query', {
|
||||
'./helpers': {
|
||||
mod = proxyquire('../../remote-queries/run-remote-query', {
|
||||
'../helpers': {
|
||||
showAndLogErrorMessage: showAndLogErrorMessageSpy,
|
||||
showInformationMessageWithAction: showInformationMessageWithActionSpy
|
||||
},
|
||||
'./logging': {
|
||||
'../logging': {
|
||||
'logger': {
|
||||
log: logSpy
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@ import { sarifParser } from '../../sarif-parser';
|
||||
chai.use(chaiAsPromised);
|
||||
const expect = chai.expect;
|
||||
|
||||
describe.only('sarif parser', function() {
|
||||
describe('sarif parser', function() {
|
||||
const sarifDir = path.join(__dirname, 'data/sarif');
|
||||
it('should parse a valid SARIF file', async () => {
|
||||
const result = await sarifParser(path.join(sarifDir, 'validSarif.sarif'));
|
||||
@@ -22,4 +22,4 @@ describe.only('sarif parser', function() {
|
||||
const result = await sarifParser(path.join(sarifDir, 'emptyResultsSarif.sarif'));
|
||||
expect(result.runs[0].results).to.be.empty;
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -80,10 +80,19 @@ async function main() {
|
||||
if (dirs.includes(TestDir.CliIntegration)) {
|
||||
console.log('Installing required extensions');
|
||||
const cliPath = resolveCliPathFromVSCodeExecutablePath(vscodeExecutablePath);
|
||||
cp.spawnSync(cliPath, ['--install-extension', 'hbenl.vscode-test-explorer'], {
|
||||
encoding: 'utf-8',
|
||||
stdio: 'inherit'
|
||||
});
|
||||
cp.spawnSync(
|
||||
cliPath,
|
||||
[
|
||||
'--install-extension',
|
||||
'hbenl.vscode-test-explorer',
|
||||
'--install-extension',
|
||||
'ms-vscode.test-adapter-converter',
|
||||
],
|
||||
{
|
||||
encoding: 'utf-8',
|
||||
stdio: 'inherit',
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
console.log(`Running integration tests in these directories: ${dirs}`);
|
||||
|
||||
6
package-lock.json
generated
6
package-lock.json
generated
@@ -1,6 +0,0 @@
|
||||
{
|
||||
"name": "vscode-codeql",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {}
|
||||
}
|
||||
Reference in New Issue
Block a user