Log validation errors

This commit is contained in:
Michael B. Gale
2025-10-14 18:48:05 +01:00
parent 913cd47984
commit 0822fb12e7
4 changed files with 67 additions and 13 deletions

View File

@@ -526,6 +526,7 @@ async function downloadCacheWithTime(
}
async function loadUserConfig(
logger: Logger,
configFile: string,
workspacePath: string,
apiDetails: api.GitHubApiCombinedDetails,
@@ -542,9 +543,9 @@ async function loadUserConfig(
);
}
}
return getLocalConfig(configFile);
return getLocalConfig(logger, configFile);
} else {
return await getRemoteConfig(configFile, apiDetails);
return await getRemoteConfig(logger, configFile, apiDetails);
}
}
@@ -801,6 +802,7 @@ export async function initConfig(inputs: InitConfigInputs): Promise<Config> {
} else {
logger.debug(`Using configuration file: ${inputs.configFile}`);
userConfig = await loadUserConfig(
logger,
inputs.configFile,
inputs.workspacePath,
inputs.apiDetails,
@@ -898,7 +900,7 @@ function isLocal(configPath: string): boolean {
return configPath.indexOf("@") === -1;
}
function getLocalConfig(configFile: string): UserConfig {
function getLocalConfig(logger: Logger, configFile: string): UserConfig {
// Error if the file does not exist
if (!fs.existsSync(configFile)) {
throw new ConfigurationError(
@@ -906,10 +908,15 @@ function getLocalConfig(configFile: string): UserConfig {
);
}
return parseUserConfig(configFile, fs.readFileSync(configFile, "utf-8"));
return parseUserConfig(
logger,
configFile,
fs.readFileSync(configFile, "utf-8"),
);
}
async function getRemoteConfig(
logger: Logger,
configFile: string,
apiDetails: api.GitHubApiCombinedDetails,
): Promise<UserConfig> {
@@ -948,6 +955,7 @@ async function getRemoteConfig(
}
return parseUserConfig(
logger,
configFile,
Buffer.from(fileContents, "base64").toString("binary"),
);

View File

@@ -2,6 +2,12 @@ import test, { ExecutionContext } from "ava";
import { RepositoryProperties } from "../feature-flags/properties";
import { KnownLanguage, Language } from "../languages";
import { getRunnerLogger } from "../logging";
import {
checkExpectedLogMessages,
getRecordingLogger,
LoggedMessage,
} from "../testing-utils";
import { ConfigurationError, prettyPrintPack } from "../util";
import * as dbConfig from "./db-config";
@@ -394,6 +400,7 @@ test(
test("parseUserConfig - successfully parses valid YAML", (t) => {
const result = dbConfig.parseUserConfig(
getRunnerLogger(true),
"test",
`
paths-ignore:
@@ -418,6 +425,7 @@ test("parseUserConfig - throws a ConfigurationError if the file is not valid YAM
t.throws(
() =>
dbConfig.parseUserConfig(
getRunnerLogger(true),
"test",
`
paths-ignore:
@@ -431,3 +439,27 @@ test("parseUserConfig - throws a ConfigurationError if the file is not valid YAM
},
);
});
test("parseUserConfig - throws a ConfigurationError if validation fails", (t) => {
const loggedMessages: LoggedMessage[] = [];
const logger = getRecordingLogger(loggedMessages);
t.throws(
() =>
dbConfig.parseUserConfig(
logger,
"test",
`
paths-ignore:
- "some/path"
queries: true
`,
),
{
instanceOf: ConfigurationError,
},
);
const expectedMessages = ["instance.queries is not of a type(s) array"];
checkExpectedLogMessages(t, loggedMessages, expectedMessages);
});

View File

@@ -480,12 +480,14 @@ export function generateCodeScanningConfig(
/**
* Attempts to parse `contents` into a `UserConfig` value.
*
* @param logger The logger to use.
* @param pathInput The path to the file where `contents` was obtained from, for use in error messages.
* @param contents The string contents of a YAML file to try and parse as a `UserConfig`.
* @returns The `UserConfig` corresponding to `contents`, if parsing was successful.
* @throws A `ConfigurationError` if parsing failed.
*/
export function parseUserConfig(
logger: Logger,
pathInput: string,
contents: string,
): UserConfig {
@@ -498,10 +500,13 @@ export function parseUserConfig(
const result = new jsonschema.Validator().validate(doc, schema);
if (result.errors.length > 0) {
for (const error of result.errors) {
logger.error(error.stack);
}
throw new ConfigurationError(
errorMessages.getInvalidConfigFileMessage(
pathInput,
`The configuration file contained ${result.errors.length} error(s)`,
`There are ${result.errors.length} error(s)`,
),
);
}