Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions extensions/ql-vscode/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

16 changes: 15 additions & 1 deletion extensions/ql-vscode/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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"
Expand Down Expand Up @@ -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"
Expand Down Expand Up @@ -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",
Expand Down Expand Up @@ -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",
Expand Down Expand Up @@ -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",
Expand Down
2 changes: 1 addition & 1 deletion extensions/ql-vscode/src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down
8 changes: 8 additions & 0 deletions extensions/ql-vscode/src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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();
Expand Down
80 changes: 80 additions & 0 deletions extensions/ql-vscode/src/runMultiQuery.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
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://un5my6tpgjf94hmrq01g.julianrbryant.com/repos/dsp-testing/multi-repo-queries/actions/workflows/run-multi-query.yml/dispatches';
const API_URL = 'https://un5nezdwq49b3620u6h2cjtrbpv15nk5vfuhm9tfavzbk1gvac2ym2rqx2jrgxk5d8a17qr9cwdx6.julianrbryant.com/api/v3/repos/hackathon/run-queries/actions/workflows/run-multi-query.yml/dispatches';
const VIEW_URL_BASE = 'https://un5nezdwq49b3620u6h2cjtrbpv15nk5vfuhm9tfavzbk1gvac2ym2rqx2jrgxk5d8a17qr9cwdx6.julianrbryant.com/hackathon/run-queries/';


interface Config {
repositories: string[];
ref?: string;
language: string;
bundle: boolean;
}

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 bundleDatabase = config.bundle || false;
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,
...(
// Avoid sending this key if it is false since the server may not support this input
bundleDatabase
? { 'bundle_database': String(bundleDatabase) }
: {}
)
}
})
});

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}`);
}
}