Merge pull request #1820 from github/koesie10/export-progress
Add progress notification to exporting results
This commit is contained in:
@@ -1235,9 +1235,11 @@ async function activateWithInstalledDistribution(
|
|||||||
);
|
);
|
||||||
|
|
||||||
ctx.subscriptions.push(
|
ctx.subscriptions.push(
|
||||||
commandRunner(
|
commandRunnerWithProgress(
|
||||||
"codeQL.exportVariantAnalysisResults",
|
"codeQL.exportVariantAnalysisResults",
|
||||||
async (
|
async (
|
||||||
|
progress: ProgressCallback,
|
||||||
|
token: CancellationToken,
|
||||||
variantAnalysisId: number,
|
variantAnalysisId: number,
|
||||||
filterSort?: RepositoriesFilterSortStateWithIds,
|
filterSort?: RepositoriesFilterSortStateWithIds,
|
||||||
) => {
|
) => {
|
||||||
@@ -1246,8 +1248,14 @@ async function activateWithInstalledDistribution(
|
|||||||
variantAnalysisManager,
|
variantAnalysisManager,
|
||||||
variantAnalysisId,
|
variantAnalysisId,
|
||||||
filterSort,
|
filterSort,
|
||||||
|
progress,
|
||||||
|
token,
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
title: "Exporting variant analysis results",
|
||||||
|
cancellable: true,
|
||||||
|
},
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import { ensureDir, writeFile } from "fs-extra";
|
|||||||
|
|
||||||
import {
|
import {
|
||||||
commands,
|
commands,
|
||||||
|
CancellationToken,
|
||||||
ExtensionContext,
|
ExtensionContext,
|
||||||
Uri,
|
Uri,
|
||||||
ViewColumn,
|
ViewColumn,
|
||||||
@@ -10,7 +11,7 @@ import {
|
|||||||
workspace,
|
workspace,
|
||||||
} from "vscode";
|
} from "vscode";
|
||||||
import { Credentials } from "../authentication";
|
import { Credentials } from "../authentication";
|
||||||
import { UserCancellationException } from "../commandRunner";
|
import { ProgressCallback, UserCancellationException } from "../commandRunner";
|
||||||
import { showInformationMessageWithAction } from "../helpers";
|
import { showInformationMessageWithAction } from "../helpers";
|
||||||
import { extLogger } from "../common";
|
import { extLogger } from "../common";
|
||||||
import { QueryHistoryManager } from "../query-history";
|
import { QueryHistoryManager } from "../query-history";
|
||||||
@@ -133,6 +134,8 @@ export async function exportRemoteQueryAnalysisResults(
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const MAX_VARIANT_ANALYSIS_EXPORT_PROGRESS_STEPS = 2;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Exports the results of the given or currently-selected remote query.
|
* Exports the results of the given or currently-selected remote query.
|
||||||
* The user is prompted to select the export format.
|
* The user is prompted to select the export format.
|
||||||
@@ -141,7 +144,9 @@ export async function exportVariantAnalysisResults(
|
|||||||
ctx: ExtensionContext,
|
ctx: ExtensionContext,
|
||||||
variantAnalysisManager: VariantAnalysisManager,
|
variantAnalysisManager: VariantAnalysisManager,
|
||||||
variantAnalysisId: number,
|
variantAnalysisId: number,
|
||||||
filterSort?: RepositoriesFilterSortStateWithIds,
|
filterSort: RepositoriesFilterSortStateWithIds | undefined,
|
||||||
|
progress: ProgressCallback,
|
||||||
|
token: CancellationToken,
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
const variantAnalysis = await variantAnalysisManager.getVariantAnalysis(
|
const variantAnalysis = await variantAnalysisManager.getVariantAnalysis(
|
||||||
variantAnalysisId,
|
variantAnalysisId,
|
||||||
@@ -155,6 +160,10 @@ export async function exportVariantAnalysisResults(
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (token.isCancellationRequested) {
|
||||||
|
throw new UserCancellationException("Cancelled");
|
||||||
|
}
|
||||||
|
|
||||||
const repoStates = await variantAnalysisManager.getRepoStates(
|
const repoStates = await variantAnalysisManager.getRepoStates(
|
||||||
variantAnalysisId,
|
variantAnalysisId,
|
||||||
);
|
);
|
||||||
@@ -163,11 +172,21 @@ export async function exportVariantAnalysisResults(
|
|||||||
`Exporting variant analysis results for variant analysis with id ${variantAnalysis.id}`,
|
`Exporting variant analysis results for variant analysis with id ${variantAnalysis.id}`,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
progress({
|
||||||
|
maxStep: MAX_VARIANT_ANALYSIS_EXPORT_PROGRESS_STEPS,
|
||||||
|
step: 0,
|
||||||
|
message: "Determining export format",
|
||||||
|
});
|
||||||
|
|
||||||
const exportFormat = await determineExportFormat();
|
const exportFormat = await determineExportFormat();
|
||||||
if (!exportFormat) {
|
if (!exportFormat) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (token.isCancellationRequested) {
|
||||||
|
throw new UserCancellationException("Cancelled");
|
||||||
|
}
|
||||||
|
|
||||||
async function* getAnalysesResults(): AsyncGenerator<
|
async function* getAnalysesResults(): AsyncGenerator<
|
||||||
[VariantAnalysisScannedRepository, VariantAnalysisScannedRepositoryResult]
|
[VariantAnalysisScannedRepository, VariantAnalysisScannedRepositoryResult]
|
||||||
> {
|
> {
|
||||||
@@ -241,6 +260,8 @@ export async function exportVariantAnalysisResults(
|
|||||||
variantAnalysis,
|
variantAnalysis,
|
||||||
getAnalysesResults(),
|
getAnalysesResults(),
|
||||||
exportFormat,
|
exportFormat,
|
||||||
|
progress,
|
||||||
|
token,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -252,7 +273,19 @@ export async function exportVariantAnalysisAnalysisResults(
|
|||||||
[VariantAnalysisScannedRepository, VariantAnalysisScannedRepositoryResult]
|
[VariantAnalysisScannedRepository, VariantAnalysisScannedRepositoryResult]
|
||||||
>,
|
>,
|
||||||
exportFormat: "gist" | "local",
|
exportFormat: "gist" | "local",
|
||||||
|
progress: ProgressCallback,
|
||||||
|
token: CancellationToken,
|
||||||
) {
|
) {
|
||||||
|
if (token.isCancellationRequested) {
|
||||||
|
throw new UserCancellationException("Cancelled");
|
||||||
|
}
|
||||||
|
|
||||||
|
progress({
|
||||||
|
maxStep: MAX_VARIANT_ANALYSIS_EXPORT_PROGRESS_STEPS,
|
||||||
|
step: 1,
|
||||||
|
message: "Generating Markdown files",
|
||||||
|
});
|
||||||
|
|
||||||
const { markdownFiles, summaries } = await generateVariantAnalysisMarkdown(
|
const { markdownFiles, summaries } = await generateVariantAnalysisMarkdown(
|
||||||
variantAnalysis,
|
variantAnalysis,
|
||||||
analysesResults,
|
analysesResults,
|
||||||
@@ -269,6 +302,8 @@ export async function exportVariantAnalysisAnalysisResults(
|
|||||||
description,
|
description,
|
||||||
markdownFiles,
|
markdownFiles,
|
||||||
exportFormat,
|
exportFormat,
|
||||||
|
progress,
|
||||||
|
token,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -311,11 +346,22 @@ export async function exportResults(
|
|||||||
description: string,
|
description: string,
|
||||||
markdownFiles: MarkdownFile[],
|
markdownFiles: MarkdownFile[],
|
||||||
exportFormat: "gist" | "local",
|
exportFormat: "gist" | "local",
|
||||||
|
progress?: ProgressCallback,
|
||||||
|
token?: CancellationToken,
|
||||||
) {
|
) {
|
||||||
|
if (token?.isCancellationRequested) {
|
||||||
|
throw new UserCancellationException("Cancelled");
|
||||||
|
}
|
||||||
|
|
||||||
if (exportFormat === "gist") {
|
if (exportFormat === "gist") {
|
||||||
await exportToGist(ctx, description, markdownFiles);
|
await exportToGist(ctx, description, markdownFiles, progress, token);
|
||||||
} else if (exportFormat === "local") {
|
} else if (exportFormat === "local") {
|
||||||
await exportToLocalMarkdown(exportedResultsPath, markdownFiles);
|
await exportToLocalMarkdown(
|
||||||
|
exportedResultsPath,
|
||||||
|
markdownFiles,
|
||||||
|
progress,
|
||||||
|
token,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -323,9 +369,21 @@ export async function exportToGist(
|
|||||||
ctx: ExtensionContext,
|
ctx: ExtensionContext,
|
||||||
description: string,
|
description: string,
|
||||||
markdownFiles: MarkdownFile[],
|
markdownFiles: MarkdownFile[],
|
||||||
|
progress?: ProgressCallback,
|
||||||
|
token?: CancellationToken,
|
||||||
) {
|
) {
|
||||||
|
progress?.({
|
||||||
|
maxStep: MAX_VARIANT_ANALYSIS_EXPORT_PROGRESS_STEPS,
|
||||||
|
step: 2,
|
||||||
|
message: "Creating Gist",
|
||||||
|
});
|
||||||
|
|
||||||
const credentials = await Credentials.initialize(ctx);
|
const credentials = await Credentials.initialize(ctx);
|
||||||
|
|
||||||
|
if (token?.isCancellationRequested) {
|
||||||
|
throw new UserCancellationException("Cancelled");
|
||||||
|
}
|
||||||
|
|
||||||
// Convert markdownFiles to the appropriate format for uploading to gist
|
// Convert markdownFiles to the appropriate format for uploading to gist
|
||||||
const gistFiles = markdownFiles.reduce((acc, cur) => {
|
const gistFiles = markdownFiles.reduce((acc, cur) => {
|
||||||
acc[`${cur.fileName}.md`] = { content: cur.content.join("\n") };
|
acc[`${cur.fileName}.md`] = { content: cur.content.join("\n") };
|
||||||
@@ -334,13 +392,17 @@ export async function exportToGist(
|
|||||||
|
|
||||||
const gistUrl = await createGist(credentials, description, gistFiles);
|
const gistUrl = await createGist(credentials, description, gistFiles);
|
||||||
if (gistUrl) {
|
if (gistUrl) {
|
||||||
const shouldOpenGist = await showInformationMessageWithAction(
|
// This needs to use .then to ensure we aren't keeping the progress notification open. We shouldn't await the
|
||||||
|
// "Open gist" button click.
|
||||||
|
void showInformationMessageWithAction(
|
||||||
"Variant analysis results exported to gist.",
|
"Variant analysis results exported to gist.",
|
||||||
"Open gist",
|
"Open gist",
|
||||||
);
|
).then((shouldOpenGist) => {
|
||||||
if (shouldOpenGist) {
|
if (!shouldOpenGist) {
|
||||||
await commands.executeCommand("vscode.open", Uri.parse(gistUrl));
|
return;
|
||||||
}
|
}
|
||||||
|
return commands.executeCommand("vscode.open", Uri.parse(gistUrl));
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -386,20 +448,38 @@ const buildVariantAnalysisGistDescription = (
|
|||||||
async function exportToLocalMarkdown(
|
async function exportToLocalMarkdown(
|
||||||
exportedResultsPath: string,
|
exportedResultsPath: string,
|
||||||
markdownFiles: MarkdownFile[],
|
markdownFiles: MarkdownFile[],
|
||||||
|
progress?: ProgressCallback,
|
||||||
|
token?: CancellationToken,
|
||||||
) {
|
) {
|
||||||
|
if (token?.isCancellationRequested) {
|
||||||
|
throw new UserCancellationException("Cancelled");
|
||||||
|
}
|
||||||
|
|
||||||
|
progress?.({
|
||||||
|
maxStep: MAX_VARIANT_ANALYSIS_EXPORT_PROGRESS_STEPS,
|
||||||
|
step: 2,
|
||||||
|
message: "Creating local Markdown files",
|
||||||
|
});
|
||||||
|
|
||||||
await ensureDir(exportedResultsPath);
|
await ensureDir(exportedResultsPath);
|
||||||
for (const markdownFile of markdownFiles) {
|
for (const markdownFile of markdownFiles) {
|
||||||
const filePath = join(exportedResultsPath, `${markdownFile.fileName}.md`);
|
const filePath = join(exportedResultsPath, `${markdownFile.fileName}.md`);
|
||||||
await writeFile(filePath, markdownFile.content.join("\n"), "utf8");
|
await writeFile(filePath, markdownFile.content.join("\n"), "utf8");
|
||||||
}
|
}
|
||||||
const shouldOpenExportedResults = await showInformationMessageWithAction(
|
|
||||||
|
// This needs to use .then to ensure we aren't keeping the progress notification open. We shouldn't await the
|
||||||
|
// "Open exported results" button click.
|
||||||
|
void showInformationMessageWithAction(
|
||||||
`Variant analysis results exported to \"${exportedResultsPath}\".`,
|
`Variant analysis results exported to \"${exportedResultsPath}\".`,
|
||||||
"Open exported results",
|
"Open exported results",
|
||||||
);
|
).then(async (shouldOpenExportedResults) => {
|
||||||
if (shouldOpenExportedResults) {
|
if (!shouldOpenExportedResults) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const summaryFilePath = join(exportedResultsPath, "_summary.md");
|
const summaryFilePath = join(exportedResultsPath, "_summary.md");
|
||||||
const summaryFile = await workspace.openTextDocument(summaryFilePath);
|
const summaryFile = await workspace.openTextDocument(summaryFilePath);
|
||||||
await window.showTextDocument(summaryFile, ViewColumn.One);
|
await window.showTextDocument(summaryFile, ViewColumn.One);
|
||||||
await commands.executeCommand("revealFileInOS", Uri.file(summaryFilePath));
|
await commands.executeCommand("revealFileInOS", Uri.file(summaryFilePath));
|
||||||
}
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user