Skip to content

Commit a661daa

Browse files
committed
Merge remote-tracking branch 'origin/main' into koesie10/fix-duplicate-downloads
2 parents 18e1cfa + b062f61 commit a661daa

40 files changed

+1376
-153
lines changed

extensions/ql-vscode/gulpfile.ts/deploy.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,8 @@ const packageFiles = [
1515
'snippets.json',
1616
'media',
1717
'node_modules',
18-
'out'
18+
'out',
19+
'workspace-databases-schema.json'
1920
];
2021

2122
async function copyPackage(sourcePath: string, destPath: string): Promise<void> {

extensions/ql-vscode/package.json

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,12 @@
8484
"editor.wordBasedSuggestions": false
8585
}
8686
},
87+
"jsonValidation": [
88+
{
89+
"fileMatch": "workspace-databases.json",
90+
"url": "./workspace-databases-schema.json"
91+
}
92+
],
8793
"languages": [
8894
{
8995
"id": "ql",

extensions/ql-vscode/src/databases/db-config-store.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ export class DbConfigStore extends DisposableObject {
1212

1313
public constructor(workspaceStoragePath: string) {
1414
super();
15+
1516
this.configPath = path.join(workspaceStoragePath, 'workspace-databases.json');
1617

1718
this.config = this.createEmptyConfig();

extensions/ql-vscode/src/databases/ui/db-tree-data-provider.ts

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { logger } from '../../logging';
22
import { ProviderResult, TreeDataProvider, TreeItem } from 'vscode';
3-
import { DbTreeViewItem } from './db-tree-view-item';
3+
import { createDbTreeViewItemWarning, DbTreeViewItem } from './db-tree-view-item';
44
import { DbManager } from '../db-manager';
55

66
export class DbTreeDataProvider implements TreeDataProvider<DbTreeViewItem> {
@@ -41,6 +41,12 @@ export class DbTreeDataProvider implements TreeDataProvider<DbTreeViewItem> {
4141
// This will be fleshed out in a future change.
4242
void logger.log(`Creating database tree with ${dbItems.length} items`);
4343

44-
return [];
44+
// Add a sample warning as a proof of concept.
45+
const warningTreeViewItem = createDbTreeViewItemWarning(
46+
'There was an error',
47+
'Fix it'
48+
);
49+
50+
return [warningTreeViewItem];
4551
}
4652
}

extensions/ql-vscode/src/databases/ui/db-tree-view-item.ts

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,13 @@ import * as vscode from 'vscode';
22
import { DbItem } from '../db-item';
33

44
/**
5-
* Represents an item in the database tree view.
5+
* Represents an item in the database tree view. This item could be
6+
* representing an actual database item or a warning.
67
*/
78
export class DbTreeViewItem extends vscode.TreeItem {
89
constructor(
9-
public readonly dbItem: DbItem,
10+
public readonly dbItem: DbItem | undefined,
11+
public readonly iconPath: vscode.ThemeIcon,
1012
public readonly label: string,
1113
public readonly tooltip: string,
1214
public readonly collapsibleState: vscode.TreeItemCollapsibleState,
@@ -15,3 +17,14 @@ export class DbTreeViewItem extends vscode.TreeItem {
1517
super(label, collapsibleState);
1618
}
1719
}
20+
21+
export function createDbTreeViewItemWarning(label: string, tooltip: string): DbTreeViewItem {
22+
return new DbTreeViewItem(
23+
undefined,
24+
new vscode.ThemeIcon('warning', new vscode.ThemeColor('problemsWarningIcon.foreground')),
25+
label,
26+
tooltip,
27+
vscode.TreeItemCollapsibleState.None,
28+
[]
29+
);
30+
}

extensions/ql-vscode/src/extension.ts

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -109,11 +109,7 @@ import { NewQueryRunner } from './query-server/query-runner';
109109
import { QueryRunner } from './queryRunner';
110110
import { VariantAnalysisView } from './remote-queries/variant-analysis-view';
111111
import { VariantAnalysisViewSerializer } from './remote-queries/variant-analysis-view-serializer';
112-
import { VariantAnalysis } from './remote-queries/shared/variant-analysis';
113-
import {
114-
VariantAnalysis as VariantAnalysisApiResponse,
115-
VariantAnalysisScannedRepository as ApiVariantAnalysisScannedRepository
116-
} from './remote-queries/gh-api/variant-analysis';
112+
import { VariantAnalysis, VariantAnalysisScannedRepository } from './remote-queries/shared/variant-analysis';
117113
import { VariantAnalysisManager } from './remote-queries/variant-analysis-manager';
118114
import { createVariantAnalysisContentProvider } from './remote-queries/variant-analysis-content-provider';
119115
import { VSCodeMockGitHubApiServer } from './mocks/vscode-mock-gh-api-server';
@@ -949,8 +945,8 @@ async function activateWithInstalledDistribution(
949945

950946
ctx.subscriptions.push(
951947
commandRunner('codeQL.autoDownloadVariantAnalysisResult', async (
952-
scannedRepo: ApiVariantAnalysisScannedRepository,
953-
variantAnalysisSummary: VariantAnalysisApiResponse,
948+
scannedRepo: VariantAnalysisScannedRepository,
949+
variantAnalysisSummary: VariantAnalysis,
954950
token: CancellationToken
955951
) => {
956952
await variantAnalysisManager.enqueueDownload(scannedRepo, variantAnalysisSummary, token);

extensions/ql-vscode/src/query-history.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ import * as fs from 'fs-extra';
4040
import { CliVersionConstraint } from './cli';
4141
import { HistoryItemLabelProvider } from './history-item-label-provider';
4242
import { Credentials } from './authentication';
43-
import { cancelRemoteQuery } from './remote-queries/gh-api/gh-actions-api-client';
43+
import { cancelRemoteQuery, cancelVariantAnalysis } from './remote-queries/gh-api/gh-actions-api-client';
4444
import { RemoteQueriesManager } from './remote-queries/remote-queries-manager';
4545
import { RemoteQueryHistoryItem } from './remote-queries/remote-query-history-item';
4646
import { ResultsView } from './interface';
@@ -1109,6 +1109,7 @@ export class QueryHistoryManager extends DisposableObject {
11091109
const { finalSingleItem, finalMultiSelect } = this.determineSelection(singleItem, multiSelect);
11101110

11111111
const selected = finalMultiSelect || [finalSingleItem];
1112+
11121113
const results = selected.map(async item => {
11131114
if (item.status === QueryStatus.InProgress) {
11141115
if (item.t === 'local') {
@@ -1117,6 +1118,10 @@ export class QueryHistoryManager extends DisposableObject {
11171118
void showAndLogInformationMessage('Cancelling variant analysis. This may take a while.');
11181119
const credentials = await this.getCredentials();
11191120
await cancelRemoteQuery(credentials, item.remoteQuery);
1121+
} else if (item.t === 'variant-analysis') {
1122+
void showAndLogInformationMessage('Cancelling variant analysis. This may take a while.');
1123+
const credentials = await this.getCredentials();
1124+
await cancelVariantAnalysis(credentials, item.variantAnalysis);
11201125
}
11211126
}
11221127
});

extensions/ql-vscode/src/remote-queries/gh-api/gh-actions-api-client.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import { RemoteQuery } from '../remote-query';
99
import { RemoteQueryFailureIndexItem, RemoteQueryResultIndex, RemoteQuerySuccessIndexItem } from '../remote-query-result-index';
1010
import { getErrorMessage } from '../../pure/helpers-pure';
1111
import { unzipFile } from '../../pure/zip';
12+
import { VariantAnalysis } from '../shared/variant-analysis';
1213

1314
export const RESULT_INDEX_ARTIFACT_NAME = 'result-index';
1415

@@ -94,6 +95,18 @@ export async function cancelRemoteQuery(
9495
}
9596
}
9697

98+
export async function cancelVariantAnalysis(
99+
credentials: Credentials,
100+
variantAnalysis: VariantAnalysis
101+
): Promise<void> {
102+
const octokit = await credentials.getOctokit();
103+
const { actionsWorkflowRunId, controllerRepo: { fullName } } = variantAnalysis;
104+
const response = await octokit.request(`POST /repos/${fullName}/actions/runs/${actionsWorkflowRunId}/cancel`);
105+
if (response.status >= 300) {
106+
throw new Error(`Error cancelling variant analysis: ${response.status} ${response?.data?.message || ''}`);
107+
}
108+
}
109+
97110
export async function downloadArtifactFromLink(
98111
credentials: Credentials,
99112
storagePath: string,

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

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,17 @@ export interface VariantAnalysisScannedRepository {
7676
failureMessage?: string
7777
}
7878

79+
export interface VariantAnalysisRepositoryTask {
80+
repository: Repository,
81+
analysisStatus: VariantAnalysisRepoStatus,
82+
resultCount?: number,
83+
artifactSizeInBytes?: number,
84+
failureMessage?: string,
85+
databaseCommitSha?: string,
86+
sourceLocationPrefix?: string,
87+
artifactUrl?: string,
88+
}
89+
7990
export interface VariantAnalysisSkippedRepositories {
8091
accessMismatchRepos?: VariantAnalysisSkippedRepositoryGroup,
8192
notFoundRepos?: VariantAnalysisSkippedRepositoryGroup,

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

Lines changed: 27 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,11 @@ import { CancellationToken, commands, EventEmitter, ExtensionContext, window } f
55
import { DisposableObject } from '../pure/disposable-object';
66
import { Credentials } from '../authentication';
77
import { VariantAnalysisMonitor } from './variant-analysis-monitor';
8-
import {
9-
VariantAnalysis as VariantAnalysisApiResponse,
10-
VariantAnalysisRepoTask,
11-
VariantAnalysisScannedRepository as ApiVariantAnalysisScannedRepository
12-
} from './gh-api/variant-analysis';
138
import {
149
isVariantAnalysisComplete,
15-
VariantAnalysis, VariantAnalysisQueryLanguage,
10+
VariantAnalysis,
11+
VariantAnalysisQueryLanguage,
12+
VariantAnalysisRepositoryTask,
1613
VariantAnalysisScannedRepository,
1714
VariantAnalysisScannedRepositoryDownloadStatus,
1815
VariantAnalysisScannedRepositoryResult,
@@ -23,7 +20,7 @@ import { VariantAnalysisView } from './variant-analysis-view';
2320
import { VariantAnalysisViewManager } from './variant-analysis-view-manager';
2421
import { VariantAnalysisResultsManager } from './variant-analysis-results-manager';
2522
import { getControllerRepo } from './run-remote-query';
26-
import { processUpdatedVariantAnalysis } from './variant-analysis-processor';
23+
import { processUpdatedVariantAnalysis, processVariantAnalysisRepositoryTask } from './variant-analysis-processor';
2724
import PQueue from 'p-queue';
2825
import { createTimestampFile, showAndLogErrorMessage } from '../helpers';
2926
import * as fs from 'fs-extra';
@@ -206,11 +203,11 @@ export class VariantAnalysisManager extends DisposableObject implements VariantA
206203
}
207204

208205
public async autoDownloadVariantAnalysisResult(
209-
scannedRepo: ApiVariantAnalysisScannedRepository,
210-
variantAnalysisSummary: VariantAnalysisApiResponse,
206+
scannedRepo: VariantAnalysisScannedRepository,
207+
variantAnalysis: VariantAnalysis,
211208
cancellationToken: CancellationToken
212209
): Promise<void> {
213-
if (this.repoStates.get(variantAnalysisSummary.id)?.[scannedRepo.repository.id]?.downloadStatus === VariantAnalysisScannedRepositoryDownloadStatus.Succeeded) {
210+
if (this.repoStates.get(variantAnalysis.id)?.[scannedRepo.repository.id]?.downloadStatus === VariantAnalysisScannedRepositoryDownloadStatus.Succeeded) {
214211
return;
215212
}
216213

@@ -219,56 +216,58 @@ export class VariantAnalysisManager extends DisposableObject implements VariantA
219216
downloadStatus: VariantAnalysisScannedRepositoryDownloadStatus.Pending,
220217
};
221218

222-
await this.onRepoStateUpdated(variantAnalysisSummary.id, repoState);
219+
await this.onRepoStateUpdated(variantAnalysis.id, repoState);
223220

224221
const credentials = await Credentials.initialize(this.ctx);
225222
if (!credentials) { throw Error('Error authenticating with GitHub'); }
226223

227224
if (cancellationToken && cancellationToken.isCancellationRequested) {
228225
repoState.downloadStatus = VariantAnalysisScannedRepositoryDownloadStatus.Failed;
229-
await this.onRepoStateUpdated(variantAnalysisSummary.id, repoState);
226+
await this.onRepoStateUpdated(variantAnalysis.id, repoState);
230227
return;
231228
}
232229

233-
let repoTask: VariantAnalysisRepoTask;
230+
let repoTask: VariantAnalysisRepositoryTask;
234231
try {
235-
repoTask = await ghApiClient.getVariantAnalysisRepo(
232+
const repoTaskResponse = await ghApiClient.getVariantAnalysisRepo(
236233
credentials,
237-
variantAnalysisSummary.controller_repo.id,
238-
variantAnalysisSummary.id,
234+
variantAnalysis.controllerRepo.id,
235+
variantAnalysis.id,
239236
scannedRepo.repository.id
240237
);
238+
239+
repoTask = processVariantAnalysisRepositoryTask(repoTaskResponse);
241240
} catch (e) {
242241
repoState.downloadStatus = VariantAnalysisScannedRepositoryDownloadStatus.Failed;
243-
await this.onRepoStateUpdated(variantAnalysisSummary.id, repoState);
244-
throw new Error(`Could not download the results for variant analysis with id: ${variantAnalysisSummary.id}. Error: ${getErrorMessage(e)}`);
242+
await this.onRepoStateUpdated(variantAnalysis.id, repoState);
243+
throw new Error(`Could not download the results for variant analysis with id: ${variantAnalysis.id}. Error: ${getErrorMessage(e)}`);
245244
}
246245

247-
if (repoTask.artifact_url) {
246+
if (repoTask.artifactUrl) {
248247
repoState.downloadStatus = VariantAnalysisScannedRepositoryDownloadStatus.InProgress;
249-
await this.onRepoStateUpdated(variantAnalysisSummary.id, repoState);
248+
await this.onRepoStateUpdated(variantAnalysis.id, repoState);
250249

251250
try {
252-
await this.variantAnalysisResultsManager.download(credentials, variantAnalysisSummary.id, repoTask, this.getVariantAnalysisStorageLocation(variantAnalysisSummary.id));
251+
await this.variantAnalysisResultsManager.download(credentials, variantAnalysis.id, repoTask, this.getVariantAnalysisStorageLocation(variantAnalysis.id));
253252
} catch (e) {
254253
repoState.downloadStatus = VariantAnalysisScannedRepositoryDownloadStatus.Failed;
255-
await this.onRepoStateUpdated(variantAnalysisSummary.id, repoState);
256-
throw new Error(`Could not download the results for variant analysis with id: ${variantAnalysisSummary.id}. Error: ${getErrorMessage(e)}`);
254+
await this.onRepoStateUpdated(variantAnalysis.id, repoState);
255+
throw new Error(`Could not download the results for variant analysis with id: ${variantAnalysis.id}. Error: ${getErrorMessage(e)}`);
257256
}
258257
}
259258

260259
repoState.downloadStatus = VariantAnalysisScannedRepositoryDownloadStatus.Succeeded;
261-
await this.onRepoStateUpdated(variantAnalysisSummary.id, repoState);
260+
await this.onRepoStateUpdated(variantAnalysis.id, repoState);
262261

263-
await fs.outputJson(this.getRepoStatesStoragePath(variantAnalysisSummary.id), this.repoStates.get(variantAnalysisSummary.id));
262+
await fs.outputJson(this.getRepoStatesStoragePath(variantAnalysis.id), this.repoStates.get(variantAnalysis.id));
264263
}
265264

266265
public async enqueueDownload(
267-
scannedRepo: ApiVariantAnalysisScannedRepository,
268-
variantAnalysisSummary: VariantAnalysisApiResponse,
266+
scannedRepo: VariantAnalysisScannedRepository,
267+
variantAnalysis: VariantAnalysis,
269268
token: CancellationToken
270269
): Promise<void> {
271-
await this.queue.add(() => this.autoDownloadVariantAnalysisResult(scannedRepo, variantAnalysisSummary, token));
270+
await this.queue.add(() => this.autoDownloadVariantAnalysisResult(scannedRepo, variantAnalysis, token));
272271
}
273272

274273
public downloadsQueueSize(): number {

0 commit comments

Comments
 (0)