Merge pull request #1716 from github/koesie10/use-shared-types-in-variant-analysis
Remove `gh-api` usage from variant analysis code
This commit is contained in:
@@ -109,11 +109,7 @@ import { NewQueryRunner } from './query-server/query-runner';
|
||||
import { QueryRunner } from './queryRunner';
|
||||
import { VariantAnalysisView } from './remote-queries/variant-analysis-view';
|
||||
import { VariantAnalysisViewSerializer } from './remote-queries/variant-analysis-view-serializer';
|
||||
import { VariantAnalysis } from './remote-queries/shared/variant-analysis';
|
||||
import {
|
||||
VariantAnalysis as VariantAnalysisApiResponse,
|
||||
VariantAnalysisScannedRepository as ApiVariantAnalysisScannedRepository
|
||||
} from './remote-queries/gh-api/variant-analysis';
|
||||
import { VariantAnalysis, VariantAnalysisScannedRepository } from './remote-queries/shared/variant-analysis';
|
||||
import { VariantAnalysisManager } from './remote-queries/variant-analysis-manager';
|
||||
import { createVariantAnalysisContentProvider } from './remote-queries/variant-analysis-content-provider';
|
||||
import { VSCodeMockGitHubApiServer } from './mocks/vscode-mock-gh-api-server';
|
||||
@@ -949,8 +945,8 @@ async function activateWithInstalledDistribution(
|
||||
|
||||
ctx.subscriptions.push(
|
||||
commandRunner('codeQL.autoDownloadVariantAnalysisResult', async (
|
||||
scannedRepo: ApiVariantAnalysisScannedRepository,
|
||||
variantAnalysisSummary: VariantAnalysisApiResponse,
|
||||
scannedRepo: VariantAnalysisScannedRepository,
|
||||
variantAnalysisSummary: VariantAnalysis,
|
||||
token: CancellationToken
|
||||
) => {
|
||||
await variantAnalysisManager.enqueueDownload(scannedRepo, variantAnalysisSummary, token);
|
||||
|
||||
@@ -76,6 +76,17 @@ export interface VariantAnalysisScannedRepository {
|
||||
failureMessage?: string
|
||||
}
|
||||
|
||||
export interface VariantAnalysisRepositoryTask {
|
||||
repository: Repository,
|
||||
analysisStatus: VariantAnalysisRepoStatus,
|
||||
resultCount?: number,
|
||||
artifactSizeInBytes?: number,
|
||||
failureMessage?: string,
|
||||
databaseCommitSha?: string,
|
||||
sourceLocationPrefix?: string,
|
||||
artifactUrl?: string,
|
||||
}
|
||||
|
||||
export interface VariantAnalysisSkippedRepositories {
|
||||
accessMismatchRepos?: VariantAnalysisSkippedRepositoryGroup,
|
||||
notFoundRepos?: VariantAnalysisSkippedRepositoryGroup,
|
||||
|
||||
@@ -5,14 +5,11 @@ import { CancellationToken, commands, EventEmitter, ExtensionContext, window } f
|
||||
import { DisposableObject } from '../pure/disposable-object';
|
||||
import { Credentials } from '../authentication';
|
||||
import { VariantAnalysisMonitor } from './variant-analysis-monitor';
|
||||
import {
|
||||
VariantAnalysis as VariantAnalysisApiResponse,
|
||||
VariantAnalysisRepoTask,
|
||||
VariantAnalysisScannedRepository as ApiVariantAnalysisScannedRepository
|
||||
} from './gh-api/variant-analysis';
|
||||
import {
|
||||
isVariantAnalysisComplete,
|
||||
VariantAnalysis, VariantAnalysisQueryLanguage,
|
||||
VariantAnalysis,
|
||||
VariantAnalysisQueryLanguage,
|
||||
VariantAnalysisRepositoryTask,
|
||||
VariantAnalysisScannedRepository,
|
||||
VariantAnalysisScannedRepositoryDownloadStatus,
|
||||
VariantAnalysisScannedRepositoryResult,
|
||||
@@ -23,7 +20,7 @@ import { VariantAnalysisView } from './variant-analysis-view';
|
||||
import { VariantAnalysisViewManager } from './variant-analysis-view-manager';
|
||||
import { VariantAnalysisResultsManager } from './variant-analysis-results-manager';
|
||||
import { getControllerRepo } from './run-remote-query';
|
||||
import { processUpdatedVariantAnalysis } from './variant-analysis-processor';
|
||||
import { processUpdatedVariantAnalysis, processVariantAnalysisRepositoryTask } from './variant-analysis-processor';
|
||||
import PQueue from 'p-queue';
|
||||
import { createTimestampFile, showAndLogErrorMessage } from '../helpers';
|
||||
import * as fs from 'fs-extra';
|
||||
@@ -179,8 +176,8 @@ export class VariantAnalysisManager extends DisposableObject implements VariantA
|
||||
}
|
||||
|
||||
public async autoDownloadVariantAnalysisResult(
|
||||
scannedRepo: ApiVariantAnalysisScannedRepository,
|
||||
variantAnalysisSummary: VariantAnalysisApiResponse,
|
||||
scannedRepo: VariantAnalysisScannedRepository,
|
||||
variantAnalysis: VariantAnalysis,
|
||||
cancellationToken: CancellationToken
|
||||
): Promise<void> {
|
||||
const repoState = {
|
||||
@@ -188,48 +185,50 @@ export class VariantAnalysisManager extends DisposableObject implements VariantA
|
||||
downloadStatus: VariantAnalysisScannedRepositoryDownloadStatus.Pending,
|
||||
};
|
||||
|
||||
await this.onRepoStateUpdated(variantAnalysisSummary.id, repoState);
|
||||
await this.onRepoStateUpdated(variantAnalysis.id, repoState);
|
||||
|
||||
const credentials = await Credentials.initialize(this.ctx);
|
||||
if (!credentials) { throw Error('Error authenticating with GitHub'); }
|
||||
|
||||
if (cancellationToken && cancellationToken.isCancellationRequested) {
|
||||
repoState.downloadStatus = VariantAnalysisScannedRepositoryDownloadStatus.Failed;
|
||||
await this.onRepoStateUpdated(variantAnalysisSummary.id, repoState);
|
||||
await this.onRepoStateUpdated(variantAnalysis.id, repoState);
|
||||
return;
|
||||
}
|
||||
|
||||
let repoTask: VariantAnalysisRepoTask;
|
||||
let repoTask: VariantAnalysisRepositoryTask;
|
||||
try {
|
||||
repoTask = await ghApiClient.getVariantAnalysisRepo(
|
||||
const repoTaskResponse = await ghApiClient.getVariantAnalysisRepo(
|
||||
credentials,
|
||||
variantAnalysisSummary.controller_repo.id,
|
||||
variantAnalysisSummary.id,
|
||||
variantAnalysis.controllerRepo.id,
|
||||
variantAnalysis.id,
|
||||
scannedRepo.repository.id
|
||||
);
|
||||
|
||||
repoTask = processVariantAnalysisRepositoryTask(repoTaskResponse);
|
||||
} catch (e) {
|
||||
repoState.downloadStatus = VariantAnalysisScannedRepositoryDownloadStatus.Failed;
|
||||
await this.onRepoStateUpdated(variantAnalysisSummary.id, repoState);
|
||||
throw new Error(`Could not download the results for variant analysis with id: ${variantAnalysisSummary.id}. Error: ${getErrorMessage(e)}`);
|
||||
await this.onRepoStateUpdated(variantAnalysis.id, repoState);
|
||||
throw new Error(`Could not download the results for variant analysis with id: ${variantAnalysis.id}. Error: ${getErrorMessage(e)}`);
|
||||
}
|
||||
|
||||
if (repoTask.artifact_url) {
|
||||
if (repoTask.artifactUrl) {
|
||||
repoState.downloadStatus = VariantAnalysisScannedRepositoryDownloadStatus.InProgress;
|
||||
await this.onRepoStateUpdated(variantAnalysisSummary.id, repoState);
|
||||
await this.onRepoStateUpdated(variantAnalysis.id, repoState);
|
||||
|
||||
await this.variantAnalysisResultsManager.download(credentials, variantAnalysisSummary.id, repoTask, this.getVariantAnalysisStorageLocation(variantAnalysisSummary.id));
|
||||
await this.variantAnalysisResultsManager.download(credentials, variantAnalysis.id, repoTask, this.getVariantAnalysisStorageLocation(variantAnalysis.id));
|
||||
}
|
||||
|
||||
repoState.downloadStatus = VariantAnalysisScannedRepositoryDownloadStatus.Succeeded;
|
||||
await this.onRepoStateUpdated(variantAnalysisSummary.id, repoState);
|
||||
await this.onRepoStateUpdated(variantAnalysis.id, repoState);
|
||||
}
|
||||
|
||||
public async enqueueDownload(
|
||||
scannedRepo: ApiVariantAnalysisScannedRepository,
|
||||
variantAnalysisSummary: VariantAnalysisApiResponse,
|
||||
scannedRepo: VariantAnalysisScannedRepository,
|
||||
variantAnalysis: VariantAnalysis,
|
||||
token: CancellationToken
|
||||
): Promise<void> {
|
||||
await this.queue.add(() => this.autoDownloadVariantAnalysisResult(scannedRepo, variantAnalysisSummary, token));
|
||||
await this.queue.add(() => this.autoDownloadVariantAnalysisResult(scannedRepo, variantAnalysis, token));
|
||||
}
|
||||
|
||||
public downloadsQueueSize(): number {
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
import { ExtensionContext, CancellationToken, commands, EventEmitter } from 'vscode';
|
||||
import { CancellationToken, commands, EventEmitter, ExtensionContext } from 'vscode';
|
||||
import { Credentials } from '../authentication';
|
||||
import * as ghApiClient from './gh-api/gh-api-client';
|
||||
|
||||
import { isFinalVariantAnalysisStatus, VariantAnalysis } from './shared/variant-analysis';
|
||||
import {
|
||||
VariantAnalysis as VariantAnalysisApiResponse,
|
||||
isFinalVariantAnalysisStatus,
|
||||
VariantAnalysis,
|
||||
VariantAnalysisRepoStatus,
|
||||
VariantAnalysisScannedRepository
|
||||
} from './gh-api/variant-analysis';
|
||||
} from './shared/variant-analysis';
|
||||
import { VariantAnalysisMonitorResult } from './shared/variant-analysis-monitor-result';
|
||||
import { processUpdatedVariantAnalysis } from './variant-analysis-processor';
|
||||
import { DisposableObject } from '../pure/disposable-object';
|
||||
@@ -57,7 +58,7 @@ export class VariantAnalysisMonitor extends DisposableObject {
|
||||
|
||||
this._onVariantAnalysisChange.fire(variantAnalysis);
|
||||
|
||||
const downloadedRepos = this.downloadVariantAnalysisResults(variantAnalysisSummary, scannedReposDownloaded);
|
||||
const downloadedRepos = this.downloadVariantAnalysisResults(variantAnalysis, scannedReposDownloaded);
|
||||
scannedReposDownloaded.push(...downloadedRepos);
|
||||
|
||||
if (isFinalVariantAnalysisStatus(variantAnalysis.status) || variantAnalysis.failureReason) {
|
||||
@@ -72,7 +73,7 @@ export class VariantAnalysisMonitor extends DisposableObject {
|
||||
|
||||
private scheduleForDownload(
|
||||
scannedRepo: VariantAnalysisScannedRepository,
|
||||
variantAnalysisSummary: VariantAnalysisApiResponse
|
||||
variantAnalysisSummary: VariantAnalysis
|
||||
) {
|
||||
void commands.executeCommand('codeQL.autoDownloadVariantAnalysisResult', scannedRepo, variantAnalysisSummary);
|
||||
}
|
||||
@@ -81,22 +82,22 @@ export class VariantAnalysisMonitor extends DisposableObject {
|
||||
scannedRepo: VariantAnalysisScannedRepository,
|
||||
alreadyDownloaded: number[]
|
||||
): boolean {
|
||||
return !alreadyDownloaded.includes(scannedRepo.repository.id) && scannedRepo.analysis_status === 'succeeded';
|
||||
return !alreadyDownloaded.includes(scannedRepo.repository.id) && scannedRepo.analysisStatus === VariantAnalysisRepoStatus.Succeeded;
|
||||
}
|
||||
|
||||
private getReposToDownload(
|
||||
variantAnalysisSummary: VariantAnalysisApiResponse,
|
||||
variantAnalysisSummary: VariantAnalysis,
|
||||
alreadyDownloaded: number[]
|
||||
): VariantAnalysisScannedRepository[] {
|
||||
if (variantAnalysisSummary.scanned_repositories) {
|
||||
return variantAnalysisSummary.scanned_repositories.filter(scannedRepo => this.shouldDownload(scannedRepo, alreadyDownloaded));
|
||||
if (variantAnalysisSummary.scannedRepos) {
|
||||
return variantAnalysisSummary.scannedRepos.filter(scannedRepo => this.shouldDownload(scannedRepo, alreadyDownloaded));
|
||||
} else {
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
private downloadVariantAnalysisResults(
|
||||
variantAnalysisSummary: VariantAnalysisApiResponse,
|
||||
variantAnalysisSummary: VariantAnalysis,
|
||||
scannedReposDownloaded: number[]
|
||||
): number[] {
|
||||
const repoResultsToDownload = this.getReposToDownload(variantAnalysisSummary, scannedReposDownloaded);
|
||||
|
||||
@@ -6,7 +6,8 @@ import {
|
||||
VariantAnalysisFailureReason as ApiVariantAnalysisFailureReason,
|
||||
VariantAnalysisStatus as ApiVariantAnalysisStatus,
|
||||
VariantAnalysisSkippedRepositoryGroup as ApiVariantAnalysisSkippedRepositoryGroup,
|
||||
VariantAnalysisNotFoundRepositoryGroup as ApiVariantAnalysisNotFoundRepositoryGroup
|
||||
VariantAnalysisNotFoundRepositoryGroup as ApiVariantAnalysisNotFoundRepositoryGroup,
|
||||
VariantAnalysisRepoTask as ApiVariantAnalysisRepoTask,
|
||||
} from './gh-api/variant-analysis';
|
||||
import {
|
||||
VariantAnalysis,
|
||||
@@ -16,7 +17,8 @@ import {
|
||||
VariantAnalysisStatus,
|
||||
VariantAnalysisRepoStatus,
|
||||
VariantAnalysisSubmission,
|
||||
VariantAnalysisSkippedRepositoryGroup
|
||||
VariantAnalysisSkippedRepositoryGroup,
|
||||
VariantAnalysisRepositoryTask
|
||||
} from './shared/variant-analysis';
|
||||
|
||||
export function processVariantAnalysis(
|
||||
@@ -76,24 +78,47 @@ export function processUpdatedVariantAnalysis(
|
||||
return variantAnalysis;
|
||||
}
|
||||
|
||||
export function processVariantAnalysisRepositoryTask(
|
||||
response: ApiVariantAnalysisRepoTask
|
||||
): VariantAnalysisRepositoryTask {
|
||||
return {
|
||||
repository: {
|
||||
id: response.repository.id,
|
||||
fullName: response.repository.full_name,
|
||||
private: response.repository.private,
|
||||
},
|
||||
analysisStatus: processApiRepoStatus(response.analysis_status),
|
||||
resultCount: response.result_count,
|
||||
artifactSizeInBytes: response.artifact_size_in_bytes,
|
||||
failureMessage: response.failure_message,
|
||||
databaseCommitSha: response.database_commit_sha,
|
||||
sourceLocationPrefix: response.source_location_prefix,
|
||||
artifactUrl: response.artifact_url,
|
||||
};
|
||||
}
|
||||
|
||||
export function processScannedRepository(
|
||||
scannedRepo: ApiVariantAnalysisScannedRepository
|
||||
): VariantAnalysisScannedRepository {
|
||||
return {
|
||||
repository: {
|
||||
id: scannedRepo.repository.id,
|
||||
fullName: scannedRepo.repository.full_name,
|
||||
private: scannedRepo.repository.private,
|
||||
stargazersCount: scannedRepo.repository.stargazers_count,
|
||||
updatedAt: scannedRepo.repository.updated_at,
|
||||
},
|
||||
analysisStatus: processApiRepoStatus(scannedRepo.analysis_status),
|
||||
resultCount: scannedRepo.result_count,
|
||||
artifactSizeInBytes: scannedRepo.artifact_size_in_bytes,
|
||||
failureMessage: scannedRepo.failure_message
|
||||
};
|
||||
}
|
||||
|
||||
function processScannedRepositories(
|
||||
scannedRepos: ApiVariantAnalysisScannedRepository[]
|
||||
): VariantAnalysisScannedRepository[] {
|
||||
return scannedRepos.map(scannedRepo => {
|
||||
return {
|
||||
repository: {
|
||||
id: scannedRepo.repository.id,
|
||||
fullName: scannedRepo.repository.full_name,
|
||||
private: scannedRepo.repository.private,
|
||||
stargazersCount: scannedRepo.repository.stargazers_count,
|
||||
updatedAt: scannedRepo.repository.updated_at,
|
||||
},
|
||||
analysisStatus: processApiRepoStatus(scannedRepo.analysis_status),
|
||||
resultCount: scannedRepo.result_count,
|
||||
artifactSizeInBytes: scannedRepo.artifact_size_in_bytes,
|
||||
failureMessage: scannedRepo.failure_message
|
||||
};
|
||||
});
|
||||
return scannedRepos.map(scannedRepo => processScannedRepository(scannedRepo));
|
||||
}
|
||||
|
||||
function processSkippedRepositories(
|
||||
|
||||
@@ -9,9 +9,12 @@ import { sarifParser } from '../sarif-parser';
|
||||
import { extractAnalysisAlerts } from './sarif-processing';
|
||||
import { CodeQLCliServer } from '../cli';
|
||||
import { extractRawResults } from './bqrs-processing';
|
||||
import { VariantAnalysis, VariantAnalysisScannedRepositoryResult } from './shared/variant-analysis';
|
||||
import {
|
||||
VariantAnalysis,
|
||||
VariantAnalysisRepositoryTask,
|
||||
VariantAnalysisScannedRepositoryResult
|
||||
} from './shared/variant-analysis';
|
||||
import { DisposableObject, DisposeHandler } from '../pure/disposable-object';
|
||||
import { VariantAnalysisRepoTask } from './gh-api/variant-analysis';
|
||||
import * as ghApiClient from './gh-api/gh-api-client';
|
||||
import { EventEmitter } from 'vscode';
|
||||
import { unzipFile } from '../pure/zip';
|
||||
@@ -22,7 +25,7 @@ const createCacheKey = (variantAnalysisId: number, repositoryFullName: string):
|
||||
|
||||
export type ResultDownloadedEvent = {
|
||||
variantAnalysisId: number;
|
||||
repoTask: VariantAnalysisRepoTask;
|
||||
repoTask: VariantAnalysisRepositoryTask;
|
||||
}
|
||||
|
||||
export class VariantAnalysisResultsManager extends DisposableObject {
|
||||
@@ -48,18 +51,18 @@ export class VariantAnalysisResultsManager extends DisposableObject {
|
||||
public async download(
|
||||
credentials: Credentials,
|
||||
variantAnalysisId: number,
|
||||
repoTask: VariantAnalysisRepoTask,
|
||||
repoTask: VariantAnalysisRepositoryTask,
|
||||
variantAnalysisStoragePath: string,
|
||||
): Promise<void> {
|
||||
if (!repoTask.artifact_url) {
|
||||
if (!repoTask.artifactUrl) {
|
||||
throw new Error('Missing artifact URL');
|
||||
}
|
||||
|
||||
const resultDirectory = this.getRepoStorageDirectory(variantAnalysisStoragePath, repoTask.repository.full_name);
|
||||
const resultDirectory = this.getRepoStorageDirectory(variantAnalysisStoragePath, repoTask.repository.fullName);
|
||||
|
||||
const result = await ghApiClient.getVariantAnalysisRepoResult(
|
||||
credentials,
|
||||
repoTask.artifact_url
|
||||
repoTask.artifactUrl
|
||||
);
|
||||
|
||||
if (!(await fs.pathExists(resultDirectory))) {
|
||||
@@ -112,13 +115,13 @@ export class VariantAnalysisResultsManager extends DisposableObject {
|
||||
|
||||
const storageDirectory = this.getRepoStorageDirectory(variantAnalysisStoragePath, repositoryFullName);
|
||||
|
||||
const repoTask: VariantAnalysisRepoTask = await fs.readJson(path.join(storageDirectory, VariantAnalysisResultsManager.REPO_TASK_FILENAME));
|
||||
const repoTask: VariantAnalysisRepositoryTask = await fs.readJson(path.join(storageDirectory, VariantAnalysisResultsManager.REPO_TASK_FILENAME));
|
||||
|
||||
if (!repoTask.database_commit_sha || !repoTask.source_location_prefix) {
|
||||
if (!repoTask.databaseCommitSha || !repoTask.sourceLocationPrefix) {
|
||||
throw new Error('Missing database commit SHA');
|
||||
}
|
||||
|
||||
const fileLinkPrefix = this.createGitHubDotcomFileLinkPrefix(repoTask.repository.full_name, repoTask.database_commit_sha);
|
||||
const fileLinkPrefix = this.createGitHubDotcomFileLinkPrefix(repoTask.repository.fullName, repoTask.databaseCommitSha);
|
||||
|
||||
const resultsDirectory = path.join(storageDirectory, VariantAnalysisResultsManager.RESULTS_DIRECTORY);
|
||||
const sarifPath = path.join(resultsDirectory, 'results.sarif');
|
||||
@@ -134,7 +137,7 @@ export class VariantAnalysisResultsManager extends DisposableObject {
|
||||
}
|
||||
|
||||
if (await fs.pathExists(bqrsPath)) {
|
||||
const rawResults = await this.readBqrsResults(bqrsPath, fileLinkPrefix, repoTask.source_location_prefix);
|
||||
const rawResults = await this.readBqrsResults(bqrsPath, fileLinkPrefix, repoTask.sourceLocationPrefix);
|
||||
|
||||
return {
|
||||
variantAnalysisId,
|
||||
|
||||
@@ -10,29 +10,28 @@ import * as fs from 'fs-extra';
|
||||
import * as path from 'path';
|
||||
|
||||
import { VariantAnalysisManager } from '../../../remote-queries/variant-analysis-manager';
|
||||
import {
|
||||
VariantAnalysis as VariantAnalysisApiResponse,
|
||||
VariantAnalysisRepoTask,
|
||||
VariantAnalysisScannedRepository as ApiVariantAnalysisScannedRepository
|
||||
} from '../../../remote-queries/gh-api/variant-analysis';
|
||||
import { createMockApiResponse } from '../../factories/remote-queries/gh-api/variant-analysis-api-response';
|
||||
import { createMockScannedRepos } from '../../factories/remote-queries/gh-api/scanned-repositories';
|
||||
import { createMockVariantAnalysisRepoTask } from '../../factories/remote-queries/gh-api/variant-analysis-repo-task';
|
||||
import { CodeQLCliServer } from '../../../cli';
|
||||
import { storagePath } from '../global.helper';
|
||||
import { VariantAnalysisResultsManager } from '../../../remote-queries/variant-analysis-results-manager';
|
||||
import { createMockVariantAnalysis } from '../../factories/remote-queries/shared/variant-analysis';
|
||||
import { VariantAnalysis } from '../../../remote-queries/shared/variant-analysis';
|
||||
import * as VariantAnalysisModule from '../../../remote-queries/shared/variant-analysis';
|
||||
import { createMockScannedRepos } from '../../factories/remote-queries/shared/scanned-repositories';
|
||||
import {
|
||||
VariantAnalysis,
|
||||
VariantAnalysisScannedRepository,
|
||||
VariantAnalysisStatus,
|
||||
} from '../../../remote-queries/shared/variant-analysis';
|
||||
import { createTimestampFile } from '../../../helpers';
|
||||
import { createMockVariantAnalysisRepoTask } from '../../factories/remote-queries/gh-api/variant-analysis-repo-task';
|
||||
import { VariantAnalysisRepoTask } from '../../../remote-queries/gh-api/variant-analysis';
|
||||
|
||||
describe('Variant Analysis Manager', async function() {
|
||||
let sandbox: sinon.SinonSandbox;
|
||||
let cli: CodeQLCliServer;
|
||||
let cancellationTokenSource: CancellationTokenSource;
|
||||
let variantAnalysisManager: VariantAnalysisManager;
|
||||
let variantAnalysisApiResponse: VariantAnalysisApiResponse;
|
||||
let scannedRepos: ApiVariantAnalysisScannedRepository[];
|
||||
let variantAnalysis: VariantAnalysis;
|
||||
let scannedRepos: VariantAnalysisScannedRepository[];
|
||||
let getVariantAnalysisRepoStub: sinon.SinonStub;
|
||||
let getVariantAnalysisRepoResultStub: sinon.SinonStub;
|
||||
let variantAnalysisResultsManager: VariantAnalysisResultsManager;
|
||||
@@ -47,7 +46,10 @@ describe('Variant Analysis Manager', async function() {
|
||||
cancellationTokenSource = new CancellationTokenSource();
|
||||
|
||||
scannedRepos = createMockScannedRepos();
|
||||
variantAnalysisApiResponse = createMockApiResponse('in_progress', scannedRepos);
|
||||
variantAnalysis = createMockVariantAnalysis({
|
||||
status: VariantAnalysisStatus.InProgress,
|
||||
scannedRepos,
|
||||
});
|
||||
|
||||
try {
|
||||
const extension = await extensions.getExtension<CodeQLExtensionInterface | Record<string, never>>('GitHub.vscode-codeql')!.activate();
|
||||
@@ -70,7 +72,7 @@ describe('Variant Analysis Manager', async function() {
|
||||
try {
|
||||
await variantAnalysisManager.autoDownloadVariantAnalysisResult(
|
||||
scannedRepos[0],
|
||||
variantAnalysisApiResponse,
|
||||
variantAnalysis,
|
||||
cancellationTokenSource.token
|
||||
);
|
||||
} catch (error: any) {
|
||||
@@ -107,7 +109,7 @@ describe('Variant Analysis Manager', async function() {
|
||||
it('should not try to download the result', async () => {
|
||||
await variantAnalysisManager.autoDownloadVariantAnalysisResult(
|
||||
scannedRepos[0],
|
||||
variantAnalysisApiResponse,
|
||||
variantAnalysis,
|
||||
cancellationTokenSource.token
|
||||
);
|
||||
|
||||
@@ -131,7 +133,7 @@ describe('Variant Analysis Manager', async function() {
|
||||
|
||||
await variantAnalysisManager.autoDownloadVariantAnalysisResult(
|
||||
scannedRepos[0],
|
||||
variantAnalysisApiResponse,
|
||||
variantAnalysis,
|
||||
cancellationTokenSource.token
|
||||
);
|
||||
|
||||
@@ -141,7 +143,7 @@ describe('Variant Analysis Manager', async function() {
|
||||
it('should fetch a repo task', async () => {
|
||||
await variantAnalysisManager.autoDownloadVariantAnalysisResult(
|
||||
scannedRepos[0],
|
||||
variantAnalysisApiResponse,
|
||||
variantAnalysis,
|
||||
cancellationTokenSource.token
|
||||
);
|
||||
|
||||
@@ -151,7 +153,7 @@ describe('Variant Analysis Manager', async function() {
|
||||
it('should fetch a repo result', async () => {
|
||||
await variantAnalysisManager.autoDownloadVariantAnalysisResult(
|
||||
scannedRepos[0],
|
||||
variantAnalysisApiResponse,
|
||||
variantAnalysis,
|
||||
cancellationTokenSource.token
|
||||
);
|
||||
|
||||
@@ -163,9 +165,9 @@ describe('Variant Analysis Manager', async function() {
|
||||
it('should pop download tasks off the queue', async () => {
|
||||
const getResultsSpy = sandbox.spy(variantAnalysisManager, 'autoDownloadVariantAnalysisResult');
|
||||
|
||||
await variantAnalysisManager.enqueueDownload(scannedRepos[0], variantAnalysisApiResponse, cancellationTokenSource.token);
|
||||
await variantAnalysisManager.enqueueDownload(scannedRepos[1], variantAnalysisApiResponse, cancellationTokenSource.token);
|
||||
await variantAnalysisManager.enqueueDownload(scannedRepos[2], variantAnalysisApiResponse, cancellationTokenSource.token);
|
||||
await variantAnalysisManager.enqueueDownload(scannedRepos[0], variantAnalysis, cancellationTokenSource.token);
|
||||
await variantAnalysisManager.enqueueDownload(scannedRepos[1], variantAnalysis, cancellationTokenSource.token);
|
||||
await variantAnalysisManager.enqueueDownload(scannedRepos[2], variantAnalysis, cancellationTokenSource.token);
|
||||
|
||||
expect(variantAnalysisManager.downloadsQueueSize()).to.equal(0);
|
||||
expect(getResultsSpy).to.have.been.calledThrice;
|
||||
|
||||
@@ -14,7 +14,11 @@ import {
|
||||
import { createFailedMockApiResponse, createMockApiResponse } from '../../factories/remote-queries/gh-api/variant-analysis-api-response';
|
||||
import { VariantAnalysis, VariantAnalysisStatus } from '../../../remote-queries/shared/variant-analysis';
|
||||
import { createMockScannedRepos } from '../../factories/remote-queries/gh-api/scanned-repositories';
|
||||
import { processFailureReason } from '../../../remote-queries/variant-analysis-processor';
|
||||
import {
|
||||
processFailureReason,
|
||||
processScannedRepository,
|
||||
processUpdatedVariantAnalysis,
|
||||
} from '../../../remote-queries/variant-analysis-processor';
|
||||
import { Credentials } from '../../../authentication';
|
||||
import { createMockVariantAnalysis } from '../../factories/remote-queries/shared/variant-analysis';
|
||||
import { VariantAnalysisManager } from '../../../remote-queries/variant-analysis-manager';
|
||||
@@ -143,8 +147,8 @@ describe('Variant Analysis Monitor', async function() {
|
||||
|
||||
succeededRepos.forEach((succeededRepo, index) => {
|
||||
expect(commandSpy.getCall(index).args[0]).to.eq('codeQL.autoDownloadVariantAnalysisResult');
|
||||
expect(commandSpy.getCall(index).args[1]).to.eq(succeededRepo);
|
||||
expect(commandSpy.getCall(index).args[2]).to.eq(mockApiResponse);
|
||||
expect(commandSpy.getCall(index).args[1]).to.deep.eq(processScannedRepository(succeededRepo));
|
||||
expect(commandSpy.getCall(index).args[2]).to.deep.eq(processUpdatedVariantAnalysis(variantAnalysis, mockApiResponse));
|
||||
});
|
||||
});
|
||||
|
||||
@@ -154,8 +158,8 @@ describe('Variant Analysis Monitor', async function() {
|
||||
expect(mockGetDownloadResult).to.have.callCount(succeededRepos.length);
|
||||
|
||||
succeededRepos.forEach((succeededRepo, index) => {
|
||||
expect(mockGetDownloadResult.getCall(index).args[0]).to.eq(succeededRepo);
|
||||
expect(mockGetDownloadResult.getCall(index).args[1]).to.eq(mockApiResponse);
|
||||
expect(mockGetDownloadResult.getCall(index).args[0]).to.deep.eq(processScannedRepository(succeededRepo));
|
||||
expect(mockGetDownloadResult.getCall(index).args[1]).to.deep.eq(processUpdatedVariantAnalysis(variantAnalysis, mockApiResponse));
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -8,11 +8,14 @@ import * as fs from 'fs-extra';
|
||||
import * as path from 'path';
|
||||
|
||||
import { VariantAnalysisResultsManager } from '../../../remote-queries/variant-analysis-results-manager';
|
||||
import { createMockVariantAnalysisRepoTask } from '../../factories/remote-queries/gh-api/variant-analysis-repo-task';
|
||||
import { CodeQLCliServer } from '../../../cli';
|
||||
import { storagePath } from '../global.helper';
|
||||
import { faker } from '@faker-js/faker';
|
||||
import * as ghApiClient from '../../../remote-queries/gh-api/gh-api-client';
|
||||
import {
|
||||
createMockVariantAnalysisRepositoryTask
|
||||
} from '../../factories/remote-queries/shared/variant-analysis-repo-tasks';
|
||||
import { VariantAnalysisRepositoryTask } from '../../../remote-queries/shared/variant-analysis';
|
||||
|
||||
describe(VariantAnalysisResultsManager.name, function() {
|
||||
this.timeout(10000);
|
||||
@@ -51,15 +54,15 @@ describe(VariantAnalysisResultsManager.name, function() {
|
||||
request: getOctokitStub
|
||||
})
|
||||
} as unknown as Credentials;
|
||||
let dummyRepoTask = createMockVariantAnalysisRepoTask();
|
||||
let dummyRepoTask: VariantAnalysisRepositoryTask;
|
||||
let variantAnalysisStoragePath: string;
|
||||
let repoTaskStorageDirectory: string;
|
||||
|
||||
beforeEach(async () => {
|
||||
dummyRepoTask = createMockVariantAnalysisRepoTask();
|
||||
dummyRepoTask = createMockVariantAnalysisRepositoryTask();
|
||||
|
||||
variantAnalysisStoragePath = path.join(storagePath, variantAnalysisId.toString());
|
||||
repoTaskStorageDirectory = variantAnalysisResultsManager.getRepoStorageDirectory(variantAnalysisStoragePath, dummyRepoTask.repository.full_name);
|
||||
repoTaskStorageDirectory = variantAnalysisResultsManager.getRepoStorageDirectory(variantAnalysisStoragePath, dummyRepoTask.repository.fullName);
|
||||
});
|
||||
|
||||
afterEach(async () => {
|
||||
@@ -70,14 +73,14 @@ describe(VariantAnalysisResultsManager.name, function() {
|
||||
|
||||
describe('isVariantAnalysisRepoDownloaded', () => {
|
||||
it('should return false when no results are downloaded', async () => {
|
||||
expect(await variantAnalysisResultsManager.isVariantAnalysisRepoDownloaded(variantAnalysisStoragePath, dummyRepoTask.repository.full_name)).to.equal(false);
|
||||
expect(await variantAnalysisResultsManager.isVariantAnalysisRepoDownloaded(variantAnalysisStoragePath, dummyRepoTask.repository.fullName)).to.equal(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('when the artifact_url is missing', async () => {
|
||||
it('should not try to download the result', async () => {
|
||||
const dummyRepoTask = createMockVariantAnalysisRepoTask();
|
||||
delete dummyRepoTask.artifact_url;
|
||||
const dummyRepoTask = createMockVariantAnalysisRepositoryTask();
|
||||
delete dummyRepoTask.artifactUrl;
|
||||
|
||||
try {
|
||||
await variantAnalysisResultsManager.download(
|
||||
@@ -103,7 +106,7 @@ describe(VariantAnalysisResultsManager.name, function() {
|
||||
|
||||
getVariantAnalysisRepoResultStub = sandbox
|
||||
.stub(ghApiClient, 'getVariantAnalysisRepoResult')
|
||||
.withArgs(mockCredentials, dummyRepoTask.artifact_url as string)
|
||||
.withArgs(mockCredentials, dummyRepoTask.artifactUrl as string)
|
||||
.resolves(arrayBuffer);
|
||||
});
|
||||
|
||||
@@ -149,7 +152,7 @@ describe(VariantAnalysisResultsManager.name, function() {
|
||||
variantAnalysisStoragePath
|
||||
);
|
||||
|
||||
expect(await variantAnalysisResultsManager.isVariantAnalysisRepoDownloaded(variantAnalysisStoragePath, dummyRepoTask.repository.full_name)).to.equal(true);
|
||||
expect(await variantAnalysisResultsManager.isVariantAnalysisRepoDownloaded(variantAnalysisStoragePath, dummyRepoTask.repository.fullName)).to.equal(true);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
import { faker } from '@faker-js/faker';
|
||||
import {
|
||||
VariantAnalysisRepositoryTask,
|
||||
VariantAnalysisRepoStatus,
|
||||
} from '../../../../remote-queries/shared/variant-analysis';
|
||||
import { createMockRepositoryWithMetadata } from './repository';
|
||||
|
||||
export function createMockVariantAnalysisRepositoryTask(data?: Partial<VariantAnalysisRepositoryTask>): VariantAnalysisRepositoryTask {
|
||||
return {
|
||||
repository: createMockRepositoryWithMetadata(),
|
||||
analysisStatus: VariantAnalysisRepoStatus.Pending,
|
||||
resultCount: faker.datatype.number(),
|
||||
artifactSizeInBytes: faker.datatype.number(),
|
||||
databaseCommitSha: faker.git.commitSha(),
|
||||
sourceLocationPrefix: faker.system.filePath(),
|
||||
artifactUrl: faker.internet.url(),
|
||||
...data,
|
||||
};
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
import { expect } from 'chai';
|
||||
import { faker } from '@faker-js/faker';
|
||||
import {
|
||||
VariantAnalysisScannedRepository as ApiVariantAnalysisScannedRepository
|
||||
} from '../../../src/remote-queries/gh-api/variant-analysis';
|
||||
@@ -7,8 +8,15 @@ import {
|
||||
VariantAnalysisScannedRepository,
|
||||
VariantAnalysisRepoStatus
|
||||
} from '../../../src/remote-queries/shared/variant-analysis';
|
||||
import { processVariantAnalysis } from '../../../src/remote-queries/variant-analysis-processor';
|
||||
import { createMockScannedRepos } from '../../../src/vscode-tests/factories/remote-queries/gh-api/scanned-repositories';
|
||||
import {
|
||||
processScannedRepository,
|
||||
processVariantAnalysis,
|
||||
processVariantAnalysisRepositoryTask
|
||||
} from '../../../src/remote-queries/variant-analysis-processor';
|
||||
import {
|
||||
createMockScannedRepo,
|
||||
createMockScannedRepos
|
||||
} from '../../../src/vscode-tests/factories/remote-queries/gh-api/scanned-repositories';
|
||||
import { createMockSkippedRepos } from '../../../src/vscode-tests/factories/remote-queries/gh-api/skipped-repositories';
|
||||
import {
|
||||
createMockApiResponse
|
||||
@@ -16,8 +24,11 @@ import {
|
||||
import {
|
||||
createMockSubmission
|
||||
} from '../../../src/vscode-tests/factories/remote-queries/shared/variant-analysis-submission';
|
||||
import {
|
||||
createMockVariantAnalysisRepoTask
|
||||
} from '../../../src/vscode-tests/factories/remote-queries/gh-api/variant-analysis-repo-task';
|
||||
|
||||
describe('Variant Analysis processor', function() {
|
||||
describe(processVariantAnalysis.name, function() {
|
||||
const scannedRepos = createMockScannedRepos();
|
||||
const skippedRepos = createMockSkippedRepos();
|
||||
const mockApiResponse = createMockApiResponse('completed', scannedRepos, skippedRepos);
|
||||
@@ -147,3 +158,44 @@ describe('Variant Analysis processor', function() {
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
describe(processVariantAnalysisRepositoryTask.name, () => {
|
||||
const mockApiResponse = createMockVariantAnalysisRepoTask();
|
||||
|
||||
it('should return the correct result', () => {
|
||||
expect(processVariantAnalysisRepositoryTask(mockApiResponse)).to.deep.eq({
|
||||
repository: {
|
||||
id: mockApiResponse.repository.id,
|
||||
fullName: mockApiResponse.repository.full_name,
|
||||
private: mockApiResponse.repository.private,
|
||||
},
|
||||
analysisStatus: 'succeeded',
|
||||
resultCount: mockApiResponse.result_count,
|
||||
artifactSizeInBytes: mockApiResponse.artifact_size_in_bytes,
|
||||
failureMessage: mockApiResponse.failure_message,
|
||||
databaseCommitSha: mockApiResponse.database_commit_sha,
|
||||
sourceLocationPrefix: mockApiResponse.source_location_prefix,
|
||||
artifactUrl: mockApiResponse.artifact_url,
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe(processScannedRepository.name, () => {
|
||||
const mockApiResponse = createMockScannedRepo(faker.random.word(), faker.datatype.boolean(), VariantAnalysisRepoStatus.Pending);
|
||||
|
||||
it('should return the correct result', () => {
|
||||
expect(processScannedRepository(mockApiResponse)).to.deep.eq({
|
||||
repository: {
|
||||
id: mockApiResponse.repository.id,
|
||||
fullName: mockApiResponse.repository.full_name,
|
||||
private: mockApiResponse.repository.private,
|
||||
stargazersCount: mockApiResponse.repository.stargazers_count,
|
||||
updatedAt: mockApiResponse.repository.updated_at,
|
||||
},
|
||||
analysisStatus: 'pending',
|
||||
resultCount: mockApiResponse.result_count,
|
||||
artifactSizeInBytes: mockApiResponse.artifact_size_in_bytes,
|
||||
failureMessage: mockApiResponse.failure_message,
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user