Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 2 additions & 30 deletions extensions/ql-vscode/src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -109,10 +109,7 @@ import {
handleInstallPackDependencies,
} from "./packaging";
import { HistoryItemLabelProvider } from "./query-history/history-item-label-provider";
import {
exportSelectedVariantAnalysisResults,
exportVariantAnalysisResults,
} from "./variant-analysis/export-results";
import { exportSelectedVariantAnalysisResults } from "./variant-analysis/export-results";
import { EvalLogViewer } from "./eval-log-viewer";
import { SummaryLanguageSupport } from "./log-insights/summary-language-support";
import { JoinOrderScannerProvider } from "./log-insights/join-order";
Expand Down Expand Up @@ -1156,35 +1153,10 @@ async function activateWithInstalledDistribution(

ctx.subscriptions.push(
commandRunner("codeQL.exportSelectedVariantAnalysisResults", async () => {
await exportSelectedVariantAnalysisResults(qhm);
await exportSelectedVariantAnalysisResults(variantAnalysisManager, qhm);
}),
);

ctx.subscriptions.push(
commandRunnerWithProgress(
"codeQL.exportVariantAnalysisResults",
async (
progress: ProgressCallback,
token: CancellationToken,
variantAnalysisId: number,
filterSort?: RepositoriesFilterSortStateWithIds,
) => {
await exportVariantAnalysisResults(
variantAnalysisManager,
variantAnalysisId,
filterSort,
app.credentials,
progress,
token,
);
},
{
title: "Exporting variant analysis results",
cancellable: true,
},
),
);

ctx.subscriptions.push(
commandRunner(
"codeQL.loadVariantAnalysisRepoResults",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1238,8 +1238,7 @@ export class QueryHistoryManager extends DisposableObject {
return;
}

await commands.executeCommand(
"codeQL.exportVariantAnalysisResults",
await this.variantAnalysisManager.exportResults(
finalSingleItem.variantAnalysis.id,
);
}
Expand Down
199 changes: 106 additions & 93 deletions extensions/ql-vscode/src/variant-analysis/export-results.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,11 @@ import {
window,
workspace,
} from "vscode";
import { ProgressCallback, UserCancellationException } from "../commandRunner";
import {
ProgressCallback,
UserCancellationException,
withProgress,
} from "../commandRunner";
import { showInformationMessageWithAction } from "../helpers";
import { extLogger } from "../common";
import { QueryHistoryManager } from "../query-history/query-history-manager";
Expand Down Expand Up @@ -37,6 +41,7 @@ import { Credentials } from "../common/authentication";
* Exports the results of the currently-selected variant analysis.
*/
export async function exportSelectedVariantAnalysisResults(
variantAnalysisManager: VariantAnalysisManager,
queryHistoryManager: QueryHistoryManager,
): Promise<void> {
const queryHistoryItem = queryHistoryManager.getCurrentQueryHistoryItem();
Expand All @@ -46,8 +51,7 @@ export async function exportSelectedVariantAnalysisResults(
);
}

return commands.executeCommand(
"codeQL.exportVariantAnalysisResults",
await variantAnalysisManager.exportResults(
queryHistoryItem.variantAnalysis.id,
);
}
Expand All @@ -63,108 +67,117 @@ export async function exportVariantAnalysisResults(
variantAnalysisId: number,
filterSort: RepositoriesFilterSortStateWithIds | undefined,
credentials: Credentials,
progress: ProgressCallback,
token: CancellationToken,
): Promise<void> {
const variantAnalysis = await variantAnalysisManager.getVariantAnalysis(
variantAnalysisId,
);
if (!variantAnalysis) {
void extLogger.log(
`Could not find variant analysis with id ${variantAnalysisId}`,
);
throw new Error(
"There was an error when trying to retrieve variant analysis information",
);
}

if (token.isCancellationRequested) {
throw new UserCancellationException("Cancelled");
}

const repoStates = await variantAnalysisManager.getRepoStates(
variantAnalysisId,
);

void extLogger.log(
`Exporting variant analysis results for variant analysis with id ${variantAnalysis.id}`,
);
await withProgress(
async (progress: ProgressCallback, token: CancellationToken) => {
const variantAnalysis = await variantAnalysisManager.getVariantAnalysis(
variantAnalysisId,
);
if (!variantAnalysis) {
void extLogger.log(
`Could not find variant analysis with id ${variantAnalysisId}`,
);
throw new Error(
"There was an error when trying to retrieve variant analysis information",
);
}

progress({
maxStep: MAX_VARIANT_ANALYSIS_EXPORT_PROGRESS_STEPS,
step: 0,
message: "Determining export format",
});
if (token.isCancellationRequested) {
throw new UserCancellationException("Cancelled");
}

const exportFormat = await determineExportFormat();
if (!exportFormat) {
return;
}
const repoStates = await variantAnalysisManager.getRepoStates(
variantAnalysisId,
);

if (token.isCancellationRequested) {
throw new UserCancellationException("Cancelled");
}
void extLogger.log(
`Exporting variant analysis results for variant analysis with id ${variantAnalysis.id}`,
);

const repositories = filterAndSortRepositoriesWithResults(
variantAnalysis.scannedRepos,
filterSort,
)?.filter(
(repo) =>
repo.resultCount &&
repoStates.find((r) => r.repositoryId === repo.repository.id)
?.downloadStatus ===
VariantAnalysisScannedRepositoryDownloadStatus.Succeeded,
);
progress({
maxStep: MAX_VARIANT_ANALYSIS_EXPORT_PROGRESS_STEPS,
step: 0,
message: "Determining export format",
});

async function* getAnalysesResults(): AsyncGenerator<
[VariantAnalysisScannedRepository, VariantAnalysisScannedRepositoryResult]
> {
if (!variantAnalysis) {
return;
}
const exportFormat = await determineExportFormat();
if (!exportFormat) {
return;
}

if (!repositories) {
return;
}
if (token.isCancellationRequested) {
throw new UserCancellationException("Cancelled");
}

for (const repo of repositories) {
const result = await variantAnalysisManager.loadResults(
variantAnalysis.id,
repo.repository.fullName,
{
skipCacheStore: true,
},
const repositories = filterAndSortRepositoriesWithResults(
variantAnalysis.scannedRepos,
filterSort,
)?.filter(
(repo) =>
repo.resultCount &&
repoStates.find((r) => r.repositoryId === repo.repository.id)
?.downloadStatus ===
VariantAnalysisScannedRepositoryDownloadStatus.Succeeded,
);

yield [repo, result];
}
}

const exportDirectory =
variantAnalysisManager.getVariantAnalysisStorageLocation(
variantAnalysis.id,
);
async function* getAnalysesResults(): AsyncGenerator<
[
VariantAnalysisScannedRepository,
VariantAnalysisScannedRepositoryResult,
]
> {
if (!variantAnalysis) {
return;
}

if (!repositories) {
return;
}

for (const repo of repositories) {
const result = await variantAnalysisManager.loadResults(
variantAnalysis.id,
repo.repository.fullName,
{
skipCacheStore: true,
},
);

yield [repo, result];
}
}

// The date will be formatted like the following: 20221115T123456Z. The time is in UTC.
const formattedDate = new Date()
.toISOString()
.replace(/[-:]/g, "")
.replace(/\.\d+Z$/, "Z");
const exportedResultsDirectory = join(
exportDirectory,
"exported-results",
`results_${formattedDate}`,
);
const exportDirectory =
variantAnalysisManager.getVariantAnalysisStorageLocation(
variantAnalysis.id,
);

// The date will be formatted like the following: 20221115T123456Z. The time is in UTC.
const formattedDate = new Date()
.toISOString()
.replace(/[-:]/g, "")
.replace(/\.\d+Z$/, "Z");
const exportedResultsDirectory = join(
exportDirectory,
"exported-results",
`results_${formattedDate}`,
);

await exportVariantAnalysisAnalysisResults(
exportedResultsDirectory,
variantAnalysis,
getAnalysesResults(),
repositories?.length ?? 0,
exportFormat,
credentials,
progress,
token,
await exportVariantAnalysisAnalysisResults(
exportedResultsDirectory,
variantAnalysis,
getAnalysesResults(),
repositories?.length ?? 0,
exportFormat,
credentials,
progress,
token,
);
},
{
title: "Exporting variant analysis results",
cancellable: true,
},
);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ import { DbManager } from "../databases/db-manager";
import { App } from "../common/app";
import { redactableError } from "../pure/errors";
import { AppCommandManager, VariantAnalysisCommands } from "../common/commands";
import { exportVariantAnalysisResults } from "./export-results";

export class VariantAnalysisManager
extends DisposableObject
Expand Down Expand Up @@ -690,6 +691,18 @@ export class VariantAnalysisManager
await env.clipboard.writeText(text.join(EOL));
}

public async exportResults(
variantAnalysisId: number,
filterSort?: RepositoriesFilterSortStateWithIds,
) {
await exportVariantAnalysisResults(
this,
variantAnalysisId,
filterSort,
this.app.credentials,
);
}

private getRepoStatesStoragePath(variantAnalysisId: number): string {
return join(
this.getVariantAnalysisStorageLocation(variantAnalysisId),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import {
VariantAnalysisScannedRepositoryState,
} from "./shared/variant-analysis";
import { AppCommandManager } from "../common/commands";
import { RepositoriesFilterSortStateWithIds } from "../pure/variant-analysis-filter-sort";

export interface VariantAnalysisViewInterface {
variantAnalysisId: number;
Expand All @@ -25,4 +26,8 @@ export interface VariantAnalysisViewManager<
variantAnalysisId: number,
): Promise<VariantAnalysisScannedRepositoryState[]>;
openQueryFile(variantAnalysisId: number): Promise<void>;
exportResults(
variantAnalysisId: number,
filterSort?: RepositoriesFilterSortStateWithIds,
): Promise<void>;
}
Original file line number Diff line number Diff line change
Expand Up @@ -139,8 +139,7 @@ export class VariantAnalysisView
);
break;
case "exportResults":
void commands.executeCommand(
"codeQL.exportVariantAnalysisResults",
await this.manager.exportResults(
this.variantAnalysisId,
msg.filterSort,
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,7 @@ export function VariantAnalysis({
repositoryIds: selectedRepositoryIds,
},
});
sendTelemetry("variant-analysis-export-results");
}, [filterSortState, selectedRepositoryIds]);

if (
Expand Down