Avoid downloading a result if it already exists

This commit adds a check if a results artifact already exists before
trying to download it again.

This is not a complete solution since the page icon will still have a
download button even if the artifact already exists. In this case,
clicking on it will avoid downloading it a second time.

The next step is to read in the downloaded artifacts and display them
appropriately.
This commit is contained in:
Andrew Eisenberg
2022-02-22 20:07:37 -08:00
parent c943c89fc6
commit 548a216b56
3 changed files with 36 additions and 31 deletions

View File

@@ -1,12 +1,13 @@
import * as os from 'os';
import * as path from 'path';
import { CancellationToken, ExtensionContext } from 'vscode';
import { Credentials } from '../authentication';
import { Logger } from '../logging';
import { downloadArtifactFromLink } from './gh-actions-api-client';
import * as path from 'path';
import { AnalysisSummary } from './shared/remote-query-result';
import { AnalysisResults, QueryResult } from './shared/analysis-result';
import { UserCancellationException } from '../commandRunner';
import * as os from 'os';
import { sarifParser } from '../sarif-parser';
export class AnalysesResultsManager {
@@ -26,8 +27,8 @@ export class AnalysesResultsManager {
analysisSummary: AnalysisSummary,
publishResults: (analysesResults: AnalysisResults[]) => Promise<void>
): Promise<void> {
if (this.isAnalysisDownloaded(analysisSummary)) {
// We already have the results for this analysis, don't download again.
if (this.isAnalysisInMemory(analysisSummary)) {
// We already have the results for this analysis in memory, don't download again.
return;
}
@@ -43,8 +44,8 @@ export class AnalysesResultsManager {
token: CancellationToken | undefined,
publishResults: (analysesResults: AnalysisResults[]) => Promise<void>
): Promise<void> {
// Filter out analyses that we have already downloaded.
const analysesToDownload = allAnalysesToDownload.filter(x => !this.isAnalysisDownloaded(x));
// Filter out analyses that we have already in memory.
const analysesToDownload = allAnalysesToDownload.filter(x => !this.isAnalysisInMemory(x));
const credentials = await Credentials.initialize(this.ctx);
@@ -149,7 +150,7 @@ export class AnalysesResultsManager {
return queryResults;
}
private isAnalysisDownloaded(analysis: AnalysisSummary): boolean {
private isAnalysisInMemory(analysis: AnalysisSummary): boolean {
return this.internalGetAnalysesResults(analysis.downloadLink.queryId).some(x => x.nwo === analysis.nwo);
}
}

View File

@@ -80,16 +80,19 @@ export async function downloadArtifactFromLink(
const octokit = await credentials.getOctokit();
// Download the zipped artifact.
const response = await octokit.request(`GET ${downloadLink.urlPath}/zip`, {});
const zipFilePath = path.join(storagePath, downloadLink.queryId, `${downloadLink.id}.zip`);
await saveFile(`${zipFilePath}`, response.data as ArrayBuffer);
// Extract the zipped artifact.
const extractedPath = path.join(storagePath, downloadLink.queryId, downloadLink.id);
await unzipFile(zipFilePath, extractedPath);
// first check if we already have the artifact
if (!(await fs.pathExists(extractedPath))) {
// Download the zipped artifact.
const response = await octokit.request(`GET ${downloadLink.urlPath}/zip`, {});
const zipFilePath = path.join(storagePath, downloadLink.queryId, `${downloadLink.id}.zip`);
await saveFile(`${zipFilePath}`, response.data as ArrayBuffer);
// Extract the zipped artifact.
await unzipFile(zipFilePath, extractedPath);
}
return path.join(extractedPath, downloadLink.innerFilePath || '');
}

View File

@@ -133,26 +133,27 @@ export class RemoteQueriesManager extends DisposableObject {
if (queryWorkflowResult.status === 'CompletedSuccessfully') {
const resultIndex = await getRemoteQueryIndex(credentials, queryItem.remoteQuery);
if (!resultIndex) {
void showAndLogErrorMessage(`There was an issue retrieving the result for the query ${queryItem.label}`);
return;
}
queryItem.completed = true;
queryItem.status = QueryStatus.Completed;
const queryResult = this.mapQueryResult(executionEndTime, resultIndex, queryItem.queryId);
if (resultIndex) {
queryItem.status = QueryStatus.Completed;
const queryResult = this.mapQueryResult(executionEndTime, resultIndex, queryItem.queryId);
await this.storeJsonFile(queryItem, 'query-result.json', queryResult);
await this.storeJsonFile(queryItem, 'query-result.json', queryResult);
// Kick off auto-download of results in the background.
void commands.executeCommand('codeQL.autoDownloadRemoteQueryResults', queryResult);
// Kick off auto-download of results in the background.
void commands.executeCommand('codeQL.autoDownloadRemoteQueryResults', queryResult);
// Ask if the user wants to open the results in the background.
void this.askToOpenResults(queryItem.remoteQuery, queryResult).then(
noop,
err => {
void showAndLogErrorMessage(err);
}
);
// Ask if the user wants to open the results in the background.
void this.askToOpenResults(queryItem.remoteQuery, queryResult).then(
noop,
err => {
void showAndLogErrorMessage(err);
}
);
} else {
void showAndLogErrorMessage(`There was an issue retrieving the result for the query ${queryItem.label}`);
queryItem.status = QueryStatus.Failed;
}
} else if (queryWorkflowResult.status === 'CompletedUnsuccessfully') {
queryItem.failureReason = queryWorkflowResult.error;
queryItem.status = QueryStatus.Failed;