From 37f3bfc967a946fefc220c3c9e48e57b5599a390 Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Tue, 24 Feb 2026 19:59:56 +0000 Subject: [PATCH] Move `getOrInitCodeQL` to `upload-sarif` --- lib/upload-sarif-action.js | 3754 ++++++++++++++++++------------------ src/upload-sarif-action.ts | 37 +- src/upload-sarif.ts | 34 +- 3 files changed, 1914 insertions(+), 1911 deletions(-) diff --git a/lib/upload-sarif-action.js b/lib/upload-sarif-action.js index 3681b9d84..d36868fa2 100644 --- a/lib/upload-sarif-action.js +++ b/lib/upload-sarif-action.js @@ -105887,8 +105887,8 @@ function cacheCodeQlVersion(version) { function getCachedCodeQlVersion() { return cachedCodeQlVersion; } -async function codeQlVersionAtLeast(codeql2, requiredVersion) { - return semver.gte((await codeql2.getVersion()).version, requiredVersion); +async function codeQlVersionAtLeast(codeql, requiredVersion) { + return semver.gte((await codeql.getVersion()).version, requiredVersion); } function getBaseDatabaseOidsFilePath(config) { return path.join(config.dbLocation, BASE_DATABASE_OIDS_FILE_NAME); @@ -106500,254 +106500,6 @@ function wrapApiConfigurationError(e) { return e; } -// src/codeql.ts -var fs10 = __toESM(require("fs")); -var path10 = __toESM(require("path")); -var core10 = __toESM(require_core()); -var toolrunner3 = __toESM(require_toolrunner()); - -// src/cli-errors.ts -var SUPPORTED_PLATFORMS = [ - ["linux", "x64"], - ["win32", "x64"], - ["darwin", "x64"], - ["darwin", "arm64"] -]; -var CliError = class extends Error { - exitCode; - stderr; - constructor({ cmd, args, exitCode, stderr }) { - const prettyCommand = prettyPrintInvocation(cmd, args); - const fatalErrors = extractFatalErrors(stderr); - const autobuildErrors = extractAutobuildErrors(stderr); - let message; - if (fatalErrors) { - message = `Encountered a fatal error while running "${prettyCommand}". Exit code was ${exitCode} and error was: ${ensureEndsInPeriod( - fatalErrors.trim() - )} See the logs for more details.`; - } else if (autobuildErrors) { - message = `We were unable to automatically build your code. Please provide manual build steps. See ${"https://docs.github.com/en/code-security/code-scanning/troubleshooting-code-scanning/automatic-build-failed" /* AUTOMATIC_BUILD_FAILED */} for more information. Encountered the following error: ${autobuildErrors}`; - } else { - const lastLine = ensureEndsInPeriod( - stderr.trim().split("\n").pop()?.trim() || "n/a" - ); - message = `Encountered a fatal error while running "${prettyCommand}". Exit code was ${exitCode} and last log line was: ${lastLine} See the logs for more details.`; - } - super(message); - this.exitCode = exitCode; - this.stderr = stderr; - } -}; -function extractFatalErrors(error3) { - const fatalErrorRegex = /.*fatal (internal )?error occurr?ed(. Details)?:/gi; - let fatalErrors = []; - let lastFatalErrorIndex; - let match; - while ((match = fatalErrorRegex.exec(error3)) !== null) { - if (lastFatalErrorIndex !== void 0) { - fatalErrors.push(error3.slice(lastFatalErrorIndex, match.index).trim()); - } - lastFatalErrorIndex = match.index; - } - if (lastFatalErrorIndex !== void 0) { - const lastError = error3.slice(lastFatalErrorIndex).trim(); - if (fatalErrors.length === 0) { - return lastError; - } - const isOneLiner = !fatalErrors.some((e) => e.includes("\n")); - if (isOneLiner) { - fatalErrors = fatalErrors.map(ensureEndsInPeriod); - } - return [ - ensureEndsInPeriod(lastError), - "Context:", - ...fatalErrors.reverse() - ].join(isOneLiner ? " " : "\n"); - } - return void 0; -} -function extractAutobuildErrors(error3) { - const pattern = /.*\[autobuild\] \[ERROR\] (.*)/gi; - let errorLines = [...error3.matchAll(pattern)].map((match) => match[1]); - if (errorLines.length > 10) { - errorLines = errorLines.slice(0, 10); - errorLines.push("(truncated)"); - } - return errorLines.join("\n") || void 0; -} -var cliErrorsConfig = { - ["AutobuildError" /* AutobuildError */]: { - cliErrorMessageCandidates: [ - new RegExp("We were unable to automatically build your code") - ] - }, - ["CouldNotCreateTempDir" /* CouldNotCreateTempDir */]: { - cliErrorMessageCandidates: [new RegExp("Could not create temp directory")] - }, - ["ExternalRepositoryCloneFailed" /* ExternalRepositoryCloneFailed */]: { - cliErrorMessageCandidates: [ - new RegExp("Failed to clone external Git repository") - ] - }, - ["GradleBuildFailed" /* GradleBuildFailed */]: { - cliErrorMessageCandidates: [ - new RegExp("\\[autobuild\\] FAILURE: Build failed with an exception.") - ] - }, - // Version of CodeQL CLI is incompatible with this version of the CodeQL Action - ["IncompatibleWithActionVersion" /* IncompatibleWithActionVersion */]: { - cliErrorMessageCandidates: [ - new RegExp("is not compatible with this CodeQL CLI") - ] - }, - ["InitCalledTwice" /* InitCalledTwice */]: { - cliErrorMessageCandidates: [ - new RegExp( - "Refusing to create databases .* but could not process any of it" - ) - ], - additionalErrorMessageToAppend: `Is the "init" action called twice in the same job?` - }, - ["InvalidConfigFile" /* InvalidConfigFile */]: { - cliErrorMessageCandidates: [ - new RegExp("Config file .* is not valid"), - new RegExp("The supplied config file is empty") - ] - }, - ["InvalidExternalRepoSpecifier" /* InvalidExternalRepoSpecifier */]: { - cliErrorMessageCandidates: [ - new RegExp("Specifier for external repository is invalid") - ] - }, - // Expected source location for database creation does not exist - ["InvalidSourceRoot" /* InvalidSourceRoot */]: { - cliErrorMessageCandidates: [new RegExp("Invalid source root")] - }, - ["MavenBuildFailed" /* MavenBuildFailed */]: { - cliErrorMessageCandidates: [ - new RegExp("\\[autobuild\\] \\[ERROR\\] Failed to execute goal") - ] - }, - ["NoBuildCommandAutodetected" /* NoBuildCommandAutodetected */]: { - cliErrorMessageCandidates: [ - new RegExp("Could not auto-detect a suitable build method") - ] - }, - ["NoBuildMethodAutodetected" /* NoBuildMethodAutodetected */]: { - cliErrorMessageCandidates: [ - new RegExp( - "Could not detect a suitable build command for the source checkout" - ) - ] - }, - // Usually when a manual build script has failed, or if an autodetected language - // was unintended to have CodeQL analysis run on it. - ["NoSourceCodeSeen" /* NoSourceCodeSeen */]: { - exitCode: 32, - cliErrorMessageCandidates: [ - new RegExp( - "CodeQL detected code written in .* but could not process any of it" - ), - new RegExp( - "CodeQL did not detect any code written in languages supported by CodeQL" - ) - ] - }, - ["NoSupportedBuildCommandSucceeded" /* NoSupportedBuildCommandSucceeded */]: { - cliErrorMessageCandidates: [ - new RegExp("No supported build command succeeded") - ] - }, - ["NoSupportedBuildSystemDetected" /* NoSupportedBuildSystemDetected */]: { - cliErrorMessageCandidates: [ - new RegExp("No supported build system detected") - ] - }, - ["OutOfMemoryOrDisk" /* OutOfMemoryOrDisk */]: { - cliErrorMessageCandidates: [ - new RegExp("CodeQL is out of memory."), - new RegExp("out of disk"), - new RegExp("No space left on device") - ], - additionalErrorMessageToAppend: "For more information, see https://gh.io/troubleshooting-code-scanning/out-of-disk-or-memory" - }, - ["PackCannotBeFound" /* PackCannotBeFound */]: { - cliErrorMessageCandidates: [ - new RegExp( - "Query pack .* cannot be found\\. Check the spelling of the pack\\." - ), - new RegExp( - "is not a .ql file, .qls file, a directory, or a query pack specification." - ) - ] - }, - ["PackMissingAuth" /* PackMissingAuth */]: { - cliErrorMessageCandidates: [ - new RegExp("GitHub Container registry .* 403 Forbidden"), - new RegExp( - "Do you need to specify a token to authenticate to the registry?" - ) - ] - }, - ["SwiftBuildFailed" /* SwiftBuildFailed */]: { - cliErrorMessageCandidates: [ - new RegExp( - "\\[autobuilder/build\\] \\[build-command-failed\\] `autobuild` failed to run the build command" - ) - ] - }, - ["UnsupportedBuildMode" /* UnsupportedBuildMode */]: { - cliErrorMessageCandidates: [ - new RegExp( - "does not support the .* build mode. Please try using one of the following build modes instead" - ) - ] - }, - ["NotFoundInRegistry" /* NotFoundInRegistry */]: { - cliErrorMessageCandidates: [ - new RegExp("'.*' not found in the registry '.*'") - ] - } -}; -function getCliConfigCategoryIfExists(cliError) { - for (const [category, configuration] of Object.entries(cliErrorsConfig)) { - if (cliError.exitCode !== void 0 && configuration.exitCode !== void 0 && cliError.exitCode === configuration.exitCode) { - return category; - } - for (const e of configuration.cliErrorMessageCandidates) { - if (cliError.message.match(e) || cliError.stderr.match(e)) { - return category; - } - } - } - return void 0; -} -function isUnsupportedPlatform() { - return !SUPPORTED_PLATFORMS.some( - ([platform, arch2]) => platform === process.platform && arch2 === process.arch - ); -} -function getUnsupportedPlatformError(cliError) { - return new ConfigurationError( - `The CodeQL CLI does not support the platform/architecture combination of ${process.platform}/${process.arch} (see ${"https://codeql.github.com/docs/codeql-overview/system-requirements/" /* SYSTEM_REQUIREMENTS */}). The underlying error was: ${cliError.message}` - ); -} -function wrapCliConfigurationError(cliError) { - if (isUnsupportedPlatform()) { - return getUnsupportedPlatformError(cliError); - } - const cliConfigErrorCategory = getCliConfigCategoryIfExists(cliError); - if (cliConfigErrorCategory === void 0) { - return cliError; - } - let errorMessageBuilder = cliError.message; - const additionalErrorMessageToAppend = cliErrorsConfig[cliConfigErrorCategory].additionalErrorMessageToAppend; - if (additionalErrorMessageToAppend !== void 0) { - errorMessageBuilder = `${errorMessageBuilder} ${additionalErrorMessageToAppend}`; - } - return new ConfigurationError(errorMessageBuilder); -} - // src/config-utils.ts var fs6 = __toESM(require("fs")); var path7 = __toESM(require("path")); @@ -107404,8 +107156,8 @@ var OfflineFeatures = class { * * @throws if a `minimumVersion` is specified for the feature, and `codeql` is not provided. */ - async getValue(feature, codeql2) { - const offlineValue = await this.getOfflineValue(feature, codeql2); + async getValue(feature, codeql) { + const offlineValue = await this.getOfflineValue(feature, codeql); if (offlineValue !== void 0) { return offlineValue; } @@ -107414,14 +107166,14 @@ var OfflineFeatures = class { /** * Determines whether `feature` is enabled using the CLI and environment variables. */ - async getOfflineValue(feature, codeql2) { + async getOfflineValue(feature, codeql) { const config = this.getFeatureConfig(feature); - if (!codeql2 && config.minimumVersion) { + if (!codeql && config.minimumVersion) { throw new Error( `Internal error: A minimum version is specified for feature ${feature}, but no instance of CodeQL was provided.` ); } - if (!codeql2 && config.toolsFeature) { + if (!codeql && config.toolsFeature) { throw new Error( `Internal error: A required tools feature is specified for feature ${feature}, but no instance of CodeQL was provided.` ); @@ -107434,28 +107186,28 @@ var OfflineFeatures = class { return false; } const minimumVersion = config.minimumVersion; - if (codeql2 && minimumVersion) { - if (!await codeQlVersionAtLeast(codeql2, minimumVersion)) { + if (codeql && minimumVersion) { + if (!await codeQlVersionAtLeast(codeql, minimumVersion)) { this.logger.debug( `Feature ${feature} is disabled because the CodeQL CLI version is older than the minimum version ${minimumVersion}.` ); return false; } else { this.logger.debug( - `CodeQL CLI version ${(await codeql2.getVersion()).version} is newer than the minimum version ${minimumVersion} for feature ${feature}.` + `CodeQL CLI version ${(await codeql.getVersion()).version} is newer than the minimum version ${minimumVersion} for feature ${feature}.` ); } } const toolsFeature = config.toolsFeature; - if (codeql2 && toolsFeature) { - if (!await codeql2.supportsFeature(toolsFeature)) { + if (codeql && toolsFeature) { + if (!await codeql.supportsFeature(toolsFeature)) { this.logger.debug( `Feature ${feature} is disabled because the CodeQL CLI version does not support the required tools feature ${toolsFeature}.` ); return false; } else { this.logger.debug( - `CodeQL CLI version ${(await codeql2.getVersion()).version} supports the required tools feature ${toolsFeature} for feature ${feature}.` + `CodeQL CLI version ${(await codeql.getVersion()).version} supports the required tools feature ${toolsFeature} for feature ${feature}.` ); } } @@ -107505,8 +107257,8 @@ var Features = class extends OfflineFeatures { * * @throws if a `minimumVersion` is specified for the feature, and `codeql` is not provided. */ - async getValue(feature, codeql2) { - const offlineValue = await this.getOfflineValue(feature, codeql2); + async getValue(feature, codeql) { + const offlineValue = await this.getOfflineValue(feature, codeql); if (offlineValue !== void 0) { return offlineValue; } @@ -107795,1585 +107547,9 @@ function appendExtraQueryExclusions(extraQueryExclusions, cliConfig) { return augmentedConfig; } -// src/setup-codeql.ts -var fs9 = __toESM(require("fs")); -var path9 = __toESM(require("path")); -var toolcache3 = __toESM(require_tool_cache()); -var import_fast_deep_equal = __toESM(require_fast_deep_equal()); -var semver8 = __toESM(require_semver2()); - -// node_modules/uuid/dist-node/stringify.js -var byteToHex = []; -for (let i = 0; i < 256; ++i) { - byteToHex.push((i + 256).toString(16).slice(1)); -} -function unsafeStringify(arr, offset = 0) { - return (byteToHex[arr[offset + 0]] + byteToHex[arr[offset + 1]] + byteToHex[arr[offset + 2]] + byteToHex[arr[offset + 3]] + "-" + byteToHex[arr[offset + 4]] + byteToHex[arr[offset + 5]] + "-" + byteToHex[arr[offset + 6]] + byteToHex[arr[offset + 7]] + "-" + byteToHex[arr[offset + 8]] + byteToHex[arr[offset + 9]] + "-" + byteToHex[arr[offset + 10]] + byteToHex[arr[offset + 11]] + byteToHex[arr[offset + 12]] + byteToHex[arr[offset + 13]] + byteToHex[arr[offset + 14]] + byteToHex[arr[offset + 15]]).toLowerCase(); -} - -// node_modules/uuid/dist-node/rng.js -var import_node_crypto = require("node:crypto"); -var rnds8Pool = new Uint8Array(256); -var poolPtr = rnds8Pool.length; -function rng() { - if (poolPtr > rnds8Pool.length - 16) { - (0, import_node_crypto.randomFillSync)(rnds8Pool); - poolPtr = 0; - } - return rnds8Pool.slice(poolPtr, poolPtr += 16); -} - -// node_modules/uuid/dist-node/native.js -var import_node_crypto2 = require("node:crypto"); -var native_default = { randomUUID: import_node_crypto2.randomUUID }; - -// node_modules/uuid/dist-node/v4.js -function _v4(options, buf, offset) { - options = options || {}; - const rnds = options.random ?? options.rng?.() ?? rng(); - if (rnds.length < 16) { - throw new Error("Random bytes length must be >= 16"); - } - rnds[6] = rnds[6] & 15 | 64; - rnds[8] = rnds[8] & 63 | 128; - if (buf) { - offset = offset || 0; - if (offset < 0 || offset + 16 > buf.length) { - throw new RangeError(`UUID byte range ${offset}:${offset + 15} is out of buffer bounds`); - } - for (let i = 0; i < 16; ++i) { - buf[offset + i] = rnds[i]; - } - return buf; - } - return unsafeStringify(rnds); -} -function v4(options, buf, offset) { - if (native_default.randomUUID && !buf && !options) { - return native_default.randomUUID(); - } - return _v4(options, buf, offset); -} -var v4_default = v4; - -// src/tar.ts -var import_child_process = require("child_process"); -var fs7 = __toESM(require("fs")); -var stream = __toESM(require("stream")); -var import_toolrunner = __toESM(require_toolrunner()); -var io4 = __toESM(require_io()); -var toolcache = __toESM(require_tool_cache()); -var semver6 = __toESM(require_semver2()); -var MIN_REQUIRED_BSD_TAR_VERSION = "3.4.3"; -var MIN_REQUIRED_GNU_TAR_VERSION = "1.31"; -async function getTarVersion() { - const tar = await io4.which("tar", true); - let stdout = ""; - const exitCode = await new import_toolrunner.ToolRunner(tar, ["--version"], { - listeners: { - stdout: (data) => { - stdout += data.toString(); - } - } - }).exec(); - if (exitCode !== 0) { - throw new Error("Failed to call tar --version"); - } - if (stdout.includes("GNU tar")) { - const match = stdout.match(/tar \(GNU tar\) ([0-9.]+)/); - if (!match?.[1]) { - throw new Error("Failed to parse output of tar --version."); - } - return { type: "gnu", version: match[1] }; - } else if (stdout.includes("bsdtar")) { - const match = stdout.match(/bsdtar ([0-9.]+)/); - if (!match?.[1]) { - throw new Error("Failed to parse output of tar --version."); - } - return { type: "bsd", version: match[1] }; - } else { - throw new Error("Unknown tar version"); - } -} -async function isZstdAvailable(logger) { - const foundZstdBinary = await isBinaryAccessible("zstd", logger); - try { - const tarVersion = await getTarVersion(); - const { type: type2, version } = tarVersion; - logger.info(`Found ${type2} tar version ${version}.`); - switch (type2) { - case "gnu": - return { - available: foundZstdBinary && // GNU tar only uses major and minor version numbers - semver6.gte( - semver6.coerce(version), - semver6.coerce(MIN_REQUIRED_GNU_TAR_VERSION) - ), - foundZstdBinary, - version: tarVersion - }; - case "bsd": - return { - available: foundZstdBinary && // Do a loose comparison since these version numbers don't contain - // a patch version number. - semver6.gte(version, MIN_REQUIRED_BSD_TAR_VERSION), - foundZstdBinary, - version: tarVersion - }; - default: - assertNever(type2); - } - } catch (e) { - logger.warning( - `Failed to determine tar version, therefore will assume zstd is not available. The underlying error was: ${e}` - ); - return { available: false, foundZstdBinary }; - } -} -async function extract(tarPath, dest, compressionMethod, tarVersion, logger) { - fs7.mkdirSync(dest, { recursive: true }); - switch (compressionMethod) { - case "gzip": - return await toolcache.extractTar(tarPath, dest); - case "zstd": { - if (!tarVersion) { - throw new Error( - "Could not determine tar version, which is required to extract a Zstandard archive." - ); - } - await extractTarZst(tarPath, dest, tarVersion, logger); - return dest; - } - } -} -async function extractTarZst(tar, dest, tarVersion, logger) { - logger.debug( - `Extracting to ${dest}.${tar instanceof stream.Readable ? ` Input stream has high water mark ${tar.readableHighWaterMark}.` : ""}` - ); - try { - const args = ["-x", "--zstd", "--ignore-zeros"]; - if (tarVersion.type === "gnu") { - args.push("--warning=no-unknown-keyword"); - args.push("--overwrite"); - } - args.push("-f", tar instanceof stream.Readable ? "-" : tar, "-C", dest); - process.stdout.write(`[command]tar ${args.join(" ")} -`); - await new Promise((resolve6, reject) => { - const tarProcess = (0, import_child_process.spawn)("tar", args, { stdio: "pipe" }); - let stdout = ""; - tarProcess.stdout?.on("data", (data) => { - stdout += data.toString(); - process.stdout.write(data); - }); - let stderr = ""; - tarProcess.stderr?.on("data", (data) => { - stderr += data.toString(); - process.stdout.write(data); - }); - tarProcess.on("error", (err) => { - reject(new Error(`Error while extracting tar: ${err}`)); - }); - if (tar instanceof stream.Readable) { - tar.pipe(tarProcess.stdin).on("error", (err) => { - reject( - new Error(`Error while downloading and extracting tar: ${err}`) - ); - }); - } - tarProcess.on("exit", (code) => { - if (code !== 0) { - reject( - new CommandInvocationError( - "tar", - args, - code ?? void 0, - stdout, - stderr - ) - ); - } - resolve6(); - }); - }); - } catch (e) { - await cleanUpPath(dest, "extraction destination directory", logger); - throw e; - } -} -var KNOWN_EXTENSIONS = { - "tar.gz": "gzip", - "tar.zst": "zstd" -}; -function inferCompressionMethod(tarPath) { - for (const [ext, method] of Object.entries(KNOWN_EXTENSIONS)) { - if (tarPath.endsWith(`.${ext}`)) { - return method; - } - } - return void 0; -} - -// src/tools-download.ts -var fs8 = __toESM(require("fs")); -var os = __toESM(require("os")); -var path8 = __toESM(require("path")); -var import_perf_hooks = require("perf_hooks"); -var core9 = __toESM(require_core()); -var import_http_client = __toESM(require_lib()); -var toolcache2 = __toESM(require_tool_cache()); -var import_follow_redirects = __toESM(require_follow_redirects()); -var semver7 = __toESM(require_semver2()); -var STREAMING_HIGH_WATERMARK_BYTES = 4 * 1024 * 1024; -var TOOLCACHE_TOOL_NAME = "CodeQL"; -function makeDownloadFirstToolsDownloadDurations(downloadDurationMs, extractionDurationMs) { - return { - combinedDurationMs: downloadDurationMs + extractionDurationMs, - downloadDurationMs, - extractionDurationMs, - streamExtraction: false - }; -} -function makeStreamedToolsDownloadDurations(combinedDurationMs) { - return { - combinedDurationMs, - downloadDurationMs: void 0, - extractionDurationMs: void 0, - streamExtraction: true - }; -} -async function downloadAndExtract(codeqlURL, compressionMethod, dest, authorization, headers, tarVersion, logger) { - logger.info( - `Downloading CodeQL tools from ${codeqlURL} . This may take a while.` - ); - try { - if (compressionMethod === "zstd" && process.platform === "linux") { - logger.info(`Streaming the extraction of the CodeQL bundle.`); - const toolsInstallStart = import_perf_hooks.performance.now(); - await downloadAndExtractZstdWithStreaming( - codeqlURL, - dest, - authorization, - headers, - tarVersion, - logger - ); - const combinedDurationMs = Math.round( - import_perf_hooks.performance.now() - toolsInstallStart - ); - logger.info( - `Finished downloading and extracting CodeQL bundle to ${dest} (${formatDuration( - combinedDurationMs - )}).` - ); - return { - compressionMethod, - toolsUrl: sanitizeUrlForStatusReport(codeqlURL), - ...makeStreamedToolsDownloadDurations(combinedDurationMs) - }; - } - } catch (e) { - core9.warning( - `Failed to download and extract CodeQL bundle using streaming with error: ${getErrorMessage(e)}` - ); - core9.warning(`Falling back to downloading the bundle before extracting.`); - await cleanUpPath(dest, "CodeQL bundle", logger); - } - const toolsDownloadStart = import_perf_hooks.performance.now(); - const archivedBundlePath = await toolcache2.downloadTool( - codeqlURL, - void 0, - authorization, - headers - ); - const downloadDurationMs = Math.round(import_perf_hooks.performance.now() - toolsDownloadStart); - logger.info( - `Finished downloading CodeQL bundle to ${archivedBundlePath} (${formatDuration( - downloadDurationMs - )}).` - ); - let extractionDurationMs; - try { - logger.info("Extracting CodeQL bundle."); - const extractionStart = import_perf_hooks.performance.now(); - await extract( - archivedBundlePath, - dest, - compressionMethod, - tarVersion, - logger - ); - extractionDurationMs = Math.round(import_perf_hooks.performance.now() - extractionStart); - logger.info( - `Finished extracting CodeQL bundle to ${dest} (${formatDuration( - extractionDurationMs - )}).` - ); - } finally { - await cleanUpPath(archivedBundlePath, "CodeQL bundle archive", logger); - } - return { - compressionMethod, - toolsUrl: sanitizeUrlForStatusReport(codeqlURL), - ...makeDownloadFirstToolsDownloadDurations( - downloadDurationMs, - extractionDurationMs - ) - }; -} -async function downloadAndExtractZstdWithStreaming(codeqlURL, dest, authorization, headers, tarVersion, logger) { - fs8.mkdirSync(dest, { recursive: true }); - const agent = new import_http_client.HttpClient().getAgent(codeqlURL); - headers = Object.assign( - { "User-Agent": "CodeQL Action" }, - authorization ? { authorization } : {}, - headers - ); - const response = await new Promise( - (resolve6) => import_follow_redirects.https.get( - codeqlURL, - { - headers, - // Increase the high water mark to improve performance. - highWaterMark: STREAMING_HIGH_WATERMARK_BYTES, - // Use the agent to respect proxy settings. - agent - }, - (r) => resolve6(r) - ) - ); - if (response.statusCode !== 200) { - throw new Error( - `Failed to download CodeQL bundle from ${codeqlURL}. HTTP status code: ${response.statusCode}.` - ); - } - await extractTarZst(response, dest, tarVersion, logger); -} -function getToolcacheDirectory(version) { - return path8.join( - getRequiredEnvParam("RUNNER_TOOL_CACHE"), - TOOLCACHE_TOOL_NAME, - semver7.clean(version) || version, - os.arch() || "" - ); -} -function writeToolcacheMarkerFile(extractedPath, logger) { - const markerFilePath = `${extractedPath}.complete`; - fs8.writeFileSync(markerFilePath, ""); - logger.info(`Created toolcache marker file ${markerFilePath}`); -} -function sanitizeUrlForStatusReport(url2) { - return ["github/codeql-action", "dsp-testing/codeql-cli-nightlies"].some( - (repo) => url2.startsWith(`https://github.com/${repo}/releases/download/`) - ) ? url2 : "sanitized-value"; -} - -// src/setup-codeql.ts -var CODEQL_DEFAULT_ACTION_REPOSITORY = "github/codeql-action"; -var CODEQL_NIGHTLIES_REPOSITORY_OWNER = "dsp-testing"; -var CODEQL_NIGHTLIES_REPOSITORY_NAME = "codeql-cli-nightlies"; -var CODEQL_BUNDLE_VERSION_ALIAS = ["linked", "latest"]; -var CODEQL_NIGHTLY_TOOLS_INPUTS = ["nightly", "nightly-latest"]; -var CODEQL_TOOLCACHE_INPUT = "toolcache"; -function getCodeQLBundleExtension(compressionMethod) { - switch (compressionMethod) { - case "gzip": - return ".tar.gz"; - case "zstd": - return ".tar.zst"; - default: - assertNever(compressionMethod); - } -} -function getCodeQLBundleName(compressionMethod) { - const extension = getCodeQLBundleExtension(compressionMethod); - let platform; - if (process.platform === "win32") { - platform = "win64"; - } else if (process.platform === "linux") { - platform = "linux64"; - } else if (process.platform === "darwin") { - platform = "osx64"; - } else { - return `codeql-bundle${extension}`; - } - return `codeql-bundle-${platform}${extension}`; -} -function getCodeQLActionRepository(logger) { - if (isRunningLocalAction()) { - logger.info( - "The CodeQL Action is checked out locally. Using the default CodeQL Action repository." - ); - return CODEQL_DEFAULT_ACTION_REPOSITORY; - } - return getRequiredEnvParam("GITHUB_ACTION_REPOSITORY"); -} -async function getCodeQLBundleDownloadURL(tagName, apiDetails, compressionMethod, logger) { - const codeQLActionRepository = getCodeQLActionRepository(logger); - const potentialDownloadSources = [ - // This GitHub instance, and this Action. - [apiDetails.url, codeQLActionRepository], - // This GitHub instance, and the canonical Action. - [apiDetails.url, CODEQL_DEFAULT_ACTION_REPOSITORY], - // GitHub.com, and the canonical Action. - [GITHUB_DOTCOM_URL, CODEQL_DEFAULT_ACTION_REPOSITORY] - ]; - const uniqueDownloadSources = potentialDownloadSources.filter( - (source, index, self2) => { - return !self2.slice(0, index).some((other) => (0, import_fast_deep_equal.default)(source, other)); - } - ); - const codeQLBundleName = getCodeQLBundleName(compressionMethod); - for (const downloadSource of uniqueDownloadSources) { - const [apiURL, repository] = downloadSource; - if (apiURL === GITHUB_DOTCOM_URL && repository === CODEQL_DEFAULT_ACTION_REPOSITORY) { - break; - } - const [repositoryOwner, repositoryName] = repository.split("/"); - try { - const release2 = await getApiClient().rest.repos.getReleaseByTag({ - owner: repositoryOwner, - repo: repositoryName, - tag: tagName - }); - for (const asset of release2.data.assets) { - if (asset.name === codeQLBundleName) { - logger.info( - `Found CodeQL bundle ${codeQLBundleName} in ${repository} on ${apiURL} with URL ${asset.url}.` - ); - return asset.url; - } - } - } catch (e) { - logger.info( - `Looked for CodeQL bundle ${codeQLBundleName} in ${repository} on ${apiURL} but got error ${e}.` - ); - } - } - return `https://github.com/${CODEQL_DEFAULT_ACTION_REPOSITORY}/releases/download/${tagName}/${codeQLBundleName}`; -} -function tryGetBundleVersionFromTagName(tagName, logger) { - const match = tagName.match(/^codeql-bundle-(.*)$/); - if (match === null || match.length < 2) { - logger.debug(`Could not determine bundle version from tag ${tagName}.`); - return void 0; - } - return match[1]; -} -function tryGetTagNameFromUrl(url2, logger) { - const matches = [...url2.matchAll(/\/(codeql-bundle-[^/]*)\//g)]; - if (matches.length === 0) { - logger.debug(`Could not determine tag name for URL ${url2}.`); - return void 0; - } - const match = matches[matches.length - 1]; - if (match?.length !== 2) { - logger.debug( - `Could not determine tag name for URL ${url2}. Matched ${JSON.stringify( - match - )}.` - ); - return void 0; - } - return match[1]; -} -function convertToSemVer(version, logger) { - if (!semver8.valid(version)) { - logger.debug( - `Bundle version ${version} is not in SemVer format. Will treat it as pre-release 0.0.0-${version}.` - ); - version = `0.0.0-${version}`; - } - const s = semver8.clean(version); - if (!s) { - throw new Error(`Bundle version ${version} is not in SemVer format.`); - } - return s; -} -async function findOverridingToolsInCache(humanReadableVersion, logger) { - const candidates = toolcache3.findAllVersions("CodeQL").filter(isGoodVersion).map((version) => ({ - folder: toolcache3.find("CodeQL", version), - version - })).filter(({ folder }) => fs9.existsSync(path9.join(folder, "pinned-version"))); - if (candidates.length === 1) { - const candidate = candidates[0]; - logger.debug( - `CodeQL tools version ${candidate.version} in toolcache overriding version ${humanReadableVersion}.` - ); - return { - codeqlFolder: candidate.folder, - sourceType: "toolcache", - toolsVersion: candidate.version - }; - } else if (candidates.length === 0) { - logger.debug( - "Did not find any candidate pinned versions of the CodeQL tools in the toolcache." - ); - } else { - logger.debug( - "Could not use CodeQL tools from the toolcache since more than one candidate pinned version was found in the toolcache." - ); - } - return void 0; -} -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); - if (compressionMethod2 === void 0) { - throw new ConfigurationError( - `Could not infer compression method from path ${toolsInput}. Please specify a path ending in '.tar.gz' or '.tar.zst'.` - ); - } - return { - codeqlTarPath: toolsInput, - compressionMethod: compressionMethod2, - sourceType: "local", - toolsVersion: "local" - }; - } - let cliVersion2; - let tagName; - let url2; - const canForceNightlyWithFF = isDynamicWorkflow() || isInTestMode(); - const forceNightlyValueFF = await features.getValue("force_nightly" /* ForceNightly */); - const forceNightly = forceNightlyValueFF && canForceNightlyWithFF; - const nightlyRequestedByToolsInput = toolsInput !== void 0 && CODEQL_NIGHTLY_TOOLS_INPUTS.includes(toolsInput); - if (forceNightly || nightlyRequestedByToolsInput) { - if (forceNightly) { - logger.info( - `Using the latest CodeQL CLI nightly, as forced by the ${"force_nightly" /* ForceNightly */} feature flag.` - ); - addNoLanguageDiagnostic( - void 0, - makeDiagnostic( - "codeql-action/forced-nightly-cli", - "A nightly release of CodeQL was used", - { - markdownMessage: "GitHub configured this analysis to use a nightly release of CodeQL to allow you to preview changes from an upcoming release.\n\nNightly releases do not undergo the same validation as regular releases and may lead to analysis instability.\n\nIf use of a nightly CodeQL release for this analysis is unexpected, please contact GitHub support.", - visibility: { - cliSummaryTable: true, - statusPage: true, - telemetry: true - }, - severity: "note" - } - ) - ); - } else { - logger.info( - `Using the latest CodeQL CLI nightly, as requested by 'tools: ${toolsInput}'.` - ); - } - toolsInput = await getNightlyToolsUrl(logger); - } - const forceShippedTools = toolsInput && CODEQL_BUNDLE_VERSION_ALIAS.includes(toolsInput); - if (forceShippedTools) { - cliVersion2 = cliVersion; - tagName = bundleVersion; - logger.info( - `'tools: ${toolsInput}' was requested, so using CodeQL version ${cliVersion2}, the version shipped with the Action.` - ); - if (toolsInput === "latest") { - logger.warning( - "`tools: latest` has been renamed to `tools: linked`, but the old name is still supported. No action is required." - ); - } - } else if (toolsInput !== void 0 && toolsInput === CODEQL_TOOLCACHE_INPUT) { - let latestToolcacheVersion; - 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}'.` - ); - latestToolcacheVersion = getLatestToolcacheVersion(logger); - if (latestToolcacheVersion) { - cliVersion2 = latestToolcacheVersion; - } - } - if (latestToolcacheVersion === void 0) { - if (allowToolcacheValue) { - logger.info( - `Found no CodeQL CLI in the toolcache, ignoring 'tools: ${toolsInput}'...` - ); - } else { - if (allowToolcacheValueFF) { - logger.warning( - `Ignoring 'tools: ${toolsInput}' because the workflow was not triggered dynamically.` - ); - } else { - logger.info( - `Ignoring 'tools: ${toolsInput}' because the feature is not enabled.` - ); - } - } - cliVersion2 = defaultCliVersion.cliVersion; - tagName = defaultCliVersion.tagName; - } - } else if (toolsInput !== void 0) { - tagName = tryGetTagNameFromUrl(toolsInput, logger); - url2 = toolsInput; - if (tagName) { - const bundleVersion3 = tryGetBundleVersionFromTagName(tagName, logger); - if (bundleVersion3 && semver8.valid(bundleVersion3)) { - cliVersion2 = convertToSemVer(bundleVersion3, logger); - } - } - } else { - cliVersion2 = defaultCliVersion.cliVersion; - tagName = defaultCliVersion.tagName; - } - const bundleVersion2 = tagName && tryGetBundleVersionFromTagName(tagName, logger); - const humanReadableVersion = cliVersion2 ?? (bundleVersion2 && convertToSemVer(bundleVersion2, logger)) ?? tagName ?? url2 ?? "unknown"; - logger.debug( - `Attempting to obtain CodeQL tools. CLI version: ${cliVersion2 ?? "unknown"}, bundle tag name: ${tagName ?? "unknown"}, URL: ${url2 ?? "unspecified"}.` - ); - let codeqlFolder; - if (cliVersion2) { - codeqlFolder = toolcache3.find("CodeQL", cliVersion2); - if (!codeqlFolder) { - logger.debug( - `Didn't find a version of the CodeQL tools in the toolcache with a version number exactly matching ${cliVersion2}.` - ); - const allVersions = toolcache3.findAllVersions("CodeQL"); - logger.debug( - `Found the following versions of the CodeQL tools in the toolcache: ${JSON.stringify( - allVersions - )}.` - ); - const candidateVersions = allVersions.filter( - (version) => version.startsWith(`${cliVersion2}-`) - ); - if (candidateVersions.length === 1) { - logger.debug( - `Exactly one version of the CodeQL tools starting with ${cliVersion2} found in the toolcache, using that.` - ); - codeqlFolder = toolcache3.find("CodeQL", candidateVersions[0]); - } else if (candidateVersions.length === 0) { - logger.debug( - `Didn't find any versions of the CodeQL tools starting with ${cliVersion2} in the toolcache. Trying next fallback method.` - ); - } else { - logger.warning( - `Found ${candidateVersions.length} versions of the CodeQL tools starting with ${cliVersion2} in the toolcache, but at most one was expected.` - ); - logger.debug("Trying next fallback method."); - } - } - } - if (!codeqlFolder && tagName) { - const fallbackVersion = await tryGetFallbackToolcacheVersion( - cliVersion2, - tagName, - logger - ); - if (fallbackVersion) { - codeqlFolder = toolcache3.find("CodeQL", fallbackVersion); - } else { - logger.debug( - `Could not determine a fallback toolcache version number for CodeQL tools version ${humanReadableVersion}.` - ); - } - } - if (codeqlFolder) { - logger.info( - `Found CodeQL tools version ${humanReadableVersion} in the toolcache.` - ); - } else { - logger.info( - `Did not find CodeQL tools version ${humanReadableVersion} in the toolcache.` - ); - } - if (codeqlFolder) { - if (cliVersion2) { - logger.info( - `Using CodeQL CLI version ${cliVersion2} from toolcache at ${codeqlFolder}` - ); - } else { - logger.info(`Using CodeQL CLI from toolcache at ${codeqlFolder}`); - } - return { - codeqlFolder, - sourceType: "toolcache", - toolsVersion: cliVersion2 ?? humanReadableVersion - }; - } - if (variant === "GitHub Enterprise Server" /* GHES */ && !forceShippedTools && !toolsInput) { - const result = await findOverridingToolsInCache( - humanReadableVersion, - logger - ); - if (result !== void 0) { - return result; - } - } - let compressionMethod; - if (!url2) { - compressionMethod = cliVersion2 !== void 0 && await useZstdBundle(cliVersion2, tarSupportsZstd) ? "zstd" : "gzip"; - url2 = await getCodeQLBundleDownloadURL( - tagName, - apiDetails, - compressionMethod, - logger - ); - } else { - const method = inferCompressionMethod(url2); - if (method === void 0) { - throw new ConfigurationError( - `Could not infer compression method from URL ${url2}. Please specify a URL ending in '.tar.gz' or '.tar.zst'.` - ); - } - compressionMethod = method; - } - if (cliVersion2) { - logger.info(`Using CodeQL CLI version ${cliVersion2} sourced from ${url2} .`); - } else { - logger.info(`Using CodeQL CLI sourced from ${url2} .`); - } - return { - bundleVersion: tagName && tryGetBundleVersionFromTagName(tagName, logger), - cliVersion: cliVersion2, - codeqlURL: url2, - compressionMethod, - sourceType: "download", - toolsVersion: cliVersion2 ?? humanReadableVersion - }; -} -async function tryGetFallbackToolcacheVersion(cliVersion2, tagName, logger) { - const bundleVersion2 = tryGetBundleVersionFromTagName(tagName, logger); - if (!bundleVersion2) { - return void 0; - } - const fallbackVersion = convertToSemVer(bundleVersion2, logger); - logger.debug( - `Computed a fallback toolcache version number of ${fallbackVersion} for CodeQL version ${cliVersion2 ?? tagName}.` - ); - return fallbackVersion; -} -var downloadCodeQL = async function(codeqlURL, compressionMethod, maybeBundleVersion, maybeCliVersion, apiDetails, tarVersion, tempDir, logger) { - const parsedCodeQLURL = new URL(codeqlURL); - const searchParams = new URLSearchParams(parsedCodeQLURL.search); - const headers = { - accept: "application/octet-stream" - }; - let authorization = void 0; - if (searchParams.has("token")) { - logger.debug("CodeQL tools URL contains an authorization token."); - } else { - authorization = getAuthorizationHeaderFor( - logger, - apiDetails, - codeqlURL - ); - } - const toolcacheInfo = getToolcacheDestinationInfo( - maybeBundleVersion, - maybeCliVersion, - logger - ); - const extractedBundlePath = toolcacheInfo?.path ?? getTempExtractionDir(tempDir); - const statusReport = await downloadAndExtract( - codeqlURL, - compressionMethod, - extractedBundlePath, - authorization, - { "User-Agent": "CodeQL Action", ...headers }, - tarVersion, - logger - ); - if (!toolcacheInfo) { - logger.debug( - `Could not cache CodeQL tools because we could not determine the bundle version from the URL ${codeqlURL}.` - ); - return { - codeqlFolder: extractedBundlePath, - statusReport, - toolsVersion: maybeCliVersion ?? "unknown" - }; - } - writeToolcacheMarkerFile(toolcacheInfo.path, logger); - return { - codeqlFolder: extractedBundlePath, - statusReport, - toolsVersion: maybeCliVersion ?? toolcacheInfo.version - }; -}; -function getToolcacheDestinationInfo(maybeBundleVersion, maybeCliVersion, logger) { - if (maybeBundleVersion) { - const version = getCanonicalToolcacheVersion( - maybeCliVersion, - maybeBundleVersion, - logger - ); - return { - path: getToolcacheDirectory(version), - version - }; - } - return void 0; -} -function getCanonicalToolcacheVersion(cliVersion2, bundleVersion2, logger) { - if (!cliVersion2?.match(/^[0-9]+\.[0-9]+\.[0-9]+$/)) { - return convertToSemVer(bundleVersion2, logger); - } - return cliVersion2; -} -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." - ); - } - const zstdAvailability = await isZstdAvailable(logger); - const source = await getCodeQLSource( - toolsInput, - defaultCliVersion, - apiDetails, - variant, - zstdAvailability.available, - features, - logger - ); - let codeqlFolder; - let toolsVersion = source.toolsVersion; - let toolsDownloadStatusReport; - let toolsSource; - switch (source.sourceType) { - case "local": { - codeqlFolder = await extract( - source.codeqlTarPath, - getTempExtractionDir(tempDir), - source.compressionMethod, - zstdAvailability.version, - logger - ); - toolsSource = "LOCAL" /* Local */; - break; - } - case "toolcache": - codeqlFolder = source.codeqlFolder; - logger.debug(`CodeQL found in cache ${codeqlFolder}`); - toolsSource = "TOOLCACHE" /* Toolcache */; - break; - case "download": { - const result = await downloadCodeQL( - source.codeqlURL, - source.compressionMethod, - source.bundleVersion, - source.cliVersion, - apiDetails, - zstdAvailability.version, - tempDir, - logger - ); - toolsVersion = result.toolsVersion; - codeqlFolder = result.codeqlFolder; - toolsDownloadStatusReport = result.statusReport; - toolsSource = "DOWNLOAD" /* Download */; - break; - } - default: - assertNever(source); - } - return { - codeqlFolder, - toolsDownloadStatusReport, - toolsSource, - toolsVersion, - zstdAvailability - }; -} -async function useZstdBundle(cliVersion2, tarSupportsZstd) { - return ( - // In testing, gzip performs better than zstd on Windows. - process.platform !== "win32" && tarSupportsZstd && semver8.gte(cliVersion2, CODEQL_VERSION_ZSTD_BUNDLE) - ); -} -function getTempExtractionDir(tempDir) { - return path9.join(tempDir, v4_default()); -} -async function getNightlyToolsUrl(logger) { - const zstdAvailability = await isZstdAvailable(logger); - const compressionMethod = await useZstdBundle( - CODEQL_VERSION_ZSTD_BUNDLE, - zstdAvailability.available - ) ? "zstd" : "gzip"; - try { - const release2 = await getApiClient().rest.repos.listReleases({ - owner: CODEQL_NIGHTLIES_REPOSITORY_OWNER, - repo: CODEQL_NIGHTLIES_REPOSITORY_NAME, - per_page: 1, - page: 1, - prerelease: true - }); - const latestRelease = release2.data[0]; - if (!latestRelease) { - throw new Error("Could not find the latest nightly release."); - } - return `https://github.com/${CODEQL_NIGHTLIES_REPOSITORY_OWNER}/${CODEQL_NIGHTLIES_REPOSITORY_NAME}/releases/download/${latestRelease.tag_name}/${getCodeQLBundleName(compressionMethod)}`; - } catch (e) { - throw new Error( - `Failed to retrieve the latest nightly release: ${wrapError(e)}` - ); - } -} -function getLatestToolcacheVersion(logger) { - const allVersions = toolcache3.findAllVersions("CodeQL").sort((a, b) => semver8.compare(b, a)); - logger.debug( - `Found the following versions of the CodeQL tools in the toolcache: ${JSON.stringify( - allVersions - )}.` - ); - if (allVersions.length > 0) { - const latestToolcacheVersion = allVersions[0]; - logger.info( - `CLI version ${latestToolcacheVersion} is the latest version in the toolcache.` - ); - return latestToolcacheVersion; - } - return void 0; -} -function isReservedToolsValue(tools) { - return CODEQL_BUNDLE_VERSION_ALIAS.includes(tools) || CODEQL_NIGHTLY_TOOLS_INPUTS.includes(tools) || tools === CODEQL_TOOLCACHE_INPUT; -} - -// src/tracer-config.ts -async function shouldEnableIndirectTracing(codeql2, config) { - if (config.buildMode === "none" /* None */) { - return false; - } - if (config.buildMode === "autobuild" /* Autobuild */) { - return false; - } - return asyncSome(config.languages, (l) => codeql2.isTracedLanguage(l)); -} - -// src/codeql.ts -var cachedCodeQL = void 0; -var CODEQL_MINIMUM_VERSION = "2.17.6"; -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++"; -var CODEQL_VERSION_CACHE_CLEANUP = "2.17.1"; -async function setupCodeQL(toolsInput, apiDetails, tempDir, variant, defaultCliVersion, features, logger, checkVersion) { - try { - const { - codeqlFolder, - toolsDownloadStatusReport, - toolsSource, - toolsVersion, - zstdAvailability - } = await setupCodeQLBundle( - toolsInput, - apiDetails, - tempDir, - variant, - defaultCliVersion, - features, - logger - ); - logger.debug( - `Bundle download status report: ${JSON.stringify( - toolsDownloadStatusReport - )}` - ); - let codeqlCmd = path10.join(codeqlFolder, "codeql", "codeql"); - if (process.platform === "win32") { - codeqlCmd += ".exe"; - } else if (process.platform !== "linux" && process.platform !== "darwin") { - throw new ConfigurationError( - `Unsupported platform: ${process.platform}` - ); - } - cachedCodeQL = await getCodeQLForCmd(codeqlCmd, checkVersion); - return { - codeql: cachedCodeQL, - toolsDownloadStatusReport, - toolsSource, - toolsVersion, - zstdAvailability - }; - } catch (rawError) { - const e = wrapApiConfigurationError(rawError); - const ErrorClass = e instanceof ConfigurationError || e instanceof Error && e.message.includes("ENOSPC") ? ConfigurationError : Error; - throw new ErrorClass( - `Unable to download and extract CodeQL CLI: ${getErrorMessage(e)}${e instanceof Error && e.stack ? ` - -Details: ${e.stack}` : ""}` - ); - } -} -async function getCodeQL(cmd) { - if (cachedCodeQL === void 0) { - cachedCodeQL = await getCodeQLForCmd(cmd, true); - } - return cachedCodeQL; -} -async function getCodeQLForCmd(cmd, checkVersion) { - const codeql2 = { - getPath() { - return cmd; - }, - async getVersion() { - let result = getCachedCodeQlVersion(); - if (result === void 0) { - const output = await runCli(cmd, ["version", "--format=json"], { - noStreamStdout: true - }); - try { - result = JSON.parse(output); - } catch { - throw Error( - `Invalid JSON output from \`version --format=json\`: ${output}` - ); - } - cacheCodeQlVersion(result); - } - return result; - }, - async printVersion() { - await runCli(cmd, ["version", "--format=json"]); - }, - async supportsFeature(feature) { - return isSupportedToolsFeature(await this.getVersion(), feature); - }, - async isTracedLanguage(language) { - const extractorPath = await this.resolveExtractor(language); - const tracingConfigPath = path10.join( - extractorPath, - "tools", - "tracing-config.lua" - ); - return fs10.existsSync(tracingConfigPath); - }, - async isScannedLanguage(language) { - return !await this.isTracedLanguage(language); - }, - async databaseInitCluster(config, sourceRoot, processName, qlconfigFile, logger) { - const extraArgs = config.languages.map( - (language) => `--language=${language}` - ); - if (await shouldEnableIndirectTracing(codeql2, config)) { - extraArgs.push("--begin-tracing"); - extraArgs.push(...await getTrapCachingExtractorConfigArgs(config)); - extraArgs.push(`--trace-process-name=${processName}`); - } - const codeScanningConfigFile = await writeCodeScanningConfigFile( - config, - logger - ); - const externalRepositoryToken = getOptionalInput( - "external-repository-token" - ); - extraArgs.push(`--codescanning-config=${codeScanningConfigFile}`); - if (externalRepositoryToken) { - extraArgs.push("--external-repository-token-stdin"); - } - if (config.buildMode !== void 0) { - extraArgs.push(`--build-mode=${config.buildMode}`); - } - if (qlconfigFile !== void 0) { - extraArgs.push(`--qlconfig-file=${qlconfigFile}`); - } - const overwriteFlag = isSupportedToolsFeature( - await this.getVersion(), - "forceOverwrite" /* ForceOverwrite */ - ) ? "--force-overwrite" : "--overwrite"; - const overlayDatabaseMode = config.overlayDatabaseMode; - if (overlayDatabaseMode === "overlay" /* Overlay */) { - const overlayChangesFile = await writeOverlayChangesFile( - config, - sourceRoot, - logger - ); - extraArgs.push(`--overlay-changes=${overlayChangesFile}`); - } else if (overlayDatabaseMode === "overlay-base" /* OverlayBase */) { - extraArgs.push("--overlay-base"); - } - const baselineFilesOptions = config.enableFileCoverageInformation ? [ - "--calculate-language-specific-baseline", - "--sublanguage-file-coverage" - ] : ["--no-calculate-baseline"]; - await runCli( - cmd, - [ - "database", - "init", - ...overlayDatabaseMode === "overlay" /* Overlay */ ? [] : [overwriteFlag], - "--db-cluster", - config.dbLocation, - `--source-root=${sourceRoot}`, - ...baselineFilesOptions, - "--extractor-include-aliases", - ...extraArgs, - ...getExtraOptionsFromEnv(["database", "init"], { - // Some user configs specify `--no-calculate-baseline` as an additional - // argument to `codeql database init`. Therefore ignore the baseline file - // options here to avoid specifying the same argument twice and erroring. - ignoringOptions: ["--overwrite", ...baselineFilesOptions] - }) - ], - { stdin: externalRepositoryToken } - ); - if (overlayDatabaseMode === "overlay-base" /* OverlayBase */) { - await writeBaseDatabaseOidsFile(config, sourceRoot); - } - }, - async runAutobuild(config, language) { - applyAutobuildAzurePipelinesTimeoutFix(); - const autobuildCmd = path10.join( - await this.resolveExtractor(language), - "tools", - process.platform === "win32" ? "autobuild.cmd" : "autobuild.sh" - ); - if (config.debugMode) { - process.env["CODEQL_VERBOSITY" /* CLI_VERBOSITY */] = process.env["CODEQL_VERBOSITY" /* CLI_VERBOSITY */] || EXTRACTION_DEBUG_MODE_VERBOSITY; - } - await runCli(autobuildCmd); - }, - async extractScannedLanguage(config, language) { - await runCli(cmd, [ - "database", - "trace-command", - "--index-traceless-dbs", - ...await getTrapCachingExtractorConfigArgsForLang(config, language), - ...getExtractionVerbosityArguments(config.debugMode), - ...getExtraOptionsFromEnv(["database", "trace-command"]), - getCodeQLDatabasePath(config, language) - ]); - }, - async extractUsingBuildMode(config, language) { - if (config.buildMode === "autobuild" /* Autobuild */) { - applyAutobuildAzurePipelinesTimeoutFix(); - } - try { - await runCli(cmd, [ - "database", - "trace-command", - "--use-build-mode", - "--working-dir", - process.cwd(), - ...await getTrapCachingExtractorConfigArgsForLang(config, language), - ...getExtractionVerbosityArguments(config.debugMode), - ...getExtraOptionsFromEnv(["database", "trace-command"]), - getCodeQLDatabasePath(config, language) - ]); - } catch (e) { - if (config.buildMode === "autobuild" /* Autobuild */) { - const prefix = `We were unable to automatically build your code. Please change the build mode for this language to manual and specify build steps for your project. See ${"https://docs.github.com/en/code-security/code-scanning/troubleshooting-code-scanning/automatic-build-failed" /* AUTOMATIC_BUILD_FAILED */} for more information.`; - throw new ConfigurationError(`${prefix} ${getErrorMessage(e)}`); - } else { - throw e; - } - } - }, - async finalizeDatabase(databasePath, threadsFlag, memoryFlag, enableDebugLogging) { - const args = [ - "database", - "finalize", - "--finalize-dataset", - threadsFlag, - memoryFlag, - ...getExtractionVerbosityArguments(enableDebugLogging), - ...getExtraOptionsFromEnv(["database", "finalize"]), - databasePath - ]; - await runCli(cmd, args); - }, - async resolveLanguages() { - const codeqlArgs = [ - "resolve", - "languages", - "--format=json", - ...getExtraOptionsFromEnv(["resolve", "languages"]) - ]; - const output = await runCli(cmd, codeqlArgs); - try { - return JSON.parse(output); - } catch (e) { - throw new Error( - `Unexpected output from codeql resolve languages: ${e}` - ); - } - }, - async betterResolveLanguages({ - filterToLanguagesWithQueries - } = { filterToLanguagesWithQueries: false }) { - const codeqlArgs = [ - "resolve", - "languages", - "--format=betterjson", - "--extractor-options-verbosity=4", - "--extractor-include-aliases", - ...filterToLanguagesWithQueries ? ["--filter-to-languages-with-queries"] : [], - ...getExtraOptionsFromEnv(["resolve", "languages"]) - ]; - const output = await runCli(cmd, codeqlArgs); - try { - return JSON.parse(output); - } catch (e) { - throw new Error( - `Unexpected output from codeql resolve languages with --format=betterjson: ${e}` - ); - } - }, - async resolveBuildEnvironment(workingDir, language) { - const codeqlArgs = [ - "resolve", - "build-environment", - `--language=${language}`, - "--extractor-include-aliases", - ...getExtraOptionsFromEnv(["resolve", "build-environment"]) - ]; - if (workingDir !== void 0) { - codeqlArgs.push("--working-dir", workingDir); - } - const output = await runCli(cmd, codeqlArgs); - try { - return JSON.parse(output); - } catch (e) { - throw new Error( - `Unexpected output from codeql resolve build-environment: ${e} in -${output}` - ); - } - }, - async databaseRunQueries(databasePath, flags, queries = []) { - const codeqlArgs = [ - "database", - "run-queries", - ...flags, - databasePath, - "--min-disk-free=1024", - // Try to leave at least 1GB free - "-v", - ...queries, - ...getExtraOptionsFromEnv(["database", "run-queries"], { - ignoringOptions: ["--expect-discarded-cache"] - }) - ]; - await runCli(cmd, codeqlArgs); - }, - async databaseInterpretResults(databasePath, querySuitePaths, sarifFile, threadsFlag, verbosityFlag, sarifRunPropertyFlag, automationDetailsId, config, features) { - const shouldExportDiagnostics = await features.getValue( - "export_diagnostics_enabled" /* ExportDiagnosticsEnabled */, - this - ); - const codeqlArgs = [ - "database", - "interpret-results", - threadsFlag, - "--format=sarif-latest", - verbosityFlag, - `--output=${sarifFile}`, - "--print-diagnostics-summary", - "--print-metrics-summary", - "--sarif-add-baseline-file-info", - `--sarif-codescanning-config=${getGeneratedCodeScanningConfigPath( - config - )}`, - "--sarif-group-rules-by-pack", - "--sarif-include-query-help=always", - "--sublanguage-file-coverage", - ...await getJobRunUuidSarifOptions(this), - ...getExtraOptionsFromEnv(["database", "interpret-results"]) - ]; - if (sarifRunPropertyFlag !== void 0) { - codeqlArgs.push(sarifRunPropertyFlag); - } - if (automationDetailsId !== void 0) { - codeqlArgs.push("--sarif-category", automationDetailsId); - } - if (shouldExportDiagnostics) { - codeqlArgs.push("--sarif-include-diagnostics"); - } else { - codeqlArgs.push("--no-sarif-include-diagnostics"); - } - codeqlArgs.push(databasePath); - if (querySuitePaths) { - codeqlArgs.push(...querySuitePaths); - } - return await runCli(cmd, codeqlArgs, { - noStreamStdout: true - }); - }, - async databaseCleanupCluster(config, cleanupLevel) { - const cacheCleanupFlag = await codeQlVersionAtLeast( - this, - CODEQL_VERSION_CACHE_CLEANUP - ) ? "--cache-cleanup" : "--mode"; - for (const language of config.languages) { - const databasePath = getCodeQLDatabasePath(config, language); - const codeqlArgs = [ - "database", - "cleanup", - databasePath, - `${cacheCleanupFlag}=${cleanupLevel}`, - ...getExtraOptionsFromEnv(["database", "cleanup"]) - ]; - await runCli(cmd, codeqlArgs); - } - }, - async databaseBundle(databasePath, outputFilePath, databaseName, includeDiagnostics, alsoIncludeRelativePaths) { - const includeDiagnosticsArgs = includeDiagnostics ? ["--include-diagnostics"] : []; - const args = [ - "database", - "bundle", - databasePath, - `--output=${outputFilePath}`, - `--name=${databaseName}`, - ...includeDiagnosticsArgs, - ...getExtraOptionsFromEnv(["database", "bundle"], { - ignoringOptions: includeDiagnosticsArgs - }) - ]; - if (await this.supportsFeature("bundleSupportsIncludeOption" /* BundleSupportsIncludeOption */)) { - args.push( - ...alsoIncludeRelativePaths.flatMap((relativePath) => [ - "--include", - relativePath - ]) - ); - } - await new toolrunner3.ToolRunner(cmd, args).exec(); - }, - async databaseExportDiagnostics(databasePath, sarifFile, automationDetailsId) { - const args = [ - "database", - "export-diagnostics", - `${databasePath}`, - "--db-cluster", - // Database is always a cluster for CodeQL versions that support diagnostics. - "--format=sarif-latest", - `--output=${sarifFile}`, - "--sarif-include-diagnostics", - // ExportDiagnosticsEnabled is always true if this command is run. - "-vvv", - ...getExtraOptionsFromEnv(["diagnostics", "export"]) - ]; - if (automationDetailsId !== void 0) { - args.push("--sarif-category", automationDetailsId); - } - await new toolrunner3.ToolRunner(cmd, args).exec(); - }, - async diagnosticsExport(sarifFile, automationDetailsId, config) { - const args = [ - "diagnostics", - "export", - "--format=sarif-latest", - `--output=${sarifFile}`, - `--sarif-codescanning-config=${getGeneratedCodeScanningConfigPath( - config - )}`, - ...getExtraOptionsFromEnv(["diagnostics", "export"]) - ]; - if (automationDetailsId !== void 0) { - args.push("--sarif-category", automationDetailsId); - } - await new toolrunner3.ToolRunner(cmd, args).exec(); - }, - async resolveExtractor(language) { - let extractorPath = ""; - await new toolrunner3.ToolRunner( - cmd, - [ - "resolve", - "extractor", - "--format=json", - `--language=${language}`, - "--extractor-include-aliases", - ...getExtraOptionsFromEnv(["resolve", "extractor"]) - ], - { - silent: true, - listeners: { - stdout: (data) => { - extractorPath += data.toString(); - }, - stderr: (data) => { - process.stderr.write(data); - } - } - } - ).exec(); - return JSON.parse(extractorPath); - }, - async resolveQueriesStartingPacks(queries) { - const codeqlArgs = [ - "resolve", - "queries", - "--format=startingpacks", - ...getExtraOptionsFromEnv(["resolve", "queries"]), - ...queries - ]; - const output = await runCli(cmd, codeqlArgs, { noStreamStdout: true }); - try { - return JSON.parse(output); - } catch (e) { - throw new Error( - `Unexpected output from codeql resolve queries --format=startingpacks: ${e}` - ); - } - }, - async resolveDatabase(databasePath) { - const codeqlArgs = [ - "resolve", - "database", - databasePath, - "--format=json", - ...getExtraOptionsFromEnv(["resolve", "database"]) - ]; - const output = await runCli(cmd, codeqlArgs, { noStreamStdout: true }); - try { - return JSON.parse(output); - } catch (e) { - throw new Error( - `Unexpected output from codeql resolve database --format=json: ${e}` - ); - } - }, - async mergeResults(sarifFiles, outputFile, { - mergeRunsFromEqualCategory = false - }) { - const args = [ - "github", - "merge-results", - "--output", - outputFile, - ...getExtraOptionsFromEnv(["github", "merge-results"]) - ]; - for (const sarifFile of sarifFiles) { - args.push("--sarif", sarifFile); - } - if (mergeRunsFromEqualCategory) { - args.push("--sarif-merge-runs-from-equal-category"); - } - await runCli(cmd, args); - } - }; - if (checkVersion && !await codeQlVersionAtLeast(codeql2, CODEQL_MINIMUM_VERSION)) { - throw new ConfigurationError( - `Expected a CodeQL CLI with version at least ${CODEQL_MINIMUM_VERSION} but got version ${(await codeql2.getVersion()).version}` - ); - } else if (checkVersion && process.env["CODEQL_ACTION_SUPPRESS_DEPRECATED_SOON_WARNING" /* SUPPRESS_DEPRECATED_SOON_WARNING */] !== "true" && !await codeQlVersionAtLeast(codeql2, CODEQL_NEXT_MINIMUM_VERSION)) { - const result = await codeql2.getVersion(); - core10.warning( - `CodeQL CLI version ${result.version} was discontinued on ${GHES_MOST_RECENT_DEPRECATION_DATE} alongside GitHub Enterprise Server ${GHES_VERSION_MOST_RECENTLY_DEPRECATED} and will not be supported by the next minor release of the CodeQL Action. Please update to CodeQL CLI version ${CODEQL_NEXT_MINIMUM_VERSION} or later. For instance, if you have specified a custom version of the CLI using the 'tools' input to the 'init' Action, you can remove this input to use the default version. - -Alternatively, if you want to continue using CodeQL CLI version ${result.version}, you can replace 'github/codeql-action/*@v${getActionVersion().split(".")[0]}' by 'github/codeql-action/*@v${getActionVersion()}' in your code scanning workflow to continue using this version of the CodeQL Action.` - ); - core10.exportVariable("CODEQL_ACTION_SUPPRESS_DEPRECATED_SOON_WARNING" /* SUPPRESS_DEPRECATED_SOON_WARNING */, "true"); - } - return codeql2; -} -function getExtraOptionsFromEnv(paths, { ignoringOptions } = {}) { - const options = getExtraOptionsEnvParam(); - return getExtraOptions(options, paths, []).filter( - (option) => !ignoringOptions?.includes(option) - ); -} -function asExtraOptions(options, pathInfo) { - if (options === void 0) { - return []; - } - if (!Array.isArray(options)) { - const msg = `The extra options for '${pathInfo.join( - "." - )}' ('${JSON.stringify(options)}') are not in an array.`; - throw new Error(msg); - } - return options.map((o) => { - const t = typeof o; - if (t !== "string" && t !== "number" && t !== "boolean") { - const msg = `The extra option for '${pathInfo.join( - "." - )}' ('${JSON.stringify(o)}') is not a primitive value.`; - throw new Error(msg); - } - return `${o}`; - }); -} -function getExtraOptions(options, paths, pathInfo) { - const all = asExtraOptions(options?.["*"], pathInfo.concat("*")); - const specific = paths.length === 0 ? asExtraOptions(options, pathInfo) : getExtraOptions( - options?.[paths[0]], - paths?.slice(1), - pathInfo.concat(paths[0]) - ); - return all.concat(specific); -} -async function runCli(cmd, args = [], opts = {}) { - try { - return await runTool(cmd, args, opts); - } catch (e) { - if (e instanceof CommandInvocationError) { - throw wrapCliConfigurationError(new CliError(e)); - } - throw e; - } -} -async function writeCodeScanningConfigFile(config, logger) { - const codeScanningConfigFile = getGeneratedCodeScanningConfigPath(config); - const augmentedConfig = appendExtraQueryExclusions( - config.extraQueryExclusions, - config.computedConfig - ); - logger.info( - `Writing augmented user configuration file to ${codeScanningConfigFile}` - ); - logger.startGroup("Augmented user configuration file contents"); - logger.info(dump(augmentedConfig)); - logger.endGroup(); - fs10.writeFileSync(codeScanningConfigFile, dump(augmentedConfig)); - return codeScanningConfigFile; -} -var TRAP_CACHE_SIZE_MB = 1024; -async function getTrapCachingExtractorConfigArgs(config) { - const result = []; - for (const language of config.languages) - result.push( - await getTrapCachingExtractorConfigArgsForLang(config, language) - ); - return result.flat(); -} -async function getTrapCachingExtractorConfigArgsForLang(config, language) { - const cacheDir = config.trapCaches[language]; - if (cacheDir === void 0) return []; - const write = await isAnalyzingDefaultBranch(); - return [ - `-O=${language}.trap.cache.dir=${cacheDir}`, - `-O=${language}.trap.cache.bound=${TRAP_CACHE_SIZE_MB}`, - `-O=${language}.trap.cache.write=${write}` - ]; -} -function getGeneratedCodeScanningConfigPath(config) { - return path10.resolve(config.tempDir, "user-config.yaml"); -} -function getExtractionVerbosityArguments(enableDebugLogging) { - return enableDebugLogging ? [`--verbosity=${EXTRACTION_DEBUG_MODE_VERBOSITY}`] : []; -} -function applyAutobuildAzurePipelinesTimeoutFix() { - const javaToolOptions = process.env["JAVA_TOOL_OPTIONS"] || ""; - process.env["JAVA_TOOL_OPTIONS"] = [ - ...javaToolOptions.split(/\s+/), - "-Dhttp.keepAlive=false", - "-Dmaven.wagon.http.pool=false" - ].join(" "); -} -async function getJobRunUuidSarifOptions(codeql2) { - const jobRunUuid = process.env["JOB_RUN_UUID" /* JOB_RUN_UUID */]; - return jobRunUuid && await codeql2.supportsFeature( - "databaseInterpretResultsSupportsSarifRunProperty" /* DatabaseInterpretResultsSupportsSarifRunProperty */ - ) ? [`--sarif-run-property=jobRunUuid=${jobRunUuid}`] : []; -} - // src/status-report.ts -var os2 = __toESM(require("os")); -var core11 = __toESM(require_core()); +var os = __toESM(require("os")); +var core9 = __toESM(require_core()); function isFirstPartyAnalysis(actionName) { if (actionName !== "upload-sarif" /* UploadSarif */) { return true; @@ -109392,12 +107568,12 @@ function getActionsStatus(error3, otherFailureCause) { } function setJobStatusIfUnsuccessful(actionStatus) { if (actionStatus === "user-error") { - core11.exportVariable( + core9.exportVariable( "CODEQL_ACTION_JOB_STATUS" /* JOB_STATUS */, process.env["CODEQL_ACTION_JOB_STATUS" /* JOB_STATUS */] ?? "JOB_STATUS_CONFIGURATION_ERROR" /* ConfigErrorStatus */ ); } else if (actionStatus === "failure" || actionStatus === "aborted") { - core11.exportVariable( + core9.exportVariable( "CODEQL_ACTION_JOB_STATUS" /* JOB_STATUS */, process.env["CODEQL_ACTION_JOB_STATUS" /* JOB_STATUS */] ?? "JOB_STATUS_FAILURE" /* FailureStatus */ ); @@ -109416,14 +107592,14 @@ async function createStatusReportBase(actionName, status, actionStartedAt, confi let workflowStartedAt = process.env["CODEQL_WORKFLOW_STARTED_AT" /* WORKFLOW_STARTED_AT */]; if (workflowStartedAt === void 0) { workflowStartedAt = actionStartedAt.toISOString(); - core11.exportVariable("CODEQL_WORKFLOW_STARTED_AT" /* WORKFLOW_STARTED_AT */, workflowStartedAt); + core9.exportVariable("CODEQL_WORKFLOW_STARTED_AT" /* WORKFLOW_STARTED_AT */, workflowStartedAt); } const runnerOs = getRequiredEnvParam("RUNNER_OS"); const codeQlCliVersion = getCachedCodeQlVersion(); const actionRef = process.env["GITHUB_ACTION_REF"] || ""; const testingEnvironment = getTestingEnvironment(); if (testingEnvironment) { - core11.exportVariable("CODEQL_ACTION_TESTING_ENVIRONMENT" /* TESTING_ENVIRONMENT */, testingEnvironment); + core9.exportVariable("CODEQL_ACTION_TESTING_ENVIRONMENT" /* TESTING_ENVIRONMENT */, testingEnvironment); } const isSteadyStateDefaultSetupRun = process.env["CODE_SCANNING_IS_STEADY_STATE_DEFAULT_SETUP"] === "true"; const statusReport = { @@ -109481,7 +107657,7 @@ async function createStatusReportBase(actionName, status, actionStartedAt, confi statusReport.runner_arch = process.env["RUNNER_ARCH"]; } if (!(runnerOs === "Linux" && isSelfHostedRunner())) { - statusReport.runner_os_release = os2.release(); + statusReport.runner_os_release = os.release(); } if (codeQlCliVersion !== void 0) { statusReport.codeql_version = codeQlCliVersion.version; @@ -109506,9 +107682,9 @@ var INCOMPATIBLE_MSG = "CodeQL Action version is incompatible with the API endpo async function sendStatusReport(statusReport) { setJobStatusIfUnsuccessful(statusReport.status); const statusReportJSON = JSON.stringify(statusReport); - core11.debug(`Sending status report: ${statusReportJSON}`); + core9.debug(`Sending status report: ${statusReportJSON}`); if (isInTestMode()) { - core11.debug("In test mode. Status reports are not uploaded."); + core9.debug("In test mode. Status reports are not uploaded."); return; } const nwo = getRepositoryNwo(); @@ -109528,28 +107704,28 @@ async function sendStatusReport(statusReport) { switch (httpError.status) { case 403: if (getWorkflowEventName() === "push" && process.env["GITHUB_ACTOR"] === "dependabot[bot]") { - core11.warning( + core9.warning( `Workflows triggered by Dependabot on the "push" event run with read-only access. Uploading CodeQL results requires write access. To use CodeQL with Dependabot, please ensure you are using the "pull_request" event for this workflow and avoid triggering on the "push" event for Dependabot branches. See ${"https://docs.github.com/en/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/customizing-your-advanced-setup-for-code-scanning#scanning-on-push" /* SCANNING_ON_PUSH */} for more information on how to configure these events.` ); } else { - core11.warning( + core9.warning( `This run of the CodeQL Action does not have permission to access the CodeQL Action API endpoints. This could be because the Action is running on a pull request from a fork. If not, please ensure the workflow has at least the 'security-events: read' permission. Details: ${httpError.message}` ); } return; case 404: - core11.warning(httpError.message); + core9.warning(httpError.message); return; case 422: if (getRequiredEnvParam("GITHUB_SERVER_URL") !== GITHUB_DOTCOM_URL) { - core11.debug(INCOMPATIBLE_MSG); + core9.debug(INCOMPATIBLE_MSG); } else { - core11.debug(OUT_OF_DATE_MSG); + core9.debug(OUT_OF_DATE_MSG); } return; } } - core11.warning( + core9.warning( `An unexpected error occurred when sending a status report: ${getErrorMessage( e )}` @@ -109590,7 +107766,7 @@ var core12 = __toESM(require_core()); var jsonschema2 = __toESM(require_lib2()); // src/fingerprints.ts -var fs11 = __toESM(require("fs")); +var fs7 = __toESM(require("fs")); var import_path2 = __toESM(require("path")); // node_modules/long/index.js @@ -110163,7 +108339,7 @@ LongPrototype.greaterThanOrEqual = function greaterThanOrEqual(other) { }; LongPrototype.gte = LongPrototype.greaterThanOrEqual; LongPrototype.ge = LongPrototype.greaterThanOrEqual; -LongPrototype.compare = function compare2(other) { +LongPrototype.compare = function compare(other) { if (!isLong(other)) other = fromValue(other); if (this.eq(other)) return 0; var thisNeg = this.isNegative(), otherNeg = other.isNegative(); @@ -110578,7 +108754,7 @@ async function hash(callback, filepath) { } updateHash(current); }; - const readStream = fs11.createReadStream(filepath, "utf8"); + const readStream = fs7.createReadStream(filepath, "utf8"); for await (const data of readStream) { for (let i = 0; i < data.length; ++i) { processCharacter(data.charCodeAt(i)); @@ -110653,11 +108829,11 @@ function resolveUriToFile(location, artifacts, sourceRoot, logger) { if (!import_path2.default.isAbsolute(uri)) { uri = srcRootPrefix + uri; } - if (!fs11.existsSync(uri)) { + if (!fs7.existsSync(uri)) { logger.debug(`Unable to compute fingerprint for non-existent file: ${uri}`); return void 0; } - if (fs11.statSync(uri).isDirectory()) { + if (fs7.statSync(uri).isDirectory()) { logger.debug(`Unable to compute fingerprint for directory: ${uri}`); return void 0; } @@ -110714,10 +108890,1836 @@ async function addFingerprints(sarif, sourceRoot, logger) { // src/init.ts var toolrunner4 = __toESM(require_toolrunner()); var io5 = __toESM(require_io()); + +// src/codeql.ts +var fs11 = __toESM(require("fs")); +var path11 = __toESM(require("path")); +var core11 = __toESM(require_core()); +var toolrunner3 = __toESM(require_toolrunner()); + +// src/cli-errors.ts +var SUPPORTED_PLATFORMS = [ + ["linux", "x64"], + ["win32", "x64"], + ["darwin", "x64"], + ["darwin", "arm64"] +]; +var CliError = class extends Error { + exitCode; + stderr; + constructor({ cmd, args, exitCode, stderr }) { + const prettyCommand = prettyPrintInvocation(cmd, args); + const fatalErrors = extractFatalErrors(stderr); + const autobuildErrors = extractAutobuildErrors(stderr); + let message; + if (fatalErrors) { + message = `Encountered a fatal error while running "${prettyCommand}". Exit code was ${exitCode} and error was: ${ensureEndsInPeriod( + fatalErrors.trim() + )} See the logs for more details.`; + } else if (autobuildErrors) { + message = `We were unable to automatically build your code. Please provide manual build steps. See ${"https://docs.github.com/en/code-security/code-scanning/troubleshooting-code-scanning/automatic-build-failed" /* AUTOMATIC_BUILD_FAILED */} for more information. Encountered the following error: ${autobuildErrors}`; + } else { + const lastLine = ensureEndsInPeriod( + stderr.trim().split("\n").pop()?.trim() || "n/a" + ); + message = `Encountered a fatal error while running "${prettyCommand}". Exit code was ${exitCode} and last log line was: ${lastLine} See the logs for more details.`; + } + super(message); + this.exitCode = exitCode; + this.stderr = stderr; + } +}; +function extractFatalErrors(error3) { + const fatalErrorRegex = /.*fatal (internal )?error occurr?ed(. Details)?:/gi; + let fatalErrors = []; + let lastFatalErrorIndex; + let match; + while ((match = fatalErrorRegex.exec(error3)) !== null) { + if (lastFatalErrorIndex !== void 0) { + fatalErrors.push(error3.slice(lastFatalErrorIndex, match.index).trim()); + } + lastFatalErrorIndex = match.index; + } + if (lastFatalErrorIndex !== void 0) { + const lastError = error3.slice(lastFatalErrorIndex).trim(); + if (fatalErrors.length === 0) { + return lastError; + } + const isOneLiner = !fatalErrors.some((e) => e.includes("\n")); + if (isOneLiner) { + fatalErrors = fatalErrors.map(ensureEndsInPeriod); + } + return [ + ensureEndsInPeriod(lastError), + "Context:", + ...fatalErrors.reverse() + ].join(isOneLiner ? " " : "\n"); + } + return void 0; +} +function extractAutobuildErrors(error3) { + const pattern = /.*\[autobuild\] \[ERROR\] (.*)/gi; + let errorLines = [...error3.matchAll(pattern)].map((match) => match[1]); + if (errorLines.length > 10) { + errorLines = errorLines.slice(0, 10); + errorLines.push("(truncated)"); + } + return errorLines.join("\n") || void 0; +} +var cliErrorsConfig = { + ["AutobuildError" /* AutobuildError */]: { + cliErrorMessageCandidates: [ + new RegExp("We were unable to automatically build your code") + ] + }, + ["CouldNotCreateTempDir" /* CouldNotCreateTempDir */]: { + cliErrorMessageCandidates: [new RegExp("Could not create temp directory")] + }, + ["ExternalRepositoryCloneFailed" /* ExternalRepositoryCloneFailed */]: { + cliErrorMessageCandidates: [ + new RegExp("Failed to clone external Git repository") + ] + }, + ["GradleBuildFailed" /* GradleBuildFailed */]: { + cliErrorMessageCandidates: [ + new RegExp("\\[autobuild\\] FAILURE: Build failed with an exception.") + ] + }, + // Version of CodeQL CLI is incompatible with this version of the CodeQL Action + ["IncompatibleWithActionVersion" /* IncompatibleWithActionVersion */]: { + cliErrorMessageCandidates: [ + new RegExp("is not compatible with this CodeQL CLI") + ] + }, + ["InitCalledTwice" /* InitCalledTwice */]: { + cliErrorMessageCandidates: [ + new RegExp( + "Refusing to create databases .* but could not process any of it" + ) + ], + additionalErrorMessageToAppend: `Is the "init" action called twice in the same job?` + }, + ["InvalidConfigFile" /* InvalidConfigFile */]: { + cliErrorMessageCandidates: [ + new RegExp("Config file .* is not valid"), + new RegExp("The supplied config file is empty") + ] + }, + ["InvalidExternalRepoSpecifier" /* InvalidExternalRepoSpecifier */]: { + cliErrorMessageCandidates: [ + new RegExp("Specifier for external repository is invalid") + ] + }, + // Expected source location for database creation does not exist + ["InvalidSourceRoot" /* InvalidSourceRoot */]: { + cliErrorMessageCandidates: [new RegExp("Invalid source root")] + }, + ["MavenBuildFailed" /* MavenBuildFailed */]: { + cliErrorMessageCandidates: [ + new RegExp("\\[autobuild\\] \\[ERROR\\] Failed to execute goal") + ] + }, + ["NoBuildCommandAutodetected" /* NoBuildCommandAutodetected */]: { + cliErrorMessageCandidates: [ + new RegExp("Could not auto-detect a suitable build method") + ] + }, + ["NoBuildMethodAutodetected" /* NoBuildMethodAutodetected */]: { + cliErrorMessageCandidates: [ + new RegExp( + "Could not detect a suitable build command for the source checkout" + ) + ] + }, + // Usually when a manual build script has failed, or if an autodetected language + // was unintended to have CodeQL analysis run on it. + ["NoSourceCodeSeen" /* NoSourceCodeSeen */]: { + exitCode: 32, + cliErrorMessageCandidates: [ + new RegExp( + "CodeQL detected code written in .* but could not process any of it" + ), + new RegExp( + "CodeQL did not detect any code written in languages supported by CodeQL" + ) + ] + }, + ["NoSupportedBuildCommandSucceeded" /* NoSupportedBuildCommandSucceeded */]: { + cliErrorMessageCandidates: [ + new RegExp("No supported build command succeeded") + ] + }, + ["NoSupportedBuildSystemDetected" /* NoSupportedBuildSystemDetected */]: { + cliErrorMessageCandidates: [ + new RegExp("No supported build system detected") + ] + }, + ["OutOfMemoryOrDisk" /* OutOfMemoryOrDisk */]: { + cliErrorMessageCandidates: [ + new RegExp("CodeQL is out of memory."), + new RegExp("out of disk"), + new RegExp("No space left on device") + ], + additionalErrorMessageToAppend: "For more information, see https://gh.io/troubleshooting-code-scanning/out-of-disk-or-memory" + }, + ["PackCannotBeFound" /* PackCannotBeFound */]: { + cliErrorMessageCandidates: [ + new RegExp( + "Query pack .* cannot be found\\. Check the spelling of the pack\\." + ), + new RegExp( + "is not a .ql file, .qls file, a directory, or a query pack specification." + ) + ] + }, + ["PackMissingAuth" /* PackMissingAuth */]: { + cliErrorMessageCandidates: [ + new RegExp("GitHub Container registry .* 403 Forbidden"), + new RegExp( + "Do you need to specify a token to authenticate to the registry?" + ) + ] + }, + ["SwiftBuildFailed" /* SwiftBuildFailed */]: { + cliErrorMessageCandidates: [ + new RegExp( + "\\[autobuilder/build\\] \\[build-command-failed\\] `autobuild` failed to run the build command" + ) + ] + }, + ["UnsupportedBuildMode" /* UnsupportedBuildMode */]: { + cliErrorMessageCandidates: [ + new RegExp( + "does not support the .* build mode. Please try using one of the following build modes instead" + ) + ] + }, + ["NotFoundInRegistry" /* NotFoundInRegistry */]: { + cliErrorMessageCandidates: [ + new RegExp("'.*' not found in the registry '.*'") + ] + } +}; +function getCliConfigCategoryIfExists(cliError) { + for (const [category, configuration] of Object.entries(cliErrorsConfig)) { + if (cliError.exitCode !== void 0 && configuration.exitCode !== void 0 && cliError.exitCode === configuration.exitCode) { + return category; + } + for (const e of configuration.cliErrorMessageCandidates) { + if (cliError.message.match(e) || cliError.stderr.match(e)) { + return category; + } + } + } + return void 0; +} +function isUnsupportedPlatform() { + return !SUPPORTED_PLATFORMS.some( + ([platform, arch2]) => platform === process.platform && arch2 === process.arch + ); +} +function getUnsupportedPlatformError(cliError) { + return new ConfigurationError( + `The CodeQL CLI does not support the platform/architecture combination of ${process.platform}/${process.arch} (see ${"https://codeql.github.com/docs/codeql-overview/system-requirements/" /* SYSTEM_REQUIREMENTS */}). The underlying error was: ${cliError.message}` + ); +} +function wrapCliConfigurationError(cliError) { + if (isUnsupportedPlatform()) { + return getUnsupportedPlatformError(cliError); + } + const cliConfigErrorCategory = getCliConfigCategoryIfExists(cliError); + if (cliConfigErrorCategory === void 0) { + return cliError; + } + let errorMessageBuilder = cliError.message; + const additionalErrorMessageToAppend = cliErrorsConfig[cliConfigErrorCategory].additionalErrorMessageToAppend; + if (additionalErrorMessageToAppend !== void 0) { + errorMessageBuilder = `${errorMessageBuilder} ${additionalErrorMessageToAppend}`; + } + return new ConfigurationError(errorMessageBuilder); +} + +// src/setup-codeql.ts +var fs10 = __toESM(require("fs")); +var path10 = __toESM(require("path")); +var toolcache3 = __toESM(require_tool_cache()); +var import_fast_deep_equal = __toESM(require_fast_deep_equal()); +var semver8 = __toESM(require_semver2()); + +// node_modules/uuid/dist-node/stringify.js +var byteToHex = []; +for (let i = 0; i < 256; ++i) { + byteToHex.push((i + 256).toString(16).slice(1)); +} +function unsafeStringify(arr, offset = 0) { + return (byteToHex[arr[offset + 0]] + byteToHex[arr[offset + 1]] + byteToHex[arr[offset + 2]] + byteToHex[arr[offset + 3]] + "-" + byteToHex[arr[offset + 4]] + byteToHex[arr[offset + 5]] + "-" + byteToHex[arr[offset + 6]] + byteToHex[arr[offset + 7]] + "-" + byteToHex[arr[offset + 8]] + byteToHex[arr[offset + 9]] + "-" + byteToHex[arr[offset + 10]] + byteToHex[arr[offset + 11]] + byteToHex[arr[offset + 12]] + byteToHex[arr[offset + 13]] + byteToHex[arr[offset + 14]] + byteToHex[arr[offset + 15]]).toLowerCase(); +} + +// node_modules/uuid/dist-node/rng.js +var import_node_crypto = require("node:crypto"); +var rnds8Pool = new Uint8Array(256); +var poolPtr = rnds8Pool.length; +function rng() { + if (poolPtr > rnds8Pool.length - 16) { + (0, import_node_crypto.randomFillSync)(rnds8Pool); + poolPtr = 0; + } + return rnds8Pool.slice(poolPtr, poolPtr += 16); +} + +// node_modules/uuid/dist-node/native.js +var import_node_crypto2 = require("node:crypto"); +var native_default = { randomUUID: import_node_crypto2.randomUUID }; + +// node_modules/uuid/dist-node/v4.js +function _v4(options, buf, offset) { + options = options || {}; + const rnds = options.random ?? options.rng?.() ?? rng(); + if (rnds.length < 16) { + throw new Error("Random bytes length must be >= 16"); + } + rnds[6] = rnds[6] & 15 | 64; + rnds[8] = rnds[8] & 63 | 128; + if (buf) { + offset = offset || 0; + if (offset < 0 || offset + 16 > buf.length) { + throw new RangeError(`UUID byte range ${offset}:${offset + 15} is out of buffer bounds`); + } + for (let i = 0; i < 16; ++i) { + buf[offset + i] = rnds[i]; + } + return buf; + } + return unsafeStringify(rnds); +} +function v4(options, buf, offset) { + if (native_default.randomUUID && !buf && !options) { + return native_default.randomUUID(); + } + return _v4(options, buf, offset); +} +var v4_default = v4; + +// src/tar.ts +var import_child_process = require("child_process"); +var fs8 = __toESM(require("fs")); +var stream = __toESM(require("stream")); +var import_toolrunner = __toESM(require_toolrunner()); +var io4 = __toESM(require_io()); +var toolcache = __toESM(require_tool_cache()); +var semver6 = __toESM(require_semver2()); +var MIN_REQUIRED_BSD_TAR_VERSION = "3.4.3"; +var MIN_REQUIRED_GNU_TAR_VERSION = "1.31"; +async function getTarVersion() { + const tar = await io4.which("tar", true); + let stdout = ""; + const exitCode = await new import_toolrunner.ToolRunner(tar, ["--version"], { + listeners: { + stdout: (data) => { + stdout += data.toString(); + } + } + }).exec(); + if (exitCode !== 0) { + throw new Error("Failed to call tar --version"); + } + if (stdout.includes("GNU tar")) { + const match = stdout.match(/tar \(GNU tar\) ([0-9.]+)/); + if (!match?.[1]) { + throw new Error("Failed to parse output of tar --version."); + } + return { type: "gnu", version: match[1] }; + } else if (stdout.includes("bsdtar")) { + const match = stdout.match(/bsdtar ([0-9.]+)/); + if (!match?.[1]) { + throw new Error("Failed to parse output of tar --version."); + } + return { type: "bsd", version: match[1] }; + } else { + throw new Error("Unknown tar version"); + } +} +async function isZstdAvailable(logger) { + const foundZstdBinary = await isBinaryAccessible("zstd", logger); + try { + const tarVersion = await getTarVersion(); + const { type: type2, version } = tarVersion; + logger.info(`Found ${type2} tar version ${version}.`); + switch (type2) { + case "gnu": + return { + available: foundZstdBinary && // GNU tar only uses major and minor version numbers + semver6.gte( + semver6.coerce(version), + semver6.coerce(MIN_REQUIRED_GNU_TAR_VERSION) + ), + foundZstdBinary, + version: tarVersion + }; + case "bsd": + return { + available: foundZstdBinary && // Do a loose comparison since these version numbers don't contain + // a patch version number. + semver6.gte(version, MIN_REQUIRED_BSD_TAR_VERSION), + foundZstdBinary, + version: tarVersion + }; + default: + assertNever(type2); + } + } catch (e) { + logger.warning( + `Failed to determine tar version, therefore will assume zstd is not available. The underlying error was: ${e}` + ); + return { available: false, foundZstdBinary }; + } +} +async function extract(tarPath, dest, compressionMethod, tarVersion, logger) { + fs8.mkdirSync(dest, { recursive: true }); + switch (compressionMethod) { + case "gzip": + return await toolcache.extractTar(tarPath, dest); + case "zstd": { + if (!tarVersion) { + throw new Error( + "Could not determine tar version, which is required to extract a Zstandard archive." + ); + } + await extractTarZst(tarPath, dest, tarVersion, logger); + return dest; + } + } +} +async function extractTarZst(tar, dest, tarVersion, logger) { + logger.debug( + `Extracting to ${dest}.${tar instanceof stream.Readable ? ` Input stream has high water mark ${tar.readableHighWaterMark}.` : ""}` + ); + try { + const args = ["-x", "--zstd", "--ignore-zeros"]; + if (tarVersion.type === "gnu") { + args.push("--warning=no-unknown-keyword"); + args.push("--overwrite"); + } + args.push("-f", tar instanceof stream.Readable ? "-" : tar, "-C", dest); + process.stdout.write(`[command]tar ${args.join(" ")} +`); + await new Promise((resolve6, reject) => { + const tarProcess = (0, import_child_process.spawn)("tar", args, { stdio: "pipe" }); + let stdout = ""; + tarProcess.stdout?.on("data", (data) => { + stdout += data.toString(); + process.stdout.write(data); + }); + let stderr = ""; + tarProcess.stderr?.on("data", (data) => { + stderr += data.toString(); + process.stdout.write(data); + }); + tarProcess.on("error", (err) => { + reject(new Error(`Error while extracting tar: ${err}`)); + }); + if (tar instanceof stream.Readable) { + tar.pipe(tarProcess.stdin).on("error", (err) => { + reject( + new Error(`Error while downloading and extracting tar: ${err}`) + ); + }); + } + tarProcess.on("exit", (code) => { + if (code !== 0) { + reject( + new CommandInvocationError( + "tar", + args, + code ?? void 0, + stdout, + stderr + ) + ); + } + resolve6(); + }); + }); + } catch (e) { + await cleanUpPath(dest, "extraction destination directory", logger); + throw e; + } +} +var KNOWN_EXTENSIONS = { + "tar.gz": "gzip", + "tar.zst": "zstd" +}; +function inferCompressionMethod(tarPath) { + for (const [ext, method] of Object.entries(KNOWN_EXTENSIONS)) { + if (tarPath.endsWith(`.${ext}`)) { + return method; + } + } + return void 0; +} + +// src/tools-download.ts +var fs9 = __toESM(require("fs")); +var os2 = __toESM(require("os")); +var path9 = __toESM(require("path")); +var import_perf_hooks = require("perf_hooks"); +var core10 = __toESM(require_core()); +var import_http_client = __toESM(require_lib()); +var toolcache2 = __toESM(require_tool_cache()); +var import_follow_redirects = __toESM(require_follow_redirects()); +var semver7 = __toESM(require_semver2()); +var STREAMING_HIGH_WATERMARK_BYTES = 4 * 1024 * 1024; +var TOOLCACHE_TOOL_NAME = "CodeQL"; +function makeDownloadFirstToolsDownloadDurations(downloadDurationMs, extractionDurationMs) { + return { + combinedDurationMs: downloadDurationMs + extractionDurationMs, + downloadDurationMs, + extractionDurationMs, + streamExtraction: false + }; +} +function makeStreamedToolsDownloadDurations(combinedDurationMs) { + return { + combinedDurationMs, + downloadDurationMs: void 0, + extractionDurationMs: void 0, + streamExtraction: true + }; +} +async function downloadAndExtract(codeqlURL, compressionMethod, dest, authorization, headers, tarVersion, logger) { + logger.info( + `Downloading CodeQL tools from ${codeqlURL} . This may take a while.` + ); + try { + if (compressionMethod === "zstd" && process.platform === "linux") { + logger.info(`Streaming the extraction of the CodeQL bundle.`); + const toolsInstallStart = import_perf_hooks.performance.now(); + await downloadAndExtractZstdWithStreaming( + codeqlURL, + dest, + authorization, + headers, + tarVersion, + logger + ); + const combinedDurationMs = Math.round( + import_perf_hooks.performance.now() - toolsInstallStart + ); + logger.info( + `Finished downloading and extracting CodeQL bundle to ${dest} (${formatDuration( + combinedDurationMs + )}).` + ); + return { + compressionMethod, + toolsUrl: sanitizeUrlForStatusReport(codeqlURL), + ...makeStreamedToolsDownloadDurations(combinedDurationMs) + }; + } + } catch (e) { + core10.warning( + `Failed to download and extract CodeQL bundle using streaming with error: ${getErrorMessage(e)}` + ); + core10.warning(`Falling back to downloading the bundle before extracting.`); + await cleanUpPath(dest, "CodeQL bundle", logger); + } + const toolsDownloadStart = import_perf_hooks.performance.now(); + const archivedBundlePath = await toolcache2.downloadTool( + codeqlURL, + void 0, + authorization, + headers + ); + const downloadDurationMs = Math.round(import_perf_hooks.performance.now() - toolsDownloadStart); + logger.info( + `Finished downloading CodeQL bundle to ${archivedBundlePath} (${formatDuration( + downloadDurationMs + )}).` + ); + let extractionDurationMs; + try { + logger.info("Extracting CodeQL bundle."); + const extractionStart = import_perf_hooks.performance.now(); + await extract( + archivedBundlePath, + dest, + compressionMethod, + tarVersion, + logger + ); + extractionDurationMs = Math.round(import_perf_hooks.performance.now() - extractionStart); + logger.info( + `Finished extracting CodeQL bundle to ${dest} (${formatDuration( + extractionDurationMs + )}).` + ); + } finally { + await cleanUpPath(archivedBundlePath, "CodeQL bundle archive", logger); + } + return { + compressionMethod, + toolsUrl: sanitizeUrlForStatusReport(codeqlURL), + ...makeDownloadFirstToolsDownloadDurations( + downloadDurationMs, + extractionDurationMs + ) + }; +} +async function downloadAndExtractZstdWithStreaming(codeqlURL, dest, authorization, headers, tarVersion, logger) { + fs9.mkdirSync(dest, { recursive: true }); + const agent = new import_http_client.HttpClient().getAgent(codeqlURL); + headers = Object.assign( + { "User-Agent": "CodeQL Action" }, + authorization ? { authorization } : {}, + headers + ); + const response = await new Promise( + (resolve6) => import_follow_redirects.https.get( + codeqlURL, + { + headers, + // Increase the high water mark to improve performance. + highWaterMark: STREAMING_HIGH_WATERMARK_BYTES, + // Use the agent to respect proxy settings. + agent + }, + (r) => resolve6(r) + ) + ); + if (response.statusCode !== 200) { + throw new Error( + `Failed to download CodeQL bundle from ${codeqlURL}. HTTP status code: ${response.statusCode}.` + ); + } + await extractTarZst(response, dest, tarVersion, logger); +} +function getToolcacheDirectory(version) { + return path9.join( + getRequiredEnvParam("RUNNER_TOOL_CACHE"), + TOOLCACHE_TOOL_NAME, + semver7.clean(version) || version, + os2.arch() || "" + ); +} +function writeToolcacheMarkerFile(extractedPath, logger) { + const markerFilePath = `${extractedPath}.complete`; + fs9.writeFileSync(markerFilePath, ""); + logger.info(`Created toolcache marker file ${markerFilePath}`); +} +function sanitizeUrlForStatusReport(url2) { + return ["github/codeql-action", "dsp-testing/codeql-cli-nightlies"].some( + (repo) => url2.startsWith(`https://github.com/${repo}/releases/download/`) + ) ? url2 : "sanitized-value"; +} + +// src/setup-codeql.ts +var CODEQL_DEFAULT_ACTION_REPOSITORY = "github/codeql-action"; +var CODEQL_NIGHTLIES_REPOSITORY_OWNER = "dsp-testing"; +var CODEQL_NIGHTLIES_REPOSITORY_NAME = "codeql-cli-nightlies"; +var CODEQL_BUNDLE_VERSION_ALIAS = ["linked", "latest"]; +var CODEQL_NIGHTLY_TOOLS_INPUTS = ["nightly", "nightly-latest"]; +var CODEQL_TOOLCACHE_INPUT = "toolcache"; +function getCodeQLBundleExtension(compressionMethod) { + switch (compressionMethod) { + case "gzip": + return ".tar.gz"; + case "zstd": + return ".tar.zst"; + default: + assertNever(compressionMethod); + } +} +function getCodeQLBundleName(compressionMethod) { + const extension = getCodeQLBundleExtension(compressionMethod); + let platform; + if (process.platform === "win32") { + platform = "win64"; + } else if (process.platform === "linux") { + platform = "linux64"; + } else if (process.platform === "darwin") { + platform = "osx64"; + } else { + return `codeql-bundle${extension}`; + } + return `codeql-bundle-${platform}${extension}`; +} +function getCodeQLActionRepository(logger) { + if (isRunningLocalAction()) { + logger.info( + "The CodeQL Action is checked out locally. Using the default CodeQL Action repository." + ); + return CODEQL_DEFAULT_ACTION_REPOSITORY; + } + return getRequiredEnvParam("GITHUB_ACTION_REPOSITORY"); +} +async function getCodeQLBundleDownloadURL(tagName, apiDetails, compressionMethod, logger) { + const codeQLActionRepository = getCodeQLActionRepository(logger); + const potentialDownloadSources = [ + // This GitHub instance, and this Action. + [apiDetails.url, codeQLActionRepository], + // This GitHub instance, and the canonical Action. + [apiDetails.url, CODEQL_DEFAULT_ACTION_REPOSITORY], + // GitHub.com, and the canonical Action. + [GITHUB_DOTCOM_URL, CODEQL_DEFAULT_ACTION_REPOSITORY] + ]; + const uniqueDownloadSources = potentialDownloadSources.filter( + (source, index, self2) => { + return !self2.slice(0, index).some((other) => (0, import_fast_deep_equal.default)(source, other)); + } + ); + const codeQLBundleName = getCodeQLBundleName(compressionMethod); + for (const downloadSource of uniqueDownloadSources) { + const [apiURL, repository] = downloadSource; + if (apiURL === GITHUB_DOTCOM_URL && repository === CODEQL_DEFAULT_ACTION_REPOSITORY) { + break; + } + const [repositoryOwner, repositoryName] = repository.split("/"); + try { + const release2 = await getApiClient().rest.repos.getReleaseByTag({ + owner: repositoryOwner, + repo: repositoryName, + tag: tagName + }); + for (const asset of release2.data.assets) { + if (asset.name === codeQLBundleName) { + logger.info( + `Found CodeQL bundle ${codeQLBundleName} in ${repository} on ${apiURL} with URL ${asset.url}.` + ); + return asset.url; + } + } + } catch (e) { + logger.info( + `Looked for CodeQL bundle ${codeQLBundleName} in ${repository} on ${apiURL} but got error ${e}.` + ); + } + } + return `https://github.com/${CODEQL_DEFAULT_ACTION_REPOSITORY}/releases/download/${tagName}/${codeQLBundleName}`; +} +function tryGetBundleVersionFromTagName(tagName, logger) { + const match = tagName.match(/^codeql-bundle-(.*)$/); + if (match === null || match.length < 2) { + logger.debug(`Could not determine bundle version from tag ${tagName}.`); + return void 0; + } + return match[1]; +} +function tryGetTagNameFromUrl(url2, logger) { + const matches = [...url2.matchAll(/\/(codeql-bundle-[^/]*)\//g)]; + if (matches.length === 0) { + logger.debug(`Could not determine tag name for URL ${url2}.`); + return void 0; + } + const match = matches[matches.length - 1]; + if (match?.length !== 2) { + logger.debug( + `Could not determine tag name for URL ${url2}. Matched ${JSON.stringify( + match + )}.` + ); + return void 0; + } + return match[1]; +} +function convertToSemVer(version, logger) { + if (!semver8.valid(version)) { + logger.debug( + `Bundle version ${version} is not in SemVer format. Will treat it as pre-release 0.0.0-${version}.` + ); + version = `0.0.0-${version}`; + } + const s = semver8.clean(version); + if (!s) { + throw new Error(`Bundle version ${version} is not in SemVer format.`); + } + return s; +} +async function findOverridingToolsInCache(humanReadableVersion, logger) { + const candidates = toolcache3.findAllVersions("CodeQL").filter(isGoodVersion).map((version) => ({ + folder: toolcache3.find("CodeQL", version), + version + })).filter(({ folder }) => fs10.existsSync(path10.join(folder, "pinned-version"))); + if (candidates.length === 1) { + const candidate = candidates[0]; + logger.debug( + `CodeQL tools version ${candidate.version} in toolcache overriding version ${humanReadableVersion}.` + ); + return { + codeqlFolder: candidate.folder, + sourceType: "toolcache", + toolsVersion: candidate.version + }; + } else if (candidates.length === 0) { + logger.debug( + "Did not find any candidate pinned versions of the CodeQL tools in the toolcache." + ); + } else { + logger.debug( + "Could not use CodeQL tools from the toolcache since more than one candidate pinned version was found in the toolcache." + ); + } + return void 0; +} +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); + if (compressionMethod2 === void 0) { + throw new ConfigurationError( + `Could not infer compression method from path ${toolsInput}. Please specify a path ending in '.tar.gz' or '.tar.zst'.` + ); + } + return { + codeqlTarPath: toolsInput, + compressionMethod: compressionMethod2, + sourceType: "local", + toolsVersion: "local" + }; + } + let cliVersion2; + let tagName; + let url2; + const canForceNightlyWithFF = isDynamicWorkflow() || isInTestMode(); + const forceNightlyValueFF = await features.getValue("force_nightly" /* ForceNightly */); + const forceNightly = forceNightlyValueFF && canForceNightlyWithFF; + const nightlyRequestedByToolsInput = toolsInput !== void 0 && CODEQL_NIGHTLY_TOOLS_INPUTS.includes(toolsInput); + if (forceNightly || nightlyRequestedByToolsInput) { + if (forceNightly) { + logger.info( + `Using the latest CodeQL CLI nightly, as forced by the ${"force_nightly" /* ForceNightly */} feature flag.` + ); + addNoLanguageDiagnostic( + void 0, + makeDiagnostic( + "codeql-action/forced-nightly-cli", + "A nightly release of CodeQL was used", + { + markdownMessage: "GitHub configured this analysis to use a nightly release of CodeQL to allow you to preview changes from an upcoming release.\n\nNightly releases do not undergo the same validation as regular releases and may lead to analysis instability.\n\nIf use of a nightly CodeQL release for this analysis is unexpected, please contact GitHub support.", + visibility: { + cliSummaryTable: true, + statusPage: true, + telemetry: true + }, + severity: "note" + } + ) + ); + } else { + logger.info( + `Using the latest CodeQL CLI nightly, as requested by 'tools: ${toolsInput}'.` + ); + } + toolsInput = await getNightlyToolsUrl(logger); + } + const forceShippedTools = toolsInput && CODEQL_BUNDLE_VERSION_ALIAS.includes(toolsInput); + if (forceShippedTools) { + cliVersion2 = cliVersion; + tagName = bundleVersion; + logger.info( + `'tools: ${toolsInput}' was requested, so using CodeQL version ${cliVersion2}, the version shipped with the Action.` + ); + if (toolsInput === "latest") { + logger.warning( + "`tools: latest` has been renamed to `tools: linked`, but the old name is still supported. No action is required." + ); + } + } else if (toolsInput !== void 0 && toolsInput === CODEQL_TOOLCACHE_INPUT) { + let latestToolcacheVersion; + 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}'.` + ); + latestToolcacheVersion = getLatestToolcacheVersion(logger); + if (latestToolcacheVersion) { + cliVersion2 = latestToolcacheVersion; + } + } + if (latestToolcacheVersion === void 0) { + if (allowToolcacheValue) { + logger.info( + `Found no CodeQL CLI in the toolcache, ignoring 'tools: ${toolsInput}'...` + ); + } else { + if (allowToolcacheValueFF) { + logger.warning( + `Ignoring 'tools: ${toolsInput}' because the workflow was not triggered dynamically.` + ); + } else { + logger.info( + `Ignoring 'tools: ${toolsInput}' because the feature is not enabled.` + ); + } + } + cliVersion2 = defaultCliVersion.cliVersion; + tagName = defaultCliVersion.tagName; + } + } else if (toolsInput !== void 0) { + tagName = tryGetTagNameFromUrl(toolsInput, logger); + url2 = toolsInput; + if (tagName) { + const bundleVersion3 = tryGetBundleVersionFromTagName(tagName, logger); + if (bundleVersion3 && semver8.valid(bundleVersion3)) { + cliVersion2 = convertToSemVer(bundleVersion3, logger); + } + } + } else { + cliVersion2 = defaultCliVersion.cliVersion; + tagName = defaultCliVersion.tagName; + } + const bundleVersion2 = tagName && tryGetBundleVersionFromTagName(tagName, logger); + const humanReadableVersion = cliVersion2 ?? (bundleVersion2 && convertToSemVer(bundleVersion2, logger)) ?? tagName ?? url2 ?? "unknown"; + logger.debug( + `Attempting to obtain CodeQL tools. CLI version: ${cliVersion2 ?? "unknown"}, bundle tag name: ${tagName ?? "unknown"}, URL: ${url2 ?? "unspecified"}.` + ); + let codeqlFolder; + if (cliVersion2) { + codeqlFolder = toolcache3.find("CodeQL", cliVersion2); + if (!codeqlFolder) { + logger.debug( + `Didn't find a version of the CodeQL tools in the toolcache with a version number exactly matching ${cliVersion2}.` + ); + const allVersions = toolcache3.findAllVersions("CodeQL"); + logger.debug( + `Found the following versions of the CodeQL tools in the toolcache: ${JSON.stringify( + allVersions + )}.` + ); + const candidateVersions = allVersions.filter( + (version) => version.startsWith(`${cliVersion2}-`) + ); + if (candidateVersions.length === 1) { + logger.debug( + `Exactly one version of the CodeQL tools starting with ${cliVersion2} found in the toolcache, using that.` + ); + codeqlFolder = toolcache3.find("CodeQL", candidateVersions[0]); + } else if (candidateVersions.length === 0) { + logger.debug( + `Didn't find any versions of the CodeQL tools starting with ${cliVersion2} in the toolcache. Trying next fallback method.` + ); + } else { + logger.warning( + `Found ${candidateVersions.length} versions of the CodeQL tools starting with ${cliVersion2} in the toolcache, but at most one was expected.` + ); + logger.debug("Trying next fallback method."); + } + } + } + if (!codeqlFolder && tagName) { + const fallbackVersion = await tryGetFallbackToolcacheVersion( + cliVersion2, + tagName, + logger + ); + if (fallbackVersion) { + codeqlFolder = toolcache3.find("CodeQL", fallbackVersion); + } else { + logger.debug( + `Could not determine a fallback toolcache version number for CodeQL tools version ${humanReadableVersion}.` + ); + } + } + if (codeqlFolder) { + logger.info( + `Found CodeQL tools version ${humanReadableVersion} in the toolcache.` + ); + } else { + logger.info( + `Did not find CodeQL tools version ${humanReadableVersion} in the toolcache.` + ); + } + if (codeqlFolder) { + if (cliVersion2) { + logger.info( + `Using CodeQL CLI version ${cliVersion2} from toolcache at ${codeqlFolder}` + ); + } else { + logger.info(`Using CodeQL CLI from toolcache at ${codeqlFolder}`); + } + return { + codeqlFolder, + sourceType: "toolcache", + toolsVersion: cliVersion2 ?? humanReadableVersion + }; + } + if (variant === "GitHub Enterprise Server" /* GHES */ && !forceShippedTools && !toolsInput) { + const result = await findOverridingToolsInCache( + humanReadableVersion, + logger + ); + if (result !== void 0) { + return result; + } + } + let compressionMethod; + if (!url2) { + compressionMethod = cliVersion2 !== void 0 && await useZstdBundle(cliVersion2, tarSupportsZstd) ? "zstd" : "gzip"; + url2 = await getCodeQLBundleDownloadURL( + tagName, + apiDetails, + compressionMethod, + logger + ); + } else { + const method = inferCompressionMethod(url2); + if (method === void 0) { + throw new ConfigurationError( + `Could not infer compression method from URL ${url2}. Please specify a URL ending in '.tar.gz' or '.tar.zst'.` + ); + } + compressionMethod = method; + } + if (cliVersion2) { + logger.info(`Using CodeQL CLI version ${cliVersion2} sourced from ${url2} .`); + } else { + logger.info(`Using CodeQL CLI sourced from ${url2} .`); + } + return { + bundleVersion: tagName && tryGetBundleVersionFromTagName(tagName, logger), + cliVersion: cliVersion2, + codeqlURL: url2, + compressionMethod, + sourceType: "download", + toolsVersion: cliVersion2 ?? humanReadableVersion + }; +} +async function tryGetFallbackToolcacheVersion(cliVersion2, tagName, logger) { + const bundleVersion2 = tryGetBundleVersionFromTagName(tagName, logger); + if (!bundleVersion2) { + return void 0; + } + const fallbackVersion = convertToSemVer(bundleVersion2, logger); + logger.debug( + `Computed a fallback toolcache version number of ${fallbackVersion} for CodeQL version ${cliVersion2 ?? tagName}.` + ); + return fallbackVersion; +} +var downloadCodeQL = async function(codeqlURL, compressionMethod, maybeBundleVersion, maybeCliVersion, apiDetails, tarVersion, tempDir, logger) { + const parsedCodeQLURL = new URL(codeqlURL); + const searchParams = new URLSearchParams(parsedCodeQLURL.search); + const headers = { + accept: "application/octet-stream" + }; + let authorization = void 0; + if (searchParams.has("token")) { + logger.debug("CodeQL tools URL contains an authorization token."); + } else { + authorization = getAuthorizationHeaderFor( + logger, + apiDetails, + codeqlURL + ); + } + const toolcacheInfo = getToolcacheDestinationInfo( + maybeBundleVersion, + maybeCliVersion, + logger + ); + const extractedBundlePath = toolcacheInfo?.path ?? getTempExtractionDir(tempDir); + const statusReport = await downloadAndExtract( + codeqlURL, + compressionMethod, + extractedBundlePath, + authorization, + { "User-Agent": "CodeQL Action", ...headers }, + tarVersion, + logger + ); + if (!toolcacheInfo) { + logger.debug( + `Could not cache CodeQL tools because we could not determine the bundle version from the URL ${codeqlURL}.` + ); + return { + codeqlFolder: extractedBundlePath, + statusReport, + toolsVersion: maybeCliVersion ?? "unknown" + }; + } + writeToolcacheMarkerFile(toolcacheInfo.path, logger); + return { + codeqlFolder: extractedBundlePath, + statusReport, + toolsVersion: maybeCliVersion ?? toolcacheInfo.version + }; +}; +function getToolcacheDestinationInfo(maybeBundleVersion, maybeCliVersion, logger) { + if (maybeBundleVersion) { + const version = getCanonicalToolcacheVersion( + maybeCliVersion, + maybeBundleVersion, + logger + ); + return { + path: getToolcacheDirectory(version), + version + }; + } + return void 0; +} +function getCanonicalToolcacheVersion(cliVersion2, bundleVersion2, logger) { + if (!cliVersion2?.match(/^[0-9]+\.[0-9]+\.[0-9]+$/)) { + return convertToSemVer(bundleVersion2, logger); + } + return cliVersion2; +} +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." + ); + } + const zstdAvailability = await isZstdAvailable(logger); + const source = await getCodeQLSource( + toolsInput, + defaultCliVersion, + apiDetails, + variant, + zstdAvailability.available, + features, + logger + ); + let codeqlFolder; + let toolsVersion = source.toolsVersion; + let toolsDownloadStatusReport; + let toolsSource; + switch (source.sourceType) { + case "local": { + codeqlFolder = await extract( + source.codeqlTarPath, + getTempExtractionDir(tempDir), + source.compressionMethod, + zstdAvailability.version, + logger + ); + toolsSource = "LOCAL" /* Local */; + break; + } + case "toolcache": + codeqlFolder = source.codeqlFolder; + logger.debug(`CodeQL found in cache ${codeqlFolder}`); + toolsSource = "TOOLCACHE" /* Toolcache */; + break; + case "download": { + const result = await downloadCodeQL( + source.codeqlURL, + source.compressionMethod, + source.bundleVersion, + source.cliVersion, + apiDetails, + zstdAvailability.version, + tempDir, + logger + ); + toolsVersion = result.toolsVersion; + codeqlFolder = result.codeqlFolder; + toolsDownloadStatusReport = result.statusReport; + toolsSource = "DOWNLOAD" /* Download */; + break; + } + default: + assertNever(source); + } + return { + codeqlFolder, + toolsDownloadStatusReport, + toolsSource, + toolsVersion, + zstdAvailability + }; +} +async function useZstdBundle(cliVersion2, tarSupportsZstd) { + return ( + // In testing, gzip performs better than zstd on Windows. + process.platform !== "win32" && tarSupportsZstd && semver8.gte(cliVersion2, CODEQL_VERSION_ZSTD_BUNDLE) + ); +} +function getTempExtractionDir(tempDir) { + return path10.join(tempDir, v4_default()); +} +async function getNightlyToolsUrl(logger) { + const zstdAvailability = await isZstdAvailable(logger); + const compressionMethod = await useZstdBundle( + CODEQL_VERSION_ZSTD_BUNDLE, + zstdAvailability.available + ) ? "zstd" : "gzip"; + try { + const release2 = await getApiClient().rest.repos.listReleases({ + owner: CODEQL_NIGHTLIES_REPOSITORY_OWNER, + repo: CODEQL_NIGHTLIES_REPOSITORY_NAME, + per_page: 1, + page: 1, + prerelease: true + }); + const latestRelease = release2.data[0]; + if (!latestRelease) { + throw new Error("Could not find the latest nightly release."); + } + return `https://github.com/${CODEQL_NIGHTLIES_REPOSITORY_OWNER}/${CODEQL_NIGHTLIES_REPOSITORY_NAME}/releases/download/${latestRelease.tag_name}/${getCodeQLBundleName(compressionMethod)}`; + } catch (e) { + throw new Error( + `Failed to retrieve the latest nightly release: ${wrapError(e)}` + ); + } +} +function getLatestToolcacheVersion(logger) { + const allVersions = toolcache3.findAllVersions("CodeQL").sort((a, b) => semver8.compare(b, a)); + logger.debug( + `Found the following versions of the CodeQL tools in the toolcache: ${JSON.stringify( + allVersions + )}.` + ); + if (allVersions.length > 0) { + const latestToolcacheVersion = allVersions[0]; + logger.info( + `CLI version ${latestToolcacheVersion} is the latest version in the toolcache.` + ); + return latestToolcacheVersion; + } + return void 0; +} +function isReservedToolsValue(tools) { + return CODEQL_BUNDLE_VERSION_ALIAS.includes(tools) || CODEQL_NIGHTLY_TOOLS_INPUTS.includes(tools) || tools === CODEQL_TOOLCACHE_INPUT; +} + +// src/tracer-config.ts +async function shouldEnableIndirectTracing(codeql, config) { + if (config.buildMode === "none" /* None */) { + return false; + } + if (config.buildMode === "autobuild" /* Autobuild */) { + return false; + } + return asyncSome(config.languages, (l) => codeql.isTracedLanguage(l)); +} + +// src/codeql.ts +var cachedCodeQL = void 0; +var CODEQL_MINIMUM_VERSION = "2.17.6"; +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++"; +var CODEQL_VERSION_CACHE_CLEANUP = "2.17.1"; +async function setupCodeQL(toolsInput, apiDetails, tempDir, variant, defaultCliVersion, features, logger, checkVersion) { + try { + const { + codeqlFolder, + toolsDownloadStatusReport, + toolsSource, + toolsVersion, + zstdAvailability + } = await setupCodeQLBundle( + toolsInput, + apiDetails, + tempDir, + variant, + defaultCliVersion, + features, + logger + ); + logger.debug( + `Bundle download status report: ${JSON.stringify( + toolsDownloadStatusReport + )}` + ); + let codeqlCmd = path11.join(codeqlFolder, "codeql", "codeql"); + if (process.platform === "win32") { + codeqlCmd += ".exe"; + } else if (process.platform !== "linux" && process.platform !== "darwin") { + throw new ConfigurationError( + `Unsupported platform: ${process.platform}` + ); + } + cachedCodeQL = await getCodeQLForCmd(codeqlCmd, checkVersion); + return { + codeql: cachedCodeQL, + toolsDownloadStatusReport, + toolsSource, + toolsVersion, + zstdAvailability + }; + } catch (rawError) { + const e = wrapApiConfigurationError(rawError); + const ErrorClass = e instanceof ConfigurationError || e instanceof Error && e.message.includes("ENOSPC") ? ConfigurationError : Error; + throw new ErrorClass( + `Unable to download and extract CodeQL CLI: ${getErrorMessage(e)}${e instanceof Error && e.stack ? ` + +Details: ${e.stack}` : ""}` + ); + } +} +async function getCodeQL(cmd) { + if (cachedCodeQL === void 0) { + cachedCodeQL = await getCodeQLForCmd(cmd, true); + } + return cachedCodeQL; +} +async function getCodeQLForCmd(cmd, checkVersion) { + const codeql = { + getPath() { + return cmd; + }, + async getVersion() { + let result = getCachedCodeQlVersion(); + if (result === void 0) { + const output = await runCli(cmd, ["version", "--format=json"], { + noStreamStdout: true + }); + try { + result = JSON.parse(output); + } catch { + throw Error( + `Invalid JSON output from \`version --format=json\`: ${output}` + ); + } + cacheCodeQlVersion(result); + } + return result; + }, + async printVersion() { + await runCli(cmd, ["version", "--format=json"]); + }, + async supportsFeature(feature) { + return isSupportedToolsFeature(await this.getVersion(), feature); + }, + async isTracedLanguage(language) { + const extractorPath = await this.resolveExtractor(language); + const tracingConfigPath = path11.join( + extractorPath, + "tools", + "tracing-config.lua" + ); + return fs11.existsSync(tracingConfigPath); + }, + async isScannedLanguage(language) { + return !await this.isTracedLanguage(language); + }, + async databaseInitCluster(config, sourceRoot, processName, qlconfigFile, logger) { + const extraArgs = config.languages.map( + (language) => `--language=${language}` + ); + if (await shouldEnableIndirectTracing(codeql, config)) { + extraArgs.push("--begin-tracing"); + extraArgs.push(...await getTrapCachingExtractorConfigArgs(config)); + extraArgs.push(`--trace-process-name=${processName}`); + } + const codeScanningConfigFile = await writeCodeScanningConfigFile( + config, + logger + ); + const externalRepositoryToken = getOptionalInput( + "external-repository-token" + ); + extraArgs.push(`--codescanning-config=${codeScanningConfigFile}`); + if (externalRepositoryToken) { + extraArgs.push("--external-repository-token-stdin"); + } + if (config.buildMode !== void 0) { + extraArgs.push(`--build-mode=${config.buildMode}`); + } + if (qlconfigFile !== void 0) { + extraArgs.push(`--qlconfig-file=${qlconfigFile}`); + } + const overwriteFlag = isSupportedToolsFeature( + await this.getVersion(), + "forceOverwrite" /* ForceOverwrite */ + ) ? "--force-overwrite" : "--overwrite"; + const overlayDatabaseMode = config.overlayDatabaseMode; + if (overlayDatabaseMode === "overlay" /* Overlay */) { + const overlayChangesFile = await writeOverlayChangesFile( + config, + sourceRoot, + logger + ); + extraArgs.push(`--overlay-changes=${overlayChangesFile}`); + } else if (overlayDatabaseMode === "overlay-base" /* OverlayBase */) { + extraArgs.push("--overlay-base"); + } + const baselineFilesOptions = config.enableFileCoverageInformation ? [ + "--calculate-language-specific-baseline", + "--sublanguage-file-coverage" + ] : ["--no-calculate-baseline"]; + await runCli( + cmd, + [ + "database", + "init", + ...overlayDatabaseMode === "overlay" /* Overlay */ ? [] : [overwriteFlag], + "--db-cluster", + config.dbLocation, + `--source-root=${sourceRoot}`, + ...baselineFilesOptions, + "--extractor-include-aliases", + ...extraArgs, + ...getExtraOptionsFromEnv(["database", "init"], { + // Some user configs specify `--no-calculate-baseline` as an additional + // argument to `codeql database init`. Therefore ignore the baseline file + // options here to avoid specifying the same argument twice and erroring. + ignoringOptions: ["--overwrite", ...baselineFilesOptions] + }) + ], + { stdin: externalRepositoryToken } + ); + if (overlayDatabaseMode === "overlay-base" /* OverlayBase */) { + await writeBaseDatabaseOidsFile(config, sourceRoot); + } + }, + async runAutobuild(config, language) { + applyAutobuildAzurePipelinesTimeoutFix(); + const autobuildCmd = path11.join( + await this.resolveExtractor(language), + "tools", + process.platform === "win32" ? "autobuild.cmd" : "autobuild.sh" + ); + if (config.debugMode) { + process.env["CODEQL_VERBOSITY" /* CLI_VERBOSITY */] = process.env["CODEQL_VERBOSITY" /* CLI_VERBOSITY */] || EXTRACTION_DEBUG_MODE_VERBOSITY; + } + await runCli(autobuildCmd); + }, + async extractScannedLanguage(config, language) { + await runCli(cmd, [ + "database", + "trace-command", + "--index-traceless-dbs", + ...await getTrapCachingExtractorConfigArgsForLang(config, language), + ...getExtractionVerbosityArguments(config.debugMode), + ...getExtraOptionsFromEnv(["database", "trace-command"]), + getCodeQLDatabasePath(config, language) + ]); + }, + async extractUsingBuildMode(config, language) { + if (config.buildMode === "autobuild" /* Autobuild */) { + applyAutobuildAzurePipelinesTimeoutFix(); + } + try { + await runCli(cmd, [ + "database", + "trace-command", + "--use-build-mode", + "--working-dir", + process.cwd(), + ...await getTrapCachingExtractorConfigArgsForLang(config, language), + ...getExtractionVerbosityArguments(config.debugMode), + ...getExtraOptionsFromEnv(["database", "trace-command"]), + getCodeQLDatabasePath(config, language) + ]); + } catch (e) { + if (config.buildMode === "autobuild" /* Autobuild */) { + const prefix = `We were unable to automatically build your code. Please change the build mode for this language to manual and specify build steps for your project. See ${"https://docs.github.com/en/code-security/code-scanning/troubleshooting-code-scanning/automatic-build-failed" /* AUTOMATIC_BUILD_FAILED */} for more information.`; + throw new ConfigurationError(`${prefix} ${getErrorMessage(e)}`); + } else { + throw e; + } + } + }, + async finalizeDatabase(databasePath, threadsFlag, memoryFlag, enableDebugLogging) { + const args = [ + "database", + "finalize", + "--finalize-dataset", + threadsFlag, + memoryFlag, + ...getExtractionVerbosityArguments(enableDebugLogging), + ...getExtraOptionsFromEnv(["database", "finalize"]), + databasePath + ]; + await runCli(cmd, args); + }, + async resolveLanguages() { + const codeqlArgs = [ + "resolve", + "languages", + "--format=json", + ...getExtraOptionsFromEnv(["resolve", "languages"]) + ]; + const output = await runCli(cmd, codeqlArgs); + try { + return JSON.parse(output); + } catch (e) { + throw new Error( + `Unexpected output from codeql resolve languages: ${e}` + ); + } + }, + async betterResolveLanguages({ + filterToLanguagesWithQueries + } = { filterToLanguagesWithQueries: false }) { + const codeqlArgs = [ + "resolve", + "languages", + "--format=betterjson", + "--extractor-options-verbosity=4", + "--extractor-include-aliases", + ...filterToLanguagesWithQueries ? ["--filter-to-languages-with-queries"] : [], + ...getExtraOptionsFromEnv(["resolve", "languages"]) + ]; + const output = await runCli(cmd, codeqlArgs); + try { + return JSON.parse(output); + } catch (e) { + throw new Error( + `Unexpected output from codeql resolve languages with --format=betterjson: ${e}` + ); + } + }, + async resolveBuildEnvironment(workingDir, language) { + const codeqlArgs = [ + "resolve", + "build-environment", + `--language=${language}`, + "--extractor-include-aliases", + ...getExtraOptionsFromEnv(["resolve", "build-environment"]) + ]; + if (workingDir !== void 0) { + codeqlArgs.push("--working-dir", workingDir); + } + const output = await runCli(cmd, codeqlArgs); + try { + return JSON.parse(output); + } catch (e) { + throw new Error( + `Unexpected output from codeql resolve build-environment: ${e} in +${output}` + ); + } + }, + async databaseRunQueries(databasePath, flags, queries = []) { + const codeqlArgs = [ + "database", + "run-queries", + ...flags, + databasePath, + "--min-disk-free=1024", + // Try to leave at least 1GB free + "-v", + ...queries, + ...getExtraOptionsFromEnv(["database", "run-queries"], { + ignoringOptions: ["--expect-discarded-cache"] + }) + ]; + await runCli(cmd, codeqlArgs); + }, + async databaseInterpretResults(databasePath, querySuitePaths, sarifFile, threadsFlag, verbosityFlag, sarifRunPropertyFlag, automationDetailsId, config, features) { + const shouldExportDiagnostics = await features.getValue( + "export_diagnostics_enabled" /* ExportDiagnosticsEnabled */, + this + ); + const codeqlArgs = [ + "database", + "interpret-results", + threadsFlag, + "--format=sarif-latest", + verbosityFlag, + `--output=${sarifFile}`, + "--print-diagnostics-summary", + "--print-metrics-summary", + "--sarif-add-baseline-file-info", + `--sarif-codescanning-config=${getGeneratedCodeScanningConfigPath( + config + )}`, + "--sarif-group-rules-by-pack", + "--sarif-include-query-help=always", + "--sublanguage-file-coverage", + ...await getJobRunUuidSarifOptions(this), + ...getExtraOptionsFromEnv(["database", "interpret-results"]) + ]; + if (sarifRunPropertyFlag !== void 0) { + codeqlArgs.push(sarifRunPropertyFlag); + } + if (automationDetailsId !== void 0) { + codeqlArgs.push("--sarif-category", automationDetailsId); + } + if (shouldExportDiagnostics) { + codeqlArgs.push("--sarif-include-diagnostics"); + } else { + codeqlArgs.push("--no-sarif-include-diagnostics"); + } + codeqlArgs.push(databasePath); + if (querySuitePaths) { + codeqlArgs.push(...querySuitePaths); + } + return await runCli(cmd, codeqlArgs, { + noStreamStdout: true + }); + }, + async databaseCleanupCluster(config, cleanupLevel) { + const cacheCleanupFlag = await codeQlVersionAtLeast( + this, + CODEQL_VERSION_CACHE_CLEANUP + ) ? "--cache-cleanup" : "--mode"; + for (const language of config.languages) { + const databasePath = getCodeQLDatabasePath(config, language); + const codeqlArgs = [ + "database", + "cleanup", + databasePath, + `${cacheCleanupFlag}=${cleanupLevel}`, + ...getExtraOptionsFromEnv(["database", "cleanup"]) + ]; + await runCli(cmd, codeqlArgs); + } + }, + async databaseBundle(databasePath, outputFilePath, databaseName, includeDiagnostics, alsoIncludeRelativePaths) { + const includeDiagnosticsArgs = includeDiagnostics ? ["--include-diagnostics"] : []; + const args = [ + "database", + "bundle", + databasePath, + `--output=${outputFilePath}`, + `--name=${databaseName}`, + ...includeDiagnosticsArgs, + ...getExtraOptionsFromEnv(["database", "bundle"], { + ignoringOptions: includeDiagnosticsArgs + }) + ]; + if (await this.supportsFeature("bundleSupportsIncludeOption" /* BundleSupportsIncludeOption */)) { + args.push( + ...alsoIncludeRelativePaths.flatMap((relativePath) => [ + "--include", + relativePath + ]) + ); + } + await new toolrunner3.ToolRunner(cmd, args).exec(); + }, + async databaseExportDiagnostics(databasePath, sarifFile, automationDetailsId) { + const args = [ + "database", + "export-diagnostics", + `${databasePath}`, + "--db-cluster", + // Database is always a cluster for CodeQL versions that support diagnostics. + "--format=sarif-latest", + `--output=${sarifFile}`, + "--sarif-include-diagnostics", + // ExportDiagnosticsEnabled is always true if this command is run. + "-vvv", + ...getExtraOptionsFromEnv(["diagnostics", "export"]) + ]; + if (automationDetailsId !== void 0) { + args.push("--sarif-category", automationDetailsId); + } + await new toolrunner3.ToolRunner(cmd, args).exec(); + }, + async diagnosticsExport(sarifFile, automationDetailsId, config) { + const args = [ + "diagnostics", + "export", + "--format=sarif-latest", + `--output=${sarifFile}`, + `--sarif-codescanning-config=${getGeneratedCodeScanningConfigPath( + config + )}`, + ...getExtraOptionsFromEnv(["diagnostics", "export"]) + ]; + if (automationDetailsId !== void 0) { + args.push("--sarif-category", automationDetailsId); + } + await new toolrunner3.ToolRunner(cmd, args).exec(); + }, + async resolveExtractor(language) { + let extractorPath = ""; + await new toolrunner3.ToolRunner( + cmd, + [ + "resolve", + "extractor", + "--format=json", + `--language=${language}`, + "--extractor-include-aliases", + ...getExtraOptionsFromEnv(["resolve", "extractor"]) + ], + { + silent: true, + listeners: { + stdout: (data) => { + extractorPath += data.toString(); + }, + stderr: (data) => { + process.stderr.write(data); + } + } + } + ).exec(); + return JSON.parse(extractorPath); + }, + async resolveQueriesStartingPacks(queries) { + const codeqlArgs = [ + "resolve", + "queries", + "--format=startingpacks", + ...getExtraOptionsFromEnv(["resolve", "queries"]), + ...queries + ]; + const output = await runCli(cmd, codeqlArgs, { noStreamStdout: true }); + try { + return JSON.parse(output); + } catch (e) { + throw new Error( + `Unexpected output from codeql resolve queries --format=startingpacks: ${e}` + ); + } + }, + async resolveDatabase(databasePath) { + const codeqlArgs = [ + "resolve", + "database", + databasePath, + "--format=json", + ...getExtraOptionsFromEnv(["resolve", "database"]) + ]; + const output = await runCli(cmd, codeqlArgs, { noStreamStdout: true }); + try { + return JSON.parse(output); + } catch (e) { + throw new Error( + `Unexpected output from codeql resolve database --format=json: ${e}` + ); + } + }, + async mergeResults(sarifFiles, outputFile, { + mergeRunsFromEqualCategory = false + }) { + const args = [ + "github", + "merge-results", + "--output", + outputFile, + ...getExtraOptionsFromEnv(["github", "merge-results"]) + ]; + for (const sarifFile of sarifFiles) { + args.push("--sarif", sarifFile); + } + if (mergeRunsFromEqualCategory) { + args.push("--sarif-merge-runs-from-equal-category"); + } + await runCli(cmd, args); + } + }; + if (checkVersion && !await codeQlVersionAtLeast(codeql, CODEQL_MINIMUM_VERSION)) { + throw new ConfigurationError( + `Expected a CodeQL CLI with version at least ${CODEQL_MINIMUM_VERSION} but got version ${(await codeql.getVersion()).version}` + ); + } else if (checkVersion && process.env["CODEQL_ACTION_SUPPRESS_DEPRECATED_SOON_WARNING" /* SUPPRESS_DEPRECATED_SOON_WARNING */] !== "true" && !await codeQlVersionAtLeast(codeql, CODEQL_NEXT_MINIMUM_VERSION)) { + const result = await codeql.getVersion(); + core11.warning( + `CodeQL CLI version ${result.version} was discontinued on ${GHES_MOST_RECENT_DEPRECATION_DATE} alongside GitHub Enterprise Server ${GHES_VERSION_MOST_RECENTLY_DEPRECATED} and will not be supported by the next minor release of the CodeQL Action. Please update to CodeQL CLI version ${CODEQL_NEXT_MINIMUM_VERSION} or later. For instance, if you have specified a custom version of the CLI using the 'tools' input to the 'init' Action, you can remove this input to use the default version. + +Alternatively, if you want to continue using CodeQL CLI version ${result.version}, you can replace 'github/codeql-action/*@v${getActionVersion().split(".")[0]}' by 'github/codeql-action/*@v${getActionVersion()}' in your code scanning workflow to continue using this version of the CodeQL Action.` + ); + core11.exportVariable("CODEQL_ACTION_SUPPRESS_DEPRECATED_SOON_WARNING" /* SUPPRESS_DEPRECATED_SOON_WARNING */, "true"); + } + return codeql; +} +function getExtraOptionsFromEnv(paths, { ignoringOptions } = {}) { + const options = getExtraOptionsEnvParam(); + return getExtraOptions(options, paths, []).filter( + (option) => !ignoringOptions?.includes(option) + ); +} +function asExtraOptions(options, pathInfo) { + if (options === void 0) { + return []; + } + if (!Array.isArray(options)) { + const msg = `The extra options for '${pathInfo.join( + "." + )}' ('${JSON.stringify(options)}') are not in an array.`; + throw new Error(msg); + } + return options.map((o) => { + const t = typeof o; + if (t !== "string" && t !== "number" && t !== "boolean") { + const msg = `The extra option for '${pathInfo.join( + "." + )}' ('${JSON.stringify(o)}') is not a primitive value.`; + throw new Error(msg); + } + return `${o}`; + }); +} +function getExtraOptions(options, paths, pathInfo) { + const all = asExtraOptions(options?.["*"], pathInfo.concat("*")); + const specific = paths.length === 0 ? asExtraOptions(options, pathInfo) : getExtraOptions( + options?.[paths[0]], + paths?.slice(1), + pathInfo.concat(paths[0]) + ); + return all.concat(specific); +} +async function runCli(cmd, args = [], opts = {}) { + try { + return await runTool(cmd, args, opts); + } catch (e) { + if (e instanceof CommandInvocationError) { + throw wrapCliConfigurationError(new CliError(e)); + } + throw e; + } +} +async function writeCodeScanningConfigFile(config, logger) { + const codeScanningConfigFile = getGeneratedCodeScanningConfigPath(config); + const augmentedConfig = appendExtraQueryExclusions( + config.extraQueryExclusions, + config.computedConfig + ); + logger.info( + `Writing augmented user configuration file to ${codeScanningConfigFile}` + ); + logger.startGroup("Augmented user configuration file contents"); + logger.info(dump(augmentedConfig)); + logger.endGroup(); + fs11.writeFileSync(codeScanningConfigFile, dump(augmentedConfig)); + return codeScanningConfigFile; +} +var TRAP_CACHE_SIZE_MB = 1024; +async function getTrapCachingExtractorConfigArgs(config) { + const result = []; + for (const language of config.languages) + result.push( + await getTrapCachingExtractorConfigArgsForLang(config, language) + ); + return result.flat(); +} +async function getTrapCachingExtractorConfigArgsForLang(config, language) { + const cacheDir = config.trapCaches[language]; + if (cacheDir === void 0) return []; + const write = await isAnalyzingDefaultBranch(); + return [ + `-O=${language}.trap.cache.dir=${cacheDir}`, + `-O=${language}.trap.cache.bound=${TRAP_CACHE_SIZE_MB}`, + `-O=${language}.trap.cache.write=${write}` + ]; +} +function getGeneratedCodeScanningConfigPath(config) { + return path11.resolve(config.tempDir, "user-config.yaml"); +} +function getExtractionVerbosityArguments(enableDebugLogging) { + return enableDebugLogging ? [`--verbosity=${EXTRACTION_DEBUG_MODE_VERBOSITY}`] : []; +} +function applyAutobuildAzurePipelinesTimeoutFix() { + const javaToolOptions = process.env["JAVA_TOOL_OPTIONS"] || ""; + process.env["JAVA_TOOL_OPTIONS"] = [ + ...javaToolOptions.split(/\s+/), + "-Dhttp.keepAlive=false", + "-Dmaven.wagon.http.pool=false" + ].join(" "); +} +async function getJobRunUuidSarifOptions(codeql) { + const jobRunUuid = process.env["JOB_RUN_UUID" /* JOB_RUN_UUID */]; + return jobRunUuid && await codeql.supportsFeature( + "databaseInterpretResultsSupportsSarifRunProperty" /* DatabaseInterpretResultsSupportsSarifRunProperty */ + ) ? [`--sarif-run-property=jobRunUuid=${jobRunUuid}`] : []; +} + +// src/init.ts async function initCodeQL(toolsInput, apiDetails, tempDir, variant, defaultCliVersion, features, logger) { logger.startGroup("Setup CodeQL tools"); const { - codeql: codeql2, + codeql, toolsDownloadStatusReport, toolsSource, toolsVersion, @@ -110732,10 +110734,10 @@ async function initCodeQL(toolsInput, apiDetails, tempDir, variant, defaultCliVe logger, true ); - await codeql2.printVersion(); + await codeql.printVersion(); logger.endGroup(); return { - codeql: codeql2, + codeql, toolsDownloadStatusReport, toolsSource, toolsVersion, @@ -111368,6 +111370,20 @@ function filterAlertsByDiffRange(logger, sarif) { } // src/upload-sarif.ts +var cachedCodeQL2; +async function getOrInitCodeQL(logger, gitHubVersion, features, config) { + if (cachedCodeQL2 !== void 0) return cachedCodeQL2; + if (config !== void 0) { + cachedCodeQL2 = await getCodeQL(config.codeQLCmd); + } else { + cachedCodeQL2 = await minimalInitCodeQL( + logger, + gitHubVersion, + features + ); + } + return cachedCodeQL2; +} async function postProcessAndUploadSarif(logger, tempPath, features, getCodeQL2, uploadKind, checkoutPath, sarifPath, category, postProcessedOutputPath) { const sarifGroups = await getGroupedSarifFilePaths( logger, @@ -111424,20 +111440,6 @@ async function sendSuccessStatusReport(startedAt, uploadStats, logger) { await sendStatusReport(statusReport); } } -var codeql; -async function getOrInitCodeQL(logger, gitHubVersion, features, config) { - if (codeql !== void 0) return codeql; - if (config !== void 0) { - codeql = await getCodeQL(config.codeQLCmd); - } else { - codeql = await minimalInitCodeQL( - logger, - gitHubVersion, - features - ); - } - return codeql; -} async function run(startedAt) { const logger = getActionsLogger(); try { diff --git a/src/upload-sarif-action.ts b/src/upload-sarif-action.ts index 737396dd6..4cc4bfc49 100644 --- a/src/upload-sarif-action.ts +++ b/src/upload-sarif-action.ts @@ -3,9 +3,8 @@ import * as core from "@actions/core"; import * as actionsUtil from "./actions-util"; import * as analyses from "./analyses"; import { getGitHubVersion } from "./api-client"; -import { CodeQL, getCodeQL } from "./codeql"; -import { Config, getConfig } from "./config-utils"; -import { FeatureEnablement, initFeatures } from "./feature-flags"; +import { getConfig } from "./config-utils"; +import { initFeatures } from "./feature-flags"; import { Logger, getActionsLogger } from "./logging"; import { getRepositoryNwo } from "./repository"; import { @@ -18,10 +17,9 @@ import { isThirdPartyAnalysis, } from "./status-report"; import * as upload_lib from "./upload-lib"; -import { postProcessAndUploadSarif } from "./upload-sarif"; +import { getOrInitCodeQL, postProcessAndUploadSarif } from "./upload-sarif"; import { ConfigurationError, - GitHubVersion, checkActionVersion, checkDiskUsage, getErrorMessage, @@ -56,35 +54,6 @@ async function sendSuccessStatusReport( } } -/** The cached `CodeQL` instance, if any. */ -let codeql: CodeQL | undefined; - -/** Get or initialise a `CodeQL` instance for use by the `upload-sarif` action. */ -async function getOrInitCodeQL( - logger: Logger, - gitHubVersion: GitHubVersion, - features: FeatureEnablement, - config: Config | undefined, -): Promise { - // Return the cached instance, if we have one. - if (codeql !== undefined) return codeql; - - // If we have been able to load a `Config` from an earlier CodeQL Action step in the job, - // then use the CodeQL executable that we have used previously. Otherwise, initialise the - // CLI specifically for `upload-sarif`. Either way, we cache the instance. - if (config !== undefined) { - codeql = await getCodeQL(config.codeQLCmd); - } else { - codeql = await upload_lib.minimalInitCodeQL( - logger, - gitHubVersion, - features, - ); - } - - return codeql; -} - async function run(startedAt: Date) { // To capture errors appropriately, keep as much code within the try-catch as // possible, and only use safe functions outside. diff --git a/src/upload-sarif.ts b/src/upload-sarif.ts index 372b2d1f4..f704c2c28 100644 --- a/src/upload-sarif.ts +++ b/src/upload-sarif.ts @@ -1,15 +1,47 @@ import { UploadKind } from "./actions-util"; import * as analyses from "./analyses"; +import type { CodeQL } from "./codeql"; +import * as codeql from "./codeql"; +import { Config } from "./config-utils"; import { FeatureEnablement } from "./feature-flags"; import { Logger } from "./logging"; import * as upload_lib from "./upload-lib"; -import { unsafeEntriesInvariant } from "./util"; +import { GitHubVersion, unsafeEntriesInvariant } from "./util"; // Maps analysis kinds to SARIF IDs. export type UploadSarifResults = Partial< Record >; +/** The cached `CodeQL` instance, if any. */ +let cachedCodeQL: CodeQL | undefined; + +/** Get or initialise a `CodeQL` instance for use by the `upload-sarif` action. */ +export async function getOrInitCodeQL( + logger: Logger, + gitHubVersion: GitHubVersion, + features: FeatureEnablement, + config: Config | undefined, +): Promise { + // Return the cached instance, if we have one. + if (cachedCodeQL !== undefined) return cachedCodeQL; + + // If we have been able to load a `Config` from an earlier CodeQL Action step in the job, + // then use the CodeQL executable that we have used previously. Otherwise, initialise the + // CLI specifically for `upload-sarif`. Either way, we cache the instance. + if (config !== undefined) { + cachedCodeQL = await codeql.getCodeQL(config.codeQLCmd); + } else { + cachedCodeQL = await upload_lib.minimalInitCodeQL( + logger, + gitHubVersion, + features, + ); + } + + return cachedCodeQL; +} + /** * Finds SARIF files in `sarifPath`, post-processes them, and uploads them to the appropriate services. *