diff --git a/lib/entry-points.js b/lib/entry-points.js index 952c615417..0bceda727a 100644 --- a/lib/entry-points.js +++ b/lib/entry-points.js @@ -184864,13 +184864,16 @@ async function deleteToolcacheBundles({ } const versionDirectory = path12.join(toolDirectory, entry.name); try { + const deletionStart = import_perf_hooks3.performance.now(); await fs15.promises.rm(versionDirectory, { force: true, recursive: true }); deletedVersions.push(entry.name); logger2.info( - `Deleted the CodeQL tools at '${versionDirectory}' from the toolcache to free up disk space.` + `Deleted the CodeQL tools at '${versionDirectory}' from the toolcache to free up disk space (${formatDuration( + durationMsSince(deletionStart) + )}).` ); } catch (e) { failed = true; @@ -185369,13 +185372,14 @@ async function tryDeleteToolcacheBundles({ if (!isGitHubHostedRunner(env) || !isToolcacheOnWorkspaceFilesystem(logger2)) { return; } + const startTime = import_perf_hooks4.performance.now(); const result = await deleteToolcacheBundles({ env, logger: logger2 }); addNoLanguageDiagnostic( void 0, makeTelemetryDiagnostic( "codeql-action/toolcache-bundle-cleanup", "Toolcache CodeQL bundle cleanup", - { ...result } + { ...result, durationMs: durationMsSince(startTime) } ) ); } diff --git a/src/setup-codeql.test.ts b/src/setup-codeql.test.ts index a244501c38..e8c64c6166 100644 --- a/src/setup-codeql.test.ts +++ b/src/setup-codeql.test.ts @@ -1821,7 +1821,8 @@ function createToolcacheEntry( /** * Stubs out the download and the diagnostic sink, then downloads the CodeQL tools. * - * @returns the extraction directory and the toolcache cleanup diagnostic, if emitted. + * @returns the extraction directory and, if the toolcache cleanup diagnostic was emitted, the + * cleanup duration it reports and its other attributes. */ async function runDownloadCodeQL( toolcacheRoot: string, @@ -1837,6 +1838,7 @@ async function runDownloadCodeQL( ): Promise<{ codeqlFolder: string; cleanupDiagnostic: toolsDownload.ToolcacheCleanupResult | undefined; + cleanupDurationMs: number | undefined; }> { stubDownloadAndExtract(); const addDiagnostic = sinon.stub(diagnostics, "addNoLanguageDiagnostic"); @@ -1866,11 +1868,21 @@ async function runDownloadCodeQL( .map((call) => call.args[1]) .find((d) => d.source?.id === "codeql-action/toolcache-bundle-cleanup"); - return { - codeqlFolder, - cleanupDiagnostic: diagnostic?.attributes as - toolsDownload.ToolcacheCleanupResult | undefined, - }; + if (diagnostic === undefined) { + return { + codeqlFolder, + cleanupDiagnostic: undefined, + cleanupDurationMs: undefined, + }; + } + + // The duration varies between runs, so split it out to let tests compare the other attributes + // exactly. + const { durationMs, ...cleanupDiagnostic } = + diagnostic.attributes as toolsDownload.ToolcacheCleanupResult & { + durationMs: number; + }; + return { codeqlFolder, cleanupDiagnostic, cleanupDurationMs: durationMs }; } /** @@ -1991,6 +2003,35 @@ test.serial( }, ); +test.serial( + "downloadCodeQLBundle reports the total time taken to clean up the toolcache", + async (t) => { + await withTmpDir(async (tmpDir) => { + setupActionsVars(tmpDir, tmpDir); + + createToolcacheEntry(tmpDir, "CodeQL", CLEANUP_CLI_VERSION); + createToolcacheEntry(tmpDir, "CodeQL", CLEANUP_STALE_VERSION); + + // Advance the clock by 1.5s each time a path is deleted, so that deleting both versions + // takes 3s. + let elapsedMs = 1000; + sinon.stub(performance, "now").callsFake(() => elapsedMs); + const rm = fs.promises.rm; + sinon.stub(fs.promises, "rm").callsFake(async (...args) => { + elapsedMs += 1500; + await rm(...args); + }); + + const { cleanupDurationMs } = await runDownloadCodeQL( + tmpDir, + CLEANUP_BUNDLE_VERSION, + ); + + t.is(cleanupDurationMs, 3000); + }); + }, +); + test.serial( "downloadCodeQLBundle reports no deleted versions when the toolcache has no CodeQL bundles", async (t) => { diff --git a/src/setup-codeql.ts b/src/setup-codeql.ts index d70e1f5087..b87b81bdc0 100644 --- a/src/setup-codeql.ts +++ b/src/setup-codeql.ts @@ -814,6 +814,7 @@ async function tryDeleteToolcacheBundles({ return; } + const startTime = performance.now(); const result = await deleteToolcacheBundles({ env, logger }); addNoLanguageDiagnostic( @@ -821,7 +822,7 @@ async function tryDeleteToolcacheBundles({ makeTelemetryDiagnostic( "codeql-action/toolcache-bundle-cleanup", "Toolcache CodeQL bundle cleanup", - { ...result }, + { ...result, durationMs: util.durationMsSince(startTime) }, ), ); } diff --git a/src/tools-download.ts b/src/tools-download.ts index a92dad0acf..a5b5a5a0da 100644 --- a/src/tools-download.ts +++ b/src/tools-download.ts @@ -342,13 +342,16 @@ export async function deleteToolcacheBundles({ const versionDirectory = path.join(toolDirectory, entry.name); try { + const deletionStart = performance.now(); await fs.promises.rm(versionDirectory, { force: true, recursive: true, }); deletedVersions.push(entry.name); logger.info( - `Deleted the CodeQL tools at '${versionDirectory}' from the toolcache to free up disk space.`, + `Deleted the CodeQL tools at '${versionDirectory}' from the toolcache to free up disk space (${formatDuration( + durationMsSince(deletionStart), + )}).`, ); } catch (e) { failed = true;