Merge pull request #1538 from github/robertbrignull/submit-variant-analysis
Implement submitting a live-results variant analysis
This commit is contained in:
@@ -6,6 +6,7 @@ import {
|
||||
VariantAnalysisRepoTask,
|
||||
VariantAnalysisSubmissionRequest
|
||||
} from './variant-analysis';
|
||||
import { Repository } from './repository';
|
||||
|
||||
export async function submitVariantAnalysis(
|
||||
credentials: Credentials,
|
||||
@@ -73,13 +74,13 @@ export async function getVariantAnalysisRepo(
|
||||
return response.data;
|
||||
}
|
||||
|
||||
export async function getRepositoryIdFromNwo(
|
||||
export async function getRepositoryFromNwo(
|
||||
credentials: Credentials,
|
||||
owner: string,
|
||||
repo: string
|
||||
): Promise<number> {
|
||||
): Promise<Repository> {
|
||||
const octokit = await credentials.getOctokit();
|
||||
|
||||
const response = await octokit.rest.repos.get({ owner, repo });
|
||||
return response.data.id;
|
||||
return response.data as Repository;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
import { RemoteQuery } from './remote-query';
|
||||
import { VariantAnalysis } from './shared/variant-analysis';
|
||||
|
||||
export interface RemoteQuerySubmissionResult {
|
||||
queryDirPath?: string;
|
||||
query?: RemoteQuery;
|
||||
variantAnalysis?: VariantAnalysis;
|
||||
}
|
||||
|
||||
@@ -17,14 +17,17 @@ import {
|
||||
import { Credentials } from '../authentication';
|
||||
import * as cli from '../cli';
|
||||
import { logger } from '../logging';
|
||||
import { getActionBranch, getRemoteControllerRepo, setRemoteControllerRepo } from '../config';
|
||||
import { getActionBranch, getRemoteControllerRepo, isVariantAnalysisLiveResultsEnabled, setRemoteControllerRepo } from '../config';
|
||||
import { ProgressCallback, UserCancellationException } from '../commandRunner';
|
||||
import { OctokitResponse } from '@octokit/types/dist-types';
|
||||
import { OctokitResponse, RequestError } from '@octokit/types/dist-types';
|
||||
import { RemoteQuery } from './remote-query';
|
||||
import { RemoteQuerySubmissionResult } from './remote-query-submission-result';
|
||||
import { QueryMetadata } from '../pure/interface-types';
|
||||
import { getErrorMessage, REPO_REGEX } from '../pure/helpers-pure';
|
||||
import * as ghApiClient from './gh-api/gh-api-client';
|
||||
import { getRepositorySelection, isValidSelection, RepositorySelection } from './repository-selection';
|
||||
import { parseVariantAnalysisQueryLanguage, VariantAnalysis, VariantAnalysisStatus, VariantAnalysisSubmission } from './shared/variant-analysis';
|
||||
import { Repository } from './shared/repository';
|
||||
|
||||
export interface QlPack {
|
||||
name: string;
|
||||
@@ -210,31 +213,7 @@ export async function runRemoteQuery(
|
||||
message: 'Determining controller repo'
|
||||
});
|
||||
|
||||
// Get the controller repo from the config, if it exists.
|
||||
// If it doesn't exist, prompt the user to enter it, and save that value to the config.
|
||||
let controllerRepo: string | undefined;
|
||||
controllerRepo = getRemoteControllerRepo();
|
||||
if (!controllerRepo || !REPO_REGEX.test(controllerRepo)) {
|
||||
void logger.log(controllerRepo ? 'Invalid controller repository name.' : 'No controller repository defined.');
|
||||
controllerRepo = await window.showInputBox({
|
||||
title: 'Controller repository in which to run the GitHub Actions workflow for this variant analysis',
|
||||
placeHolder: '<owner>/<repo>',
|
||||
prompt: 'Enter the name of a GitHub repository in the format <owner>/<repo>',
|
||||
ignoreFocusOut: true,
|
||||
});
|
||||
if (!controllerRepo) {
|
||||
void showAndLogErrorMessage('No controller repository entered.');
|
||||
return;
|
||||
} else if (!REPO_REGEX.test(controllerRepo)) { // Check if user entered invalid input
|
||||
void showAndLogErrorMessage('Invalid repository format. Must be a valid GitHub repository in the format <owner>/<repo>.');
|
||||
return;
|
||||
}
|
||||
void logger.log(`Setting the controller repository as: ${controllerRepo}`);
|
||||
await setRemoteControllerRepo(controllerRepo);
|
||||
}
|
||||
|
||||
void logger.log(`Using controller repository: ${controllerRepo}`);
|
||||
const [owner, repo] = controllerRepo.split('/');
|
||||
const controllerRepo = await getControllerRepo(credentials);
|
||||
|
||||
progress({
|
||||
maxStep: 4,
|
||||
@@ -259,31 +238,84 @@ export async function runRemoteQuery(
|
||||
});
|
||||
|
||||
const actionBranch = getActionBranch();
|
||||
const apiResponse = await runRemoteQueriesApiRequest(credentials, actionBranch, language, repoSelection, owner, repo, base64Pack, dryRun);
|
||||
const queryStartTime = Date.now();
|
||||
const queryMetadata = await tryGetQueryMetadata(cliServer, queryFile);
|
||||
|
||||
if (dryRun) {
|
||||
return { queryDirPath: remoteQueryDir.path };
|
||||
} else {
|
||||
if (!apiResponse) {
|
||||
return;
|
||||
if (isVariantAnalysisLiveResultsEnabled()) {
|
||||
const queryName = getQueryName(queryMetadata, queryFile);
|
||||
const variantAnalysisLanguage = parseVariantAnalysisQueryLanguage(language);
|
||||
if (variantAnalysisLanguage === undefined) {
|
||||
throw new UserCancellationException(`Found unsupported language: ${language}`);
|
||||
}
|
||||
|
||||
const workflowRunId = apiResponse.workflow_run_id;
|
||||
const repositoryCount = apiResponse.repositories_queried.length;
|
||||
const remoteQuery = await buildRemoteQueryEntity(
|
||||
queryFile,
|
||||
queryMetadata,
|
||||
owner,
|
||||
repo,
|
||||
queryStartTime,
|
||||
workflowRunId,
|
||||
language,
|
||||
repositoryCount);
|
||||
const variantAnalysisSubmission: VariantAnalysisSubmission = {
|
||||
startTime: queryStartTime,
|
||||
actionRepoRef: actionBranch,
|
||||
controllerRepoId: controllerRepo.id,
|
||||
query: {
|
||||
name: queryName,
|
||||
filePath: queryFile,
|
||||
pack: base64Pack,
|
||||
language: variantAnalysisLanguage,
|
||||
},
|
||||
databases: {
|
||||
repositories: repoSelection.repositories,
|
||||
repositoryLists: repoSelection.repositoryLists,
|
||||
repositoryOwners: repoSelection.owners
|
||||
}
|
||||
};
|
||||
|
||||
// don't return the path because it has been deleted
|
||||
return { query: remoteQuery };
|
||||
const variantAnalysisResponse = await ghApiClient.submitVariantAnalysis(
|
||||
credentials,
|
||||
variantAnalysisSubmission
|
||||
);
|
||||
|
||||
const variantAnalysis: VariantAnalysis = {
|
||||
id: variantAnalysisResponse.id,
|
||||
controllerRepoId: variantAnalysisResponse.controller_repo.id,
|
||||
query: {
|
||||
name: variantAnalysisSubmission.query.name,
|
||||
filePath: variantAnalysisSubmission.query.filePath,
|
||||
language: variantAnalysisSubmission.query.language,
|
||||
},
|
||||
databases: {
|
||||
repositories: variantAnalysisSubmission.databases.repositories,
|
||||
repositoryLists: variantAnalysisSubmission.databases.repositoryLists,
|
||||
repositoryOwners: variantAnalysisSubmission.databases.repositoryOwners,
|
||||
},
|
||||
status: VariantAnalysisStatus.InProgress,
|
||||
};
|
||||
|
||||
// TODO: Remove once we have a proper notification
|
||||
void showAndLogInformationMessage('Variant analysis submitted for processing');
|
||||
void logger.log(`Variant analysis:\n${JSON.stringify(variantAnalysis, null, 2)}`);
|
||||
|
||||
return { variantAnalysis };
|
||||
|
||||
} else {
|
||||
const apiResponse = await runRemoteQueriesApiRequest(credentials, actionBranch, language, repoSelection, controllerRepo, base64Pack, dryRun);
|
||||
|
||||
if (dryRun) {
|
||||
return { queryDirPath: remoteQueryDir.path };
|
||||
} else {
|
||||
if (!apiResponse) {
|
||||
return;
|
||||
}
|
||||
|
||||
const workflowRunId = apiResponse.workflow_run_id;
|
||||
const repositoryCount = apiResponse.repositories_queried.length;
|
||||
const remoteQuery = await buildRemoteQueryEntity(
|
||||
queryFile,
|
||||
queryMetadata,
|
||||
controllerRepo,
|
||||
queryStartTime,
|
||||
workflowRunId,
|
||||
language,
|
||||
repositoryCount);
|
||||
|
||||
// don't return the path because it has been deleted
|
||||
return { query: remoteQuery };
|
||||
}
|
||||
}
|
||||
|
||||
} finally {
|
||||
@@ -301,8 +333,7 @@ async function runRemoteQueriesApiRequest(
|
||||
ref: string,
|
||||
language: string,
|
||||
repoSelection: RepositorySelection,
|
||||
owner: string,
|
||||
repo: string,
|
||||
controllerRepo: Repository,
|
||||
queryPackBase64: string,
|
||||
dryRun = false
|
||||
): Promise<void | QueriesResponse> {
|
||||
@@ -318,8 +349,7 @@ async function runRemoteQueriesApiRequest(
|
||||
if (dryRun) {
|
||||
void showAndLogInformationMessage('[DRY RUN] Would have sent request. See extension log for the payload.');
|
||||
void logger.log(JSON.stringify({
|
||||
owner,
|
||||
repo,
|
||||
controllerRepo,
|
||||
data: {
|
||||
...data,
|
||||
queryPackBase64: queryPackBase64.substring(0, 100) + '... ' + queryPackBase64.length + ' bytes'
|
||||
@@ -331,14 +361,13 @@ async function runRemoteQueriesApiRequest(
|
||||
try {
|
||||
const octokit = await credentials.getOctokit();
|
||||
const response: OctokitResponse<QueriesResponse, number> = await octokit.request(
|
||||
'POST /repos/:owner/:repo/code-scanning/codeql/queries',
|
||||
'POST /repos/:controllerRepo/code-scanning/codeql/queries',
|
||||
{
|
||||
owner,
|
||||
repo,
|
||||
controllerRepo: controllerRepo.fullName,
|
||||
data
|
||||
}
|
||||
);
|
||||
const { popupMessage, logMessage } = parseResponse(owner, repo, response.data);
|
||||
const { popupMessage, logMessage } = parseResponse(controllerRepo, response.data);
|
||||
void showAndLogInformationMessage(popupMessage, { fullMessage: logMessage });
|
||||
return response.data;
|
||||
} catch (error: any) {
|
||||
@@ -354,14 +383,14 @@ const eol = os.EOL;
|
||||
const eol2 = os.EOL + os.EOL;
|
||||
|
||||
// exported for testing only
|
||||
export function parseResponse(owner: string, repo: string, response: QueriesResponse) {
|
||||
export function parseResponse(controllerRepo: Repository, response: QueriesResponse) {
|
||||
const repositoriesQueried = response.repositories_queried;
|
||||
const repositoryCount = repositoriesQueried.length;
|
||||
|
||||
const popupMessage = `Successfully scheduled runs on ${pluralize(repositoryCount, 'repository', 'repositories')}. [Click here to see the progress](https://github.com/${owner}/${repo}/actions/runs/${response.workflow_run_id}).`
|
||||
const popupMessage = `Successfully scheduled runs on ${pluralize(repositoryCount, 'repository', 'repositories')}. [Click here to see the progress](https://github.com/${controllerRepo.fullName}/actions/runs/${response.workflow_run_id}).`
|
||||
+ (response.errors ? `${eol2}Some repositories could not be scheduled. See extension log for details.` : '');
|
||||
|
||||
let logMessage = `Successfully scheduled runs on ${pluralize(repositoryCount, 'repository', 'repositories')}. See https://github.com/${owner}/${repo}/actions/runs/${response.workflow_run_id}.`;
|
||||
let logMessage = `Successfully scheduled runs on ${pluralize(repositoryCount, 'repository', 'repositories')}. See https://github.com/${controllerRepo.fullName}/actions/runs/${response.workflow_run_id}.`;
|
||||
logMessage += `${eol2}Repositories queried:${eol}${repositoriesQueried.join(', ')}`;
|
||||
if (response.errors) {
|
||||
const { invalid_repositories, repositories_without_database, private_repositories, cutoff_repositories, cutoff_repositories_count } = response.errors;
|
||||
@@ -425,17 +454,15 @@ async function ensureNameAndSuite(queryPackDir: string, packRelativePath: string
|
||||
async function buildRemoteQueryEntity(
|
||||
queryFilePath: string,
|
||||
queryMetadata: QueryMetadata | undefined,
|
||||
controllerRepoOwner: string,
|
||||
controllerRepoName: string,
|
||||
controllerRepo: Repository,
|
||||
queryStartTime: number,
|
||||
workflowRunId: number,
|
||||
language: string,
|
||||
repositoryCount: number
|
||||
): Promise<RemoteQuery> {
|
||||
// The query name is either the name as specified in the query metadata, or the file name.
|
||||
const queryName = queryMetadata?.name ?? path.basename(queryFilePath);
|
||||
|
||||
const queryName = getQueryName(queryMetadata, queryFilePath);
|
||||
const queryText = await fs.readFile(queryFilePath, 'utf8');
|
||||
const [owner, name] = controllerRepo.fullName.split('/');
|
||||
|
||||
return {
|
||||
queryName,
|
||||
@@ -443,11 +470,59 @@ async function buildRemoteQueryEntity(
|
||||
queryText,
|
||||
language,
|
||||
controllerRepository: {
|
||||
owner: controllerRepoOwner,
|
||||
name: controllerRepoName,
|
||||
owner,
|
||||
name,
|
||||
},
|
||||
executionStartTime: queryStartTime,
|
||||
actionsWorkflowRunId: workflowRunId,
|
||||
repositoryCount,
|
||||
};
|
||||
}
|
||||
|
||||
function getQueryName(queryMetadata: QueryMetadata | undefined, queryFilePath: string): string {
|
||||
// The query name is either the name as specified in the query metadata, or the file name.
|
||||
return queryMetadata?.name ?? path.basename(queryFilePath);
|
||||
}
|
||||
|
||||
async function getControllerRepo(credentials: Credentials): Promise<Repository> {
|
||||
// Get the controller repo from the config, if it exists.
|
||||
// If it doesn't exist, prompt the user to enter it, and save that value to the config.
|
||||
let controllerRepoNwo: string | undefined;
|
||||
controllerRepoNwo = getRemoteControllerRepo();
|
||||
if (!controllerRepoNwo || !REPO_REGEX.test(controllerRepoNwo)) {
|
||||
void logger.log(controllerRepoNwo ? 'Invalid controller repository name.' : 'No controller repository defined.');
|
||||
controllerRepoNwo = await window.showInputBox({
|
||||
title: 'Controller repository in which to run the GitHub Actions workflow for this variant analysis',
|
||||
placeHolder: '<owner>/<repo>',
|
||||
prompt: 'Enter the name of a GitHub repository in the format <owner>/<repo>',
|
||||
ignoreFocusOut: true,
|
||||
});
|
||||
if (!controllerRepoNwo) {
|
||||
throw new UserCancellationException('No controller repository entered.');
|
||||
} else if (!REPO_REGEX.test(controllerRepoNwo)) { // Check if user entered invalid input
|
||||
throw new UserCancellationException('Invalid repository format. Must be a valid GitHub repository in the format <owner>/<repo>.');
|
||||
}
|
||||
void logger.log(`Setting the controller repository as: ${controllerRepoNwo}`);
|
||||
await setRemoteControllerRepo(controllerRepoNwo);
|
||||
}
|
||||
|
||||
void logger.log(`Using controller repository: ${controllerRepoNwo}`);
|
||||
const [owner, repo] = controllerRepoNwo.split('/');
|
||||
|
||||
try {
|
||||
const controllerRepo = await ghApiClient.getRepositoryFromNwo(credentials, owner, repo);
|
||||
void logger.log(`Controller repository ID: ${controllerRepo.id}`);
|
||||
return {
|
||||
id: controllerRepo.id,
|
||||
fullName: controllerRepo.full_name,
|
||||
private: controllerRepo.private,
|
||||
};
|
||||
|
||||
} catch (e: any) {
|
||||
if ((e as RequestError).status === 404) {
|
||||
throw new Error(`Controller repository "${owner}/${repo}" not found`);
|
||||
} else {
|
||||
throw new Error(`Error getting controller repository "${owner}/${repo}": ${e.message}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,6 +30,10 @@ export enum VariantAnalysisQueryLanguage {
|
||||
Ruby = 'ruby'
|
||||
}
|
||||
|
||||
export function parseVariantAnalysisQueryLanguage(language: string): VariantAnalysisQueryLanguage | undefined {
|
||||
return Object.values(VariantAnalysisQueryLanguage).find(x => x === language);
|
||||
}
|
||||
|
||||
export enum VariantAnalysisStatus {
|
||||
InProgress = 'inProgress',
|
||||
Succeeded = 'succeeded',
|
||||
|
||||
@@ -11,8 +11,13 @@ import { Credentials } from '../../../authentication';
|
||||
import { CliVersionConstraint, CodeQLCliServer } from '../../../cli';
|
||||
import { CodeQLExtensionInterface } from '../../../extension';
|
||||
import { setRemoteControllerRepo, setRemoteRepositoryLists } from '../../../config';
|
||||
import * as config from '../../../config';
|
||||
import { UserCancellationException } from '../../../commandRunner';
|
||||
import * as ghApiClient from '../../../remote-queries/gh-api/gh-api-client';
|
||||
import { lte } from 'semver';
|
||||
import { VariantAnalysis } from '../../../remote-queries/gh-api/variant-analysis';
|
||||
import { Repository } from '../../../remote-queries/gh-api/repository';
|
||||
import { VariantAnalysisStatus } from '../../../remote-queries/shared/variant-analysis';
|
||||
|
||||
describe('Remote queries', function() {
|
||||
const baseDir = path.join(__dirname, '../../../../src/vscode-tests/cli-integration');
|
||||
@@ -27,6 +32,8 @@ describe('Remote queries', function() {
|
||||
let token: CancellationToken;
|
||||
let progress: sinon.SinonSpy;
|
||||
let showQuickPickSpy: sinon.SinonStub;
|
||||
let getRepositoryFromNwoStub: sinon.SinonStub;
|
||||
let liveResultsStub: sinon.SinonStub;
|
||||
|
||||
// use `function` so we have access to `this`
|
||||
beforeEach(async function() {
|
||||
@@ -55,208 +62,309 @@ describe('Remote queries', function() {
|
||||
.onFirstCall().resolves({ repositories: ['github/vscode-codeql'] } as unknown as QuickPickItem)
|
||||
.onSecondCall().resolves('javascript' as unknown as QuickPickItem);
|
||||
|
||||
const dummyRepository: Repository = {
|
||||
id: 123,
|
||||
name: 'vscode-codeql',
|
||||
full_name: 'github/vscode-codeql',
|
||||
private: false,
|
||||
};
|
||||
getRepositoryFromNwoStub = sandbox.stub(ghApiClient, 'getRepositoryFromNwo').resolves(dummyRepository);
|
||||
|
||||
// always run in the vscode-codeql repo
|
||||
await setRemoteControllerRepo('github/vscode-codeql');
|
||||
await setRemoteRepositoryLists({ 'vscode-codeql': ['github/vscode-codeql'] });
|
||||
|
||||
liveResultsStub = sandbox.stub(config, 'isVariantAnalysisLiveResultsEnabled').returns(false);
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
afterEach(async () => {
|
||||
sandbox.restore();
|
||||
});
|
||||
|
||||
it('should run a remote query that is part of a qlpack', async () => {
|
||||
const fileUri = getFile('data-remote-qlpack/in-pack.ql');
|
||||
describe('when live results are not enabled', () => {
|
||||
it('should run a remote query that is part of a qlpack', async () => {
|
||||
const fileUri = getFile('data-remote-qlpack/in-pack.ql');
|
||||
|
||||
const querySubmissionResult = await runRemoteQuery(cli, credentials, fileUri, true, progress, token);
|
||||
expect(querySubmissionResult).to.be.ok;
|
||||
const queryPackRootDir = querySubmissionResult!.queryDirPath!;
|
||||
printDirectoryContents(queryPackRootDir);
|
||||
const querySubmissionResult = await runRemoteQuery(cli, credentials, fileUri, true, progress, token);
|
||||
expect(querySubmissionResult).to.be.ok;
|
||||
const queryPackRootDir = querySubmissionResult!.queryDirPath!;
|
||||
printDirectoryContents(queryPackRootDir);
|
||||
|
||||
// to retrieve the list of repositories
|
||||
expect(showQuickPickSpy).to.have.been.calledOnce;
|
||||
// to retrieve the list of repositories
|
||||
expect(showQuickPickSpy).to.have.been.calledOnce;
|
||||
|
||||
// check a few files that we know should exist and others that we know should not
|
||||
expect(getRepositoryFromNwoStub).to.have.been.calledOnce;
|
||||
|
||||
// the tarball to deliver to the server
|
||||
expect(fs.readdirSync(queryPackRootDir).find(f => f.startsWith('qlpack-') && f.endsWith('-generated.tgz'))).not.to.be.undefined;
|
||||
// check a few files that we know should exist and others that we know should not
|
||||
|
||||
const queryPackDir = path.join(queryPackRootDir, 'query-pack');
|
||||
printDirectoryContents(queryPackDir);
|
||||
// the tarball to deliver to the server
|
||||
expect(fs.readdirSync(queryPackRootDir).find(f => f.startsWith('qlpack-') && f.endsWith('-generated.tgz'))).not.to.be.undefined;
|
||||
|
||||
expect(fs.existsSync(path.join(queryPackDir, 'in-pack.ql'))).to.be.true;
|
||||
expect(fs.existsSync(path.join(queryPackDir, 'lib.qll'))).to.be.true;
|
||||
expect(fs.existsSync(path.join(queryPackDir, 'qlpack.yml'))).to.be.true;
|
||||
const queryPackDir = path.join(queryPackRootDir, 'query-pack');
|
||||
printDirectoryContents(queryPackDir);
|
||||
|
||||
// depending on the cli version, we should have one of these files
|
||||
expect(
|
||||
fs.existsSync(path.join(queryPackDir, 'qlpack.lock.yml')) ||
|
||||
fs.existsSync(path.join(queryPackDir, 'codeql-pack.lock.yml'))
|
||||
).to.be.true;
|
||||
expect(fs.existsSync(path.join(queryPackDir, 'not-in-pack.ql'))).to.be.false;
|
||||
expect(fs.existsSync(path.join(queryPackDir, 'in-pack.ql'))).to.be.true;
|
||||
expect(fs.existsSync(path.join(queryPackDir, 'lib.qll'))).to.be.true;
|
||||
expect(fs.existsSync(path.join(queryPackDir, 'qlpack.yml'))).to.be.true;
|
||||
|
||||
// the compiled pack
|
||||
const compiledPackDir = path.join(queryPackDir, '.codeql/pack/codeql-remote/query/0.0.0/');
|
||||
printDirectoryContents(compiledPackDir);
|
||||
// depending on the cli version, we should have one of these files
|
||||
expect(
|
||||
fs.existsSync(path.join(queryPackDir, 'qlpack.lock.yml')) ||
|
||||
fs.existsSync(path.join(queryPackDir, 'codeql-pack.lock.yml'))
|
||||
).to.be.true;
|
||||
expect(fs.existsSync(path.join(queryPackDir, 'not-in-pack.ql'))).to.be.false;
|
||||
|
||||
expect(fs.existsSync(path.join(compiledPackDir, 'in-pack.ql'))).to.be.true;
|
||||
expect(fs.existsSync(path.join(compiledPackDir, 'lib.qll'))).to.be.true;
|
||||
expect(fs.existsSync(path.join(compiledPackDir, 'qlpack.yml'))).to.be.true;
|
||||
// should have generated a correct qlpack file
|
||||
const qlpackContents: any = yaml.load(fs.readFileSync(path.join(compiledPackDir, 'qlpack.yml'), 'utf8'));
|
||||
expect(qlpackContents.name).to.equal('codeql-remote/query');
|
||||
// the compiled pack
|
||||
const compiledPackDir = path.join(queryPackDir, '.codeql/pack/codeql-remote/query/0.0.0/');
|
||||
printDirectoryContents(compiledPackDir);
|
||||
|
||||
// depending on the cli version, we should have one of these files
|
||||
expect(
|
||||
fs.existsSync(path.join(compiledPackDir, 'qlpack.lock.yml')) ||
|
||||
fs.existsSync(path.join(compiledPackDir, 'codeql-pack.lock.yml'))
|
||||
).to.be.true;
|
||||
expect(fs.existsSync(path.join(compiledPackDir, 'not-in-pack.ql'))).to.be.false;
|
||||
verifyQlPack(path.join(compiledPackDir, 'qlpack.yml'), 'in-pack.ql', '0.0.0', await pathSerializationBroken());
|
||||
expect(fs.existsSync(path.join(compiledPackDir, 'in-pack.ql'))).to.be.true;
|
||||
expect(fs.existsSync(path.join(compiledPackDir, 'lib.qll'))).to.be.true;
|
||||
expect(fs.existsSync(path.join(compiledPackDir, 'qlpack.yml'))).to.be.true;
|
||||
// should have generated a correct qlpack file
|
||||
const qlpackContents: any = yaml.load(fs.readFileSync(path.join(compiledPackDir, 'qlpack.yml'), 'utf8'));
|
||||
expect(qlpackContents.name).to.equal('codeql-remote/query');
|
||||
|
||||
const libraryDir = path.join(compiledPackDir, '.codeql/libraries/codeql');
|
||||
const packNames = fs.readdirSync(libraryDir).sort();
|
||||
// depending on the cli version, we should have one of these files
|
||||
expect(
|
||||
fs.existsSync(path.join(compiledPackDir, 'qlpack.lock.yml')) ||
|
||||
fs.existsSync(path.join(compiledPackDir, 'codeql-pack.lock.yml'))
|
||||
).to.be.true;
|
||||
expect(fs.existsSync(path.join(compiledPackDir, 'not-in-pack.ql'))).to.be.false;
|
||||
verifyQlPack(path.join(compiledPackDir, 'qlpack.yml'), 'in-pack.ql', '0.0.0', await pathSerializationBroken());
|
||||
|
||||
// check dependencies.
|
||||
// 2.7.4 and earlier have ['javascript-all', 'javascript-upgrades']
|
||||
// later only have ['javascript-all']. ensure this test can handle either
|
||||
expect(packNames.length).to.be.lessThan(3).and.greaterThan(0);
|
||||
expect(packNames[0]).to.deep.equal('javascript-all');
|
||||
const libraryDir = path.join(compiledPackDir, '.codeql/libraries/codeql');
|
||||
const packNames = fs.readdirSync(libraryDir).sort();
|
||||
|
||||
// check dependencies.
|
||||
// 2.7.4 and earlier have ['javascript-all', 'javascript-upgrades']
|
||||
// later only have ['javascript-all']. ensure this test can handle either
|
||||
expect(packNames.length).to.be.lessThan(3).and.greaterThan(0);
|
||||
expect(packNames[0]).to.deep.equal('javascript-all');
|
||||
});
|
||||
|
||||
it('should run a remote query that is not part of a qlpack', async () => {
|
||||
const fileUri = getFile('data-remote-no-qlpack/in-pack.ql');
|
||||
|
||||
const querySubmissionResult = await runRemoteQuery(cli, credentials, fileUri, true, progress, token);
|
||||
expect(querySubmissionResult).to.be.ok;
|
||||
const queryPackRootDir = querySubmissionResult!.queryDirPath!;
|
||||
|
||||
// to retrieve the list of repositories
|
||||
// and a second time to ask for the language
|
||||
expect(showQuickPickSpy).to.have.been.calledTwice;
|
||||
|
||||
expect(getRepositoryFromNwoStub).to.have.been.calledOnce;
|
||||
|
||||
// check a few files that we know should exist and others that we know should not
|
||||
|
||||
// the tarball to deliver to the server
|
||||
printDirectoryContents(queryPackRootDir);
|
||||
expect(fs.readdirSync(queryPackRootDir).find(f => f.startsWith('qlpack-') && f.endsWith('-generated.tgz'))).not.to.be.undefined;
|
||||
|
||||
const queryPackDir = path.join(queryPackRootDir, 'query-pack');
|
||||
printDirectoryContents(queryPackDir);
|
||||
|
||||
expect(fs.existsSync(path.join(queryPackDir, 'in-pack.ql'))).to.be.true;
|
||||
expect(fs.existsSync(path.join(queryPackDir, 'qlpack.yml'))).to.be.true;
|
||||
// depending on the cli version, we should have one of these files
|
||||
expect(
|
||||
fs.existsSync(path.join(queryPackDir, 'qlpack.lock.yml')) ||
|
||||
fs.existsSync(path.join(queryPackDir, 'codeql-pack.lock.yml'))
|
||||
).to.be.true;
|
||||
expect(fs.existsSync(path.join(queryPackDir, 'lib.qll'))).to.be.false;
|
||||
expect(fs.existsSync(path.join(queryPackDir, 'not-in-pack.ql'))).to.be.false;
|
||||
|
||||
// the compiled pack
|
||||
const compiledPackDir = path.join(queryPackDir, '.codeql/pack/codeql-remote/query/0.0.0/');
|
||||
printDirectoryContents(compiledPackDir);
|
||||
expect(fs.existsSync(path.join(compiledPackDir, 'in-pack.ql'))).to.be.true;
|
||||
expect(fs.existsSync(path.join(compiledPackDir, 'qlpack.yml'))).to.be.true;
|
||||
verifyQlPack(path.join(compiledPackDir, 'qlpack.yml'), 'in-pack.ql', '0.0.0', await pathSerializationBroken());
|
||||
|
||||
// depending on the cli version, we should have one of these files
|
||||
expect(
|
||||
fs.existsSync(path.join(compiledPackDir, 'qlpack.lock.yml')) ||
|
||||
fs.existsSync(path.join(compiledPackDir, 'codeql-pack.lock.yml'))
|
||||
).to.be.true;
|
||||
expect(fs.existsSync(path.join(compiledPackDir, 'lib.qll'))).to.be.false;
|
||||
expect(fs.existsSync(path.join(compiledPackDir, 'not-in-pack.ql'))).to.be.false;
|
||||
// should have generated a correct qlpack file
|
||||
const qlpackContents: any = yaml.load(fs.readFileSync(path.join(compiledPackDir, 'qlpack.yml'), 'utf8'));
|
||||
expect(qlpackContents.name).to.equal('codeql-remote/query');
|
||||
expect(qlpackContents.version).to.equal('0.0.0');
|
||||
expect(qlpackContents.dependencies?.['codeql/javascript-all']).to.equal('*');
|
||||
|
||||
const libraryDir = path.join(compiledPackDir, '.codeql/libraries/codeql');
|
||||
printDirectoryContents(libraryDir);
|
||||
const packNames = fs.readdirSync(libraryDir).sort();
|
||||
|
||||
// check dependencies.
|
||||
// 2.7.4 and earlier have ['javascript-all', 'javascript-upgrades']
|
||||
// later only have ['javascript-all']. ensure this test can handle either
|
||||
expect(packNames.length).to.be.lessThan(3).and.greaterThan(0);
|
||||
expect(packNames[0]).to.deep.equal('javascript-all');
|
||||
});
|
||||
|
||||
it('should run a remote query that is nested inside a qlpack', async () => {
|
||||
const fileUri = getFile('data-remote-qlpack-nested/subfolder/in-pack.ql');
|
||||
|
||||
const querySubmissionResult = await runRemoteQuery(cli, credentials, fileUri, true, progress, token);
|
||||
expect(querySubmissionResult).to.be.ok;
|
||||
const queryPackRootDir = querySubmissionResult!.queryDirPath!;
|
||||
|
||||
// to retrieve the list of repositories
|
||||
expect(showQuickPickSpy).to.have.been.calledOnce;
|
||||
|
||||
expect(getRepositoryFromNwoStub).to.have.been.calledOnce;
|
||||
|
||||
// check a few files that we know should exist and others that we know should not
|
||||
|
||||
// the tarball to deliver to the server
|
||||
printDirectoryContents(queryPackRootDir);
|
||||
expect(fs.readdirSync(queryPackRootDir).find(f => f.startsWith('qlpack-') && f.endsWith('-generated.tgz'))).not.to.be.undefined;
|
||||
|
||||
const queryPackDir = path.join(queryPackRootDir, 'query-pack');
|
||||
printDirectoryContents(queryPackDir);
|
||||
|
||||
expect(fs.existsSync(path.join(queryPackDir, 'subfolder/in-pack.ql'))).to.be.true;
|
||||
expect(fs.existsSync(path.join(queryPackDir, 'qlpack.yml'))).to.be.true;
|
||||
// depending on the cli version, we should have one of these files
|
||||
expect(
|
||||
fs.existsSync(path.join(queryPackDir, 'qlpack.lock.yml')) ||
|
||||
fs.existsSync(path.join(queryPackDir, 'codeql-pack.lock.yml'))
|
||||
).to.be.true;
|
||||
expect(fs.existsSync(path.join(queryPackDir, 'otherfolder/lib.qll'))).to.be.true;
|
||||
expect(fs.existsSync(path.join(queryPackDir, 'not-in-pack.ql'))).to.be.false;
|
||||
|
||||
// the compiled pack
|
||||
const compiledPackDir = path.join(queryPackDir, '.codeql/pack/codeql-remote/query/0.0.0/');
|
||||
printDirectoryContents(compiledPackDir);
|
||||
expect(fs.existsSync(path.join(compiledPackDir, 'otherfolder/lib.qll'))).to.be.true;
|
||||
expect(fs.existsSync(path.join(compiledPackDir, 'subfolder/in-pack.ql'))).to.be.true;
|
||||
expect(fs.existsSync(path.join(compiledPackDir, 'qlpack.yml'))).to.be.true;
|
||||
verifyQlPack(path.join(compiledPackDir, 'qlpack.yml'), 'subfolder/in-pack.ql', '0.0.0', await pathSerializationBroken());
|
||||
|
||||
// depending on the cli version, we should have one of these files
|
||||
expect(
|
||||
fs.existsSync(path.join(compiledPackDir, 'qlpack.lock.yml')) ||
|
||||
fs.existsSync(path.join(compiledPackDir, 'codeql-pack.lock.yml'))
|
||||
).to.be.true;
|
||||
expect(fs.existsSync(path.join(compiledPackDir, 'not-in-pack.ql'))).to.be.false;
|
||||
// should have generated a correct qlpack file
|
||||
const qlpackContents: any = yaml.load(fs.readFileSync(path.join(compiledPackDir, 'qlpack.yml'), 'utf8'));
|
||||
expect(qlpackContents.name).to.equal('codeql-remote/query');
|
||||
expect(qlpackContents.version).to.equal('0.0.0');
|
||||
expect(qlpackContents.dependencies?.['codeql/javascript-all']).to.equal('*');
|
||||
|
||||
const libraryDir = path.join(compiledPackDir, '.codeql/libraries/codeql');
|
||||
printDirectoryContents(libraryDir);
|
||||
const packNames = fs.readdirSync(libraryDir).sort();
|
||||
|
||||
// check dependencies.
|
||||
// 2.7.4 and earlier have ['javascript-all', 'javascript-upgrades']
|
||||
// later only have ['javascript-all']. ensure this test can handle either
|
||||
expect(packNames.length).to.be.lessThan(3).and.greaterThan(0);
|
||||
expect(packNames[0]).to.deep.equal('javascript-all');
|
||||
});
|
||||
|
||||
it('should cancel a run before uploading', async () => {
|
||||
const fileUri = getFile('data-remote-no-qlpack/in-pack.ql');
|
||||
|
||||
const promise = runRemoteQuery(cli, credentials, fileUri, true, progress, token);
|
||||
|
||||
token.isCancellationRequested = true;
|
||||
|
||||
try {
|
||||
await promise;
|
||||
assert.fail('should have thrown');
|
||||
} catch (e) {
|
||||
expect(e).to.be.instanceof(UserCancellationException);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
it('should run a remote query that is not part of a qlpack', async () => {
|
||||
const fileUri = getFile('data-remote-no-qlpack/in-pack.ql');
|
||||
describe('when live results are enabled', () => {
|
||||
beforeEach(() => {
|
||||
liveResultsStub.returns(true);
|
||||
});
|
||||
|
||||
const querySubmissionResult = await runRemoteQuery(cli, credentials, fileUri, true, progress, token);
|
||||
expect(querySubmissionResult).to.be.ok;
|
||||
const queryPackRootDir = querySubmissionResult!.queryDirPath!;
|
||||
const dummyVariantAnalysis: VariantAnalysis = {
|
||||
id: 123,
|
||||
controller_repo: {
|
||||
id: 64,
|
||||
name: 'pickles',
|
||||
full_name: 'github/pickles',
|
||||
private: false,
|
||||
},
|
||||
actor_id: 27,
|
||||
query_language: 'javascript',
|
||||
query_pack_url: 'https://example.com/foo',
|
||||
status: 'in_progress',
|
||||
};
|
||||
|
||||
// to retrieve the list of repositories
|
||||
// and a second time to ask for the language
|
||||
expect(showQuickPickSpy).to.have.been.calledTwice;
|
||||
it('should run a variant analysis that is part of a qlpack', async () => {
|
||||
const submitVariantAnalysisStub = sandbox.stub(ghApiClient, 'submitVariantAnalysis').resolves(dummyVariantAnalysis);
|
||||
|
||||
// check a few files that we know should exist and others that we know should not
|
||||
const fileUri = getFile('data-remote-qlpack/in-pack.ql');
|
||||
|
||||
// the tarball to deliver to the server
|
||||
printDirectoryContents(queryPackRootDir);
|
||||
expect(fs.readdirSync(queryPackRootDir).find(f => f.startsWith('qlpack-') && f.endsWith('-generated.tgz'))).not.to.be.undefined;
|
||||
const querySubmissionResult = await runRemoteQuery(cli, credentials, fileUri, true, progress, token);
|
||||
expect(querySubmissionResult).to.be.ok;
|
||||
const variantAnalysis = querySubmissionResult!.variantAnalysis!;
|
||||
expect(variantAnalysis.id).to.be.equal(dummyVariantAnalysis.id);
|
||||
expect(variantAnalysis.status).to.be.equal(VariantAnalysisStatus.InProgress);
|
||||
|
||||
const queryPackDir = path.join(queryPackRootDir, 'query-pack');
|
||||
printDirectoryContents(queryPackDir);
|
||||
expect(getRepositoryFromNwoStub).to.have.been.calledOnce;
|
||||
|
||||
expect(fs.existsSync(path.join(queryPackDir, 'in-pack.ql'))).to.be.true;
|
||||
expect(fs.existsSync(path.join(queryPackDir, 'qlpack.yml'))).to.be.true;
|
||||
// depending on the cli version, we should have one of these files
|
||||
expect(
|
||||
fs.existsSync(path.join(queryPackDir, 'qlpack.lock.yml')) ||
|
||||
fs.existsSync(path.join(queryPackDir, 'codeql-pack.lock.yml'))
|
||||
).to.be.true;
|
||||
expect(fs.existsSync(path.join(queryPackDir, 'lib.qll'))).to.be.false;
|
||||
expect(fs.existsSync(path.join(queryPackDir, 'not-in-pack.ql'))).to.be.false;
|
||||
expect(submitVariantAnalysisStub).to.have.been.calledOnce;
|
||||
});
|
||||
|
||||
// the compiled pack
|
||||
const compiledPackDir = path.join(queryPackDir, '.codeql/pack/codeql-remote/query/0.0.0/');
|
||||
printDirectoryContents(compiledPackDir);
|
||||
expect(fs.existsSync(path.join(compiledPackDir, 'in-pack.ql'))).to.be.true;
|
||||
expect(fs.existsSync(path.join(compiledPackDir, 'qlpack.yml'))).to.be.true;
|
||||
verifyQlPack(path.join(compiledPackDir, 'qlpack.yml'), 'in-pack.ql', '0.0.0', await pathSerializationBroken());
|
||||
it('should run a remote query that is not part of a qlpack', async () => {
|
||||
const submitVariantAnalysisStub = sandbox.stub(ghApiClient, 'submitVariantAnalysis').resolves(dummyVariantAnalysis);
|
||||
|
||||
// depending on the cli version, we should have one of these files
|
||||
expect(
|
||||
fs.existsSync(path.join(compiledPackDir, 'qlpack.lock.yml')) ||
|
||||
fs.existsSync(path.join(compiledPackDir, 'codeql-pack.lock.yml'))
|
||||
).to.be.true;
|
||||
expect(fs.existsSync(path.join(compiledPackDir, 'lib.qll'))).to.be.false;
|
||||
expect(fs.existsSync(path.join(compiledPackDir, 'not-in-pack.ql'))).to.be.false;
|
||||
// should have generated a correct qlpack file
|
||||
const qlpackContents: any = yaml.load(fs.readFileSync(path.join(compiledPackDir, 'qlpack.yml'), 'utf8'));
|
||||
expect(qlpackContents.name).to.equal('codeql-remote/query');
|
||||
expect(qlpackContents.version).to.equal('0.0.0');
|
||||
expect(qlpackContents.dependencies?.['codeql/javascript-all']).to.equal('*');
|
||||
const fileUri = getFile('data-remote-no-qlpack/in-pack.ql');
|
||||
|
||||
const libraryDir = path.join(compiledPackDir, '.codeql/libraries/codeql');
|
||||
printDirectoryContents(libraryDir);
|
||||
const packNames = fs.readdirSync(libraryDir).sort();
|
||||
const querySubmissionResult = await runRemoteQuery(cli, credentials, fileUri, true, progress, token);
|
||||
expect(querySubmissionResult).to.be.ok;
|
||||
const variantAnalysis = querySubmissionResult!.variantAnalysis!;
|
||||
expect(variantAnalysis.id).to.be.equal(dummyVariantAnalysis.id);
|
||||
expect(variantAnalysis.status).to.be.equal(VariantAnalysisStatus.InProgress);
|
||||
|
||||
// check dependencies.
|
||||
// 2.7.4 and earlier have ['javascript-all', 'javascript-upgrades']
|
||||
// later only have ['javascript-all']. ensure this test can handle either
|
||||
expect(packNames.length).to.be.lessThan(3).and.greaterThan(0);
|
||||
expect(packNames[0]).to.deep.equal('javascript-all');
|
||||
});
|
||||
expect(getRepositoryFromNwoStub).to.have.been.calledOnce;
|
||||
|
||||
it('should run a remote query that is nested inside a qlpack', async () => {
|
||||
const fileUri = getFile('data-remote-qlpack-nested/subfolder/in-pack.ql');
|
||||
expect(submitVariantAnalysisStub).to.have.been.calledOnce;
|
||||
});
|
||||
|
||||
const querySubmissionResult = await runRemoteQuery(cli, credentials, fileUri, true, progress, token);
|
||||
expect(querySubmissionResult).to.be.ok;
|
||||
const queryPackRootDir = querySubmissionResult!.queryDirPath!;
|
||||
it('should run a remote query that is nested inside a qlpack', async () => {
|
||||
const submitVariantAnalysisStub = sandbox.stub(ghApiClient, 'submitVariantAnalysis').resolves(dummyVariantAnalysis);
|
||||
|
||||
// to retrieve the list of repositories
|
||||
expect(showQuickPickSpy).to.have.been.calledOnce;
|
||||
const fileUri = getFile('data-remote-qlpack-nested/subfolder/in-pack.ql');
|
||||
|
||||
// check a few files that we know should exist and others that we know should not
|
||||
const querySubmissionResult = await runRemoteQuery(cli, credentials, fileUri, true, progress, token);
|
||||
expect(querySubmissionResult).to.be.ok;
|
||||
const variantAnalysis = querySubmissionResult!.variantAnalysis!;
|
||||
expect(variantAnalysis.id).to.be.equal(dummyVariantAnalysis.id);
|
||||
expect(variantAnalysis.status).to.be.equal(VariantAnalysisStatus.InProgress);
|
||||
|
||||
// the tarball to deliver to the server
|
||||
printDirectoryContents(queryPackRootDir);
|
||||
expect(fs.readdirSync(queryPackRootDir).find(f => f.startsWith('qlpack-') && f.endsWith('-generated.tgz'))).not.to.be.undefined;
|
||||
expect(getRepositoryFromNwoStub).to.have.been.calledOnce;
|
||||
|
||||
const queryPackDir = path.join(queryPackRootDir, 'query-pack');
|
||||
printDirectoryContents(queryPackDir);
|
||||
expect(submitVariantAnalysisStub).to.have.been.calledOnce;
|
||||
});
|
||||
|
||||
expect(fs.existsSync(path.join(queryPackDir, 'subfolder/in-pack.ql'))).to.be.true;
|
||||
expect(fs.existsSync(path.join(queryPackDir, 'qlpack.yml'))).to.be.true;
|
||||
// depending on the cli version, we should have one of these files
|
||||
expect(
|
||||
fs.existsSync(path.join(queryPackDir, 'qlpack.lock.yml')) ||
|
||||
fs.existsSync(path.join(queryPackDir, 'codeql-pack.lock.yml'))
|
||||
).to.be.true;
|
||||
expect(fs.existsSync(path.join(queryPackDir, 'otherfolder/lib.qll'))).to.be.true;
|
||||
expect(fs.existsSync(path.join(queryPackDir, 'not-in-pack.ql'))).to.be.false;
|
||||
it('should cancel a run before uploading', async () => {
|
||||
const fileUri = getFile('data-remote-no-qlpack/in-pack.ql');
|
||||
|
||||
// the compiled pack
|
||||
const compiledPackDir = path.join(queryPackDir, '.codeql/pack/codeql-remote/query/0.0.0/');
|
||||
printDirectoryContents(compiledPackDir);
|
||||
expect(fs.existsSync(path.join(compiledPackDir, 'otherfolder/lib.qll'))).to.be.true;
|
||||
expect(fs.existsSync(path.join(compiledPackDir, 'subfolder/in-pack.ql'))).to.be.true;
|
||||
expect(fs.existsSync(path.join(compiledPackDir, 'qlpack.yml'))).to.be.true;
|
||||
verifyQlPack(path.join(compiledPackDir, 'qlpack.yml'), 'subfolder/in-pack.ql', '0.0.0', await pathSerializationBroken());
|
||||
const promise = runRemoteQuery(cli, credentials, fileUri, true, progress, token);
|
||||
|
||||
// depending on the cli version, we should have one of these files
|
||||
expect(
|
||||
fs.existsSync(path.join(compiledPackDir, 'qlpack.lock.yml')) ||
|
||||
fs.existsSync(path.join(compiledPackDir, 'codeql-pack.lock.yml'))
|
||||
).to.be.true;
|
||||
expect(fs.existsSync(path.join(compiledPackDir, 'not-in-pack.ql'))).to.be.false;
|
||||
// should have generated a correct qlpack file
|
||||
const qlpackContents: any = yaml.load(fs.readFileSync(path.join(compiledPackDir, 'qlpack.yml'), 'utf8'));
|
||||
expect(qlpackContents.name).to.equal('codeql-remote/query');
|
||||
expect(qlpackContents.version).to.equal('0.0.0');
|
||||
expect(qlpackContents.dependencies?.['codeql/javascript-all']).to.equal('*');
|
||||
token.isCancellationRequested = true;
|
||||
|
||||
const libraryDir = path.join(compiledPackDir, '.codeql/libraries/codeql');
|
||||
printDirectoryContents(libraryDir);
|
||||
const packNames = fs.readdirSync(libraryDir).sort();
|
||||
|
||||
// check dependencies.
|
||||
// 2.7.4 and earlier have ['javascript-all', 'javascript-upgrades']
|
||||
// later only have ['javascript-all']. ensure this test can handle either
|
||||
expect(packNames.length).to.be.lessThan(3).and.greaterThan(0);
|
||||
expect(packNames[0]).to.deep.equal('javascript-all');
|
||||
});
|
||||
|
||||
it('should cancel a run before uploading', async () => {
|
||||
const fileUri = getFile('data-remote-no-qlpack/in-pack.ql');
|
||||
|
||||
const promise = runRemoteQuery(cli, credentials, fileUri, true, progress, token);
|
||||
|
||||
token.isCancellationRequested = true;
|
||||
|
||||
try {
|
||||
await promise;
|
||||
assert.fail('should have thrown');
|
||||
} catch (e) {
|
||||
expect(e).to.be.instanceof(UserCancellationException);
|
||||
}
|
||||
try {
|
||||
await promise;
|
||||
assert.fail('should have thrown');
|
||||
} catch (e) {
|
||||
expect(e).to.be.instanceof(UserCancellationException);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
function verifyQlPack(qlpackPath: string, queryPath: string, packVersion: string, pathSerializationBroken: boolean) {
|
||||
|
||||
@@ -1,11 +1,18 @@
|
||||
import { expect } from 'chai';
|
||||
import * as os from 'os';
|
||||
import { parseResponse } from '../../../remote-queries/run-remote-query';
|
||||
import { Repository } from '../../../remote-queries/shared/repository';
|
||||
|
||||
describe('run-remote-query', () => {
|
||||
describe('parseResponse', () => {
|
||||
const controllerRepository: Repository = {
|
||||
id: 123,
|
||||
fullName: 'org/name',
|
||||
private: true
|
||||
};
|
||||
|
||||
it('should parse a successful response', () => {
|
||||
const result = parseResponse('org', 'name', {
|
||||
const result = parseResponse(controllerRepository, {
|
||||
workflow_run_id: 123,
|
||||
repositories_queried: ['a/b', 'c/d'],
|
||||
});
|
||||
@@ -20,7 +27,7 @@ describe('run-remote-query', () => {
|
||||
});
|
||||
|
||||
it('should parse a response with invalid repos', () => {
|
||||
const result = parseResponse('org', 'name', {
|
||||
const result = parseResponse(controllerRepository, {
|
||||
workflow_run_id: 123,
|
||||
repositories_queried: ['a/b', 'c/d'],
|
||||
errors: {
|
||||
@@ -47,7 +54,7 @@ describe('run-remote-query', () => {
|
||||
});
|
||||
|
||||
it('should parse a response with repos w/o databases', () => {
|
||||
const result = parseResponse('org', 'name', {
|
||||
const result = parseResponse(controllerRepository, {
|
||||
workflow_run_id: 123,
|
||||
repositories_queried: ['a/b', 'c/d'],
|
||||
errors: {
|
||||
@@ -75,7 +82,7 @@ describe('run-remote-query', () => {
|
||||
});
|
||||
|
||||
it('should parse a response with private repos', () => {
|
||||
const result = parseResponse('org', 'name', {
|
||||
const result = parseResponse(controllerRepository, {
|
||||
workflow_run_id: 123,
|
||||
repositories_queried: ['a/b', 'c/d'],
|
||||
errors: {
|
||||
@@ -103,7 +110,7 @@ describe('run-remote-query', () => {
|
||||
});
|
||||
|
||||
it('should parse a response with cutoff repos and cutoff repos count', () => {
|
||||
const result = parseResponse('org', 'name', {
|
||||
const result = parseResponse(controllerRepository, {
|
||||
workflow_run_id: 123,
|
||||
repositories_queried: ['a/b', 'c/d'],
|
||||
errors: {
|
||||
@@ -132,7 +139,7 @@ describe('run-remote-query', () => {
|
||||
});
|
||||
|
||||
it('should parse a response with cutoff repos count but not cutoff repos', () => {
|
||||
const result = parseResponse('org', 'name', {
|
||||
const result = parseResponse(controllerRepository, {
|
||||
workflow_run_id: 123,
|
||||
repositories_queried: ['a/b', 'c/d'],
|
||||
errors: {
|
||||
@@ -159,7 +166,7 @@ describe('run-remote-query', () => {
|
||||
});
|
||||
|
||||
it('should parse a response with invalid repos and repos w/o databases', () => {
|
||||
const result = parseResponse('org', 'name', {
|
||||
const result = parseResponse(controllerRepository, {
|
||||
workflow_run_id: 123,
|
||||
repositories_queried: ['a/b', 'c/d'],
|
||||
errors: {
|
||||
@@ -191,7 +198,7 @@ describe('run-remote-query', () => {
|
||||
});
|
||||
|
||||
it('should parse a response with one repo of each category, and not pluralize "repositories"', () => {
|
||||
const result = parseResponse('org', 'name', {
|
||||
const result = parseResponse(controllerRepository, {
|
||||
workflow_run_id: 123,
|
||||
repositories_queried: ['a/b'],
|
||||
errors: {
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
import { expect } from 'chai';
|
||||
import { parseVariantAnalysisQueryLanguage, VariantAnalysisQueryLanguage } from '../../src/remote-queries/shared/variant-analysis';
|
||||
|
||||
describe('parseVariantAnalysisQueryLanguage', () => {
|
||||
it('parses a valid language', () => {
|
||||
expect(parseVariantAnalysisQueryLanguage('javascript')).to.equal(VariantAnalysisQueryLanguage.Javascript);
|
||||
});
|
||||
|
||||
it('returns undefined for an valid language', () => {
|
||||
expect(parseVariantAnalysisQueryLanguage('rubbish')).to.not.exist;
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user