Skip to content

Commit 7fed5ba

Browse files
committed
Merge remote-tracking branch 'origin/main' into koesie10/restore-mrva-on-restart
2 parents fcecfa1 + d3e961f commit 7fed5ba

18 files changed

+323
-106
lines changed

extensions/ql-vscode/package-lock.json

Lines changed: 7 additions & 7 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: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1208,7 +1208,7 @@
12081208
"dependencies": {
12091209
"@octokit/plugin-retry": "^3.0.9",
12101210
"@octokit/rest": "^19.0.4",
1211-
"@primer/octicons-react": "^16.3.0",
1211+
"@primer/octicons-react": "^17.6.0",
12121212
"@primer/react": "^35.0.0",
12131213
"@vscode/codicons": "^0.0.31",
12141214
"@vscode/webview-ui-toolkit": "^1.0.1",

extensions/ql-vscode/src/extension.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,7 @@ export interface CodeQLExtensionInterface {
178178
readonly distributionManager: DistributionManager;
179179
readonly databaseManager: DatabaseManager;
180180
readonly databaseUI: DatabaseUI;
181+
readonly variantAnalysisManager: VariantAnalysisManager;
181182
readonly dispose: () => void;
182183
}
183184

@@ -400,7 +401,7 @@ export async function activate(ctx: ExtensionContext): Promise<CodeQLExtensionIn
400401
allowAutoUpdating: !!ctx.globalState.get(shouldUpdateOnNextActivationKey)
401402
});
402403

403-
variantAnalysisViewSerializer.onExtensionLoaded();
404+
variantAnalysisViewSerializer.onExtensionLoaded(codeQlExtension.variantAnalysisManager);
404405

405406
return codeQlExtension;
406407
}
@@ -946,16 +947,14 @@ async function activateWithInstalledDistribution(
946947
// Generate a random variant analysis ID for testing
947948
const variantAnalysisId: number = Math.floor(Math.random() * 1000000);
948949

949-
const variantAnalysisView = new VariantAnalysisView(ctx, variantAnalysisId);
950-
void variantAnalysisView.openView();
950+
await variantAnalysisManager.showView(variantAnalysisId);
951951
})
952952
);
953953

954954
// The "openVariantAnalysisView" command is internal-only.
955955
ctx.subscriptions.push(
956956
commandRunner('codeQL.openVariantAnalysisView', async (variantAnalysisId: number) => {
957-
const variantAnalysisView = new VariantAnalysisView(ctx, variantAnalysisId);
958-
void variantAnalysisView.openView();
957+
await variantAnalysisManager.showView(variantAnalysisId);
959958
})
960959
);
961960

@@ -1173,6 +1172,7 @@ async function activateWithInstalledDistribution(
11731172
distributionManager,
11741173
databaseManager: dbm,
11751174
databaseUI,
1175+
variantAnalysisManager,
11761176
dispose: () => {
11771177
ctx.subscriptions.forEach(d => d.dispose());
11781178
}

extensions/ql-vscode/src/pure/interface-types.ts

Lines changed: 24 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,11 @@ import * as sarif from 'sarif';
22
import { AnalysisResults } from '../remote-queries/shared/analysis-result';
33
import { AnalysisSummary, RemoteQueryResult } from '../remote-queries/shared/remote-query-result';
44
import { RawResultSet, ResultRow, ResultSetSchema, Column, ResolvableLocationValue } from './bqrs-cli-types';
5-
import { VariantAnalysis } from '../remote-queries/shared/variant-analysis';
5+
import {
6+
VariantAnalysis,
7+
VariantAnalysisScannedRepositoryResult,
8+
VariantAnalysisScannedRepositoryState,
9+
} from '../remote-queries/shared/variant-analysis';
610

711
/**
812
* This module contains types and code that are shared between
@@ -436,18 +440,30 @@ export interface SetVariantAnalysisMessage {
436440
variantAnalysis: VariantAnalysis;
437441
}
438442

439-
export type ToVariantAnalysisMessage =
440-
| SetVariantAnalysisMessage;
441-
442443
export type StopVariantAnalysisMessage = {
443444
t: 'stopVariantAnalysis';
444445
variantAnalysisId: number;
445446
}
446447

447-
export type FromVariantAnalysisMessage =
448-
| ViewLoadedMsg
449-
| StopVariantAnalysisMessage;
450-
451448
export type VariantAnalysisState = {
452449
variantAnalysisId: number;
453450
}
451+
452+
export interface SetRepoResultsMessage {
453+
t: 'setRepoResults';
454+
repoResults: VariantAnalysisScannedRepositoryResult[];
455+
}
456+
457+
export interface SetRepoStatesMessage {
458+
t: 'setRepoStates';
459+
repoStates: VariantAnalysisScannedRepositoryState[];
460+
}
461+
462+
export type ToVariantAnalysisMessage =
463+
| SetVariantAnalysisMessage
464+
| SetRepoResultsMessage
465+
| SetRepoStatesMessage;
466+
467+
export type FromVariantAnalysisMessage =
468+
| ViewLoadedMsg
469+
| StopVariantAnalysisMessage;

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

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -76,8 +76,8 @@ export interface VariantAnalysisRepoTask {
7676
}
7777

7878
export interface VariantAnalysisSkippedRepositories {
79-
access_mismatch_repos: VariantAnalysisSkippedRepositoryGroup,
80-
not_found_repo_nwos: VariantAnalysisNotFoundRepositoryGroup,
81-
no_codeql_db_repos: VariantAnalysisSkippedRepositoryGroup,
82-
over_limit_repos: VariantAnalysisSkippedRepositoryGroup
79+
access_mismatch_repos?: VariantAnalysisSkippedRepositoryGroup,
80+
not_found_repo_nwos?: VariantAnalysisNotFoundRepositoryGroup,
81+
no_codeql_db_repos?: VariantAnalysisSkippedRepositoryGroup,
82+
over_limit_repos?: VariantAnalysisSkippedRepositoryGroup
8383
}

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

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,18 @@ export interface VariantAnalysisSkippedRepository {
8282
private?: boolean,
8383
}
8484

85+
export enum VariantAnalysisScannedRepositoryDownloadStatus {
86+
Pending = 'pending',
87+
InProgress = 'inProgress',
88+
Succeeded = 'succeeded',
89+
Failed = 'failed',
90+
}
91+
92+
export interface VariantAnalysisScannedRepositoryState {
93+
repositoryId: number;
94+
downloadStatus: VariantAnalysisScannedRepositoryDownloadStatus;
95+
}
96+
8597
export interface VariantAnalysisScannedRepositoryResult {
8698
repositoryId: number;
8799
interpretedResults?: AnalysisAlert[];

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

Lines changed: 68 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,18 +11,65 @@ import {
1111
VariantAnalysisRepoTask,
1212
VariantAnalysisScannedRepository as ApiVariantAnalysisScannedRepository
1313
} from './gh-api/variant-analysis';
14-
import { VariantAnalysis } from './shared/variant-analysis';
14+
import {
15+
VariantAnalysis,
16+
VariantAnalysisScannedRepositoryDownloadStatus,
17+
VariantAnalysisScannedRepositoryState
18+
} from './shared/variant-analysis';
1519
import { getErrorMessage } from '../pure/helpers-pure';
20+
import { VariantAnalysisView } from './variant-analysis-view';
21+
import { VariantAnalysisViewManager } from './variant-analysis-view-manager';
1622

17-
export class VariantAnalysisManager extends DisposableObject {
23+
export class VariantAnalysisManager extends DisposableObject implements VariantAnalysisViewManager<VariantAnalysisView> {
1824
private readonly variantAnalysisMonitor: VariantAnalysisMonitor;
25+
private readonly views = new Map<number, VariantAnalysisView>();
1926

2027
constructor(
2128
private readonly ctx: ExtensionContext,
2229
logger: Logger,
2330
) {
2431
super();
25-
this.variantAnalysisMonitor = new VariantAnalysisMonitor(ctx, logger);
32+
this.variantAnalysisMonitor = this.push(new VariantAnalysisMonitor(ctx, logger));
33+
this.variantAnalysisMonitor.onVariantAnalysisChange(this.onVariantAnalysisUpdated.bind(this));
34+
}
35+
36+
public async showView(variantAnalysisId: number): Promise<void> {
37+
if (!this.views.has(variantAnalysisId)) {
38+
// The view will register itself with the manager, so we don't need to do anything here.
39+
this.push(new VariantAnalysisView(this.ctx, variantAnalysisId, this));
40+
}
41+
42+
const variantAnalysisView = this.views.get(variantAnalysisId)!;
43+
await variantAnalysisView.openView();
44+
return;
45+
}
46+
47+
public registerView(view: VariantAnalysisView): void {
48+
if (this.views.has(view.variantAnalysisId)) {
49+
throw new Error(`View for variant analysis with id: ${view.variantAnalysisId} already exists`);
50+
}
51+
52+
this.views.set(view.variantAnalysisId, view);
53+
}
54+
55+
public unregisterView(view: VariantAnalysisView): void {
56+
this.views.delete(view.variantAnalysisId);
57+
}
58+
59+
public getView(variantAnalysisId: number): VariantAnalysisView | undefined {
60+
return this.views.get(variantAnalysisId);
61+
}
62+
63+
private async onVariantAnalysisUpdated(variantAnalysis: VariantAnalysis | undefined): Promise<void> {
64+
if (!variantAnalysis) {
65+
return;
66+
}
67+
68+
await this.getView(variantAnalysis.id)?.updateView(variantAnalysis);
69+
}
70+
71+
private async onRepoStateUpdated(variantAnalysisId: number, repoState: VariantAnalysisScannedRepositoryState): Promise<void> {
72+
await this.getView(variantAnalysisId)?.updateRepoState(repoState);
2673
}
2774

2875
public async monitorVariantAnalysis(
@@ -37,11 +84,19 @@ export class VariantAnalysisManager extends DisposableObject {
3784
variantAnalysisSummary: VariantAnalysisApiResponse,
3885
cancellationToken: CancellationToken
3986
): Promise<void> {
87+
const repoState = {
88+
repositoryId: scannedRepo.repository.id,
89+
downloadStatus: VariantAnalysisScannedRepositoryDownloadStatus.Pending,
90+
};
91+
92+
await this.onRepoStateUpdated(variantAnalysisSummary.id, repoState);
4093

4194
const credentials = await Credentials.initialize(this.ctx);
4295
if (!credentials) { throw Error('Error authenticating with GitHub'); }
4396

4497
if (cancellationToken && cancellationToken.isCancellationRequested) {
98+
repoState.downloadStatus = VariantAnalysisScannedRepositoryDownloadStatus.Failed;
99+
await this.onRepoStateUpdated(variantAnalysisSummary.id, repoState);
45100
return;
46101
}
47102

@@ -53,10 +108,16 @@ export class VariantAnalysisManager extends DisposableObject {
53108
variantAnalysisSummary.id,
54109
scannedRepo.repository.id
55110
);
111+
} catch (e) {
112+
repoState.downloadStatus = VariantAnalysisScannedRepositoryDownloadStatus.Failed;
113+
await this.onRepoStateUpdated(variantAnalysisSummary.id, repoState);
114+
throw new Error(`Could not download the results for variant analysis with id: ${variantAnalysisSummary.id}. Error: ${getErrorMessage(e)}`);
56115
}
57-
catch (e) { throw new Error(`Could not download the results for variant analysis with id: ${variantAnalysisSummary.id}. Error: ${getErrorMessage(e)}`); }
58116

59117
if (repoTask.artifact_url) {
118+
repoState.downloadStatus = VariantAnalysisScannedRepositoryDownloadStatus.InProgress;
119+
await this.onRepoStateUpdated(variantAnalysisSummary.id, repoState);
120+
60121
const resultDirectory = path.join(
61122
this.ctx.globalStorageUri.fsPath,
62123
'variant-analyses',
@@ -77,5 +138,8 @@ export class VariantAnalysisManager extends DisposableObject {
77138
fs.mkdirSync(resultDirectory, { recursive: true });
78139
await fs.writeFile(storagePath, JSON.stringify(result, null, 2), 'utf8');
79140
}
141+
142+
repoState.downloadStatus = VariantAnalysisScannedRepositoryDownloadStatus.Succeeded;
143+
await this.onRepoStateUpdated(variantAnalysisSummary.id, repoState);
80144
}
81145
}

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

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { ExtensionContext, CancellationToken, commands } from 'vscode';
1+
import { ExtensionContext, CancellationToken, commands, EventEmitter } from 'vscode';
22
import { Credentials } from '../authentication';
33
import { Logger } from '../logging';
44
import * as ghApiClient from './gh-api/gh-api-client';
@@ -8,18 +8,23 @@ import {
88
VariantAnalysis as VariantAnalysisApiResponse
99
} from './gh-api/variant-analysis';
1010
import { VariantAnalysisMonitorResult } from './shared/variant-analysis-monitor-result';
11-
import { processFailureReason } from './variant-analysis-processor';
11+
import { processFailureReason, processUpdatedVariantAnalysis } from './variant-analysis-processor';
12+
import { DisposableObject } from '../pure/disposable-object';
1213

13-
export class VariantAnalysisMonitor {
14+
export class VariantAnalysisMonitor extends DisposableObject {
1415
// With a sleep of 5 seconds, the maximum number of attempts takes
1516
// us to just over 2 days worth of monitoring.
1617
public static maxAttemptCount = 17280;
1718
public static sleepTime = 5000;
1819

20+
private readonly _onVariantAnalysisChange = this.push(new EventEmitter<VariantAnalysis | undefined>());
21+
readonly onVariantAnalysisChange = this._onVariantAnalysisChange.event;
22+
1923
constructor(
2024
private readonly extensionContext: ExtensionContext,
2125
private readonly logger: Logger
2226
) {
27+
super();
2328
}
2429

2530
public async monitorVariantAnalysis(
@@ -59,6 +64,10 @@ export class VariantAnalysisMonitor {
5964
};
6065
}
6166

67+
variantAnalysis = processUpdatedVariantAnalysis(variantAnalysis, variantAnalysisSummary);
68+
69+
this._onVariantAnalysisChange.fire(variantAnalysis);
70+
6271
void this.logger.log('****** Retrieved variant analysis' + JSON.stringify(variantAnalysisSummary));
6372

6473
if (variantAnalysisSummary.scanned_repositories) {

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

Lines changed: 27 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,20 @@ export function processVariantAnalysis(
2323
submission: VariantAnalysisSubmission,
2424
response: ApiVariantAnalysis
2525
): VariantAnalysis {
26+
return processUpdatedVariantAnalysis({
27+
query: {
28+
name: submission.query.name,
29+
filePath: submission.query.filePath,
30+
language: submission.query.language
31+
},
32+
databases: submission.databases,
33+
}, response);
34+
}
2635

36+
export function processUpdatedVariantAnalysis(
37+
previousVariantAnalysis: Pick<VariantAnalysis, 'query' | 'databases'>,
38+
response: ApiVariantAnalysis
39+
): VariantAnalysis {
2740
let scannedRepos: VariantAnalysisScannedRepository[] = [];
2841
let skippedRepos: VariantAnalysisSkippedRepositories = {};
2942

@@ -39,11 +52,11 @@ export function processVariantAnalysis(
3952
id: response.id,
4053
controllerRepoId: response.controller_repo.id,
4154
query: {
42-
name: submission.query.name,
43-
filePath: submission.query.filePath,
44-
language: submission.query.language
55+
name: previousVariantAnalysis.query.name,
56+
filePath: previousVariantAnalysis.query.filePath,
57+
language: previousVariantAnalysis.query.language
4558
},
46-
databases: submission.databases,
59+
databases: previousVariantAnalysis.databases,
4760
status: processApiStatus(response.status),
4861
actionsWorkflowRunId: response.actions_workflow_run_id,
4962
scannedRepos: scannedRepos,
@@ -87,7 +100,11 @@ function processSkippedRepositories(
87100
};
88101
}
89102

90-
function processRepoGroup(repoGroup: ApiVariantAnalysisSkippedRepositoryGroup): VariantAnalysisSkippedRepositoryGroup {
103+
function processRepoGroup(repoGroup: ApiVariantAnalysisSkippedRepositoryGroup | undefined): VariantAnalysisSkippedRepositoryGroup | undefined {
104+
if (!repoGroup) {
105+
return undefined;
106+
}
107+
91108
const repos = repoGroup.repositories.map(repo => {
92109
return {
93110
id: repo.id,
@@ -101,7 +118,11 @@ function processRepoGroup(repoGroup: ApiVariantAnalysisSkippedRepositoryGroup):
101118
};
102119
}
103120

104-
function processNotFoundRepoGroup(repoGroup: ApiVariantAnalysisNotFoundRepositoryGroup): VariantAnalysisSkippedRepositoryGroup {
121+
function processNotFoundRepoGroup(repoGroup: ApiVariantAnalysisNotFoundRepositoryGroup | undefined): VariantAnalysisSkippedRepositoryGroup | undefined {
122+
if (!repoGroup) {
123+
return undefined;
124+
}
125+
105126
const repo_full_names = repoGroup.repository_full_names.map(nwo => {
106127
return {
107128
fullName: nwo

0 commit comments

Comments
 (0)