diff --git a/lib/analyze-action-post.js b/lib/analyze-action-post.js index b501469f5e..fc411ec94e 100644 --- a/lib/analyze-action-post.js +++ b/lib/analyze-action-post.js @@ -162033,6 +162033,7 @@ var RepositoryPropertyName = /* @__PURE__ */ ((RepositoryPropertyName2) => { RepositoryPropertyName2["DISABLE_OVERLAY"] = "github-codeql-disable-overlay"; RepositoryPropertyName2["EXTRA_QUERIES"] = "github-codeql-extra-queries"; RepositoryPropertyName2["FILE_COVERAGE_ON_PRS"] = "github-codeql-file-coverage-on-prs"; + RepositoryPropertyName2["TOOLS"] = "github-codeql-tools"; return RepositoryPropertyName2; })(RepositoryPropertyName || {}); var KNOWN_REPOSITORY_PROPERTY_NAMES = new Set( diff --git a/lib/analyze-action.js b/lib/analyze-action.js index 7f7f4fbe88..592c059dd9 100644 --- a/lib/analyze-action.js +++ b/lib/analyze-action.js @@ -107537,6 +107537,7 @@ var RepositoryPropertyName = /* @__PURE__ */ ((RepositoryPropertyName2) => { RepositoryPropertyName2["DISABLE_OVERLAY"] = "github-codeql-disable-overlay"; RepositoryPropertyName2["EXTRA_QUERIES"] = "github-codeql-extra-queries"; RepositoryPropertyName2["FILE_COVERAGE_ON_PRS"] = "github-codeql-file-coverage-on-prs"; + RepositoryPropertyName2["TOOLS"] = "github-codeql-tools"; return RepositoryPropertyName2; })(RepositoryPropertyName || {}); var KNOWN_REPOSITORY_PROPERTY_NAMES = new Set( @@ -109491,7 +109492,7 @@ async function findOverridingToolsInCache(humanReadableVersion, logger) { } return void 0; } -async function getCodeQLSource(toolsInput, defaultCliVersion, apiDetails, variant, tarSupportsZstd, features, logger) { +async function getCodeQLSource(toolsInput, defaultCliVersion, apiDetails, variant, tarSupportsZstd, features, logger, toolsInputFromRepositoryProperty = false) { if (toolsInput && !isReservedToolsValue(toolsInput) && !toolsInput.startsWith("http")) { logger.info(`Using CodeQL CLI from local path ${toolsInput}`); const compressionMethod2 = inferCompressionMethod(toolsInput); @@ -109559,11 +109560,17 @@ async function getCodeQLSource(toolsInput, defaultCliVersion, apiDetails, varian const allowToolcacheValueFF = await features.getValue( "allow_toolcache_input" /* AllowToolcacheInput */ ); - const allowToolcacheValue = allowToolcacheValueFF && (isDynamicWorkflow() || isInTestMode()); + const allowToolcacheValue = toolsInputFromRepositoryProperty || allowToolcacheValueFF && (isDynamicWorkflow() || isInTestMode()); if (allowToolcacheValue) { - logger.info( - `Attempting to use the latest CodeQL CLI version in the toolcache, as requested by 'tools: ${toolsInput}'.` - ); + if (toolsInputFromRepositoryProperty) { + logger.info( + `Attempting to use the latest CodeQL CLI version in the toolcache, as requested by the 'github-codeql-tools' repository property.` + ); + } else { + logger.info( + `Attempting to use the latest CodeQL CLI version in the toolcache, as requested by 'tools: ${toolsInput}'.` + ); + } latestToolcacheVersion = getLatestToolcacheVersion(logger); if (latestToolcacheVersion) { cliVersion2 = latestToolcacheVersion; @@ -109571,9 +109578,15 @@ async function getCodeQLSource(toolsInput, defaultCliVersion, apiDetails, varian } if (latestToolcacheVersion === void 0) { if (allowToolcacheValue) { - logger.info( - `Found no CodeQL CLI in the toolcache, ignoring 'tools: ${toolsInput}'...` - ); + if (toolsInputFromRepositoryProperty) { + logger.info( + `Found no CodeQL CLI in the toolcache, ignoring the 'github-codeql-tools' repository property...` + ); + } else { + logger.info( + `Found no CodeQL CLI in the toolcache, ignoring 'tools: ${toolsInput}'...` + ); + } } else { if (allowToolcacheValueFF) { logger.warning( @@ -109796,7 +109809,7 @@ function getCanonicalToolcacheVersion(cliVersion2, bundleVersion2, logger) { } return cliVersion2; } -async function setupCodeQLBundle(toolsInput, apiDetails, tempDir, variant, defaultCliVersion, features, logger) { +async function setupCodeQLBundle(toolsInput, apiDetails, tempDir, variant, defaultCliVersion, features, logger, toolsInputFromRepositoryProperty = false) { if (!await isBinaryAccessible("tar", logger)) { throw new ConfigurationError( "Could not find tar in PATH, so unable to extract CodeQL bundle." @@ -109810,7 +109823,8 @@ async function setupCodeQLBundle(toolsInput, apiDetails, tempDir, variant, defau variant, zstdAvailability.available, features, - logger + logger, + toolsInputFromRepositoryProperty ); let codeqlFolder; let toolsVersion = source.toolsVersion; @@ -109966,7 +109980,7 @@ var CODEQL_NEXT_MINIMUM_VERSION = "2.17.6"; var GHES_VERSION_MOST_RECENTLY_DEPRECATED = "3.13"; var GHES_MOST_RECENT_DEPRECATION_DATE = "2025-06-19"; var EXTRACTION_DEBUG_MODE_VERBOSITY = "progress++"; -async function setupCodeQL(toolsInput, apiDetails, tempDir, variant, defaultCliVersion, features, logger, checkVersion) { +async function setupCodeQL(toolsInput, apiDetails, tempDir, variant, defaultCliVersion, features, logger, checkVersion, toolsInputFromRepositoryProperty = false) { try { const { codeqlFolder, @@ -109981,7 +109995,8 @@ async function setupCodeQL(toolsInput, apiDetails, tempDir, variant, defaultCliV variant, defaultCliVersion, features, - logger + logger, + toolsInputFromRepositoryProperty ); logger.debug( `Bundle download status report: ${JSON.stringify( @@ -112679,7 +112694,7 @@ var core14 = __toESM(require_core()); var toolrunner4 = __toESM(require_toolrunner()); var github2 = __toESM(require_github()); var io6 = __toESM(require_io()); -async function initCodeQL(toolsInput, apiDetails, tempDir, variant, defaultCliVersion, features, logger) { +async function initCodeQL(toolsInput, apiDetails, tempDir, variant, defaultCliVersion, features, logger, toolsInputFromRepositoryProperty = false) { logger.startGroup("Setup CodeQL tools"); const { codeql, @@ -112695,7 +112710,8 @@ async function initCodeQL(toolsInput, apiDetails, tempDir, variant, defaultCliVe defaultCliVersion, features, logger, - true + true, + toolsInputFromRepositoryProperty ); await codeql.printVersion(); logger.endGroup(); diff --git a/lib/autobuild-action.js b/lib/autobuild-action.js index 42d955963e..eabf92cff0 100644 --- a/lib/autobuild-action.js +++ b/lib/autobuild-action.js @@ -104089,6 +104089,7 @@ var RepositoryPropertyName = /* @__PURE__ */ ((RepositoryPropertyName2) => { RepositoryPropertyName2["DISABLE_OVERLAY"] = "github-codeql-disable-overlay"; RepositoryPropertyName2["EXTRA_QUERIES"] = "github-codeql-extra-queries"; RepositoryPropertyName2["FILE_COVERAGE_ON_PRS"] = "github-codeql-file-coverage-on-prs"; + RepositoryPropertyName2["TOOLS"] = "github-codeql-tools"; return RepositoryPropertyName2; })(RepositoryPropertyName || {}); var KNOWN_REPOSITORY_PROPERTY_NAMES = new Set( diff --git a/lib/init-action-post.js b/lib/init-action-post.js index 27cb1e9b40..4897dc4669 100644 --- a/lib/init-action-post.js +++ b/lib/init-action-post.js @@ -165431,6 +165431,7 @@ var RepositoryPropertyName = /* @__PURE__ */ ((RepositoryPropertyName2) => { RepositoryPropertyName2["DISABLE_OVERLAY"] = "github-codeql-disable-overlay"; RepositoryPropertyName2["EXTRA_QUERIES"] = "github-codeql-extra-queries"; RepositoryPropertyName2["FILE_COVERAGE_ON_PRS"] = "github-codeql-file-coverage-on-prs"; + RepositoryPropertyName2["TOOLS"] = "github-codeql-tools"; return RepositoryPropertyName2; })(RepositoryPropertyName || {}); var KNOWN_REPOSITORY_PROPERTY_NAMES = new Set( @@ -167044,7 +167045,7 @@ async function findOverridingToolsInCache(humanReadableVersion, logger) { } return void 0; } -async function getCodeQLSource(toolsInput, defaultCliVersion, apiDetails, variant, tarSupportsZstd, features, logger) { +async function getCodeQLSource(toolsInput, defaultCliVersion, apiDetails, variant, tarSupportsZstd, features, logger, toolsInputFromRepositoryProperty = false) { if (toolsInput && !isReservedToolsValue(toolsInput) && !toolsInput.startsWith("http")) { logger.info(`Using CodeQL CLI from local path ${toolsInput}`); const compressionMethod2 = inferCompressionMethod(toolsInput); @@ -167112,11 +167113,17 @@ async function getCodeQLSource(toolsInput, defaultCliVersion, apiDetails, varian const allowToolcacheValueFF = await features.getValue( "allow_toolcache_input" /* AllowToolcacheInput */ ); - const allowToolcacheValue = allowToolcacheValueFF && (isDynamicWorkflow() || isInTestMode()); + const allowToolcacheValue = toolsInputFromRepositoryProperty || allowToolcacheValueFF && (isDynamicWorkflow() || isInTestMode()); if (allowToolcacheValue) { - logger.info( - `Attempting to use the latest CodeQL CLI version in the toolcache, as requested by 'tools: ${toolsInput}'.` - ); + if (toolsInputFromRepositoryProperty) { + logger.info( + `Attempting to use the latest CodeQL CLI version in the toolcache, as requested by the 'github-codeql-tools' repository property.` + ); + } else { + logger.info( + `Attempting to use the latest CodeQL CLI version in the toolcache, as requested by 'tools: ${toolsInput}'.` + ); + } latestToolcacheVersion = getLatestToolcacheVersion(logger); if (latestToolcacheVersion) { cliVersion2 = latestToolcacheVersion; @@ -167124,9 +167131,15 @@ async function getCodeQLSource(toolsInput, defaultCliVersion, apiDetails, varian } if (latestToolcacheVersion === void 0) { if (allowToolcacheValue) { - logger.info( - `Found no CodeQL CLI in the toolcache, ignoring 'tools: ${toolsInput}'...` - ); + if (toolsInputFromRepositoryProperty) { + logger.info( + `Found no CodeQL CLI in the toolcache, ignoring the 'github-codeql-tools' repository property...` + ); + } else { + logger.info( + `Found no CodeQL CLI in the toolcache, ignoring 'tools: ${toolsInput}'...` + ); + } } else { if (allowToolcacheValueFF) { logger.warning( @@ -167349,7 +167362,7 @@ function getCanonicalToolcacheVersion(cliVersion2, bundleVersion2, logger) { } return cliVersion2; } -async function setupCodeQLBundle(toolsInput, apiDetails, tempDir, variant, defaultCliVersion, features, logger) { +async function setupCodeQLBundle(toolsInput, apiDetails, tempDir, variant, defaultCliVersion, features, logger, toolsInputFromRepositoryProperty = false) { if (!await isBinaryAccessible("tar", logger)) { throw new ConfigurationError( "Could not find tar in PATH, so unable to extract CodeQL bundle." @@ -167363,7 +167376,8 @@ async function setupCodeQLBundle(toolsInput, apiDetails, tempDir, variant, defau variant, zstdAvailability.available, features, - logger + logger, + toolsInputFromRepositoryProperty ); let codeqlFolder; let toolsVersion = source.toolsVersion; @@ -167486,7 +167500,7 @@ var CODEQL_NEXT_MINIMUM_VERSION = "2.17.6"; var GHES_VERSION_MOST_RECENTLY_DEPRECATED = "3.13"; var GHES_MOST_RECENT_DEPRECATION_DATE = "2025-06-19"; var EXTRACTION_DEBUG_MODE_VERBOSITY = "progress++"; -async function setupCodeQL(toolsInput, apiDetails, tempDir, variant, defaultCliVersion, features, logger, checkVersion) { +async function setupCodeQL(toolsInput, apiDetails, tempDir, variant, defaultCliVersion, features, logger, checkVersion, toolsInputFromRepositoryProperty = false) { try { const { codeqlFolder, @@ -167501,7 +167515,8 @@ async function setupCodeQL(toolsInput, apiDetails, tempDir, variant, defaultCliV variant, defaultCliVersion, features, - logger + logger, + toolsInputFromRepositoryProperty ); logger.debug( `Bundle download status report: ${JSON.stringify( @@ -169756,7 +169771,7 @@ var core14 = __toESM(require_core()); var toolrunner4 = __toESM(require_toolrunner()); var github2 = __toESM(require_github()); var io6 = __toESM(require_io()); -async function initCodeQL(toolsInput, apiDetails, tempDir, variant, defaultCliVersion, features, logger) { +async function initCodeQL(toolsInput, apiDetails, tempDir, variant, defaultCliVersion, features, logger, toolsInputFromRepositoryProperty = false) { logger.startGroup("Setup CodeQL tools"); const { codeql, @@ -169772,7 +169787,8 @@ async function initCodeQL(toolsInput, apiDetails, tempDir, variant, defaultCliVe defaultCliVersion, features, logger, - true + true, + toolsInputFromRepositoryProperty ); await codeql.printVersion(); logger.endGroup(); diff --git a/lib/init-action.js b/lib/init-action.js index 625562ed91..98f1a259ea 100644 --- a/lib/init-action.js +++ b/lib/init-action.js @@ -104710,6 +104710,7 @@ var RepositoryPropertyName = /* @__PURE__ */ ((RepositoryPropertyName2) => { RepositoryPropertyName2["DISABLE_OVERLAY"] = "github-codeql-disable-overlay"; RepositoryPropertyName2["EXTRA_QUERIES"] = "github-codeql-extra-queries"; RepositoryPropertyName2["FILE_COVERAGE_ON_PRS"] = "github-codeql-file-coverage-on-prs"; + RepositoryPropertyName2["TOOLS"] = "github-codeql-tools"; return RepositoryPropertyName2; })(RepositoryPropertyName || {}); function isString2(value) { @@ -104727,7 +104728,8 @@ var booleanProperty = { var repositoryPropertyParsers = { ["github-codeql-disable-overlay" /* DISABLE_OVERLAY */]: booleanProperty, ["github-codeql-extra-queries" /* EXTRA_QUERIES */]: stringProperty, - ["github-codeql-file-coverage-on-prs" /* FILE_COVERAGE_ON_PRS */]: booleanProperty + ["github-codeql-file-coverage-on-prs" /* FILE_COVERAGE_ON_PRS */]: booleanProperty, + ["github-codeql-tools" /* TOOLS */]: stringProperty }; async function loadPropertiesFromApi(logger, repositoryNwo) { try { @@ -108177,7 +108179,7 @@ async function findOverridingToolsInCache(humanReadableVersion, logger) { } return void 0; } -async function getCodeQLSource(toolsInput, defaultCliVersion, apiDetails, variant, tarSupportsZstd, features, logger) { +async function getCodeQLSource(toolsInput, defaultCliVersion, apiDetails, variant, tarSupportsZstd, features, logger, toolsInputFromRepositoryProperty = false) { if (toolsInput && !isReservedToolsValue(toolsInput) && !toolsInput.startsWith("http")) { logger.info(`Using CodeQL CLI from local path ${toolsInput}`); const compressionMethod2 = inferCompressionMethod(toolsInput); @@ -108245,11 +108247,17 @@ async function getCodeQLSource(toolsInput, defaultCliVersion, apiDetails, varian const allowToolcacheValueFF = await features.getValue( "allow_toolcache_input" /* AllowToolcacheInput */ ); - const allowToolcacheValue = allowToolcacheValueFF && (isDynamicWorkflow() || isInTestMode()); + const allowToolcacheValue = toolsInputFromRepositoryProperty || allowToolcacheValueFF && (isDynamicWorkflow() || isInTestMode()); if (allowToolcacheValue) { - logger.info( - `Attempting to use the latest CodeQL CLI version in the toolcache, as requested by 'tools: ${toolsInput}'.` - ); + if (toolsInputFromRepositoryProperty) { + logger.info( + `Attempting to use the latest CodeQL CLI version in the toolcache, as requested by the 'github-codeql-tools' repository property.` + ); + } else { + logger.info( + `Attempting to use the latest CodeQL CLI version in the toolcache, as requested by 'tools: ${toolsInput}'.` + ); + } latestToolcacheVersion = getLatestToolcacheVersion(logger); if (latestToolcacheVersion) { cliVersion2 = latestToolcacheVersion; @@ -108257,9 +108265,15 @@ async function getCodeQLSource(toolsInput, defaultCliVersion, apiDetails, varian } if (latestToolcacheVersion === void 0) { if (allowToolcacheValue) { - logger.info( - `Found no CodeQL CLI in the toolcache, ignoring 'tools: ${toolsInput}'...` - ); + if (toolsInputFromRepositoryProperty) { + logger.info( + `Found no CodeQL CLI in the toolcache, ignoring the 'github-codeql-tools' repository property...` + ); + } else { + logger.info( + `Found no CodeQL CLI in the toolcache, ignoring 'tools: ${toolsInput}'...` + ); + } } else { if (allowToolcacheValueFF) { logger.warning( @@ -108482,7 +108496,7 @@ function getCanonicalToolcacheVersion(cliVersion2, bundleVersion2, logger) { } return cliVersion2; } -async function setupCodeQLBundle(toolsInput, apiDetails, tempDir, variant, defaultCliVersion, features, logger) { +async function setupCodeQLBundle(toolsInput, apiDetails, tempDir, variant, defaultCliVersion, features, logger, toolsInputFromRepositoryProperty = false) { if (!await isBinaryAccessible("tar", logger)) { throw new ConfigurationError( "Could not find tar in PATH, so unable to extract CodeQL bundle." @@ -108496,7 +108510,8 @@ async function setupCodeQLBundle(toolsInput, apiDetails, tempDir, variant, defau variant, zstdAvailability.available, features, - logger + logger, + toolsInputFromRepositoryProperty ); let codeqlFolder; let toolsVersion = source.toolsVersion; @@ -108641,7 +108656,7 @@ var CODEQL_NEXT_MINIMUM_VERSION = "2.17.6"; var GHES_VERSION_MOST_RECENTLY_DEPRECATED = "3.13"; var GHES_MOST_RECENT_DEPRECATION_DATE = "2025-06-19"; var EXTRACTION_DEBUG_MODE_VERBOSITY = "progress++"; -async function setupCodeQL(toolsInput, apiDetails, tempDir, variant, defaultCliVersion, features, logger, checkVersion) { +async function setupCodeQL(toolsInput, apiDetails, tempDir, variant, defaultCliVersion, features, logger, checkVersion, toolsInputFromRepositoryProperty = false) { try { const { codeqlFolder, @@ -108656,7 +108671,8 @@ async function setupCodeQL(toolsInput, apiDetails, tempDir, variant, defaultCliV variant, defaultCliVersion, features, - logger + logger, + toolsInputFromRepositoryProperty ); logger.debug( `Bundle download status report: ${JSON.stringify( @@ -109244,7 +109260,7 @@ async function getJobRunUuidSarifOptions(codeql) { } // src/init.ts -async function initCodeQL(toolsInput, apiDetails, tempDir, variant, defaultCliVersion, features, logger) { +async function initCodeQL(toolsInput, apiDetails, tempDir, variant, defaultCliVersion, features, logger, toolsInputFromRepositoryProperty = false) { logger.startGroup("Setup CodeQL tools"); const { codeql, @@ -109260,7 +109276,8 @@ async function initCodeQL(toolsInput, apiDetails, tempDir, variant, defaultCliVe defaultCliVersion, features, logger, - true + true, + toolsInputFromRepositoryProperty ); await codeql.printVersion(); logger.endGroup(); @@ -110042,14 +110059,19 @@ async function run(startedAt) { gitHubVersion.type ); toolsFeatureFlagsValid = codeQLDefaultVersionInfo.toolsFeatureFlagsValid; + const toolsWorkflowInput = getOptionalInput("tools"); + const toolsPropertyValue = repositoryPropertiesResult.orElse({})["github-codeql-tools" /* TOOLS */]; + const effectiveToolsInput = toolsWorkflowInput ?? toolsPropertyValue; + const toolsInputFromRepositoryProperty = toolsWorkflowInput === void 0 && toolsPropertyValue !== void 0; const initCodeQLResult = await initCodeQL( - getOptionalInput("tools"), + effectiveToolsInput, apiDetails, getTemporaryDirectory(), gitHubVersion.type, codeQLDefaultVersionInfo, features, - logger + logger, + toolsInputFromRepositoryProperty ); codeql = initCodeQLResult.codeql; toolsDownloadStatusReport = initCodeQLResult.toolsDownloadStatusReport; diff --git a/lib/resolve-environment-action.js b/lib/resolve-environment-action.js index df13d019d4..f4abd56335 100644 --- a/lib/resolve-environment-action.js +++ b/lib/resolve-environment-action.js @@ -104088,6 +104088,7 @@ var RepositoryPropertyName = /* @__PURE__ */ ((RepositoryPropertyName2) => { RepositoryPropertyName2["DISABLE_OVERLAY"] = "github-codeql-disable-overlay"; RepositoryPropertyName2["EXTRA_QUERIES"] = "github-codeql-extra-queries"; RepositoryPropertyName2["FILE_COVERAGE_ON_PRS"] = "github-codeql-file-coverage-on-prs"; + RepositoryPropertyName2["TOOLS"] = "github-codeql-tools"; return RepositoryPropertyName2; })(RepositoryPropertyName || {}); var KNOWN_REPOSITORY_PROPERTY_NAMES = new Set( diff --git a/lib/setup-codeql-action.js b/lib/setup-codeql-action.js index e710db4911..90052f7930 100644 --- a/lib/setup-codeql-action.js +++ b/lib/setup-codeql-action.js @@ -105069,6 +105069,7 @@ var RepositoryPropertyName = /* @__PURE__ */ ((RepositoryPropertyName2) => { RepositoryPropertyName2["DISABLE_OVERLAY"] = "github-codeql-disable-overlay"; RepositoryPropertyName2["EXTRA_QUERIES"] = "github-codeql-extra-queries"; RepositoryPropertyName2["FILE_COVERAGE_ON_PRS"] = "github-codeql-file-coverage-on-prs"; + RepositoryPropertyName2["TOOLS"] = "github-codeql-tools"; return RepositoryPropertyName2; })(RepositoryPropertyName || {}); var KNOWN_REPOSITORY_PROPERTY_NAMES = new Set( @@ -105658,7 +105659,7 @@ async function findOverridingToolsInCache(humanReadableVersion, logger) { } return void 0; } -async function getCodeQLSource(toolsInput, defaultCliVersion, apiDetails, variant, tarSupportsZstd, features, logger) { +async function getCodeQLSource(toolsInput, defaultCliVersion, apiDetails, variant, tarSupportsZstd, features, logger, toolsInputFromRepositoryProperty = false) { if (toolsInput && !isReservedToolsValue(toolsInput) && !toolsInput.startsWith("http")) { logger.info(`Using CodeQL CLI from local path ${toolsInput}`); const compressionMethod2 = inferCompressionMethod(toolsInput); @@ -105726,11 +105727,17 @@ async function getCodeQLSource(toolsInput, defaultCliVersion, apiDetails, varian const allowToolcacheValueFF = await features.getValue( "allow_toolcache_input" /* AllowToolcacheInput */ ); - const allowToolcacheValue = allowToolcacheValueFF && (isDynamicWorkflow() || isInTestMode()); + const allowToolcacheValue = toolsInputFromRepositoryProperty || allowToolcacheValueFF && (isDynamicWorkflow() || isInTestMode()); if (allowToolcacheValue) { - logger.info( - `Attempting to use the latest CodeQL CLI version in the toolcache, as requested by 'tools: ${toolsInput}'.` - ); + if (toolsInputFromRepositoryProperty) { + logger.info( + `Attempting to use the latest CodeQL CLI version in the toolcache, as requested by the 'github-codeql-tools' repository property.` + ); + } else { + logger.info( + `Attempting to use the latest CodeQL CLI version in the toolcache, as requested by 'tools: ${toolsInput}'.` + ); + } latestToolcacheVersion = getLatestToolcacheVersion(logger); if (latestToolcacheVersion) { cliVersion2 = latestToolcacheVersion; @@ -105738,9 +105745,15 @@ async function getCodeQLSource(toolsInput, defaultCliVersion, apiDetails, varian } if (latestToolcacheVersion === void 0) { if (allowToolcacheValue) { - logger.info( - `Found no CodeQL CLI in the toolcache, ignoring 'tools: ${toolsInput}'...` - ); + if (toolsInputFromRepositoryProperty) { + logger.info( + `Found no CodeQL CLI in the toolcache, ignoring the 'github-codeql-tools' repository property...` + ); + } else { + logger.info( + `Found no CodeQL CLI in the toolcache, ignoring 'tools: ${toolsInput}'...` + ); + } } else { if (allowToolcacheValueFF) { logger.warning( @@ -105963,7 +105976,7 @@ function getCanonicalToolcacheVersion(cliVersion2, bundleVersion2, logger) { } return cliVersion2; } -async function setupCodeQLBundle(toolsInput, apiDetails, tempDir, variant, defaultCliVersion, features, logger) { +async function setupCodeQLBundle(toolsInput, apiDetails, tempDir, variant, defaultCliVersion, features, logger, toolsInputFromRepositoryProperty = false) { if (!await isBinaryAccessible("tar", logger)) { throw new ConfigurationError( "Could not find tar in PATH, so unable to extract CodeQL bundle." @@ -105977,7 +105990,8 @@ async function setupCodeQLBundle(toolsInput, apiDetails, tempDir, variant, defau variant, zstdAvailability.available, features, - logger + logger, + toolsInputFromRepositoryProperty ); let codeqlFolder; let toolsVersion = source.toolsVersion; @@ -106100,7 +106114,7 @@ var CODEQL_NEXT_MINIMUM_VERSION = "2.17.6"; var GHES_VERSION_MOST_RECENTLY_DEPRECATED = "3.13"; var GHES_MOST_RECENT_DEPRECATION_DATE = "2025-06-19"; var EXTRACTION_DEBUG_MODE_VERBOSITY = "progress++"; -async function setupCodeQL(toolsInput, apiDetails, tempDir, variant, defaultCliVersion, features, logger, checkVersion) { +async function setupCodeQL(toolsInput, apiDetails, tempDir, variant, defaultCliVersion, features, logger, checkVersion, toolsInputFromRepositoryProperty = false) { try { const { codeqlFolder, @@ -106115,7 +106129,8 @@ async function setupCodeQL(toolsInput, apiDetails, tempDir, variant, defaultCliV variant, defaultCliVersion, features, - logger + logger, + toolsInputFromRepositoryProperty ); logger.debug( `Bundle download status report: ${JSON.stringify( @@ -106703,7 +106718,7 @@ async function getJobRunUuidSarifOptions(codeql) { } // src/init.ts -async function initCodeQL(toolsInput, apiDetails, tempDir, variant, defaultCliVersion, features, logger) { +async function initCodeQL(toolsInput, apiDetails, tempDir, variant, defaultCliVersion, features, logger, toolsInputFromRepositoryProperty = false) { logger.startGroup("Setup CodeQL tools"); const { codeql, @@ -106719,7 +106734,8 @@ async function initCodeQL(toolsInput, apiDetails, tempDir, variant, defaultCliVe defaultCliVersion, features, logger, - true + true, + toolsInputFromRepositoryProperty ); await codeql.printVersion(); logger.endGroup(); diff --git a/lib/start-proxy-action-post.js b/lib/start-proxy-action-post.js index 0160eecbd9..af44aea8b9 100644 --- a/lib/start-proxy-action-post.js +++ b/lib/start-proxy-action-post.js @@ -161668,6 +161668,7 @@ var RepositoryPropertyName = /* @__PURE__ */ ((RepositoryPropertyName2) => { RepositoryPropertyName2["DISABLE_OVERLAY"] = "github-codeql-disable-overlay"; RepositoryPropertyName2["EXTRA_QUERIES"] = "github-codeql-extra-queries"; RepositoryPropertyName2["FILE_COVERAGE_ON_PRS"] = "github-codeql-file-coverage-on-prs"; + RepositoryPropertyName2["TOOLS"] = "github-codeql-tools"; return RepositoryPropertyName2; })(RepositoryPropertyName || {}); var KNOWN_REPOSITORY_PROPERTY_NAMES = new Set( diff --git a/lib/start-proxy-action.js b/lib/start-proxy-action.js index a1b8a027f8..4a26b93a71 100644 --- a/lib/start-proxy-action.js +++ b/lib/start-proxy-action.js @@ -121774,6 +121774,7 @@ var RepositoryPropertyName = /* @__PURE__ */ ((RepositoryPropertyName2) => { RepositoryPropertyName2["DISABLE_OVERLAY"] = "github-codeql-disable-overlay"; RepositoryPropertyName2["EXTRA_QUERIES"] = "github-codeql-extra-queries"; RepositoryPropertyName2["FILE_COVERAGE_ON_PRS"] = "github-codeql-file-coverage-on-prs"; + RepositoryPropertyName2["TOOLS"] = "github-codeql-tools"; return RepositoryPropertyName2; })(RepositoryPropertyName || {}); var KNOWN_REPOSITORY_PROPERTY_NAMES = new Set( diff --git a/lib/upload-lib.js b/lib/upload-lib.js index 485021d43d..5f119603d4 100644 --- a/lib/upload-lib.js +++ b/lib/upload-lib.js @@ -107132,6 +107132,7 @@ var RepositoryPropertyName = /* @__PURE__ */ ((RepositoryPropertyName2) => { RepositoryPropertyName2["DISABLE_OVERLAY"] = "github-codeql-disable-overlay"; RepositoryPropertyName2["EXTRA_QUERIES"] = "github-codeql-extra-queries"; RepositoryPropertyName2["FILE_COVERAGE_ON_PRS"] = "github-codeql-file-coverage-on-prs"; + RepositoryPropertyName2["TOOLS"] = "github-codeql-tools"; return RepositoryPropertyName2; })(RepositoryPropertyName || {}); var KNOWN_REPOSITORY_PROPERTY_NAMES = new Set( @@ -108347,7 +108348,7 @@ async function findOverridingToolsInCache(humanReadableVersion, logger) { } return void 0; } -async function getCodeQLSource(toolsInput, defaultCliVersion, apiDetails, variant, tarSupportsZstd, features, logger) { +async function getCodeQLSource(toolsInput, defaultCliVersion, apiDetails, variant, tarSupportsZstd, features, logger, toolsInputFromRepositoryProperty = false) { if (toolsInput && !isReservedToolsValue(toolsInput) && !toolsInput.startsWith("http")) { logger.info(`Using CodeQL CLI from local path ${toolsInput}`); const compressionMethod2 = inferCompressionMethod(toolsInput); @@ -108415,11 +108416,17 @@ async function getCodeQLSource(toolsInput, defaultCliVersion, apiDetails, varian const allowToolcacheValueFF = await features.getValue( "allow_toolcache_input" /* AllowToolcacheInput */ ); - const allowToolcacheValue = allowToolcacheValueFF && (isDynamicWorkflow() || isInTestMode()); + const allowToolcacheValue = toolsInputFromRepositoryProperty || allowToolcacheValueFF && (isDynamicWorkflow() || isInTestMode()); if (allowToolcacheValue) { - logger.info( - `Attempting to use the latest CodeQL CLI version in the toolcache, as requested by 'tools: ${toolsInput}'.` - ); + if (toolsInputFromRepositoryProperty) { + logger.info( + `Attempting to use the latest CodeQL CLI version in the toolcache, as requested by the 'github-codeql-tools' repository property.` + ); + } else { + logger.info( + `Attempting to use the latest CodeQL CLI version in the toolcache, as requested by 'tools: ${toolsInput}'.` + ); + } latestToolcacheVersion = getLatestToolcacheVersion(logger); if (latestToolcacheVersion) { cliVersion2 = latestToolcacheVersion; @@ -108427,9 +108434,15 @@ async function getCodeQLSource(toolsInput, defaultCliVersion, apiDetails, varian } if (latestToolcacheVersion === void 0) { if (allowToolcacheValue) { - logger.info( - `Found no CodeQL CLI in the toolcache, ignoring 'tools: ${toolsInput}'...` - ); + if (toolsInputFromRepositoryProperty) { + logger.info( + `Found no CodeQL CLI in the toolcache, ignoring the 'github-codeql-tools' repository property...` + ); + } else { + logger.info( + `Found no CodeQL CLI in the toolcache, ignoring 'tools: ${toolsInput}'...` + ); + } } else { if (allowToolcacheValueFF) { logger.warning( @@ -108652,7 +108665,7 @@ function getCanonicalToolcacheVersion(cliVersion2, bundleVersion2, logger) { } return cliVersion2; } -async function setupCodeQLBundle(toolsInput, apiDetails, tempDir, variant, defaultCliVersion, features, logger) { +async function setupCodeQLBundle(toolsInput, apiDetails, tempDir, variant, defaultCliVersion, features, logger, toolsInputFromRepositoryProperty = false) { if (!await isBinaryAccessible("tar", logger)) { throw new ConfigurationError( "Could not find tar in PATH, so unable to extract CodeQL bundle." @@ -108666,7 +108679,8 @@ async function setupCodeQLBundle(toolsInput, apiDetails, tempDir, variant, defau variant, zstdAvailability.available, features, - logger + logger, + toolsInputFromRepositoryProperty ); let codeqlFolder; let toolsVersion = source.toolsVersion; @@ -108789,7 +108803,7 @@ var CODEQL_NEXT_MINIMUM_VERSION = "2.17.6"; var GHES_VERSION_MOST_RECENTLY_DEPRECATED = "3.13"; var GHES_MOST_RECENT_DEPRECATION_DATE = "2025-06-19"; var EXTRACTION_DEBUG_MODE_VERBOSITY = "progress++"; -async function setupCodeQL(toolsInput, apiDetails, tempDir, variant, defaultCliVersion, features, logger, checkVersion) { +async function setupCodeQL(toolsInput, apiDetails, tempDir, variant, defaultCliVersion, features, logger, checkVersion, toolsInputFromRepositoryProperty = false) { try { const { codeqlFolder, @@ -108804,7 +108818,8 @@ async function setupCodeQL(toolsInput, apiDetails, tempDir, variant, defaultCliV variant, defaultCliVersion, features, - logger + logger, + toolsInputFromRepositoryProperty ); logger.debug( `Bundle download status report: ${JSON.stringify( @@ -110524,7 +110539,7 @@ var core12 = __toESM(require_core()); var toolrunner4 = __toESM(require_toolrunner()); var github2 = __toESM(require_github()); var io5 = __toESM(require_io()); -async function initCodeQL(toolsInput, apiDetails, tempDir, variant, defaultCliVersion, features, logger) { +async function initCodeQL(toolsInput, apiDetails, tempDir, variant, defaultCliVersion, features, logger, toolsInputFromRepositoryProperty = false) { logger.startGroup("Setup CodeQL tools"); const { codeql, @@ -110540,7 +110555,8 @@ async function initCodeQL(toolsInput, apiDetails, tempDir, variant, defaultCliVe defaultCliVersion, features, logger, - true + true, + toolsInputFromRepositoryProperty ); await codeql.printVersion(); logger.endGroup(); diff --git a/lib/upload-sarif-action-post.js b/lib/upload-sarif-action-post.js index 74a5b57fd9..a8f4d79cc1 100644 --- a/lib/upload-sarif-action-post.js +++ b/lib/upload-sarif-action-post.js @@ -161820,6 +161820,7 @@ var RepositoryPropertyName = /* @__PURE__ */ ((RepositoryPropertyName2) => { RepositoryPropertyName2["DISABLE_OVERLAY"] = "github-codeql-disable-overlay"; RepositoryPropertyName2["EXTRA_QUERIES"] = "github-codeql-extra-queries"; RepositoryPropertyName2["FILE_COVERAGE_ON_PRS"] = "github-codeql-file-coverage-on-prs"; + RepositoryPropertyName2["TOOLS"] = "github-codeql-tools"; return RepositoryPropertyName2; })(RepositoryPropertyName || {}); var KNOWN_REPOSITORY_PROPERTY_NAMES = new Set( diff --git a/lib/upload-sarif-action.js b/lib/upload-sarif-action.js index 484025f829..9042fe0c10 100644 --- a/lib/upload-sarif-action.js +++ b/lib/upload-sarif-action.js @@ -107858,6 +107858,7 @@ var RepositoryPropertyName = /* @__PURE__ */ ((RepositoryPropertyName2) => { RepositoryPropertyName2["DISABLE_OVERLAY"] = "github-codeql-disable-overlay"; RepositoryPropertyName2["EXTRA_QUERIES"] = "github-codeql-extra-queries"; RepositoryPropertyName2["FILE_COVERAGE_ON_PRS"] = "github-codeql-file-coverage-on-prs"; + RepositoryPropertyName2["TOOLS"] = "github-codeql-tools"; return RepositoryPropertyName2; })(RepositoryPropertyName || {}); var KNOWN_REPOSITORY_PROPERTY_NAMES = new Set( @@ -109009,7 +109010,7 @@ async function findOverridingToolsInCache(humanReadableVersion, logger) { } return void 0; } -async function getCodeQLSource(toolsInput, defaultCliVersion, apiDetails, variant, tarSupportsZstd, features, logger) { +async function getCodeQLSource(toolsInput, defaultCliVersion, apiDetails, variant, tarSupportsZstd, features, logger, toolsInputFromRepositoryProperty = false) { if (toolsInput && !isReservedToolsValue(toolsInput) && !toolsInput.startsWith("http")) { logger.info(`Using CodeQL CLI from local path ${toolsInput}`); const compressionMethod2 = inferCompressionMethod(toolsInput); @@ -109077,11 +109078,17 @@ async function getCodeQLSource(toolsInput, defaultCliVersion, apiDetails, varian const allowToolcacheValueFF = await features.getValue( "allow_toolcache_input" /* AllowToolcacheInput */ ); - const allowToolcacheValue = allowToolcacheValueFF && (isDynamicWorkflow() || isInTestMode()); + const allowToolcacheValue = toolsInputFromRepositoryProperty || allowToolcacheValueFF && (isDynamicWorkflow() || isInTestMode()); if (allowToolcacheValue) { - logger.info( - `Attempting to use the latest CodeQL CLI version in the toolcache, as requested by 'tools: ${toolsInput}'.` - ); + if (toolsInputFromRepositoryProperty) { + logger.info( + `Attempting to use the latest CodeQL CLI version in the toolcache, as requested by the 'github-codeql-tools' repository property.` + ); + } else { + logger.info( + `Attempting to use the latest CodeQL CLI version in the toolcache, as requested by 'tools: ${toolsInput}'.` + ); + } latestToolcacheVersion = getLatestToolcacheVersion(logger); if (latestToolcacheVersion) { cliVersion2 = latestToolcacheVersion; @@ -109089,9 +109096,15 @@ async function getCodeQLSource(toolsInput, defaultCliVersion, apiDetails, varian } if (latestToolcacheVersion === void 0) { if (allowToolcacheValue) { - logger.info( - `Found no CodeQL CLI in the toolcache, ignoring 'tools: ${toolsInput}'...` - ); + if (toolsInputFromRepositoryProperty) { + logger.info( + `Found no CodeQL CLI in the toolcache, ignoring the 'github-codeql-tools' repository property...` + ); + } else { + logger.info( + `Found no CodeQL CLI in the toolcache, ignoring 'tools: ${toolsInput}'...` + ); + } } else { if (allowToolcacheValueFF) { logger.warning( @@ -109314,7 +109327,7 @@ function getCanonicalToolcacheVersion(cliVersion2, bundleVersion2, logger) { } return cliVersion2; } -async function setupCodeQLBundle(toolsInput, apiDetails, tempDir, variant, defaultCliVersion, features, logger) { +async function setupCodeQLBundle(toolsInput, apiDetails, tempDir, variant, defaultCliVersion, features, logger, toolsInputFromRepositoryProperty = false) { if (!await isBinaryAccessible("tar", logger)) { throw new ConfigurationError( "Could not find tar in PATH, so unable to extract CodeQL bundle." @@ -109328,7 +109341,8 @@ async function setupCodeQLBundle(toolsInput, apiDetails, tempDir, variant, defau variant, zstdAvailability.available, features, - logger + logger, + toolsInputFromRepositoryProperty ); let codeqlFolder; let toolsVersion = source.toolsVersion; @@ -109451,7 +109465,7 @@ var CODEQL_NEXT_MINIMUM_VERSION = "2.17.6"; var GHES_VERSION_MOST_RECENTLY_DEPRECATED = "3.13"; var GHES_MOST_RECENT_DEPRECATION_DATE = "2025-06-19"; var EXTRACTION_DEBUG_MODE_VERBOSITY = "progress++"; -async function setupCodeQL(toolsInput, apiDetails, tempDir, variant, defaultCliVersion, features, logger, checkVersion) { +async function setupCodeQL(toolsInput, apiDetails, tempDir, variant, defaultCliVersion, features, logger, checkVersion, toolsInputFromRepositoryProperty = false) { try { const { codeqlFolder, @@ -109466,7 +109480,8 @@ async function setupCodeQL(toolsInput, apiDetails, tempDir, variant, defaultCliV variant, defaultCliVersion, features, - logger + logger, + toolsInputFromRepositoryProperty ); logger.debug( `Bundle download status report: ${JSON.stringify( @@ -111186,7 +111201,7 @@ var core13 = __toESM(require_core()); var toolrunner4 = __toESM(require_toolrunner()); var github2 = __toESM(require_github()); var io5 = __toESM(require_io()); -async function initCodeQL(toolsInput, apiDetails, tempDir, variant, defaultCliVersion, features, logger) { +async function initCodeQL(toolsInput, apiDetails, tempDir, variant, defaultCliVersion, features, logger, toolsInputFromRepositoryProperty = false) { logger.startGroup("Setup CodeQL tools"); const { codeql, @@ -111202,7 +111217,8 @@ async function initCodeQL(toolsInput, apiDetails, tempDir, variant, defaultCliVe defaultCliVersion, features, logger, - true + true, + toolsInputFromRepositoryProperty ); await codeql.printVersion(); logger.endGroup(); diff --git a/src/codeql.ts b/src/codeql.ts index ee2773c01b..dad77466d6 100644 --- a/src/codeql.ts +++ b/src/codeql.ts @@ -323,6 +323,7 @@ export async function setupCodeQL( features: FeatureEnablement, logger: Logger, checkVersion: boolean, + toolsInputFromRepositoryProperty = false, ): Promise<{ codeql: CodeQL; toolsDownloadStatusReport?: ToolsDownloadStatusReport; @@ -345,6 +346,7 @@ export async function setupCodeQL( defaultCliVersion, features, logger, + toolsInputFromRepositoryProperty, ); logger.debug( diff --git a/src/feature-flags/properties.test.ts b/src/feature-flags/properties.test.ts index 2676c2dcda..ec9e856a2d 100644 --- a/src/feature-flags/properties.test.ts +++ b/src/feature-flags/properties.test.ts @@ -90,6 +90,25 @@ test.serial("loadPropertiesFromApi loads known properties", async (t) => { t.deepEqual(response, { "github-codeql-extra-queries": "+queries" }); }); + +test.serial("loadPropertiesFromApi loads github-codeql-tools property", async (t) => { + sinon.stub(api, "getRepositoryProperties").resolves({ + headers: {}, + status: 200, + url: "", + data: [ + { property_name: "github-codeql-tools", value: "toolcache" }, + ] satisfies properties.GitHubPropertiesResponse, + }); + const logger = getRunnerLogger(true); + const mockRepositoryNwo = parseRepositoryNwo("owner/repo"); + const response = await properties.loadPropertiesFromApi( + logger, + mockRepositoryNwo, + ); + t.deepEqual(response, { "github-codeql-tools": "toolcache" }); +}); + test.serial("loadPropertiesFromApi parses true boolean property", async (t) => { sinon.stub(api, "getRepositoryProperties").resolves({ headers: {}, diff --git a/src/feature-flags/properties.ts b/src/feature-flags/properties.ts index 12ba280bec..4fb929b53f 100644 --- a/src/feature-flags/properties.ts +++ b/src/feature-flags/properties.ts @@ -13,6 +13,7 @@ export enum RepositoryPropertyName { DISABLE_OVERLAY = "github-codeql-disable-overlay", EXTRA_QUERIES = "github-codeql-extra-queries", FILE_COVERAGE_ON_PRS = "github-codeql-file-coverage-on-prs", + TOOLS = "github-codeql-tools", } /** Parsed types of the known repository properties. */ @@ -20,6 +21,7 @@ export type AllRepositoryProperties = { [RepositoryPropertyName.DISABLE_OVERLAY]: boolean; [RepositoryPropertyName.EXTRA_QUERIES]: string; [RepositoryPropertyName.FILE_COVERAGE_ON_PRS]: boolean; + [RepositoryPropertyName.TOOLS]: string; }; /** Parsed repository properties. */ @@ -30,6 +32,7 @@ export type RepositoryPropertyApiType = { [RepositoryPropertyName.DISABLE_OVERLAY]: string; [RepositoryPropertyName.EXTRA_QUERIES]: string; [RepositoryPropertyName.FILE_COVERAGE_ON_PRS]: string; + [RepositoryPropertyName.TOOLS]: string; }; /** The type of functions which take the `value` from the API and try to convert it to the type we want. */ @@ -77,6 +80,7 @@ const repositoryPropertyParsers: { [RepositoryPropertyName.DISABLE_OVERLAY]: booleanProperty, [RepositoryPropertyName.EXTRA_QUERIES]: stringProperty, [RepositoryPropertyName.FILE_COVERAGE_ON_PRS]: booleanProperty, + [RepositoryPropertyName.TOOLS]: stringProperty, }; /** diff --git a/src/init-action.ts b/src/init-action.ts index 6fe89165bd..5357f4a22a 100644 --- a/src/init-action.ts +++ b/src/init-action.ts @@ -42,6 +42,7 @@ import { Feature, FeatureEnablement, initFeatures } from "./feature-flags"; import { loadPropertiesFromApi, RepositoryProperties, + RepositoryPropertyName, } from "./feature-flags/properties"; import { checkInstallPython311, @@ -297,14 +298,26 @@ async function run(startedAt: Date) { gitHubVersion.type, ); toolsFeatureFlagsValid = codeQLDefaultVersionInfo.toolsFeatureFlagsValid; + + // Determine the effective tools input. + // The explicit `tools` workflow input takes precedence. If none is provided, + // fall back to the 'github-codeql-tools' repository property (if set). + const toolsWorkflowInput = getOptionalInput("tools"); + const toolsPropertyValue = + repositoryPropertiesResult.orElse({})[RepositoryPropertyName.TOOLS]; + const effectiveToolsInput = toolsWorkflowInput ?? toolsPropertyValue; + const toolsInputFromRepositoryProperty = + toolsWorkflowInput === undefined && toolsPropertyValue !== undefined; + const initCodeQLResult = await initCodeQL( - getOptionalInput("tools"), + effectiveToolsInput, apiDetails, getTemporaryDirectory(), gitHubVersion.type, codeQLDefaultVersionInfo, features, logger, + toolsInputFromRepositoryProperty, ); codeql = initCodeQLResult.codeql; toolsDownloadStatusReport = initCodeQLResult.toolsDownloadStatusReport; diff --git a/src/init.ts b/src/init.ts index 8e3fa21a4a..376425861c 100644 --- a/src/init.ts +++ b/src/init.ts @@ -41,6 +41,7 @@ export async function initCodeQL( defaultCliVersion: CodeQLDefaultVersionInfo, features: FeatureEnablement, logger: Logger, + toolsInputFromRepositoryProperty = false, ): Promise<{ codeql: CodeQL; toolsDownloadStatusReport?: ToolsDownloadStatusReport; @@ -64,6 +65,7 @@ export async function initCodeQL( features, logger, true, + toolsInputFromRepositoryProperty, ); await codeql.printVersion(); logger.endGroup(); diff --git a/src/setup-codeql.test.ts b/src/setup-codeql.test.ts index 555352bd21..4c249fcfb6 100644 --- a/src/setup-codeql.test.ts +++ b/src/setup-codeql.test.ts @@ -565,6 +565,115 @@ test.serial( [`Ignoring 'tools: toolcache' because the feature is not enabled.`], ); +test.serial( + "getCodeQLSource correctly returns latest version from toolcache when set via repository property", + async (t) => { + const loggedMessages: LoggedMessage[] = []; + const logger = getRecordingLogger(loggedMessages); + const features = createFeatures([]); + + const latestToolcacheVersion = "3.2.1"; + const latestVersionPath = "/path/to/latest"; + const testVersions = ["2.3.1", latestToolcacheVersion, "1.2.3"]; + const findAllVersionsStub = sinon + .stub(toolcache, "findAllVersions") + .returns(testVersions); + const findStub = sinon.stub(toolcache, "find"); + findStub + .withArgs("CodeQL", latestToolcacheVersion) + .returns(latestVersionPath); + + await withTmpDir(async (tmpDir) => { + // Note: GITHUB_EVENT_NAME is not "dynamic", and the feature flag is not enabled. + // The repository property should bypass these restrictions. + setupActionsVars(tmpDir, tmpDir, { GITHUB_EVENT_NAME: "pull_request" }); + + const source = await setupCodeql.getCodeQLSource( + "toolcache", + SAMPLE_DEFAULT_CLI_VERSION, + SAMPLE_DOTCOM_API_DETAILS, + GitHubVariant.DOTCOM, + false, + features, + logger, + true, // toolsInputFromRepositoryProperty + ); + + t.assert( + findAllVersionsStub.calledOnceWith("CodeQL"), + `toolcache.findAllVersions("CodeQL") wasn't called`, + ); + t.assert( + findStub.calledOnceWith("CodeQL", latestToolcacheVersion), + `toolcache.find("CodeQL", ${latestToolcacheVersion}) wasn't called`, + ); + + t.is(source.sourceType, "toolcache"); + t.is(source.toolsVersion, latestToolcacheVersion); + + const expectedMessages: string[] = [ + `Attempting to use the latest CodeQL CLI version in the toolcache, as requested by the 'github-codeql-tools' repository property.`, + `CLI version ${latestToolcacheVersion} is the latest version in the toolcache.`, + `Using CodeQL CLI version ${latestToolcacheVersion} from toolcache at ${latestVersionPath}`, + ]; + 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 in:\n ${loggedMessages.map((m) => ` - '${m.message}'`).join("\n")}`, + ); + } + }); + }, +); + +test.serial( + "getCodeQLSource falls back to downloading CLI if toolcache is empty when set via repository property", + async (t) => { + const loggedMessages: LoggedMessage[] = []; + const logger = getRecordingLogger(loggedMessages); + const features = createFeatures([]); + + sinon.stub(toolcache, "findAllVersions").returns([]); + + await withTmpDir(async (tmpDir) => { + setupActionsVars(tmpDir, tmpDir, { GITHUB_EVENT_NAME: "pull_request" }); + + const source = await setupCodeql.getCodeQLSource( + "toolcache", + SAMPLE_DEFAULT_CLI_VERSION, + SAMPLE_DOTCOM_API_DETAILS, + GitHubVariant.DOTCOM, + false, + features, + logger, + true, // toolsInputFromRepositoryProperty + ); + + t.is(source.sourceType, "download"); + t.is(source.toolsVersion, SAMPLE_DEFAULT_CLI_VERSION.cliVersion); + + const expectedMessages: string[] = [ + `Attempting to use the latest CodeQL CLI version in the toolcache, as requested by the 'github-codeql-tools' repository property.`, + `Found no CodeQL CLI in the toolcache, ignoring the 'github-codeql-tools' repository property...`, + ]; + 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 in:\n ${loggedMessages.map((m) => ` - '${m.message}'`).join("\n")}`, + ); + } + }); + }, +); + test.serial( 'tryGetTagNameFromUrl extracts the right tag name for a repo name containing "codeql-bundle"', (t) => { diff --git a/src/setup-codeql.ts b/src/setup-codeql.ts index 4ca3302f95..6c0ecf4e8c 100644 --- a/src/setup-codeql.ts +++ b/src/setup-codeql.ts @@ -286,6 +286,7 @@ export async function getCodeQLSource( tarSupportsZstd: boolean, features: FeatureEnablement, logger: Logger, + toolsInputFromRepositoryProperty = false, ): Promise { // If there is an explicit `tools` input, it's not one of the reserved values, and it doesn't appear // to point to a URL, then we assume it is a local path and use the CLI from there. @@ -401,19 +402,27 @@ 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. + // We also allow this in test mode, and when the value was set via a repository property (in which case the + // organization admin has explicitly opted in to this behavior). const allowToolcacheValueFF = await features.getValue( Feature.AllowToolcacheInput, ); const allowToolcacheValue = - allowToolcacheValueFF && (isDynamicWorkflow() || util.isInTestMode()); + toolsInputFromRepositoryProperty || + (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 // the linked version. - logger.info( - `Attempting to use the latest CodeQL CLI version in the toolcache, as requested by 'tools: ${toolsInput}'.`, - ); + if (toolsInputFromRepositoryProperty) { + logger.info( + `Attempting to use the latest CodeQL CLI version in the toolcache, as requested by the 'github-codeql-tools' repository property.`, + ); + } else { + logger.info( + `Attempting to use the latest CodeQL CLI version in the toolcache, as requested by 'tools: ${toolsInput}'.`, + ); + } latestToolcacheVersion = getLatestToolcacheVersion(logger); if (latestToolcacheVersion) { @@ -423,9 +432,15 @@ export async function getCodeQLSource( if (latestToolcacheVersion === undefined) { if (allowToolcacheValue) { - logger.info( - `Found no CodeQL CLI in the toolcache, ignoring 'tools: ${toolsInput}'...`, - ); + if (toolsInputFromRepositoryProperty) { + logger.info( + `Found no CodeQL CLI in the toolcache, ignoring the 'github-codeql-tools' repository property...`, + ); + } else { + logger.info( + `Found no CodeQL CLI in the toolcache, ignoring 'tools: ${toolsInput}'...`, + ); + } } else { if (allowToolcacheValueFF) { logger.warning( @@ -793,6 +808,7 @@ export async function setupCodeQLBundle( defaultCliVersion: CodeQLDefaultVersionInfo, features: FeatureEnablement, logger: Logger, + toolsInputFromRepositoryProperty = false, ): Promise { if (!(await util.isBinaryAccessible("tar", logger))) { throw new util.ConfigurationError( @@ -809,6 +825,7 @@ export async function setupCodeQLBundle( zstdAvailability.available, features, logger, + toolsInputFromRepositoryProperty, ); let codeqlFolder: string;