Add util.getFileContentsUsingAPI

This commit is contained in:
David Verdeguer
2020-08-20 17:24:39 +02:00
parent e9e2284547
commit 382c51457f
6 changed files with 178 additions and 5 deletions
+55
View File
@@ -1,7 +1,10 @@
import * as github from "@actions/github";
import test from 'ava';
import * as fs from 'fs';
import * as os from "os";
import sinon from 'sinon';
import * as api from './api-client';
import {setupTests} from './testing-utils';
import * as util from './util';
@@ -150,3 +153,55 @@ test('getExtraOptionsEnvParam() fails on invalid JSON', t => {
process.env.CODEQL_ACTION_EXTRA_OPTIONS = origExtraOptions;
});
type GetContentsResponse = { content?: string; } | {}[];
function mockGetContents(content: GetContentsResponse, status: number, isDirectory = false): sinon.SinonStub<any, any> {
// Passing an auth token is required, so we just use a dummy value
let client = new github.GitHub('123');
const response = {
data: isDirectory ? [content] : content,
status: status
};
const spyGetContents = sinon.stub(client.repos, "getContents").resolves(response as any);
sinon.stub(api, "getApiClient").value(() => client);
return spyGetContents;
}
test('getFileContentsUsingAPI() throws if the request does not succeed', async t => {
const spyGetContents = mockGetContents({}, 400);
try {
await util.getFileContentsUsingAPI('github', 'codeql-action', 'non-existing-file', 'main');
throw new Error('initConfig did not throw error');
} catch (err) {
t.assert(spyGetContents.called);
t.deepEqual(err, new Error(util.fileDownloadError('github/codeql-action/non-existing-file@main')));
}
});
test('getFileContentsUsingAPI() throws if the requested file is a directory', async t => {
const inputFileContents = `content content content`;
const dummyResponse = {
content: Buffer.from(inputFileContents).toString("base64"),
};
const spyGetContents = mockGetContents(dummyResponse, 200, true);
try {
await util.getFileContentsUsingAPI('github', 'codeql-action', 'non-existing-file', 'main');
throw new Error('initConfig did not throw error');
} catch (err) {
t.assert(spyGetContents.called);
t.deepEqual(err, new Error(util.fileIsADirectoryError('github/codeql-action/non-existing-file@main')));
}
});
test('getFileContentsUsingAPI() returns the right content', async t => {
const inputFileContents = `content content content`;
const dummyResponse = {
content: Buffer.from(inputFileContents).toString("base64"),
};
const spyGetContents = mockGetContents(dummyResponse, 200);
const content = await util.getFileContentsUsingAPI('github', 'codeql-action', 'non-existing-file', 'main');
t.deepEqual(content, inputFileContents);
t.assert(spyGetContents.called);
});
+36
View File
@@ -433,3 +433,39 @@ export function getThreadsFlag(): string {
export function getCodeQLDatabasesDir() {
return path.resolve(getRequiredEnvParam('RUNNER_TEMP'), 'codeql_databases');
}
export function fileDownloadError(file: string): string {
return 'Error while trying to download `' + file + '`';
}
export function fileIsADirectoryError(file: string): string {
return '`' + file + '` is a directory';
}
export async function getFileContentsUsingAPI(owner: string, repo: string, path: string, ref: string): Promise<string> {
const response = await api.getActionsApiClient(true).repos.getContents({
owner: owner,
repo: repo,
path: path,
ref: ref,
});
const file = [owner, repo, path].join('/') + '@' + ref;
if (response.status !== 200) {
throw new Error(fileDownloadError(file));
}
if (Array.isArray(response.data)) {
throw new Error(fileIsADirectoryError(file));
}
let fileContents: string;
if ("content" in response.data && response.data.content !== undefined) {
fileContents = response.data.content;
} else {
throw new Error(fileDownloadError(file));
}
return Buffer.from(fileContents, 'base64').toString('binary');
}