Skip to content

Commit be054ca

Browse files
committed
Move "exporting results" to a separate file
1 parent 0a06452 commit be054ca

File tree

3 files changed

+109
-65
lines changed

3 files changed

+109
-65
lines changed

extensions/ql-vscode/src/extension.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,7 @@ import { URLSearchParams } from 'url';
9797
import { handleDownloadPacks, handleInstallPackDependencies } from './packaging';
9898
import { RemoteQueryHistoryItem } from './remote-queries/remote-query-history-item';
9999
import { HistoryItemLabelProvider } from './history-item-label-provider';
100+
import { exportRemoteQueryResults } from './remote-queries/export-results';
100101

101102
/**
102103
* extension.ts
@@ -897,8 +898,9 @@ async function activateWithInstalledDistribution(
897898

898899
ctx.subscriptions.push(
899900
commandRunner('codeQL.exportVariantAnalysisResults', async () => {
900-
await rqm.exportVariantAnalysisResults();
901-
}));
901+
await exportRemoteQueryResults(qhm, rqm, ctx);
902+
})
903+
);
902904

903905
ctx.subscriptions.push(
904906
commandRunner(
Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
import { window, commands, Uri, ExtensionContext, QuickPickItem } from 'vscode';
2+
import { Credentials } from '../authentication';
3+
import { UserCancellationException } from '../commandRunner';
4+
import { showInformationMessageWithAction, showAndLogInformationMessage } from '../helpers';
5+
import { logger } from '../logging';
6+
import { QueryHistoryManager } from '../query-history';
7+
import { createGist } from './gh-actions-api-client';
8+
import { RemoteQueriesManager } from './remote-queries-manager';
9+
import { generateMarkdown } from './remote-queries-markdown-generation';
10+
import { RemoteQuery } from './remote-query';
11+
import { AnalysisResults } from './shared/analysis-result';
12+
13+
/**
14+
* Exports the results of the currently-selected remote query.
15+
* The user is prompted to select the export format.
16+
*/
17+
export async function exportRemoteQueryResults(
18+
queryHistoryManager: QueryHistoryManager,
19+
remoteQueriesManager: RemoteQueriesManager,
20+
ctx: ExtensionContext,
21+
): Promise<void> {
22+
const queryHistoryItem = queryHistoryManager.getCurrentQueryHistoryItem();
23+
if (!queryHistoryItem || queryHistoryItem.t !== 'remote') {
24+
throw new Error('No variant analysis results currently open. To open results, click an item in the query history view.');
25+
} else if (!queryHistoryItem.completed) {
26+
throw new Error('Variant analysis results are not yet available.');
27+
}
28+
const queryId = queryHistoryItem.queryId;
29+
void logger.log(`Exporting variant analysis results for query: ${queryId}`);
30+
const query = queryHistoryItem.remoteQuery;
31+
const analysesResults = remoteQueriesManager.getAnalysesResults(queryId);
32+
33+
const gistOption = {
34+
label: '$(ports-open-browser-icon) Create Gist (GitHub)',
35+
};
36+
const localMarkdownOption = {
37+
label: '$(markdown) Save as markdown',
38+
};
39+
const exportFormat = await determineExportFormat(gistOption, localMarkdownOption);
40+
41+
if (exportFormat === gistOption) {
42+
await exportResultsToGist(ctx, query, analysesResults);
43+
} else if (exportFormat === localMarkdownOption) {
44+
// TODO: Write function that creates local markdown files
45+
// const markdownFiles = generateMarkdown(query, analysesResults, 'local');
46+
void showAndLogInformationMessage('Local markdown export not yet available');
47+
}
48+
}
49+
50+
/**
51+
* Determines the format in which to export the results, from the given export options.
52+
*/
53+
async function determineExportFormat(
54+
...options: { label: string }[]
55+
): Promise<QuickPickItem> {
56+
const exportFormat = await window.showQuickPick(
57+
options,
58+
{
59+
placeHolder: 'Select export format',
60+
canPickMany: false,
61+
ignoreFocusOut: true,
62+
}
63+
);
64+
if (!exportFormat || !exportFormat.label) {
65+
throw new UserCancellationException('No export format selected', true);
66+
}
67+
return exportFormat;
68+
}
69+
70+
/**
71+
* Converts the results of a remote query to markdown and uploads the files as a secret gist.
72+
*/
73+
async function exportResultsToGist(
74+
ctx: ExtensionContext,
75+
query: RemoteQuery,
76+
analysesResults: AnalysisResults[]
77+
): Promise<void> {
78+
const credentials = await Credentials.initialize(ctx);
79+
const description = 'CodeQL Variant Analysis Results';
80+
const markdownFiles = generateMarkdown(query, analysesResults, 'gist');
81+
// Convert markdownFiles to the appropriate format for uploading to gist
82+
const gistFiles = markdownFiles.reduce((acc, cur) => {
83+
acc[`${cur.fileName}.md`] = { content: cur.content.join('\n') };
84+
return acc;
85+
}, {} as { [key: string]: { content: string } });
86+
87+
const gistUrl = await createGist(credentials, description, gistFiles);
88+
if (gistUrl) {
89+
const shouldOpenGist = await showInformationMessageWithAction(
90+
'Variant analysis results exported to gist.',
91+
'Open gist'
92+
);
93+
if (shouldOpenGist) {
94+
await commands.executeCommand('vscode.open', Uri.parse(gistUrl));
95+
}
96+
}
97+
}

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

Lines changed: 8 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,14 @@ import * as fs from 'fs-extra';
55

66
import { Credentials } from '../authentication';
77
import { CodeQLCliServer } from '../cli';
8-
import { ProgressCallback, UserCancellationException } from '../commandRunner';
8+
import { ProgressCallback } from '../commandRunner';
99
import { createTimestampFile, showAndLogErrorMessage, showAndLogInformationMessage, showInformationMessageWithAction } from '../helpers';
1010
import { Logger } from '../logging';
1111
import { runRemoteQuery } from './run-remote-query';
1212
import { RemoteQueriesInterfaceManager } from './remote-queries-interface';
1313
import { RemoteQuery } from './remote-query';
1414
import { RemoteQueriesMonitor } from './remote-queries-monitor';
15-
import { createGist, getRemoteQueryIndex } from './gh-actions-api-client';
15+
import { getRemoteQueryIndex } from './gh-actions-api-client';
1616
import { RemoteQueryResultIndex } from './remote-query-result-index';
1717
import { RemoteQueryResult } from './remote-query-result';
1818
import { DownloadLink } from './download-link';
@@ -23,7 +23,7 @@ import { QueryHistoryManager } from '../query-history';
2323
import { QueryStatus } from '../query-status';
2424
import { DisposableObject } from '../pure/disposable-object';
2525
import { QueryHistoryInfo } from '../query-results';
26-
import { generateMarkdown } from './remote-queries-markdown-generation';
26+
import { AnalysisResults } from './shared/analysis-result';
2727

2828
const autoDownloadMaxSize = 300 * 1024;
2929
const autoDownloadMaxCount = 100;
@@ -39,7 +39,7 @@ export class RemoteQueriesManager extends DisposableObject {
3939
private readonly cliServer: CodeQLCliServer,
4040
private readonly qhm: QueryHistoryManager,
4141
private readonly storagePath: string,
42-
private readonly logger: Logger,
42+
logger: Logger,
4343
) {
4444
super();
4545
this.analysesResultsManager = new AnalysesResultsManager(ctx, cliServer, storagePath, logger);
@@ -303,64 +303,9 @@ export class RemoteQueriesManager extends DisposableObject {
303303
}
304304
}
305305

306-
public async exportVariantAnalysisResults(): Promise<void> {
307-
const queryHistoryItem = this.qhm.getCurrentQueryHistoryItem();
308-
309-
if (!queryHistoryItem || queryHistoryItem.t !== 'remote') {
310-
throw new Error('No variant analysis results currently open. To open results, click an item in the query history view.');
311-
} else if (!queryHistoryItem.completed) {
312-
throw new Error('Variant analysis results are not yet available.');
313-
}
314-
315-
const queryId = queryHistoryItem.queryId;
316-
void this.logger.log(`Exporting variant analysis results for query: ${queryId}`);
317-
const query = queryHistoryItem.remoteQuery;
318-
const analysesResults = this.analysesResultsManager.getAnalysesResults(queryId);
319-
320-
const gistOption = {
321-
label: '$(ports-open-browser-icon) Create Gist (GitHub)',
322-
};
323-
const localMarkdownOption = {
324-
label: '$(markdown) Save as markdown',
325-
};
326-
327-
// User selects export format in quick pick
328-
const exportFormat = await window.showQuickPick(
329-
[gistOption, localMarkdownOption],
330-
{
331-
placeHolder: 'Select export format',
332-
canPickMany: false,
333-
ignoreFocusOut: true,
334-
}
335-
);
336-
337-
if (!exportFormat || !exportFormat.label) {
338-
throw new UserCancellationException('No export format selected', true);
339-
}
340-
341-
if (exportFormat === gistOption) {
342-
const credentials = await Credentials.initialize(this.ctx);
343-
const description = 'CodeQL Variant Analysis Results';
344-
345-
const markdownFiles = generateMarkdown(query, analysesResults, 'gist');
346-
347-
// Convert markdownFiles to the appropriate format for uploading to gist
348-
const gistFiles = markdownFiles.reduce((acc, cur) => {
349-
acc[`${cur.fileName}.md`] = { content: cur.content.join('\n') };
350-
return acc;
351-
}, {} as { [key: string]: { content: string } });
352-
353-
const gistUrl = await createGist(credentials, description, gistFiles);
354-
if (gistUrl) {
355-
const shouldOpenGist = await showInformationMessageWithAction('Variant analysis results exported to gist.', 'Open gist');
356-
if (shouldOpenGist) {
357-
await commands.executeCommand('vscode.open', Uri.parse(gistUrl));
358-
}
359-
}
360-
} else if (exportFormat === localMarkdownOption) {
361-
// TODO: Write function that creates local markdown files
362-
// const markdownFiles = generateMarkdown(query, analysesResults, 'local');
363-
void showAndLogInformationMessage('Local markdown export not yet available');
364-
}
306+
// Pulled from the analysis results manager, so that we can get access to
307+
// analyses results from the "export results" command.
308+
public getAnalysesResults(queryId: string): AnalysisResults[] {
309+
return [...this.analysesResultsManager.getAnalysesResults(queryId)];
365310
}
366311
}

0 commit comments

Comments
 (0)