Add packs and queries from input
This commit adds the packs and queries from the actions input to the config file used by the CodeQL CLI. When the `+` is used, the actions input value is combined with the config value and when it is not used, the input value overrides the config value. This commit also adds a bunch of integration tests for this feature. In order to avoid adding too many new jobs, all of the tests are run sequentially in a single job (matrixed across relevant operating systems and OSes).
This commit is contained in:
parent
237260b693
commit
6fabde2be8
53 changed files with 2072 additions and 219 deletions
120
lib/config-utils.js
generated
120
lib/config-utils.js
generated
|
|
@ -19,7 +19,7 @@ var __importStar = (this && this.__importStar) || function (mod) {
|
|||
return result;
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.getConfig = exports.getPathToParsedConfigFile = exports.initConfig = exports.parsePacks = exports.validatePacksSpecification = exports.parsePacksFromConfig = exports.getDefaultConfig = exports.getUnknownLanguagesError = exports.getNoLanguagesError = exports.getConfigFileDirectoryGivenMessage = exports.getConfigFileFormatInvalidMessage = exports.getConfigFileRepoFormatInvalidMessage = exports.getConfigFileDoesNotExistErrorMessage = exports.getConfigFileOutsideWorkspaceErrorMessage = exports.getLocalPathDoesNotExist = exports.getLocalPathOutsideOfRepository = exports.getPacksStrInvalid = exports.getPacksInvalid = exports.getPacksInvalidSplit = exports.getPathsInvalid = exports.getPathsIgnoreInvalid = exports.getQueryUsesInvalid = exports.getQueriesInvalid = exports.getDisableDefaultQueriesInvalid = exports.getNameInvalid = exports.validateAndSanitisePath = void 0;
|
||||
exports.getConfig = exports.getPathToParsedConfigFile = exports.initConfig = exports.parsePacks = exports.validatePacksSpecification = exports.parsePacksFromConfig = exports.calculateAugmentation = exports.getDefaultConfig = exports.getUnknownLanguagesError = exports.getNoLanguagesError = exports.getConfigFileDirectoryGivenMessage = exports.getConfigFileFormatInvalidMessage = exports.getConfigFileRepoFormatInvalidMessage = exports.getConfigFileDoesNotExistErrorMessage = exports.getConfigFileOutsideWorkspaceErrorMessage = exports.getLocalPathDoesNotExist = exports.getLocalPathOutsideOfRepository = exports.getPacksStrInvalid = exports.getPacksInvalid = exports.getPacksInvalidSplit = exports.getPathsInvalid = exports.getPathsIgnoreInvalid = exports.getQueryUsesInvalid = exports.getQueriesInvalid = exports.getDisableDefaultQueriesInvalid = exports.getNameInvalid = exports.validateAndSanitisePath = void 0;
|
||||
const fs = __importStar(require("fs"));
|
||||
const path = __importStar(require("path"));
|
||||
const yaml = __importStar(require("js-yaml"));
|
||||
|
|
@ -462,8 +462,7 @@ function shouldAddConfigFileQueries(queriesInput) {
|
|||
/**
|
||||
* Get the default config for when the user has not supplied one.
|
||||
*/
|
||||
async function getDefaultConfig(languagesInput, queriesInput, packsInput, dbLocation, debugMode, debugArtifactName, debugDatabaseName, repository, tempDir, toolCacheDir, codeQL, workspacePath, gitHubVersion, apiDetails, featureFlags, logger) {
|
||||
var _a;
|
||||
async function getDefaultConfig(languagesInput, rawQueriesInput, rawPacksInput, dbLocation, debugMode, debugArtifactName, debugDatabaseName, repository, tempDir, toolCacheDir, codeQL, workspacePath, gitHubVersion, apiDetails, featureFlags, logger) {
|
||||
const languages = await getLanguages(codeQL, languagesInput, repository, apiDetails, logger);
|
||||
const queries = {};
|
||||
for (const language of languages) {
|
||||
|
|
@ -473,10 +472,15 @@ async function getDefaultConfig(languagesInput, queriesInput, packsInput, dbLoca
|
|||
};
|
||||
}
|
||||
await addDefaultQueries(codeQL, languages, queries);
|
||||
const packs = (_a = parsePacksFromInput(packsInput, languages)) !== null && _a !== void 0 ? _a : {};
|
||||
let injectedMlQueries = false;
|
||||
if (queriesInput) {
|
||||
injectedMlQueries = await addQueriesAndPacksFromWorkflow(codeQL, queriesInput, languages, queries, packs, tempDir, workspacePath, apiDetails, featureFlags, logger);
|
||||
const augmentationProperties = calculateAugmentation(rawPacksInput, rawQueriesInput, languages);
|
||||
const packs = augmentationProperties.packsInput
|
||||
? {
|
||||
[languages[0]]: augmentationProperties.packsInput,
|
||||
}
|
||||
: {};
|
||||
if (rawQueriesInput) {
|
||||
augmentationProperties.injectedMlQueries =
|
||||
await addQueriesAndPacksFromWorkflow(codeQL, rawQueriesInput, languages, queries, packs, tempDir, workspacePath, apiDetails, featureFlags, logger);
|
||||
}
|
||||
return {
|
||||
languages,
|
||||
|
|
@ -493,14 +497,14 @@ async function getDefaultConfig(languagesInput, queriesInput, packsInput, dbLoca
|
|||
debugMode,
|
||||
debugArtifactName,
|
||||
debugDatabaseName,
|
||||
injectedMlQueries,
|
||||
augmentationProperties,
|
||||
};
|
||||
}
|
||||
exports.getDefaultConfig = getDefaultConfig;
|
||||
/**
|
||||
* Load the config from the given file.
|
||||
*/
|
||||
async function loadConfig(languagesInput, queriesInput, packsInput, configFile, dbLocation, debugMode, debugArtifactName, debugDatabaseName, repository, tempDir, toolCacheDir, codeQL, workspacePath, gitHubVersion, apiDetails, featureFlags, logger) {
|
||||
async function loadConfig(languagesInput, rawQueriesInput, rawPacksInput, configFile, dbLocation, debugMode, debugArtifactName, debugDatabaseName, repository, tempDir, toolCacheDir, codeQL, workspacePath, gitHubVersion, apiDetails, featureFlags, logger) {
|
||||
var _a;
|
||||
let parsedYAML;
|
||||
if (isLocal(configFile)) {
|
||||
|
|
@ -541,16 +545,17 @@ async function loadConfig(languagesInput, queriesInput, packsInput, configFile,
|
|||
if (!disableDefaultQueries) {
|
||||
await addDefaultQueries(codeQL, languages, queries);
|
||||
}
|
||||
const packs = parsePacks((_a = parsedYAML[PACKS_PROPERTY]) !== null && _a !== void 0 ? _a : {}, packsInput, languages, configFile, logger);
|
||||
const augmentationProperties = calculateAugmentation(rawPacksInput, rawQueriesInput, languages);
|
||||
const packs = parsePacks((_a = parsedYAML[PACKS_PROPERTY]) !== null && _a !== void 0 ? _a : {}, rawPacksInput, augmentationProperties.packsInputCombines, languages, configFile, logger);
|
||||
// If queries were provided using `with` in the action configuration,
|
||||
// they should take precedence over the queries in the config file
|
||||
// unless they're prefixed with "+", in which case they supplement those
|
||||
// in the config file.
|
||||
let injectedMlQueries = false;
|
||||
if (queriesInput) {
|
||||
injectedMlQueries = await addQueriesAndPacksFromWorkflow(codeQL, queriesInput, languages, queries, packs, tempDir, workspacePath, apiDetails, featureFlags, logger);
|
||||
if (rawQueriesInput) {
|
||||
augmentationProperties.injectedMlQueries =
|
||||
await addQueriesAndPacksFromWorkflow(codeQL, rawQueriesInput, languages, queries, packs, tempDir, workspacePath, apiDetails, featureFlags, logger);
|
||||
}
|
||||
if (shouldAddConfigFileQueries(queriesInput) &&
|
||||
if (shouldAddConfigFileQueries(rawQueriesInput) &&
|
||||
QUERIES_PROPERTY in parsedYAML) {
|
||||
const queriesArr = parsedYAML[QUERIES_PROPERTY];
|
||||
if (!Array.isArray(queriesArr)) {
|
||||
|
|
@ -601,9 +606,54 @@ async function loadConfig(languagesInput, queriesInput, packsInput, configFile,
|
|||
debugMode,
|
||||
debugArtifactName,
|
||||
debugDatabaseName,
|
||||
injectedMlQueries,
|
||||
augmentationProperties,
|
||||
};
|
||||
}
|
||||
/**
|
||||
* Calculates how the codeql config file needs to be augmented before passing
|
||||
* it to the CLI. The reason this is necessary is the codeql-action can be called
|
||||
* with extra inputs from the workflow. These inputs are not part of the config
|
||||
* and the CLI does not know about these inputs so we need to inject them into
|
||||
* the config file sent to the CLI.
|
||||
*
|
||||
* @param rawPacksInput The packs input from the action configuration.
|
||||
* @param rawQueriesInput The queries input from the action configuration.
|
||||
* @param languages The languages that the config file is for. If the packs input
|
||||
* is non-empty, then there must be exactly one language. Otherwise, an
|
||||
* error is thrown.
|
||||
*
|
||||
* @returns The properties that need to be augmented in the config file.
|
||||
*
|
||||
* @throws An error if the packs input is non-empty and the languages input does
|
||||
* not have exactly one language.
|
||||
*/
|
||||
// exported for testing.
|
||||
function calculateAugmentation(rawPacksInput, rawQueriesInput, languages) {
|
||||
const packsInputCombines = shouldCombine(rawPacksInput);
|
||||
const packsInput = parsePacksFromInput(rawPacksInput, languages, packsInputCombines);
|
||||
const queriesInputCombines = shouldCombine(rawQueriesInput);
|
||||
const queriesInput = parseQueriesFromInput(rawQueriesInput, queriesInputCombines);
|
||||
return {
|
||||
injectedMlQueries: false,
|
||||
packsInputCombines,
|
||||
packsInput: packsInput === null || packsInput === void 0 ? void 0 : packsInput[languages[0]],
|
||||
queriesInput,
|
||||
queriesInputCombines,
|
||||
};
|
||||
}
|
||||
exports.calculateAugmentation = calculateAugmentation;
|
||||
function parseQueriesFromInput(rawQueriesInput, queriesInputCombines) {
|
||||
if (!rawQueriesInput) {
|
||||
return undefined;
|
||||
}
|
||||
const trimmedInput = queriesInputCombines
|
||||
? rawQueriesInput.trim().slice(1).trim()
|
||||
: rawQueriesInput === null || rawQueriesInput === void 0 ? void 0 : rawQueriesInput.trim();
|
||||
if (queriesInputCombines && trimmedInput.length === 0) {
|
||||
throw new Error(getConfigFilePropertyError(undefined, "queries", "A '+' was used in the 'queries' input to specify that you wished to add some packs to your CodeQL analysis. However, no packs were specified. Please either remove the '+' or specify some packs."));
|
||||
}
|
||||
return trimmedInput.split(",").map((query) => ({ uses: query.trim() }));
|
||||
}
|
||||
/**
|
||||
* Pack names must be in the form of `scope/name`, with only alpha-numeric characters,
|
||||
* and `-` allowed as long as not the first or last char.
|
||||
|
|
@ -653,8 +703,8 @@ function parsePacksFromConfig(packsByLanguage, languages, configFile, logger) {
|
|||
return packs;
|
||||
}
|
||||
exports.parsePacksFromConfig = parsePacksFromConfig;
|
||||
function parsePacksFromInput(packsInput, languages) {
|
||||
if (!(packsInput === null || packsInput === void 0 ? void 0 : packsInput.trim())) {
|
||||
function parsePacksFromInput(rawPacksInput, languages, packsInputCombines) {
|
||||
if (!(rawPacksInput === null || rawPacksInput === void 0 ? void 0 : rawPacksInput.trim())) {
|
||||
return undefined;
|
||||
}
|
||||
if (languages.length > 1) {
|
||||
|
|
@ -663,16 +713,16 @@ function parsePacksFromInput(packsInput, languages) {
|
|||
else if (languages.length === 0) {
|
||||
throw new Error("No languages specified. Cannot process the packs input.");
|
||||
}
|
||||
packsInput = packsInput.trim();
|
||||
if (packsInput.startsWith("+")) {
|
||||
packsInput = packsInput.substring(1).trim();
|
||||
if (!packsInput) {
|
||||
throw new Error("A '+' was used in the 'packs' input to specify that you wished to add some packs to your CodeQL analysis. However, no packs were specified. Please either remove the '+' or specify some packs.");
|
||||
rawPacksInput = rawPacksInput.trim();
|
||||
if (packsInputCombines) {
|
||||
rawPacksInput = rawPacksInput.trim().substring(1).trim();
|
||||
if (!rawPacksInput) {
|
||||
throw new Error(getConfigFilePropertyError(undefined, "packs", "A '+' was used in the 'packs' input to specify that you wished to add some packs to your CodeQL analysis. However, no packs were specified. Please either remove the '+' or specify some packs."));
|
||||
}
|
||||
}
|
||||
return {
|
||||
[languages[0]]: packsInput.split(",").reduce((packs, pack) => {
|
||||
packs.push(validatePacksSpecification(pack, ""));
|
||||
[languages[0]]: rawPacksInput.split(",").reduce((packs, pack) => {
|
||||
packs.push(validatePacksSpecification(pack));
|
||||
return packs;
|
||||
}, []),
|
||||
};
|
||||
|
|
@ -741,20 +791,32 @@ function validatePacksSpecification(packStr, configFile) {
|
|||
}
|
||||
exports.validatePacksSpecification = validatePacksSpecification;
|
||||
// exported for testing
|
||||
function parsePacks(rawPacksFromConfig, rawPacksInput, languages, configFile, logger) {
|
||||
const packsFromInput = parsePacksFromInput(rawPacksInput, languages);
|
||||
function parsePacks(rawPacksFromConfig, rawPacksFromInput, packsInputCombines, languages, configFile, logger) {
|
||||
const packsFomConfig = parsePacksFromConfig(rawPacksFromConfig, languages, configFile, logger);
|
||||
const packsFromInput = parsePacksFromInput(rawPacksFromInput, languages, packsInputCombines);
|
||||
if (!packsFromInput) {
|
||||
return packsFomConfig;
|
||||
}
|
||||
if (!shouldCombinePacks(rawPacksInput)) {
|
||||
if (!packsInputCombines) {
|
||||
if (!packsFromInput) {
|
||||
throw new Error(getPacksInvalid(configFile));
|
||||
}
|
||||
return packsFromInput;
|
||||
}
|
||||
return combinePacks(packsFromInput, packsFomConfig);
|
||||
}
|
||||
exports.parsePacks = parsePacks;
|
||||
function shouldCombinePacks(packsInput) {
|
||||
return !!(packsInput === null || packsInput === void 0 ? void 0 : packsInput.trim().startsWith("+"));
|
||||
/**
|
||||
* The convention in this action is that an input value that is prefixed with a '+' will
|
||||
* be combined with the corresponding value in the config file.
|
||||
*
|
||||
* Without a '+', an input value will override the corresponding value in the config file.
|
||||
*
|
||||
* @param inputValue The input value to process.
|
||||
* @returns true if the input value should replace the corresponding value in the config file, false if it should be appended.
|
||||
*/
|
||||
function shouldCombine(inputValue) {
|
||||
return !!(inputValue === null || inputValue === void 0 ? void 0 : inputValue.trim().startsWith("+"));
|
||||
}
|
||||
function combinePacks(packs1, packs2) {
|
||||
const packs = {};
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue