Skip to content

Commit dc6ae6c

Browse files
Merge pull request #1576 from github/elenatanasoiu/unzip
Make download method handle zip files
2 parents 81b53c9 + 3902596 commit dc6ae6c

File tree

5 files changed

+69
-29
lines changed

5 files changed

+69
-29
lines changed

extensions/ql-vscode/src/remote-queries/gh-api/gh-api-client.ts

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -77,12 +77,9 @@ export async function getVariantAnalysisRepo(
7777
export async function getVariantAnalysisRepoResult(
7878
credentials: Credentials,
7979
downloadUrl: string,
80-
): Promise<unknown> {
80+
): Promise<ArrayBuffer> {
8181
const octokit = await credentials.getOctokit();
82-
83-
const response: OctokitResponse<VariantAnalysisRepoTask> = await octokit.request(
84-
`GET ${downloadUrl}`
85-
);
82+
const response = await octokit.request(`GET ${downloadUrl}`);
8683

8784
return response.data;
8885
}

extensions/ql-vscode/src/remote-queries/variant-analysis-results-manager.ts

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import { DisposableObject, DisposeHandler } from '../pure/disposable-object';
1414
import { VariantAnalysisRepoTask } from './gh-api/variant-analysis';
1515
import * as ghApiClient from './gh-api/gh-api-client';
1616
import { EventEmitter } from 'vscode';
17+
import { unzipFile } from '../pure/zip';
1718

1819
type CacheKey = `${number}/${string}`;
1920

@@ -58,8 +59,15 @@ export class VariantAnalysisResultsManager extends DisposableObject {
5859
repoTask.artifact_url
5960
);
6061

61-
fs.mkdirSync(resultDirectory, { recursive: true });
62-
await fs.writeFile(path.join(resultDirectory, 'results.zip'), JSON.stringify(result, null, 2), 'utf8');
62+
if (!(await fs.pathExists(resultDirectory))) {
63+
await fs.mkdir(resultDirectory, { recursive: true });
64+
}
65+
66+
const zipFilePath = path.join(resultDirectory, 'results.zip');
67+
const unzippedFilesDirectory = path.join(resultDirectory, 'results');
68+
69+
fs.writeFileSync(zipFilePath, Buffer.from(result));
70+
await unzipFile(zipFilePath, unzippedFilesDirectory);
6371

6472
this._onResultDownloaded.fire({
6573
variantAnalysisId,
@@ -156,7 +164,7 @@ export class VariantAnalysisResultsManager extends DisposableObject {
156164
);
157165
}
158166

159-
private getRepoStorageDirectory(variantAnalysisId: number, fullName: string): string {
167+
public getRepoStorageDirectory(variantAnalysisId: number, fullName: string): string {
160168
return path.join(
161169
this.getStorageDirectory(variantAnalysisId),
162170
fullName
Binary file not shown.

extensions/ql-vscode/src/vscode-tests/cli-integration/remote-queries/variant-analysis-manager.test.ts

Lines changed: 13 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,12 @@ import * as config from '../../../config';
77
import * as ghApiClient from '../../../remote-queries/gh-api/gh-api-client';
88
import { Credentials } from '../../../authentication';
99
import * as fs from 'fs-extra';
10+
import * as path from 'path';
1011

1112
import { VariantAnalysisManager } from '../../../remote-queries/variant-analysis-manager';
1213
import {
1314
VariantAnalysis as VariantAnalysisApiResponse,
15+
VariantAnalysisRepoTask,
1416
VariantAnalysisScannedRepository as ApiVariantAnalysisScannedRepository
1517
} from '../../../remote-queries/gh-api/variant-analysis';
1618
import { createMockApiResponse } from '../../factories/remote-queries/gh-api/variant-analysis-api-response';
@@ -72,6 +74,7 @@ describe('Variant Analysis Manager', async function() {
7274

7375
describe('when credentials are valid', async () => {
7476
let getOctokitStub: sinon.SinonStub;
77+
let arrayBuffer: ArrayBuffer;
7578

7679
beforeEach(async () => {
7780
const mockCredentials = {
@@ -80,16 +83,18 @@ describe('Variant Analysis Manager', async function() {
8083
})
8184
} as unknown as Credentials;
8285
sandbox.stub(Credentials, 'initialize').resolves(mockCredentials);
86+
87+
const sourceFilePath = path.join(__dirname, '../../../../src/vscode-tests/cli-integration/data/variant-analysis-results.zip');
88+
arrayBuffer = fs.readFileSync(sourceFilePath).buffer;
8389
});
8490

8591
describe('when the artifact_url is missing', async () => {
8692
beforeEach(async () => {
8793
const dummyRepoTask = createMockVariantAnalysisRepoTask();
8894
delete dummyRepoTask.artifact_url;
89-
getVariantAnalysisRepoStub = sandbox.stub(ghApiClient, 'getVariantAnalysisRepo').resolves(dummyRepoTask);
9095

91-
const dummyResult = 'this-is-a-repo-result';
92-
getVariantAnalysisRepoResultStub = sandbox.stub(ghApiClient, 'getVariantAnalysisRepoResult').resolves(dummyResult);
96+
getVariantAnalysisRepoStub = sandbox.stub(ghApiClient, 'getVariantAnalysisRepo').resolves(dummyRepoTask);
97+
getVariantAnalysisRepoResultStub = sandbox.stub(ghApiClient, 'getVariantAnalysisRepoResult').resolves(arrayBuffer);
9398
});
9499

95100
it('should not try to download the result', async () => {
@@ -104,12 +109,13 @@ describe('Variant Analysis Manager', async function() {
104109
});
105110

106111
describe('when the artifact_url is present', async () => {
112+
let dummyRepoTask: VariantAnalysisRepoTask;
113+
107114
beforeEach(async () => {
108-
const dummyRepoTask = createMockVariantAnalysisRepoTask();
109-
getVariantAnalysisRepoStub = sandbox.stub(ghApiClient, 'getVariantAnalysisRepo').resolves(dummyRepoTask);
115+
dummyRepoTask = createMockVariantAnalysisRepoTask();
110116

111-
const dummyResult = 'this-is-a-repo-result';
112-
getVariantAnalysisRepoResultStub = sandbox.stub(ghApiClient, 'getVariantAnalysisRepoResult').resolves(dummyResult);
117+
getVariantAnalysisRepoStub = sandbox.stub(ghApiClient, 'getVariantAnalysisRepo').resolves(dummyRepoTask);
118+
getVariantAnalysisRepoResultStub = sandbox.stub(ghApiClient, 'getVariantAnalysisRepoResult').resolves(arrayBuffer);
113119
});
114120

115121
it('should return early if variant analysis is cancelled', async () => {
@@ -143,16 +149,6 @@ describe('Variant Analysis Manager', async function() {
143149

144150
expect(getVariantAnalysisRepoResultStub.calledOnce).to.be.true;
145151
});
146-
147-
it('should save the result to disk', async () => {
148-
await variantAnalysisManager.autoDownloadVariantAnalysisResult(
149-
scannedRepos[0],
150-
variantAnalysis,
151-
cancellationTokenSource.token
152-
);
153-
154-
expect(getVariantAnalysisRepoResultStub.calledOnce).to.be.true;
155-
});
156152
});
157153
});
158154
});

extensions/ql-vscode/src/vscode-tests/cli-integration/remote-queries/variant-analysis-results-manager.test.ts

Lines changed: 43 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,15 @@ import { CodeQLExtensionInterface } from '../../../extension';
55
import { logger } from '../../../logging';
66
import { Credentials } from '../../../authentication';
77
import * as fs from 'fs-extra';
8+
import * as path from 'path';
89

910
import { VariantAnalysisResultsManager } from '../../../remote-queries/variant-analysis-results-manager';
1011
import { createMockVariantAnalysisRepoTask } from '../../factories/remote-queries/gh-api/variant-analysis-repo-task';
1112
import { CodeQLCliServer } from '../../../cli';
1213
import { storagePath } from '../global.helper';
1314
import { faker } from '@faker-js/faker';
1415
import * as ghApiClient from '../../../remote-queries/gh-api/gh-api-client';
16+
import { VariantAnalysisRepoTask } from '../../../remote-queries/gh-api/variant-analysis';
1517

1618
describe(VariantAnalysisResultsManager.name, () => {
1719
let sandbox: sinon.SinonSandbox;
@@ -69,12 +71,29 @@ describe(VariantAnalysisResultsManager.name, () => {
6971
});
7072

7173
describe('when the artifact_url is present', async () => {
72-
it('should save the result to disk', async () => {
73-
const dummyRepoTask = createMockVariantAnalysisRepoTask();
74+
let dummyRepoTask: VariantAnalysisRepoTask;
75+
let storageDirectory: string;
76+
let arrayBuffer: ArrayBuffer;
77+
78+
beforeEach(async () => {
79+
dummyRepoTask = createMockVariantAnalysisRepoTask();
80+
81+
storageDirectory = variantAnalysisResultsManager.getRepoStorageDirectory(variantAnalysisId, dummyRepoTask.repository.full_name);
82+
const sourceFilePath = path.join(__dirname, '../../../../src/vscode-tests/cli-integration/data/variant-analysis-results.zip');
83+
arrayBuffer = fs.readFileSync(sourceFilePath).buffer;
7484

75-
const dummyResult = 'this-is-a-repo-result';
76-
getVariantAnalysisRepoResultStub = sandbox.stub(ghApiClient, 'getVariantAnalysisRepoResult').withArgs(mockCredentials, dummyRepoTask.artifact_url as string).resolves(dummyResult);
85+
getVariantAnalysisRepoResultStub = sandbox
86+
.stub(ghApiClient, 'getVariantAnalysisRepoResult')
87+
.withArgs(mockCredentials, dummyRepoTask.artifact_url as string)
88+
.resolves(arrayBuffer);
89+
});
90+
91+
afterEach(async () => {
92+
fs.removeSync(`${storageDirectory}/results.zip`);
93+
fs.removeSync(`${storageDirectory}/results`);
94+
});
7795

96+
it('should call the API to download the results', async () => {
7897
await variantAnalysisResultsManager.download(
7998
mockCredentials,
8099
variantAnalysisId,
@@ -83,6 +102,26 @@ describe(VariantAnalysisResultsManager.name, () => {
83102

84103
expect(getVariantAnalysisRepoResultStub.calledOnce).to.be.true;
85104
});
105+
106+
it('should save the results zip file to disk', async () => {
107+
await variantAnalysisResultsManager.download(
108+
mockCredentials,
109+
variantAnalysisId,
110+
dummyRepoTask
111+
);
112+
113+
expect(fs.existsSync(`${storageDirectory}/results.zip`)).to.be.true;
114+
});
115+
116+
it('should unzip the results in a `results/` folder', async () => {
117+
await variantAnalysisResultsManager.download(
118+
mockCredentials,
119+
variantAnalysisId,
120+
dummyRepoTask
121+
);
122+
123+
expect(fs.existsSync(`${storageDirectory}/results/results.sarif`)).to.be.true;
124+
});
86125
});
87126
});
88127
});

0 commit comments

Comments
 (0)