Make remote config retrieval more robust
This commit is contained in:
parent
51becd2cf8
commit
0607771cc2
6 changed files with 149 additions and 9 deletions
19
lib/config-utils.js
generated
19
lib/config-utils.js
generated
|
|
@ -153,6 +153,14 @@ function getConfigFileRepoFormatInvalidMessage(configFile) {
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
exports.getConfigFileRepoFormatInvalidMessage = getConfigFileRepoFormatInvalidMessage;
|
exports.getConfigFileRepoFormatInvalidMessage = getConfigFileRepoFormatInvalidMessage;
|
||||||
|
function getConfigFileFormatInvalidMessage(configFile) {
|
||||||
|
return 'The configuration file "' + configFile + '" could not be read';
|
||||||
|
}
|
||||||
|
exports.getConfigFileFormatInvalidMessage = getConfigFileFormatInvalidMessage;
|
||||||
|
function getConfigFileDirectoryGivenMessage(configFile) {
|
||||||
|
return 'The configuration file "' + configFile + '" looks like a directory, not a file';
|
||||||
|
}
|
||||||
|
exports.getConfigFileDirectoryGivenMessage = getConfigFileDirectoryGivenMessage;
|
||||||
function getConfigFilePropertyError(configFile, property, error) {
|
function getConfigFilePropertyError(configFile, property, error) {
|
||||||
return 'The configuration file "' + configFile + '" is invalid: property "' + property + '" ' + error;
|
return 'The configuration file "' + configFile + '" is invalid: property "' + property + '" ' + error;
|
||||||
}
|
}
|
||||||
|
|
@ -256,11 +264,16 @@ async function getRemoteConfig(configFile) {
|
||||||
path: pieces.groups.path,
|
path: pieces.groups.path,
|
||||||
ref: pieces.groups.ref,
|
ref: pieces.groups.ref,
|
||||||
});
|
});
|
||||||
// todo handle response.encoding not being base64
|
|
||||||
let fileContents;
|
let fileContents;
|
||||||
if ("content" in response.data) {
|
if ("content" in response.data && response.data.content !== undefined) {
|
||||||
fileContents = response.data.content;
|
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'));
|
return yaml.safeLoad(Buffer.from(fileContents, 'base64').toString('binary'));
|
||||||
}
|
}
|
||||||
function getConfigFolder() {
|
function getConfigFolder() {
|
||||||
|
|
|
||||||
File diff suppressed because one or more lines are too long
54
lib/config-utils.test.js
generated
54
lib/config-utils.test.js
generated
|
|
@ -164,6 +164,60 @@ ava_1.default("API client used when reading remote config", async (t) => {
|
||||||
sinon_1.default.restore();
|
sinon_1.default.restore();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
ava_1.default("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: [],
|
||||||
|
};
|
||||||
|
let ok = new octokit.Octokit({
|
||||||
|
userAgent: "CodeQL Action",
|
||||||
|
});
|
||||||
|
const repos = ok.repos;
|
||||||
|
sinon_1.default.stub(repos, "getContents").resolves(Promise.resolve(dummyResponse));
|
||||||
|
ok.repos = repos;
|
||||||
|
sinon_1.default.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_1.default.restore();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
ava_1.default("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_1.default.stub(repos, "getContents").resolves(Promise.resolve(dummyResponse));
|
||||||
|
ok.repos = repos;
|
||||||
|
sinon_1.default.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_1.default.restore();
|
||||||
|
});
|
||||||
|
});
|
||||||
function doInvalidInputTest(testName, inputFileContents, expectedErrorMessageGenerator) {
|
function doInvalidInputTest(testName, inputFileContents, expectedErrorMessageGenerator) {
|
||||||
ava_1.default("load invalid input - " + testName, async (t) => {
|
ava_1.default("load invalid input - " + testName, async (t) => {
|
||||||
return await util.withTmpDir(async (tmpDir) => {
|
return await util.withTmpDir(async (tmpDir) => {
|
||||||
|
|
|
||||||
File diff suppressed because one or more lines are too long
|
|
@ -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(
|
function doInvalidInputTest(
|
||||||
testName: string,
|
testName: string,
|
||||||
inputFileContents: string,
|
inputFileContents: string,
|
||||||
|
|
|
||||||
|
|
@ -171,6 +171,14 @@ export function getConfigFileRepoFormatInvalidMessage(configFile: string): strin
|
||||||
return error;
|
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 {
|
function getConfigFilePropertyError(configFile: string, property: string, error: string): string {
|
||||||
return 'The configuration file "' + configFile + '" is invalid: property "' + property + '" ' + error;
|
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,
|
ref: pieces.groups.ref,
|
||||||
});
|
});
|
||||||
|
|
||||||
// todo handle response.encoding not being base64
|
let fileContents: string;
|
||||||
let fileContents;
|
if ("content" in response.data && response.data.content !== undefined) {
|
||||||
if ("content" in response.data) {
|
|
||||||
fileContents = response.data.content;
|
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'));
|
return yaml.safeLoad(Buffer.from(fileContents, 'base64').toString('binary'));
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue