Skip to content

Commit

Permalink
Add support for basic query overriding in action file itself
Browse files Browse the repository at this point in the history
  • Loading branch information
Sam Partington committed Jul 27, 2020
1 parent 7426813 commit 95cef22
Show file tree
Hide file tree
Showing 6 changed files with 141 additions and 2 deletions.
18 changes: 18 additions & 0 deletions lib/config-utils.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion lib/config-utils.js.map

Large diffs are not rendered by default.

45 changes: 45 additions & 0 deletions lib/config-utils.test.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion lib/config-utils.test.js.map

Large diffs are not rendered by default.

54 changes: 54 additions & 0 deletions src/config-utils.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 => {
return await util.withTmpDir(async tmpDir => {
process.env['RUNNER_TEMP'] = tmpDir;
Expand Down
22 changes: 22 additions & 0 deletions src/config-utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -599,6 +599,13 @@ export async function initConfig(): Promise<Config> {
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
await saveConfig(config);
return config;
Expand All @@ -613,6 +620,21 @@ function isLocal(configPath: string): boolean {
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 {
// Error if the config file is now outside of the workspace
if (!(configFile + path.sep).startsWith(workspacePath + path.sep)) {
Expand Down

0 comments on commit 95cef22

Please sign in to comment.