Avoid artifactStorageDir and use queryId to build storage paths

This is still an intermediate step as we start to bring in more
abstractions. I plan to implement a storage handler that will
keep track of all the different bits for a remote query.
This commit is contained in:
Andrew Eisenberg
2022-02-16 11:46:10 -08:00
parent bf8e77b9b9
commit 5bb2a763e3
7 changed files with 29 additions and 27 deletions

View File

@@ -95,7 +95,7 @@ export class AnalysesResultsManager {
let artifactPath; let artifactPath;
try { try {
artifactPath = await downloadArtifactFromLink(credentials, analysis.downloadLink); artifactPath = await downloadArtifactFromLink(credentials, this.storagePath, analysis.downloadLink);
} }
catch (e) { catch (e) {
throw new Error(`Could not download the analysis results for ${analysis.nwo}: ${e.message}`); throw new Error(`Could not download the analysis results for ${analysis.nwo}: ${e.message}`);

View File

@@ -19,7 +19,7 @@ export interface DownloadLink {
innerFilePath?: string; innerFilePath?: string;
/** /**
* The full path to the directory where the artifacts for this link is stored. * A unique id of the remote query run. This is used to determine where to store artifacts and data from the run.
*/ */
artifactStorageDir: string; queryId: string;
} }

View File

@@ -54,6 +54,7 @@ export async function getRemoteQueryIndex(
export async function downloadArtifactFromLink( export async function downloadArtifactFromLink(
credentials: Credentials, credentials: Credentials,
storagePath: string,
downloadLink: DownloadLink downloadLink: DownloadLink
): Promise<string> { ): Promise<string> {
@@ -62,11 +63,11 @@ export async function downloadArtifactFromLink(
// Download the zipped artifact. // Download the zipped artifact.
const response = await octokit.request(`GET ${downloadLink.urlPath}/zip`, {}); const response = await octokit.request(`GET ${downloadLink.urlPath}/zip`, {});
const zipFilePath = path.join(downloadLink.artifactStorageDir, `${downloadLink.id}.zip`); const zipFilePath = path.join(storagePath, downloadLink.queryId, `${downloadLink.id}.zip`);
await saveFile(`${zipFilePath}`, response.data as ArrayBuffer); await saveFile(`${zipFilePath}`, response.data as ArrayBuffer);
// Extract the zipped artifact. // Extract the zipped artifact.
const extractedPath = path.join(downloadLink.artifactStorageDir, downloadLink.id); const extractedPath = path.join(storagePath, downloadLink.queryId, downloadLink.id);
await unzipFile(zipFilePath, extractedPath); await unzipFile(zipFilePath, extractedPath);
return path.join(extractedPath, downloadLink.innerFilePath || ''); return path.join(extractedPath, downloadLink.innerFilePath || '');

View File

@@ -224,7 +224,7 @@ export class RemoteQueriesInterfaceManager {
private async viewAnalysisResults(msg: RemoteQueryViewAnalysisResultsMessage): Promise<void> { private async viewAnalysisResults(msg: RemoteQueryViewAnalysisResultsMessage): Promise<void> {
const downloadLink = msg.analysisSummary.downloadLink; const downloadLink = msg.analysisSummary.downloadLink;
const filePath = path.join(downloadLink.artifactStorageDir, downloadLink.id, downloadLink.innerFilePath || ''); const filePath = path.join(this.analysesResultsManager.storagePath, downloadLink.queryId, downloadLink.id, downloadLink.innerFilePath || '');
const sarifViewerExtensionId = 'MS-SarifVSCode.sarif-viewer'; const sarifViewerExtensionId = 'MS-SarifVSCode.sarif-viewer';

View File

@@ -74,11 +74,12 @@ export class RemoteQueriesManager {
return; return;
} }
const artifactStorageDir = await this.prepareStorageDirectory(query.queryName); const queryId = this.createQueryId(query.queryName);
const queryResult = this.mapQueryResult(executionEndTime, resultIndex, artifactStorageDir); await this.prepareStorageDirectory(queryId);
const queryResult = this.mapQueryResult(executionEndTime, resultIndex, queryId);
// Write the query result to the storage directory. // Write the query result to the storage directory.
const queryResultFilePath = path.join(artifactStorageDir, 'query-result.json'); const queryResultFilePath = path.join(this.storagePath, queryId, 'query-result.json');
await fs.writeFile(queryResultFilePath, JSON.stringify(queryResult, null, 2), 'utf8'); await fs.writeFile(queryResultFilePath, JSON.stringify(queryResult, null, 2), 'utf8');
// Kick off auto-download of results. // Kick off auto-download of results.
@@ -126,7 +127,7 @@ export class RemoteQueriesManager {
results => this.interfaceManager.setAnalysisResults(results)); results => this.interfaceManager.setAnalysisResults(results));
} }
private mapQueryResult(executionEndTime: Date, resultIndex: RemoteQueryResultIndex, artifactStorageDir: string): RemoteQueryResult { private mapQueryResult(executionEndTime: Date, resultIndex: RemoteQueryResultIndex, queryId: string): RemoteQueryResult {
const analysisSummaries = resultIndex.items.map(item => ({ const analysisSummaries = resultIndex.items.map(item => ({
nwo: item.nwo, nwo: item.nwo,
resultCount: item.resultCount, resultCount: item.resultCount,
@@ -135,17 +136,26 @@ export class RemoteQueriesManager {
id: item.artifactId.toString(), id: item.artifactId.toString(),
urlPath: `${resultIndex.artifactsUrlPath}/${item.artifactId}`, urlPath: `${resultIndex.artifactsUrlPath}/${item.artifactId}`,
innerFilePath: item.sarifFileSize ? 'results.sarif' : 'results.bqrs', innerFilePath: item.sarifFileSize ? 'results.sarif' : 'results.bqrs',
artifactStorageDir queryId,
} as DownloadLink } as DownloadLink
})); }));
return { return {
executionEndTime, executionEndTime,
analysisSummaries, analysisSummaries,
artifactStorageDir
}; };
} }
/**
* Generates a unique id for this query, suitable for determining the storage location for the downloaded query artifacts.
* @param queryName
* @returns
*/
private createQueryId(queryName: string): string {
return `${queryName}-${nanoid()}`;
}
/** /**
* Prepares a directory for storing analysis results for a single query run. * Prepares a directory for storing analysis results for a single query run.
* This directory contains a timestamp file, which will be * This directory contains a timestamp file, which will be
@@ -153,13 +163,8 @@ export class RemoteQueriesManager {
* should be deleted. * should be deleted.
* *
* @param queryName The name of the query that was run. * @param queryName The name of the query that was run.
*
* @returns A promise resolving to the directory where all artifacts for this remote query are stored.
*/ */
private async prepareStorageDirectory(queryName: string): Promise<string> { private async prepareStorageDirectory(queryId: string): Promise<void> {
const artifactStorageDir = path.join(this.storagePath, `${queryName}-${nanoid()}`); await createTimestampFile(path.join(this.storagePath, queryId));
await createTimestampFile(artifactStorageDir);
return artifactStorageDir;
} }
} }

View File

@@ -3,7 +3,6 @@ import { DownloadLink } from './download-link';
export interface RemoteQueryResult { export interface RemoteQueryResult {
executionEndTime: Date; executionEndTime: Date;
analysisSummaries: AnalysisSummary[]; analysisSummaries: AnalysisSummary[];
artifactStorageDir: string;
} }
export interface AnalysisSummary { export interface AnalysisSummary {

View File

@@ -1,5 +1,3 @@
import * as path from 'path';
import { tmpDir } from '../helpers';
import { RemoteQuery } from './remote-query'; import { RemoteQuery } from './remote-query';
import { RemoteQueryResult } from './remote-query-result'; import { RemoteQueryResult } from './remote-query-result';
import { AnalysisResults } from './shared/analysis-result'; import { AnalysisResults } from './shared/analysis-result';
@@ -40,7 +38,6 @@ export const sampleRemoteQuery: RemoteQuery = {
export const sampleRemoteQueryResult: RemoteQueryResult = { export const sampleRemoteQueryResult: RemoteQueryResult = {
executionEndTime: new Date('2022-01-06T17:04:37.026Z'), executionEndTime: new Date('2022-01-06T17:04:37.026Z'),
artifactStorageDir: path.join(tmpDir.name, 'query.ql-123-xyz'),
analysisSummaries: [ analysisSummaries: [
{ {
nwo: 'big-corp/repo1', nwo: 'big-corp/repo1',
@@ -50,7 +47,7 @@ export const sampleRemoteQueryResult: RemoteQueryResult = {
id: '137697017', id: '137697017',
urlPath: '/repos/big-corp/controller-repo/actions/artifacts/137697017', urlPath: '/repos/big-corp/controller-repo/actions/artifacts/137697017',
innerFilePath: 'results.sarif', innerFilePath: 'results.sarif',
artifactStorageDir: path.join(tmpDir.name, 'query.ql-123-xyz') queryId: 'query.ql-123-xyz'
} }
}, },
{ {
@@ -61,7 +58,7 @@ export const sampleRemoteQueryResult: RemoteQueryResult = {
id: '137697018', id: '137697018',
urlPath: '/repos/big-corp/controller-repo/actions/artifacts/137697018', urlPath: '/repos/big-corp/controller-repo/actions/artifacts/137697018',
innerFilePath: 'results.sarif', innerFilePath: 'results.sarif',
artifactStorageDir: path.join(tmpDir.name, 'query.ql-123-xyz') queryId: 'query.ql-123-xyz'
} }
}, },
{ {
@@ -72,7 +69,7 @@ export const sampleRemoteQueryResult: RemoteQueryResult = {
id: '137697019', id: '137697019',
urlPath: '/repos/big-corp/controller-repo/actions/artifacts/137697019', urlPath: '/repos/big-corp/controller-repo/actions/artifacts/137697019',
innerFilePath: 'results.sarif', innerFilePath: 'results.sarif',
artifactStorageDir: path.join(tmpDir.name, 'query.ql-123-xyz') queryId: 'query.ql-123-xyz'
} }
}, },
{ {
@@ -83,7 +80,7 @@ export const sampleRemoteQueryResult: RemoteQueryResult = {
id: '137697020', id: '137697020',
urlPath: '/repos/big-corp/controller-repo/actions/artifacts/137697020', urlPath: '/repos/big-corp/controller-repo/actions/artifacts/137697020',
innerFilePath: 'results.sarif', innerFilePath: 'results.sarif',
artifactStorageDir: path.join(tmpDir.name, 'query.ql-123-xyz') queryId: 'query.ql-123-xyz'
} }
} }
] ]