Make remote config retrieval more robust

This commit is contained in:
Sam Partington 2020-06-26 15:56:33 +01:00
parent 51becd2cf8
commit 0607771cc2
6 changed files with 149 additions and 9 deletions

View file

@ -182,6 +182,68 @@ test("API client used when reading remote config", async t => {
});
});
test("Remote config handles the case where a directory is provided", async t => {
return await util.withTmpDir(async tmpDir => {
process.env['RUNNER_TEMP'] = tmpDir;
process.env['GITHUB_WORKSPACE'] = tmpDir;
const dummyResponse = {
data: [], // directories are returned as arrays
};
let ok = new octokit.Octokit({
userAgent: "CodeQL Action",
});
const repos = ok.repos;
sinon.stub(repos, "getContents").resolves(Promise.resolve(dummyResponse));
ok.repos = repos;
sinon.stub(api, "client").value(ok);
const repoReference = 'octo-org/codeql-config/config.yaml@main';
setInput('config-file', repoReference);
try {
await configUtils.loadConfig();
throw new Error('loadConfig did not throw error');
} catch (err) {
t.deepEqual(err, new Error(configUtils.getConfigFileDirectoryGivenMessage(repoReference)));
}
sinon.restore();
});
});
test("Invalid format of remote config handled correctly", async t => {
return await util.withTmpDir(async tmpDir => {
process.env['RUNNER_TEMP'] = tmpDir;
process.env['GITHUB_WORKSPACE'] = tmpDir;
const dummyResponse = {
data: {
// note no "content" property here
}
};
let ok = new octokit.Octokit({
userAgent: "CodeQL Action",
});
const repos = ok.repos;
sinon.stub(repos, "getContents").resolves(Promise.resolve(dummyResponse));
ok.repos = repos;
sinon.stub(api, "client").value(ok);
const repoReference = 'octo-org/codeql-config/config.yaml@main';
setInput('config-file', repoReference);
try {
await configUtils.loadConfig();
throw new Error('loadConfig did not throw error');
} catch (err) {
t.deepEqual(err, new Error(configUtils.getConfigFileFormatInvalidMessage(repoReference)));
}
sinon.restore();
});
});
function doInvalidInputTest(
testName: string,
inputFileContents: string,

View file

@ -171,6 +171,14 @@ 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';
}
function getConfigFilePropertyError(configFile: string, property: string, error: string): string {
return 'The configuration file "' + configFile + '" is invalid: property "' + property + '" ' + error;
}
@ -293,11 +301,14 @@ async function getRemoteConfig(configFile: string): Promise<any> {
ref: pieces.groups.ref,
});
// todo handle response.encoding not being base64
let fileContents;
if ("content" in response.data) {
let fileContents: string;
if ("content" in response.data && response.data.content !== undefined) {
fileContents = response.data.content;
} // todo handle else case
} else if (Array.isArray(response.data)) {
throw new Error(getConfigFileDirectoryGivenMessage(configFile));
} else {
throw new Error(getConfigFileFormatInvalidMessage(configFile));
}
return yaml.safeLoad(Buffer.from(fileContents, 'base64').toString('binary'));
}