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:
@@ -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}`);
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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 || '');
|
||||||
|
|||||||
@@ -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';
|
||||||
|
|
||||||
|
|||||||
@@ -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;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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 {
|
||||||
|
|||||||
@@ -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'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|||||||
Reference in New Issue
Block a user