Skip to content

Commit 84be3fb

Browse files
committed
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.
1 parent 370dbcb commit 84be3fb

5 files changed

Lines changed: 107 additions & 2 deletions

File tree

extensions/ql-vscode/package-lock.json

Lines changed: 11 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

extensions/ql-vscode/package.json

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,10 @@
186186
"command": "codeQL.runQueries",
187187
"title": "CodeQL: Run Queries in Selected Files"
188188
},
189+
{
190+
"command": "codeQL.scheduleMultiQuery",
191+
"title": "CodeQL: Schedule Multi-Query"
192+
},
189193
{
190194
"command": "codeQL.quickEval",
191195
"title": "CodeQL: Quick Evaluation"
@@ -534,6 +538,10 @@
534538
"command": "codeQL.runQuery",
535539
"when": "resourceLangId == ql && resourceExtname == .ql"
536540
},
541+
{
542+
"command": "codeQL.scheduleMultiQuery",
543+
"when": "resourceLangId == ql && resourceExtname == .ql"
544+
},
537545
{
538546
"command": "codeQL.runQueries",
539547
"when": "false"
@@ -656,6 +664,10 @@
656664
"command": "codeQL.runQuery",
657665
"when": "editorLangId == ql && resourceExtname == .ql"
658666
},
667+
{
668+
"command": "codeQL.scheduleMultiQuery",
669+
"when": "editorLangId == ql && resourceExtname == .ql"
670+
},
659671
{
660672
"command": "codeQL.quickEval",
661673
"when": "editorLangId == ql"
@@ -694,7 +706,7 @@
694706
},
695707
{
696708
"view": "codeQLQueryHistory",
697-
"contents": "Run the 'CodeQL: Run Query' command on a QL query.\n[Run Query](command:codeQL.runQuery)"
709+
"contents": "Run the 'CodeQL: Run Query' command on a QL query.\n[Run Query](command:codeQL.runQuery)\n[Schedule Multi-Query](command:codeQL.scheduleMultiQuery)"
698710
},
699711
{
700712
"view": "codeQLDatabases",
@@ -730,6 +742,7 @@
730742
"tmp-promise": "~3.0.2",
731743
"tree-kill": "~1.2.2",
732744
"unzipper": "~0.10.5",
745+
"uuid": "^8.3.2",
733746
"vscode-jsonrpc": "^5.0.1",
734747
"vscode-languageclient": "^6.1.3",
735748
"vscode-test-adapter-api": "~1.7.0",
@@ -761,6 +774,7 @@
761774
"@types/through2": "^2.0.36",
762775
"@types/tmp": "^0.1.0",
763776
"@types/unzipper": "~0.10.1",
777+
"@types/uuid": "^8.3.0",
764778
"@types/vscode": "^1.43.0",
765779
"@types/webpack": "^4.32.1",
766780
"@types/xml2js": "~0.4.4",

extensions/ql-vscode/src/config.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ const ROOT_SETTING = new Setting('codeQL');
4444
const DISTRIBUTION_SETTING = new Setting('cli', ROOT_SETTING);
4545
const CUSTOM_CODEQL_PATH_SETTING = new Setting('executablePath', DISTRIBUTION_SETTING);
4646
const INCLUDE_PRERELEASE_SETTING = new Setting('includePrerelease', DISTRIBUTION_SETTING);
47-
const PERSONAL_ACCESS_TOKEN_SETTING = new Setting('personalAccessToken', DISTRIBUTION_SETTING);
47+
export const PERSONAL_ACCESS_TOKEN_SETTING = new Setting('personalAccessToken', DISTRIBUTION_SETTING);
4848
const QUERY_HISTORY_SETTING = new Setting('queryHistory', ROOT_SETTING);
4949
const QUERY_HISTORY_FORMAT_SETTING = new Setting('format', QUERY_HISTORY_SETTING);
5050

extensions/ql-vscode/src/extension.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ import { QLTestAdapterFactory } from './test-adapter';
5959
import { TestUIService } from './test-ui';
6060
import { CompareInterfaceManager } from './compare/compare-interface';
6161
import { gatherQlFiles } from './pure/files';
62+
import runMultiQuery from './runMultiQuery';
6263

6364
/**
6465
* extension.ts
@@ -592,6 +593,13 @@ async function activateWithInstalledDistribution(
592593
)
593594
);
594595

596+
ctx.subscriptions.push(
597+
helpers.commandRunner('codeQL.scheduleMultiQuery', async (
598+
uri: Uri | undefined
599+
) => {
600+
runMultiQuery(uri || window.activeTextEditor?.document.uri);
601+
})
602+
);
595603
ctx.subscriptions.push(
596604
helpers.commandRunner('codeQL.restartQueryServer', async () => {
597605
await qs.restartQueryServer();
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
import { Uri, workspace } from 'vscode';
2+
import * as yaml from 'js-yaml';
3+
import * as fs from 'fs-extra';
4+
import * as path from 'path';
5+
import fetch from 'node-fetch';
6+
import { showAndLogErrorMessage, showAndLogInformationMessage } from './helpers';
7+
import { PERSONAL_ACCESS_TOKEN_SETTING } from './config';
8+
9+
// const BASE_URL = 'https://api.github.com/repos/dsp-testing/multi-repo-queries/actions/workflows/run-multi-query.yml/dispatches';
10+
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';
11+
const VIEW_URL_BASE = 'https://cbraynor-3be288ce6.service.bpdev-us-east-1.github.net/hackathon/run-queries/';
12+
13+
14+
interface Config {
15+
repositories: string[];
16+
ref?: string;
17+
language: string;
18+
}
19+
20+
export default async function runMultiQuery(uri?: Uri) {
21+
if (!uri || !uri.fsPath.endsWith('.ql')) {
22+
return;
23+
}
24+
25+
const token = PERSONAL_ACCESS_TOKEN_SETTING.getValue();
26+
if (!token) {
27+
showAndLogErrorMessage('Missing PAT for dispatching the actions run. Add a "codeQL.cli.personalAccessToken" user setting with your PAT in it.');
28+
return;
29+
}
30+
31+
const queryFile = uri.fsPath;
32+
const query = await fs.readFile(queryFile, 'utf8');
33+
34+
const repositoriesFile = queryFile.substring(0, queryFile.length - '.ql'.length) + '.repositories';
35+
if (!(await fs.pathExists(repositoriesFile))) {
36+
showAndLogErrorMessage(`Missing file: '${repositoriesFile}' to specify the repositories to run against.`);
37+
return;
38+
}
39+
40+
const config = yaml.safeLoad(await fs.readFile(repositoriesFile, 'utf8')) as Config;
41+
42+
const ref = config.ref || 'main';
43+
const language = config.language;
44+
const repositories = JSON.stringify(config.repositories);
45+
const queryRunGuid = `${path.basename(queryFile)}-${Date.now()}`;
46+
47+
const apiUrl = workspace.getConfiguration('codeQL.cli').get('multiQueryBaseUrl', API_URL);
48+
const viewUrl = workspace.getConfiguration('codeQL.cli').get('multiQueryViewUrl', VIEW_URL_BASE);
49+
50+
const result = await fetch(apiUrl, {
51+
method: 'POST',
52+
headers: {
53+
Accept: 'application/vnd.github.v3+json',
54+
Authorization: `token ${token}`
55+
},
56+
body: JSON.stringify({
57+
ref,
58+
inputs: {
59+
language,
60+
repositories,
61+
query,
62+
'query_run_guid': queryRunGuid
63+
}
64+
})
65+
});
66+
67+
if (result.ok) {
68+
showAndLogInformationMessage(`Successfully scheduled runs. [Check it out here](${viewUrl}/security/code-scanning?query=tool%3A${queryRunGuid})`);
69+
} else {
70+
showAndLogErrorMessage(`Failed to schedule run: ${result.status} ${result.statusText}`);
71+
}
72+
}

0 commit comments

Comments
 (0)