Add support for basic query overriding in action file itself
See https://github.com/github/dsp-code-scanning/issues/1446
This commit is contained in:
parent
74268130c6
commit
95cef22589
6 changed files with 141 additions and 2 deletions
18
lib/config-utils.js
generated
18
lib/config-utils.js
generated
|
|
@ -460,6 +460,12 @@ async function initConfig() {
|
||||||
else {
|
else {
|
||||||
config = await loadConfig(configFile);
|
config = await loadConfig(configFile);
|
||||||
}
|
}
|
||||||
|
// If queries were provided as using `with` in the action configuration,
|
||||||
|
// they should take precedence over the queries in the config file
|
||||||
|
const queryUses = core.getInput('queries');
|
||||||
|
if (queryUses) {
|
||||||
|
config = await updateConfigWithQueries(config, queryUses, configFile);
|
||||||
|
}
|
||||||
// Save the config so we can easily access it again in the future
|
// Save the config so we can easily access it again in the future
|
||||||
await saveConfig(config);
|
await saveConfig(config);
|
||||||
return config;
|
return config;
|
||||||
|
|
@ -472,6 +478,18 @@ function isLocal(configPath) {
|
||||||
}
|
}
|
||||||
return (configPath.indexOf("@") === -1);
|
return (configPath.indexOf("@") === -1);
|
||||||
}
|
}
|
||||||
|
async function updateConfigWithQueries(config, queryUses, configPath) {
|
||||||
|
if (isLocal(configPath)) {
|
||||||
|
// Treat the config file as relative to the workspace
|
||||||
|
const workspacePath = util.getRequiredEnvParam('GITHUB_WORKSPACE');
|
||||||
|
configPath = path.resolve(workspacePath, configPath);
|
||||||
|
}
|
||||||
|
const languages = await getLanguages();
|
||||||
|
const queries = {};
|
||||||
|
await parseQueryUses(configPath, languages, queries, queryUses);
|
||||||
|
config.queries = queries;
|
||||||
|
return config;
|
||||||
|
}
|
||||||
function getLocalConfig(configFile, workspacePath) {
|
function getLocalConfig(configFile, workspacePath) {
|
||||||
// Error if the config file is now outside of the workspace
|
// Error if the config file is now outside of the workspace
|
||||||
if (!(configFile + path.sep).startsWith(workspacePath + path.sep)) {
|
if (!(configFile + path.sep).startsWith(workspacePath + path.sep)) {
|
||||||
|
|
|
||||||
File diff suppressed because one or more lines are too long
45
lib/config-utils.test.js
generated
45
lib/config-utils.test.js
generated
|
|
@ -224,6 +224,51 @@ ava_1.default("default queries are used", async (t) => {
|
||||||
t.deepEqual(resolveQueriesArgs[0].extraSearchPath, undefined);
|
t.deepEqual(resolveQueriesArgs[0].extraSearchPath, undefined);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
ava_1.default("Queries can be overridden in action file", async (t) => {
|
||||||
|
return await util.withTmpDir(async (tmpDir) => {
|
||||||
|
process.env['RUNNER_TEMP'] = tmpDir;
|
||||||
|
process.env['GITHUB_WORKSPACE'] = tmpDir;
|
||||||
|
const inputFileContents = `
|
||||||
|
name: my config
|
||||||
|
queries:
|
||||||
|
- uses: ./foo`;
|
||||||
|
fs.mkdirSync(path.join(tmpDir, 'foo'));
|
||||||
|
fs.mkdirSync(path.join(tmpDir, 'override'));
|
||||||
|
// This config item should take precedence.
|
||||||
|
setInput('queries', './override');
|
||||||
|
const resolveQueriesArgs = [];
|
||||||
|
CodeQL.setCodeQL({
|
||||||
|
resolveQueries: async function (queries, extraSearchPath) {
|
||||||
|
resolveQueriesArgs.push({ queries, extraSearchPath });
|
||||||
|
// Return what we're given, just in the right format for a resolved query
|
||||||
|
// This way we can test overriding by seeing which returned items are in
|
||||||
|
// the final configuration.
|
||||||
|
const dummyResolvedQueries = {};
|
||||||
|
queries.forEach(q => { dummyResolvedQueries[q] = {}; });
|
||||||
|
return {
|
||||||
|
byLanguage: {
|
||||||
|
'javascript': dummyResolvedQueries,
|
||||||
|
},
|
||||||
|
noDeclaredLanguage: {},
|
||||||
|
multipleDeclaredLanguages: {},
|
||||||
|
};
|
||||||
|
},
|
||||||
|
});
|
||||||
|
fs.writeFileSync(path.join(tmpDir, 'input'), inputFileContents, 'utf8');
|
||||||
|
setInput('config-file', 'input');
|
||||||
|
setInput('languages', 'javascript');
|
||||||
|
const config = await configUtils.initConfig();
|
||||||
|
// Check resolveQueries was called correctly
|
||||||
|
// It'll be called once for the default queries, once for './foo' (from the config file),
|
||||||
|
// and then finally for './override'
|
||||||
|
t.deepEqual(resolveQueriesArgs.length, 3);
|
||||||
|
t.deepEqual(resolveQueriesArgs[2].queries.length, 1);
|
||||||
|
t.regex(resolveQueriesArgs[2].queries[0], /.*\/override$/);
|
||||||
|
// Now check that the end result contains only the override query, not the others
|
||||||
|
t.deepEqual(config.queries['javascript'].length, 1);
|
||||||
|
t.regex(config.queries['javascript'][0], /.*\/override$/);
|
||||||
|
});
|
||||||
|
});
|
||||||
ava_1.default("API client used when reading remote config", async (t) => {
|
ava_1.default("API client used when reading remote config", async (t) => {
|
||||||
return await util.withTmpDir(async (tmpDir) => {
|
return await util.withTmpDir(async (tmpDir) => {
|
||||||
process.env['RUNNER_TEMP'] = tmpDir;
|
process.env['RUNNER_TEMP'] = tmpDir;
|
||||||
|
|
|
||||||
File diff suppressed because one or more lines are too long
|
|
@ -254,6 +254,60 @@ test("default queries are used", async t => {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("Queries can be overridden in action file", async t => {
|
||||||
|
return await util.withTmpDir(async tmpDir => {
|
||||||
|
process.env['RUNNER_TEMP'] = tmpDir;
|
||||||
|
process.env['GITHUB_WORKSPACE'] = tmpDir;
|
||||||
|
|
||||||
|
const inputFileContents = `
|
||||||
|
name: my config
|
||||||
|
queries:
|
||||||
|
- uses: ./foo`;
|
||||||
|
|
||||||
|
// This config item should take precedence.
|
||||||
|
setInput('queries', './override');
|
||||||
|
|
||||||
|
fs.mkdirSync(path.join(tmpDir, 'foo'));
|
||||||
|
fs.mkdirSync(path.join(tmpDir, 'override'));
|
||||||
|
|
||||||
|
const resolveQueriesArgs: {queries: string[], extraSearchPath: string | undefined}[] = [];
|
||||||
|
CodeQL.setCodeQL({
|
||||||
|
resolveQueries: async function(queries: string[], extraSearchPath: string | undefined) {
|
||||||
|
resolveQueriesArgs.push({queries, extraSearchPath});
|
||||||
|
// Return what we're given, just in the right format for a resolved query
|
||||||
|
// This way we can test overriding by seeing which returned items are in
|
||||||
|
// the final configuration.
|
||||||
|
const dummyResolvedQueries = {};
|
||||||
|
queries.forEach(q => { dummyResolvedQueries[q] = {}; });
|
||||||
|
return {
|
||||||
|
byLanguage: {
|
||||||
|
'javascript': dummyResolvedQueries,
|
||||||
|
},
|
||||||
|
noDeclaredLanguage: {},
|
||||||
|
multipleDeclaredLanguages: {},
|
||||||
|
};
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
fs.writeFileSync(path.join(tmpDir, 'input'), inputFileContents, 'utf8');
|
||||||
|
setInput('config-file', 'input');
|
||||||
|
setInput('languages', 'javascript');
|
||||||
|
|
||||||
|
const config = await configUtils.initConfig();
|
||||||
|
|
||||||
|
// Check resolveQueries was called correctly
|
||||||
|
// It'll be called once for the default queries, once for './foo' (from the config file),
|
||||||
|
// and then finally for './override'
|
||||||
|
t.deepEqual(resolveQueriesArgs.length, 3);
|
||||||
|
t.deepEqual(resolveQueriesArgs[2].queries.length, 1);
|
||||||
|
t.regex(resolveQueriesArgs[2].queries[0], /.*\/override$/);
|
||||||
|
|
||||||
|
// Now check that the end result contains only the override query, not the others
|
||||||
|
t.deepEqual(config.queries['javascript'].length, 1);
|
||||||
|
t.regex(config.queries['javascript'][0], /.*\/override$/);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
test("API client used when reading remote config", async t => {
|
test("API client used when reading remote config", async t => {
|
||||||
return await util.withTmpDir(async tmpDir => {
|
return await util.withTmpDir(async tmpDir => {
|
||||||
process.env['RUNNER_TEMP'] = tmpDir;
|
process.env['RUNNER_TEMP'] = tmpDir;
|
||||||
|
|
|
||||||
|
|
@ -599,6 +599,13 @@ export async function initConfig(): Promise<Config> {
|
||||||
config = await loadConfig(configFile);
|
config = await loadConfig(configFile);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If queries were provided as using `with` in the action configuration,
|
||||||
|
// they should take precedence over the queries in the config file
|
||||||
|
const queryUses = core.getInput('queries');
|
||||||
|
if (queryUses) {
|
||||||
|
config = await updateConfigWithQueries(config, queryUses, configFile);
|
||||||
|
}
|
||||||
|
|
||||||
// Save the config so we can easily access it again in the future
|
// Save the config so we can easily access it again in the future
|
||||||
await saveConfig(config);
|
await saveConfig(config);
|
||||||
return config;
|
return config;
|
||||||
|
|
@ -613,6 +620,21 @@ function isLocal(configPath: string): boolean {
|
||||||
return (configPath.indexOf("@") === -1);
|
return (configPath.indexOf("@") === -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function updateConfigWithQueries(config: Config, queryUses: string, configPath: string): Promise<Config> {
|
||||||
|
if (isLocal(configPath)) {
|
||||||
|
// Treat the config file as relative to the workspace
|
||||||
|
const workspacePath = util.getRequiredEnvParam('GITHUB_WORKSPACE');
|
||||||
|
configPath = path.resolve(workspacePath, configPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
const languages = await getLanguages();
|
||||||
|
const queries = {};
|
||||||
|
await parseQueryUses(configPath, languages, queries, queryUses);
|
||||||
|
config.queries = queries;
|
||||||
|
|
||||||
|
return config;
|
||||||
|
}
|
||||||
|
|
||||||
function getLocalConfig(configFile: string, workspacePath: string): UserConfig {
|
function getLocalConfig(configFile: string, workspacePath: string): UserConfig {
|
||||||
// Error if the config file is now outside of the workspace
|
// Error if the config file is now outside of the workspace
|
||||||
if (!(configFile + path.sep).startsWith(workspacePath + path.sep)) {
|
if (!(configFile + path.sep).startsWith(workspacePath + path.sep)) {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue