From 53acf0b8aa0a8705134bb6153d859bc2817e1740 Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Tue, 28 Oct 2025 21:17:30 +0000 Subject: [PATCH 1/3] Turn enablement errors into configuration errors --- lib/analyze-action.js | 12 ++++++++++++ lib/init-action-post.js | 12 ++++++++++++ lib/init-action.js | 12 ++++++++++++ lib/setup-codeql-action.js | 12 ++++++++++++ lib/upload-lib.js | 12 ++++++++++++ lib/upload-sarif-action.js | 12 ++++++++++++ src/api-client.test.ts | 35 +++++++++++++++++++++++++++++++++++ src/api-client.ts | 13 +++++++++++++ 8 files changed, 120 insertions(+) diff --git a/lib/analyze-action.js b/lib/analyze-action.js index a94e3af59e..0afac73f9d 100644 --- a/lib/analyze-action.js +++ b/lib/analyze-action.js @@ -83621,6 +83621,13 @@ async function deleteActionsCache(id) { cache_id: id }); } +function isEnablementError(msg) { + return [ + /Code Security must be enabled/, + /Advanced Security must be enabled/, + /Code Scanning is not enabled/ + ].some((pattern) => pattern.test(msg)); +} function wrapApiConfigurationError(e) { const httpError = asHTTPError(e); if (httpError !== void 0) { @@ -83637,6 +83644,11 @@ function wrapApiConfigurationError(e) { "Please check that your token is valid and has the required permissions: contents: read, security-events: write" ); } + if (isEnablementError(httpError.message)) { + return new ConfigurationError( + `Please verify that the necessary features are enabled: ${httpError.message}` + ); + } if (httpError.status === 429) { return new ConfigurationError("API rate limit exceeded"); } diff --git a/lib/init-action-post.js b/lib/init-action-post.js index a41fc9c2d2..df8b107c8e 100644 --- a/lib/init-action-post.js +++ b/lib/init-action-post.js @@ -116758,6 +116758,13 @@ async function listActionsCaches(key, ref) { } ); } +function isEnablementError(msg) { + return [ + /Code Security must be enabled/, + /Advanced Security must be enabled/, + /Code Scanning is not enabled/ + ].some((pattern) => pattern.test(msg)); +} function wrapApiConfigurationError(e) { const httpError = asHTTPError(e); if (httpError !== void 0) { @@ -116774,6 +116781,11 @@ function wrapApiConfigurationError(e) { "Please check that your token is valid and has the required permissions: contents: read, security-events: write" ); } + if (isEnablementError(httpError.message)) { + return new ConfigurationError( + `Please verify that the necessary features are enabled: ${httpError.message}` + ); + } if (httpError.status === 429) { return new ConfigurationError("API rate limit exceeded"); } diff --git a/lib/init-action.js b/lib/init-action.js index 2302468f1a..416315e82d 100644 --- a/lib/init-action.js +++ b/lib/init-action.js @@ -80926,6 +80926,13 @@ async function getRepositoryProperties(repositoryNwo) { repo: repositoryNwo.repo }); } +function isEnablementError(msg) { + return [ + /Code Security must be enabled/, + /Advanced Security must be enabled/, + /Code Scanning is not enabled/ + ].some((pattern) => pattern.test(msg)); +} function wrapApiConfigurationError(e) { const httpError = asHTTPError(e); if (httpError !== void 0) { @@ -80942,6 +80949,11 @@ function wrapApiConfigurationError(e) { "Please check that your token is valid and has the required permissions: contents: read, security-events: write" ); } + if (isEnablementError(httpError.message)) { + return new ConfigurationError( + `Please verify that the necessary features are enabled: ${httpError.message}` + ); + } if (httpError.status === 429) { return new ConfigurationError("API rate limit exceeded"); } diff --git a/lib/setup-codeql-action.js b/lib/setup-codeql-action.js index a1a7ecdb25..249d5bfc7a 100644 --- a/lib/setup-codeql-action.js +++ b/lib/setup-codeql-action.js @@ -79275,6 +79275,13 @@ async function getAnalysisKey() { core5.exportVariable(analysisKeyEnvVar, analysisKey); return analysisKey; } +function isEnablementError(msg) { + return [ + /Code Security must be enabled/, + /Advanced Security must be enabled/, + /Code Scanning is not enabled/ + ].some((pattern) => pattern.test(msg)); +} function wrapApiConfigurationError(e) { const httpError = asHTTPError(e); if (httpError !== void 0) { @@ -79291,6 +79298,11 @@ function wrapApiConfigurationError(e) { "Please check that your token is valid and has the required permissions: contents: read, security-events: write" ); } + if (isEnablementError(httpError.message)) { + return new ConfigurationError( + `Please verify that the necessary features are enabled: ${httpError.message}` + ); + } if (httpError.status === 429) { return new ConfigurationError("API rate limit exceeded"); } diff --git a/lib/upload-lib.js b/lib/upload-lib.js index 330eeed1a7..68e449efaa 100644 --- a/lib/upload-lib.js +++ b/lib/upload-lib.js @@ -82146,6 +82146,13 @@ function computeAutomationID(analysis_key, environment) { } return automationID; } +function isEnablementError(msg) { + return [ + /Code Security must be enabled/, + /Advanced Security must be enabled/, + /Code Scanning is not enabled/ + ].some((pattern) => pattern.test(msg)); +} function wrapApiConfigurationError(e) { const httpError = asHTTPError(e); if (httpError !== void 0) { @@ -82162,6 +82169,11 @@ function wrapApiConfigurationError(e) { "Please check that your token is valid and has the required permissions: contents: read, security-events: write" ); } + if (isEnablementError(httpError.message)) { + return new ConfigurationError( + `Please verify that the necessary features are enabled: ${httpError.message}` + ); + } if (httpError.status === 429) { return new ConfigurationError("API rate limit exceeded"); } diff --git a/lib/upload-sarif-action.js b/lib/upload-sarif-action.js index 540515b7ad..cb5dd92dc2 100644 --- a/lib/upload-sarif-action.js +++ b/lib/upload-sarif-action.js @@ -82191,6 +82191,13 @@ function computeAutomationID(analysis_key, environment) { } return automationID; } +function isEnablementError(msg) { + return [ + /Code Security must be enabled/, + /Advanced Security must be enabled/, + /Code Scanning is not enabled/ + ].some((pattern) => pattern.test(msg)); +} function wrapApiConfigurationError(e) { const httpError = asHTTPError(e); if (httpError !== void 0) { @@ -82207,6 +82214,11 @@ function wrapApiConfigurationError(e) { "Please check that your token is valid and has the required permissions: contents: read, security-events: write" ); } + if (isEnablementError(httpError.message)) { + return new ConfigurationError( + `Please verify that the necessary features are enabled: ${httpError.message}` + ); + } if (httpError.status === 429) { return new ConfigurationError("API rate limit exceeded"); } diff --git a/src/api-client.test.ts b/src/api-client.test.ts index d2647b2bbb..301eb91a14 100644 --- a/src/api-client.test.ts +++ b/src/api-client.test.ts @@ -169,4 +169,39 @@ test("wrapApiConfigurationError correctly wraps specific configuration errors", res, new util.ConfigurationError("Resource not accessible by integration"), ); + + // Enablement errors. + const codeSecurityNotEnabledError = new util.HTTPError( + "Code Security must be enabled for this repository to use code scanning", + 403, + ); + res = api.wrapApiConfigurationError(codeSecurityNotEnabledError); + t.deepEqual( + res, + new util.ConfigurationError( + `Please verify that the necessary features are enabled: ${codeSecurityNotEnabledError.message}`, + ), + ); + const advancedSecurityNotEnabledError = new util.HTTPError( + "Advanced Security must be enabled for this repository to use code scanning", + 403, + ); + res = api.wrapApiConfigurationError(advancedSecurityNotEnabledError); + t.deepEqual( + res, + new util.ConfigurationError( + `Please verify that the necessary features are enabled: ${advancedSecurityNotEnabledError.message}`, + ), + ); + const codeScanningNotEnabledError = new util.HTTPError( + "Code Scanning is not enabled for this repository. Please enable code scanning in the repository settings.", + 403, + ); + res = api.wrapApiConfigurationError(codeScanningNotEnabledError); + t.deepEqual( + res, + new util.ConfigurationError( + `Please verify that the necessary features are enabled: ${codeScanningNotEnabledError.message}`, + ), + ); }); diff --git a/src/api-client.ts b/src/api-client.ts index 4289c2058f..e947672c62 100644 --- a/src/api-client.ts +++ b/src/api-client.ts @@ -283,6 +283,14 @@ export async function getRepositoryProperties(repositoryNwo: RepositoryNwo) { }); } +function isEnablementError(msg: string) { + return [ + /Code Security must be enabled/, + /Advanced Security must be enabled/, + /Code Scanning is not enabled/, + ].some((pattern) => pattern.test(msg)); +} + export function wrapApiConfigurationError(e: unknown) { const httpError = asHTTPError(e); if (httpError !== undefined) { @@ -304,6 +312,11 @@ export function wrapApiConfigurationError(e: unknown) { "Please check that your token is valid and has the required permissions: contents: read, security-events: write", ); } + if (isEnablementError(httpError.message)) { + return new ConfigurationError( + `Please verify that the necessary features are enabled: ${httpError.message}`, + ); + } if (httpError.status === 429) { return new ConfigurationError("API rate limit exceeded"); } From 194ba0ee2dcf02e70ff941763c144ea06f58c485 Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Wed, 29 Oct 2025 08:29:11 +0000 Subject: [PATCH 2/3] Make error message tests less brittle --- lib/analyze-action.js | 5 ++++- lib/init-action-post.js | 5 ++++- lib/init-action.js | 5 ++++- lib/setup-codeql-action.js | 5 ++++- lib/upload-lib.js | 5 ++++- lib/upload-sarif-action.js | 5 ++++- src/api-client.test.ts | 6 +++--- src/api-client.ts | 8 +++++++- 8 files changed, 34 insertions(+), 10 deletions(-) diff --git a/lib/analyze-action.js b/lib/analyze-action.js index 0afac73f9d..253ef2c9b4 100644 --- a/lib/analyze-action.js +++ b/lib/analyze-action.js @@ -83628,6 +83628,9 @@ function isEnablementError(msg) { /Code Scanning is not enabled/ ].some((pattern) => pattern.test(msg)); } +function getFeatureEnablementError(message) { + return `Please verify that the necessary features are enabled: ${message}`; +} function wrapApiConfigurationError(e) { const httpError = asHTTPError(e); if (httpError !== void 0) { @@ -83646,7 +83649,7 @@ function wrapApiConfigurationError(e) { } if (isEnablementError(httpError.message)) { return new ConfigurationError( - `Please verify that the necessary features are enabled: ${httpError.message}` + getFeatureEnablementError(httpError.message) ); } if (httpError.status === 429) { diff --git a/lib/init-action-post.js b/lib/init-action-post.js index df8b107c8e..1f56d4943e 100644 --- a/lib/init-action-post.js +++ b/lib/init-action-post.js @@ -116765,6 +116765,9 @@ function isEnablementError(msg) { /Code Scanning is not enabled/ ].some((pattern) => pattern.test(msg)); } +function getFeatureEnablementError(message) { + return `Please verify that the necessary features are enabled: ${message}`; +} function wrapApiConfigurationError(e) { const httpError = asHTTPError(e); if (httpError !== void 0) { @@ -116783,7 +116786,7 @@ function wrapApiConfigurationError(e) { } if (isEnablementError(httpError.message)) { return new ConfigurationError( - `Please verify that the necessary features are enabled: ${httpError.message}` + getFeatureEnablementError(httpError.message) ); } if (httpError.status === 429) { diff --git a/lib/init-action.js b/lib/init-action.js index 416315e82d..3c63f5a42a 100644 --- a/lib/init-action.js +++ b/lib/init-action.js @@ -80933,6 +80933,9 @@ function isEnablementError(msg) { /Code Scanning is not enabled/ ].some((pattern) => pattern.test(msg)); } +function getFeatureEnablementError(message) { + return `Please verify that the necessary features are enabled: ${message}`; +} function wrapApiConfigurationError(e) { const httpError = asHTTPError(e); if (httpError !== void 0) { @@ -80951,7 +80954,7 @@ function wrapApiConfigurationError(e) { } if (isEnablementError(httpError.message)) { return new ConfigurationError( - `Please verify that the necessary features are enabled: ${httpError.message}` + getFeatureEnablementError(httpError.message) ); } if (httpError.status === 429) { diff --git a/lib/setup-codeql-action.js b/lib/setup-codeql-action.js index 249d5bfc7a..5b8888d453 100644 --- a/lib/setup-codeql-action.js +++ b/lib/setup-codeql-action.js @@ -79282,6 +79282,9 @@ function isEnablementError(msg) { /Code Scanning is not enabled/ ].some((pattern) => pattern.test(msg)); } +function getFeatureEnablementError(message) { + return `Please verify that the necessary features are enabled: ${message}`; +} function wrapApiConfigurationError(e) { const httpError = asHTTPError(e); if (httpError !== void 0) { @@ -79300,7 +79303,7 @@ function wrapApiConfigurationError(e) { } if (isEnablementError(httpError.message)) { return new ConfigurationError( - `Please verify that the necessary features are enabled: ${httpError.message}` + getFeatureEnablementError(httpError.message) ); } if (httpError.status === 429) { diff --git a/lib/upload-lib.js b/lib/upload-lib.js index 68e449efaa..d220cda561 100644 --- a/lib/upload-lib.js +++ b/lib/upload-lib.js @@ -82153,6 +82153,9 @@ function isEnablementError(msg) { /Code Scanning is not enabled/ ].some((pattern) => pattern.test(msg)); } +function getFeatureEnablementError(message) { + return `Please verify that the necessary features are enabled: ${message}`; +} function wrapApiConfigurationError(e) { const httpError = asHTTPError(e); if (httpError !== void 0) { @@ -82171,7 +82174,7 @@ function wrapApiConfigurationError(e) { } if (isEnablementError(httpError.message)) { return new ConfigurationError( - `Please verify that the necessary features are enabled: ${httpError.message}` + getFeatureEnablementError(httpError.message) ); } if (httpError.status === 429) { diff --git a/lib/upload-sarif-action.js b/lib/upload-sarif-action.js index cb5dd92dc2..1a981457f2 100644 --- a/lib/upload-sarif-action.js +++ b/lib/upload-sarif-action.js @@ -82198,6 +82198,9 @@ function isEnablementError(msg) { /Code Scanning is not enabled/ ].some((pattern) => pattern.test(msg)); } +function getFeatureEnablementError(message) { + return `Please verify that the necessary features are enabled: ${message}`; +} function wrapApiConfigurationError(e) { const httpError = asHTTPError(e); if (httpError !== void 0) { @@ -82216,7 +82219,7 @@ function wrapApiConfigurationError(e) { } if (isEnablementError(httpError.message)) { return new ConfigurationError( - `Please verify that the necessary features are enabled: ${httpError.message}` + getFeatureEnablementError(httpError.message) ); } if (httpError.status === 429) { diff --git a/src/api-client.test.ts b/src/api-client.test.ts index 301eb91a14..29e3ef852e 100644 --- a/src/api-client.test.ts +++ b/src/api-client.test.ts @@ -179,7 +179,7 @@ test("wrapApiConfigurationError correctly wraps specific configuration errors", t.deepEqual( res, new util.ConfigurationError( - `Please verify that the necessary features are enabled: ${codeSecurityNotEnabledError.message}`, + api.getFeatureEnablementError(codeSecurityNotEnabledError.message), ), ); const advancedSecurityNotEnabledError = new util.HTTPError( @@ -190,7 +190,7 @@ test("wrapApiConfigurationError correctly wraps specific configuration errors", t.deepEqual( res, new util.ConfigurationError( - `Please verify that the necessary features are enabled: ${advancedSecurityNotEnabledError.message}`, + api.getFeatureEnablementError(advancedSecurityNotEnabledError.message), ), ); const codeScanningNotEnabledError = new util.HTTPError( @@ -201,7 +201,7 @@ test("wrapApiConfigurationError correctly wraps specific configuration errors", t.deepEqual( res, new util.ConfigurationError( - `Please verify that the necessary features are enabled: ${codeScanningNotEnabledError.message}`, + api.getFeatureEnablementError(codeScanningNotEnabledError.message), ), ); }); diff --git a/src/api-client.ts b/src/api-client.ts index e947672c62..8b730e4ede 100644 --- a/src/api-client.ts +++ b/src/api-client.ts @@ -291,6 +291,12 @@ function isEnablementError(msg: string) { ].some((pattern) => pattern.test(msg)); } +// TODO: Move to `error-messages.ts` after refactoring import order to avoid cycle +// since `error-messages.ts` currently depends on this file. +export function getFeatureEnablementError(message: string): string { + return `Please verify that the necessary features are enabled: ${message}`; +} + export function wrapApiConfigurationError(e: unknown) { const httpError = asHTTPError(e); if (httpError !== undefined) { @@ -314,7 +320,7 @@ export function wrapApiConfigurationError(e: unknown) { } if (isEnablementError(httpError.message)) { return new ConfigurationError( - `Please verify that the necessary features are enabled: ${httpError.message}`, + getFeatureEnablementError(httpError.message), ); } if (httpError.status === 429) { From 52a7bd7b6e714abd930eb15cde3c7c76c45d6c0f Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Wed, 29 Oct 2025 08:35:19 +0000 Subject: [PATCH 3/3] Check for 403 status --- lib/analyze-action.js | 2 +- lib/init-action-post.js | 2 +- lib/init-action.js | 2 +- lib/setup-codeql-action.js | 2 +- lib/upload-lib.js | 2 +- lib/upload-sarif-action.js | 2 +- src/api-client.ts | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/lib/analyze-action.js b/lib/analyze-action.js index 253ef2c9b4..9515b2a434 100644 --- a/lib/analyze-action.js +++ b/lib/analyze-action.js @@ -83647,7 +83647,7 @@ function wrapApiConfigurationError(e) { "Please check that your token is valid and has the required permissions: contents: read, security-events: write" ); } - if (isEnablementError(httpError.message)) { + if (httpError.status === 403 && isEnablementError(httpError.message)) { return new ConfigurationError( getFeatureEnablementError(httpError.message) ); diff --git a/lib/init-action-post.js b/lib/init-action-post.js index 1f56d4943e..69e6230d21 100644 --- a/lib/init-action-post.js +++ b/lib/init-action-post.js @@ -116784,7 +116784,7 @@ function wrapApiConfigurationError(e) { "Please check that your token is valid and has the required permissions: contents: read, security-events: write" ); } - if (isEnablementError(httpError.message)) { + if (httpError.status === 403 && isEnablementError(httpError.message)) { return new ConfigurationError( getFeatureEnablementError(httpError.message) ); diff --git a/lib/init-action.js b/lib/init-action.js index 3c63f5a42a..c976f2e30a 100644 --- a/lib/init-action.js +++ b/lib/init-action.js @@ -80952,7 +80952,7 @@ function wrapApiConfigurationError(e) { "Please check that your token is valid and has the required permissions: contents: read, security-events: write" ); } - if (isEnablementError(httpError.message)) { + if (httpError.status === 403 && isEnablementError(httpError.message)) { return new ConfigurationError( getFeatureEnablementError(httpError.message) ); diff --git a/lib/setup-codeql-action.js b/lib/setup-codeql-action.js index 5b8888d453..327dcfcb86 100644 --- a/lib/setup-codeql-action.js +++ b/lib/setup-codeql-action.js @@ -79301,7 +79301,7 @@ function wrapApiConfigurationError(e) { "Please check that your token is valid and has the required permissions: contents: read, security-events: write" ); } - if (isEnablementError(httpError.message)) { + if (httpError.status === 403 && isEnablementError(httpError.message)) { return new ConfigurationError( getFeatureEnablementError(httpError.message) ); diff --git a/lib/upload-lib.js b/lib/upload-lib.js index d220cda561..bc3545aa64 100644 --- a/lib/upload-lib.js +++ b/lib/upload-lib.js @@ -82172,7 +82172,7 @@ function wrapApiConfigurationError(e) { "Please check that your token is valid and has the required permissions: contents: read, security-events: write" ); } - if (isEnablementError(httpError.message)) { + if (httpError.status === 403 && isEnablementError(httpError.message)) { return new ConfigurationError( getFeatureEnablementError(httpError.message) ); diff --git a/lib/upload-sarif-action.js b/lib/upload-sarif-action.js index 1a981457f2..ed785239d6 100644 --- a/lib/upload-sarif-action.js +++ b/lib/upload-sarif-action.js @@ -82217,7 +82217,7 @@ function wrapApiConfigurationError(e) { "Please check that your token is valid and has the required permissions: contents: read, security-events: write" ); } - if (isEnablementError(httpError.message)) { + if (httpError.status === 403 && isEnablementError(httpError.message)) { return new ConfigurationError( getFeatureEnablementError(httpError.message) ); diff --git a/src/api-client.ts b/src/api-client.ts index 8b730e4ede..f271c27910 100644 --- a/src/api-client.ts +++ b/src/api-client.ts @@ -318,7 +318,7 @@ export function wrapApiConfigurationError(e: unknown) { "Please check that your token is valid and has the required permissions: contents: read, security-events: write", ); } - if (isEnablementError(httpError.message)) { + if (httpError.status === 403 && isEnablementError(httpError.message)) { return new ConfigurationError( getFeatureEnablementError(httpError.message), );