Make config-util.getRemoteConfig use util.getFileContentsUsingAPI

This commit is contained in:
David Verdeguer
2020-08-20 17:41:15 +02:00
parent 382c51457f
commit 7a50226279
12 changed files with 90 additions and 136 deletions
+9 -20
View File
@@ -7,10 +7,10 @@ import sinon from 'sinon';
import * as api from './api-client';
import * as CodeQL from './codeql';
import * as configUtils from './config-utils';
import {setupTests} from './testing-utils';
import * as testingUtils from './testing-utils';
import * as util from './util';
setupTests(test);
testingUtils.setupTests(test);
function setInput(name: string, value: string | undefined) {
// Transformation copied from
@@ -23,19 +23,6 @@ function setInput(name: string, value: string | undefined) {
}
}
type GetContentsResponse = { content?: string; } | {}[];
function mockGetContents(content: GetContentsResponse): 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: content
};
const spyGetContents = sinon.stub(client.repos, "getContents").resolves(response as any);
sinon.stub(api, "getApiClient").value(() => client);
return spyGetContents;
}
function mockListLanguages(languages: string[]) {
// Passing an auth token is required, so we just use a dummy value
let client = new github.GitHub('123');
@@ -303,7 +290,7 @@ test("API client used when reading remote config", async t => {
const dummyResponse = {
content: Buffer.from(inputFileContents).toString("base64"),
};
const spyGetContents = mockGetContents(dummyResponse);
const spyGetContents = testingUtils.mockGetContents(dummyResponse, 200);
// Create checkout directory for remote queries repository
fs.mkdirSync(path.join(tmpDir, 'foo/bar'), { recursive: true });
@@ -322,7 +309,7 @@ test("Remote config handles the case where a directory is provided", async t =>
process.env['GITHUB_WORKSPACE'] = tmpDir;
const dummyResponse = []; // directories are returned as arrays
mockGetContents(dummyResponse);
testingUtils.mockGetContents(dummyResponse, 200);
const repoReference = 'octo-org/codeql-config/config.yaml@main';
setInput('config-file', repoReference);
@@ -330,7 +317,8 @@ test("Remote config handles the case where a directory is provided", async t =>
await configUtils.initConfig();
throw new Error('initConfig did not throw error');
} catch (err) {
t.deepEqual(err, new Error(configUtils.getConfigFileDirectoryGivenMessage(repoReference)));
const reason = util.fileIsADirectoryError(repoReference);
t.deepEqual(err, new Error(configUtils.getConfigFileFormatInvalidMessage(repoReference, reason)));
}
});
});
@@ -343,7 +331,7 @@ test("Invalid format of remote config handled correctly", async t => {
const dummyResponse = {
// note no "content" property here
};
mockGetContents(dummyResponse);
testingUtils.mockGetContents(dummyResponse, 400);
const repoReference = 'octo-org/codeql-config/config.yaml@main';
setInput('config-file', repoReference);
@@ -351,7 +339,8 @@ test("Invalid format of remote config handled correctly", async t => {
await configUtils.initConfig();
throw new Error('initConfig did not throw error');
} catch (err) {
t.deepEqual(err, new Error(configUtils.getConfigFileFormatInvalidMessage(repoReference)));
const reason = util.fileDownloadError(repoReference);
t.deepEqual(err, new Error(configUtils.getConfigFileFormatInvalidMessage(repoReference, reason)));
}
});
});
+11 -20
View File
@@ -399,12 +399,8 @@ export function getConfigFileRepoFormatInvalidMessage(configFile: string): strin
return error;
}
export function getConfigFileFormatInvalidMessage(configFile: string): string {
return 'The configuration file "' + configFile + '" could not be read';
}
export function getConfigFileDirectoryGivenMessage(configFile: string): string {
return 'The configuration file "' + configFile + '" looks like a directory, not a file';
export function getConfigFileFormatInvalidMessage(configFile: string, reason: string): string {
return 'The configuration file "' + configFile + '" could not be read. Reason: ' + reason;
}
function getConfigFilePropertyError(configFile: string, property: string, error: string): string {
@@ -689,23 +685,18 @@ async function getRemoteConfig(configFile: string): Promise<UserConfig> {
throw new Error(getConfigFileRepoFormatInvalidMessage(configFile));
}
const response = await api.getActionsApiClient(true).repos.getContents({
owner: pieces.groups.owner,
repo: pieces.groups.repo,
path: pieces.groups.path,
ref: pieces.groups.ref,
});
let fileContents: string;
if ("content" in response.data && response.data.content !== undefined) {
fileContents = response.data.content;
} else if (Array.isArray(response.data)) {
throw new Error(getConfigFileDirectoryGivenMessage(configFile));
} else {
throw new Error(getConfigFileFormatInvalidMessage(configFile));
try {
fileContents = await util.getFileContentsUsingAPI(
pieces.groups.owner,
pieces.groups.repo,
pieces.groups.path,
pieces.groups.ref);
} catch (err) {
throw new Error(getConfigFileFormatInvalidMessage(configFile, err.message));
}
return yaml.safeLoad(Buffer.from(fileContents, 'base64').toString('binary'));
return yaml.safeLoad(fileContents);
}
/**
+17
View File
@@ -1,6 +1,8 @@
import * as github from "@actions/github";
import {TestInterface} from 'ava';
import sinon from 'sinon';
import * as api from './api-client';
import * as CodeQL from './codeql';
type TestContext = {stdoutWrite: any, stderrWrite: any, testOutput: string, env: NodeJS.ProcessEnv};
@@ -77,3 +79,18 @@ export function setupTests(test: TestInterface<any>) {
process.env = t.context.env;
});
}
export type GetContentsResponse = { content?: string; } | {}[];
export function mockGetContents(content: GetContentsResponse, status: number): 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: content,
status: status
};
const spyGetContents = sinon.stub(client.repos, "getContents").resolves(response as any);
sinon.stub(api, "getApiClient").value(() => client);
return spyGetContents;
}
+7 -26
View File
@@ -1,14 +1,12 @@
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 testingUtils from './testing-utils';
import * as util from './util';
setupTests(test);
testingUtils.setupTests(test);
test('getToolNames', t => {
const input = fs.readFileSync(__dirname + '/../src/testdata/tool-names.sarif', 'utf8');
@@ -153,23 +151,9 @@ 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);
const spyGetContents = testingUtils.mockGetContents({}, 400);
try {
await util.getFileContentsUsingAPI('github', 'codeql-action', 'non-existing-file', 'main');
throw new Error('initConfig did not throw error');
@@ -180,11 +164,8 @@ test('getFileContentsUsingAPI() throws if the request does not succeed', async t
});
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);
const dummyResponse = []; // directories are returned as arrays
const spyGetContents = testingUtils.mockGetContents(dummyResponse, 200);
try {
await util.getFileContentsUsingAPI('github', 'codeql-action', 'non-existing-file', 'main');
throw new Error('initConfig did not throw error');
@@ -199,7 +180,7 @@ test('getFileContentsUsingAPI() returns the right content', async t => {
const dummyResponse = {
content: Buffer.from(inputFileContents).toString("base64"),
};
const spyGetContents = mockGetContents(dummyResponse, 200);
const spyGetContents = testingUtils.mockGetContents(dummyResponse, 200);
const content = await util.getFileContentsUsingAPI('github', 'codeql-action', 'non-existing-file', 'main');
t.deepEqual(content, inputFileContents);