Skip to content

Commit b1a5f14

Browse files
committed
Split flows for running remote queries
This removes the `runRemoteQuery` method and instead moves all logic specific to remote queries/variant analysis to the remote queries manager and variant analysis manager respectively. This will make it easier to completely remove the remote queries manager in the future.
1 parent 082fea8 commit b1a5f14

File tree

6 files changed

+270
-224
lines changed

6 files changed

+270
-224
lines changed

extensions/ql-vscode/src/extension.ts

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ import {
3333
CliConfigListener,
3434
DistributionConfigListener,
3535
isCanary,
36+
isVariantAnalysisLiveResultsEnabled,
3637
joinOrderWarningThreshold,
3738
MAX_QUERIES,
3839
QueryHistoryConfigListener,
@@ -489,13 +490,13 @@ async function activateWithInstalledDistribution(
489490
const variantAnalysisStorageDir = path.join(ctx.globalStorageUri.fsPath, 'variant-analyses');
490491
await fs.ensureDir(variantAnalysisStorageDir);
491492
const variantAnalysisResultsManager = new VariantAnalysisResultsManager(cliServer, logger);
492-
const variantAnalysisManager = new VariantAnalysisManager(ctx, variantAnalysisStorageDir, variantAnalysisResultsManager);
493+
const variantAnalysisManager = new VariantAnalysisManager(ctx, cliServer, variantAnalysisStorageDir, variantAnalysisResultsManager);
493494
ctx.subscriptions.push(variantAnalysisManager);
494495
ctx.subscriptions.push(variantAnalysisResultsManager);
495496
ctx.subscriptions.push(workspace.registerTextDocumentContentProvider('codeql-variant-analysis', createVariantAnalysisContentProvider(variantAnalysisManager)));
496497

497498
void logger.log('Initializing remote queries manager.');
498-
const rqm = new RemoteQueriesManager(ctx, cliServer, queryStorageDir, logger, variantAnalysisManager);
499+
const rqm = new RemoteQueriesManager(ctx, cliServer, queryStorageDir, logger);
499500
ctx.subscriptions.push(rqm);
500501

501502
void logger.log('Initializing query history.');
@@ -906,11 +907,20 @@ async function activateWithInstalledDistribution(
906907
step: 0,
907908
message: 'Getting credentials'
908909
});
909-
await rqm.runRemoteQuery(
910-
uri || window.activeTextEditor?.document.uri,
911-
progress,
912-
token
913-
);
910+
911+
if (isVariantAnalysisLiveResultsEnabled()) {
912+
await variantAnalysisManager.runVariantAnalysis(
913+
uri || window.activeTextEditor?.document.uri,
914+
progress,
915+
token
916+
);
917+
} else {
918+
await rqm.runRemoteQuery(
919+
uri || window.activeTextEditor?.document.uri,
920+
progress,
921+
token
922+
);
923+
}
914924
} else {
915925
throw new Error('Variant analysis requires the CodeQL Canary version to run.');
916926
}

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

Lines changed: 42 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { CancellationToken, commands, EventEmitter, ExtensionContext, Uri, env, window } from 'vscode';
1+
import { CancellationToken, commands, EventEmitter, ExtensionContext, Uri, env } from 'vscode';
22
import { nanoid } from 'nanoid';
33
import * as path from 'path';
44
import * as fs from 'fs-extra';
@@ -9,7 +9,11 @@ import { CodeQLCliServer } from '../cli';
99
import { ProgressCallback } from '../commandRunner';
1010
import { createTimestampFile, showAndLogErrorMessage, showAndLogInformationMessage, showInformationMessageWithAction } from '../helpers';
1111
import { Logger } from '../logging';
12-
import { runRemoteQuery } from './run-remote-query';
12+
import {
13+
buildRemoteQueryEntity,
14+
prepareRemoteQueryRun,
15+
runRemoteQueriesApiRequest,
16+
} from './run-remote-query';
1317
import { RemoteQueriesView } from './remote-queries-view';
1418
import { RemoteQuery } from './remote-query';
1519
import { RemoteQueriesMonitor } from './remote-queries-monitor';
@@ -22,7 +26,6 @@ import { assertNever } from '../pure/helpers-pure';
2226
import { QueryStatus } from '../query-status';
2327
import { DisposableObject } from '../pure/disposable-object';
2428
import { AnalysisResults } from './shared/analysis-result';
25-
import { VariantAnalysisManager } from './variant-analysis-manager';
2629

2730
const autoDownloadMaxSize = 300 * 1024;
2831
const autoDownloadMaxCount = 100;
@@ -57,21 +60,18 @@ export class RemoteQueriesManager extends DisposableObject {
5760

5861
private readonly remoteQueriesMonitor: RemoteQueriesMonitor;
5962
private readonly analysesResultsManager: AnalysesResultsManager;
60-
private readonly variantAnalysisManager: VariantAnalysisManager;
6163
private readonly view: RemoteQueriesView;
6264

6365
constructor(
6466
private readonly ctx: ExtensionContext,
6567
private readonly cliServer: CodeQLCliServer,
6668
private readonly storagePath: string,
6769
logger: Logger,
68-
variantAnalysisManager: VariantAnalysisManager,
6970
) {
7071
super();
7172
this.analysesResultsManager = new AnalysesResultsManager(ctx, cliServer, storagePath, logger);
7273
this.view = new RemoteQueriesView(ctx, logger, this.analysesResultsManager);
7374
this.remoteQueriesMonitor = new RemoteQueriesMonitor(ctx, logger);
74-
this.variantAnalysisManager = variantAnalysisManager;
7575

7676
this.remoteQueryAddedEventEmitter = this.push(new EventEmitter<NewQueryEvent>());
7777
this.remoteQueryRemovedEventEmitter = this.push(new EventEmitter<RemovedQueryEvent>());
@@ -119,21 +119,47 @@ export class RemoteQueriesManager extends DisposableObject {
119119
uri: Uri | undefined,
120120
progress: ProgressCallback,
121121
token: CancellationToken
122-
): Promise<void> {
122+
): Promise<RemoteQuery | undefined> {
123123
const credentials = await Credentials.initialize(this.ctx);
124124

125-
const querySubmission = await runRemoteQuery(this.cliServer, credentials, uri || window.activeTextEditor?.document.uri, progress, token, this.variantAnalysisManager);
125+
const {
126+
actionBranch,
127+
base64Pack,
128+
repoSelection,
129+
queryFile,
130+
queryMetadata,
131+
controllerRepo,
132+
queryStartTime,
133+
language,
134+
} = await prepareRemoteQueryRun(this.cliServer, credentials, uri, progress, token);
135+
136+
const apiResponse = await runRemoteQueriesApiRequest(credentials, actionBranch, language, repoSelection, controllerRepo, base64Pack);
137+
138+
if (!apiResponse) {
139+
return undefined;
140+
}
126141

127-
if (querySubmission?.query) {
128-
const query = querySubmission.query;
129-
const queryId = this.createQueryId();
142+
const workflowRunId = apiResponse.workflow_run_id;
143+
const repositoryCount = apiResponse.repositories_queried.length;
144+
const query = await buildRemoteQueryEntity(
145+
queryFile,
146+
queryMetadata,
147+
controllerRepo,
148+
queryStartTime,
149+
workflowRunId,
150+
language,
151+
repositoryCount
152+
);
130153

131-
await this.prepareStorageDirectory(queryId);
132-
await this.storeJsonFile(queryId, 'query.json', query);
154+
const queryId = this.createQueryId();
133155

134-
this.remoteQueryAddedEventEmitter.fire({ queryId, query });
135-
void commands.executeCommand('codeQL.monitorRemoteQuery', queryId, query);
136-
}
156+
await this.prepareStorageDirectory(queryId);
157+
await this.storeJsonFile(queryId, 'query.json', query);
158+
159+
this.remoteQueryAddedEventEmitter.fire({ queryId, query });
160+
void commands.executeCommand('codeQL.monitorRemoteQuery', queryId, query);
161+
162+
return query;
137163
}
138164

139165
public async monitorRemoteQuery(

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

Lines changed: 5 additions & 101 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { CancellationToken, commands, Uri, window } from 'vscode';
1+
import { CancellationToken, Uri, window } from 'vscode';
22
import * as path from 'path';
33
import * as yaml from 'js-yaml';
44
import * as fs from 'fs-extra';
@@ -16,22 +16,17 @@ import {
1616
import { Credentials } from '../authentication';
1717
import * as cli from '../cli';
1818
import { logger } from '../logging';
19-
import { getActionBranch, getRemoteControllerRepo, isVariantAnalysisLiveResultsEnabled, setRemoteControllerRepo } from '../config';
19+
import { getActionBranch, getRemoteControllerRepo, setRemoteControllerRepo } from '../config';
2020
import { ProgressCallback, UserCancellationException } from '../commandRunner';
2121
import { RequestError } from '@octokit/types/dist-types';
2222
import { RemoteQuery } from './remote-query';
23-
import { RemoteQuerySubmissionResult } from './remote-query-submission-result';
2423
import { QueryMetadata } from '../pure/interface-types';
2524
import { getErrorMessage, REPO_REGEX } from '../pure/helpers-pure';
2625
import { pluralize } from '../pure/word';
2726
import * as ghApiClient from './gh-api/gh-api-client';
2827
import { RemoteQueriesResponse } from './gh-api/remote-queries';
2928
import { getRepositorySelection, isValidSelection, RepositorySelection } from './repository-selection';
30-
import { parseVariantAnalysisQueryLanguage, VariantAnalysisSubmission } from './shared/variant-analysis';
3129
import { Repository } from './shared/repository';
32-
import { processVariantAnalysis } from './variant-analysis-processor';
33-
import { VariantAnalysisManager } from './variant-analysis-manager';
34-
import { CodeQLCliServer } from '../cli';
3530

3631
export interface QlPack {
3732
name: string;
@@ -262,98 +257,7 @@ export async function prepareRemoteQueryRun(
262257
};
263258
}
264259

265-
export async function runRemoteQuery(
266-
cliServer: CodeQLCliServer,
267-
credentials: Credentials,
268-
uri: Uri | undefined,
269-
progress: ProgressCallback,
270-
token: CancellationToken,
271-
variantAnalysisManager: VariantAnalysisManager,
272-
): Promise<void | RemoteQuerySubmissionResult> {
273-
if (!(await cliServer.cliConstraints.supportsRemoteQueries())) {
274-
throw new Error(`Variant analysis is not supported by this version of CodeQL. Please upgrade to v${cli.CliVersionConstraint.CLI_VERSION_REMOTE_QUERIES
275-
} or later.`);
276-
}
277-
278-
const {
279-
actionBranch,
280-
base64Pack,
281-
repoSelection,
282-
queryFile,
283-
queryMetadata,
284-
controllerRepo,
285-
queryStartTime,
286-
language,
287-
} = await prepareRemoteQueryRun(cliServer, credentials, uri, progress, token);
288-
289-
if (isVariantAnalysisLiveResultsEnabled()) {
290-
const queryName = getQueryName(queryMetadata, queryFile);
291-
const variantAnalysisLanguage = parseVariantAnalysisQueryLanguage(language);
292-
if (variantAnalysisLanguage === undefined) {
293-
throw new UserCancellationException(`Found unsupported language: ${language}`);
294-
}
295-
296-
const queryText = await fs.readFile(queryFile, 'utf8');
297-
298-
const variantAnalysisSubmission: VariantAnalysisSubmission = {
299-
startTime: queryStartTime,
300-
actionRepoRef: actionBranch,
301-
controllerRepoId: controllerRepo.id,
302-
query: {
303-
name: queryName,
304-
filePath: queryFile,
305-
pack: base64Pack,
306-
language: variantAnalysisLanguage,
307-
text: queryText,
308-
},
309-
databases: {
310-
repositories: repoSelection.repositories,
311-
repositoryLists: repoSelection.repositoryLists,
312-
repositoryOwners: repoSelection.owners
313-
}
314-
};
315-
316-
const variantAnalysisResponse = await ghApiClient.submitVariantAnalysis(
317-
credentials,
318-
variantAnalysisSubmission
319-
);
320-
321-
const processedVariantAnalysis = processVariantAnalysis(variantAnalysisSubmission, variantAnalysisResponse);
322-
323-
await variantAnalysisManager.onVariantAnalysisSubmitted(processedVariantAnalysis);
324-
325-
void logger.log(`Variant analysis:\n${JSON.stringify(processedVariantAnalysis, null, 2)}`);
326-
327-
void showAndLogInformationMessage(`Variant analysis ${processedVariantAnalysis.query.name} submitted for processing`);
328-
329-
void commands.executeCommand('codeQL.openVariantAnalysisView', processedVariantAnalysis.id);
330-
void commands.executeCommand('codeQL.monitorVariantAnalysis', processedVariantAnalysis);
331-
332-
return { variantAnalysis: processedVariantAnalysis };
333-
} else {
334-
const apiResponse = await runRemoteQueriesApiRequest(credentials, actionBranch, language, repoSelection, controllerRepo, base64Pack);
335-
336-
if (!apiResponse) {
337-
return;
338-
}
339-
340-
const workflowRunId = apiResponse.workflow_run_id;
341-
const repositoryCount = apiResponse.repositories_queried.length;
342-
const remoteQuery = await buildRemoteQueryEntity(
343-
queryFile,
344-
queryMetadata,
345-
controllerRepo,
346-
queryStartTime,
347-
workflowRunId,
348-
language,
349-
repositoryCount);
350-
351-
// don't return the path because it has been deleted
352-
return { query: remoteQuery };
353-
}
354-
}
355-
356-
async function runRemoteQueriesApiRequest(
260+
export async function runRemoteQueriesApiRequest(
357261
credentials: Credentials,
358262
ref: string,
359263
language: string,
@@ -455,7 +359,7 @@ async function ensureNameAndSuite(queryPackDir: string, packRelativePath: string
455359
await fs.writeFile(packPath, yaml.dump(qlpack));
456360
}
457361

458-
async function buildRemoteQueryEntity(
362+
export async function buildRemoteQueryEntity(
459363
queryFilePath: string,
460364
queryMetadata: QueryMetadata | undefined,
461365
controllerRepo: Repository,
@@ -483,7 +387,7 @@ async function buildRemoteQueryEntity(
483387
};
484388
}
485389

486-
function getQueryName(queryMetadata: QueryMetadata | undefined, queryFilePath: string): string {
390+
export function getQueryName(queryMetadata: QueryMetadata | undefined, queryFilePath: string): string {
487391
// The query name is either the name as specified in the query metadata, or the file name.
488392
return queryMetadata?.name ?? path.basename(queryFilePath);
489393
}

0 commit comments

Comments
 (0)