From 84be3fb6bae3067ef2fb64365ce98fdd0b1dd71a Mon Sep 17 00:00:00 2001 From: Andrew Eisenberg Date: Wed, 9 Dec 2020 10:28:54 -0800 Subject: [PATCH 1/2] Hackathon: Create command to issue multi-queries Need to add your PAT as a setting to codeQL.cli.personalAccessToken. Make sure to create a new PAT for this and assign `repo` privileges so that it can dispatch actions. --- extensions/ql-vscode/package-lock.json | 11 ++++ extensions/ql-vscode/package.json | 16 ++++- extensions/ql-vscode/src/config.ts | 2 +- extensions/ql-vscode/src/extension.ts | 8 +++ extensions/ql-vscode/src/runMultiQuery.ts | 72 +++++++++++++++++++++++ 5 files changed, 107 insertions(+), 2 deletions(-) create mode 100644 extensions/ql-vscode/src/runMultiQuery.ts diff --git a/extensions/ql-vscode/package-lock.json b/extensions/ql-vscode/package-lock.json index ed9d08accb0..ab7c52e11aa 100644 --- a/extensions/ql-vscode/package-lock.json +++ b/extensions/ql-vscode/package-lock.json @@ -470,6 +470,12 @@ "@types/node": "*" } }, + "@types/uuid": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-8.3.0.tgz", + "integrity": "sha512-eQ9qFW/fhfGJF8WKHGEHZEyVWfZxrT+6CLIJGBcZPfxUh/+BnEj+UCGYMlr9qZuX/2AltsvwrGqp0LhEW8D0zQ==", + "dev": true + }, "@types/vinyl": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/@types/vinyl/-/vinyl-2.0.4.tgz", @@ -9046,6 +9052,11 @@ "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" }, + "uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==" + }, "v8-compile-cache": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.1.1.tgz", diff --git a/extensions/ql-vscode/package.json b/extensions/ql-vscode/package.json index ebe6aa83564..66dae8da072 100644 --- a/extensions/ql-vscode/package.json +++ b/extensions/ql-vscode/package.json @@ -186,6 +186,10 @@ "command": "codeQL.runQueries", "title": "CodeQL: Run Queries in Selected Files" }, + { + "command": "codeQL.scheduleMultiQuery", + "title": "CodeQL: Schedule Multi-Query" + }, { "command": "codeQL.quickEval", "title": "CodeQL: Quick Evaluation" @@ -534,6 +538,10 @@ "command": "codeQL.runQuery", "when": "resourceLangId == ql && resourceExtname == .ql" }, + { + "command": "codeQL.scheduleMultiQuery", + "when": "resourceLangId == ql && resourceExtname == .ql" + }, { "command": "codeQL.runQueries", "when": "false" @@ -656,6 +664,10 @@ "command": "codeQL.runQuery", "when": "editorLangId == ql && resourceExtname == .ql" }, + { + "command": "codeQL.scheduleMultiQuery", + "when": "editorLangId == ql && resourceExtname == .ql" + }, { "command": "codeQL.quickEval", "when": "editorLangId == ql" @@ -694,7 +706,7 @@ }, { "view": "codeQLQueryHistory", - "contents": "Run the 'CodeQL: Run Query' command on a QL query.\n[Run Query](command:codeQL.runQuery)" + "contents": "Run the 'CodeQL: Run Query' command on a QL query.\n[Run Query](command:codeQL.runQuery)\n[Schedule Multi-Query](command:codeQL.scheduleMultiQuery)" }, { "view": "codeQLDatabases", @@ -730,6 +742,7 @@ "tmp-promise": "~3.0.2", "tree-kill": "~1.2.2", "unzipper": "~0.10.5", + "uuid": "^8.3.2", "vscode-jsonrpc": "^5.0.1", "vscode-languageclient": "^6.1.3", "vscode-test-adapter-api": "~1.7.0", @@ -761,6 +774,7 @@ "@types/through2": "^2.0.36", "@types/tmp": "^0.1.0", "@types/unzipper": "~0.10.1", + "@types/uuid": "^8.3.0", "@types/vscode": "^1.43.0", "@types/webpack": "^4.32.1", "@types/xml2js": "~0.4.4", diff --git a/extensions/ql-vscode/src/config.ts b/extensions/ql-vscode/src/config.ts index 170ce080cd1..b26dd05ad37 100644 --- a/extensions/ql-vscode/src/config.ts +++ b/extensions/ql-vscode/src/config.ts @@ -44,7 +44,7 @@ const ROOT_SETTING = new Setting('codeQL'); const DISTRIBUTION_SETTING = new Setting('cli', ROOT_SETTING); const CUSTOM_CODEQL_PATH_SETTING = new Setting('executablePath', DISTRIBUTION_SETTING); const INCLUDE_PRERELEASE_SETTING = new Setting('includePrerelease', DISTRIBUTION_SETTING); -const PERSONAL_ACCESS_TOKEN_SETTING = new Setting('personalAccessToken', DISTRIBUTION_SETTING); +export const PERSONAL_ACCESS_TOKEN_SETTING = new Setting('personalAccessToken', DISTRIBUTION_SETTING); const QUERY_HISTORY_SETTING = new Setting('queryHistory', ROOT_SETTING); const QUERY_HISTORY_FORMAT_SETTING = new Setting('format', QUERY_HISTORY_SETTING); diff --git a/extensions/ql-vscode/src/extension.ts b/extensions/ql-vscode/src/extension.ts index b113f2a06ee..90feb66330d 100644 --- a/extensions/ql-vscode/src/extension.ts +++ b/extensions/ql-vscode/src/extension.ts @@ -59,6 +59,7 @@ import { QLTestAdapterFactory } from './test-adapter'; import { TestUIService } from './test-ui'; import { CompareInterfaceManager } from './compare/compare-interface'; import { gatherQlFiles } from './pure/files'; +import runMultiQuery from './runMultiQuery'; /** * extension.ts @@ -592,6 +593,13 @@ async function activateWithInstalledDistribution( ) ); + ctx.subscriptions.push( + helpers.commandRunner('codeQL.scheduleMultiQuery', async ( + uri: Uri | undefined + ) => { + runMultiQuery(uri || window.activeTextEditor?.document.uri); + }) + ); ctx.subscriptions.push( helpers.commandRunner('codeQL.restartQueryServer', async () => { await qs.restartQueryServer(); diff --git a/extensions/ql-vscode/src/runMultiQuery.ts b/extensions/ql-vscode/src/runMultiQuery.ts new file mode 100644 index 00000000000..e9987985c71 --- /dev/null +++ b/extensions/ql-vscode/src/runMultiQuery.ts @@ -0,0 +1,72 @@ +import { Uri, workspace } from 'vscode'; +import * as yaml from 'js-yaml'; +import * as fs from 'fs-extra'; +import * as path from 'path'; +import fetch from 'node-fetch'; +import { showAndLogErrorMessage, showAndLogInformationMessage } from './helpers'; +import { PERSONAL_ACCESS_TOKEN_SETTING } from './config'; + +// const BASE_URL = 'https://api.github.com/repos/dsp-testing/multi-repo-queries/actions/workflows/run-multi-query.yml/dispatches'; +const API_URL = 'https://cbraynor-3be288ce6.service.bpdev-us-east-1.github.net/api/v3/repos/hackathon/run-queries/actions/workflows/run-multi-query.yml/dispatches'; +const VIEW_URL_BASE = 'https://cbraynor-3be288ce6.service.bpdev-us-east-1.github.net/hackathon/run-queries/'; + + +interface Config { + repositories: string[]; + ref?: string; + language: string; +} + +export default async function runMultiQuery(uri?: Uri) { + if (!uri || !uri.fsPath.endsWith('.ql')) { + return; + } + + const token = PERSONAL_ACCESS_TOKEN_SETTING.getValue(); + if (!token) { + showAndLogErrorMessage('Missing PAT for dispatching the actions run. Add a "codeQL.cli.personalAccessToken" user setting with your PAT in it.'); + return; + } + + const queryFile = uri.fsPath; + const query = await fs.readFile(queryFile, 'utf8'); + + const repositoriesFile = queryFile.substring(0, queryFile.length - '.ql'.length) + '.repositories'; + if (!(await fs.pathExists(repositoriesFile))) { + showAndLogErrorMessage(`Missing file: '${repositoriesFile}' to specify the repositories to run against.`); + return; + } + + const config = yaml.safeLoad(await fs.readFile(repositoriesFile, 'utf8')) as Config; + + const ref = config.ref || 'main'; + const language = config.language; + const repositories = JSON.stringify(config.repositories); + const queryRunGuid = `${path.basename(queryFile)}-${Date.now()}`; + + const apiUrl = workspace.getConfiguration('codeQL.cli').get('multiQueryBaseUrl', API_URL); + const viewUrl = workspace.getConfiguration('codeQL.cli').get('multiQueryViewUrl', VIEW_URL_BASE); + + const result = await fetch(apiUrl, { + method: 'POST', + headers: { + Accept: 'application/vnd.github.v3+json', + Authorization: `token ${token}` + }, + body: JSON.stringify({ + ref, + inputs: { + language, + repositories, + query, + 'query_run_guid': queryRunGuid + } + }) + }); + + if (result.ok) { + showAndLogInformationMessage(`Successfully scheduled runs. [Check it out here](${viewUrl}/security/code-scanning?query=tool%3A${queryRunGuid})`); + } else { + showAndLogErrorMessage(`Failed to schedule run: ${result.status} ${result.statusText}`); + } +} From 89ae09f771a9af45184fce801eec5876e17f75f9 Mon Sep 17 00:00:00 2001 From: Andrew Eisenberg Date: Thu, 10 Dec 2020 15:51:13 -0800 Subject: [PATCH 2/2] Add bundle_database option --- extensions/ql-vscode/src/runMultiQuery.ts | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/extensions/ql-vscode/src/runMultiQuery.ts b/extensions/ql-vscode/src/runMultiQuery.ts index e9987985c71..8210510d584 100644 --- a/extensions/ql-vscode/src/runMultiQuery.ts +++ b/extensions/ql-vscode/src/runMultiQuery.ts @@ -15,6 +15,7 @@ interface Config { repositories: string[]; ref?: string; language: string; + bundle: boolean; } export default async function runMultiQuery(uri?: Uri) { @@ -41,6 +42,7 @@ export default async function runMultiQuery(uri?: Uri) { const ref = config.ref || 'main'; const language = config.language; + const bundleDatabase = config.bundle || false; const repositories = JSON.stringify(config.repositories); const queryRunGuid = `${path.basename(queryFile)}-${Date.now()}`; @@ -59,7 +61,13 @@ export default async function runMultiQuery(uri?: Uri) { language, repositories, query, - 'query_run_guid': queryRunGuid + 'query_run_guid': queryRunGuid, + ...( + // Avoid sending this key if it is false since the server may not support this input + bundleDatabase + ? { 'bundle_database': String(bundleDatabase) } + : {} + ) } }) });