Add new setting to specify controller repo

This commit is contained in:
shati-patel
2021-09-28 14:15:26 +01:00
committed by Shati Patel
parent 41ae5a4b5f
commit 7a79d39e23
3 changed files with 40 additions and 13 deletions

View File

@@ -256,6 +256,13 @@
},
"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>`)."
},
"codeQL.remoteQueries.controllerRepo": {
"type": "string",
"default": "",
"pattern": "^$|^(?:[a-zA-Z0-9]+-)*[a-zA-Z0-9]+/[a-zA-Z0-9-_]+$",
"patternErrorMessage": "Please enter a valid GitHub repository",
"markdownDescription": "[For internal use only] The name of the GitHub repository where you can view the progress and results of the \"Run Remote query\" command. The repository should be of the form `<owner>/<repo>`)."
}
}
},

View File

@@ -313,3 +313,15 @@ const REMOTE_REPO_LISTS = new Setting('repositoryLists', REMOTE_QUERIES_SETTING)
export function getRemoteRepositoryLists(): Record<string, string[]> | undefined {
return REMOTE_REPO_LISTS.getValue<Record<string, string[]>>() || undefined;
}
/**
* The name of the "controller" repository that you want to use with the "Run Remote query" command.
* Note: This command is only available for internal users.
*
* This setting should be a GitHub repository of the form `<owner>/<repo>`.
*/
const REMOTE_CONTROLLER_REPO = new Setting('controllerRepo', REMOTE_QUERIES_SETTING);
export function getRemoteControllerRepo(): string | undefined {
return REMOTE_CONTROLLER_REPO.getValue<string>() || undefined;
}

View File

@@ -5,17 +5,13 @@ import { findLanguage, showAndLogErrorMessage, showAndLogInformationMessage, sho
import { Credentials } from './authentication';
import * as cli from './cli';
import { logger } from './logging';
import { getRemoteRepositoryLists } from './config';
import { getRemoteControllerRepo, getRemoteRepositoryLists } from './config';
interface Config {
repositories: string[];
ref?: string;
language?: string;
}
// Test "controller" repository and workflow.
const OWNER = 'dsp-testing';
const REPO = 'qc-controller';
interface RepoListQuickPickItem extends QuickPickItem {
repoList: string[];
}
@@ -107,18 +103,30 @@ export async function runRemoteQuery(cliServer: cli.CodeQLCliServer, credentials
return; // No error message needed, since `getRepositories` already displays one.
}
await runRemoteQueriesApiRequest(credentials, ref, language, repositories, query);
// Get the controller repo
let owner: string;
let repo: string;
const controllerRepo = getRemoteControllerRepo();
if (controllerRepo) {
void logger.log(`Using controller repository: ${controllerRepo}`);
[owner, repo] = controllerRepo.split('/');
} else {
[owner, repo] = ['dsp-testing', 'qc-controller'];
void logger.log(`No controller repository defined in the 'codeQL.remoteQueries.controllerRepo' setting. Using default repository: ${owner}/${repo}.`);
}
await runRemoteQueriesApiRequest(credentials, ref, language, repositories, query, owner, repo);
}
async function runRemoteQueriesApiRequest(credentials: Credentials, ref: string, language: string, repositories: string[], query: string) {
async function runRemoteQueriesApiRequest(credentials: Credentials, ref: string, language: string, repositories: string[], query: string, owner: string, repo: string) {
const octokit = await credentials.getOctokit();
try {
await octokit.request(
'POST /repos/:owner/:repo/code-scanning/codeql/queries',
{
owner: OWNER,
repo: REPO,
owner,
repo,
data: {
ref: ref,
language: language,
@@ -127,15 +135,15 @@ async function runRemoteQueriesApiRequest(credentials: Credentials, ref: string,
}
}
);
void showAndLogInformationMessage(`Successfully scheduled runs. [Click here to see the progress](https://github.com/${OWNER}/${REPO}/actions).`);
void showAndLogInformationMessage(`Successfully scheduled runs. [Click here to see the progress](https://github.com/${owner}/${repo}/actions).`);
} catch (error) {
await attemptRerun(error, credentials, ref, language, repositories, query);
await attemptRerun(error, credentials, ref, language, repositories, query, owner, repo);
}
}
/** Attempts to rerun the query on only the valid repositories */
export async function attemptRerun(error: any, credentials: Credentials, ref: string, language: string, repositories: string[], query: string) {
export async function attemptRerun(error: any, credentials: Credentials, ref: string, language: string, repositories: string[], query: string, owner: string, repo: string) {
if (typeof error.message === 'string' && error.message.includes('Some repositories were invalid')) {
const invalidRepos = error?.response?.data?.invalid_repos || [];
const reposWithoutDbUploads = error?.response?.data?.repos_without_db_uploads || [];
@@ -158,7 +166,7 @@ export async function attemptRerun(error: any, credentials: Credentials, ref: st
if (rerunQuery) {
const validRepositories = repositories.filter(r => !invalidRepos.includes(r) && !reposWithoutDbUploads.includes(r));
void logger.log(`Rerunning query on set of valid repositories: ${JSON.stringify(validRepositories)}`);
await runRemoteQueriesApiRequest(credentials, ref, language, validRepositories, query);
await runRemoteQueriesApiRequest(credentials, ref, language, validRepositories, query, owner, repo);
}
} else {