Skip to content

Commit d33b07b

Browse files
committed
Merge branch 'main' into koesie10/show-variant-analysis-view
2 parents b5b3474 + 0a6db47 commit d33b07b

40 files changed

+2496
-262
lines changed

.github/workflows/main.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,7 @@ jobs:
139139
strategy:
140140
matrix:
141141
os: [ubuntu-latest, windows-latest]
142-
version: ['v2.6.3', 'v2.7.6', 'v2.8.5', 'v2.9.4', 'v2.10.5', 'nightly']
142+
version: ['v2.6.3', 'v2.7.6', 'v2.8.5', 'v2.9.4', 'v2.10.5', 'v2.11.0', 'nightly']
143143
env:
144144
CLI_VERSION: ${{ matrix.version }}
145145
NIGHTLY_URL: ${{ needs.find-nightly.outputs.url }}

extensions/ql-vscode/package-lock.json

Lines changed: 368 additions & 104 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

extensions/ql-vscode/package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1206,7 +1206,7 @@
12061206
},
12071207
"dependencies": {
12081208
"@octokit/plugin-retry": "^3.0.9",
1209-
"@octokit/rest": "^18.5.6",
1209+
"@octokit/rest": "^19.0.4",
12101210
"@primer/octicons-react": "^16.3.0",
12111211
"@primer/react": "^35.0.0",
12121212
"@vscode/codicons": "^0.0.31",
@@ -1246,6 +1246,7 @@
12461246
"devDependencies": {
12471247
"@babel/core": "^7.18.13",
12481248
"@babel/plugin-transform-modules-commonjs": "^7.18.6",
1249+
"@faker-js/faker": "^7.5.0",
12491250
"@storybook/addon-actions": "^6.5.10",
12501251
"@storybook/addon-essentials": "^6.5.10",
12511252
"@storybook/addon-interactions": "^6.5.10",

extensions/ql-vscode/src/extension.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,8 @@ import { createInitialQueryInfo } from './run-queries-shared';
105105
import { LegacyQueryRunner } from './legacy-query-server/legacyRunner';
106106
import { QueryRunner } from './queryRunner';
107107
import { VariantAnalysisView } from './remote-queries/variant-analysis-view';
108+
import { VariantAnalysisMonitor } from './remote-queries/variant-analysis-monitor';
109+
import { VariantAnalysis } from './remote-queries/shared/variant-analysis';
108110

109111
/**
110112
* extension.ts
@@ -894,6 +896,16 @@ async function activateWithInstalledDistribution(
894896
})
895897
);
896898

899+
const variantAnalysisMonitor = new VariantAnalysisMonitor(ctx, logger);
900+
ctx.subscriptions.push(
901+
commandRunner('codeQL.monitorVariantAnalysis', async (
902+
variantAnalysis: VariantAnalysis,
903+
token: CancellationToken
904+
) => {
905+
await variantAnalysisMonitor.monitorVariantAnalysis(variantAnalysis, token);
906+
})
907+
);
908+
897909
ctx.subscriptions.push(
898910
commandRunner('codeQL.autoDownloadRemoteQueryResults', async (
899911
queryResult: RemoteQueryResult,

extensions/ql-vscode/src/remote-queries/gh-api/variant-analysis.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ export interface VariantAnalysisSkippedRepositoryGroup {
6262

6363
export interface VariantAnalysisNotFoundRepositoryGroup {
6464
repository_count: number,
65-
repository_nwos: string[]
65+
repository_full_names: string[]
6666
}
6767
export interface VariantAnalysisRepoTask {
6868
repository: Repository,

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

Lines changed: 8 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,9 @@ import { QueryMetadata } from '../pure/interface-types';
2626
import { getErrorMessage, REPO_REGEX } from '../pure/helpers-pure';
2727
import * as ghApiClient from './gh-api/gh-api-client';
2828
import { getRepositorySelection, isValidSelection, RepositorySelection } from './repository-selection';
29-
import { parseVariantAnalysisQueryLanguage, VariantAnalysis, VariantAnalysisStatus, VariantAnalysisSubmission } from './shared/variant-analysis';
29+
import { parseVariantAnalysisQueryLanguage, VariantAnalysisSubmission } from './shared/variant-analysis';
3030
import { Repository } from './shared/repository';
31+
import { processVariantAnalysis } from './variant-analysis-processor';
3132

3233
export interface QlPack {
3334
name: string;
@@ -270,30 +271,16 @@ export async function runRemoteQuery(
270271
variantAnalysisSubmission
271272
);
272273

273-
const variantAnalysis: VariantAnalysis = {
274-
id: variantAnalysisResponse.id,
275-
controllerRepoId: variantAnalysisResponse.controller_repo.id,
276-
query: {
277-
name: variantAnalysisSubmission.query.name,
278-
filePath: variantAnalysisSubmission.query.filePath,
279-
language: variantAnalysisSubmission.query.language,
280-
},
281-
databases: {
282-
repositories: variantAnalysisSubmission.databases.repositories,
283-
repositoryLists: variantAnalysisSubmission.databases.repositoryLists,
284-
repositoryOwners: variantAnalysisSubmission.databases.repositoryOwners,
285-
},
286-
status: VariantAnalysisStatus.InProgress,
287-
};
288-
289-
void logger.log(`Variant analysis:\n${JSON.stringify(variantAnalysis, null, 2)}`);
274+
const processedVariantAnalysis = processVariantAnalysis(variantAnalysisSubmission, variantAnalysisResponse);
290275

291-
void showAndLogInformationMessage(`Variant analysis ${variantAnalysis.query.name} submitted for processing`);
276+
void logger.log(`Variant analysis:\n${JSON.stringify(processedVariantAnalysis, null, 2)}`);
292277

293-
void commands.executeCommand('codeQL.openVariantAnalysisView', variantAnalysis.id);
278+
void showAndLogInformationMessage(`Variant analysis ${processedVariantAnalysis.query.name} submitted for processing`);
294279

295-
return { variantAnalysis };
280+
void commands.executeCommand('codeQL.openVariantAnalysisView', processedVariantAnalysis.id);
281+
void commands.executeCommand('codeQL.monitorVariantAnalysis', processedVariantAnalysis);
296282

283+
return { variantAnalysis: processedVariantAnalysis };
297284
} else {
298285
const apiResponse = await runRemoteQueriesApiRequest(credentials, actionBranch, language, repoSelection, controllerRepo, base64Pack, dryRun);
299286

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import { VariantAnalysis } from './variant-analysis';
2+
3+
export type VariantAnalysisMonitorStatus =
4+
| 'InProgress'
5+
| 'CompletedSuccessfully'
6+
| 'CompletedUnsuccessfully'
7+
| 'Failed'
8+
| 'Cancelled'
9+
| 'TimedOut';
10+
11+
export interface VariantAnalysisMonitorResult {
12+
status: VariantAnalysisMonitorStatus;
13+
error?: string;
14+
scannedReposDownloaded?: number[],
15+
variantAnalysis?: VariantAnalysis
16+
}

extensions/ql-vscode/src/remote-queries/shared/variant-analysis.ts

Lines changed: 26 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { Repository } from './repository';
2+
import { AnalysisAlert, AnalysisRawResults } from './analysis-result';
23

34
export interface VariantAnalysis {
45
id: number,
@@ -72,10 +73,19 @@ export interface VariantAnalysisSkippedRepositories {
7273

7374
export interface VariantAnalysisSkippedRepositoryGroup {
7475
repositoryCount: number,
75-
repositories: Array<{
76-
id?: number,
77-
fullName: string
78-
}>
76+
repositories: VariantAnalysisSkippedRepository[],
77+
}
78+
79+
export interface VariantAnalysisSkippedRepository {
80+
id?: number,
81+
fullName: string,
82+
private?: boolean,
83+
}
84+
85+
export interface VariantAnalysisScannedRepositoryResult {
86+
repositoryId: number;
87+
interpretedResults?: AnalysisAlert[];
88+
rawResults?: AnalysisRawResults;
7989
}
8090

8191
/**
@@ -102,16 +112,24 @@ export interface VariantAnalysisSubmission {
102112
}
103113

104114
/**
105-
* @param repo
106-
* @returns whether the repo scan is in a completed state, i.e. it cannot normally change state anymore
115+
* @param status
116+
* @returns whether the status is in a completed state, i.e. it cannot normally change state anymore
107117
*/
108-
export function hasRepoScanCompleted(repo: VariantAnalysisScannedRepository): boolean {
118+
export function isCompletedAnalysisRepoStatus(status: VariantAnalysisRepoStatus): boolean {
109119
return [
110120
// All states that indicates the repository has been scanned and cannot
111121
// change status anymore.
112122
VariantAnalysisRepoStatus.Succeeded, VariantAnalysisRepoStatus.Failed,
113123
VariantAnalysisRepoStatus.Canceled, VariantAnalysisRepoStatus.TimedOut,
114-
].includes(repo.analysisStatus);
124+
].includes(status);
125+
}
126+
127+
/**
128+
* @param repo
129+
* @returns whether the repo scan is in a completed state, i.e. it cannot normally change state anymore
130+
*/
131+
export function hasRepoScanCompleted(repo: VariantAnalysisScannedRepository): boolean {
132+
return isCompletedAnalysisRepoStatus(repo.analysisStatus);
115133
}
116134

117135
/**
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
import * as vscode from 'vscode';
2+
import { Credentials } from '../authentication';
3+
import { Logger } from '../logging';
4+
import * as ghApiClient from './gh-api/gh-api-client';
5+
6+
import { VariantAnalysis, VariantAnalysisStatus } from './shared/variant-analysis';
7+
import {
8+
VariantAnalysis as VariantAnalysisApiResponse
9+
} from './gh-api/variant-analysis';
10+
import { VariantAnalysisMonitorResult } from './shared/variant-analysis-monitor-result';
11+
import { processFailureReason } from './variant-analysis-processor';
12+
13+
export class VariantAnalysisMonitor {
14+
// With a sleep of 5 seconds, the maximum number of attempts takes
15+
// us to just over 2 days worth of monitoring.
16+
public static maxAttemptCount = 17280;
17+
public static sleepTime = 5000;
18+
19+
constructor(
20+
private readonly extensionContext: vscode.ExtensionContext,
21+
private readonly logger: Logger
22+
) {
23+
}
24+
25+
public async monitorVariantAnalysis(
26+
variantAnalysis: VariantAnalysis,
27+
cancellationToken: vscode.CancellationToken
28+
): Promise<VariantAnalysisMonitorResult> {
29+
30+
const credentials = await Credentials.initialize(this.extensionContext);
31+
if (!credentials) {
32+
throw Error('Error authenticating with GitHub');
33+
}
34+
35+
let variantAnalysisSummary: VariantAnalysisApiResponse;
36+
let attemptCount = 0;
37+
const scannedReposDownloaded: number[] = [];
38+
39+
while (attemptCount <= VariantAnalysisMonitor.maxAttemptCount) {
40+
await this.sleep(VariantAnalysisMonitor.sleepTime);
41+
42+
if (cancellationToken && cancellationToken.isCancellationRequested) {
43+
return { status: 'Cancelled', error: 'Variant Analysis was canceled.' };
44+
}
45+
46+
variantAnalysisSummary = await ghApiClient.getVariantAnalysis(
47+
credentials,
48+
variantAnalysis.controllerRepoId,
49+
variantAnalysis.id
50+
);
51+
52+
if (variantAnalysisSummary.failure_reason) {
53+
variantAnalysis.status = VariantAnalysisStatus.Failed;
54+
variantAnalysis.failureReason = processFailureReason(variantAnalysisSummary.failure_reason);
55+
return {
56+
status: 'Failed',
57+
error: `Variant Analysis has failed: ${variantAnalysisSummary.failure_reason}`,
58+
variantAnalysis: variantAnalysis
59+
};
60+
}
61+
62+
void this.logger.log('****** Retrieved variant analysis' + JSON.stringify(variantAnalysisSummary));
63+
64+
if (variantAnalysisSummary.scanned_repositories) {
65+
variantAnalysisSummary.scanned_repositories.forEach(scannedRepo => {
66+
if (!scannedReposDownloaded.includes(scannedRepo.repository.id) && scannedRepo.analysis_status === 'succeeded') {
67+
scannedReposDownloaded.push(scannedRepo.repository.id);
68+
}
69+
});
70+
}
71+
72+
if (variantAnalysisSummary.status === 'completed') {
73+
break;
74+
}
75+
76+
attemptCount++;
77+
}
78+
79+
return { status: 'CompletedSuccessfully', scannedReposDownloaded: scannedReposDownloaded };
80+
}
81+
82+
private async sleep(ms: number) {
83+
return new Promise(resolve => setTimeout(resolve, ms));
84+
}
85+
}

0 commit comments

Comments
 (0)