From 62f0f21c3cf729521f1b7c6610048be4eb0cbea9 Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Fri, 10 Oct 2025 13:27:50 +0100 Subject: [PATCH 1/6] Add `AllowToolcacheInput` feature --- lib/analyze-action-post.js | 5 +++++ lib/analyze-action.js | 5 +++++ lib/autobuild-action.js | 5 +++++ lib/init-action-post.js | 5 +++++ lib/init-action.js | 5 +++++ lib/resolve-environment-action.js | 5 +++++ lib/start-proxy-action-post.js | 5 +++++ lib/start-proxy-action.js | 5 +++++ lib/upload-lib.js | 5 +++++ lib/upload-sarif-action-post.js | 5 +++++ lib/upload-sarif-action.js | 5 +++++ src/feature-flags.ts | 8 +++++++- 12 files changed, 62 insertions(+), 1 deletion(-) diff --git a/lib/analyze-action-post.js b/lib/analyze-action-post.js index 19c987905e..a118f067ee 100644 --- a/lib/analyze-action-post.js +++ b/lib/analyze-action-post.js @@ -117806,6 +117806,11 @@ function isSafeArtifactUpload(codeQlVersion) { // src/feature-flags.ts var featureConfig = { + ["allow_toolcache_input" /* AllowToolcacheInput */]: { + defaultValue: false, + envVar: "CODEQL_ACTION_ALLOW_TOOLCACHE_INPUT", + minimumVersion: void 0 + }, ["cleanup_trap_caches" /* CleanupTrapCaches */]: { defaultValue: false, envVar: "CODEQL_ACTION_CLEANUP_TRAP_CACHES", diff --git a/lib/analyze-action.js b/lib/analyze-action.js index af3fb58319..aec886409e 100644 --- a/lib/analyze-action.js +++ b/lib/analyze-action.js @@ -91095,6 +91095,11 @@ var DEFAULT_VERSION_FEATURE_FLAG_PREFIX = "default_codeql_version_"; var DEFAULT_VERSION_FEATURE_FLAG_SUFFIX = "_enabled"; var CODEQL_VERSION_ZSTD_BUNDLE = "2.19.0"; var featureConfig = { + ["allow_toolcache_input" /* AllowToolcacheInput */]: { + defaultValue: false, + envVar: "CODEQL_ACTION_ALLOW_TOOLCACHE_INPUT", + minimumVersion: void 0 + }, ["cleanup_trap_caches" /* CleanupTrapCaches */]: { defaultValue: false, envVar: "CODEQL_ACTION_CLEANUP_TRAP_CACHES", diff --git a/lib/autobuild-action.js b/lib/autobuild-action.js index adf440738a..ef95f3e146 100644 --- a/lib/autobuild-action.js +++ b/lib/autobuild-action.js @@ -78544,6 +78544,11 @@ function isSupportedToolsFeature(versionInfo, feature) { var DEFAULT_VERSION_FEATURE_FLAG_PREFIX = "default_codeql_version_"; var DEFAULT_VERSION_FEATURE_FLAG_SUFFIX = "_enabled"; var featureConfig = { + ["allow_toolcache_input" /* AllowToolcacheInput */]: { + defaultValue: false, + envVar: "CODEQL_ACTION_ALLOW_TOOLCACHE_INPUT", + minimumVersion: void 0 + }, ["cleanup_trap_caches" /* CleanupTrapCaches */]: { defaultValue: false, envVar: "CODEQL_ACTION_CLEANUP_TRAP_CACHES", diff --git a/lib/init-action-post.js b/lib/init-action-post.js index 08c8449012..ab441ee67b 100644 --- a/lib/init-action-post.js +++ b/lib/init-action-post.js @@ -129233,6 +129233,11 @@ var DEFAULT_VERSION_FEATURE_FLAG_PREFIX = "default_codeql_version_"; var DEFAULT_VERSION_FEATURE_FLAG_SUFFIX = "_enabled"; var CODEQL_VERSION_ZSTD_BUNDLE = "2.19.0"; var featureConfig = { + ["allow_toolcache_input" /* AllowToolcacheInput */]: { + defaultValue: false, + envVar: "CODEQL_ACTION_ALLOW_TOOLCACHE_INPUT", + minimumVersion: void 0 + }, ["cleanup_trap_caches" /* CleanupTrapCaches */]: { defaultValue: false, envVar: "CODEQL_ACTION_CLEANUP_TRAP_CACHES", diff --git a/lib/init-action.js b/lib/init-action.js index 5481ab1e8f..8a1c1455b4 100644 --- a/lib/init-action.js +++ b/lib/init-action.js @@ -86981,6 +86981,11 @@ var DEFAULT_VERSION_FEATURE_FLAG_PREFIX = "default_codeql_version_"; var DEFAULT_VERSION_FEATURE_FLAG_SUFFIX = "_enabled"; var CODEQL_VERSION_ZSTD_BUNDLE = "2.19.0"; var featureConfig = { + ["allow_toolcache_input" /* AllowToolcacheInput */]: { + defaultValue: false, + envVar: "CODEQL_ACTION_ALLOW_TOOLCACHE_INPUT", + minimumVersion: void 0 + }, ["cleanup_trap_caches" /* CleanupTrapCaches */]: { defaultValue: false, envVar: "CODEQL_ACTION_CLEANUP_TRAP_CACHES", diff --git a/lib/resolve-environment-action.js b/lib/resolve-environment-action.js index 4d1cdf81af..8c583694c1 100644 --- a/lib/resolve-environment-action.js +++ b/lib/resolve-environment-action.js @@ -78535,6 +78535,11 @@ function isSupportedToolsFeature(versionInfo, feature) { // src/feature-flags.ts var featureConfig = { + ["allow_toolcache_input" /* AllowToolcacheInput */]: { + defaultValue: false, + envVar: "CODEQL_ACTION_ALLOW_TOOLCACHE_INPUT", + minimumVersion: void 0 + }, ["cleanup_trap_caches" /* CleanupTrapCaches */]: { defaultValue: false, envVar: "CODEQL_ACTION_CLEANUP_TRAP_CACHES", diff --git a/lib/start-proxy-action-post.js b/lib/start-proxy-action-post.js index 2b468746ba..be478338a6 100644 --- a/lib/start-proxy-action-post.js +++ b/lib/start-proxy-action-post.js @@ -117215,6 +117215,11 @@ var semver3 = __toESM(require_semver2()); // src/feature-flags.ts var featureConfig = { + ["allow_toolcache_input" /* AllowToolcacheInput */]: { + defaultValue: false, + envVar: "CODEQL_ACTION_ALLOW_TOOLCACHE_INPUT", + minimumVersion: void 0 + }, ["cleanup_trap_caches" /* CleanupTrapCaches */]: { defaultValue: false, envVar: "CODEQL_ACTION_CLEANUP_TRAP_CACHES", diff --git a/lib/start-proxy-action.js b/lib/start-proxy-action.js index 29aea7357a..77de29490a 100644 --- a/lib/start-proxy-action.js +++ b/lib/start-proxy-action.js @@ -95329,6 +95329,11 @@ var semver3 = __toESM(require_semver2()); // src/feature-flags.ts var featureConfig = { + ["allow_toolcache_input" /* AllowToolcacheInput */]: { + defaultValue: false, + envVar: "CODEQL_ACTION_ALLOW_TOOLCACHE_INPUT", + minimumVersion: void 0 + }, ["cleanup_trap_caches" /* CleanupTrapCaches */]: { defaultValue: false, envVar: "CODEQL_ACTION_CLEANUP_TRAP_CACHES", diff --git a/lib/upload-lib.js b/lib/upload-lib.js index 508e16a109..3a783a2a0f 100644 --- a/lib/upload-lib.js +++ b/lib/upload-lib.js @@ -89332,6 +89332,11 @@ function isSupportedToolsFeature(versionInfo, feature) { // src/feature-flags.ts var CODEQL_VERSION_ZSTD_BUNDLE = "2.19.0"; var featureConfig = { + ["allow_toolcache_input" /* AllowToolcacheInput */]: { + defaultValue: false, + envVar: "CODEQL_ACTION_ALLOW_TOOLCACHE_INPUT", + minimumVersion: void 0 + }, ["cleanup_trap_caches" /* CleanupTrapCaches */]: { defaultValue: false, envVar: "CODEQL_ACTION_CLEANUP_TRAP_CACHES", diff --git a/lib/upload-sarif-action-post.js b/lib/upload-sarif-action-post.js index 6f9835b144..f4eda54fb3 100644 --- a/lib/upload-sarif-action-post.js +++ b/lib/upload-sarif-action-post.js @@ -117378,6 +117378,11 @@ function isSafeArtifactUpload(codeQlVersion) { // src/feature-flags.ts var featureConfig = { + ["allow_toolcache_input" /* AllowToolcacheInput */]: { + defaultValue: false, + envVar: "CODEQL_ACTION_ALLOW_TOOLCACHE_INPUT", + minimumVersion: void 0 + }, ["cleanup_trap_caches" /* CleanupTrapCaches */]: { defaultValue: false, envVar: "CODEQL_ACTION_CLEANUP_TRAP_CACHES", diff --git a/lib/upload-sarif-action.js b/lib/upload-sarif-action.js index ecdb515e3f..5d09915245 100644 --- a/lib/upload-sarif-action.js +++ b/lib/upload-sarif-action.js @@ -89248,6 +89248,11 @@ var DEFAULT_VERSION_FEATURE_FLAG_PREFIX = "default_codeql_version_"; var DEFAULT_VERSION_FEATURE_FLAG_SUFFIX = "_enabled"; var CODEQL_VERSION_ZSTD_BUNDLE = "2.19.0"; var featureConfig = { + ["allow_toolcache_input" /* AllowToolcacheInput */]: { + defaultValue: false, + envVar: "CODEQL_ACTION_ALLOW_TOOLCACHE_INPUT", + minimumVersion: void 0 + }, ["cleanup_trap_caches" /* CleanupTrapCaches */]: { defaultValue: false, envVar: "CODEQL_ACTION_CLEANUP_TRAP_CACHES", diff --git a/src/feature-flags.ts b/src/feature-flags.ts index 2938f5108c..3a548ffa1a 100644 --- a/src/feature-flags.ts +++ b/src/feature-flags.ts @@ -43,6 +43,7 @@ export interface FeatureEnablement { * Legacy features should end with `_enabled`. */ export enum Feature { + AllowToolcacheInput = "allow_toolcache_input", CleanupTrapCaches = "cleanup_trap_caches", CppDependencyInstallation = "cpp_dependency_installation_enabled", DiffInformedQueries = "diff_informed_queries", @@ -73,9 +74,9 @@ export enum Feature { OverlayAnalysisRust = "overlay_analysis_rust", OverlayAnalysisSwift = "overlay_analysis_swift", PythonDefaultIsToNotExtractStdlib = "python_default_is_to_not_extract_stdlib", - UseRepositoryProperties = "use_repository_properties", QaTelemetryEnabled = "qa_telemetry_enabled", ResolveSupportedLanguagesUsingCli = "resolve_supported_languages_using_cli", + UseRepositoryProperties = "use_repository_properties", } export const featureConfig: Record< @@ -109,6 +110,11 @@ export const featureConfig: Record< toolsFeature?: ToolsFeature; } > = { + [Feature.AllowToolcacheInput]: { + defaultValue: false, + envVar: "CODEQL_ACTION_ALLOW_TOOLCACHE_INPUT", + minimumVersion: undefined, + }, [Feature.CleanupTrapCaches]: { defaultValue: false, envVar: "CODEQL_ACTION_CLEANUP_TRAP_CACHES", From a512fe0868dad020a7936ebc957e18cb421aaba9 Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Fri, 10 Oct 2025 13:49:06 +0100 Subject: [PATCH 2/6] Gate `tools: toolcache` behind FF Mainly to allow us to disable it, if needed. --- lib/analyze-action.js | 29 +++++++++++++++++++++-------- lib/init-action-post.js | 29 +++++++++++++++++++++-------- lib/init-action.js | 29 +++++++++++++++++++++-------- lib/upload-lib.js | 29 +++++++++++++++++++++-------- lib/upload-sarif-action.js | 29 +++++++++++++++++++++-------- src/codeql.test.ts | 28 ++++++++++++++++++++++++++++ src/codeql.ts | 3 +++ src/init-action.ts | 1 + src/init.ts | 4 +++- src/setup-codeql.test.ts | 17 +++++++++++++++++ src/setup-codeql.ts | 23 +++++++++++++++++++---- src/upload-lib.ts | 1 + 12 files changed, 177 insertions(+), 45 deletions(-) diff --git a/lib/analyze-action.js b/lib/analyze-action.js index aec886409e..c94a9e3843 100644 --- a/lib/analyze-action.js +++ b/lib/analyze-action.js @@ -92304,7 +92304,7 @@ async function findOverridingToolsInCache(humanReadableVersion, logger) { } return void 0; } -async function getCodeQLSource(toolsInput, defaultCliVersion, apiDetails, variant, tarSupportsZstd, logger) { +async function getCodeQLSource(toolsInput, defaultCliVersion, apiDetails, variant, tarSupportsZstd, features, logger) { if (toolsInput && !isReservedToolsValue(toolsInput) && !toolsInput.startsWith("http")) { logger.info(`Using CodeQL CLI from local path ${toolsInput}`); const compressionMethod2 = inferCompressionMethod(toolsInput); @@ -92343,7 +92343,10 @@ async function getCodeQLSource(toolsInput, defaultCliVersion, apiDetails, varian } } else if (toolsInput !== void 0 && toolsInput === CODEQL_TOOLCACHE_INPUT) { let latestToolcacheVersion; - const allowToolcacheValue = isDynamicWorkflow() || isInTestMode(); + const allowToolcacheValueFF = await features.getValue( + "allow_toolcache_input" /* AllowToolcacheInput */ + ); + const allowToolcacheValue = allowToolcacheValueFF && (isDynamicWorkflow() || isInTestMode()); if (allowToolcacheValue) { logger.info( `Attempting to use the latest CodeQL CLI version in the toolcache, as requested by 'tools: ${toolsInput}'.` @@ -92359,9 +92362,15 @@ async function getCodeQLSource(toolsInput, defaultCliVersion, apiDetails, varian `Found no CodeQL CLI in the toolcache, ignoring 'tools: ${toolsInput}'...` ); } else { - logger.warning( - `Ignoring 'tools: ${toolsInput}' because the workflow was not triggered dynamically.` - ); + if (allowToolcacheValueFF) { + logger.info( + `Ignoring 'tools: ${toolsInput}' because the feature is not enabled.` + ); + } else { + logger.warning( + `Ignoring 'tools: ${toolsInput}' because the workflow was not triggered dynamically.` + ); + } } cliVersion2 = defaultCliVersion.cliVersion; tagName = defaultCliVersion.tagName; @@ -92574,7 +92583,7 @@ function getCanonicalToolcacheVersion(cliVersion2, bundleVersion2, logger) { } return cliVersion2; } -async function setupCodeQLBundle(toolsInput, apiDetails, tempDir, variant, defaultCliVersion, logger) { +async function setupCodeQLBundle(toolsInput, apiDetails, tempDir, variant, defaultCliVersion, features, logger) { if (!await isBinaryAccessible("tar", logger)) { throw new ConfigurationError( "Could not find tar in PATH, so unable to extract CodeQL bundle." @@ -92587,6 +92596,7 @@ async function setupCodeQLBundle(toolsInput, apiDetails, tempDir, variant, defau apiDetails, variant, zstdAvailability.available, + features, logger ); let codeqlFolder; @@ -92744,7 +92754,7 @@ var GHES_VERSION_MOST_RECENTLY_DEPRECATED = "3.13"; var GHES_MOST_RECENT_DEPRECATION_DATE = "2025-06-19"; var EXTRACTION_DEBUG_MODE_VERBOSITY = "progress++"; var CODEQL_VERSION_CACHE_CLEANUP = "2.17.1"; -async function setupCodeQL(toolsInput, apiDetails, tempDir, variant, defaultCliVersion, logger, checkVersion) { +async function setupCodeQL(toolsInput, apiDetails, tempDir, variant, defaultCliVersion, features, logger, checkVersion) { try { const { codeqlFolder, @@ -92758,6 +92768,7 @@ async function setupCodeQL(toolsInput, apiDetails, tempDir, variant, defaultCliV tempDir, variant, defaultCliVersion, + features, logger ); logger.debug( @@ -95409,7 +95420,7 @@ async function addFingerprints(sarif, sourceRoot, logger) { // src/init.ts var toolrunner4 = __toESM(require_toolrunner()); var io6 = __toESM(require_io()); -async function initCodeQL(toolsInput, apiDetails, tempDir, variant, defaultCliVersion, logger) { +async function initCodeQL(toolsInput, apiDetails, tempDir, variant, defaultCliVersion, features, logger) { logger.startGroup("Setup CodeQL tools"); const { codeql, @@ -95423,6 +95434,7 @@ async function initCodeQL(toolsInput, apiDetails, tempDir, variant, defaultCliVe tempDir, variant, defaultCliVersion, + features, logger, true ); @@ -95569,6 +95581,7 @@ async function combineSarifFilesUsingCLI(sarifFiles, gitHubVersion, features, lo tempDir, gitHubVersion.type, codeQLDefaultVersionInfo, + features, logger ); codeQL = initCodeQLResult.codeql; diff --git a/lib/init-action-post.js b/lib/init-action-post.js index ab441ee67b..cc3b6a9d2c 100644 --- a/lib/init-action-post.js +++ b/lib/init-action-post.js @@ -130286,7 +130286,7 @@ async function findOverridingToolsInCache(humanReadableVersion, logger) { } return void 0; } -async function getCodeQLSource(toolsInput, defaultCliVersion, apiDetails, variant, tarSupportsZstd, logger) { +async function getCodeQLSource(toolsInput, defaultCliVersion, apiDetails, variant, tarSupportsZstd, features, logger) { if (toolsInput && !isReservedToolsValue(toolsInput) && !toolsInput.startsWith("http")) { logger.info(`Using CodeQL CLI from local path ${toolsInput}`); const compressionMethod2 = inferCompressionMethod(toolsInput); @@ -130325,7 +130325,10 @@ async function getCodeQLSource(toolsInput, defaultCliVersion, apiDetails, varian } } else if (toolsInput !== void 0 && toolsInput === CODEQL_TOOLCACHE_INPUT) { let latestToolcacheVersion; - const allowToolcacheValue = isDynamicWorkflow() || isInTestMode(); + const allowToolcacheValueFF = await features.getValue( + "allow_toolcache_input" /* AllowToolcacheInput */ + ); + const allowToolcacheValue = allowToolcacheValueFF && (isDynamicWorkflow() || isInTestMode()); if (allowToolcacheValue) { logger.info( `Attempting to use the latest CodeQL CLI version in the toolcache, as requested by 'tools: ${toolsInput}'.` @@ -130341,9 +130344,15 @@ async function getCodeQLSource(toolsInput, defaultCliVersion, apiDetails, varian `Found no CodeQL CLI in the toolcache, ignoring 'tools: ${toolsInput}'...` ); } else { - logger.warning( - `Ignoring 'tools: ${toolsInput}' because the workflow was not triggered dynamically.` - ); + if (allowToolcacheValueFF) { + logger.info( + `Ignoring 'tools: ${toolsInput}' because the feature is not enabled.` + ); + } else { + logger.warning( + `Ignoring 'tools: ${toolsInput}' because the workflow was not triggered dynamically.` + ); + } } cliVersion2 = defaultCliVersion.cliVersion; tagName = defaultCliVersion.tagName; @@ -130556,7 +130565,7 @@ function getCanonicalToolcacheVersion(cliVersion2, bundleVersion2, logger) { } return cliVersion2; } -async function setupCodeQLBundle(toolsInput, apiDetails, tempDir, variant, defaultCliVersion, logger) { +async function setupCodeQLBundle(toolsInput, apiDetails, tempDir, variant, defaultCliVersion, features, logger) { if (!await isBinaryAccessible("tar", logger)) { throw new ConfigurationError( "Could not find tar in PATH, so unable to extract CodeQL bundle." @@ -130569,6 +130578,7 @@ async function setupCodeQLBundle(toolsInput, apiDetails, tempDir, variant, defau apiDetails, variant, zstdAvailability.available, + features, logger ); let codeqlFolder; @@ -130693,7 +130703,7 @@ var GHES_VERSION_MOST_RECENTLY_DEPRECATED = "3.13"; var GHES_MOST_RECENT_DEPRECATION_DATE = "2025-06-19"; var EXTRACTION_DEBUG_MODE_VERBOSITY = "progress++"; var CODEQL_VERSION_CACHE_CLEANUP = "2.17.1"; -async function setupCodeQL(toolsInput, apiDetails, tempDir, variant, defaultCliVersion, logger, checkVersion) { +async function setupCodeQL(toolsInput, apiDetails, tempDir, variant, defaultCliVersion, features, logger, checkVersion) { try { const { codeqlFolder, @@ -130707,6 +130717,7 @@ async function setupCodeQL(toolsInput, apiDetails, tempDir, variant, defaultCliV tempDir, variant, defaultCliVersion, + features, logger ); logger.debug( @@ -132885,7 +132896,7 @@ async function addFingerprints(sarif, sourceRoot, logger) { // src/init.ts var toolrunner4 = __toESM(require_toolrunner()); var io6 = __toESM(require_io()); -async function initCodeQL(toolsInput, apiDetails, tempDir, variant, defaultCliVersion, logger) { +async function initCodeQL(toolsInput, apiDetails, tempDir, variant, defaultCliVersion, features, logger) { logger.startGroup("Setup CodeQL tools"); const { codeql, @@ -132899,6 +132910,7 @@ async function initCodeQL(toolsInput, apiDetails, tempDir, variant, defaultCliVe tempDir, variant, defaultCliVersion, + features, logger, true ); @@ -133045,6 +133057,7 @@ async function combineSarifFilesUsingCLI(sarifFiles, gitHubVersion, features, lo tempDir, gitHubVersion.type, codeQLDefaultVersionInfo, + features, logger ); codeQL = initCodeQLResult.codeql; diff --git a/lib/init-action.js b/lib/init-action.js index 8a1c1455b4..c1009d393f 100644 --- a/lib/init-action.js +++ b/lib/init-action.js @@ -89082,7 +89082,7 @@ async function findOverridingToolsInCache(humanReadableVersion, logger) { } return void 0; } -async function getCodeQLSource(toolsInput, defaultCliVersion, apiDetails, variant, tarSupportsZstd, logger) { +async function getCodeQLSource(toolsInput, defaultCliVersion, apiDetails, variant, tarSupportsZstd, features, logger) { if (toolsInput && !isReservedToolsValue(toolsInput) && !toolsInput.startsWith("http")) { logger.info(`Using CodeQL CLI from local path ${toolsInput}`); const compressionMethod2 = inferCompressionMethod(toolsInput); @@ -89121,7 +89121,10 @@ async function getCodeQLSource(toolsInput, defaultCliVersion, apiDetails, varian } } else if (toolsInput !== void 0 && toolsInput === CODEQL_TOOLCACHE_INPUT) { let latestToolcacheVersion; - const allowToolcacheValue = isDynamicWorkflow() || isInTestMode(); + const allowToolcacheValueFF = await features.getValue( + "allow_toolcache_input" /* AllowToolcacheInput */ + ); + const allowToolcacheValue = allowToolcacheValueFF && (isDynamicWorkflow() || isInTestMode()); if (allowToolcacheValue) { logger.info( `Attempting to use the latest CodeQL CLI version in the toolcache, as requested by 'tools: ${toolsInput}'.` @@ -89137,9 +89140,15 @@ async function getCodeQLSource(toolsInput, defaultCliVersion, apiDetails, varian `Found no CodeQL CLI in the toolcache, ignoring 'tools: ${toolsInput}'...` ); } else { - logger.warning( - `Ignoring 'tools: ${toolsInput}' because the workflow was not triggered dynamically.` - ); + if (allowToolcacheValueFF) { + logger.info( + `Ignoring 'tools: ${toolsInput}' because the feature is not enabled.` + ); + } else { + logger.warning( + `Ignoring 'tools: ${toolsInput}' because the workflow was not triggered dynamically.` + ); + } } cliVersion2 = defaultCliVersion.cliVersion; tagName = defaultCliVersion.tagName; @@ -89352,7 +89361,7 @@ function getCanonicalToolcacheVersion(cliVersion2, bundleVersion2, logger) { } return cliVersion2; } -async function setupCodeQLBundle(toolsInput, apiDetails, tempDir, variant, defaultCliVersion, logger) { +async function setupCodeQLBundle(toolsInput, apiDetails, tempDir, variant, defaultCliVersion, features, logger) { if (!await isBinaryAccessible("tar", logger)) { throw new ConfigurationError( "Could not find tar in PATH, so unable to extract CodeQL bundle." @@ -89365,6 +89374,7 @@ async function setupCodeQLBundle(toolsInput, apiDetails, tempDir, variant, defau apiDetails, variant, zstdAvailability.available, + features, logger ); let codeqlFolder; @@ -89511,7 +89521,7 @@ var GHES_VERSION_MOST_RECENTLY_DEPRECATED = "3.13"; var GHES_MOST_RECENT_DEPRECATION_DATE = "2025-06-19"; var EXTRACTION_DEBUG_MODE_VERBOSITY = "progress++"; var CODEQL_VERSION_CACHE_CLEANUP = "2.17.1"; -async function setupCodeQL(toolsInput, apiDetails, tempDir, variant, defaultCliVersion, logger, checkVersion) { +async function setupCodeQL(toolsInput, apiDetails, tempDir, variant, defaultCliVersion, features, logger, checkVersion) { try { const { codeqlFolder, @@ -89525,6 +89535,7 @@ async function setupCodeQL(toolsInput, apiDetails, tempDir, variant, defaultCliV tempDir, variant, defaultCliVersion, + features, logger ); logger.debug( @@ -90098,7 +90109,7 @@ async function getJobRunUuidSarifOptions(codeql) { } // src/init.ts -async function initCodeQL(toolsInput, apiDetails, tempDir, variant, defaultCliVersion, logger) { +async function initCodeQL(toolsInput, apiDetails, tempDir, variant, defaultCliVersion, features, logger) { logger.startGroup("Setup CodeQL tools"); const { codeql, @@ -90112,6 +90123,7 @@ async function initCodeQL(toolsInput, apiDetails, tempDir, variant, defaultCliVe tempDir, variant, defaultCliVersion, + features, logger, true ); @@ -90760,6 +90772,7 @@ async function run() { getTemporaryDirectory(), gitHubVersion.type, codeQLDefaultVersionInfo, + features, logger ); codeql = initCodeQLResult.codeql; diff --git a/lib/upload-lib.js b/lib/upload-lib.js index 3a783a2a0f..f820544aa9 100644 --- a/lib/upload-lib.js +++ b/lib/upload-lib.js @@ -90121,7 +90121,7 @@ async function findOverridingToolsInCache(humanReadableVersion, logger) { } return void 0; } -async function getCodeQLSource(toolsInput, defaultCliVersion, apiDetails, variant, tarSupportsZstd, logger) { +async function getCodeQLSource(toolsInput, defaultCliVersion, apiDetails, variant, tarSupportsZstd, features, logger) { if (toolsInput && !isReservedToolsValue(toolsInput) && !toolsInput.startsWith("http")) { logger.info(`Using CodeQL CLI from local path ${toolsInput}`); const compressionMethod2 = inferCompressionMethod(toolsInput); @@ -90160,7 +90160,10 @@ async function getCodeQLSource(toolsInput, defaultCliVersion, apiDetails, varian } } else if (toolsInput !== void 0 && toolsInput === CODEQL_TOOLCACHE_INPUT) { let latestToolcacheVersion; - const allowToolcacheValue = isDynamicWorkflow() || isInTestMode(); + const allowToolcacheValueFF = await features.getValue( + "allow_toolcache_input" /* AllowToolcacheInput */ + ); + const allowToolcacheValue = allowToolcacheValueFF && (isDynamicWorkflow() || isInTestMode()); if (allowToolcacheValue) { logger.info( `Attempting to use the latest CodeQL CLI version in the toolcache, as requested by 'tools: ${toolsInput}'.` @@ -90176,9 +90179,15 @@ async function getCodeQLSource(toolsInput, defaultCliVersion, apiDetails, varian `Found no CodeQL CLI in the toolcache, ignoring 'tools: ${toolsInput}'...` ); } else { - logger.warning( - `Ignoring 'tools: ${toolsInput}' because the workflow was not triggered dynamically.` - ); + if (allowToolcacheValueFF) { + logger.info( + `Ignoring 'tools: ${toolsInput}' because the feature is not enabled.` + ); + } else { + logger.warning( + `Ignoring 'tools: ${toolsInput}' because the workflow was not triggered dynamically.` + ); + } } cliVersion2 = defaultCliVersion.cliVersion; tagName = defaultCliVersion.tagName; @@ -90391,7 +90400,7 @@ function getCanonicalToolcacheVersion(cliVersion2, bundleVersion2, logger) { } return cliVersion2; } -async function setupCodeQLBundle(toolsInput, apiDetails, tempDir, variant, defaultCliVersion, logger) { +async function setupCodeQLBundle(toolsInput, apiDetails, tempDir, variant, defaultCliVersion, features, logger) { if (!await isBinaryAccessible("tar", logger)) { throw new ConfigurationError( "Could not find tar in PATH, so unable to extract CodeQL bundle." @@ -90404,6 +90413,7 @@ async function setupCodeQLBundle(toolsInput, apiDetails, tempDir, variant, defau apiDetails, variant, zstdAvailability.available, + features, logger ); let codeqlFolder; @@ -90528,7 +90538,7 @@ var GHES_VERSION_MOST_RECENTLY_DEPRECATED = "3.13"; var GHES_MOST_RECENT_DEPRECATION_DATE = "2025-06-19"; var EXTRACTION_DEBUG_MODE_VERBOSITY = "progress++"; var CODEQL_VERSION_CACHE_CLEANUP = "2.17.1"; -async function setupCodeQL(toolsInput, apiDetails, tempDir, variant, defaultCliVersion, logger, checkVersion) { +async function setupCodeQL(toolsInput, apiDetails, tempDir, variant, defaultCliVersion, features, logger, checkVersion) { try { const { codeqlFolder, @@ -90542,6 +90552,7 @@ async function setupCodeQL(toolsInput, apiDetails, tempDir, variant, defaultCliV tempDir, variant, defaultCliVersion, + features, logger ); logger.debug( @@ -92245,7 +92256,7 @@ async function addFingerprints(sarif, sourceRoot, logger) { // src/init.ts var toolrunner4 = __toESM(require_toolrunner()); var io5 = __toESM(require_io()); -async function initCodeQL(toolsInput, apiDetails, tempDir, variant, defaultCliVersion, logger) { +async function initCodeQL(toolsInput, apiDetails, tempDir, variant, defaultCliVersion, features, logger) { logger.startGroup("Setup CodeQL tools"); const { codeql, @@ -92259,6 +92270,7 @@ async function initCodeQL(toolsInput, apiDetails, tempDir, variant, defaultCliVe tempDir, variant, defaultCliVersion, + features, logger, true ); @@ -92405,6 +92417,7 @@ async function combineSarifFilesUsingCLI(sarifFiles, gitHubVersion, features, lo tempDir, gitHubVersion.type, codeQLDefaultVersionInfo, + features, logger ); codeQL = initCodeQLResult.codeql; diff --git a/lib/upload-sarif-action.js b/lib/upload-sarif-action.js index 5d09915245..efd8fe7e88 100644 --- a/lib/upload-sarif-action.js +++ b/lib/upload-sarif-action.js @@ -90792,7 +90792,7 @@ async function findOverridingToolsInCache(humanReadableVersion, logger) { } return void 0; } -async function getCodeQLSource(toolsInput, defaultCliVersion, apiDetails, variant, tarSupportsZstd, logger) { +async function getCodeQLSource(toolsInput, defaultCliVersion, apiDetails, variant, tarSupportsZstd, features, logger) { if (toolsInput && !isReservedToolsValue(toolsInput) && !toolsInput.startsWith("http")) { logger.info(`Using CodeQL CLI from local path ${toolsInput}`); const compressionMethod2 = inferCompressionMethod(toolsInput); @@ -90831,7 +90831,10 @@ async function getCodeQLSource(toolsInput, defaultCliVersion, apiDetails, varian } } else if (toolsInput !== void 0 && toolsInput === CODEQL_TOOLCACHE_INPUT) { let latestToolcacheVersion; - const allowToolcacheValue = isDynamicWorkflow() || isInTestMode(); + const allowToolcacheValueFF = await features.getValue( + "allow_toolcache_input" /* AllowToolcacheInput */ + ); + const allowToolcacheValue = allowToolcacheValueFF && (isDynamicWorkflow() || isInTestMode()); if (allowToolcacheValue) { logger.info( `Attempting to use the latest CodeQL CLI version in the toolcache, as requested by 'tools: ${toolsInput}'.` @@ -90847,9 +90850,15 @@ async function getCodeQLSource(toolsInput, defaultCliVersion, apiDetails, varian `Found no CodeQL CLI in the toolcache, ignoring 'tools: ${toolsInput}'...` ); } else { - logger.warning( - `Ignoring 'tools: ${toolsInput}' because the workflow was not triggered dynamically.` - ); + if (allowToolcacheValueFF) { + logger.info( + `Ignoring 'tools: ${toolsInput}' because the feature is not enabled.` + ); + } else { + logger.warning( + `Ignoring 'tools: ${toolsInput}' because the workflow was not triggered dynamically.` + ); + } } cliVersion2 = defaultCliVersion.cliVersion; tagName = defaultCliVersion.tagName; @@ -91062,7 +91071,7 @@ function getCanonicalToolcacheVersion(cliVersion2, bundleVersion2, logger) { } return cliVersion2; } -async function setupCodeQLBundle(toolsInput, apiDetails, tempDir, variant, defaultCliVersion, logger) { +async function setupCodeQLBundle(toolsInput, apiDetails, tempDir, variant, defaultCliVersion, features, logger) { if (!await isBinaryAccessible("tar", logger)) { throw new ConfigurationError( "Could not find tar in PATH, so unable to extract CodeQL bundle." @@ -91075,6 +91084,7 @@ async function setupCodeQLBundle(toolsInput, apiDetails, tempDir, variant, defau apiDetails, variant, zstdAvailability.available, + features, logger ); let codeqlFolder; @@ -91199,7 +91209,7 @@ var GHES_VERSION_MOST_RECENTLY_DEPRECATED = "3.13"; var GHES_MOST_RECENT_DEPRECATION_DATE = "2025-06-19"; var EXTRACTION_DEBUG_MODE_VERBOSITY = "progress++"; var CODEQL_VERSION_CACHE_CLEANUP = "2.17.1"; -async function setupCodeQL(toolsInput, apiDetails, tempDir, variant, defaultCliVersion, logger, checkVersion) { +async function setupCodeQL(toolsInput, apiDetails, tempDir, variant, defaultCliVersion, features, logger, checkVersion) { try { const { codeqlFolder, @@ -91213,6 +91223,7 @@ async function setupCodeQL(toolsInput, apiDetails, tempDir, variant, defaultCliV tempDir, variant, defaultCliVersion, + features, logger ); logger.debug( @@ -92916,7 +92927,7 @@ async function addFingerprints(sarif, sourceRoot, logger) { // src/init.ts var toolrunner4 = __toESM(require_toolrunner()); var io5 = __toESM(require_io()); -async function initCodeQL(toolsInput, apiDetails, tempDir, variant, defaultCliVersion, logger) { +async function initCodeQL(toolsInput, apiDetails, tempDir, variant, defaultCliVersion, features, logger) { logger.startGroup("Setup CodeQL tools"); const { codeql, @@ -92930,6 +92941,7 @@ async function initCodeQL(toolsInput, apiDetails, tempDir, variant, defaultCliVe tempDir, variant, defaultCliVersion, + features, logger, true ); @@ -93076,6 +93088,7 @@ async function combineSarifFilesUsingCLI(sarifFiles, gitHubVersion, features, lo tempDir, gitHubVersion.type, codeQLDefaultVersionInfo, + features, logger ); codeQL = initCodeQLResult.codeql; diff --git a/src/codeql.test.ts b/src/codeql.test.ts index a5422b1e38..24d88069b8 100644 --- a/src/codeql.test.ts +++ b/src/codeql.test.ts @@ -74,6 +74,7 @@ async function installIntoToolcache({ cliVersion !== undefined ? { cliVersion, tagName } : SAMPLE_DEFAULT_CLI_VERSION, + createFeatures([]), getRunnerLogger(true), false, ); @@ -122,6 +123,8 @@ async function stubCodeql(): Promise { } test("downloads and caches explicitly requested bundles that aren't in the toolcache", async (t) => { + const features = createFeatures([]); + await util.withTmpDir(async (tmpDir) => { setupActionsVars(tmpDir, tmpDir); @@ -140,6 +143,7 @@ test("downloads and caches explicitly requested bundles that aren't in the toolc tmpDir, util.GitHubVariant.DOTCOM, SAMPLE_DEFAULT_CLI_VERSION, + features, getRunnerLogger(true), false, ); @@ -154,6 +158,8 @@ test("downloads and caches explicitly requested bundles that aren't in the toolc }); test("caches semantically versioned bundles using their semantic version number", async (t) => { + const features = createFeatures([]); + await util.withTmpDir(async (tmpDir) => { setupActionsVars(tmpDir, tmpDir); const url = mockBundleDownloadApi({ @@ -166,6 +172,7 @@ test("caches semantically versioned bundles using their semantic version number" tmpDir, util.GitHubVariant.DOTCOM, SAMPLE_DEFAULT_CLI_VERSION, + features, getRunnerLogger(true), false, ); @@ -181,6 +188,8 @@ test("caches semantically versioned bundles using their semantic version number" }); test("downloads an explicitly requested bundle even if a different version is cached", async (t) => { + const features = createFeatures([]); + await util.withTmpDir(async (tmpDir) => { setupActionsVars(tmpDir, tmpDir); @@ -199,6 +208,7 @@ test("downloads an explicitly requested bundle even if a different version is ca tmpDir, util.GitHubVariant.DOTCOM, SAMPLE_DEFAULT_CLI_VERSION, + features, getRunnerLogger(true), false, ); @@ -227,6 +237,8 @@ for (const { expectedToolcacheVersion, } of EXPLICITLY_REQUESTED_BUNDLE_TEST_CASES) { test(`caches explicitly requested bundle ${tagName} as ${expectedToolcacheVersion}`, async (t) => { + const features = createFeatures([]); + await util.withTmpDir(async (tmpDir) => { setupActionsVars(tmpDir, tmpDir); @@ -243,6 +255,7 @@ for (const { tmpDir, util.GitHubVariant.DOTCOM, SAMPLE_DEFAULT_CLI_VERSION, + features, getRunnerLogger(true), false, ); @@ -266,6 +279,8 @@ for (const toolcacheVersion of [ `uses tools from toolcache when ${SAMPLE_DEFAULT_CLI_VERSION.cliVersion} is requested and ` + `${toolcacheVersion} is installed`, async (t) => { + const features = createFeatures([]); + await util.withTmpDir(async (tmpDir) => { setupActionsVars(tmpDir, tmpDir); @@ -281,6 +296,7 @@ for (const toolcacheVersion of [ tmpDir, util.GitHubVariant.DOTCOM, SAMPLE_DEFAULT_CLI_VERSION, + features, getRunnerLogger(true), false, ); @@ -295,6 +311,8 @@ for (const toolcacheVersion of [ } test(`uses a cached bundle when no tools input is given on GHES`, async (t) => { + const features = createFeatures([]); + await util.withTmpDir(async (tmpDir) => { setupActionsVars(tmpDir, tmpDir); @@ -313,6 +331,7 @@ test(`uses a cached bundle when no tools input is given on GHES`, async (t) => { cliVersion: defaults.cliVersion, tagName: defaults.bundleVersion, }, + features, getRunnerLogger(true), false, ); @@ -328,6 +347,8 @@ test(`uses a cached bundle when no tools input is given on GHES`, async (t) => { }); test(`downloads bundle if only an unpinned version is cached on GHES`, async (t) => { + const features = createFeatures([]); + await util.withTmpDir(async (tmpDir) => { setupActionsVars(tmpDir, tmpDir); @@ -349,6 +370,7 @@ test(`downloads bundle if only an unpinned version is cached on GHES`, async (t) cliVersion: defaults.cliVersion, tagName: defaults.bundleVersion, }, + features, getRunnerLogger(true), false, ); @@ -364,6 +386,8 @@ test(`downloads bundle if only an unpinned version is cached on GHES`, async (t) }); test('downloads bundle if "latest" tools specified but not cached', async (t) => { + const features = createFeatures([]); + await util.withTmpDir(async (tmpDir) => { setupActionsVars(tmpDir, tmpDir); @@ -382,6 +406,7 @@ test('downloads bundle if "latest" tools specified but not cached', async (t) => tmpDir, util.GitHubVariant.DOTCOM, SAMPLE_DEFAULT_CLI_VERSION, + features, getRunnerLogger(true), false, ); @@ -397,6 +422,8 @@ test('downloads bundle if "latest" tools specified but not cached', async (t) => }); test("bundle URL from another repo is cached as 0.0.0-bundleVersion", async (t) => { + const features = createFeatures([]); + await util.withTmpDir(async (tmpDir) => { setupActionsVars(tmpDir, tmpDir); @@ -417,6 +444,7 @@ test("bundle URL from another repo is cached as 0.0.0-bundleVersion", async (t) tmpDir, util.GitHubVariant.DOTCOM, SAMPLE_DEFAULT_CLI_VERSION, + features, getRunnerLogger(true), false, ); diff --git a/src/codeql.ts b/src/codeql.ts index 5241ff2476..ccb7be08da 100644 --- a/src/codeql.ts +++ b/src/codeql.ts @@ -309,6 +309,7 @@ const CODEQL_VERSION_CACHE_CLEANUP = "2.17.1"; * @param tempDir * @param variant * @param defaultCliVersion + * @param features Information about the features that are enabled. * @param logger * @param checkVersion Whether to check that CodeQL CLI meets the minimum * version requirement. Must be set to true outside tests. @@ -320,6 +321,7 @@ export async function setupCodeQL( tempDir: string, variant: util.GitHubVariant, defaultCliVersion: CodeQLDefaultVersionInfo, + features: FeatureEnablement, logger: Logger, checkVersion: boolean, ): Promise<{ @@ -342,6 +344,7 @@ export async function setupCodeQL( tempDir, variant, defaultCliVersion, + features, logger, ); diff --git a/src/init-action.ts b/src/init-action.ts index 114ad6cab1..0dbe957a76 100644 --- a/src/init-action.ts +++ b/src/init-action.ts @@ -248,6 +248,7 @@ async function run() { getTemporaryDirectory(), gitHubVersion.type, codeQLDefaultVersionInfo, + features, logger, ); codeql = initCodeQLResult.codeql; diff --git a/src/init.ts b/src/init.ts index 687afc1227..7ca6a3e39d 100644 --- a/src/init.ts +++ b/src/init.ts @@ -9,7 +9,7 @@ import { getOptionalInput, isSelfHostedRunner } from "./actions-util"; import { GitHubApiDetails } from "./api-client"; import { CodeQL, setupCodeQL } from "./codeql"; import * as configUtils from "./config-utils"; -import { CodeQLDefaultVersionInfo } from "./feature-flags"; +import { CodeQLDefaultVersionInfo, FeatureEnablement } from "./feature-flags"; import { KnownLanguage, Language } from "./languages"; import { Logger, withGroupAsync } from "./logging"; import { ToolsSource } from "./setup-codeql"; @@ -23,6 +23,7 @@ export async function initCodeQL( tempDir: string, variant: util.GitHubVariant, defaultCliVersion: CodeQLDefaultVersionInfo, + features: FeatureEnablement, logger: Logger, ): Promise<{ codeql: CodeQL; @@ -44,6 +45,7 @@ export async function initCodeQL( tempDir, variant, defaultCliVersion, + features, logger, true, ); diff --git a/src/setup-codeql.test.ts b/src/setup-codeql.test.ts index 4e65c6edf4..561dfb4e58 100644 --- a/src/setup-codeql.test.ts +++ b/src/setup-codeql.test.ts @@ -13,6 +13,7 @@ import { LoggedMessage, SAMPLE_DEFAULT_CLI_VERSION, SAMPLE_DOTCOM_API_DETAILS, + createFeatures, getRecordingLogger, initializeFeatures, mockBundleDownloadApi, @@ -91,6 +92,8 @@ test("getCodeQLActionRepository", (t) => { }); test("getCodeQLSource sets CLI version for a semver tagged bundle", async (t) => { + const features = createFeatures([]); + await withTmpDir(async (tmpDir) => { setupActionsVars(tmpDir, tmpDir); const tagName = "codeql-bundle-v1.2.3"; @@ -101,6 +104,7 @@ test("getCodeQLSource sets CLI version for a semver tagged bundle", async (t) => SAMPLE_DOTCOM_API_DETAILS, GitHubVariant.DOTCOM, false, + features, getRunnerLogger(true), ); @@ -110,6 +114,8 @@ test("getCodeQLSource sets CLI version for a semver tagged bundle", async (t) => }); test("getCodeQLSource correctly returns bundled CLI version when tools == linked", async (t) => { + const features = createFeatures([]); + await withTmpDir(async (tmpDir) => { setupActionsVars(tmpDir, tmpDir); const source = await setupCodeql.getCodeQLSource( @@ -118,6 +124,7 @@ test("getCodeQLSource correctly returns bundled CLI version when tools == linked SAMPLE_DOTCOM_API_DETAILS, GitHubVariant.DOTCOM, false, + features, getRunnerLogger(true), ); @@ -129,6 +136,7 @@ test("getCodeQLSource correctly returns bundled CLI version when tools == linked test("getCodeQLSource correctly returns bundled CLI version when tools == latest", async (t) => { const loggedMessages: LoggedMessage[] = []; const logger = getRecordingLogger(loggedMessages); + const features = createFeatures([]); await withTmpDir(async (tmpDir) => { setupActionsVars(tmpDir, tmpDir); @@ -138,6 +146,7 @@ test("getCodeQLSource correctly returns bundled CLI version when tools == latest SAMPLE_DOTCOM_API_DETAILS, GitHubVariant.DOTCOM, false, + features, logger, ); @@ -162,6 +171,7 @@ test("getCodeQLSource correctly returns bundled CLI version when tools == latest test("setupCodeQLBundle logs the CodeQL CLI version being used when asked to use linked tools", async (t) => { const loggedMessages: LoggedMessage[] = []; const logger = getRecordingLogger(loggedMessages); + const features = createFeatures([]); // Stub the downloadCodeQL function to prevent downloading artefacts // during testing from being called. @@ -186,6 +196,7 @@ test("setupCodeQLBundle logs the CodeQL CLI version being used when asked to use "tmp/codeql_action_test/", GitHubVariant.DOTCOM, SAMPLE_DEFAULT_CLI_VERSION, + features, logger, ); @@ -208,6 +219,7 @@ test("setupCodeQLBundle logs the CodeQL CLI version being used when asked to use test("setupCodeQLBundle logs the CodeQL CLI version being used when asked to download a non-default bundle", async (t) => { const loggedMessages: LoggedMessage[] = []; const logger = getRecordingLogger(loggedMessages); + const features = createFeatures([]); const bundleUrl = "https://github.com/github/codeql-action/releases/download/codeql-bundle-v2.16.0/codeql-bundle-linux64.tar.gz"; @@ -236,6 +248,7 @@ test("setupCodeQLBundle logs the CodeQL CLI version being used when asked to dow "tmp/codeql_action_test/", GitHubVariant.DOTCOM, SAMPLE_DEFAULT_CLI_VERSION, + features, logger, ); @@ -258,6 +271,7 @@ test("setupCodeQLBundle logs the CodeQL CLI version being used when asked to dow test("getCodeQLSource correctly returns latest version from toolcache when tools == toolcache", async (t) => { const loggedMessages: LoggedMessage[] = []; const logger = getRecordingLogger(loggedMessages); + const features = createFeatures([Feature.AllowToolcacheInput]); process.env["GITHUB_EVENT_NAME"] = "dynamic"; @@ -280,6 +294,7 @@ test("getCodeQLSource correctly returns latest version from toolcache when tools SAMPLE_DOTCOM_API_DETAILS, GitHubVariant.DOTCOM, false, + features, logger, ); @@ -319,6 +334,7 @@ test("getCodeQLSource correctly returns latest version from toolcache when tools test("getCodeQLSource falls back to downloading the CLI if the toolcache doesn't have a CodeQL CLI when tools == toolcache", async (t) => { const loggedMessages: LoggedMessage[] = []; const logger = getRecordingLogger(loggedMessages); + const features = createFeatures([Feature.AllowToolcacheInput]); process.env["GITHUB_EVENT_NAME"] = "dynamic"; @@ -335,6 +351,7 @@ test("getCodeQLSource falls back to downloading the CLI if the toolcache doesn't SAMPLE_DOTCOM_API_DETAILS, GitHubVariant.DOTCOM, false, + features, logger, ); diff --git a/src/setup-codeql.ts b/src/setup-codeql.ts index e01037223a..35b831f560 100644 --- a/src/setup-codeql.ts +++ b/src/setup-codeql.ts @@ -13,6 +13,8 @@ import * as defaults from "./defaults.json"; import { CODEQL_VERSION_ZSTD_BUNDLE, CodeQLDefaultVersionInfo, + Feature, + FeatureEnablement, } from "./feature-flags"; import { Logger } from "./logging"; import * as tar from "./tar"; @@ -276,6 +278,7 @@ export async function getCodeQLSource( apiDetails: api.GitHubApiDetails, variant: util.GitHubVariant, tarSupportsZstd: boolean, + features: FeatureEnablement, logger: Logger, ): Promise { if ( @@ -356,7 +359,11 @@ export async function getCodeQLSource( // We only allow `toolsInput === "toolcache"` for `dynamic` events. In general, using `toolsInput === "toolcache"` // can lead to alert wobble and so it shouldn't be used for an analysis where results are intended to be uploaded. // We also allow this in test mode. - const allowToolcacheValue = isDynamicWorkflow() || util.isInTestMode(); + const allowToolcacheValueFF = await features.getValue( + Feature.AllowToolcacheInput, + ); + const allowToolcacheValue = + allowToolcacheValueFF && (isDynamicWorkflow() || util.isInTestMode()); if (allowToolcacheValue) { // If `toolsInput === "toolcache"`, try to find the latest version of the CLI that's available in the toolcache // and use that. We perform this check here since we can set `cliVersion` directly and don't want to default to @@ -377,9 +384,15 @@ export async function getCodeQLSource( `Found no CodeQL CLI in the toolcache, ignoring 'tools: ${toolsInput}'...`, ); } else { - logger.warning( - `Ignoring 'tools: ${toolsInput}' because the workflow was not triggered dynamically.`, - ); + if (allowToolcacheValueFF) { + logger.info( + `Ignoring 'tools: ${toolsInput}' because the feature is not enabled.`, + ); + } else { + logger.warning( + `Ignoring 'tools: ${toolsInput}' because the workflow was not triggered dynamically.`, + ); + } } cliVersion = defaultCliVersion.cliVersion; @@ -735,6 +748,7 @@ export async function setupCodeQLBundle( tempDir: string, variant: util.GitHubVariant, defaultCliVersion: CodeQLDefaultVersionInfo, + features: FeatureEnablement, logger: Logger, ) { if (!(await util.isBinaryAccessible("tar", logger))) { @@ -750,6 +764,7 @@ export async function setupCodeQLBundle( apiDetails, variant, zstdAvailability.available, + features, logger, ); diff --git a/src/upload-lib.ts b/src/upload-lib.ts index 90f0342de5..26ae88f32f 100644 --- a/src/upload-lib.ts +++ b/src/upload-lib.ts @@ -262,6 +262,7 @@ async function combineSarifFilesUsingCLI( tempDir, gitHubVersion.type, codeQLDefaultVersionInfo, + features, logger, ); From 524b9a00e8f3b89d9e8a0803bd0a3646261829ea Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Fri, 10 Oct 2025 14:04:39 +0100 Subject: [PATCH 3/6] Fix log message swap --- lib/analyze-action.js | 4 ++-- lib/init-action-post.js | 4 ++-- lib/init-action.js | 4 ++-- lib/upload-lib.js | 4 ++-- lib/upload-sarif-action.js | 4 ++-- src/setup-codeql.ts | 4 ++-- 6 files changed, 12 insertions(+), 12 deletions(-) diff --git a/lib/analyze-action.js b/lib/analyze-action.js index c94a9e3843..8b30d734f4 100644 --- a/lib/analyze-action.js +++ b/lib/analyze-action.js @@ -92364,11 +92364,11 @@ async function getCodeQLSource(toolsInput, defaultCliVersion, apiDetails, varian } else { if (allowToolcacheValueFF) { logger.info( - `Ignoring 'tools: ${toolsInput}' because the feature is not enabled.` + `Ignoring 'tools: ${toolsInput}' because the workflow was not triggered dynamically.` ); } else { logger.warning( - `Ignoring 'tools: ${toolsInput}' because the workflow was not triggered dynamically.` + `Ignoring 'tools: ${toolsInput}' because the feature is not enabled.` ); } } diff --git a/lib/init-action-post.js b/lib/init-action-post.js index cc3b6a9d2c..553b7d150a 100644 --- a/lib/init-action-post.js +++ b/lib/init-action-post.js @@ -130346,11 +130346,11 @@ async function getCodeQLSource(toolsInput, defaultCliVersion, apiDetails, varian } else { if (allowToolcacheValueFF) { logger.info( - `Ignoring 'tools: ${toolsInput}' because the feature is not enabled.` + `Ignoring 'tools: ${toolsInput}' because the workflow was not triggered dynamically.` ); } else { logger.warning( - `Ignoring 'tools: ${toolsInput}' because the workflow was not triggered dynamically.` + `Ignoring 'tools: ${toolsInput}' because the feature is not enabled.` ); } } diff --git a/lib/init-action.js b/lib/init-action.js index c1009d393f..e3f3ddacd8 100644 --- a/lib/init-action.js +++ b/lib/init-action.js @@ -89142,11 +89142,11 @@ async function getCodeQLSource(toolsInput, defaultCliVersion, apiDetails, varian } else { if (allowToolcacheValueFF) { logger.info( - `Ignoring 'tools: ${toolsInput}' because the feature is not enabled.` + `Ignoring 'tools: ${toolsInput}' because the workflow was not triggered dynamically.` ); } else { logger.warning( - `Ignoring 'tools: ${toolsInput}' because the workflow was not triggered dynamically.` + `Ignoring 'tools: ${toolsInput}' because the feature is not enabled.` ); } } diff --git a/lib/upload-lib.js b/lib/upload-lib.js index f820544aa9..9697d2eea0 100644 --- a/lib/upload-lib.js +++ b/lib/upload-lib.js @@ -90181,11 +90181,11 @@ async function getCodeQLSource(toolsInput, defaultCliVersion, apiDetails, varian } else { if (allowToolcacheValueFF) { logger.info( - `Ignoring 'tools: ${toolsInput}' because the feature is not enabled.` + `Ignoring 'tools: ${toolsInput}' because the workflow was not triggered dynamically.` ); } else { logger.warning( - `Ignoring 'tools: ${toolsInput}' because the workflow was not triggered dynamically.` + `Ignoring 'tools: ${toolsInput}' because the feature is not enabled.` ); } } diff --git a/lib/upload-sarif-action.js b/lib/upload-sarif-action.js index efd8fe7e88..41b14acad1 100644 --- a/lib/upload-sarif-action.js +++ b/lib/upload-sarif-action.js @@ -90852,11 +90852,11 @@ async function getCodeQLSource(toolsInput, defaultCliVersion, apiDetails, varian } else { if (allowToolcacheValueFF) { logger.info( - `Ignoring 'tools: ${toolsInput}' because the feature is not enabled.` + `Ignoring 'tools: ${toolsInput}' because the workflow was not triggered dynamically.` ); } else { logger.warning( - `Ignoring 'tools: ${toolsInput}' because the workflow was not triggered dynamically.` + `Ignoring 'tools: ${toolsInput}' because the feature is not enabled.` ); } } diff --git a/src/setup-codeql.ts b/src/setup-codeql.ts index 35b831f560..1a938ca891 100644 --- a/src/setup-codeql.ts +++ b/src/setup-codeql.ts @@ -386,11 +386,11 @@ export async function getCodeQLSource( } else { if (allowToolcacheValueFF) { logger.info( - `Ignoring 'tools: ${toolsInput}' because the feature is not enabled.`, + `Ignoring 'tools: ${toolsInput}' because the workflow was not triggered dynamically.`, ); } else { logger.warning( - `Ignoring 'tools: ${toolsInput}' because the workflow was not triggered dynamically.`, + `Ignoring 'tools: ${toolsInput}' because the feature is not enabled.`, ); } } From 5c752c85dd2b8139dd3f3a8be1c0a35ffb4b82c4 Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Fri, 10 Oct 2025 14:15:08 +0100 Subject: [PATCH 4/6] Add test macro for fallback tests --- src/setup-codeql.test.ts | 113 +++++++++++++++++++++++---------------- 1 file changed, 66 insertions(+), 47 deletions(-) diff --git a/src/setup-codeql.test.ts b/src/setup-codeql.test.ts index 561dfb4e58..d02bf59e6e 100644 --- a/src/setup-codeql.test.ts +++ b/src/setup-codeql.test.ts @@ -1,7 +1,7 @@ import * as path from "path"; import * as toolcache from "@actions/tool-cache"; -import test from "ava"; +import test, { ExecutionContext } from "ava"; import * as sinon from "sinon"; import * as actionsUtil from "./actions-util"; @@ -331,58 +331,77 @@ test("getCodeQLSource correctly returns latest version from toolcache when tools }); }); -test("getCodeQLSource falls back to downloading the CLI if the toolcache doesn't have a CodeQL CLI when tools == toolcache", async (t) => { - const loggedMessages: LoggedMessage[] = []; - const logger = getRecordingLogger(loggedMessages); - const features = createFeatures([Feature.AllowToolcacheInput]); - - process.env["GITHUB_EVENT_NAME"] = "dynamic"; - - const testVersions = []; - const findAllVersionsStub = sinon - .stub(toolcache, "findAllVersions") - .returns(testVersions); - - await withTmpDir(async (tmpDir) => { - setupActionsVars(tmpDir, tmpDir); - const source = await setupCodeql.getCodeQLSource( - "toolcache", - SAMPLE_DEFAULT_CLI_VERSION, - SAMPLE_DOTCOM_API_DETAILS, - GitHubVariant.DOTCOM, - false, - features, - logger, - ); - - // Check that the toolcache functions were called with the expected arguments - t.assert( - findAllVersionsStub.calledWith("CodeQL"), - `toolcache.findAllVersions("CodeQL") wasn't called`, - ); +const toolcacheInputFallbackMacro = test.macro({ + exec: async ( + t: ExecutionContext, + featureList: Feature[], + environment: Record, + testVersions: string[], + expectedMessages: string[], + ) => { + const loggedMessages: LoggedMessage[] = []; + const logger = getRecordingLogger(loggedMessages); + const features = createFeatures(featureList); + + for (const [k, v] of Object.entries(environment)) { + process.env[k] = v; + } - // Check that `sourceType` and `toolsVersion` match expectations. - t.is(source.sourceType, "download"); - t.is(source.toolsVersion, SAMPLE_DEFAULT_CLI_VERSION.cliVersion); + const findAllVersionsStub = sinon + .stub(toolcache, "findAllVersions") + .returns(testVersions); + + await withTmpDir(async (tmpDir) => { + setupActionsVars(tmpDir, tmpDir); + const source = await setupCodeql.getCodeQLSource( + "toolcache", + SAMPLE_DEFAULT_CLI_VERSION, + SAMPLE_DOTCOM_API_DETAILS, + GitHubVariant.DOTCOM, + false, + features, + logger, + ); - // Check that key messages we would expect to find in the log are present. - const expectedMessages: string[] = [ - `Attempting to use the latest CodeQL CLI version in the toolcache, as requested by 'tools: toolcache'.`, - `Found no CodeQL CLI in the toolcache, ignoring 'tools: toolcache'...`, - ]; - for (const expectedMessage of expectedMessages) { + // Check that the toolcache functions were called with the expected arguments t.assert( - loggedMessages.some( - (msg) => - typeof msg.message === "string" && - msg.message.includes(expectedMessage), - ), - `Expected '${expectedMessage}' in the logger output, but didn't find it.`, + findAllVersionsStub.calledWith("CodeQL"), + `toolcache.findAllVersions("CodeQL") wasn't called`, ); - } - }); + + // Check that `sourceType` and `toolsVersion` match expectations. + t.is(source.sourceType, "download"); + t.is(source.toolsVersion, SAMPLE_DEFAULT_CLI_VERSION.cliVersion); + + // Check that key messages we would expect to find in the log are present. + for (const expectedMessage of expectedMessages) { + t.assert( + loggedMessages.some( + (msg) => + typeof msg.message === "string" && + msg.message.includes(expectedMessage), + ), + `Expected '${expectedMessage}' in the logger output, but didn't find it.`, + ); + } + }); + }, + title: (providedTitle = "") => + `getCodeQLSource falls back to downloading the CLI if ${providedTitle}`, }); +test( + "the toolcache doesn't have a CodeQL CLI when tools == toolcache", + toolcacheInputFallbackMacro, + [Feature.AllowToolcacheInput], + { GITHUB_EVENT_NAME: "dynamic" }, + [], + [ + `Attempting to use the latest CodeQL CLI version in the toolcache, as requested by 'tools: toolcache'.`, + `Found no CodeQL CLI in the toolcache, ignoring 'tools: toolcache'...`, + ], +); + test('tryGetTagNameFromUrl extracts the right tag name for a repo name containing "codeql-bundle"', (t) => { t.is( setupCodeql.tryGetTagNameFromUrl( From dc2ced8385fe206c30e6accdd2d900759080cadf Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Fri, 10 Oct 2025 14:20:51 +0100 Subject: [PATCH 5/6] Add tests for scenarios where the feature is unavailable --- src/setup-codeql.test.ts | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/src/setup-codeql.test.ts b/src/setup-codeql.test.ts index d02bf59e6e..3046b6ff56 100644 --- a/src/setup-codeql.test.ts +++ b/src/setup-codeql.test.ts @@ -325,7 +325,7 @@ test("getCodeQLSource correctly returns latest version from toolcache when tools typeof msg.message === "string" && msg.message.includes(expectedMessage), ), - `Expected '${expectedMessage}' in the logger output, but didn't find it.`, + `Expected '${expectedMessage}' in the logger output, but didn't find it in:\n ${loggedMessages.map((m) => ` - '${m.message}'`).join("\n")}`, ); } }); @@ -381,7 +381,7 @@ const toolcacheInputFallbackMacro = test.macro({ typeof msg.message === "string" && msg.message.includes(expectedMessage), ), - `Expected '${expectedMessage}' in the logger output, but didn't find it.`, + `Expected '${expectedMessage}' in the logger output, but didn't find it in:\n ${loggedMessages.map((m) => ` - '${m.message}'`).join("\n")}`, ); } }); @@ -402,6 +402,26 @@ test( ], ); +test( + "the workflow trigger is not `dynamic`", + toolcacheInputFallbackMacro, + [Feature.AllowToolcacheInput], + { GITHUB_EVENT_NAME: "pull_request" }, + [], + [ + `Ignoring 'tools: toolcache' because the workflow was not triggered dynamically.`, + ], +); + +test( + "the feature flag is not enabled", + toolcacheInputFallbackMacro, + [], + { GITHUB_EVENT_NAME: "dynamic" }, + [], + [`Ignoring 'tools: toolcache' because the feature is not enabled.`], +); + test('tryGetTagNameFromUrl extracts the right tag name for a repo name containing "codeql-bundle"', (t) => { t.is( setupCodeql.tryGetTagNameFromUrl( From 4704ab18691cbc020ec00ac79ac5eb698ad192bc Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Fri, 10 Oct 2025 14:42:09 +0100 Subject: [PATCH 6/6] Fix swapped log levels --- lib/analyze-action.js | 4 ++-- lib/init-action-post.js | 4 ++-- lib/init-action.js | 4 ++-- lib/upload-lib.js | 4 ++-- lib/upload-sarif-action.js | 4 ++-- src/setup-codeql.ts | 4 ++-- 6 files changed, 12 insertions(+), 12 deletions(-) diff --git a/lib/analyze-action.js b/lib/analyze-action.js index 8b30d734f4..0f0e38d97a 100644 --- a/lib/analyze-action.js +++ b/lib/analyze-action.js @@ -92363,11 +92363,11 @@ async function getCodeQLSource(toolsInput, defaultCliVersion, apiDetails, varian ); } else { if (allowToolcacheValueFF) { - logger.info( + logger.warning( `Ignoring 'tools: ${toolsInput}' because the workflow was not triggered dynamically.` ); } else { - logger.warning( + logger.info( `Ignoring 'tools: ${toolsInput}' because the feature is not enabled.` ); } diff --git a/lib/init-action-post.js b/lib/init-action-post.js index 553b7d150a..8b283fbe66 100644 --- a/lib/init-action-post.js +++ b/lib/init-action-post.js @@ -130345,11 +130345,11 @@ async function getCodeQLSource(toolsInput, defaultCliVersion, apiDetails, varian ); } else { if (allowToolcacheValueFF) { - logger.info( + logger.warning( `Ignoring 'tools: ${toolsInput}' because the workflow was not triggered dynamically.` ); } else { - logger.warning( + logger.info( `Ignoring 'tools: ${toolsInput}' because the feature is not enabled.` ); } diff --git a/lib/init-action.js b/lib/init-action.js index e3f3ddacd8..d47e42a785 100644 --- a/lib/init-action.js +++ b/lib/init-action.js @@ -89141,11 +89141,11 @@ async function getCodeQLSource(toolsInput, defaultCliVersion, apiDetails, varian ); } else { if (allowToolcacheValueFF) { - logger.info( + logger.warning( `Ignoring 'tools: ${toolsInput}' because the workflow was not triggered dynamically.` ); } else { - logger.warning( + logger.info( `Ignoring 'tools: ${toolsInput}' because the feature is not enabled.` ); } diff --git a/lib/upload-lib.js b/lib/upload-lib.js index 9697d2eea0..65b0566031 100644 --- a/lib/upload-lib.js +++ b/lib/upload-lib.js @@ -90180,11 +90180,11 @@ async function getCodeQLSource(toolsInput, defaultCliVersion, apiDetails, varian ); } else { if (allowToolcacheValueFF) { - logger.info( + logger.warning( `Ignoring 'tools: ${toolsInput}' because the workflow was not triggered dynamically.` ); } else { - logger.warning( + logger.info( `Ignoring 'tools: ${toolsInput}' because the feature is not enabled.` ); } diff --git a/lib/upload-sarif-action.js b/lib/upload-sarif-action.js index 41b14acad1..7be0ff8b11 100644 --- a/lib/upload-sarif-action.js +++ b/lib/upload-sarif-action.js @@ -90851,11 +90851,11 @@ async function getCodeQLSource(toolsInput, defaultCliVersion, apiDetails, varian ); } else { if (allowToolcacheValueFF) { - logger.info( + logger.warning( `Ignoring 'tools: ${toolsInput}' because the workflow was not triggered dynamically.` ); } else { - logger.warning( + logger.info( `Ignoring 'tools: ${toolsInput}' because the feature is not enabled.` ); } diff --git a/src/setup-codeql.ts b/src/setup-codeql.ts index 1a938ca891..9ee0c4b82a 100644 --- a/src/setup-codeql.ts +++ b/src/setup-codeql.ts @@ -385,11 +385,11 @@ export async function getCodeQLSource( ); } else { if (allowToolcacheValueFF) { - logger.info( + logger.warning( `Ignoring 'tools: ${toolsInput}' because the workflow was not triggered dynamically.`, ); } else { - logger.warning( + logger.info( `Ignoring 'tools: ${toolsInput}' because the feature is not enabled.`, ); }