From c3dc529aef20e50d2567365bf3bec42ca2e5a3d9 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 16 Dec 2025 17:19:46 +0000 Subject: [PATCH] Address feedback: cache git version, improve error handling, add telemetry - Cache the git version to avoid recomputing on repeated calls - Refactor getGitVersion to getGitVersionOrThrow with detailed errors - Add getGitVersion that logs errors and handles caching - Add makeTelemetryDiagnostic helper to diagnostics.ts - Add logGitVersionTelemetry function to log git version telemetry - Call logGitVersionTelemetry in init-action.ts - Add resetCachedGitVersion for testing - Update tests to work with new function signatures and caching Co-authored-by: henrymercer <14129055+henrymercer@users.noreply.github.com> --- lib/analyze-action-post.js | 54 ++--- lib/analyze-action.js | 226 ++++++++++----------- lib/autobuild-action.js | 38 ++-- lib/init-action-post.js | 76 +++---- lib/init-action.js | 321 +++++++++++++++++------------- lib/resolve-environment-action.js | 38 ++-- lib/setup-codeql-action.js | 60 +++--- lib/start-proxy-action-post.js | 18 +- lib/upload-lib.js | 38 ++-- lib/upload-sarif-action-post.js | 22 +- lib/upload-sarif-action.js | 60 +++--- src/diagnostics.ts | 25 +++ src/git-utils.test.ts | 94 ++++++++- src/git-utils.ts | 100 ++++++++-- src/init-action.ts | 4 + 15 files changed, 694 insertions(+), 480 deletions(-) diff --git a/lib/analyze-action-post.js b/lib/analyze-action-post.js index bd4457726..d5d6a1646 100644 --- a/lib/analyze-action-post.js +++ b/lib/analyze-action-post.js @@ -119759,14 +119759,38 @@ var path2 = __toESM(require("path")); var actionsCache = __toESM(require_cache3()); // src/git-utils.ts -var core7 = __toESM(require_core()); +var core8 = __toESM(require_core()); var toolrunner2 = __toESM(require_toolrunner()); var io3 = __toESM(require_io2()); var semver3 = __toESM(require_semver2()); + +// src/logging.ts +var core7 = __toESM(require_core()); +function getActionsLogger() { + return { + debug: core7.debug, + info: core7.info, + warning: core7.warning, + error: core7.error, + isDebug: core7.isDebug, + startGroup: core7.startGroup, + endGroup: core7.endGroup + }; +} +function withGroup(groupName, f) { + core7.startGroup(groupName); + try { + return f(); + } finally { + core7.endGroup(); + } +} + +// src/git-utils.ts var runGitCommand = async function(workingDirectory, args, customErrorMessage) { let stdout = ""; let stderr = ""; - core7.debug(`Running git command: git ${args.join(" ")}`); + core8.debug(`Running git command: git ${args.join(" ")}`); try { await new toolrunner2.ToolRunner(await io3.which("git", true), args, { silent: true, @@ -119786,7 +119810,7 @@ var runGitCommand = async function(workingDirectory, args, customErrorMessage) { if (stderr.includes("not a git repository")) { reason = "The checkout path provided to the action does not appear to be a git repository."; } - core7.info(`git call failed. ${customErrorMessage} Error: ${reason}`); + core8.info(`git call failed. ${customErrorMessage} Error: ${reason}`); throw error3; } }; @@ -119897,7 +119921,7 @@ async function getRef() { ) !== head; if (hasChangedRef) { const newRef = ref.replace(pull_ref_regex, "refs/pull/$1/head"); - core7.debug( + core8.debug( `No longer on merge commit, rewriting ref from ${ref} to ${newRef}.` ); return newRef; @@ -119922,28 +119946,6 @@ async function isAnalyzingDefaultBranch() { return currentRef === defaultBranch; } -// src/logging.ts -var core8 = __toESM(require_core()); -function getActionsLogger() { - return { - debug: core8.debug, - info: core8.info, - warning: core8.warning, - error: core8.error, - isDebug: core8.isDebug, - startGroup: core8.startGroup, - endGroup: core8.endGroup - }; -} -function withGroup(groupName, f) { - core8.startGroup(groupName); - try { - return f(); - } finally { - core8.endGroup(); - } -} - // src/overlay-database-utils.ts var CODEQL_OVERLAY_MINIMUM_VERSION = "2.23.5"; var OVERLAY_BASE_DATABASE_MAX_UPLOAD_SIZE_MB = 7500; diff --git a/lib/analyze-action.js b/lib/analyze-action.js index 6b3a31099..fc58fc76c 100644 --- a/lib/analyze-action.js +++ b/lib/analyze-action.js @@ -87925,7 +87925,7 @@ function wrapApiConfigurationError(e) { // src/codeql.ts var fs11 = __toESM(require("fs")); -var path10 = __toESM(require("path")); +var path11 = __toESM(require("path")); var core10 = __toESM(require_core()); var toolrunner3 = __toESM(require_toolrunner()); @@ -88171,7 +88171,7 @@ function wrapCliConfigurationError(cliError) { // src/config-utils.ts var fs6 = __toESM(require("fs")); -var path6 = __toESM(require("path")); +var path7 = __toESM(require("path")); // src/caching-utils.ts var crypto = __toESM(require("crypto")); @@ -88203,11 +88203,11 @@ var PACK_IDENTIFIER_PATTERN = (function() { // src/diff-informed-analysis-utils.ts var fs5 = __toESM(require("fs")); -var path5 = __toESM(require("path")); +var path6 = __toESM(require("path")); // src/feature-flags.ts var fs4 = __toESM(require("fs")); -var path4 = __toESM(require("path")); +var path5 = __toESM(require("path")); var semver5 = __toESM(require_semver2()); // src/defaults.json @@ -88216,18 +88216,100 @@ var cliVersion = "2.23.8"; // src/overlay-database-utils.ts var fs3 = __toESM(require("fs")); -var path3 = __toESM(require("path")); +var path4 = __toESM(require("path")); var actionsCache = __toESM(require_cache3()); // src/git-utils.ts -var core7 = __toESM(require_core()); +var core8 = __toESM(require_core()); var toolrunner2 = __toESM(require_toolrunner()); var io3 = __toESM(require_io2()); var semver3 = __toESM(require_semver2()); + +// src/diagnostics.ts +var import_fs = require("fs"); +var import_path = __toESM(require("path")); + +// src/logging.ts +var core7 = __toESM(require_core()); +function getActionsLogger() { + return { + debug: core7.debug, + info: core7.info, + warning: core7.warning, + error: core7.error, + isDebug: core7.isDebug, + startGroup: core7.startGroup, + endGroup: core7.endGroup + }; +} +async function withGroupAsync(groupName, f) { + core7.startGroup(groupName); + try { + return await f(); + } finally { + core7.endGroup(); + } +} +function formatDuration(durationMs) { + if (durationMs < 1e3) { + return `${durationMs}ms`; + } + if (durationMs < 60 * 1e3) { + return `${(durationMs / 1e3).toFixed(1)}s`; + } + const minutes = Math.floor(durationMs / (60 * 1e3)); + const seconds = Math.floor(durationMs % (60 * 1e3) / 1e3); + return `${minutes}m${seconds}s`; +} + +// src/diagnostics.ts +var unwrittenDiagnostics = []; +function makeDiagnostic(id, name, data = void 0) { + return { + ...data, + timestamp: data?.timestamp ?? (/* @__PURE__ */ new Date()).toISOString(), + source: { ...data?.source, id, name } + }; +} +function addDiagnostic(config, language, diagnostic) { + const logger = getActionsLogger(); + const databasePath = language ? getCodeQLDatabasePath(config, language) : config.dbLocation; + if ((0, import_fs.existsSync)(databasePath)) { + writeDiagnostic(config, language, diagnostic); + } else { + logger.debug( + `Writing a diagnostic for ${language}, but the database at ${databasePath} does not exist yet.` + ); + unwrittenDiagnostics.push({ diagnostic, language }); + } +} +function writeDiagnostic(config, language, diagnostic) { + const logger = getActionsLogger(); + const databasePath = language ? getCodeQLDatabasePath(config, language) : config.dbLocation; + const diagnosticsPath = import_path.default.resolve( + databasePath, + "diagnostic", + "codeql-action" + ); + try { + (0, import_fs.mkdirSync)(diagnosticsPath, { recursive: true }); + const jsonPath = import_path.default.resolve( + diagnosticsPath, + // Remove colons from the timestamp as these are not allowed in Windows filenames. + `codeql-action-${diagnostic.timestamp.replaceAll(":", "")}.json` + ); + (0, import_fs.writeFileSync)(jsonPath, JSON.stringify(diagnostic)); + } catch (err) { + logger.warning(`Unable to write diagnostic message to database: ${err}`); + logger.debug(JSON.stringify(diagnostic)); + } +} + +// src/git-utils.ts var runGitCommand = async function(workingDirectory, args, customErrorMessage) { let stdout = ""; let stderr = ""; - core7.debug(`Running git command: git ${args.join(" ")}`); + core8.debug(`Running git command: git ${args.join(" ")}`); try { await new toolrunner2.ToolRunner(await io3.which("git", true), args, { silent: true, @@ -88247,7 +88329,7 @@ var runGitCommand = async function(workingDirectory, args, customErrorMessage) { if (stderr.includes("not a git repository")) { reason = "The checkout path provided to the action does not appear to be a git repository."; } - core7.info(`git call failed. ${customErrorMessage} Error: ${reason}`); + core8.info(`git call failed. ${customErrorMessage} Error: ${reason}`); throw error3; } }; @@ -88392,7 +88474,7 @@ async function getRef() { ) !== head; if (hasChangedRef) { const newRef = ref.replace(pull_ref_regex, "refs/pull/$1/head"); - core7.debug( + core8.debug( `No longer on merge commit, rewriting ref from ${ref} to ${newRef}.` ); return newRef; @@ -88417,39 +88499,6 @@ async function isAnalyzingDefaultBranch() { return currentRef === defaultBranch; } -// src/logging.ts -var core8 = __toESM(require_core()); -function getActionsLogger() { - return { - debug: core8.debug, - info: core8.info, - warning: core8.warning, - error: core8.error, - isDebug: core8.isDebug, - startGroup: core8.startGroup, - endGroup: core8.endGroup - }; -} -async function withGroupAsync(groupName, f) { - core8.startGroup(groupName); - try { - return await f(); - } finally { - core8.endGroup(); - } -} -function formatDuration(durationMs) { - if (durationMs < 1e3) { - return `${durationMs}ms`; - } - if (durationMs < 60 * 1e3) { - return `${(durationMs / 1e3).toFixed(1)}s`; - } - const minutes = Math.floor(durationMs / (60 * 1e3)); - const seconds = Math.floor(durationMs % (60 * 1e3) / 1e3); - return `${minutes}m${seconds}s`; -} - // src/overlay-database-utils.ts var CODEQL_OVERLAY_MINIMUM_VERSION = "2.23.5"; var OVERLAY_BASE_DATABASE_MAX_UPLOAD_SIZE_MB = 7500; @@ -88476,7 +88525,7 @@ async function readBaseDatabaseOidsFile(config, logger) { } } function getBaseDatabaseOidsFilePath(config) { - return path3.join(config.dbLocation, "base-database-oids.json"); + return path4.join(config.dbLocation, "base-database-oids.json"); } async function writeOverlayChangesFile(config, sourceRoot, logger) { const baseFileOids = await readBaseDatabaseOidsFile(config, logger); @@ -88486,7 +88535,7 @@ async function writeOverlayChangesFile(config, sourceRoot, logger) { `Found ${changedFiles.length} changed file(s) under ${sourceRoot}.` ); const changedFilesJson = JSON.stringify({ changes: changedFiles }); - const overlayChangesFile = path3.join( + const overlayChangesFile = path4.join( getTemporaryDirectory(), "overlay-changes.json" ); @@ -88861,7 +88910,7 @@ var Features = class { this.gitHubFeatureFlags = new GitHubFeatureFlags( gitHubVersion, repositoryNwo, - path4.join(tempDir, FEATURE_FLAGS_FILE_NAME), + path5.join(tempDir, FEATURE_FLAGS_FILE_NAME), logger ); } @@ -89141,7 +89190,7 @@ async function getDiffInformedAnalysisBranches(codeql, features, logger) { return branches; } function getDiffRangesJsonFilePath() { - return path5.join(getTemporaryDirectory(), "pr-diff-range.json"); + return path6.join(getTemporaryDirectory(), "pr-diff-range.json"); } function writeDiffRangesJsonFile(logger, ranges) { const jsonContents = JSON.stringify(ranges, null, 2); @@ -89221,7 +89270,7 @@ Error Response: ${JSON.stringify(error3.response, null, 2)}` } } function getDiffRanges(fileDiff, logger) { - const filename = path5.join(getRequiredInput("checkout_path"), fileDiff.filename).replaceAll(path5.sep, "/"); + const filename = path6.join(getRequiredInput("checkout_path"), fileDiff.filename).replaceAll(path6.sep, "/"); if (fileDiff.patch === void 0) { if (fileDiff.changes === 0) { return []; @@ -89428,7 +89477,7 @@ var OVERLAY_ANALYSIS_CODE_SCANNING_FEATURES = { swift: "overlay_analysis_code_scanning_swift" /* OverlayAnalysisCodeScanningSwift */ }; function getPathToParsedConfigFile(tempDir) { - return path6.join(tempDir, "config"); + return path7.join(tempDir, "config"); } async function getConfig(tempDir, logger) { const configFile = getPathToParsedConfigFile(tempDir); @@ -89484,7 +89533,7 @@ function getPrimaryAnalysisConfig(config) { // src/setup-codeql.ts var fs9 = __toESM(require("fs")); -var path8 = __toESM(require("path")); +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()); @@ -89704,7 +89753,7 @@ function inferCompressionMethod(tarPath) { // src/tools-download.ts var fs8 = __toESM(require("fs")); var os2 = __toESM(require("os")); -var path7 = __toESM(require("path")); +var path8 = __toESM(require("path")); var import_perf_hooks = require("perf_hooks"); var core9 = __toESM(require_core()); var import_http_client = __toESM(require_lib6()); @@ -89837,7 +89886,7 @@ async function downloadAndExtractZstdWithStreaming(codeqlURL, dest, authorizatio await extractTarZst(response, dest, tarVersion, logger); } function getToolcacheDirectory(version) { - return path7.join( + return path8.join( getRequiredEnvParam("RUNNER_TOOL_CACHE"), TOOLCACHE_TOOL_NAME, semver7.clean(version) || version, @@ -89981,7 +90030,7 @@ async function findOverridingToolsInCache(humanReadableVersion, logger) { const candidates = toolcache3.findAllVersions("CodeQL").filter(isGoodVersion).map((version) => ({ folder: toolcache3.find("CodeQL", version), version - })).filter(({ folder }) => fs9.existsSync(path8.join(folder, "pinned-version"))); + })).filter(({ folder }) => fs9.existsSync(path9.join(folder, "pinned-version"))); if (candidates.length === 1) { const candidate = candidates[0]; logger.debug( @@ -90354,7 +90403,7 @@ async function useZstdBundle(cliVersion2, tarSupportsZstd) { ); } function getTempExtractionDir(tempDir) { - return path8.join(tempDir, v4_default()); + return path9.join(tempDir, v4_default()); } async function getNightlyToolsUrl(logger) { const zstdAvailability = await isZstdAvailable(logger); @@ -90403,7 +90452,7 @@ function isReservedToolsValue(tools) { // src/tracer-config.ts var fs10 = __toESM(require("fs")); -var path9 = __toESM(require("path")); +var path10 = __toESM(require("path")); async function shouldEnableIndirectTracing(codeql, config) { if (config.buildMode === "none" /* None */) { return false; @@ -90418,7 +90467,7 @@ async function endTracingForCluster(codeql, config, logger) { logger.info( "Unsetting build tracing environment variables. Subsequent steps of this job will not be traced." ); - const envVariablesFile = path9.resolve( + const envVariablesFile = path10.resolve( config.dbLocation, "temp/tracingEnvironment/end-tracing.json" ); @@ -90475,7 +90524,7 @@ async function setupCodeQL(toolsInput, apiDetails, tempDir, variant, defaultCliV toolsDownloadStatusReport )}` ); - let codeqlCmd = path10.join(codeqlFolder, "codeql", "codeql"); + let codeqlCmd = path11.join(codeqlFolder, "codeql", "codeql"); if (process.platform === "win32") { codeqlCmd += ".exe"; } else if (process.platform !== "linux" && process.platform !== "darwin") { @@ -90537,7 +90586,7 @@ async function getCodeQLForCmd(cmd, checkVersion) { }, async isTracedLanguage(language) { const extractorPath = await this.resolveExtractor(language); - const tracingConfigPath = path10.join( + const tracingConfigPath = path11.join( extractorPath, "tools", "tracing-config.lua" @@ -90613,7 +90662,7 @@ async function getCodeQLForCmd(cmd, checkVersion) { }, async runAutobuild(config, language) { applyAutobuildAzurePipelinesTimeoutFix(); - const autobuildCmd = path10.join( + const autobuildCmd = path11.join( await this.resolveExtractor(language), "tools", process.platform === "win32" ? "autobuild.cmd" : "autobuild.sh" @@ -91036,7 +91085,7 @@ async function getTrapCachingExtractorConfigArgsForLang(config, language) { ]; } function getGeneratedCodeScanningConfigPath(config) { - return path10.resolve(config.tempDir, "user-config.yaml"); + return path11.resolve(config.tempDir, "user-config.yaml"); } function getExtractionVerbosityArguments(enableDebugLogging) { return enableDebugLogging ? [`--verbosity=${EXTRACTION_DEBUG_MODE_VERBOSITY}`] : []; @@ -91104,31 +91153,31 @@ async function runAutobuild(config, language, logger) { // src/dependency-caching.ts var os3 = __toESM(require("os")); -var import_path = require("path"); +var import_path2 = require("path"); var actionsCache3 = __toESM(require_cache3()); var glob = __toESM(require_glob2()); var CODEQL_DEPENDENCY_CACHE_PREFIX = "codeql-dependencies"; var CODEQL_DEPENDENCY_CACHE_VERSION = 1; function getJavaTempDependencyDir() { - return (0, import_path.join)(getTemporaryDirectory(), "codeql_java", "repository"); + return (0, import_path2.join)(getTemporaryDirectory(), "codeql_java", "repository"); } async function getJavaDependencyDirs() { return [ // Maven - (0, import_path.join)(os3.homedir(), ".m2", "repository"), + (0, import_path2.join)(os3.homedir(), ".m2", "repository"), // Gradle - (0, import_path.join)(os3.homedir(), ".gradle", "caches"), + (0, import_path2.join)(os3.homedir(), ".gradle", "caches"), // CodeQL Java build-mode: none getJavaTempDependencyDir() ]; } function getCsharpTempDependencyDir() { - return (0, import_path.join)(getTemporaryDirectory(), "codeql_csharp", "repository"); + return (0, import_path2.join)(getTemporaryDirectory(), "codeql_csharp", "repository"); } async function getCsharpDependencyDirs(codeql, features) { const dirs = [ // Nuget - (0, import_path.join)(os3.homedir(), ".nuget", "packages") + (0, import_path2.join)(os3.homedir(), ".nuget", "packages") ]; if (await features.getValue("csharp_cache_bmn" /* CsharpCacheBuildModeNone */, codeql)) { dirs.push(getCsharpTempDependencyDir()); @@ -91183,7 +91232,7 @@ var defaultCacheConfigs = { getHashPatterns: getCsharpHashPatterns }, go: { - getDependencyPaths: async () => [(0, import_path.join)(os3.homedir(), "go", "pkg", "mod")], + getDependencyPaths: async () => [(0, import_path2.join)(os3.homedir(), "go", "pkg", "mod")], getHashPatterns: async () => internal.makePatternCheck(["**/go.sum"]) } }; @@ -91314,51 +91363,6 @@ var internal = { makePatternCheck }; -// src/diagnostics.ts -var import_fs = require("fs"); -var import_path2 = __toESM(require("path")); -var unwrittenDiagnostics = []; -function makeDiagnostic(id, name, data = void 0) { - return { - ...data, - timestamp: data?.timestamp ?? (/* @__PURE__ */ new Date()).toISOString(), - source: { ...data?.source, id, name } - }; -} -function addDiagnostic(config, language, diagnostic) { - const logger = getActionsLogger(); - const databasePath = language ? getCodeQLDatabasePath(config, language) : config.dbLocation; - if ((0, import_fs.existsSync)(databasePath)) { - writeDiagnostic(config, language, diagnostic); - } else { - logger.debug( - `Writing a diagnostic for ${language}, but the database at ${databasePath} does not exist yet.` - ); - unwrittenDiagnostics.push({ diagnostic, language }); - } -} -function writeDiagnostic(config, language, diagnostic) { - const logger = getActionsLogger(); - const databasePath = language ? getCodeQLDatabasePath(config, language) : config.dbLocation; - const diagnosticsPath = import_path2.default.resolve( - databasePath, - "diagnostic", - "codeql-action" - ); - try { - (0, import_fs.mkdirSync)(diagnosticsPath, { recursive: true }); - const jsonPath = import_path2.default.resolve( - diagnosticsPath, - // Remove colons from the timestamp as these are not allowed in Windows filenames. - `codeql-action-${diagnostic.timestamp.replaceAll(":", "")}.json` - ); - (0, import_fs.writeFileSync)(jsonPath, JSON.stringify(diagnostic)); - } catch (err) { - logger.warning(`Unable to write diagnostic message to database: ${err}`); - logger.debug(JSON.stringify(diagnostic)); - } -} - // src/analyze.ts var CodeQLAnalysisError = class extends Error { constructor(queriesStatusReport, message, error3) { diff --git a/lib/autobuild-action.js b/lib/autobuild-action.js index e396cc502..c05d97d91 100644 --- a/lib/autobuild-action.js +++ b/lib/autobuild-action.js @@ -83710,14 +83710,30 @@ var path2 = __toESM(require("path")); var actionsCache = __toESM(require_cache3()); // src/git-utils.ts -var core7 = __toESM(require_core()); +var core8 = __toESM(require_core()); var toolrunner2 = __toESM(require_toolrunner()); var io3 = __toESM(require_io2()); var semver3 = __toESM(require_semver2()); + +// src/logging.ts +var core7 = __toESM(require_core()); +function getActionsLogger() { + return { + debug: core7.debug, + info: core7.info, + warning: core7.warning, + error: core7.error, + isDebug: core7.isDebug, + startGroup: core7.startGroup, + endGroup: core7.endGroup + }; +} + +// src/git-utils.ts var runGitCommand = async function(workingDirectory, args, customErrorMessage) { let stdout = ""; let stderr = ""; - core7.debug(`Running git command: git ${args.join(" ")}`); + core8.debug(`Running git command: git ${args.join(" ")}`); try { await new toolrunner2.ToolRunner(await io3.which("git", true), args, { silent: true, @@ -83737,7 +83753,7 @@ var runGitCommand = async function(workingDirectory, args, customErrorMessage) { if (stderr.includes("not a git repository")) { reason = "The checkout path provided to the action does not appear to be a git repository."; } - core7.info(`git call failed. ${customErrorMessage} Error: ${reason}`); + core8.info(`git call failed. ${customErrorMessage} Error: ${reason}`); throw error3; } }; @@ -83848,7 +83864,7 @@ async function getRef() { ) !== head; if (hasChangedRef) { const newRef = ref.replace(pull_ref_regex, "refs/pull/$1/head"); - core7.debug( + core8.debug( `No longer on merge commit, rewriting ref from ${ref} to ${newRef}.` ); return newRef; @@ -83873,20 +83889,6 @@ async function isAnalyzingDefaultBranch() { return currentRef === defaultBranch; } -// src/logging.ts -var core8 = __toESM(require_core()); -function getActionsLogger() { - return { - debug: core8.debug, - info: core8.info, - warning: core8.warning, - error: core8.error, - isDebug: core8.isDebug, - startGroup: core8.startGroup, - endGroup: core8.endGroup - }; -} - // src/overlay-database-utils.ts var CODEQL_OVERLAY_MINIMUM_VERSION = "2.23.5"; var OVERLAY_BASE_DATABASE_MAX_UPLOAD_SIZE_MB = 7500; diff --git a/lib/init-action-post.js b/lib/init-action-post.js index 5c1a89c35..91687091f 100644 --- a/lib/init-action-post.js +++ b/lib/init-action-post.js @@ -123092,14 +123092,49 @@ var path3 = __toESM(require("path")); var actionsCache = __toESM(require_cache3()); // src/git-utils.ts -var core7 = __toESM(require_core()); +var core8 = __toESM(require_core()); var toolrunner2 = __toESM(require_toolrunner()); var io3 = __toESM(require_io2()); var semver3 = __toESM(require_semver2()); + +// src/logging.ts +var core7 = __toESM(require_core()); +function getActionsLogger() { + return { + debug: core7.debug, + info: core7.info, + warning: core7.warning, + error: core7.error, + isDebug: core7.isDebug, + startGroup: core7.startGroup, + endGroup: core7.endGroup + }; +} +function withGroup(groupName, f) { + core7.startGroup(groupName); + try { + return f(); + } finally { + core7.endGroup(); + } +} +function formatDuration(durationMs) { + if (durationMs < 1e3) { + return `${durationMs}ms`; + } + if (durationMs < 60 * 1e3) { + return `${(durationMs / 1e3).toFixed(1)}s`; + } + const minutes = Math.floor(durationMs / (60 * 1e3)); + const seconds = Math.floor(durationMs % (60 * 1e3) / 1e3); + return `${minutes}m${seconds}s`; +} + +// src/git-utils.ts var runGitCommand = async function(workingDirectory, args, customErrorMessage) { let stdout = ""; let stderr = ""; - core7.debug(`Running git command: git ${args.join(" ")}`); + core8.debug(`Running git command: git ${args.join(" ")}`); try { await new toolrunner2.ToolRunner(await io3.which("git", true), args, { silent: true, @@ -123119,7 +123154,7 @@ var runGitCommand = async function(workingDirectory, args, customErrorMessage) { if (stderr.includes("not a git repository")) { reason = "The checkout path provided to the action does not appear to be a git repository."; } - core7.info(`git call failed. ${customErrorMessage} Error: ${reason}`); + core8.info(`git call failed. ${customErrorMessage} Error: ${reason}`); throw error3; } }; @@ -123264,7 +123299,7 @@ async function getRef() { ) !== head; if (hasChangedRef) { const newRef = ref.replace(pull_ref_regex, "refs/pull/$1/head"); - core7.debug( + core8.debug( `No longer on merge commit, rewriting ref from ${ref} to ${newRef}.` ); return newRef; @@ -123289,39 +123324,6 @@ async function isAnalyzingDefaultBranch() { return currentRef === defaultBranch; } -// src/logging.ts -var core8 = __toESM(require_core()); -function getActionsLogger() { - return { - debug: core8.debug, - info: core8.info, - warning: core8.warning, - error: core8.error, - isDebug: core8.isDebug, - startGroup: core8.startGroup, - endGroup: core8.endGroup - }; -} -function withGroup(groupName, f) { - core8.startGroup(groupName); - try { - return f(); - } finally { - core8.endGroup(); - } -} -function formatDuration(durationMs) { - if (durationMs < 1e3) { - return `${durationMs}ms`; - } - if (durationMs < 60 * 1e3) { - return `${(durationMs / 1e3).toFixed(1)}s`; - } - const minutes = Math.floor(durationMs / (60 * 1e3)); - const seconds = Math.floor(durationMs % (60 * 1e3) / 1e3); - return `${minutes}m${seconds}s`; -} - // src/overlay-database-utils.ts var CODEQL_OVERLAY_MINIMUM_VERSION = "2.23.5"; var OVERLAY_BASE_DATABASE_MAX_UPLOAD_SIZE_MB = 7500; diff --git a/lib/init-action.js b/lib/init-action.js index 3bd87b605..b814dd154 100644 --- a/lib/init-action.js +++ b/lib/init-action.js @@ -85283,7 +85283,7 @@ function getDependencyCachingEnabled() { // src/config-utils.ts var fs6 = __toESM(require("fs")); -var path7 = __toESM(require("path")); +var path8 = __toESM(require("path")); var import_perf_hooks = require("perf_hooks"); // src/config/db-config.ts @@ -85631,7 +85631,7 @@ function parseUserConfig(logger, pathInput, contents, validateConfig) { // src/feature-flags.ts var fs4 = __toESM(require("fs")); -var path5 = __toESM(require("path")); +var path6 = __toESM(require("path")); var semver5 = __toESM(require_semver2()); // src/defaults.json @@ -85640,35 +85640,171 @@ var cliVersion = "2.23.8"; // src/overlay-database-utils.ts var fs3 = __toESM(require("fs")); -var path4 = __toESM(require("path")); +var path5 = __toESM(require("path")); var actionsCache = __toESM(require_cache3()); // src/git-utils.ts -var core7 = __toESM(require_core()); +var core8 = __toESM(require_core()); var toolrunner2 = __toESM(require_toolrunner()); var io3 = __toESM(require_io2()); var semver3 = __toESM(require_semver2()); -var GIT_MINIMUM_VERSION_FOR_OVERLAY = "2.38.0"; -async function getGitVersion() { + +// src/diagnostics.ts +var import_fs = require("fs"); +var import_path = __toESM(require("path")); + +// src/logging.ts +var core7 = __toESM(require_core()); +function getActionsLogger() { + return { + debug: core7.debug, + info: core7.info, + warning: core7.warning, + error: core7.error, + isDebug: core7.isDebug, + startGroup: core7.startGroup, + endGroup: core7.endGroup + }; +} +async function withGroupAsync(groupName, f) { + core7.startGroup(groupName); try { - const stdout = await runGitCommand( - void 0, - ["--version"], - "Failed to get git version." + return await f(); + } finally { + core7.endGroup(); + } +} +function formatDuration(durationMs) { + if (durationMs < 1e3) { + return `${durationMs}ms`; + } + if (durationMs < 60 * 1e3) { + return `${(durationMs / 1e3).toFixed(1)}s`; + } + const minutes = Math.floor(durationMs / (60 * 1e3)); + const seconds = Math.floor(durationMs % (60 * 1e3) / 1e3); + return `${minutes}m${seconds}s`; +} + +// src/diagnostics.ts +var unwrittenDiagnostics = []; +function makeDiagnostic(id, name, data = void 0) { + return { + ...data, + timestamp: data?.timestamp ?? (/* @__PURE__ */ new Date()).toISOString(), + source: { ...data?.source, id, name } + }; +} +function addDiagnostic(config, language, diagnostic) { + const logger = getActionsLogger(); + const databasePath = language ? getCodeQLDatabasePath(config, language) : config.dbLocation; + if ((0, import_fs.existsSync)(databasePath)) { + writeDiagnostic(config, language, diagnostic); + } else { + logger.debug( + `Writing a diagnostic for ${language}, but the database at ${databasePath} does not exist yet.` ); - const match = stdout.match(/git version (\d+\.\d+\.\d+)/); - if (match?.[1]) { - return match[1]; + unwrittenDiagnostics.push({ diagnostic, language }); + } +} +function writeDiagnostic(config, language, diagnostic) { + const logger = getActionsLogger(); + const databasePath = language ? getCodeQLDatabasePath(config, language) : config.dbLocation; + const diagnosticsPath = import_path.default.resolve( + databasePath, + "diagnostic", + "codeql-action" + ); + try { + (0, import_fs.mkdirSync)(diagnosticsPath, { recursive: true }); + const jsonPath = import_path.default.resolve( + diagnosticsPath, + // Remove colons from the timestamp as these are not allowed in Windows filenames. + `codeql-action-${diagnostic.timestamp.replaceAll(":", "")}.json` + ); + (0, import_fs.writeFileSync)(jsonPath, JSON.stringify(diagnostic)); + } catch (err) { + logger.warning(`Unable to write diagnostic message to database: ${err}`); + logger.debug(JSON.stringify(diagnostic)); + } +} +function logUnwrittenDiagnostics() { + const logger = getActionsLogger(); + const num = unwrittenDiagnostics.length; + if (num > 0) { + logger.warning( + `${num} diagnostic(s) could not be written to the database and will not appear on the Tool Status Page.` + ); + for (const unwritten of unwrittenDiagnostics) { + logger.debug(JSON.stringify(unwritten.diagnostic)); } - return void 0; - } catch { + } +} +function flushDiagnostics(config) { + const logger = getActionsLogger(); + logger.debug( + `Writing ${unwrittenDiagnostics.length} diagnostic(s) to database.` + ); + for (const unwritten of unwrittenDiagnostics) { + writeDiagnostic(config, unwritten.language, unwritten.diagnostic); + } + unwrittenDiagnostics = []; +} +function makeTelemetryDiagnostic(id, name, attributes) { + return makeDiagnostic(id, name, { + attributes, + visibility: { + cliSummaryTable: false, + statusPage: false, + telemetry: true + } + }); +} + +// src/git-utils.ts +var GIT_MINIMUM_VERSION_FOR_OVERLAY = "2.38.0"; +var cachedGitVersion; +async function getGitVersionOrThrow() { + const stdout = await runGitCommand( + void 0, + ["--version"], + "Failed to get git version." + ); + const match = stdout.match(/git version (\d+\.\d+\.\d+)/); + if (match?.[1]) { + return match[1]; + } + throw new Error(`Could not parse Git version from output: ${stdout.trim()}`); +} +async function getGitVersion(logger) { + if (cachedGitVersion !== void 0) { + return cachedGitVersion; + } + try { + cachedGitVersion = await getGitVersionOrThrow(); + return cachedGitVersion; + } catch (e) { + logger.debug(`Could not determine Git version: ${getErrorMessage(e)}`); return void 0; } } +async function logGitVersionTelemetry(config, logger) { + const version = await getGitVersion(logger); + if (version !== void 0) { + addDiagnostic( + config, + config.languages[0], + makeTelemetryDiagnostic( + "codeql-action/git-version-telemetry", + "Git version telemetry", + { gitVersion: version } + ) + ); + } +} async function gitVersionAtLeast(requiredVersion, logger) { - const version = await getGitVersion(); + const version = await getGitVersion(logger); if (version === void 0) { - logger.debug("Could not determine Git version."); return false; } logger.debug(`Installed Git version is ${version}.`); @@ -85677,7 +85813,7 @@ async function gitVersionAtLeast(requiredVersion, logger) { var runGitCommand = async function(workingDirectory, args, customErrorMessage) { let stdout = ""; let stderr = ""; - core7.debug(`Running git command: git ${args.join(" ")}`); + core8.debug(`Running git command: git ${args.join(" ")}`); try { await new toolrunner2.ToolRunner(await io3.which("git", true), args, { silent: true, @@ -85697,7 +85833,7 @@ var runGitCommand = async function(workingDirectory, args, customErrorMessage) { if (stderr.includes("not a git repository")) { reason = "The checkout path provided to the action does not appear to be a git repository."; } - core7.info(`git call failed. ${customErrorMessage} Error: ${reason}`); + core8.info(`git call failed. ${customErrorMessage} Error: ${reason}`); throw error3; } }; @@ -85820,7 +85956,7 @@ async function getRef() { ) !== head; if (hasChangedRef) { const newRef = ref.replace(pull_ref_regex, "refs/pull/$1/head"); - core7.debug( + core8.debug( `No longer on merge commit, rewriting ref from ${ref} to ${newRef}.` ); return newRef; @@ -85845,39 +85981,6 @@ async function isAnalyzingDefaultBranch() { return currentRef === defaultBranch; } -// src/logging.ts -var core8 = __toESM(require_core()); -function getActionsLogger() { - return { - debug: core8.debug, - info: core8.info, - warning: core8.warning, - error: core8.error, - isDebug: core8.isDebug, - startGroup: core8.startGroup, - endGroup: core8.endGroup - }; -} -async function withGroupAsync(groupName, f) { - core8.startGroup(groupName); - try { - return await f(); - } finally { - core8.endGroup(); - } -} -function formatDuration(durationMs) { - if (durationMs < 1e3) { - return `${durationMs}ms`; - } - if (durationMs < 60 * 1e3) { - return `${(durationMs / 1e3).toFixed(1)}s`; - } - const minutes = Math.floor(durationMs / (60 * 1e3)); - const seconds = Math.floor(durationMs % (60 * 1e3) / 1e3); - return `${minutes}m${seconds}s`; -} - // src/overlay-database-utils.ts var CODEQL_OVERLAY_MINIMUM_VERSION = "2.23.5"; var OVERLAY_BASE_DATABASE_MAX_UPLOAD_SIZE_MB = 7500; @@ -85904,7 +86007,7 @@ async function readBaseDatabaseOidsFile(config, logger) { } } function getBaseDatabaseOidsFilePath(config) { - return path4.join(config.dbLocation, "base-database-oids.json"); + return path5.join(config.dbLocation, "base-database-oids.json"); } async function writeOverlayChangesFile(config, sourceRoot, logger) { const baseFileOids = await readBaseDatabaseOidsFile(config, logger); @@ -85914,7 +86017,7 @@ async function writeOverlayChangesFile(config, sourceRoot, logger) { `Found ${changedFiles.length} changed file(s) under ${sourceRoot}.` ); const changedFilesJson = JSON.stringify({ changes: changedFiles }); - const overlayChangesFile = path4.join( + const overlayChangesFile = path5.join( getTemporaryDirectory(), "overlay-changes.json" ); @@ -86301,7 +86404,7 @@ var Features = class { this.gitHubFeatureFlags = new GitHubFeatureFlags( gitHubVersion, repositoryNwo, - path5.join(tempDir, FEATURE_FLAGS_FILE_NAME), + path6.join(tempDir, FEATURE_FLAGS_FILE_NAME), logger ); } @@ -86601,7 +86704,7 @@ var KnownLanguage = /* @__PURE__ */ ((KnownLanguage2) => { // src/trap-caching.ts var fs5 = __toESM(require("fs")); -var path6 = __toESM(require("path")); +var path7 = __toESM(require("path")); var actionsCache2 = __toESM(require_cache3()); var CACHE_VERSION2 = 1; var CODEQL_TRAP_CACHE_PREFIX = "codeql-trap"; @@ -86617,12 +86720,12 @@ async function downloadTrapCaches(codeql, languages, logger) { `Found ${languagesSupportingCaching.length} languages that support TRAP caching` ); if (languagesSupportingCaching.length === 0) return result; - const cachesDir = path6.join( + const cachesDir = path7.join( getTemporaryDirectory(), "trapCaches" ); for (const language of languagesSupportingCaching) { - const cacheDir = path6.join(cachesDir, language); + const cacheDir = path7.join(cachesDir, language); fs5.mkdirSync(cacheDir, { recursive: true }); result[language] = cacheDir; } @@ -86635,7 +86738,7 @@ async function downloadTrapCaches(codeql, languages, logger) { let baseSha = "unknown"; const eventPath = process.env.GITHUB_EVENT_PATH; if (getWorkflowEventName() === "pull_request" && eventPath !== void 0) { - const event = JSON.parse(fs5.readFileSync(path6.resolve(eventPath), "utf-8")); + const event = JSON.parse(fs5.readFileSync(path7.resolve(eventPath), "utf-8")); baseSha = event.pull_request?.base?.sha || baseSha; } for (const language of languages) { @@ -86739,7 +86842,7 @@ async function getSupportedLanguageMap(codeql, logger) { } var baseWorkflowsPath = ".github/workflows"; function hasActionsWorkflows(sourceRoot) { - const workflowsPath = path7.resolve(sourceRoot, baseWorkflowsPath); + const workflowsPath = path8.resolve(sourceRoot, baseWorkflowsPath); const stats = fs6.lstatSync(workflowsPath, { throwIfNoEntry: false }); return stats !== void 0 && stats.isDirectory() && fs6.readdirSync(workflowsPath).length > 0; } @@ -86906,8 +87009,8 @@ async function downloadCacheWithTime(trapCachingEnabled, codeQL, languages, logg async function loadUserConfig(logger, configFile, workspacePath, apiDetails, tempDir, validateConfig) { if (isLocal(configFile)) { if (configFile !== userConfigFromActionPath(tempDir)) { - configFile = path7.resolve(workspacePath, configFile); - if (!(configFile + path7.sep).startsWith(workspacePath + path7.sep)) { + configFile = path8.resolve(workspacePath, configFile); + if (!(configFile + path8.sep).startsWith(workspacePath + path8.sep)) { throw new ConfigurationError( getConfigFileOutsideWorkspaceErrorMessage(configFile) ); @@ -87067,10 +87170,10 @@ async function getOverlayDatabaseMode(codeql, features, languages, sourceRoot, b }; } function dbLocationOrDefault(dbLocation, tempDir) { - return dbLocation || path7.resolve(tempDir, "codeql_databases"); + return dbLocation || path8.resolve(tempDir, "codeql_databases"); } function userConfigFromActionPath(tempDir) { - return path7.resolve(tempDir, "user-config-from-action.yml"); + return path8.resolve(tempDir, "user-config-from-action.yml"); } function hasQueryCustomisation(userConfig) { return isDefined(userConfig["disable-default-queries"]) || isDefined(userConfig.queries) || isDefined(userConfig["query-filters"]); @@ -87210,12 +87313,12 @@ async function getRemoteConfig(logger, configFile, apiDetails, validateConfig) { ); } function getPathToParsedConfigFile(tempDir) { - return path7.join(tempDir, "config"); + return path8.join(tempDir, "config"); } async function saveConfig(config, logger) { const configString = JSON.stringify(config); const configFile = getPathToParsedConfigFile(config.tempDir); - fs6.mkdirSync(path7.dirname(configFile), { recursive: true }); + fs6.mkdirSync(path8.dirname(configFile), { recursive: true }); fs6.writeFileSync(configFile, configString, "utf8"); logger.debug("Saved config:"); logger.debug(configString); @@ -87226,7 +87329,7 @@ async function generateRegistries(registriesInput, tempDir, logger) { let qlconfigFile; if (registries) { const qlconfig = createRegistriesBlock(registries); - qlconfigFile = path7.join(tempDir, "qlconfig.yml"); + qlconfigFile = path8.join(tempDir, "qlconfig.yml"); const qlconfigContents = dump(qlconfig); fs6.writeFileSync(qlconfigFile, qlconfigContents, "utf8"); logger.debug("Generated qlconfig.yml:"); @@ -87327,31 +87430,31 @@ function isCodeQualityEnabled(config) { // src/dependency-caching.ts var os2 = __toESM(require("os")); -var import_path = require("path"); +var import_path2 = require("path"); var actionsCache3 = __toESM(require_cache3()); var glob = __toESM(require_glob2()); var CODEQL_DEPENDENCY_CACHE_PREFIX = "codeql-dependencies"; var CODEQL_DEPENDENCY_CACHE_VERSION = 1; function getJavaTempDependencyDir() { - return (0, import_path.join)(getTemporaryDirectory(), "codeql_java", "repository"); + return (0, import_path2.join)(getTemporaryDirectory(), "codeql_java", "repository"); } async function getJavaDependencyDirs() { return [ // Maven - (0, import_path.join)(os2.homedir(), ".m2", "repository"), + (0, import_path2.join)(os2.homedir(), ".m2", "repository"), // Gradle - (0, import_path.join)(os2.homedir(), ".gradle", "caches"), + (0, import_path2.join)(os2.homedir(), ".gradle", "caches"), // CodeQL Java build-mode: none getJavaTempDependencyDir() ]; } function getCsharpTempDependencyDir() { - return (0, import_path.join)(getTemporaryDirectory(), "codeql_csharp", "repository"); + return (0, import_path2.join)(getTemporaryDirectory(), "codeql_csharp", "repository"); } async function getCsharpDependencyDirs(codeql, features) { const dirs = [ // Nuget - (0, import_path.join)(os2.homedir(), ".nuget", "packages") + (0, import_path2.join)(os2.homedir(), ".nuget", "packages") ]; if (await features.getValue("csharp_cache_bmn" /* CsharpCacheBuildModeNone */, codeql)) { dirs.push(getCsharpTempDependencyDir()); @@ -87406,7 +87509,7 @@ var defaultCacheConfigs = { getHashPatterns: getCsharpHashPatterns }, go: { - getDependencyPaths: async () => [(0, import_path.join)(os2.homedir(), "go", "pkg", "mod")], + getDependencyPaths: async () => [(0, import_path2.join)(os2.homedir(), "go", "pkg", "mod")], getHashPatterns: async () => internal.makePatternCheck(["**/go.sum"]) } }; @@ -87526,73 +87629,6 @@ var internal = { makePatternCheck }; -// src/diagnostics.ts -var import_fs = require("fs"); -var import_path2 = __toESM(require("path")); -var unwrittenDiagnostics = []; -function makeDiagnostic(id, name, data = void 0) { - return { - ...data, - timestamp: data?.timestamp ?? (/* @__PURE__ */ new Date()).toISOString(), - source: { ...data?.source, id, name } - }; -} -function addDiagnostic(config, language, diagnostic) { - const logger = getActionsLogger(); - const databasePath = language ? getCodeQLDatabasePath(config, language) : config.dbLocation; - if ((0, import_fs.existsSync)(databasePath)) { - writeDiagnostic(config, language, diagnostic); - } else { - logger.debug( - `Writing a diagnostic for ${language}, but the database at ${databasePath} does not exist yet.` - ); - unwrittenDiagnostics.push({ diagnostic, language }); - } -} -function writeDiagnostic(config, language, diagnostic) { - const logger = getActionsLogger(); - const databasePath = language ? getCodeQLDatabasePath(config, language) : config.dbLocation; - const diagnosticsPath = import_path2.default.resolve( - databasePath, - "diagnostic", - "codeql-action" - ); - try { - (0, import_fs.mkdirSync)(diagnosticsPath, { recursive: true }); - const jsonPath = import_path2.default.resolve( - diagnosticsPath, - // Remove colons from the timestamp as these are not allowed in Windows filenames. - `codeql-action-${diagnostic.timestamp.replaceAll(":", "")}.json` - ); - (0, import_fs.writeFileSync)(jsonPath, JSON.stringify(diagnostic)); - } catch (err) { - logger.warning(`Unable to write diagnostic message to database: ${err}`); - logger.debug(JSON.stringify(diagnostic)); - } -} -function logUnwrittenDiagnostics() { - const logger = getActionsLogger(); - const num = unwrittenDiagnostics.length; - if (num > 0) { - logger.warning( - `${num} diagnostic(s) could not be written to the database and will not appear on the Tool Status Page.` - ); - for (const unwritten of unwrittenDiagnostics) { - logger.debug(JSON.stringify(unwritten.diagnostic)); - } - } -} -function flushDiagnostics(config) { - const logger = getActionsLogger(); - logger.debug( - `Writing ${unwrittenDiagnostics.length} diagnostic(s) to database.` - ); - for (const unwritten of unwrittenDiagnostics) { - writeDiagnostic(config, unwritten.language, unwritten.diagnostic); - } - unwrittenDiagnostics = []; -} - // src/init.ts var fs12 = __toESM(require("fs")); var path13 = __toESM(require("path")); @@ -90170,6 +90206,7 @@ async function run() { ) ); } + await logGitVersionTelemetry(config, logger); const goFlags = process.env["GOFLAGS"]; if (goFlags) { core13.exportVariable("GOFLAGS", goFlags); diff --git a/lib/resolve-environment-action.js b/lib/resolve-environment-action.js index 17100c2c1..e73e3b40c 100644 --- a/lib/resolve-environment-action.js +++ b/lib/resolve-environment-action.js @@ -83703,14 +83703,30 @@ var path2 = __toESM(require("path")); var actionsCache = __toESM(require_cache3()); // src/git-utils.ts -var core7 = __toESM(require_core()); +var core8 = __toESM(require_core()); var toolrunner2 = __toESM(require_toolrunner()); var io3 = __toESM(require_io2()); var semver3 = __toESM(require_semver2()); + +// src/logging.ts +var core7 = __toESM(require_core()); +function getActionsLogger() { + return { + debug: core7.debug, + info: core7.info, + warning: core7.warning, + error: core7.error, + isDebug: core7.isDebug, + startGroup: core7.startGroup, + endGroup: core7.endGroup + }; +} + +// src/git-utils.ts var runGitCommand = async function(workingDirectory, args, customErrorMessage) { let stdout = ""; let stderr = ""; - core7.debug(`Running git command: git ${args.join(" ")}`); + core8.debug(`Running git command: git ${args.join(" ")}`); try { await new toolrunner2.ToolRunner(await io3.which("git", true), args, { silent: true, @@ -83730,7 +83746,7 @@ var runGitCommand = async function(workingDirectory, args, customErrorMessage) { if (stderr.includes("not a git repository")) { reason = "The checkout path provided to the action does not appear to be a git repository."; } - core7.info(`git call failed. ${customErrorMessage} Error: ${reason}`); + core8.info(`git call failed. ${customErrorMessage} Error: ${reason}`); throw error3; } }; @@ -83841,7 +83857,7 @@ async function getRef() { ) !== head; if (hasChangedRef) { const newRef = ref.replace(pull_ref_regex, "refs/pull/$1/head"); - core7.debug( + core8.debug( `No longer on merge commit, rewriting ref from ${ref} to ${newRef}.` ); return newRef; @@ -83866,20 +83882,6 @@ async function isAnalyzingDefaultBranch() { return currentRef === defaultBranch; } -// src/logging.ts -var core8 = __toESM(require_core()); -function getActionsLogger() { - return { - debug: core8.debug, - info: core8.info, - warning: core8.warning, - error: core8.error, - isDebug: core8.isDebug, - startGroup: core8.startGroup, - endGroup: core8.endGroup - }; -} - // src/overlay-database-utils.ts var CODEQL_OVERLAY_MINIMUM_VERSION = "2.23.5"; var OVERLAY_BASE_DATABASE_MAX_UPLOAD_SIZE_MB = 7500; diff --git a/lib/setup-codeql-action.js b/lib/setup-codeql-action.js index 6b5b9211d..edcf230c9 100644 --- a/lib/setup-codeql-action.js +++ b/lib/setup-codeql-action.js @@ -83601,14 +83601,41 @@ var actionsCache = __toESM(require_cache3()); var core6 = __toESM(require_core()); // src/git-utils.ts -var core7 = __toESM(require_core()); +var core8 = __toESM(require_core()); var toolrunner2 = __toESM(require_toolrunner()); var io3 = __toESM(require_io2()); var semver2 = __toESM(require_semver2()); + +// src/logging.ts +var core7 = __toESM(require_core()); +function getActionsLogger() { + return { + debug: core7.debug, + info: core7.info, + warning: core7.warning, + error: core7.error, + isDebug: core7.isDebug, + startGroup: core7.startGroup, + endGroup: core7.endGroup + }; +} +function formatDuration(durationMs) { + if (durationMs < 1e3) { + return `${durationMs}ms`; + } + if (durationMs < 60 * 1e3) { + return `${(durationMs / 1e3).toFixed(1)}s`; + } + const minutes = Math.floor(durationMs / (60 * 1e3)); + const seconds = Math.floor(durationMs % (60 * 1e3) / 1e3); + return `${minutes}m${seconds}s`; +} + +// src/git-utils.ts var runGitCommand = async function(workingDirectory, args, customErrorMessage) { let stdout = ""; let stderr = ""; - core7.debug(`Running git command: git ${args.join(" ")}`); + core8.debug(`Running git command: git ${args.join(" ")}`); try { await new toolrunner2.ToolRunner(await io3.which("git", true), args, { silent: true, @@ -83628,7 +83655,7 @@ var runGitCommand = async function(workingDirectory, args, customErrorMessage) { if (stderr.includes("not a git repository")) { reason = "The checkout path provided to the action does not appear to be a git repository."; } - core7.info(`git call failed. ${customErrorMessage} Error: ${reason}`); + core8.info(`git call failed. ${customErrorMessage} Error: ${reason}`); throw error3; } }; @@ -83739,7 +83766,7 @@ async function getRef() { ) !== head; if (hasChangedRef) { const newRef = ref.replace(pull_ref_regex, "refs/pull/$1/head"); - core7.debug( + core8.debug( `No longer on merge commit, rewriting ref from ${ref} to ${newRef}.` ); return newRef; @@ -83764,31 +83791,6 @@ async function isAnalyzingDefaultBranch() { return currentRef === defaultBranch; } -// src/logging.ts -var core8 = __toESM(require_core()); -function getActionsLogger() { - return { - debug: core8.debug, - info: core8.info, - warning: core8.warning, - error: core8.error, - isDebug: core8.isDebug, - startGroup: core8.startGroup, - endGroup: core8.endGroup - }; -} -function formatDuration(durationMs) { - if (durationMs < 1e3) { - return `${durationMs}ms`; - } - if (durationMs < 60 * 1e3) { - return `${(durationMs / 1e3).toFixed(1)}s`; - } - const minutes = Math.floor(durationMs / (60 * 1e3)); - const seconds = Math.floor(durationMs % (60 * 1e3) / 1e3); - return `${minutes}m${seconds}s`; -} - // src/overlay-database-utils.ts var CODEQL_OVERLAY_MINIMUM_VERSION = "2.23.5"; var OVERLAY_BASE_DATABASE_MAX_UPLOAD_SIZE_MB = 7500; diff --git a/lib/start-proxy-action-post.js b/lib/start-proxy-action-post.js index cd5e20cd5..6d56d3d1a 100644 --- a/lib/start-proxy-action-post.js +++ b/lib/start-proxy-action-post.js @@ -119394,22 +119394,22 @@ var semver5 = __toESM(require_semver2()); var actionsCache = __toESM(require_cache3()); // src/git-utils.ts -var core7 = __toESM(require_core()); +var core8 = __toESM(require_core()); var toolrunner2 = __toESM(require_toolrunner()); var io3 = __toESM(require_io2()); var semver3 = __toESM(require_semver2()); // src/logging.ts -var core8 = __toESM(require_core()); +var core7 = __toESM(require_core()); function getActionsLogger() { return { - debug: core8.debug, - info: core8.info, - warning: core8.warning, - error: core8.error, - isDebug: core8.isDebug, - startGroup: core8.startGroup, - endGroup: core8.endGroup + debug: core7.debug, + info: core7.info, + warning: core7.warning, + error: core7.error, + isDebug: core7.isDebug, + startGroup: core7.startGroup, + endGroup: core7.endGroup }; } diff --git a/lib/upload-lib.js b/lib/upload-lib.js index b9ac6bbe6..3c7135e25 100644 --- a/lib/upload-lib.js +++ b/lib/upload-lib.js @@ -86733,14 +86733,30 @@ var path3 = __toESM(require("path")); var actionsCache = __toESM(require_cache3()); // src/git-utils.ts -var core7 = __toESM(require_core()); +var core8 = __toESM(require_core()); var toolrunner2 = __toESM(require_toolrunner()); var io3 = __toESM(require_io2()); var semver3 = __toESM(require_semver2()); + +// src/logging.ts +var core7 = __toESM(require_core()); +function formatDuration(durationMs) { + if (durationMs < 1e3) { + return `${durationMs}ms`; + } + if (durationMs < 60 * 1e3) { + return `${(durationMs / 1e3).toFixed(1)}s`; + } + const minutes = Math.floor(durationMs / (60 * 1e3)); + const seconds = Math.floor(durationMs % (60 * 1e3) / 1e3); + return `${minutes}m${seconds}s`; +} + +// src/git-utils.ts var runGitCommand = async function(workingDirectory, args, customErrorMessage) { let stdout = ""; let stderr = ""; - core7.debug(`Running git command: git ${args.join(" ")}`); + core8.debug(`Running git command: git ${args.join(" ")}`); try { await new toolrunner2.ToolRunner(await io3.which("git", true), args, { silent: true, @@ -86760,7 +86776,7 @@ var runGitCommand = async function(workingDirectory, args, customErrorMessage) { if (stderr.includes("not a git repository")) { reason = "The checkout path provided to the action does not appear to be a git repository."; } - core7.info(`git call failed. ${customErrorMessage} Error: ${reason}`); + core8.info(`git call failed. ${customErrorMessage} Error: ${reason}`); throw error3; } }; @@ -86905,7 +86921,7 @@ async function getRef() { ) !== head; if (hasChangedRef) { const newRef = ref.replace(pull_ref_regex, "refs/pull/$1/head"); - core7.debug( + core8.debug( `No longer on merge commit, rewriting ref from ${ref} to ${newRef}.` ); return newRef; @@ -86930,20 +86946,6 @@ async function isAnalyzingDefaultBranch() { return currentRef === defaultBranch; } -// src/logging.ts -var core8 = __toESM(require_core()); -function formatDuration(durationMs) { - if (durationMs < 1e3) { - return `${durationMs}ms`; - } - if (durationMs < 60 * 1e3) { - return `${(durationMs / 1e3).toFixed(1)}s`; - } - const minutes = Math.floor(durationMs / (60 * 1e3)); - const seconds = Math.floor(durationMs % (60 * 1e3) / 1e3); - return `${minutes}m${seconds}s`; -} - // src/overlay-database-utils.ts var CODEQL_OVERLAY_MINIMUM_VERSION = "2.23.5"; var OVERLAY_BASE_DATABASE_MAX_UPLOAD_SIZE_MB = 7500; diff --git a/lib/upload-sarif-action-post.js b/lib/upload-sarif-action-post.js index 39d9d6e46..d5dc0eda5 100644 --- a/lib/upload-sarif-action-post.js +++ b/lib/upload-sarif-action-post.js @@ -119548,30 +119548,30 @@ var semver5 = __toESM(require_semver2()); var actionsCache = __toESM(require_cache3()); // src/git-utils.ts -var core7 = __toESM(require_core()); +var core8 = __toESM(require_core()); var toolrunner2 = __toESM(require_toolrunner()); var io3 = __toESM(require_io2()); var semver3 = __toESM(require_semver2()); // src/logging.ts -var core8 = __toESM(require_core()); +var core7 = __toESM(require_core()); function getActionsLogger() { return { - debug: core8.debug, - info: core8.info, - warning: core8.warning, - error: core8.error, - isDebug: core8.isDebug, - startGroup: core8.startGroup, - endGroup: core8.endGroup + debug: core7.debug, + info: core7.info, + warning: core7.warning, + error: core7.error, + isDebug: core7.isDebug, + startGroup: core7.startGroup, + endGroup: core7.endGroup }; } function withGroup(groupName, f) { - core8.startGroup(groupName); + core7.startGroup(groupName); try { return f(); } finally { - core8.endGroup(); + core7.endGroup(); } } diff --git a/lib/upload-sarif-action.js b/lib/upload-sarif-action.js index 83c50dc58..a37fbe62e 100644 --- a/lib/upload-sarif-action.js +++ b/lib/upload-sarif-action.js @@ -86517,14 +86517,41 @@ var actionsCache = __toESM(require_cache3()); var core6 = __toESM(require_core()); // src/git-utils.ts -var core7 = __toESM(require_core()); +var core8 = __toESM(require_core()); var toolrunner2 = __toESM(require_toolrunner()); var io3 = __toESM(require_io2()); var semver2 = __toESM(require_semver2()); + +// src/logging.ts +var core7 = __toESM(require_core()); +function getActionsLogger() { + return { + debug: core7.debug, + info: core7.info, + warning: core7.warning, + error: core7.error, + isDebug: core7.isDebug, + startGroup: core7.startGroup, + endGroup: core7.endGroup + }; +} +function formatDuration(durationMs) { + if (durationMs < 1e3) { + return `${durationMs}ms`; + } + if (durationMs < 60 * 1e3) { + return `${(durationMs / 1e3).toFixed(1)}s`; + } + const minutes = Math.floor(durationMs / (60 * 1e3)); + const seconds = Math.floor(durationMs % (60 * 1e3) / 1e3); + return `${minutes}m${seconds}s`; +} + +// src/git-utils.ts var runGitCommand = async function(workingDirectory, args, customErrorMessage) { let stdout = ""; let stderr = ""; - core7.debug(`Running git command: git ${args.join(" ")}`); + core8.debug(`Running git command: git ${args.join(" ")}`); try { await new toolrunner2.ToolRunner(await io3.which("git", true), args, { silent: true, @@ -86544,7 +86571,7 @@ var runGitCommand = async function(workingDirectory, args, customErrorMessage) { if (stderr.includes("not a git repository")) { reason = "The checkout path provided to the action does not appear to be a git repository."; } - core7.info(`git call failed. ${customErrorMessage} Error: ${reason}`); + core8.info(`git call failed. ${customErrorMessage} Error: ${reason}`); throw error3; } }; @@ -86689,7 +86716,7 @@ async function getRef() { ) !== head; if (hasChangedRef) { const newRef = ref.replace(pull_ref_regex, "refs/pull/$1/head"); - core7.debug( + core8.debug( `No longer on merge commit, rewriting ref from ${ref} to ${newRef}.` ); return newRef; @@ -86714,31 +86741,6 @@ async function isAnalyzingDefaultBranch() { return currentRef === defaultBranch; } -// src/logging.ts -var core8 = __toESM(require_core()); -function getActionsLogger() { - return { - debug: core8.debug, - info: core8.info, - warning: core8.warning, - error: core8.error, - isDebug: core8.isDebug, - startGroup: core8.startGroup, - endGroup: core8.endGroup - }; -} -function formatDuration(durationMs) { - if (durationMs < 1e3) { - return `${durationMs}ms`; - } - if (durationMs < 60 * 1e3) { - return `${(durationMs / 1e3).toFixed(1)}s`; - } - const minutes = Math.floor(durationMs / (60 * 1e3)); - const seconds = Math.floor(durationMs % (60 * 1e3) / 1e3); - return `${minutes}m${seconds}s`; -} - // src/overlay-database-utils.ts var CODEQL_OVERLAY_MINIMUM_VERSION = "2.23.5"; var OVERLAY_BASE_DATABASE_MAX_UPLOAD_SIZE_MB = 7500; diff --git a/src/diagnostics.ts b/src/diagnostics.ts index b3d18b23c..65b413664 100644 --- a/src/diagnostics.ts +++ b/src/diagnostics.ts @@ -185,3 +185,28 @@ export function flushDiagnostics(config: Config) { // Reset the unwritten diagnostics array. unwrittenDiagnostics = []; } + +/** + * Creates a telemetry-only diagnostic message. This is a convenience function + * for creating diagnostics that should only be sent to telemetry and not + * displayed on the status page or CLI summary table. + * + * @param id An identifier under which it makes sense to group this diagnostic message. + * @param name Display name for the ID. + * @param attributes Structured metadata about the diagnostic message. + * @returns Returns the new telemetry diagnostic message. + */ +export function makeTelemetryDiagnostic( + id: string, + name: string, + attributes: { [key: string]: any }, +): DiagnosticMessage { + return makeDiagnostic(id, name, { + attributes, + visibility: { + cliSummaryTable: false, + statusPage: false, + telemetry: true, + }, + }); +} diff --git a/src/git-utils.test.ts b/src/git-utils.test.ts index dbea5cac3..6d6a32867 100644 --- a/src/git-utils.test.ts +++ b/src/git-utils.test.ts @@ -398,39 +398,46 @@ test("getFileOidsUnderPath throws on unexpected output format", async (t) => { } }); -test("getGitVersion returns version for valid git output", async (t) => { +test("getGitVersionOrThrow returns version for valid git output", async (t) => { const runGitCommandStub = sinon .stub(gitUtils as any, "runGitCommand") .resolves("git version 2.40.0\n"); try { - const version = await gitUtils.getGitVersion(); + const version = await gitUtils.getGitVersionOrThrow(); t.is(version, "2.40.0"); } finally { runGitCommandStub.restore(); } }); -test("getGitVersion returns undefined for invalid git output", async (t) => { +test("getGitVersionOrThrow throws for invalid git output", async (t) => { const runGitCommandStub = sinon .stub(gitUtils as any, "runGitCommand") .resolves("invalid output"); try { - const version = await gitUtils.getGitVersion(); - t.is(version, undefined); + await t.throwsAsync( + async () => { + await gitUtils.getGitVersionOrThrow(); + }, + { + instanceOf: Error, + message: "Could not parse Git version from output: invalid output", + }, + ); } finally { runGitCommandStub.restore(); } }); -test("getGitVersion handles Windows-style git output", async (t) => { +test("getGitVersionOrThrow handles Windows-style git output", async (t) => { const runGitCommandStub = sinon .stub(gitUtils as any, "runGitCommand") .resolves("git version 2.40.0.windows.1\n"); try { - const version = await gitUtils.getGitVersion(); + const version = await gitUtils.getGitVersionOrThrow(); // Should extract just the major.minor.patch portion t.is(version, "2.40.0"); } finally { @@ -438,20 +445,79 @@ test("getGitVersion handles Windows-style git output", async (t) => { } }); -test("getGitVersion returns undefined when git command fails", async (t) => { +test("getGitVersionOrThrow throws when git command fails", async (t) => { const runGitCommandStub = sinon .stub(gitUtils as any, "runGitCommand") .rejects(new Error("git not found")); try { - const version = await gitUtils.getGitVersion(); - t.is(version, undefined); + await t.throwsAsync( + async () => { + await gitUtils.getGitVersionOrThrow(); + }, + { + instanceOf: Error, + message: "git not found", + }, + ); } finally { runGitCommandStub.restore(); } }); +test("getGitVersion returns version and caches it", async (t) => { + gitUtils.resetCachedGitVersion(); + const runGitCommandStub = sinon + .stub(gitUtils as any, "runGitCommand") + .resolves("git version 2.40.0\n"); + + const messages: LoggedMessage[] = []; + const logger = getRecordingLogger(messages); + + try { + // First call should fetch and cache + const version1 = await gitUtils.getGitVersion(logger); + t.is(version1, "2.40.0"); + t.is(runGitCommandStub.callCount, 1); + + // Second call should use cache + const version2 = await gitUtils.getGitVersion(logger); + t.is(version2, "2.40.0"); + t.is(runGitCommandStub.callCount, 1); // Should still be 1 + } finally { + runGitCommandStub.restore(); + gitUtils.resetCachedGitVersion(); + } +}); + +test("getGitVersion returns undefined when version cannot be determined", async (t) => { + gitUtils.resetCachedGitVersion(); + const runGitCommandStub = sinon + .stub(gitUtils as any, "runGitCommand") + .rejects(new Error("git not found")); + + const messages: LoggedMessage[] = []; + const logger = getRecordingLogger(messages); + + try { + const version = await gitUtils.getGitVersion(logger); + t.is(version, undefined); + t.true( + messages.some( + (m) => + m.type === "debug" && + typeof m.message === "string" && + m.message.includes("Could not determine Git version"), + ), + ); + } finally { + runGitCommandStub.restore(); + gitUtils.resetCachedGitVersion(); + } +}); + test("gitVersionAtLeast returns true for version meeting requirement", async (t) => { + gitUtils.resetCachedGitVersion(); const runGitCommandStub = sinon .stub(gitUtils as any, "runGitCommand") .resolves("git version 2.40.0\n"); @@ -471,10 +537,12 @@ test("gitVersionAtLeast returns true for version meeting requirement", async (t) ); } finally { runGitCommandStub.restore(); + gitUtils.resetCachedGitVersion(); } }); test("gitVersionAtLeast returns false for version not meeting requirement", async (t) => { + gitUtils.resetCachedGitVersion(); const runGitCommandStub = sinon .stub(gitUtils as any, "runGitCommand") .resolves("git version 2.30.0\n"); @@ -487,10 +555,12 @@ test("gitVersionAtLeast returns false for version not meeting requirement", asyn t.false(result); } finally { runGitCommandStub.restore(); + gitUtils.resetCachedGitVersion(); } }); test("gitVersionAtLeast returns false when version cannot be determined", async (t) => { + gitUtils.resetCachedGitVersion(); const runGitCommandStub = sinon .stub(gitUtils as any, "runGitCommand") .rejects(new Error("git not found")); @@ -505,10 +575,12 @@ test("gitVersionAtLeast returns false when version cannot be determined", async messages.some( (m) => m.type === "debug" && - m.message === "Could not determine Git version.", + typeof m.message === "string" && + m.message.includes("Could not determine Git version"), ), ); } finally { runGitCommandStub.restore(); + gitUtils.resetCachedGitVersion(); } }); diff --git a/src/git-utils.ts b/src/git-utils.ts index 6fa1369ce..6bae2f40e 100644 --- a/src/git-utils.ts +++ b/src/git-utils.ts @@ -8,8 +8,14 @@ import { getWorkflowEvent, getWorkflowEventName, } from "./actions-util"; +import type { Config } from "./config-utils"; +import { addDiagnostic, makeTelemetryDiagnostic } from "./diagnostics"; import { Logger } from "./logging"; -import { ConfigurationError, getRequiredEnvParam } from "./util"; +import { + ConfigurationError, + getErrorMessage, + getRequiredEnvParam, +} from "./util"; /** * Minimum Git version required for overlay analysis. The `git ls-files --format` @@ -17,28 +23,81 @@ import { ConfigurationError, getRequiredEnvParam } from "./util"; */ export const GIT_MINIMUM_VERSION_FOR_OVERLAY = "2.38.0"; +/** Cached git version to avoid recomputing it multiple times. */ +let cachedGitVersion: string | undefined; + /** - * Gets the version of Git installed on the system. - * - * @returns The Git version string (e.g., "2.40.0"), or undefined if the - * version could not be determined. + * Resets the cached git version. This is intended for use in tests only. */ -export async function getGitVersion(): Promise { +export function resetCachedGitVersion(): void { + cachedGitVersion = undefined; +} + +/** + * Gets the version of Git installed on the system and throws an error if + * the version cannot be determined. + * + * @returns The Git version string (e.g., "2.40.0"). + * @throws {Error} if the version could not be determined. + */ +export async function getGitVersionOrThrow(): Promise { + const stdout = await runGitCommand( + undefined, + ["--version"], + "Failed to get git version.", + ); + // Git version output can vary: "git version 2.40.0" or "git version 2.40.0.windows.1" + // We capture just the major.minor.patch portion to ensure semver compatibility. + const match = stdout.match(/git version (\d+\.\d+\.\d+)/); + if (match?.[1]) { + return match[1]; + } + throw new Error(`Could not parse Git version from output: ${stdout.trim()}`); +} + +/** + * Gets the cached Git version, or fetches and caches it if not yet cached. + * + * @param logger A logger to use for logging errors. + * @returns The cached Git version, or undefined if the version could not be determined. + */ +export async function getGitVersion( + logger: Logger, +): Promise { + if (cachedGitVersion !== undefined) { + return cachedGitVersion; + } try { - const stdout = await runGitCommand( - undefined, - ["--version"], - "Failed to get git version.", + cachedGitVersion = await getGitVersionOrThrow(); + return cachedGitVersion; + } catch (e) { + logger.debug(`Could not determine Git version: ${getErrorMessage(e)}`); + return undefined; + } +} + +/** + * Logs the Git version as a telemetry diagnostic. Should be called once during + * initialization after the config is available. + * + * @param config The configuration that tells us where to store the diagnostic. + * @param logger A logger to use for logging errors. + */ +export async function logGitVersionTelemetry( + config: Config, + logger: Logger, +): Promise { + const version = await getGitVersion(logger); + if (version !== undefined) { + addDiagnostic( + config, + config.languages[0], + makeTelemetryDiagnostic( + "codeql-action/git-version-telemetry", + "Git version telemetry", + { gitVersion: version }, + ), ); - // Git version output can vary: "git version 2.40.0" or "git version 2.40.0.windows.1" - // We capture just the major.minor.patch portion to ensure semver compatibility. - const match = stdout.match(/git version (\d+\.\d+\.\d+)/); - if (match?.[1]) { - return match[1]; - } - return undefined; - } catch { - return undefined; } } @@ -54,9 +113,8 @@ export async function gitVersionAtLeast( requiredVersion: string, logger: Logger, ): Promise { - const version = await getGitVersion(); + const version = await getGitVersion(logger); if (version === undefined) { - logger.debug("Could not determine Git version."); return false; } logger.debug(`Installed Git version is ${version}.`); diff --git a/src/init-action.ts b/src/init-action.ts index 8fa7899d8..dbbae2ad6 100644 --- a/src/init-action.ts +++ b/src/init-action.ts @@ -37,6 +37,7 @@ import { import { EnvVar } from "./environment"; import { Feature, Features } from "./feature-flags"; import { loadPropertiesFromApi } from "./feature-flags/properties"; +import { logGitVersionTelemetry } from "./git-utils"; import { checkInstallPython311, checkPacksForOverlayCompatibility, @@ -433,6 +434,9 @@ async function run() { ); } + // Log Git version telemetry + await logGitVersionTelemetry(config, logger); + // Forward Go flags const goFlags = process.env["GOFLAGS"]; if (goFlags) {