From f4fa111630c809cc10991d9761d73c2f782230d6 Mon Sep 17 00:00:00 2001 From: Henry Mercer Date: Wed, 16 Sep 2026 19:51:23 +0100 Subject: [PATCH] Share elapsed-time rounding for bundle downloads Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --- lib/entry-points.js | 56 +++++++++++++++++++++++-------------------- src/setup-codeql.ts | 2 +- src/tools-download.ts | 9 +++---- src/util.test.ts | 21 ++++++++++++++++ src/util.ts | 6 +++++ 5 files changed, 63 insertions(+), 31 deletions(-) diff --git a/lib/entry-points.js b/lib/entry-points.js index fc50bae4f..cc4cf5f24 100644 --- a/lib/entry-points.js +++ b/lib/entry-points.js @@ -4305,7 +4305,7 @@ var require_util2 = __commonJS({ var { redirectStatusSet, referrerPolicySet: referrerPolicyTokens, badPortsSet } = require_constants3(); var { getGlobalOrigin } = require_global(); var { collectASequenceOfCodePoints, collectAnHTTPQuotedString, removeChars, parseMIMEType } = require_data_url(); - var { performance: performance7 } = require("node:perf_hooks"); + var { performance: performance8 } = require("node:perf_hooks"); var { isBlobLike, ReadableStreamFrom, isValidHTTPToken, normalizedMethodRecordsBase } = require_util(); var assert = require("node:assert"); var { isUint8Array } = require("node:util/types"); @@ -4464,7 +4464,7 @@ var require_util2 = __commonJS({ }; } function coarsenedSharedCurrentTime(crossOriginIsolatedCapability) { - return coarsenTime(performance7.now(), crossOriginIsolatedCapability); + return coarsenTime(performance8.now(), crossOriginIsolatedCapability); } function createOpaqueTimingInfo(timingInfo) { return { @@ -142119,7 +142119,7 @@ module.exports = __toCommonJS(entry_points_exports); // src/analyze-action.ts var fs23 = __toESM(require("fs")); var import_path5 = __toESM(require("path")); -var import_perf_hooks5 = require("perf_hooks"); +var import_perf_hooks6 = require("perf_hooks"); var core17 = __toESM(require_core()); // src/action-common.ts @@ -142201,6 +142201,7 @@ var fs = __toESM(require("fs")); var fsPromises = __toESM(require("fs/promises")); var os = __toESM(require("os")); var path = __toESM(require("path")); +var import_perf_hooks = require("perf_hooks"); var core2 = __toESM(require_core()); var io = __toESM(require_io()); @@ -145892,6 +145893,9 @@ async function bundleDb(config, language, codeql, dbName, { includeDiagnostics } ); return databaseBundlePath; } +function durationMsSince(startTime) { + return Math.round(import_perf_hooks.performance.now() - startTime); +} async function delay(milliseconds, opts) { const { allowProcessExit } = opts || {}; return new Promise((resolve14) => { @@ -148633,7 +148637,7 @@ var SarifScanOrder = [ // src/analyze.ts var fs17 = __toESM(require("fs")); var path16 = __toESM(require("path")); -var import_perf_hooks4 = require("perf_hooks"); +var import_perf_hooks5 = require("perf_hooks"); var io5 = __toESM(require_io()); // src/autobuild.ts @@ -148897,7 +148901,7 @@ function wrapCliConfigurationError(cliError) { // src/config-utils.ts var fs10 = __toESM(require("fs")); var path11 = __toESM(require("path")); -var import_perf_hooks = require("perf_hooks"); +var import_perf_hooks2 = require("perf_hooks"); var core10 = __toESM(require_core()); // src/caching-utils.ts @@ -150523,9 +150527,9 @@ async function initActionState({ }; } async function downloadCacheWithTime(codeQL, languages, logger) { - const start = import_perf_hooks.performance.now(); + const start = import_perf_hooks2.performance.now(); const trapCaches = await downloadTrapCaches(codeQL, languages, logger); - const trapCacheDownloadTime = import_perf_hooks.performance.now() - start; + const trapCacheDownloadTime = import_perf_hooks2.performance.now() - start; return { trapCaches, trapCacheDownloadTime }; } async function loadUserConfig(actionState, configFile, workspacePath, apiDetails, tempDir) { @@ -150929,10 +150933,10 @@ async function initConfig(actionState, inputs) { } if (await features.getValue("ignore_generated_files" /* IgnoreGeneratedFiles */) && isDynamicWorkflow()) { try { - const generatedFilesCheckStartedAt = import_perf_hooks.performance.now(); + const generatedFilesCheckStartedAt = import_perf_hooks2.performance.now(); const generatedFiles = await getGeneratedFiles(inputs.sourceRoot); const generatedFilesDuration = Math.round( - import_perf_hooks.performance.now() - generatedFilesCheckStartedAt + import_perf_hooks2.performance.now() - generatedFilesCheckStartedAt ); if (generatedFiles.length > 0) { config.computedConfig["paths-ignore"] ??= []; @@ -151216,7 +151220,7 @@ async function logGeneratedFilesTelemetry(config, duration, generatedFilesCount) // src/setup-codeql.ts var fs14 = __toESM(require("fs")); var path13 = __toESM(require("path")); -var import_perf_hooks3 = require("perf_hooks"); +var import_perf_hooks4 = require("perf_hooks"); var core12 = __toESM(require_core()); var toolcache3 = __toESM(require_tool_cache()); var import_fast_deep_equal = __toESM(require_fast_deep_equal()); @@ -151789,7 +151793,7 @@ function inferCompressionMethod(tarPath) { var fs13 = __toESM(require("fs")); var os4 = __toESM(require("os")); var path12 = __toESM(require("path")); -var import_perf_hooks2 = require("perf_hooks"); +var import_perf_hooks3 = require("perf_hooks"); var core11 = __toESM(require_core()); var import_http_client = __toESM(require_lib()); var toolcache2 = __toESM(require_tool_cache()); @@ -151802,7 +151806,7 @@ async function downloadAndExtract(codeqlURL, compressionMethod, dest, authorizat logger.info( `Downloading CodeQL tools from ${codeqlURL} . This may take a while.` ); - const startTime = import_perf_hooks2.performance.now(); + const startTime = import_perf_hooks3.performance.now(); try { if (compressionMethod === "zstd" && process.platform === "linux") { logger.info(`Streaming the extraction of the CodeQL bundle.`); @@ -151814,7 +151818,7 @@ async function downloadAndExtract(codeqlURL, compressionMethod, dest, authorizat tarVersion, logger ); - const totalDurationMs = Math.round(import_perf_hooks2.performance.now() - startTime); + const totalDurationMs = durationMsSince(startTime); logger.info( `Finished downloading and extracting CodeQL bundle to ${dest} (${formatDuration( totalDurationMs @@ -151832,14 +151836,14 @@ async function downloadAndExtract(codeqlURL, compressionMethod, dest, authorizat ); core11.warning(`Falling back to downloading the bundle before extracting.`); } - const toolsDownloadStart = import_perf_hooks2.performance.now(); + const toolsDownloadStart = import_perf_hooks3.performance.now(); const archivedBundlePath = await toolcache2.downloadTool( codeqlURL, void 0, authorization, headers ); - const downloadDurationMs = Math.round(import_perf_hooks2.performance.now() - toolsDownloadStart); + const downloadDurationMs = durationMsSince(toolsDownloadStart); logger.info( `Finished downloading CodeQL bundle to ${archivedBundlePath} (${formatDuration( downloadDurationMs @@ -151848,7 +151852,7 @@ async function downloadAndExtract(codeqlURL, compressionMethod, dest, authorizat let extractionDurationMs; try { logger.info("Extracting CodeQL bundle."); - const extractionStart = import_perf_hooks2.performance.now(); + const extractionStart = import_perf_hooks3.performance.now(); await extract( archivedBundlePath, dest, @@ -151856,7 +151860,7 @@ async function downloadAndExtract(codeqlURL, compressionMethod, dest, authorizat tarVersion, logger ); - extractionDurationMs = Math.round(import_perf_hooks2.performance.now() - extractionStart); + extractionDurationMs = durationMsSince(extractionStart); logger.info( `Finished extracting CodeQL bundle to ${dest} (${formatDuration( extractionDurationMs @@ -151868,7 +151872,7 @@ async function downloadAndExtract(codeqlURL, compressionMethod, dest, authorizat return { downloadDurationMs, extractionDurationMs, - totalDurationMs: Math.round(import_perf_hooks2.performance.now() - startTime) + totalDurationMs: durationMsSince(startTime) }; } async function downloadAndExtractZstdWithStreaming(codeqlURL, dest, authorization, headers, tarVersion, logger) { @@ -152679,7 +152683,7 @@ async function downloadCodeQLBundle(action, source, apiDetails, tarVersion, temp const { bundle } = source; const { logger } = action; await tryDeleteToolcacheBundles(action); - const startTime = import_perf_hooks3.performance.now(); + const startTime = import_perf_hooks4.performance.now(); try { return await downloadCodeQL( source, @@ -152709,7 +152713,7 @@ async function downloadCodeQLBundle(action, source, apiDetails, tarVersion, temp ...result, statusReport: { ...result.statusReport, - totalDurationMs: Math.round(import_perf_hooks3.performance.now() - startTime), + totalDurationMs: durationMsSince(startTime), perLanguageBundleFallback: true } }; @@ -153873,10 +153877,10 @@ function dbIsFinalized(config, language, logger) { } } async function finalizeDatabaseCreation(codeql, features, config, threadsFlag, memoryFlag, logger) { - const extractionStart = import_perf_hooks4.performance.now(); + const extractionStart = import_perf_hooks5.performance.now(); await runExtraction(codeql, features, config, logger); - const extractionTime = import_perf_hooks4.performance.now() - extractionStart; - const trapImportStart = import_perf_hooks4.performance.now(); + const extractionTime = import_perf_hooks5.performance.now() - extractionStart; + const trapImportStart = import_perf_hooks5.performance.now(); for (const language of config.languages) { if (dbIsFinalized(config, language, logger)) { logger.info( @@ -153893,7 +153897,7 @@ async function finalizeDatabaseCreation(codeql, features, config, threadsFlag, m logger.endGroup(); } } - const trapImportTime = import_perf_hooks4.performance.now() - trapImportStart; + const trapImportTime = import_perf_hooks5.performance.now() - trapImportStart; return { scanned_language_extraction_duration_ms: Math.round(extractionTime), trap_import_duration_ms: Math.round(trapImportTime) @@ -156700,9 +156704,9 @@ async function run({ startedAt, logger }) { features, logger ); - const trapCacheUploadStartTime = import_perf_hooks5.performance.now(); + const trapCacheUploadStartTime = import_perf_hooks6.performance.now(); didUploadTrapCaches = await uploadTrapCaches(codeql, config, logger); - trapCacheUploadTime = import_perf_hooks5.performance.now() - trapCacheUploadStartTime; + trapCacheUploadTime = import_perf_hooks6.performance.now() - trapCacheUploadStartTime; trapCacheCleanupTelemetry = await cleanupTrapCaches( config, features, diff --git a/src/setup-codeql.ts b/src/setup-codeql.ts index 4efb0dc2e..cadbcb399 100644 --- a/src/setup-codeql.ts +++ b/src/setup-codeql.ts @@ -1170,7 +1170,7 @@ export async function downloadCodeQLBundle( ...result, statusReport: { ...result.statusReport, - totalDurationMs: Math.round(performance.now() - startTime), + totalDurationMs: util.durationMsSince(startTime), perLanguageBundleFallback: true, }, }; diff --git a/src/tools-download.ts b/src/tools-download.ts index 5494ab30f..61501557c 100644 --- a/src/tools-download.ts +++ b/src/tools-download.ts @@ -17,6 +17,7 @@ import * as tar from "./tar"; import { asHTTPError, cleanUpPath, + durationMsSince, getErrorMessage, getRequiredEnvParam, HTTPError, @@ -91,7 +92,7 @@ export async function downloadAndExtract( logger, ); - const totalDurationMs = Math.round(performance.now() - startTime); + const totalDurationMs = durationMsSince(startTime); logger.info( `Finished downloading and extracting CodeQL bundle to ${dest} (${formatDuration( totalDurationMs, @@ -124,7 +125,7 @@ export async function downloadAndExtract( authorization, headers, ); - const downloadDurationMs = Math.round(performance.now() - toolsDownloadStart); + const downloadDurationMs = durationMsSince(toolsDownloadStart); logger.info( `Finished downloading CodeQL bundle to ${archivedBundlePath} (${formatDuration( @@ -144,7 +145,7 @@ export async function downloadAndExtract( tarVersion, logger, ); - extractionDurationMs = Math.round(performance.now() - extractionStart); + extractionDurationMs = durationMsSince(extractionStart); logger.info( `Finished extracting CodeQL bundle to ${dest} (${formatDuration( extractionDurationMs, @@ -157,7 +158,7 @@ export async function downloadAndExtract( return { downloadDurationMs, extractionDurationMs, - totalDurationMs: Math.round(performance.now() - startTime), + totalDurationMs: durationMsSince(startTime), }; } diff --git a/src/util.test.ts b/src/util.test.ts index cca457cbe..074310279 100644 --- a/src/util.test.ts +++ b/src/util.test.ts @@ -1,6 +1,7 @@ import * as fs from "fs"; import * as os from "os"; import path from "path"; +import { performance } from "perf_hooks"; import * as core from "@actions/core"; import test from "ava"; @@ -508,6 +509,26 @@ test("joinAtMost - truncates list if array is > than limit", (t) => { t.false(result.includes("test6")); }); +test.serial( + "durationMsSince rounds elapsed milliseconds rather than the timestamps", + (t) => { + const startTime = 1000.25; + const now = sinon.stub(performance, "now"); + for (const [endTime, expected] of [ + [1000.25, 0], + [1000.74, 0], + [1000.75, 1], + [1001.74, 1], + [1001.75, 2], + [2000.74, 1000], + [2000.75, 1001], + ]) { + now.returns(endTime); + t.is(util.durationMsSince(startTime), expected); + } + }, +); + test("Success creates a success result", (t) => { const result = new util.Success("test value"); t.true(result.isSuccess()); diff --git a/src/util.ts b/src/util.ts index 49fe924f6..456cd7c3d 100644 --- a/src/util.ts +++ b/src/util.ts @@ -2,6 +2,7 @@ import * as fs from "fs"; import * as fsPromises from "fs/promises"; import * as os from "os"; import * as path from "path"; +import { performance } from "perf_hooks"; import * as core from "@actions/core"; import * as io from "@actions/io"; @@ -681,6 +682,11 @@ export async function bundleDb( return databaseBundlePath; } +/** Returns the elapsed milliseconds, rounded, since a `performance.now()` timestamp. */ +export function durationMsSince(startTime: number): number { + return Math.round(performance.now() - startTime); +} + /** * @param milliseconds time to delay * @param opts options