Add a new "remote repository lists" setting

This commit is contained in:
shati-patel
2021-07-28 12:57:44 +01:00
committed by Shati Patel
parent 3d8032c9b7
commit 087cae287f
3 changed files with 86 additions and 12 deletions

View File

@@ -233,6 +233,19 @@
"default": false,
"scope": "application",
"description": "Specifies whether or not to write telemetry events to the extension log."
},
"codeQL.remoteRepositoryLists": {
"type": "object",
"patternProperties": {
".*": {
"type": "array",
"items": {
"type": "string"
}
}
},
"default": null,
"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>`)."
}
}
},

View File

@@ -291,3 +291,17 @@ export function isCanary() {
* Avoids caching in the AST viewer if the user is also a canary user.
*/
export const NO_CACHE_AST_VIEWER = new Setting('disableCache', AST_VIEWER_SETTING);
/*
* Lists of GitHub repositories that you want to query remotely via the "Run Remote query" command.
* Note: This command is only available for internal users.
*
* This setting should be a JSON object where each key is a user-specified name (string),
* and the value is an array of GitHub repositories (of the form `<owner>/<repo>`).
*/
const REMOTE_REPO_LISTS = new Setting('remoteRepositoryLists', ROOT_SETTING);
export function getRemoteRepositoryLists(): Record<string, string[]> | undefined {
return REMOTE_REPO_LISTS.getValue<Record<string, string[]>>() || undefined;
}

View File

@@ -1,11 +1,11 @@
import { Uri, window } from 'vscode';
import { QuickPickItem, Uri, window } from 'vscode';
import * as yaml from 'js-yaml';
import * as fs from 'fs-extra';
import { getOnDiskWorkspaceFolders, showAndLogErrorMessage, showAndLogInformationMessage } from './helpers';
import { Credentials } from './authentication';
import * as cli from './cli';
import { logger } from './logging';
import { getRemoteRepositoryLists } from './config';
interface Config {
repositories: string[];
ref?: string;
@@ -47,6 +47,41 @@ export async function findLanguage(
return language;
}
interface RepoListQuickPickItem extends QuickPickItem {
repoList: string[];
}
/**
* Gets the repositories to run the query against.
*/
async function getRepositories(): Promise<string[] | undefined> {
const repoLists = getRemoteRepositoryLists();
if (repoLists && Object.keys(repoLists).length) {
const quickPickItems = Object.entries(repoLists).map<RepoListQuickPickItem>(([key, value]) => (
{
label: key, // the name of the repository list
repoList: value, // the actual array of repositories
}
));
const quickpick = await window.showQuickPick<RepoListQuickPickItem>(
quickPickItems,
{
placeHolder: 'Select a repository list. You can define repository lists in the `codeQL.remoteRepositoryLists` setting.',
ignoreFocusOut: true,
});
if (quickpick && quickpick.repoList.length > 0) {
void logger.log(`Selected repositories: ${quickpick.repoList}`);
return quickpick.repoList;
} else {
void showAndLogErrorMessage('No repositories selected.');
return;
}
} else {
void showAndLogErrorMessage('No repository lists defined. You can define repository lists in the `codeQL.remoteRepositoryLists` setting.');
return;
}
}
export async function runRemoteQuery(cliServer: cli.CodeQLCliServer, credentials: Credentials, uri?: Uri) {
if (!uri?.fsPath.endsWith('.ql')) {
return;
@@ -59,19 +94,31 @@ export async function runRemoteQuery(cliServer: cli.CodeQLCliServer, credentials
const query = await fs.readFile(queryFile, 'utf8');
const repositoriesFile = queryFile.substring(0, queryFile.length - '.ql'.length) + '.repositories';
if (!(await fs.pathExists(repositoriesFile))) {
void showAndLogErrorMessage(`Missing file: '${repositoriesFile}' to specify the repositories to run against. This file must be a sibling of ${queryFile}.`);
return;
}
let ref: string | undefined;
let language: string | undefined;
let repositories: string[] | undefined;
// If the user has an explicit `.repositories` file, use that.
// Otherwise, prompt user to select repositories from the `codeQL.remoteRepositoryLists` setting.
if (await fs.pathExists(repositoriesFile)) {
void logger.log(`Found '${repositoriesFile}'. Using information from that file to run ${queryFile}.`);
const config = yaml.safeLoad(await fs.readFile(repositoriesFile, 'utf8')) as Config;
const ref = config.ref || 'main';
const language = config.language || await findLanguage(cliServer, uri);
const repositories = config.repositories;
ref = config.ref || 'main';
language = config.language || await findLanguage(cliServer, uri);
repositories = config.repositories;
} else {
ref = 'main';
[language, repositories] = await Promise.all([findLanguage(cliServer, uri), getRepositories()]);
}
if (!language) {
return; // No error message needed, since `findlanguage` already displays one.
return; // No error message needed, since `findLanguage` already displays one.
}
if (!repositories || repositories.length === 0) {
return; // No error message needed, since `getRepositories` already displays one.
}
try {