From 6222edff533ea2a7b699f4f4480698aed2422ac5 Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Fri, 19 Sep 2025 16:44:07 +0100 Subject: [PATCH] Move error messages from `config-utils` to their own file --- lib/init-action.js | 86 ++++++++++++++++++--------------- src/config-utils.test.ts | 23 ++++----- src/config-utils.ts | 102 ++++++++------------------------------- src/error-messages.ts | 66 +++++++++++++++++++++++++ 4 files changed, 143 insertions(+), 134 deletions(-) create mode 100644 src/error-messages.ts diff --git a/lib/init-action.js b/lib/init-action.js index fe8a41dca..425744f53 100644 --- a/lib/init-action.js +++ b/lib/init-action.js @@ -87045,6 +87045,46 @@ async function getDiffInformedAnalysisBranches(codeql, features, logger) { return branches; } +// src/error-messages.ts +var PACKS_PROPERTY = "packs"; +function getConfigFileOutsideWorkspaceErrorMessage(configFile) { + return `The configuration file "${configFile}" is outside of the workspace`; +} +function getConfigFileDoesNotExistErrorMessage(configFile) { + return `The configuration file "${configFile}" does not exist`; +} +function getConfigFileRepoFormatInvalidMessage(configFile) { + let error2 = `The configuration file "${configFile}" is not a supported remote file reference.`; + error2 += " Expected format //@"; + return error2; +} +function getConfigFileFormatInvalidMessage(configFile) { + return `The configuration file "${configFile}" could not be read`; +} +function getConfigFileDirectoryGivenMessage(configFile) { + return `The configuration file "${configFile}" looks like a directory, not a file`; +} +function getConfigFilePropertyError(configFile, property, error2) { + if (configFile === void 0) { + return `The workflow property "${property}" is invalid: ${error2}`; + } else { + return `The configuration file "${configFile}" is invalid: property "${property}" ${error2}`; + } +} +function getPacksStrInvalid(packStr, configFile) { + return configFile ? getConfigFilePropertyError( + configFile, + PACKS_PROPERTY, + `"${packStr}" is not a valid pack` + ) : `"${packStr}" is not a valid pack`; +} +function getNoLanguagesError() { + return "Did not detect any languages to analyze. Please update input in workflow or check that GitHub detects the correct languages in your repository."; +} +function getUnknownLanguagesError(languages) { + return `Did not recognize the following languages: ${languages.join(", ")}`; +} + // src/languages.ts var KnownLanguage = /* @__PURE__ */ ((KnownLanguage2) => { KnownLanguage2["actions"] = "actions"; @@ -87170,44 +87210,6 @@ async function cachePrefix(codeql, language) { } // src/config-utils.ts -var PACKS_PROPERTY = "packs"; -function getPacksStrInvalid(packStr, configFile) { - return configFile ? getConfigFilePropertyError( - configFile, - PACKS_PROPERTY, - `"${packStr}" is not a valid pack` - ) : `"${packStr}" is not a valid pack`; -} -function getConfigFileOutsideWorkspaceErrorMessage(configFile) { - return `The configuration file "${configFile}" is outside of the workspace`; -} -function getConfigFileDoesNotExistErrorMessage(configFile) { - return `The configuration file "${configFile}" does not exist`; -} -function getConfigFileRepoFormatInvalidMessage(configFile) { - let error2 = `The configuration file "${configFile}" is not a supported remote file reference.`; - error2 += " Expected format //@"; - return error2; -} -function getConfigFileFormatInvalidMessage(configFile) { - return `The configuration file "${configFile}" could not be read`; -} -function getConfigFileDirectoryGivenMessage(configFile) { - return `The configuration file "${configFile}" looks like a directory, not a file`; -} -function getConfigFilePropertyError(configFile, property, error2) { - if (configFile === void 0) { - return `The workflow property "${property}" is invalid: ${error2}`; - } else { - return `The configuration file "${configFile}" is invalid: property "${property}" ${error2}`; - } -} -function getNoLanguagesError() { - return "Did not detect any languages to analyze. Please update input in workflow or check that GitHub detects the correct languages in your repository."; -} -function getUnknownLanguagesError(languages) { - return `Did not recognize the following languages: ${languages.join(", ")}`; -} async function getSupportedLanguageMap(codeql, features, logger) { const resolveSupportedLanguagesUsingCli = await features.getValue( "resolve_supported_languages_using_cli" /* ResolveSupportedLanguagesUsingCli */, @@ -87279,7 +87281,9 @@ async function getLanguages(codeql, languagesInput, repository, sourceRoot, feat } const languages = Array.from(languagesSet); if (!autodetected && unknownLanguages.length > 0) { - throw new ConfigurationError(getUnknownLanguagesError(unknownLanguages)); + throw new ConfigurationError( + getUnknownLanguagesError(unknownLanguages) + ); } if (languages.length === 0) { throw new ConfigurationError(getNoLanguagesError()); @@ -87766,7 +87770,9 @@ async function getRemoteConfig(configFile, apiDetails) { getConfigFileDirectoryGivenMessage(configFile) ); } else { - throw new ConfigurationError(getConfigFileFormatInvalidMessage(configFile)); + throw new ConfigurationError( + getConfigFileFormatInvalidMessage(configFile) + ); } return load( Buffer.from(fileContents, "base64").toString("binary") diff --git a/src/config-utils.test.ts b/src/config-utils.test.ts index b5ef77717..9722d82da 100644 --- a/src/config-utils.test.ts +++ b/src/config-utils.test.ts @@ -12,6 +12,7 @@ import * as api from "./api-client"; import { CachingKind } from "./caching-utils"; import { createStubCodeQL } from "./codeql"; import * as configUtils from "./config-utils"; +import * as errorMessages from "./error-messages"; import { Feature } from "./feature-flags"; import * as gitUtils from "./git-utils"; import { KnownLanguage, Language } from "./languages"; @@ -341,7 +342,7 @@ test("load input outside of workspace", async (t) => { t.deepEqual( err, new ConfigurationError( - configUtils.getConfigFileOutsideWorkspaceErrorMessage( + errorMessages.getConfigFileOutsideWorkspaceErrorMessage( path.join(tempDir, "../input"), ), ), @@ -368,7 +369,7 @@ test("load non-local input with invalid repo syntax", async (t) => { t.deepEqual( err, new ConfigurationError( - configUtils.getConfigFileRepoFormatInvalidMessage( + errorMessages.getConfigFileRepoFormatInvalidMessage( "octo-org/codeql-config@main", ), ), @@ -397,7 +398,7 @@ test("load non-existent input", async (t) => { t.deepEqual( err, new ConfigurationError( - configUtils.getConfigFileDoesNotExistErrorMessage( + errorMessages.getConfigFileDoesNotExistErrorMessage( path.join(tempDir, "input"), ), ), @@ -604,7 +605,7 @@ test("Remote config handles the case where a directory is provided", async (t) = t.deepEqual( err, new ConfigurationError( - configUtils.getConfigFileDirectoryGivenMessage(repoReference), + errorMessages.getConfigFileDirectoryGivenMessage(repoReference), ), ); } @@ -632,7 +633,7 @@ test("Invalid format of remote config handled correctly", async (t) => { t.deepEqual( err, new ConfigurationError( - configUtils.getConfigFileFormatInvalidMessage(repoReference), + errorMessages.getConfigFileFormatInvalidMessage(repoReference), ), ); } @@ -660,7 +661,7 @@ test("No detected languages", async (t) => { } catch (err) { t.deepEqual( err, - new ConfigurationError(configUtils.getNoLanguagesError()), + new ConfigurationError(errorMessages.getNoLanguagesError()), ); } }); @@ -683,7 +684,7 @@ test("Unknown languages", async (t) => { t.deepEqual( err, new ConfigurationError( - configUtils.getUnknownLanguagesError(["rubbish", "english"]), + errorMessages.getUnknownLanguagesError(["rubbish", "english"]), ), ); } @@ -1097,28 +1098,28 @@ const mockRepositoryNwo = parseRepositoryNwo("owner/repo"); languagesInput: "", languagesInRepository: ["html"], expectedApiCall: true, - expectedError: configUtils.getNoLanguagesError(), + expectedError: errorMessages.getNoLanguagesError(), }, { name: "no languages", languagesInput: "", languagesInRepository: [], expectedApiCall: true, - expectedError: configUtils.getNoLanguagesError(), + expectedError: errorMessages.getNoLanguagesError(), }, { name: "unrecognized languages from input", languagesInput: "a, b, c, javascript", languagesInRepository: [], expectedApiCall: false, - expectedError: configUtils.getUnknownLanguagesError(["a", "b"]), + expectedError: errorMessages.getUnknownLanguagesError(["a", "b"]), }, { name: "extractors that aren't languages aren't included (specified)", languagesInput: "html", languagesInRepository: [], expectedApiCall: false, - expectedError: configUtils.getUnknownLanguagesError(["html"]), + expectedError: errorMessages.getUnknownLanguagesError(["html"]), }, { name: "extractors that aren't languages aren't included (autodetected)", diff --git a/src/config-utils.ts b/src/config-utils.ts index 574b27528..d113dafcc 100644 --- a/src/config-utils.ts +++ b/src/config-utils.ts @@ -19,6 +19,7 @@ import { CachingKind, getCachingKind } from "./caching-utils"; import { type CodeQL } from "./codeql"; import { ExcludeQueryFilter, UserConfig } from "./config/db-config"; import { shouldPerformDiffInformedAnalysis } from "./diff-informed-analysis-utils"; +import * as errorMessages from "./error-messages"; import { Feature, FeatureEnablement } from "./feature-flags"; import { getGitRoot, isAnalyzingDefaultBranch } from "./git-utils"; import { KnownLanguage, Language } from "./languages"; @@ -41,10 +42,6 @@ import { export * from "./config/db-config"; -// Property names from the user-supplied config file. - -const PACKS_PROPERTY = "packs"; - export type RegistryConfigWithCredentials = RegistryConfigNoCredentials & { // Token to use when downloading packs from this registry. token: string; @@ -219,71 +216,6 @@ export interface Pack { path?: string; } -export function getPacksStrInvalid( - packStr: string, - configFile?: string, -): string { - return configFile - ? getConfigFilePropertyError( - configFile, - PACKS_PROPERTY, - `"${packStr}" is not a valid pack`, - ) - : `"${packStr}" is not a valid pack`; -} - -export function getConfigFileOutsideWorkspaceErrorMessage( - configFile: string, -): string { - return `The configuration file "${configFile}" is outside of the workspace`; -} - -export function getConfigFileDoesNotExistErrorMessage( - configFile: string, -): string { - return `The configuration file "${configFile}" does not exist`; -} - -export function getConfigFileRepoFormatInvalidMessage( - configFile: string, -): string { - let error = `The configuration file "${configFile}" is not a supported remote file reference.`; - error += " Expected format //@"; - - return error; -} - -export function getConfigFileFormatInvalidMessage(configFile: string): string { - return `The configuration file "${configFile}" could not be read`; -} - -export function getConfigFileDirectoryGivenMessage(configFile: string): string { - return `The configuration file "${configFile}" looks like a directory, not a file`; -} - -function getConfigFilePropertyError( - configFile: string | undefined, - property: string, - error: string, -): string { - if (configFile === undefined) { - return `The workflow property "${property}" is invalid: ${error}`; - } else { - return `The configuration file "${configFile}" is invalid: property "${property}" ${error}`; - } -} - -export function getNoLanguagesError(): string { - return ( - "Did not detect any languages to analyze. " + - "Please update input in workflow or check that GitHub detects the correct languages in your repository." - ); -} - -export function getUnknownLanguagesError(languages: string[]): string { - return `Did not recognize the following languages: ${languages.join(", ")}`; -} - export async function getSupportedLanguageMap( codeql: CodeQL, features: FeatureEnablement, @@ -420,13 +352,15 @@ export async function getLanguages( const languages = Array.from(languagesSet); if (!autodetected && unknownLanguages.length > 0) { - throw new ConfigurationError(getUnknownLanguagesError(unknownLanguages)); + throw new ConfigurationError( + errorMessages.getUnknownLanguagesError(unknownLanguages), + ); } // 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 ConfigurationError(getNoLanguagesError()); + throw new ConfigurationError(errorMessages.getNoLanguagesError()); } if (autodetected) { @@ -636,7 +570,7 @@ async function loadUserConfig( // Error if the config file is now outside of the workspace if (!(configFile + path.sep).startsWith(workspacePath + path.sep)) { throw new ConfigurationError( - getConfigFileOutsideWorkspaceErrorMessage(configFile), + errorMessages.getConfigFileOutsideWorkspaceErrorMessage(configFile), ); } } @@ -703,7 +637,7 @@ function parseQueriesFromInput( : (rawQueriesInput?.trim() ?? ""); if (queriesInputCombines && trimmedInput.length === 0) { throw new ConfigurationError( - getConfigFilePropertyError( + errorMessages.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.", @@ -944,7 +878,7 @@ export function parsePacksFromInput( rawPacksInput = rawPacksInput.trim().substring(1).trim(); if (!rawPacksInput) { throw new ConfigurationError( - getConfigFilePropertyError( + errorMessages.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.", @@ -981,7 +915,7 @@ export function parsePacksFromInput( */ export function parsePacksSpecification(packStr: string): Pack { if (typeof packStr !== "string") { - throw new ConfigurationError(getPacksStrInvalid(packStr)); + throw new ConfigurationError(errorMessages.getPacksStrInvalid(packStr)); } packStr = packStr.trim(); @@ -1009,14 +943,14 @@ export function parsePacksSpecification(packStr: string): Pack { : undefined; if (!PACK_IDENTIFIER_PATTERN.test(packName)) { - throw new ConfigurationError(getPacksStrInvalid(packStr)); + throw new ConfigurationError(errorMessages.getPacksStrInvalid(packStr)); } if (version) { try { new semver.Range(version); } catch { // The range string is invalid. OK to ignore the caught error - throw new ConfigurationError(getPacksStrInvalid(packStr)); + throw new ConfigurationError(errorMessages.getPacksStrInvalid(packStr)); } } @@ -1030,12 +964,12 @@ export function parsePacksSpecification(packStr: string): Pack { path.normalize(packPath).split(path.sep).join("/") !== packPath.split(path.sep).join("/")) ) { - throw new ConfigurationError(getPacksStrInvalid(packStr)); + throw new ConfigurationError(errorMessages.getPacksStrInvalid(packStr)); } if (!packPath && pathStart) { // 0 length path - throw new ConfigurationError(getPacksStrInvalid(packStr)); + throw new ConfigurationError(errorMessages.getPacksStrInvalid(packStr)); } return { @@ -1215,7 +1149,7 @@ function getLocalConfig(configFile: string): UserConfig { // Error if the file does not exist if (!fs.existsSync(configFile)) { throw new ConfigurationError( - getConfigFileDoesNotExistErrorMessage(configFile), + errorMessages.getConfigFileDoesNotExistErrorMessage(configFile), ); } @@ -1234,7 +1168,7 @@ async function getRemoteConfig( // 5 = 4 groups + the whole expression if (pieces === null || pieces.groups === undefined || pieces.length < 5) { throw new ConfigurationError( - getConfigFileRepoFormatInvalidMessage(configFile), + errorMessages.getConfigFileRepoFormatInvalidMessage(configFile), ); } @@ -1252,10 +1186,12 @@ async function getRemoteConfig( fileContents = response.data.content; } else if (Array.isArray(response.data)) { throw new ConfigurationError( - getConfigFileDirectoryGivenMessage(configFile), + errorMessages.getConfigFileDirectoryGivenMessage(configFile), ); } else { - throw new ConfigurationError(getConfigFileFormatInvalidMessage(configFile)); + throw new ConfigurationError( + errorMessages.getConfigFileFormatInvalidMessage(configFile), + ); } return yaml.load( diff --git a/src/error-messages.ts b/src/error-messages.ts new file mode 100644 index 000000000..61dd3ef92 --- /dev/null +++ b/src/error-messages.ts @@ -0,0 +1,66 @@ +const PACKS_PROPERTY = "packs"; + +export function getConfigFileOutsideWorkspaceErrorMessage( + configFile: string, +): string { + return `The configuration file "${configFile}" is outside of the workspace`; +} + +export function getConfigFileDoesNotExistErrorMessage( + configFile: string, +): string { + return `The configuration file "${configFile}" does not exist`; +} + +export function getConfigFileRepoFormatInvalidMessage( + configFile: string, +): string { + let error = `The configuration file "${configFile}" is not a supported remote file reference.`; + error += " Expected format //@"; + + return error; +} + +export function getConfigFileFormatInvalidMessage(configFile: string): string { + return `The configuration file "${configFile}" could not be read`; +} + +export function getConfigFileDirectoryGivenMessage(configFile: string): string { + return `The configuration file "${configFile}" looks like a directory, not a file`; +} + +export function getConfigFilePropertyError( + configFile: string | undefined, + property: string, + error: string, +): string { + if (configFile === undefined) { + return `The workflow property "${property}" is invalid: ${error}`; + } else { + return `The configuration file "${configFile}" is invalid: property "${property}" ${error}`; + } +} + +export function getPacksStrInvalid( + packStr: string, + configFile?: string, +): string { + return configFile + ? getConfigFilePropertyError( + configFile, + PACKS_PROPERTY, + `"${packStr}" is not a valid pack`, + ) + : `"${packStr}" is not a valid pack`; +} + +export function getNoLanguagesError(): string { + return ( + "Did not detect any languages to analyze. " + + "Please update input in workflow or check that GitHub detects the correct languages in your repository." + ); +} + +export function getUnknownLanguagesError(languages: string[]): string { + return `Did not recognize the following languages: ${languages.join(", ")}`; +}