Mark configuration errors as user errors
This commit is contained in:
parent
95a5fda31a
commit
6639a31758
6 changed files with 208 additions and 194 deletions
92
lib/config-utils.js
generated
92
lib/config-utils.js
generated
|
|
@ -81,13 +81,13 @@ function validateQueries(resolvedQueries) {
|
|||
const noDeclaredLanguage = resolvedQueries.noDeclaredLanguage;
|
||||
const noDeclaredLanguageQueries = Object.keys(noDeclaredLanguage);
|
||||
if (noDeclaredLanguageQueries.length !== 0) {
|
||||
throw new Error(`${"The following queries do not declare a language. " +
|
||||
throw new util_1.UserError(`${"The following queries do not declare a language. " +
|
||||
"Their qlpack.yml files are either missing or is invalid.\n"}${noDeclaredLanguageQueries.join("\n")}`);
|
||||
}
|
||||
const multipleDeclaredLanguages = resolvedQueries.multipleDeclaredLanguages;
|
||||
const multipleDeclaredLanguagesQueries = Object.keys(multipleDeclaredLanguages);
|
||||
if (multipleDeclaredLanguagesQueries.length !== 0) {
|
||||
throw new Error(`${"The following queries declare multiple languages. " +
|
||||
throw new util_1.UserError(`${"The following queries declare multiple languages. " +
|
||||
"Their qlpack.yml files are either missing or is invalid.\n"}${multipleDeclaredLanguagesQueries.join("\n")}`);
|
||||
}
|
||||
}
|
||||
|
|
@ -145,11 +145,11 @@ async function addBuiltinSuiteQueries(languages, codeQL, resultMap, packs, suite
|
|||
let injectedMlQueries = false;
|
||||
const found = builtinSuites.find((suite) => suite === suiteName);
|
||||
if (!found) {
|
||||
throw new Error(getQueryUsesInvalid(configFile, suiteName));
|
||||
throw new util_1.UserError(getQueryUsesInvalid(configFile, suiteName));
|
||||
}
|
||||
if (suiteName === "security-experimental" &&
|
||||
!(await (0, util_1.codeQlVersionAbove)(codeQL, codeql_1.CODEQL_VERSION_SECURITY_EXPERIMENTAL_SUITE))) {
|
||||
throw new Error(`The 'security-experimental' suite is not supported on CodeQL CLI versions earlier than
|
||||
throw new util_1.UserError(`The 'security-experimental' suite is not supported on CodeQL CLI versions earlier than
|
||||
${codeql_1.CODEQL_VERSION_SECURITY_EXPERIMENTAL_SUITE}. Please upgrade to CodeQL CLI version
|
||||
${codeql_1.CODEQL_VERSION_SECURITY_EXPERIMENTAL_SUITE} or later.`);
|
||||
}
|
||||
|
|
@ -188,13 +188,13 @@ async function addLocalQueries(codeQL, resultMap, localQueryPath, workspacePath,
|
|||
let absoluteQueryPath = path.join(workspacePath, localQueryPath);
|
||||
// Check the file exists
|
||||
if (!fs.existsSync(absoluteQueryPath)) {
|
||||
throw new Error(getLocalPathDoesNotExist(configFile, localQueryPath));
|
||||
throw new util_1.UserError(getLocalPathDoesNotExist(configFile, localQueryPath));
|
||||
}
|
||||
// Call this after checking file exists, because it'll fail if file doesn't exist
|
||||
absoluteQueryPath = fs.realpathSync(absoluteQueryPath);
|
||||
// Check the local path doesn't jump outside the repo using '..' or symlinks
|
||||
if (!(absoluteQueryPath + path.sep).startsWith(fs.realpathSync(workspacePath) + path.sep)) {
|
||||
throw new Error(getLocalPathOutsideOfRepository(configFile, localQueryPath));
|
||||
throw new util_1.UserError(getLocalPathOutsideOfRepository(configFile, localQueryPath));
|
||||
}
|
||||
const extraSearchPath = workspacePath;
|
||||
await runResolveQueries(codeQL, resultMap, [absoluteQueryPath], extraSearchPath);
|
||||
|
|
@ -205,7 +205,7 @@ async function addLocalQueries(codeQL, resultMap, localQueryPath, workspacePath,
|
|||
async function addRemoteQueries(codeQL, resultMap, queryUses, tempDir, apiDetails, logger, configFile) {
|
||||
let tok = queryUses.split("@");
|
||||
if (tok.length !== 2) {
|
||||
throw new Error(getQueryUsesInvalid(configFile, queryUses));
|
||||
throw new util_1.UserError(getQueryUsesInvalid(configFile, queryUses));
|
||||
}
|
||||
const ref = tok[1];
|
||||
tok = tok[0].split("/");
|
||||
|
|
@ -213,11 +213,11 @@ async function addRemoteQueries(codeQL, resultMap, queryUses, tempDir, apiDetail
|
|||
// The second token is the repo
|
||||
// The rest is a path, if there is more than one token combine them to form the full path
|
||||
if (tok.length < 2) {
|
||||
throw new Error(getQueryUsesInvalid(configFile, queryUses));
|
||||
throw new util_1.UserError(getQueryUsesInvalid(configFile, queryUses));
|
||||
}
|
||||
// Check none of the parts of the repository name are empty
|
||||
if (tok[0].trim() === "" || tok[1].trim() === "") {
|
||||
throw new Error(getQueryUsesInvalid(configFile, queryUses));
|
||||
throw new util_1.UserError(getQueryUsesInvalid(configFile, queryUses));
|
||||
}
|
||||
const nwo = `${tok[0]}/${tok[1]}`;
|
||||
// Checkout the external repository
|
||||
|
|
@ -243,7 +243,7 @@ async function addRemoteQueries(codeQL, resultMap, queryUses, tempDir, apiDetail
|
|||
async function parseQueryUses(languages, codeQL, resultMap, packs, queryUses, tempDir, workspacePath, apiDetails, features, logger, configFile) {
|
||||
queryUses = queryUses.trim();
|
||||
if (queryUses === "") {
|
||||
throw new Error(getQueryUsesInvalid(configFile));
|
||||
throw new util_1.UserError(getQueryUsesInvalid(configFile));
|
||||
}
|
||||
// Check for the local path case before we start trying to parse the repository name
|
||||
if (queryUses.startsWith("./")) {
|
||||
|
|
@ -284,12 +284,12 @@ function validateAndSanitisePath(originalPath, propertyName, configFile, logger)
|
|||
}
|
||||
// An empty path is not allowed as it's meaningless
|
||||
if (newPath === "") {
|
||||
throw new Error(getConfigFilePropertyError(configFile, propertyName, `"${originalPath}" is not an invalid path. ` +
|
||||
throw new util_1.UserError(getConfigFilePropertyError(configFile, propertyName, `"${originalPath}" is not an invalid path. ` +
|
||||
`It is not necessary to include it, and it is not allowed to exclude it.`));
|
||||
}
|
||||
// Check for illegal uses of **
|
||||
if (newPath.match(pathStarsRegex)) {
|
||||
throw new Error(getConfigFilePropertyError(configFile, propertyName, `"${originalPath}" contains an invalid "**" wildcard. ` +
|
||||
throw new util_1.UserError(getConfigFilePropertyError(configFile, propertyName, `"${originalPath}" contains an invalid "**" wildcard. ` +
|
||||
`They must be immediately preceded and followed by a slash as in "/**/", or come at the start or end.`));
|
||||
}
|
||||
// Check for other regex characters that we don't support.
|
||||
|
|
@ -302,7 +302,7 @@ function validateAndSanitisePath(originalPath, propertyName, configFile, logger)
|
|||
// This may not play nicely with project layouts.
|
||||
// This restriction can be lifted later if we determine they are ok.
|
||||
if (newPath.indexOf("\\") !== -1) {
|
||||
throw new Error(getConfigFilePropertyError(configFile, propertyName, `"${originalPath}" contains an "\\" character. These are not allowed in filters. ` +
|
||||
throw new util_1.UserError(getConfigFilePropertyError(configFile, propertyName, `"${originalPath}" contains an "\\" character. These are not allowed in filters. ` +
|
||||
`If running on windows we recommend using "/" instead for path filters.`));
|
||||
}
|
||||
return newPath;
|
||||
|
|
@ -452,7 +452,7 @@ async function getLanguages(codeQL, languagesInput, repository, logger) {
|
|||
// If the languages parameter was not given and no languages were
|
||||
// detected then fail here as this is a workflow configuration error.
|
||||
if (languages.length === 0) {
|
||||
throw new Error(getNoLanguagesError());
|
||||
throw new util_1.UserError(getNoLanguagesError());
|
||||
}
|
||||
// Make sure they are supported
|
||||
const parsedLanguages = [];
|
||||
|
|
@ -470,7 +470,7 @@ async function getLanguages(codeQL, languagesInput, repository, logger) {
|
|||
// Any unknown languages here would have come directly from the input
|
||||
// since we filter unknown languages coming from the GitHub API.
|
||||
if (unknownLanguages.length > 0) {
|
||||
throw new Error(getUnknownLanguagesError(unknownLanguages));
|
||||
throw new util_1.UserError(getUnknownLanguagesError(unknownLanguages));
|
||||
}
|
||||
return parsedLanguages;
|
||||
}
|
||||
|
|
@ -595,10 +595,10 @@ async function loadConfig(languagesInput, rawQueriesInput, rawPacksInput, config
|
|||
// even though we don't use the value yet.
|
||||
if (NAME_PROPERTY in parsedYAML) {
|
||||
if (typeof parsedYAML[NAME_PROPERTY] !== "string") {
|
||||
throw new Error(getNameInvalid(configFile));
|
||||
throw new util_1.UserError(getNameInvalid(configFile));
|
||||
}
|
||||
if (parsedYAML[NAME_PROPERTY].length === 0) {
|
||||
throw new Error(getNameInvalid(configFile));
|
||||
throw new util_1.UserError(getNameInvalid(configFile));
|
||||
}
|
||||
}
|
||||
const languages = await getLanguages(codeQL, languagesInput, repository, logger);
|
||||
|
|
@ -614,7 +614,7 @@ async function loadConfig(languagesInput, rawQueriesInput, rawPacksInput, config
|
|||
let disableDefaultQueries = false;
|
||||
if (DISABLE_DEFAULT_QUERIES_PROPERTY in parsedYAML) {
|
||||
if (typeof parsedYAML[DISABLE_DEFAULT_QUERIES_PROPERTY] !== "boolean") {
|
||||
throw new Error(getDisableDefaultQueriesInvalid(configFile));
|
||||
throw new util_1.UserError(getDisableDefaultQueriesInvalid(configFile));
|
||||
}
|
||||
disableDefaultQueries = parsedYAML[DISABLE_DEFAULT_QUERIES_PROPERTY];
|
||||
}
|
||||
|
|
@ -635,33 +635,33 @@ async function loadConfig(languagesInput, rawQueriesInput, rawPacksInput, config
|
|||
QUERIES_PROPERTY in parsedYAML) {
|
||||
const queriesArr = parsedYAML[QUERIES_PROPERTY];
|
||||
if (!Array.isArray(queriesArr)) {
|
||||
throw new Error(getQueriesInvalid(configFile));
|
||||
throw new util_1.UserError(getQueriesInvalid(configFile));
|
||||
}
|
||||
for (const query of queriesArr) {
|
||||
if (typeof query[QUERIES_USES_PROPERTY] !== "string") {
|
||||
throw new Error(getQueriesMissingUses(configFile));
|
||||
throw new util_1.UserError(getQueriesMissingUses(configFile));
|
||||
}
|
||||
await parseQueryUses(languages, codeQL, queries, packs, query[QUERIES_USES_PROPERTY], tempDir, workspacePath, apiDetails, features, logger, configFile);
|
||||
}
|
||||
}
|
||||
if (PATHS_IGNORE_PROPERTY in parsedYAML) {
|
||||
if (!Array.isArray(parsedYAML[PATHS_IGNORE_PROPERTY])) {
|
||||
throw new Error(getPathsIgnoreInvalid(configFile));
|
||||
throw new util_1.UserError(getPathsIgnoreInvalid(configFile));
|
||||
}
|
||||
for (const ignorePath of parsedYAML[PATHS_IGNORE_PROPERTY]) {
|
||||
if (typeof ignorePath !== "string" || ignorePath === "") {
|
||||
throw new Error(getPathsIgnoreInvalid(configFile));
|
||||
throw new util_1.UserError(getPathsIgnoreInvalid(configFile));
|
||||
}
|
||||
pathsIgnore.push(validateAndSanitisePath(ignorePath, PATHS_IGNORE_PROPERTY, configFile, logger));
|
||||
}
|
||||
}
|
||||
if (PATHS_PROPERTY in parsedYAML) {
|
||||
if (!Array.isArray(parsedYAML[PATHS_PROPERTY])) {
|
||||
throw new Error(getPathsInvalid(configFile));
|
||||
throw new util_1.UserError(getPathsInvalid(configFile));
|
||||
}
|
||||
for (const includePath of parsedYAML[PATHS_PROPERTY]) {
|
||||
if (typeof includePath !== "string" || includePath === "") {
|
||||
throw new Error(getPathsInvalid(configFile));
|
||||
throw new util_1.UserError(getPathsInvalid(configFile));
|
||||
}
|
||||
paths.push(validateAndSanitisePath(includePath, PATHS_PROPERTY, configFile, logger));
|
||||
}
|
||||
|
|
@ -727,7 +727,7 @@ function parseQueriesFromInput(rawQueriesInput, queriesInputCombines) {
|
|||
? rawQueriesInput.trim().slice(1).trim()
|
||||
: 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."));
|
||||
throw new util_1.UserError(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() }));
|
||||
}
|
||||
|
|
@ -754,12 +754,12 @@ function parsePacksFromConfig(packsByLanguage, languages, configFile, logger) {
|
|||
else {
|
||||
// this is an error since multi-language analysis requires
|
||||
// packs split by language
|
||||
throw new Error(getPacksInvalidSplit(configFile));
|
||||
throw new util_1.UserError(getPacksInvalidSplit(configFile));
|
||||
}
|
||||
}
|
||||
for (const [lang, packsArr] of Object.entries(packsByLanguage)) {
|
||||
if (!Array.isArray(packsArr)) {
|
||||
throw new Error(getPacksInvalid(configFile));
|
||||
throw new util_1.UserError(getPacksInvalid(configFile));
|
||||
}
|
||||
if (!languages.includes(lang)) {
|
||||
// This particular language is not being analyzed in this run.
|
||||
|
|
@ -769,7 +769,7 @@ function parsePacksFromConfig(packsByLanguage, languages, configFile, logger) {
|
|||
}
|
||||
else {
|
||||
// This language is invalid, probably a misspelling
|
||||
throw new Error(getPacksRequireLanguage(configFile, lang));
|
||||
throw new util_1.UserError(getPacksRequireLanguage(configFile, lang));
|
||||
}
|
||||
}
|
||||
packs[lang] = packsArr.map((packStr) => validatePackSpecification(packStr, configFile));
|
||||
|
|
@ -782,16 +782,16 @@ function parsePacksFromInput(rawPacksInput, languages, packsInputCombines) {
|
|||
return undefined;
|
||||
}
|
||||
if (languages.length > 1) {
|
||||
throw new Error("Cannot specify a 'packs' input in a multi-language analysis. Use a codeql-config.yml file instead and specify packs by language.");
|
||||
throw new util_1.UserError("Cannot specify a 'packs' input in a multi-language analysis. Use a codeql-config.yml file instead and specify packs by language.");
|
||||
}
|
||||
else if (languages.length === 0) {
|
||||
throw new Error("No languages specified. Cannot process the packs input.");
|
||||
throw new util_1.UserError("No languages specified. Cannot process the packs input.");
|
||||
}
|
||||
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."));
|
||||
throw new util_1.UserError(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 {
|
||||
|
|
@ -821,7 +821,7 @@ function parsePacksFromInput(rawPacksInput, languages, packsInputCombines) {
|
|||
*/
|
||||
function parsePacksSpecification(packStr, configFile) {
|
||||
if (typeof packStr !== "string") {
|
||||
throw new Error(getPacksStrInvalid(packStr, configFile));
|
||||
throw new util_1.UserError(getPacksStrInvalid(packStr, configFile));
|
||||
}
|
||||
packStr = packStr.trim();
|
||||
const atIndex = packStr.indexOf("@");
|
||||
|
|
@ -842,7 +842,7 @@ function parsePacksSpecification(packStr, configFile) {
|
|||
? packStr.slice(pathStart, pathEnd).trim()
|
||||
: undefined;
|
||||
if (!PACK_IDENTIFIER_PATTERN.test(packName)) {
|
||||
throw new Error(getPacksStrInvalid(packStr, configFile));
|
||||
throw new util_1.UserError(getPacksStrInvalid(packStr, configFile));
|
||||
}
|
||||
if (version) {
|
||||
try {
|
||||
|
|
@ -850,7 +850,7 @@ function parsePacksSpecification(packStr, configFile) {
|
|||
}
|
||||
catch (e) {
|
||||
// The range string is invalid. OK to ignore the caught error
|
||||
throw new Error(getPacksStrInvalid(packStr, configFile));
|
||||
throw new util_1.UserError(getPacksStrInvalid(packStr, configFile));
|
||||
}
|
||||
}
|
||||
if (packPath &&
|
||||
|
|
@ -861,11 +861,11 @@ function parsePacksSpecification(packStr, configFile) {
|
|||
// which seems more awkward.
|
||||
path.normalize(packPath).split(path.sep).join("/") !==
|
||||
packPath.split(path.sep).join("/"))) {
|
||||
throw new Error(getPacksStrInvalid(packStr, configFile));
|
||||
throw new util_1.UserError(getPacksStrInvalid(packStr, configFile));
|
||||
}
|
||||
if (!packPath && pathStart) {
|
||||
// 0 length path
|
||||
throw new Error(getPacksStrInvalid(packStr, configFile));
|
||||
throw new util_1.UserError(getPacksStrInvalid(packStr, configFile));
|
||||
}
|
||||
return {
|
||||
name: packName,
|
||||
|
|
@ -891,7 +891,7 @@ function parsePacks(rawPacksFromConfig, rawPacksFromInput, packsInputCombines, l
|
|||
}
|
||||
if (!packsInputCombines) {
|
||||
if (!packsFromInput) {
|
||||
throw new Error(getPacksInvalid(configFile));
|
||||
throw new util_1.UserError(getPacksInvalid(configFile));
|
||||
}
|
||||
return packsFromInput;
|
||||
}
|
||||
|
|
@ -964,7 +964,7 @@ async function initConfig(languagesInput, queriesInput, packsInput, registriesIn
|
|||
const hasCustomQueries = config.queries[language]?.custom.length > 0;
|
||||
const hasPacks = (config.packs[language]?.length || 0) > 0;
|
||||
if (!hasPacks && !hasBuiltinQueries && !hasCustomQueries) {
|
||||
throw new Error(`Did not detect any queries to run for ${language}. ` +
|
||||
throw new util_1.UserError(`Did not detect any queries to run for ${language}. ` +
|
||||
"Please make sure that the default queries are enabled, or you are specifying queries to run.");
|
||||
}
|
||||
}
|
||||
|
|
@ -982,7 +982,7 @@ function parseRegistries(registriesInput) {
|
|||
: undefined;
|
||||
}
|
||||
catch (e) {
|
||||
throw new Error("Invalid registries input. Must be a YAML string.");
|
||||
throw new util_1.UserError("Invalid registries input. Must be a YAML string.");
|
||||
}
|
||||
}
|
||||
function isLocal(configPath) {
|
||||
|
|
@ -995,11 +995,11 @@ function isLocal(configPath) {
|
|||
function getLocalConfig(configFile, workspacePath) {
|
||||
// Error if the config file is now outside of the workspace
|
||||
if (!(configFile + path.sep).startsWith(workspacePath + path.sep)) {
|
||||
throw new Error(getConfigFileOutsideWorkspaceErrorMessage(configFile));
|
||||
throw new util_1.UserError(getConfigFileOutsideWorkspaceErrorMessage(configFile));
|
||||
}
|
||||
// Error if the file does not exist
|
||||
if (!fs.existsSync(configFile)) {
|
||||
throw new Error(getConfigFileDoesNotExistErrorMessage(configFile));
|
||||
throw new util_1.UserError(getConfigFileDoesNotExistErrorMessage(configFile));
|
||||
}
|
||||
return yaml.load(fs.readFileSync(configFile, "utf8"));
|
||||
}
|
||||
|
|
@ -1009,7 +1009,7 @@ async function getRemoteConfig(configFile, apiDetails) {
|
|||
const pieces = format.exec(configFile);
|
||||
// 5 = 4 groups + the whole expression
|
||||
if (pieces === null || pieces.groups === undefined || pieces.length < 5) {
|
||||
throw new Error(getConfigFileRepoFormatInvalidMessage(configFile));
|
||||
throw new util_1.UserError(getConfigFileRepoFormatInvalidMessage(configFile));
|
||||
}
|
||||
const response = await api
|
||||
.getApiClientWithExternalAuth(apiDetails)
|
||||
|
|
@ -1024,10 +1024,10 @@ async function getRemoteConfig(configFile, apiDetails) {
|
|||
fileContents = response.data.content;
|
||||
}
|
||||
else if (Array.isArray(response.data)) {
|
||||
throw new Error(getConfigFileDirectoryGivenMessage(configFile));
|
||||
throw new util_1.UserError(getConfigFileDirectoryGivenMessage(configFile));
|
||||
}
|
||||
else {
|
||||
throw new Error(getConfigFileFormatInvalidMessage(configFile));
|
||||
throw new util_1.UserError(getConfigFileFormatInvalidMessage(configFile));
|
||||
}
|
||||
return yaml.load(Buffer.from(fileContents, "base64").toString("binary"));
|
||||
}
|
||||
|
|
@ -1112,7 +1112,7 @@ async function generateRegistries(registriesInput, codeQL, tempDir, logger) {
|
|||
let qlconfigFile;
|
||||
if (registries) {
|
||||
if (!(await (0, util_1.codeQlVersionAbove)(codeQL, codeql_1.CODEQL_VERSION_GHES_PACK_DOWNLOAD))) {
|
||||
throw new Error(`The 'registries' input is not supported on CodeQL CLI versions earlier than ${codeql_1.CODEQL_VERSION_GHES_PACK_DOWNLOAD}. Please upgrade to CodeQL CLI version ${codeql_1.CODEQL_VERSION_GHES_PACK_DOWNLOAD} or later.`);
|
||||
throw new util_1.UserError(`The 'registries' input is not supported on CodeQL CLI versions earlier than ${codeql_1.CODEQL_VERSION_GHES_PACK_DOWNLOAD}. Please upgrade to CodeQL CLI version ${codeql_1.CODEQL_VERSION_GHES_PACK_DOWNLOAD} or later.`);
|
||||
}
|
||||
// generate a qlconfig.yml file to hold the registry configs.
|
||||
const qlconfig = createRegistriesBlock(registries);
|
||||
|
|
@ -1139,7 +1139,7 @@ exports.generateRegistries = generateRegistries;
|
|||
function createRegistriesBlock(registries) {
|
||||
if (!Array.isArray(registries) ||
|
||||
registries.some((r) => !r.url || !r.packages)) {
|
||||
throw new Error("Invalid 'registries' input. Must be an array of objects with 'url' and 'packages' properties.");
|
||||
throw new util_1.UserError("Invalid 'registries' input. Must be an array of objects with 'url' and 'packages' properties.");
|
||||
}
|
||||
// be sure to remove the `token` field from the registry before writing it to disk.
|
||||
const safeRegistries = registries.map((registry) => ({
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
100
lib/config-utils.test.js
generated
100
lib/config-utils.test.js
generated
|
|
@ -40,7 +40,7 @@ const languages_1 = require("./languages");
|
|||
const logging_1 = require("./logging");
|
||||
const repository_1 = require("./repository");
|
||||
const testing_utils_1 = require("./testing-utils");
|
||||
const util = __importStar(require("./util"));
|
||||
const util_1 = require("./util");
|
||||
(0, testing_utils_1.setupTests)(ava_1.default);
|
||||
const sampleApiDetails = {
|
||||
auth: "token",
|
||||
|
|
@ -49,7 +49,7 @@ const sampleApiDetails = {
|
|||
apiURL: undefined,
|
||||
registriesAuthTokens: undefined,
|
||||
};
|
||||
const gitHubVersion = { type: util.GitHubVariant.DOTCOM };
|
||||
const gitHubVersion = { type: util_1.GitHubVariant.DOTCOM };
|
||||
// Returns the filepath of the newly-created file
|
||||
function createConfigFile(inputFileContents, tmpDir) {
|
||||
const configFilePath = path.join(tmpDir, "input");
|
||||
|
|
@ -84,7 +84,7 @@ function mockListLanguages(languages) {
|
|||
sinon.stub(api, "getApiClient").value(() => client);
|
||||
}
|
||||
(0, ava_1.default)("load empty config", async (t) => {
|
||||
return await util.withTmpDir(async (tmpDir) => {
|
||||
return await (0, util_1.withTmpDir)(async (tmpDir) => {
|
||||
const logger = (0, logging_1.getRunnerLogger)(true);
|
||||
const languages = "javascript,python";
|
||||
const codeQL = (0, codeql_1.setCodeQL)({
|
||||
|
|
@ -107,7 +107,7 @@ function mockListLanguages(languages) {
|
|||
});
|
||||
});
|
||||
(0, ava_1.default)("loading config saves config", async (t) => {
|
||||
return await util.withTmpDir(async (tmpDir) => {
|
||||
return await (0, util_1.withTmpDir)(async (tmpDir) => {
|
||||
const logger = (0, logging_1.getRunnerLogger)(true);
|
||||
const codeQL = (0, codeql_1.setCodeQL)({
|
||||
async resolveQueries() {
|
||||
|
|
@ -142,45 +142,45 @@ function mockListLanguages(languages) {
|
|||
});
|
||||
});
|
||||
(0, ava_1.default)("load input outside of workspace", async (t) => {
|
||||
return await util.withTmpDir(async (tmpDir) => {
|
||||
return await (0, util_1.withTmpDir)(async (tmpDir) => {
|
||||
try {
|
||||
await configUtils.initConfig(undefined, undefined, undefined, undefined, "../input", undefined, undefined, false, false, "", "", { owner: "github", repo: "example" }, tmpDir, (0, codeql_1.getCachedCodeQL)(), tmpDir, gitHubVersion, sampleApiDetails, (0, testing_utils_1.createFeatures)([]), (0, logging_1.getRunnerLogger)(true));
|
||||
throw new Error("initConfig did not throw error");
|
||||
throw new util_1.UserError("initConfig did not throw error");
|
||||
}
|
||||
catch (err) {
|
||||
t.deepEqual(err, new Error(configUtils.getConfigFileOutsideWorkspaceErrorMessage(path.join(tmpDir, "../input"))));
|
||||
t.deepEqual(err, new util_1.UserError(configUtils.getConfigFileOutsideWorkspaceErrorMessage(path.join(tmpDir, "../input"))));
|
||||
}
|
||||
});
|
||||
});
|
||||
(0, ava_1.default)("load non-local input with invalid repo syntax", async (t) => {
|
||||
return await util.withTmpDir(async (tmpDir) => {
|
||||
return await (0, util_1.withTmpDir)(async (tmpDir) => {
|
||||
// no filename given, just a repo
|
||||
const configFile = "octo-org/codeql-config@main";
|
||||
try {
|
||||
await configUtils.initConfig(undefined, undefined, undefined, undefined, configFile, undefined, undefined, false, false, "", "", { owner: "github", repo: "example" }, tmpDir, (0, codeql_1.getCachedCodeQL)(), tmpDir, gitHubVersion, sampleApiDetails, (0, testing_utils_1.createFeatures)([]), (0, logging_1.getRunnerLogger)(true));
|
||||
throw new Error("initConfig did not throw error");
|
||||
throw new util_1.UserError("initConfig did not throw error");
|
||||
}
|
||||
catch (err) {
|
||||
t.deepEqual(err, new Error(configUtils.getConfigFileRepoFormatInvalidMessage("octo-org/codeql-config@main")));
|
||||
t.deepEqual(err, new util_1.UserError(configUtils.getConfigFileRepoFormatInvalidMessage("octo-org/codeql-config@main")));
|
||||
}
|
||||
});
|
||||
});
|
||||
(0, ava_1.default)("load non-existent input", async (t) => {
|
||||
return await util.withTmpDir(async (tmpDir) => {
|
||||
return await (0, util_1.withTmpDir)(async (tmpDir) => {
|
||||
const languages = "javascript";
|
||||
const configFile = "input";
|
||||
t.false(fs.existsSync(path.join(tmpDir, configFile)));
|
||||
try {
|
||||
await configUtils.initConfig(languages, undefined, undefined, undefined, configFile, undefined, undefined, false, false, "", "", { owner: "github", repo: "example" }, tmpDir, (0, codeql_1.getCachedCodeQL)(), tmpDir, gitHubVersion, sampleApiDetails, (0, testing_utils_1.createFeatures)([]), (0, logging_1.getRunnerLogger)(true));
|
||||
throw new Error("initConfig did not throw error");
|
||||
throw new util_1.UserError("initConfig did not throw error");
|
||||
}
|
||||
catch (err) {
|
||||
t.deepEqual(err, new Error(configUtils.getConfigFileDoesNotExistErrorMessage(path.join(tmpDir, "input"))));
|
||||
t.deepEqual(err, new util_1.UserError(configUtils.getConfigFileDoesNotExistErrorMessage(path.join(tmpDir, "input"))));
|
||||
}
|
||||
});
|
||||
});
|
||||
(0, ava_1.default)("load non-empty input", async (t) => {
|
||||
return await util.withTmpDir(async (tmpDir) => {
|
||||
return await (0, util_1.withTmpDir)(async (tmpDir) => {
|
||||
const codeQL = (0, codeql_1.setCodeQL)({
|
||||
async resolveQueries() {
|
||||
return {
|
||||
|
|
@ -253,7 +253,7 @@ function mockListLanguages(languages) {
|
|||
});
|
||||
});
|
||||
(0, ava_1.default)("Default queries are used", async (t) => {
|
||||
return await util.withTmpDir(async (tmpDir) => {
|
||||
return await (0, util_1.withTmpDir)(async (tmpDir) => {
|
||||
// Check that the default behaviour is to add the default queries.
|
||||
// In this case if a config file is specified but does not include
|
||||
// the disable-default-queries field.
|
||||
|
|
@ -314,7 +314,7 @@ function queriesToResolvedQueryForm(queries) {
|
|||
};
|
||||
}
|
||||
(0, ava_1.default)("Queries can be specified in config file", async (t) => {
|
||||
return await util.withTmpDir(async (tmpDir) => {
|
||||
return await (0, util_1.withTmpDir)(async (tmpDir) => {
|
||||
const inputFileContents = `
|
||||
name: my config
|
||||
queries:
|
||||
|
|
@ -347,7 +347,7 @@ function queriesToResolvedQueryForm(queries) {
|
|||
});
|
||||
});
|
||||
(0, ava_1.default)("Queries from config file can be overridden in workflow file", async (t) => {
|
||||
return await util.withTmpDir(async (tmpDir) => {
|
||||
return await (0, util_1.withTmpDir)(async (tmpDir) => {
|
||||
const inputFileContents = `
|
||||
name: my config
|
||||
queries:
|
||||
|
|
@ -383,7 +383,7 @@ function queriesToResolvedQueryForm(queries) {
|
|||
});
|
||||
});
|
||||
(0, ava_1.default)("Queries in workflow file can be used in tandem with the 'disable default queries' option", async (t) => {
|
||||
return await util.withTmpDir(async (tmpDir) => {
|
||||
return await (0, util_1.withTmpDir)(async (tmpDir) => {
|
||||
process.env["RUNNER_TEMP"] = tmpDir;
|
||||
process.env["GITHUB_WORKSPACE"] = tmpDir;
|
||||
const inputFileContents = `
|
||||
|
|
@ -417,7 +417,7 @@ function queriesToResolvedQueryForm(queries) {
|
|||
});
|
||||
});
|
||||
(0, ava_1.default)("Multiple queries can be specified in workflow file, no config file required", async (t) => {
|
||||
return await util.withTmpDir(async (tmpDir) => {
|
||||
return await (0, util_1.withTmpDir)(async (tmpDir) => {
|
||||
fs.mkdirSync(path.join(tmpDir, "override1"));
|
||||
fs.mkdirSync(path.join(tmpDir, "override2"));
|
||||
const testQueries = "./override1,./override2";
|
||||
|
|
@ -450,7 +450,7 @@ function queriesToResolvedQueryForm(queries) {
|
|||
});
|
||||
});
|
||||
(0, ava_1.default)("Queries in workflow file can be added to the set of queries without overriding config file", async (t) => {
|
||||
return await util.withTmpDir(async (tmpDir) => {
|
||||
return await (0, util_1.withTmpDir)(async (tmpDir) => {
|
||||
process.env["RUNNER_TEMP"] = tmpDir;
|
||||
process.env["GITHUB_WORKSPACE"] = tmpDir;
|
||||
const inputFileContents = `
|
||||
|
|
@ -496,7 +496,7 @@ function queriesToResolvedQueryForm(queries) {
|
|||
});
|
||||
});
|
||||
(0, ava_1.default)("Queries can be specified using config input", async (t) => {
|
||||
return await util.withTmpDir(async (tmpDir) => {
|
||||
return await (0, util_1.withTmpDir)(async (tmpDir) => {
|
||||
const configInput = `
|
||||
name: my config
|
||||
queries:
|
||||
|
|
@ -538,7 +538,7 @@ function queriesToResolvedQueryForm(queries) {
|
|||
});
|
||||
});
|
||||
(0, ava_1.default)("Using config input and file together, config input should be used.", async (t) => {
|
||||
return await util.withTmpDir(async (tmpDir) => {
|
||||
return await (0, util_1.withTmpDir)(async (tmpDir) => {
|
||||
process.env["RUNNER_TEMP"] = tmpDir;
|
||||
process.env["GITHUB_WORKSPACE"] = tmpDir;
|
||||
const inputFileContents = `
|
||||
|
|
@ -587,7 +587,7 @@ function queriesToResolvedQueryForm(queries) {
|
|||
});
|
||||
});
|
||||
(0, ava_1.default)("Invalid queries in workflow file handled correctly", async (t) => {
|
||||
return await util.withTmpDir(async (tmpDir) => {
|
||||
return await (0, util_1.withTmpDir)(async (tmpDir) => {
|
||||
const queries = "foo/bar@v1@v3";
|
||||
const languages = "javascript";
|
||||
// This function just needs to be type-correct; it doesn't need to do anything,
|
||||
|
|
@ -611,12 +611,12 @@ function queriesToResolvedQueryForm(queries) {
|
|||
t.fail("initConfig did not throw error");
|
||||
}
|
||||
catch (err) {
|
||||
t.deepEqual(err, new Error(configUtils.getQueryUsesInvalid(undefined, "foo/bar@v1@v3")));
|
||||
t.deepEqual(err, new util_1.UserError(configUtils.getQueryUsesInvalid(undefined, "foo/bar@v1@v3")));
|
||||
}
|
||||
});
|
||||
});
|
||||
(0, ava_1.default)("API client used when reading remote config", async (t) => {
|
||||
return await util.withTmpDir(async (tmpDir) => {
|
||||
return await (0, util_1.withTmpDir)(async (tmpDir) => {
|
||||
const codeQL = (0, codeql_1.setCodeQL)({
|
||||
async resolveQueries() {
|
||||
return {
|
||||
|
|
@ -658,21 +658,21 @@ function queriesToResolvedQueryForm(queries) {
|
|||
});
|
||||
});
|
||||
(0, ava_1.default)("Remote config handles the case where a directory is provided", async (t) => {
|
||||
return await util.withTmpDir(async (tmpDir) => {
|
||||
return await (0, util_1.withTmpDir)(async (tmpDir) => {
|
||||
const dummyResponse = []; // directories are returned as arrays
|
||||
mockGetContents(dummyResponse);
|
||||
const repoReference = "octo-org/codeql-config/config.yaml@main";
|
||||
try {
|
||||
await configUtils.initConfig(undefined, undefined, undefined, undefined, repoReference, undefined, undefined, false, false, "", "", { owner: "github", repo: "example" }, tmpDir, (0, codeql_1.getCachedCodeQL)(), tmpDir, gitHubVersion, sampleApiDetails, (0, testing_utils_1.createFeatures)([]), (0, logging_1.getRunnerLogger)(true));
|
||||
throw new Error("initConfig did not throw error");
|
||||
throw new util_1.UserError("initConfig did not throw error");
|
||||
}
|
||||
catch (err) {
|
||||
t.deepEqual(err, new Error(configUtils.getConfigFileDirectoryGivenMessage(repoReference)));
|
||||
t.deepEqual(err, new util_1.UserError(configUtils.getConfigFileDirectoryGivenMessage(repoReference)));
|
||||
}
|
||||
});
|
||||
});
|
||||
(0, ava_1.default)("Invalid format of remote config handled correctly", async (t) => {
|
||||
return await util.withTmpDir(async (tmpDir) => {
|
||||
return await (0, util_1.withTmpDir)(async (tmpDir) => {
|
||||
const dummyResponse = {
|
||||
// note no "content" property here
|
||||
};
|
||||
|
|
@ -680,15 +680,15 @@ function queriesToResolvedQueryForm(queries) {
|
|||
const repoReference = "octo-org/codeql-config/config.yaml@main";
|
||||
try {
|
||||
await configUtils.initConfig(undefined, undefined, undefined, undefined, repoReference, undefined, undefined, false, false, "", "", { owner: "github", repo: "example" }, tmpDir, (0, codeql_1.getCachedCodeQL)(), tmpDir, gitHubVersion, sampleApiDetails, (0, testing_utils_1.createFeatures)([]), (0, logging_1.getRunnerLogger)(true));
|
||||
throw new Error("initConfig did not throw error");
|
||||
throw new util_1.UserError("initConfig did not throw error");
|
||||
}
|
||||
catch (err) {
|
||||
t.deepEqual(err, new Error(configUtils.getConfigFileFormatInvalidMessage(repoReference)));
|
||||
t.deepEqual(err, new util_1.UserError(configUtils.getConfigFileFormatInvalidMessage(repoReference)));
|
||||
}
|
||||
});
|
||||
});
|
||||
(0, ava_1.default)("No detected languages", async (t) => {
|
||||
return await util.withTmpDir(async (tmpDir) => {
|
||||
return await (0, util_1.withTmpDir)(async (tmpDir) => {
|
||||
mockListLanguages([]);
|
||||
const codeQL = (0, codeql_1.setCodeQL)({
|
||||
async resolveLanguages() {
|
||||
|
|
@ -700,27 +700,27 @@ function queriesToResolvedQueryForm(queries) {
|
|||
});
|
||||
try {
|
||||
await configUtils.initConfig(undefined, undefined, undefined, undefined, undefined, undefined, undefined, false, false, "", "", { owner: "github", repo: "example" }, tmpDir, codeQL, tmpDir, gitHubVersion, sampleApiDetails, (0, testing_utils_1.createFeatures)([]), (0, logging_1.getRunnerLogger)(true));
|
||||
throw new Error("initConfig did not throw error");
|
||||
throw new util_1.UserError("initConfig did not throw error");
|
||||
}
|
||||
catch (err) {
|
||||
t.deepEqual(err, new Error(configUtils.getNoLanguagesError()));
|
||||
t.deepEqual(err, new util_1.UserError(configUtils.getNoLanguagesError()));
|
||||
}
|
||||
});
|
||||
});
|
||||
(0, ava_1.default)("Unknown languages", async (t) => {
|
||||
return await util.withTmpDir(async (tmpDir) => {
|
||||
return await (0, util_1.withTmpDir)(async (tmpDir) => {
|
||||
const languages = "rubbish,english";
|
||||
try {
|
||||
await configUtils.initConfig(languages, undefined, undefined, undefined, undefined, undefined, undefined, false, false, "", "", { owner: "github", repo: "example" }, tmpDir, (0, codeql_1.getCachedCodeQL)(), tmpDir, gitHubVersion, sampleApiDetails, (0, testing_utils_1.createFeatures)([]), (0, logging_1.getRunnerLogger)(true));
|
||||
throw new Error("initConfig did not throw error");
|
||||
throw new util_1.UserError("initConfig did not throw error");
|
||||
}
|
||||
catch (err) {
|
||||
t.deepEqual(err, new Error(configUtils.getUnknownLanguagesError(["rubbish", "english"])));
|
||||
t.deepEqual(err, new util_1.UserError(configUtils.getUnknownLanguagesError(["rubbish", "english"])));
|
||||
}
|
||||
});
|
||||
});
|
||||
(0, ava_1.default)("Config specifies packages", async (t) => {
|
||||
return await util.withTmpDir(async (tmpDir) => {
|
||||
return await (0, util_1.withTmpDir)(async (tmpDir) => {
|
||||
const codeQL = (0, codeql_1.setCodeQL)({
|
||||
async resolveQueries() {
|
||||
return {
|
||||
|
|
@ -749,7 +749,7 @@ function queriesToResolvedQueryForm(queries) {
|
|||
});
|
||||
});
|
||||
(0, ava_1.default)("Config specifies packages for multiple languages", async (t) => {
|
||||
return await util.withTmpDir(async (tmpDir) => {
|
||||
return await (0, util_1.withTmpDir)(async (tmpDir) => {
|
||||
const codeQL = (0, codeql_1.setCodeQL)({
|
||||
async resolveQueries() {
|
||||
return {
|
||||
|
|
@ -807,7 +807,7 @@ function queriesToResolvedQueryForm(queries) {
|
|||
});
|
||||
function doInvalidInputTest(testName, inputFileContents, expectedErrorMessageGenerator) {
|
||||
(0, ava_1.default)(`load invalid input - ${testName}`, async (t) => {
|
||||
return await util.withTmpDir(async (tmpDir) => {
|
||||
return await (0, util_1.withTmpDir)(async (tmpDir) => {
|
||||
const codeQL = (0, codeql_1.setCodeQL)({
|
||||
async resolveQueries() {
|
||||
return {
|
||||
|
|
@ -826,10 +826,10 @@ function doInvalidInputTest(testName, inputFileContents, expectedErrorMessageGen
|
|||
fs.writeFileSync(inputFile, inputFileContents, "utf8");
|
||||
try {
|
||||
await configUtils.initConfig(languages, undefined, undefined, undefined, configFile, undefined, undefined, false, false, "", "", { owner: "github", repo: "example" }, tmpDir, codeQL, tmpDir, gitHubVersion, sampleApiDetails, (0, testing_utils_1.createFeatures)([]), (0, logging_1.getRunnerLogger)(true));
|
||||
throw new Error("initConfig did not throw error");
|
||||
throw new util_1.UserError("initConfig did not throw error");
|
||||
}
|
||||
catch (err) {
|
||||
t.deepEqual(err, new Error(expectedErrorMessageGenerator(inputFile)));
|
||||
t.deepEqual(err, new util_1.UserError(expectedErrorMessageGenerator(inputFile)));
|
||||
}
|
||||
});
|
||||
});
|
||||
|
|
@ -1064,7 +1064,7 @@ parseInputAndConfigErrorMacro.title = (providedTitle) => `Parse Packs input and
|
|||
(0, ava_1.default)("input with invalid pack name", parseInputAndConfigErrorMacro, {}, " xxx", [languages_1.Language.cpp], false, /"xxx" is not a valid pack/);
|
||||
const mlPoweredQueriesMacro = ava_1.default.macro({
|
||||
exec: async (t, codeQLVersion, isMlPoweredQueriesEnabled, packsInput, queriesInput, expectedVersionString) => {
|
||||
return await util.withTmpDir(async (tmpDir) => {
|
||||
return await (0, util_1.withTmpDir)(async (tmpDir) => {
|
||||
const codeQL = (0, codeql_1.setCodeQL)({
|
||||
async getVersion() {
|
||||
return codeQLVersion;
|
||||
|
|
@ -1190,7 +1190,7 @@ const calculateAugmentationErrorMacro = ava_1.default.macro({
|
|||
(0, ava_1.default)(calculateAugmentationErrorMacro, "Packs input with no languages", " + a/b, c/d ", undefined, [], /No languages specified/);
|
||||
(0, ava_1.default)(calculateAugmentationErrorMacro, "Invalid packs", " a-pack-without-a-scope ", undefined, [languages_1.Language.javascript], /"a-pack-without-a-scope" is not a valid pack/);
|
||||
(0, ava_1.default)("downloadPacks-no-registries", async (t) => {
|
||||
return await util.withTmpDir(async (tmpDir) => {
|
||||
return await (0, util_1.withTmpDir)(async (tmpDir) => {
|
||||
const packDownloadStub = sinon.stub();
|
||||
packDownloadStub.callsFake((packs) => ({
|
||||
packs,
|
||||
|
|
@ -1217,7 +1217,7 @@ const calculateAugmentationErrorMacro = ava_1.default.macro({
|
|||
(0, ava_1.default)("downloadPacks-with-registries", async (t) => {
|
||||
// same thing, but this time include a registries block and
|
||||
// associated env vars
|
||||
return await util.withTmpDir(async (tmpDir) => {
|
||||
return await (0, util_1.withTmpDir)(async (tmpDir) => {
|
||||
process.env.GITHUB_TOKEN = "not-a-token";
|
||||
process.env.CODEQL_REGISTRIES_AUTH = undefined;
|
||||
const logger = (0, logging_1.getRunnerLogger)(true);
|
||||
|
|
@ -1284,7 +1284,7 @@ const calculateAugmentationErrorMacro = ava_1.default.macro({
|
|||
(0, ava_1.default)("downloadPacks-with-registries fails on 2.10.3", async (t) => {
|
||||
// same thing, but this time include a registries block and
|
||||
// associated env vars
|
||||
return await util.withTmpDir(async (tmpDir) => {
|
||||
return await (0, util_1.withTmpDir)(async (tmpDir) => {
|
||||
process.env.GITHUB_TOKEN = "not-a-token";
|
||||
process.env.CODEQL_REGISTRIES_AUTH = "not-a-registries-auth";
|
||||
const logger = (0, logging_1.getRunnerLogger)(true);
|
||||
|
|
@ -1311,7 +1311,7 @@ const calculateAugmentationErrorMacro = ava_1.default.macro({
|
|||
(0, ava_1.default)("downloadPacks-with-registries fails with invalid registries block", async (t) => {
|
||||
// same thing, but this time include a registries block and
|
||||
// associated env vars
|
||||
return await util.withTmpDir(async (tmpDir) => {
|
||||
return await (0, util_1.withTmpDir)(async (tmpDir) => {
|
||||
process.env.GITHUB_TOKEN = "not-a-token";
|
||||
process.env.CODEQL_REGISTRIES_AUTH = "not-a-registries-auth";
|
||||
const logger = (0, logging_1.getRunnerLogger)(true);
|
||||
|
|
@ -1338,7 +1338,7 @@ const calculateAugmentationErrorMacro = ava_1.default.macro({
|
|||
// the happy path for generateRegistries is already tested in downloadPacks.
|
||||
// these following tests are for the error cases and when nothing is generated.
|
||||
(0, ava_1.default)("no generateRegistries when CLI is too old", async (t) => {
|
||||
return await util.withTmpDir(async (tmpDir) => {
|
||||
return await (0, util_1.withTmpDir)(async (tmpDir) => {
|
||||
const registriesInput = yaml.dump([
|
||||
{
|
||||
// no slash
|
||||
|
|
@ -1356,7 +1356,7 @@ const calculateAugmentationErrorMacro = ava_1.default.macro({
|
|||
});
|
||||
});
|
||||
(0, ava_1.default)("no generateRegistries when registries is undefined", async (t) => {
|
||||
return await util.withTmpDir(async (tmpDir) => {
|
||||
return await (0, util_1.withTmpDir)(async (tmpDir) => {
|
||||
const registriesInput = undefined;
|
||||
const codeQL = (0, codeql_1.setCodeQL)({
|
||||
// Accepted CLI versions are 2.10.4 or higher
|
||||
|
|
@ -1369,7 +1369,7 @@ const calculateAugmentationErrorMacro = ava_1.default.macro({
|
|||
});
|
||||
});
|
||||
(0, ava_1.default)("generateRegistries prefers original CODEQL_REGISTRIES_AUTH", async (t) => {
|
||||
return await util.withTmpDir(async (tmpDir) => {
|
||||
return await (0, util_1.withTmpDir)(async (tmpDir) => {
|
||||
process.env.CODEQL_REGISTRIES_AUTH = "original";
|
||||
const registriesInput = yaml.dump([
|
||||
{
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
|
|
@ -23,7 +23,7 @@ import {
|
|||
createFeatures,
|
||||
mockLanguagesInRepo as mockLanguagesInRepo,
|
||||
} from "./testing-utils";
|
||||
import * as util from "./util";
|
||||
import { GitHubVariant, GitHubVersion, UserError, withTmpDir } from "./util";
|
||||
|
||||
setupTests(test);
|
||||
|
||||
|
|
@ -35,7 +35,7 @@ const sampleApiDetails = {
|
|||
registriesAuthTokens: undefined,
|
||||
};
|
||||
|
||||
const gitHubVersion = { type: util.GitHubVariant.DOTCOM } as util.GitHubVersion;
|
||||
const gitHubVersion = { type: GitHubVariant.DOTCOM } as GitHubVersion;
|
||||
|
||||
// Returns the filepath of the newly-created file
|
||||
function createConfigFile(inputFileContents: string, tmpDir: string): string {
|
||||
|
|
@ -78,7 +78,7 @@ function mockListLanguages(languages: string[]) {
|
|||
}
|
||||
|
||||
test("load empty config", async (t) => {
|
||||
return await util.withTmpDir(async (tmpDir) => {
|
||||
return await withTmpDir(async (tmpDir) => {
|
||||
const logger = getRunnerLogger(true);
|
||||
const languages = "javascript,python";
|
||||
|
||||
|
|
@ -145,7 +145,7 @@ test("load empty config", async (t) => {
|
|||
});
|
||||
|
||||
test("loading config saves config", async (t) => {
|
||||
return await util.withTmpDir(async (tmpDir) => {
|
||||
return await withTmpDir(async (tmpDir) => {
|
||||
const logger = getRunnerLogger(true);
|
||||
|
||||
const codeQL = setCodeQL({
|
||||
|
|
@ -207,7 +207,7 @@ test("loading config saves config", async (t) => {
|
|||
});
|
||||
|
||||
test("load input outside of workspace", async (t) => {
|
||||
return await util.withTmpDir(async (tmpDir) => {
|
||||
return await withTmpDir(async (tmpDir) => {
|
||||
try {
|
||||
await configUtils.initConfig(
|
||||
undefined,
|
||||
|
|
@ -230,11 +230,11 @@ test("load input outside of workspace", async (t) => {
|
|||
createFeatures([]),
|
||||
getRunnerLogger(true)
|
||||
);
|
||||
throw new Error("initConfig did not throw error");
|
||||
throw new UserError("initConfig did not throw error");
|
||||
} catch (err) {
|
||||
t.deepEqual(
|
||||
err,
|
||||
new Error(
|
||||
new UserError(
|
||||
configUtils.getConfigFileOutsideWorkspaceErrorMessage(
|
||||
path.join(tmpDir, "../input")
|
||||
)
|
||||
|
|
@ -245,7 +245,7 @@ test("load input outside of workspace", async (t) => {
|
|||
});
|
||||
|
||||
test("load non-local input with invalid repo syntax", async (t) => {
|
||||
return await util.withTmpDir(async (tmpDir) => {
|
||||
return await withTmpDir(async (tmpDir) => {
|
||||
// no filename given, just a repo
|
||||
const configFile = "octo-org/codeql-config@main";
|
||||
|
||||
|
|
@ -271,11 +271,11 @@ test("load non-local input with invalid repo syntax", async (t) => {
|
|||
createFeatures([]),
|
||||
getRunnerLogger(true)
|
||||
);
|
||||
throw new Error("initConfig did not throw error");
|
||||
throw new UserError("initConfig did not throw error");
|
||||
} catch (err) {
|
||||
t.deepEqual(
|
||||
err,
|
||||
new Error(
|
||||
new UserError(
|
||||
configUtils.getConfigFileRepoFormatInvalidMessage(
|
||||
"octo-org/codeql-config@main"
|
||||
)
|
||||
|
|
@ -286,7 +286,7 @@ test("load non-local input with invalid repo syntax", async (t) => {
|
|||
});
|
||||
|
||||
test("load non-existent input", async (t) => {
|
||||
return await util.withTmpDir(async (tmpDir) => {
|
||||
return await withTmpDir(async (tmpDir) => {
|
||||
const languages = "javascript";
|
||||
const configFile = "input";
|
||||
t.false(fs.existsSync(path.join(tmpDir, configFile)));
|
||||
|
|
@ -313,11 +313,11 @@ test("load non-existent input", async (t) => {
|
|||
createFeatures([]),
|
||||
getRunnerLogger(true)
|
||||
);
|
||||
throw new Error("initConfig did not throw error");
|
||||
throw new UserError("initConfig did not throw error");
|
||||
} catch (err) {
|
||||
t.deepEqual(
|
||||
err,
|
||||
new Error(
|
||||
new UserError(
|
||||
configUtils.getConfigFileDoesNotExistErrorMessage(
|
||||
path.join(tmpDir, "input")
|
||||
)
|
||||
|
|
@ -328,7 +328,7 @@ test("load non-existent input", async (t) => {
|
|||
});
|
||||
|
||||
test("load non-empty input", async (t) => {
|
||||
return await util.withTmpDir(async (tmpDir) => {
|
||||
return await withTmpDir(async (tmpDir) => {
|
||||
const codeQL = setCodeQL({
|
||||
async resolveQueries() {
|
||||
return {
|
||||
|
|
@ -428,7 +428,7 @@ test("load non-empty input", async (t) => {
|
|||
});
|
||||
|
||||
test("Default queries are used", async (t) => {
|
||||
return await util.withTmpDir(async (tmpDir) => {
|
||||
return await withTmpDir(async (tmpDir) => {
|
||||
// Check that the default behaviour is to add the default queries.
|
||||
// In this case if a config file is specified but does not include
|
||||
// the disable-default-queries field.
|
||||
|
|
@ -523,7 +523,7 @@ function queriesToResolvedQueryForm(queries: string[]) {
|
|||
}
|
||||
|
||||
test("Queries can be specified in config file", async (t) => {
|
||||
return await util.withTmpDir(async (tmpDir) => {
|
||||
return await withTmpDir(async (tmpDir) => {
|
||||
const inputFileContents = `
|
||||
name: my config
|
||||
queries:
|
||||
|
|
@ -598,7 +598,7 @@ test("Queries can be specified in config file", async (t) => {
|
|||
});
|
||||
|
||||
test("Queries from config file can be overridden in workflow file", async (t) => {
|
||||
return await util.withTmpDir(async (tmpDir) => {
|
||||
return await withTmpDir(async (tmpDir) => {
|
||||
const inputFileContents = `
|
||||
name: my config
|
||||
queries:
|
||||
|
|
@ -677,7 +677,7 @@ test("Queries from config file can be overridden in workflow file", async (t) =>
|
|||
});
|
||||
|
||||
test("Queries in workflow file can be used in tandem with the 'disable default queries' option", async (t) => {
|
||||
return await util.withTmpDir(async (tmpDir) => {
|
||||
return await withTmpDir(async (tmpDir) => {
|
||||
process.env["RUNNER_TEMP"] = tmpDir;
|
||||
process.env["GITHUB_WORKSPACE"] = tmpDir;
|
||||
|
||||
|
|
@ -751,7 +751,7 @@ test("Queries in workflow file can be used in tandem with the 'disable default q
|
|||
});
|
||||
|
||||
test("Multiple queries can be specified in workflow file, no config file required", async (t) => {
|
||||
return await util.withTmpDir(async (tmpDir) => {
|
||||
return await withTmpDir(async (tmpDir) => {
|
||||
fs.mkdirSync(path.join(tmpDir, "override1"));
|
||||
fs.mkdirSync(path.join(tmpDir, "override2"));
|
||||
|
||||
|
|
@ -829,7 +829,7 @@ test("Multiple queries can be specified in workflow file, no config file require
|
|||
});
|
||||
|
||||
test("Queries in workflow file can be added to the set of queries without overriding config file", async (t) => {
|
||||
return await util.withTmpDir(async (tmpDir) => {
|
||||
return await withTmpDir(async (tmpDir) => {
|
||||
process.env["RUNNER_TEMP"] = tmpDir;
|
||||
process.env["GITHUB_WORKSPACE"] = tmpDir;
|
||||
|
||||
|
|
@ -926,7 +926,7 @@ test("Queries in workflow file can be added to the set of queries without overri
|
|||
});
|
||||
|
||||
test("Queries can be specified using config input", async (t) => {
|
||||
return await util.withTmpDir(async (tmpDir) => {
|
||||
return await withTmpDir(async (tmpDir) => {
|
||||
const configInput = `
|
||||
name: my config
|
||||
queries:
|
||||
|
|
@ -1009,7 +1009,7 @@ test("Queries can be specified using config input", async (t) => {
|
|||
});
|
||||
|
||||
test("Using config input and file together, config input should be used.", async (t) => {
|
||||
return await util.withTmpDir(async (tmpDir) => {
|
||||
return await withTmpDir(async (tmpDir) => {
|
||||
process.env["RUNNER_TEMP"] = tmpDir;
|
||||
process.env["GITHUB_WORKSPACE"] = tmpDir;
|
||||
|
||||
|
|
@ -1101,7 +1101,7 @@ test("Using config input and file together, config input should be used.", async
|
|||
});
|
||||
|
||||
test("Invalid queries in workflow file handled correctly", async (t) => {
|
||||
return await util.withTmpDir(async (tmpDir) => {
|
||||
return await withTmpDir(async (tmpDir) => {
|
||||
const queries = "foo/bar@v1@v3";
|
||||
const languages = "javascript";
|
||||
|
||||
|
|
@ -1148,14 +1148,16 @@ test("Invalid queries in workflow file handled correctly", async (t) => {
|
|||
} catch (err) {
|
||||
t.deepEqual(
|
||||
err,
|
||||
new Error(configUtils.getQueryUsesInvalid(undefined, "foo/bar@v1@v3"))
|
||||
new UserError(
|
||||
configUtils.getQueryUsesInvalid(undefined, "foo/bar@v1@v3")
|
||||
)
|
||||
);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
test("API client used when reading remote config", async (t) => {
|
||||
return await util.withTmpDir(async (tmpDir) => {
|
||||
return await withTmpDir(async (tmpDir) => {
|
||||
const codeQL = setCodeQL({
|
||||
async resolveQueries() {
|
||||
return {
|
||||
|
|
@ -1222,7 +1224,7 @@ 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) => {
|
||||
return await withTmpDir(async (tmpDir) => {
|
||||
const dummyResponse = []; // directories are returned as arrays
|
||||
mockGetContents(dummyResponse);
|
||||
|
||||
|
|
@ -1249,18 +1251,20 @@ test("Remote config handles the case where a directory is provided", async (t) =
|
|||
createFeatures([]),
|
||||
getRunnerLogger(true)
|
||||
);
|
||||
throw new Error("initConfig did not throw error");
|
||||
throw new UserError("initConfig did not throw error");
|
||||
} catch (err) {
|
||||
t.deepEqual(
|
||||
err,
|
||||
new Error(configUtils.getConfigFileDirectoryGivenMessage(repoReference))
|
||||
new UserError(
|
||||
configUtils.getConfigFileDirectoryGivenMessage(repoReference)
|
||||
)
|
||||
);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
test("Invalid format of remote config handled correctly", async (t) => {
|
||||
return await util.withTmpDir(async (tmpDir) => {
|
||||
return await withTmpDir(async (tmpDir) => {
|
||||
const dummyResponse = {
|
||||
// note no "content" property here
|
||||
};
|
||||
|
|
@ -1289,18 +1293,20 @@ test("Invalid format of remote config handled correctly", async (t) => {
|
|||
createFeatures([]),
|
||||
getRunnerLogger(true)
|
||||
);
|
||||
throw new Error("initConfig did not throw error");
|
||||
throw new UserError("initConfig did not throw error");
|
||||
} catch (err) {
|
||||
t.deepEqual(
|
||||
err,
|
||||
new Error(configUtils.getConfigFileFormatInvalidMessage(repoReference))
|
||||
new UserError(
|
||||
configUtils.getConfigFileFormatInvalidMessage(repoReference)
|
||||
)
|
||||
);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
test("No detected languages", async (t) => {
|
||||
return await util.withTmpDir(async (tmpDir) => {
|
||||
return await withTmpDir(async (tmpDir) => {
|
||||
mockListLanguages([]);
|
||||
const codeQL = setCodeQL({
|
||||
async resolveLanguages() {
|
||||
|
|
@ -1333,15 +1339,15 @@ test("No detected languages", async (t) => {
|
|||
createFeatures([]),
|
||||
getRunnerLogger(true)
|
||||
);
|
||||
throw new Error("initConfig did not throw error");
|
||||
throw new UserError("initConfig did not throw error");
|
||||
} catch (err) {
|
||||
t.deepEqual(err, new Error(configUtils.getNoLanguagesError()));
|
||||
t.deepEqual(err, new UserError(configUtils.getNoLanguagesError()));
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
test("Unknown languages", async (t) => {
|
||||
return await util.withTmpDir(async (tmpDir) => {
|
||||
return await withTmpDir(async (tmpDir) => {
|
||||
const languages = "rubbish,english";
|
||||
|
||||
try {
|
||||
|
|
@ -1366,18 +1372,20 @@ test("Unknown languages", async (t) => {
|
|||
createFeatures([]),
|
||||
getRunnerLogger(true)
|
||||
);
|
||||
throw new Error("initConfig did not throw error");
|
||||
throw new UserError("initConfig did not throw error");
|
||||
} catch (err) {
|
||||
t.deepEqual(
|
||||
err,
|
||||
new Error(configUtils.getUnknownLanguagesError(["rubbish", "english"]))
|
||||
new UserError(
|
||||
configUtils.getUnknownLanguagesError(["rubbish", "english"])
|
||||
)
|
||||
);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
test("Config specifies packages", async (t) => {
|
||||
return await util.withTmpDir(async (tmpDir) => {
|
||||
return await withTmpDir(async (tmpDir) => {
|
||||
const codeQL = setCodeQL({
|
||||
async resolveQueries() {
|
||||
return {
|
||||
|
|
@ -1431,7 +1439,7 @@ test("Config specifies packages", async (t) => {
|
|||
});
|
||||
|
||||
test("Config specifies packages for multiple languages", async (t) => {
|
||||
return await util.withTmpDir(async (tmpDir) => {
|
||||
return await withTmpDir(async (tmpDir) => {
|
||||
const codeQL = setCodeQL({
|
||||
async resolveQueries() {
|
||||
return {
|
||||
|
|
@ -1518,7 +1526,7 @@ function doInvalidInputTest(
|
|||
expectedErrorMessageGenerator: (configFile: string) => string
|
||||
) {
|
||||
test(`load invalid input - ${testName}`, async (t) => {
|
||||
return await util.withTmpDir(async (tmpDir) => {
|
||||
return await withTmpDir(async (tmpDir) => {
|
||||
const codeQL = setCodeQL({
|
||||
async resolveQueries() {
|
||||
return {
|
||||
|
|
@ -1559,9 +1567,12 @@ function doInvalidInputTest(
|
|||
createFeatures([]),
|
||||
getRunnerLogger(true)
|
||||
);
|
||||
throw new Error("initConfig did not throw error");
|
||||
throw new UserError("initConfig did not throw error");
|
||||
} catch (err) {
|
||||
t.deepEqual(err, new Error(expectedErrorMessageGenerator(inputFile)));
|
||||
t.deepEqual(
|
||||
err,
|
||||
new UserError(expectedErrorMessageGenerator(inputFile))
|
||||
);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
|
@ -2104,7 +2115,7 @@ const mlPoweredQueriesMacro = test.macro({
|
|||
queriesInput: string | undefined,
|
||||
expectedVersionString: string | undefined
|
||||
) => {
|
||||
return await util.withTmpDir(async (tmpDir) => {
|
||||
return await withTmpDir(async (tmpDir) => {
|
||||
const codeQL = setCodeQL({
|
||||
async getVersion() {
|
||||
return codeQLVersion;
|
||||
|
|
@ -2458,7 +2469,7 @@ test(
|
|||
);
|
||||
|
||||
test("downloadPacks-no-registries", async (t) => {
|
||||
return await util.withTmpDir(async (tmpDir) => {
|
||||
return await withTmpDir(async (tmpDir) => {
|
||||
const packDownloadStub = sinon.stub();
|
||||
packDownloadStub.callsFake((packs) => ({
|
||||
packs,
|
||||
|
|
@ -2495,7 +2506,7 @@ test("downloadPacks-no-registries", async (t) => {
|
|||
test("downloadPacks-with-registries", async (t) => {
|
||||
// same thing, but this time include a registries block and
|
||||
// associated env vars
|
||||
return await util.withTmpDir(async (tmpDir) => {
|
||||
return await withTmpDir(async (tmpDir) => {
|
||||
process.env.GITHUB_TOKEN = "not-a-token";
|
||||
process.env.CODEQL_REGISTRIES_AUTH = undefined;
|
||||
const logger = getRunnerLogger(true);
|
||||
|
|
@ -2586,7 +2597,7 @@ test("downloadPacks-with-registries", async (t) => {
|
|||
test("downloadPacks-with-registries fails on 2.10.3", async (t) => {
|
||||
// same thing, but this time include a registries block and
|
||||
// associated env vars
|
||||
return await util.withTmpDir(async (tmpDir) => {
|
||||
return await withTmpDir(async (tmpDir) => {
|
||||
process.env.GITHUB_TOKEN = "not-a-token";
|
||||
process.env.CODEQL_REGISTRIES_AUTH = "not-a-registries-auth";
|
||||
const logger = getRunnerLogger(true);
|
||||
|
|
@ -2628,7 +2639,7 @@ test("downloadPacks-with-registries fails on 2.10.3", async (t) => {
|
|||
test("downloadPacks-with-registries fails with invalid registries block", async (t) => {
|
||||
// same thing, but this time include a registries block and
|
||||
// associated env vars
|
||||
return await util.withTmpDir(async (tmpDir) => {
|
||||
return await withTmpDir(async (tmpDir) => {
|
||||
process.env.GITHUB_TOKEN = "not-a-token";
|
||||
process.env.CODEQL_REGISTRIES_AUTH = "not-a-registries-auth";
|
||||
const logger = getRunnerLogger(true);
|
||||
|
|
@ -2670,7 +2681,7 @@ test("downloadPacks-with-registries fails with invalid registries block", async
|
|||
// the happy path for generateRegistries is already tested in downloadPacks.
|
||||
// these following tests are for the error cases and when nothing is generated.
|
||||
test("no generateRegistries when CLI is too old", async (t) => {
|
||||
return await util.withTmpDir(async (tmpDir) => {
|
||||
return await withTmpDir(async (tmpDir) => {
|
||||
const registriesInput = yaml.dump([
|
||||
{
|
||||
// no slash
|
||||
|
|
@ -2698,7 +2709,7 @@ test("no generateRegistries when CLI is too old", async (t) => {
|
|||
});
|
||||
});
|
||||
test("no generateRegistries when registries is undefined", async (t) => {
|
||||
return await util.withTmpDir(async (tmpDir) => {
|
||||
return await withTmpDir(async (tmpDir) => {
|
||||
const registriesInput = undefined;
|
||||
const codeQL = setCodeQL({
|
||||
// Accepted CLI versions are 2.10.4 or higher
|
||||
|
|
@ -2719,7 +2730,7 @@ test("no generateRegistries when registries is undefined", async (t) => {
|
|||
});
|
||||
|
||||
test("generateRegistries prefers original CODEQL_REGISTRIES_AUTH", async (t) => {
|
||||
return await util.withTmpDir(async (tmpDir) => {
|
||||
return await withTmpDir(async (tmpDir) => {
|
||||
process.env.CODEQL_REGISTRIES_AUTH = "original";
|
||||
const registriesInput = yaml.dump([
|
||||
{
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@ import {
|
|||
logCodeScanningConfigInCli,
|
||||
ML_POWERED_JS_QUERIES_PACK_NAME,
|
||||
useCodeScanningConfigInCli,
|
||||
UserError,
|
||||
} from "./util";
|
||||
|
||||
// Property names from the user-supplied config file.
|
||||
|
|
@ -300,7 +301,7 @@ function validateQueries(resolvedQueries: ResolveQueriesOutput) {
|
|||
const noDeclaredLanguage = resolvedQueries.noDeclaredLanguage;
|
||||
const noDeclaredLanguageQueries = Object.keys(noDeclaredLanguage);
|
||||
if (noDeclaredLanguageQueries.length !== 0) {
|
||||
throw new Error(
|
||||
throw new UserError(
|
||||
`${
|
||||
"The following queries do not declare a language. " +
|
||||
"Their qlpack.yml files are either missing or is invalid.\n"
|
||||
|
|
@ -313,7 +314,7 @@ function validateQueries(resolvedQueries: ResolveQueriesOutput) {
|
|||
multipleDeclaredLanguages
|
||||
);
|
||||
if (multipleDeclaredLanguagesQueries.length !== 0) {
|
||||
throw new Error(
|
||||
throw new UserError(
|
||||
`${
|
||||
"The following queries declare multiple languages. " +
|
||||
"Their qlpack.yml files are either missing or is invalid.\n"
|
||||
|
|
@ -404,7 +405,7 @@ async function addBuiltinSuiteQueries(
|
|||
let injectedMlQueries = false;
|
||||
const found = builtinSuites.find((suite) => suite === suiteName);
|
||||
if (!found) {
|
||||
throw new Error(getQueryUsesInvalid(configFile, suiteName));
|
||||
throw new UserError(getQueryUsesInvalid(configFile, suiteName));
|
||||
}
|
||||
if (
|
||||
suiteName === "security-experimental" &&
|
||||
|
|
@ -413,7 +414,7 @@ async function addBuiltinSuiteQueries(
|
|||
CODEQL_VERSION_SECURITY_EXPERIMENTAL_SUITE
|
||||
))
|
||||
) {
|
||||
throw new Error(
|
||||
throw new UserError(
|
||||
`The 'security-experimental' suite is not supported on CodeQL CLI versions earlier than
|
||||
${CODEQL_VERSION_SECURITY_EXPERIMENTAL_SUITE}. Please upgrade to CodeQL CLI version
|
||||
${CODEQL_VERSION_SECURITY_EXPERIMENTAL_SUITE} or later.`
|
||||
|
|
@ -469,7 +470,7 @@ async function addLocalQueries(
|
|||
|
||||
// Check the file exists
|
||||
if (!fs.existsSync(absoluteQueryPath)) {
|
||||
throw new Error(getLocalPathDoesNotExist(configFile, localQueryPath));
|
||||
throw new UserError(getLocalPathDoesNotExist(configFile, localQueryPath));
|
||||
}
|
||||
|
||||
// Call this after checking file exists, because it'll fail if file doesn't exist
|
||||
|
|
@ -481,7 +482,7 @@ async function addLocalQueries(
|
|||
fs.realpathSync(workspacePath) + path.sep
|
||||
)
|
||||
) {
|
||||
throw new Error(
|
||||
throw new UserError(
|
||||
getLocalPathOutsideOfRepository(configFile, localQueryPath)
|
||||
);
|
||||
}
|
||||
|
|
@ -510,7 +511,7 @@ async function addRemoteQueries(
|
|||
) {
|
||||
let tok = queryUses.split("@");
|
||||
if (tok.length !== 2) {
|
||||
throw new Error(getQueryUsesInvalid(configFile, queryUses));
|
||||
throw new UserError(getQueryUsesInvalid(configFile, queryUses));
|
||||
}
|
||||
|
||||
const ref = tok[1];
|
||||
|
|
@ -520,11 +521,11 @@ async function addRemoteQueries(
|
|||
// The second token is the repo
|
||||
// The rest is a path, if there is more than one token combine them to form the full path
|
||||
if (tok.length < 2) {
|
||||
throw new Error(getQueryUsesInvalid(configFile, queryUses));
|
||||
throw new UserError(getQueryUsesInvalid(configFile, queryUses));
|
||||
}
|
||||
// Check none of the parts of the repository name are empty
|
||||
if (tok[0].trim() === "" || tok[1].trim() === "") {
|
||||
throw new Error(getQueryUsesInvalid(configFile, queryUses));
|
||||
throw new UserError(getQueryUsesInvalid(configFile, queryUses));
|
||||
}
|
||||
const nwo = `${tok[0]}/${tok[1]}`;
|
||||
|
||||
|
|
@ -573,7 +574,7 @@ async function parseQueryUses(
|
|||
): Promise<boolean> {
|
||||
queryUses = queryUses.trim();
|
||||
if (queryUses === "") {
|
||||
throw new Error(getQueryUsesInvalid(configFile));
|
||||
throw new UserError(getQueryUsesInvalid(configFile));
|
||||
}
|
||||
|
||||
// Check for the local path case before we start trying to parse the repository name
|
||||
|
|
@ -650,7 +651,7 @@ export function validateAndSanitisePath(
|
|||
|
||||
// An empty path is not allowed as it's meaningless
|
||||
if (newPath === "") {
|
||||
throw new Error(
|
||||
throw new UserError(
|
||||
getConfigFilePropertyError(
|
||||
configFile,
|
||||
propertyName,
|
||||
|
|
@ -662,7 +663,7 @@ export function validateAndSanitisePath(
|
|||
|
||||
// Check for illegal uses of **
|
||||
if (newPath.match(pathStarsRegex)) {
|
||||
throw new Error(
|
||||
throw new UserError(
|
||||
getConfigFilePropertyError(
|
||||
configFile,
|
||||
propertyName,
|
||||
|
|
@ -689,7 +690,7 @@ export function validateAndSanitisePath(
|
|||
// This may not play nicely with project layouts.
|
||||
// This restriction can be lifted later if we determine they are ok.
|
||||
if (newPath.indexOf("\\") !== -1) {
|
||||
throw new Error(
|
||||
throw new UserError(
|
||||
getConfigFilePropertyError(
|
||||
configFile,
|
||||
propertyName,
|
||||
|
|
@ -945,7 +946,7 @@ export async function getLanguages(
|
|||
// If the languages parameter was not given and no languages were
|
||||
// detected then fail here as this is a workflow configuration error.
|
||||
if (languages.length === 0) {
|
||||
throw new Error(getNoLanguagesError());
|
||||
throw new UserError(getNoLanguagesError());
|
||||
}
|
||||
|
||||
// Make sure they are supported
|
||||
|
|
@ -964,7 +965,7 @@ export async function getLanguages(
|
|||
// Any unknown languages here would have come directly from the input
|
||||
// since we filter unknown languages coming from the GitHub API.
|
||||
if (unknownLanguages.length > 0) {
|
||||
throw new Error(getUnknownLanguagesError(unknownLanguages));
|
||||
throw new UserError(getUnknownLanguagesError(unknownLanguages));
|
||||
}
|
||||
|
||||
return parsedLanguages;
|
||||
|
|
@ -1193,10 +1194,10 @@ async function loadConfig(
|
|||
// even though we don't use the value yet.
|
||||
if (NAME_PROPERTY in parsedYAML) {
|
||||
if (typeof parsedYAML[NAME_PROPERTY] !== "string") {
|
||||
throw new Error(getNameInvalid(configFile));
|
||||
throw new UserError(getNameInvalid(configFile));
|
||||
}
|
||||
if (parsedYAML[NAME_PROPERTY]!.length === 0) {
|
||||
throw new Error(getNameInvalid(configFile));
|
||||
throw new UserError(getNameInvalid(configFile));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1220,7 +1221,7 @@ async function loadConfig(
|
|||
let disableDefaultQueries = false;
|
||||
if (DISABLE_DEFAULT_QUERIES_PROPERTY in parsedYAML) {
|
||||
if (typeof parsedYAML[DISABLE_DEFAULT_QUERIES_PROPERTY] !== "boolean") {
|
||||
throw new Error(getDisableDefaultQueriesInvalid(configFile));
|
||||
throw new UserError(getDisableDefaultQueriesInvalid(configFile));
|
||||
}
|
||||
disableDefaultQueries = parsedYAML[DISABLE_DEFAULT_QUERIES_PROPERTY]!;
|
||||
}
|
||||
|
|
@ -1266,11 +1267,11 @@ async function loadConfig(
|
|||
) {
|
||||
const queriesArr = parsedYAML[QUERIES_PROPERTY];
|
||||
if (!Array.isArray(queriesArr)) {
|
||||
throw new Error(getQueriesInvalid(configFile));
|
||||
throw new UserError(getQueriesInvalid(configFile));
|
||||
}
|
||||
for (const query of queriesArr) {
|
||||
if (typeof query[QUERIES_USES_PROPERTY] !== "string") {
|
||||
throw new Error(getQueriesMissingUses(configFile));
|
||||
throw new UserError(getQueriesMissingUses(configFile));
|
||||
}
|
||||
await parseQueryUses(
|
||||
languages,
|
||||
|
|
@ -1290,11 +1291,11 @@ async function loadConfig(
|
|||
|
||||
if (PATHS_IGNORE_PROPERTY in parsedYAML) {
|
||||
if (!Array.isArray(parsedYAML[PATHS_IGNORE_PROPERTY])) {
|
||||
throw new Error(getPathsIgnoreInvalid(configFile));
|
||||
throw new UserError(getPathsIgnoreInvalid(configFile));
|
||||
}
|
||||
for (const ignorePath of parsedYAML[PATHS_IGNORE_PROPERTY]!) {
|
||||
if (typeof ignorePath !== "string" || ignorePath === "") {
|
||||
throw new Error(getPathsIgnoreInvalid(configFile));
|
||||
throw new UserError(getPathsIgnoreInvalid(configFile));
|
||||
}
|
||||
pathsIgnore.push(
|
||||
validateAndSanitisePath(
|
||||
|
|
@ -1309,11 +1310,11 @@ async function loadConfig(
|
|||
|
||||
if (PATHS_PROPERTY in parsedYAML) {
|
||||
if (!Array.isArray(parsedYAML[PATHS_PROPERTY])) {
|
||||
throw new Error(getPathsInvalid(configFile));
|
||||
throw new UserError(getPathsInvalid(configFile));
|
||||
}
|
||||
for (const includePath of parsedYAML[PATHS_PROPERTY]!) {
|
||||
if (typeof includePath !== "string" || includePath === "") {
|
||||
throw new Error(getPathsInvalid(configFile));
|
||||
throw new UserError(getPathsInvalid(configFile));
|
||||
}
|
||||
paths.push(
|
||||
validateAndSanitisePath(includePath, PATHS_PROPERTY, configFile, logger)
|
||||
|
|
@ -1405,7 +1406,7 @@ function parseQueriesFromInput(
|
|||
? rawQueriesInput.trim().slice(1).trim()
|
||||
: rawQueriesInput?.trim() ?? "";
|
||||
if (queriesInputCombines && trimmedInput.length === 0) {
|
||||
throw new Error(
|
||||
throw new UserError(
|
||||
getConfigFilePropertyError(
|
||||
undefined,
|
||||
"queries",
|
||||
|
|
@ -1445,13 +1446,13 @@ export function parsePacksFromConfig(
|
|||
} else {
|
||||
// this is an error since multi-language analysis requires
|
||||
// packs split by language
|
||||
throw new Error(getPacksInvalidSplit(configFile));
|
||||
throw new UserError(getPacksInvalidSplit(configFile));
|
||||
}
|
||||
}
|
||||
|
||||
for (const [lang, packsArr] of Object.entries(packsByLanguage)) {
|
||||
if (!Array.isArray(packsArr)) {
|
||||
throw new Error(getPacksInvalid(configFile));
|
||||
throw new UserError(getPacksInvalid(configFile));
|
||||
}
|
||||
if (!languages.includes(lang as Language)) {
|
||||
// This particular language is not being analyzed in this run.
|
||||
|
|
@ -1462,7 +1463,7 @@ export function parsePacksFromConfig(
|
|||
continue;
|
||||
} else {
|
||||
// This language is invalid, probably a misspelling
|
||||
throw new Error(getPacksRequireLanguage(configFile, lang));
|
||||
throw new UserError(getPacksRequireLanguage(configFile, lang));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1483,18 +1484,20 @@ function parsePacksFromInput(
|
|||
}
|
||||
|
||||
if (languages.length > 1) {
|
||||
throw new Error(
|
||||
throw new UserError(
|
||||
"Cannot specify a 'packs' input in a multi-language analysis. Use a codeql-config.yml file instead and specify packs by language."
|
||||
);
|
||||
} else if (languages.length === 0) {
|
||||
throw new Error("No languages specified. Cannot process the packs input.");
|
||||
throw new UserError(
|
||||
"No languages specified. Cannot process the packs input."
|
||||
);
|
||||
}
|
||||
|
||||
rawPacksInput = rawPacksInput.trim();
|
||||
if (packsInputCombines) {
|
||||
rawPacksInput = rawPacksInput.trim().substring(1).trim();
|
||||
if (!rawPacksInput) {
|
||||
throw new Error(
|
||||
throw new UserError(
|
||||
getConfigFilePropertyError(
|
||||
undefined,
|
||||
"packs",
|
||||
|
|
@ -1535,7 +1538,7 @@ export function parsePacksSpecification(
|
|||
configFile?: string
|
||||
): Pack {
|
||||
if (typeof packStr !== "string") {
|
||||
throw new Error(getPacksStrInvalid(packStr, configFile));
|
||||
throw new UserError(getPacksStrInvalid(packStr, configFile));
|
||||
}
|
||||
|
||||
packStr = packStr.trim();
|
||||
|
|
@ -1563,14 +1566,14 @@ export function parsePacksSpecification(
|
|||
: undefined;
|
||||
|
||||
if (!PACK_IDENTIFIER_PATTERN.test(packName)) {
|
||||
throw new Error(getPacksStrInvalid(packStr, configFile));
|
||||
throw new UserError(getPacksStrInvalid(packStr, configFile));
|
||||
}
|
||||
if (version) {
|
||||
try {
|
||||
new semver.Range(version);
|
||||
} catch (e) {
|
||||
// The range string is invalid. OK to ignore the caught error
|
||||
throw new Error(getPacksStrInvalid(packStr, configFile));
|
||||
throw new UserError(getPacksStrInvalid(packStr, configFile));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1584,12 +1587,12 @@ export function parsePacksSpecification(
|
|||
path.normalize(packPath).split(path.sep).join("/") !==
|
||||
packPath.split(path.sep).join("/"))
|
||||
) {
|
||||
throw new Error(getPacksStrInvalid(packStr, configFile));
|
||||
throw new UserError(getPacksStrInvalid(packStr, configFile));
|
||||
}
|
||||
|
||||
if (!packPath && pathStart) {
|
||||
// 0 length path
|
||||
throw new Error(getPacksStrInvalid(packStr, configFile));
|
||||
throw new UserError(getPacksStrInvalid(packStr, configFile));
|
||||
}
|
||||
|
||||
return {
|
||||
|
|
@ -1635,7 +1638,7 @@ export function parsePacks(
|
|||
}
|
||||
if (!packsInputCombines) {
|
||||
if (!packsFromInput) {
|
||||
throw new Error(getPacksInvalid(configFile));
|
||||
throw new UserError(getPacksInvalid(configFile));
|
||||
}
|
||||
return packsFromInput;
|
||||
}
|
||||
|
|
@ -1775,7 +1778,7 @@ export async function initConfig(
|
|||
const hasCustomQueries = config.queries[language]?.custom.length > 0;
|
||||
const hasPacks = (config.packs[language]?.length || 0) > 0;
|
||||
if (!hasPacks && !hasBuiltinQueries && !hasCustomQueries) {
|
||||
throw new Error(
|
||||
throw new UserError(
|
||||
`Did not detect any queries to run for ${language}. ` +
|
||||
"Please make sure that the default queries are enabled, or you are specifying queries to run."
|
||||
);
|
||||
|
|
@ -1806,7 +1809,7 @@ function parseRegistries(
|
|||
? (yaml.load(registriesInput) as RegistryConfigWithCredentials[])
|
||||
: undefined;
|
||||
} catch (e) {
|
||||
throw new Error("Invalid registries input. Must be a YAML string.");
|
||||
throw new UserError("Invalid registries input. Must be a YAML string.");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1822,12 +1825,12 @@ function isLocal(configPath: string): boolean {
|
|||
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)) {
|
||||
throw new Error(getConfigFileOutsideWorkspaceErrorMessage(configFile));
|
||||
throw new UserError(getConfigFileOutsideWorkspaceErrorMessage(configFile));
|
||||
}
|
||||
|
||||
// Error if the file does not exist
|
||||
if (!fs.existsSync(configFile)) {
|
||||
throw new Error(getConfigFileDoesNotExistErrorMessage(configFile));
|
||||
throw new UserError(getConfigFileDoesNotExistErrorMessage(configFile));
|
||||
}
|
||||
|
||||
return yaml.load(fs.readFileSync(configFile, "utf8")) as UserConfig;
|
||||
|
|
@ -1844,7 +1847,7 @@ async function getRemoteConfig(
|
|||
const pieces = format.exec(configFile);
|
||||
// 5 = 4 groups + the whole expression
|
||||
if (pieces === null || pieces.groups === undefined || pieces.length < 5) {
|
||||
throw new Error(getConfigFileRepoFormatInvalidMessage(configFile));
|
||||
throw new UserError(getConfigFileRepoFormatInvalidMessage(configFile));
|
||||
}
|
||||
|
||||
const response = await api
|
||||
|
|
@ -1860,9 +1863,9 @@ async function getRemoteConfig(
|
|||
if ("content" in response.data && response.data.content !== undefined) {
|
||||
fileContents = response.data.content;
|
||||
} else if (Array.isArray(response.data)) {
|
||||
throw new Error(getConfigFileDirectoryGivenMessage(configFile));
|
||||
throw new UserError(getConfigFileDirectoryGivenMessage(configFile));
|
||||
} else {
|
||||
throw new Error(getConfigFileFormatInvalidMessage(configFile));
|
||||
throw new UserError(getConfigFileFormatInvalidMessage(configFile));
|
||||
}
|
||||
|
||||
return yaml.load(
|
||||
|
|
@ -1986,7 +1989,7 @@ export async function generateRegistries(
|
|||
if (
|
||||
!(await codeQlVersionAbove(codeQL, CODEQL_VERSION_GHES_PACK_DOWNLOAD))
|
||||
) {
|
||||
throw new Error(
|
||||
throw new UserError(
|
||||
`The 'registries' input is not supported on CodeQL CLI versions earlier than ${CODEQL_VERSION_GHES_PACK_DOWNLOAD}. Please upgrade to CodeQL CLI version ${CODEQL_VERSION_GHES_PACK_DOWNLOAD} or later.`
|
||||
);
|
||||
}
|
||||
|
|
@ -2025,7 +2028,7 @@ function createRegistriesBlock(registries: RegistryConfigWithCredentials[]): {
|
|||
!Array.isArray(registries) ||
|
||||
registries.some((r) => !r.url || !r.packages)
|
||||
) {
|
||||
throw new Error(
|
||||
throw new UserError(
|
||||
"Invalid 'registries' input. Must be an array of objects with 'url' and 'packages' properties."
|
||||
);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue