Skip to content

Commit 087cae2

Browse files
committed
Add a new "remote repository lists" setting
1 parent 3d8032c commit 087cae2

File tree

3 files changed

+85
-11
lines changed

3 files changed

+85
-11
lines changed

extensions/ql-vscode/package.json

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -233,6 +233,19 @@
233233
"default": false,
234234
"scope": "application",
235235
"description": "Specifies whether or not to write telemetry events to the extension log."
236+
},
237+
"codeQL.remoteRepositoryLists": {
238+
"type": "object",
239+
"patternProperties": {
240+
".*": {
241+
"type": "array",
242+
"items": {
243+
"type": "string"
244+
}
245+
}
246+
},
247+
"default": null,
248+
"markdownDescription": "[For internal use only] Lists of GitHub repositories that you want to query remotely. This should be a JSON object where each key is a user-specified name for this repository list, and the value is an array of GitHub repositories (of the form `<owner>/<repo>`)."
236249
}
237250
}
238251
},

extensions/ql-vscode/src/config.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -291,3 +291,17 @@ export function isCanary() {
291291
* Avoids caching in the AST viewer if the user is also a canary user.
292292
*/
293293
export const NO_CACHE_AST_VIEWER = new Setting('disableCache', AST_VIEWER_SETTING);
294+
295+
/*
296+
* Lists of GitHub repositories that you want to query remotely via the "Run Remote query" command.
297+
* Note: This command is only available for internal users.
298+
*
299+
* This setting should be a JSON object where each key is a user-specified name (string),
300+
* and the value is an array of GitHub repositories (of the form `<owner>/<repo>`).
301+
*/
302+
303+
const REMOTE_REPO_LISTS = new Setting('remoteRepositoryLists', ROOT_SETTING);
304+
305+
export function getRemoteRepositoryLists(): Record<string, string[]> | undefined {
306+
return REMOTE_REPO_LISTS.getValue<Record<string, string[]>>() || undefined;
307+
}

extensions/ql-vscode/src/run-remote-query.ts

Lines changed: 58 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
1-
import { Uri, window } from 'vscode';
1+
import { QuickPickItem, Uri, window } from 'vscode';
22
import * as yaml from 'js-yaml';
33
import * as fs from 'fs-extra';
44
import { getOnDiskWorkspaceFolders, showAndLogErrorMessage, showAndLogInformationMessage } from './helpers';
55
import { Credentials } from './authentication';
66
import * as cli from './cli';
77
import { logger } from './logging';
8-
8+
import { getRemoteRepositoryLists } from './config';
99
interface Config {
1010
repositories: string[];
1111
ref?: string;
@@ -47,6 +47,41 @@ export async function findLanguage(
4747
return language;
4848
}
4949

50+
interface RepoListQuickPickItem extends QuickPickItem {
51+
repoList: string[];
52+
}
53+
54+
/**
55+
* Gets the repositories to run the query against.
56+
*/
57+
async function getRepositories(): Promise<string[] | undefined> {
58+
const repoLists = getRemoteRepositoryLists();
59+
if (repoLists && Object.keys(repoLists).length) {
60+
const quickPickItems = Object.entries(repoLists).map<RepoListQuickPickItem>(([key, value]) => (
61+
{
62+
label: key, // the name of the repository list
63+
repoList: value, // the actual array of repositories
64+
}
65+
));
66+
const quickpick = await window.showQuickPick<RepoListQuickPickItem>(
67+
quickPickItems,
68+
{
69+
placeHolder: 'Select a repository list. You can define repository lists in the `codeQL.remoteRepositoryLists` setting.',
70+
ignoreFocusOut: true,
71+
});
72+
if (quickpick && quickpick.repoList.length > 0) {
73+
void logger.log(`Selected repositories: ${quickpick.repoList}`);
74+
return quickpick.repoList;
75+
} else {
76+
void showAndLogErrorMessage('No repositories selected.');
77+
return;
78+
}
79+
} else {
80+
void showAndLogErrorMessage('No repository lists defined. You can define repository lists in the `codeQL.remoteRepositoryLists` setting.');
81+
return;
82+
}
83+
}
84+
5085
export async function runRemoteQuery(cliServer: cli.CodeQLCliServer, credentials: Credentials, uri?: Uri) {
5186
if (!uri?.fsPath.endsWith('.ql')) {
5287
return;
@@ -59,19 +94,31 @@ export async function runRemoteQuery(cliServer: cli.CodeQLCliServer, credentials
5994
const query = await fs.readFile(queryFile, 'utf8');
6095

6196
const repositoriesFile = queryFile.substring(0, queryFile.length - '.ql'.length) + '.repositories';
62-
if (!(await fs.pathExists(repositoriesFile))) {
63-
void showAndLogErrorMessage(`Missing file: '${repositoriesFile}' to specify the repositories to run against. This file must be a sibling of ${queryFile}.`);
64-
return;
65-
}
97+
let ref: string | undefined;
98+
let language: string | undefined;
99+
let repositories: string[] | undefined;
66100

67-
const config = yaml.safeLoad(await fs.readFile(repositoriesFile, 'utf8')) as Config;
101+
// If the user has an explicit `.repositories` file, use that.
102+
// Otherwise, prompt user to select repositories from the `codeQL.remoteRepositoryLists` setting.
103+
if (await fs.pathExists(repositoriesFile)) {
104+
void logger.log(`Found '${repositoriesFile}'. Using information from that file to run ${queryFile}.`);
68105

69-
const ref = config.ref || 'main';
70-
const language = config.language || await findLanguage(cliServer, uri);
71-
const repositories = config.repositories;
106+
const config = yaml.safeLoad(await fs.readFile(repositoriesFile, 'utf8')) as Config;
107+
108+
ref = config.ref || 'main';
109+
language = config.language || await findLanguage(cliServer, uri);
110+
repositories = config.repositories;
111+
} else {
112+
ref = 'main';
113+
[language, repositories] = await Promise.all([findLanguage(cliServer, uri), getRepositories()]);
114+
}
72115

73116
if (!language) {
74-
return; // No error message needed, since `findlanguage` already displays one.
117+
return; // No error message needed, since `findLanguage` already displays one.
118+
}
119+
120+
if (!repositories || repositories.length === 0) {
121+
return; // No error message needed, since `getRepositories` already displays one.
75122
}
76123

77124
try {

0 commit comments

Comments
 (0)