Move "exporting results" to a separate file

This commit is contained in:
shati-patel
2022-05-12 12:11:25 +01:00
committed by Shati Patel
parent 0a06452450
commit be054ca4f8
3 changed files with 109 additions and 65 deletions

View File

@@ -97,6 +97,7 @@ import { URLSearchParams } from 'url';
import { handleDownloadPacks, handleInstallPackDependencies } from './packaging';
import { RemoteQueryHistoryItem } from './remote-queries/remote-query-history-item';
import { HistoryItemLabelProvider } from './history-item-label-provider';
import { exportRemoteQueryResults } from './remote-queries/export-results';
/**
* extension.ts
@@ -897,8 +898,9 @@ async function activateWithInstalledDistribution(
ctx.subscriptions.push(
commandRunner('codeQL.exportVariantAnalysisResults', async () => {
await rqm.exportVariantAnalysisResults();
}));
await exportRemoteQueryResults(qhm, rqm, ctx);
})
);
ctx.subscriptions.push(
commandRunner(

View File

@@ -0,0 +1,97 @@
import { window, commands, Uri, ExtensionContext, QuickPickItem } from 'vscode';
import { Credentials } from '../authentication';
import { UserCancellationException } from '../commandRunner';
import { showInformationMessageWithAction, showAndLogInformationMessage } from '../helpers';
import { logger } from '../logging';
import { QueryHistoryManager } from '../query-history';
import { createGist } from './gh-actions-api-client';
import { RemoteQueriesManager } from './remote-queries-manager';
import { generateMarkdown } from './remote-queries-markdown-generation';
import { RemoteQuery } from './remote-query';
import { AnalysisResults } from './shared/analysis-result';
/**
* Exports the results of the currently-selected remote query.
* The user is prompted to select the export format.
*/
export async function exportRemoteQueryResults(
queryHistoryManager: QueryHistoryManager,
remoteQueriesManager: RemoteQueriesManager,
ctx: ExtensionContext,
): Promise<void> {
const queryHistoryItem = queryHistoryManager.getCurrentQueryHistoryItem();
if (!queryHistoryItem || queryHistoryItem.t !== 'remote') {
throw new Error('No variant analysis results currently open. To open results, click an item in the query history view.');
} else if (!queryHistoryItem.completed) {
throw new Error('Variant analysis results are not yet available.');
}
const queryId = queryHistoryItem.queryId;
void logger.log(`Exporting variant analysis results for query: ${queryId}`);
const query = queryHistoryItem.remoteQuery;
const analysesResults = remoteQueriesManager.getAnalysesResults(queryId);
const gistOption = {
label: '$(ports-open-browser-icon) Create Gist (GitHub)',
};
const localMarkdownOption = {
label: '$(markdown) Save as markdown',
};
const exportFormat = await determineExportFormat(gistOption, localMarkdownOption);
if (exportFormat === gistOption) {
await exportResultsToGist(ctx, query, analysesResults);
} else if (exportFormat === localMarkdownOption) {
// TODO: Write function that creates local markdown files
// const markdownFiles = generateMarkdown(query, analysesResults, 'local');
void showAndLogInformationMessage('Local markdown export not yet available');
}
}
/**
* Determines the format in which to export the results, from the given export options.
*/
async function determineExportFormat(
...options: { label: string }[]
): Promise<QuickPickItem> {
const exportFormat = await window.showQuickPick(
options,
{
placeHolder: 'Select export format',
canPickMany: false,
ignoreFocusOut: true,
}
);
if (!exportFormat || !exportFormat.label) {
throw new UserCancellationException('No export format selected', true);
}
return exportFormat;
}
/**
* Converts the results of a remote query to markdown and uploads the files as a secret gist.
*/
async function exportResultsToGist(
ctx: ExtensionContext,
query: RemoteQuery,
analysesResults: AnalysisResults[]
): Promise<void> {
const credentials = await Credentials.initialize(ctx);
const description = 'CodeQL Variant Analysis Results';
const markdownFiles = generateMarkdown(query, analysesResults, 'gist');
// Convert markdownFiles to the appropriate format for uploading to gist
const gistFiles = markdownFiles.reduce((acc, cur) => {
acc[`${cur.fileName}.md`] = { content: cur.content.join('\n') };
return acc;
}, {} as { [key: string]: { content: string } });
const gistUrl = await createGist(credentials, description, gistFiles);
if (gistUrl) {
const shouldOpenGist = await showInformationMessageWithAction(
'Variant analysis results exported to gist.',
'Open gist'
);
if (shouldOpenGist) {
await commands.executeCommand('vscode.open', Uri.parse(gistUrl));
}
}
}

View File

@@ -5,14 +5,14 @@ import * as fs from 'fs-extra';
import { Credentials } from '../authentication';
import { CodeQLCliServer } from '../cli';
import { ProgressCallback, UserCancellationException } from '../commandRunner';
import { ProgressCallback } from '../commandRunner';
import { createTimestampFile, showAndLogErrorMessage, showAndLogInformationMessage, showInformationMessageWithAction } from '../helpers';
import { Logger } from '../logging';
import { runRemoteQuery } from './run-remote-query';
import { RemoteQueriesInterfaceManager } from './remote-queries-interface';
import { RemoteQuery } from './remote-query';
import { RemoteQueriesMonitor } from './remote-queries-monitor';
import { createGist, getRemoteQueryIndex } from './gh-actions-api-client';
import { getRemoteQueryIndex } from './gh-actions-api-client';
import { RemoteQueryResultIndex } from './remote-query-result-index';
import { RemoteQueryResult } from './remote-query-result';
import { DownloadLink } from './download-link';
@@ -23,7 +23,7 @@ import { QueryHistoryManager } from '../query-history';
import { QueryStatus } from '../query-status';
import { DisposableObject } from '../pure/disposable-object';
import { QueryHistoryInfo } from '../query-results';
import { generateMarkdown } from './remote-queries-markdown-generation';
import { AnalysisResults } from './shared/analysis-result';
const autoDownloadMaxSize = 300 * 1024;
const autoDownloadMaxCount = 100;
@@ -39,7 +39,7 @@ export class RemoteQueriesManager extends DisposableObject {
private readonly cliServer: CodeQLCliServer,
private readonly qhm: QueryHistoryManager,
private readonly storagePath: string,
private readonly logger: Logger,
logger: Logger,
) {
super();
this.analysesResultsManager = new AnalysesResultsManager(ctx, cliServer, storagePath, logger);
@@ -303,64 +303,9 @@ export class RemoteQueriesManager extends DisposableObject {
}
}
public async exportVariantAnalysisResults(): Promise<void> {
const queryHistoryItem = this.qhm.getCurrentQueryHistoryItem();
if (!queryHistoryItem || queryHistoryItem.t !== 'remote') {
throw new Error('No variant analysis results currently open. To open results, click an item in the query history view.');
} else if (!queryHistoryItem.completed) {
throw new Error('Variant analysis results are not yet available.');
}
const queryId = queryHistoryItem.queryId;
void this.logger.log(`Exporting variant analysis results for query: ${queryId}`);
const query = queryHistoryItem.remoteQuery;
const analysesResults = this.analysesResultsManager.getAnalysesResults(queryId);
const gistOption = {
label: '$(ports-open-browser-icon) Create Gist (GitHub)',
};
const localMarkdownOption = {
label: '$(markdown) Save as markdown',
};
// User selects export format in quick pick
const exportFormat = await window.showQuickPick(
[gistOption, localMarkdownOption],
{
placeHolder: 'Select export format',
canPickMany: false,
ignoreFocusOut: true,
}
);
if (!exportFormat || !exportFormat.label) {
throw new UserCancellationException('No export format selected', true);
}
if (exportFormat === gistOption) {
const credentials = await Credentials.initialize(this.ctx);
const description = 'CodeQL Variant Analysis Results';
const markdownFiles = generateMarkdown(query, analysesResults, 'gist');
// Convert markdownFiles to the appropriate format for uploading to gist
const gistFiles = markdownFiles.reduce((acc, cur) => {
acc[`${cur.fileName}.md`] = { content: cur.content.join('\n') };
return acc;
}, {} as { [key: string]: { content: string } });
const gistUrl = await createGist(credentials, description, gistFiles);
if (gistUrl) {
const shouldOpenGist = await showInformationMessageWithAction('Variant analysis results exported to gist.', 'Open gist');
if (shouldOpenGist) {
await commands.executeCommand('vscode.open', Uri.parse(gistUrl));
}
}
} else if (exportFormat === localMarkdownOption) {
// TODO: Write function that creates local markdown files
// const markdownFiles = generateMarkdown(query, analysesResults, 'local');
void showAndLogInformationMessage('Local markdown export not yet available');
}
// Pulled from the analysis results manager, so that we can get access to
// analyses results from the "export results" command.
public getAnalysesResults(queryId: string): AnalysisResults[] {
return [...this.analysesResultsManager.getAnalysesResults(queryId)];
}
}