add tempDir and toolCacheDir to config

This commit is contained in:
Robert Brignull 2020-08-19 15:11:49 +01:00
parent e9e2284547
commit 9c29fe283d
18 changed files with 156 additions and 114 deletions

View file

@ -2,33 +2,42 @@ import test from 'ava';
import * as analysisPaths from './analysis-paths';
import {setupTests} from './testing-utils';
import * as util from './util';
setupTests(test);
test("emptyPaths", async t => {
const config = {
languages: [],
queries: {},
pathsIgnore: [],
paths: [],
originalUserInput: {},
};
analysisPaths.includeAndExcludeAnalysisPaths(config);
t.is(process.env['LGTM_INDEX_INCLUDE'], undefined);
t.is(process.env['LGTM_INDEX_EXCLUDE'], undefined);
t.is(process.env['LGTM_INDEX_FILTERS'], undefined);
return await util.withTmpDir(async tmpDir => {
const config = {
languages: [],
queries: {},
pathsIgnore: [],
paths: [],
originalUserInput: {},
tempDir: tmpDir,
toolCacheDir: tmpDir,
};
analysisPaths.includeAndExcludeAnalysisPaths(config);
t.is(process.env['LGTM_INDEX_INCLUDE'], undefined);
t.is(process.env['LGTM_INDEX_EXCLUDE'], undefined);
t.is(process.env['LGTM_INDEX_FILTERS'], undefined);
});
});
test("nonEmptyPaths", async t => {
const config = {
languages: [],
queries: {},
paths: ['path1', 'path2', '**/path3'],
pathsIgnore: ['path4', 'path5', 'path6/**'],
originalUserInput: {},
};
analysisPaths.includeAndExcludeAnalysisPaths(config);
t.is(process.env['LGTM_INDEX_INCLUDE'], 'path1\npath2');
t.is(process.env['LGTM_INDEX_EXCLUDE'], 'path4\npath5');
t.is(process.env['LGTM_INDEX_FILTERS'], 'include:path1\ninclude:path2\ninclude:**/path3\nexclude:path4\nexclude:path5\nexclude:path6/**');
return await util.withTmpDir(async tmpDir => {
const config = {
languages: [],
queries: {},
paths: ['path1', 'path2', '**/path3'],
pathsIgnore: ['path4', 'path5', 'path6/**'],
originalUserInput: {},
tempDir: tmpDir,
toolCacheDir: tmpDir,
};
analysisPaths.includeAndExcludeAnalysisPaths(config);
t.is(process.env['LGTM_INDEX_INCLUDE'], 'path1\npath2');
t.is(process.env['LGTM_INDEX_EXCLUDE'], 'path4\npath5');
t.is(process.env['LGTM_INDEX_FILTERS'], 'include:path1\ninclude:path2\ninclude:**/path3\nexclude:path4\nexclude:path5\nexclude:path6/**');
});
});

View file

@ -41,7 +41,7 @@ async function run() {
return;
}
const config = await config_utils.getConfig();
const config = await config_utils.getConfig(util.getRequiredEnvParam('RUNNER_TEMP'));
// Attempt to find a language to autobuild
// We want pick the dominant language in the repo from the ones we're able to build

View file

@ -67,9 +67,9 @@ test("load empty config", async t => {
},
});
const config = await configUtils.initConfig();
const config = await configUtils.initConfig(tmpDir, tmpDir);
t.deepEqual(config, await configUtils.getDefaultConfig());
t.deepEqual(config, await configUtils.getDefaultConfig(tmpDir, tmpDir));
});
});
@ -93,18 +93,18 @@ test("loading config saves config", async t => {
// Sanity check the saved config file does not already exist
t.false(fs.existsSync(configUtils.getPathToParsedConfigFile()));
t.false(fs.existsSync(configUtils.getPathToParsedConfigFile(tmpDir)));
// Sanity check that getConfig throws before we have called initConfig
await t.throwsAsync(configUtils.getConfig);
await t.throwsAsync(() => configUtils.getConfig(tmpDir));
const config1 = await configUtils.initConfig();
const config1 = await configUtils.initConfig(tmpDir, tmpDir);
// The saved config file should now exist
t.true(fs.existsSync(configUtils.getPathToParsedConfigFile()));
t.true(fs.existsSync(configUtils.getPathToParsedConfigFile(tmpDir)));
// And that same newly-initialised config should now be returned by getConfig
const config2 = await configUtils.getConfig();
const config2 = await configUtils.getConfig(tmpDir);
t.deepEqual(config1, config2);
});
});
@ -117,7 +117,7 @@ test("load input outside of workspace", async t => {
setInput('config-file', '../input');
try {
await configUtils.initConfig();
await configUtils.initConfig(tmpDir, tmpDir);
throw new Error('initConfig did not throw error');
} catch (err) {
t.deepEqual(err, new Error(configUtils.getConfigFileOutsideWorkspaceErrorMessage(path.join(tmpDir, '../input'))));
@ -134,7 +134,7 @@ test("load non-local input with invalid repo syntax", async t => {
setInput('config-file', 'octo-org/codeql-config@main');
try {
await configUtils.initConfig();
await configUtils.initConfig(tmpDir, tmpDir);
throw new Error('initConfig did not throw error');
} catch (err) {
t.deepEqual(err, new Error(configUtils.getConfigFileRepoFormatInvalidMessage('octo-org/codeql-config@main')));
@ -152,7 +152,7 @@ test("load non-existent input", async t => {
setInput('languages', 'javascript');
try {
await configUtils.initConfig();
await configUtils.initConfig(tmpDir, tmpDir);
throw new Error('initConfig did not throw error');
} catch (err) {
t.deepEqual(err, new Error(configUtils.getConfigFileDoesNotExistErrorMessage(path.join(tmpDir, 'input'))));
@ -207,13 +207,15 @@ test("load non-empty input", async t => {
'paths-ignore': ['a', 'b'],
paths: ['c/d'],
},
tempDir: tmpDir,
toolCacheDir: tmpDir,
};
fs.writeFileSync(path.join(tmpDir, 'input'), inputFileContents, 'utf8');
setInput('config-file', 'input');
setInput('languages', 'javascript');
const actualConfig = await configUtils.initConfig();
const actualConfig = await configUtils.initConfig(tmpDir, tmpDir);
// Should exactly equal the object we constructed earlier
t.deepEqual(actualConfig, expectedConfig);
@ -260,7 +262,7 @@ test("default queries are used", async t => {
setInput('config-file', 'input');
setInput('languages', 'javascript');
await configUtils.initConfig();
await configUtils.initConfig(tmpDir, tmpDir);
// Check resolve queries was called correctly
t.deepEqual(resolveQueriesArgs.length, 1);
@ -311,7 +313,7 @@ test("API client used when reading remote config", async t => {
setInput('config-file', 'octo-org/codeql-config/config.yaml@main');
setInput('languages', 'javascript');
await configUtils.initConfig();
await configUtils.initConfig(tmpDir, tmpDir);
t.assert(spyGetContents.called);
});
});
@ -327,7 +329,7 @@ test("Remote config handles the case where a directory is provided", async t =>
const repoReference = 'octo-org/codeql-config/config.yaml@main';
setInput('config-file', repoReference);
try {
await configUtils.initConfig();
await configUtils.initConfig(tmpDir, tmpDir);
throw new Error('initConfig did not throw error');
} catch (err) {
t.deepEqual(err, new Error(configUtils.getConfigFileDirectoryGivenMessage(repoReference)));
@ -348,7 +350,7 @@ test("Invalid format of remote config handled correctly", async t => {
const repoReference = 'octo-org/codeql-config/config.yaml@main';
setInput('config-file', repoReference);
try {
await configUtils.initConfig();
await configUtils.initConfig(tmpDir, tmpDir);
throw new Error('initConfig did not throw error');
} catch (err) {
t.deepEqual(err, new Error(configUtils.getConfigFileFormatInvalidMessage(repoReference)));
@ -364,7 +366,7 @@ test("No detected languages", async t => {
mockListLanguages([]);
try {
await configUtils.initConfig();
await configUtils.initConfig(tmpDir, tmpDir);
throw new Error('initConfig did not throw error');
} catch (err) {
t.deepEqual(err, new Error(configUtils.getNoLanguagesError()));
@ -380,7 +382,7 @@ test("Unknown languages", async t => {
setInput('languages', 'ruby,english');
try {
await configUtils.initConfig();
await configUtils.initConfig(tmpDir, tmpDir);
throw new Error('initConfig did not throw error');
} catch (err) {
t.deepEqual(err, new Error(configUtils.getUnknownLanguagesError(['ruby', 'english'])));
@ -414,7 +416,7 @@ function doInvalidInputTest(
setInput('languages', 'javascript');
try {
await configUtils.initConfig();
await configUtils.initConfig(tmpDir, tmpDir);
throw new Error('initConfig did not throw error');
} catch (err) {
t.deepEqual(err, new Error(expectedErrorMessageGenerator(inputFile)));

View file

@ -70,6 +70,16 @@ export interface Config {
* top-level field above.
*/
originalUserInput: UserConfig;
/**
* Directory to use for temporary files that should be
* deleted at the end of the job.
*/
tempDir: string;
/**
* Directory to use for the tool cache.
* This may be persisted between jobs but this is not guaranteed.
*/
toolCacheDir: string;
}
/**
@ -523,7 +533,7 @@ async function getLanguages(): Promise<Language[]> {
/**
* Get the default config for when the user has not supplied one.
*/
export async function getDefaultConfig(): Promise<Config> {
export async function getDefaultConfig(tempDir: string, toolCacheDir: string): Promise<Config> {
const languages = await getLanguages();
const queries = {};
await addDefaultQueries(languages, queries);
@ -533,13 +543,15 @@ export async function getDefaultConfig(): Promise<Config> {
pathsIgnore: [],
paths: [],
originalUserInput: {},
tempDir,
toolCacheDir,
};
}
/**
* Load the config from the given file.
*/
async function loadConfig(configFile: string): Promise<Config> {
async function loadConfig(configFile: string, tempDir: string, toolCacheDir: string): Promise<Config> {
let parsedYAML: UserConfig;
if (isLocal(configFile)) {
@ -630,7 +642,9 @@ async function loadConfig(configFile: string): Promise<Config> {
queries,
pathsIgnore,
paths,
originalUserInput: parsedYAML
originalUserInput: parsedYAML,
tempDir,
toolCacheDir,
};
}
@ -640,16 +654,16 @@ async function loadConfig(configFile: string): Promise<Config> {
* This will parse the config from the user input if present, or generate
* a default config. The parsed config is then stored to a known location.
*/
export async function initConfig(): Promise<Config> {
export async function initConfig(tempDir: string, toolCacheDir: string): Promise<Config> {
const configFile = core.getInput('config-file');
let config: Config;
// If no config file was provided create an empty one
if (configFile === '') {
core.debug('No configuration file was provided');
config = await getDefaultConfig();
config = await getDefaultConfig(tempDir, toolCacheDir);
} else {
config = await loadConfig(configFile);
config = await loadConfig(configFile, tempDir, toolCacheDir);
}
// Save the config so we can easily access it again in the future
@ -711,8 +725,8 @@ async function getRemoteConfig(configFile: string): Promise<UserConfig> {
/**
* Get the file path where the parsed config will be stored.
*/
export function getPathToParsedConfigFile(): string {
return path.join(util.getRequiredEnvParam('RUNNER_TEMP'), 'config');
export function getPathToParsedConfigFile(tempDir: string): string {
return path.join(tempDir, 'config');
}
/**
@ -720,7 +734,7 @@ export function getPathToParsedConfigFile(): string {
*/
async function saveConfig(config: Config) {
const configString = JSON.stringify(config);
const configFile = getPathToParsedConfigFile();
const configFile = getPathToParsedConfigFile(config.tempDir);
fs.mkdirSync(path.dirname(configFile), { recursive: true });
fs.writeFileSync(configFile, configString, 'utf8');
core.debug('Saved config:');
@ -735,8 +749,8 @@ async function saveConfig(config: Config) {
* stored to a known location. On the second and further calls, this will
* return the contents of the parsed config from the known location.
*/
export async function getConfig(): Promise<Config> {
const configFile = getPathToParsedConfigFile();
export async function getConfig(tempDir: string): Promise<Config> {
const configFile = getPathToParsedConfigFile(tempDir);
if (!fs.existsSync(configFile)) {
throw new Error("Config file could not be found at expected location. Has the 'init' action been called?");
}

View file

@ -129,7 +129,7 @@ async function run() {
if (!await util.sendStatusReport(await util.createStatusReportBase('finish', 'starting', startedAt), true)) {
return;
}
const config = await configUtils.getConfig();
const config = await configUtils.getConfig(util.getRequiredEnvParam('RUNNER_TEMP'));
core.exportVariable(sharedEnv.ODASA_TRACER_CONFIGURATION, '');
delete process.env[sharedEnv.ODASA_TRACER_CONFIGURATION];

View file

@ -186,7 +186,9 @@ async function run() {
core.endGroup();
core.startGroup('Load language configuration');
config = await configUtils.initConfig();
config = await configUtils.initConfig(
util.getRequiredEnvParam('RUNNER_TEMP'),
util.getRequiredEnvParam('RUNNER_TOOL_CACHE'));
analysisPaths.includeAndExcludeAnalysisPaths(config);
core.endGroup();