From ecec9b5a3756247bd2bfec7da1b6f7bb3eb92d46 Mon Sep 17 00:00:00 2001 From: Henry Mercer Date: Thu, 17 Sep 2026 19:06:17 +0100 Subject: [PATCH] Share per-language telemetry fields without renaming Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --- lib/entry-points.js | 15 +++--- src/setup-codeql.test.ts | 17 ++++--- src/setup-codeql.ts | 7 ++- src/status-report/tools-download.test.ts | 9 ++-- src/status-report/tools-download.ts | 59 +++++++++++------------- src/tools-download.ts | 9 +--- 6 files changed, 57 insertions(+), 59 deletions(-) diff --git a/lib/entry-points.js b/lib/entry-points.js index 53532f2f7..f8a7d6e76 100644 --- a/lib/entry-points.js +++ b/lib/entry-points.js @@ -152544,7 +152544,10 @@ var downloadCodeQL = async function(source, apiDetails, tarVersion, tempDir, log } return { codeqlFolder: extractedBundlePath, - statusReport: bundle.kind === "per-language" ? { ...statusReport, bundleLanguage: bundle.language } : statusReport + statusReport: bundle.kind === "per-language" ? { + ...statusReport, + perLanguage: { tools_bundle_language: bundle.language } + } : statusReport }; }; function getToolcacheDestination({ logger }, source) { @@ -152695,7 +152698,7 @@ async function downloadCodeQLBundle(action, source, apiDetails, tarVersion, temp statusReport: { ...result.statusReport, totalDurationMs: durationMsSince(startTime), - perLanguageBundleFallback: true + perLanguage: { tools_per_language_bundle_fallback: true } } }; } @@ -161862,7 +161865,7 @@ async function getToolsInput(action, repositoryProperties) { // src/status-report/tools-download.ts function createInitToolsDownloadFields(report, toolsFeatureFlagsValid) { - const fields = {}; + const fields = { ...report?.perLanguage }; if (report?.downloadDurationMs !== void 0) { fields.tools_download_duration_ms = report.downloadDurationMs; } @@ -161872,12 +161875,6 @@ function createInitToolsDownloadFields(report, toolsFeatureFlagsValid) { if (report?.totalDurationMs !== void 0) { fields.tools_total_duration_ms = report.totalDurationMs; } - if (report?.bundleLanguage !== void 0) { - fields.tools_bundle_language = report.bundleLanguage; - } - if (report?.perLanguageBundleFallback !== void 0) { - fields.tools_per_language_bundle_fallback = report.perLanguageBundleFallback; - } if (toolsFeatureFlagsValid !== void 0) { fields.tools_feature_flags_valid = toolsFeatureFlagsValid; } diff --git a/src/setup-codeql.test.ts b/src/setup-codeql.test.ts index c32c22b64..9346c30e6 100644 --- a/src/setup-codeql.test.ts +++ b/src/setup-codeql.test.ts @@ -557,7 +557,7 @@ for (const bundlePath of [ t.is(result.toolsVersion, "unknown"); t.is(result.toolsSource, setupCodeql.ToolsSource.Download); t.is( - result.toolsDownloadStatusReport?.bundleLanguage, + result.toolsDownloadStatusReport?.perLanguage?.tools_bundle_language, bundlePath === "codeql-bundle-ruby-linux64.tar.zst" ? BuiltInLanguage.ruby : undefined, @@ -1309,11 +1309,12 @@ for (const fallback of [false, true]) { t.is(extractStub.lastCall.args[3], "token token"); t.is(result.toolsVersion, MIN_PER_LANGUAGE_BUNDLE_CLI_VERSION); t.is( - result.toolsDownloadStatusReport?.bundleLanguage, + result.toolsDownloadStatusReport?.perLanguage?.tools_bundle_language, fallback ? undefined : BuiltInLanguage.java, ); t.is( - result.toolsDownloadStatusReport?.perLanguageBundleFallback, + result.toolsDownloadStatusReport?.perLanguage + ?.tools_per_language_bundle_fallback, fallback ? true : undefined, ); if (fallback) { @@ -1401,7 +1402,8 @@ for (const bundle of ["per-language", "combined", "fallback"] as const) { t.is(result.toolsDownloadStatusReport?.downloadDurationMs, 200); t.is(result.toolsDownloadStatusReport?.extractionDurationMs, 100); t.is( - (await downloadSpy.lastCall.returnValue).statusReport.bundleLanguage, + (await downloadSpy.lastCall.returnValue).statusReport.perLanguage + ?.tools_bundle_language, bundle === "per-language" ? BuiltInLanguage.javascript : undefined, ); t.is(extractStub.callCount, bundle === "fallback" ? 2 : 1); @@ -1415,11 +1417,12 @@ for (const bundle of ["per-language", "combined", "fallback"] as const) { bundle === "per-language" ? perLanguageURL : combinedURL, ); t.is( - result.toolsDownloadStatusReport?.bundleLanguage, + result.toolsDownloadStatusReport?.perLanguage?.tools_bundle_language, bundle === "per-language" ? BuiltInLanguage.javascript : undefined, ); t.is( - result.toolsDownloadStatusReport?.perLanguageBundleFallback, + result.toolsDownloadStatusReport?.perLanguage + ?.tools_per_language_bundle_fallback, bundle === "fallback" ? true : undefined, ); t.is( @@ -1503,7 +1506,7 @@ for (const asset of [ t.is(extractStub.firstCall.args[0], url); t.is(result.toolsVersion, "9.9.9"); t.is( - result.toolsDownloadStatusReport?.bundleLanguage, + result.toolsDownloadStatusReport?.perLanguage?.tools_bundle_language, BuiltInLanguage.ruby, ); t.is(path.dirname(result.codeqlFolder), tmpDir); diff --git a/src/setup-codeql.ts b/src/setup-codeql.ts index 60f68a37a..cf4050987 100644 --- a/src/setup-codeql.ts +++ b/src/setup-codeql.ts @@ -904,7 +904,10 @@ export const downloadCodeQL = async function ( codeqlFolder: extractedBundlePath, statusReport: bundle.kind === "per-language" - ? { ...statusReport, bundleLanguage: bundle.language } + ? { + ...statusReport, + perLanguage: { tools_bundle_language: bundle.language }, + } : statusReport, }; }; @@ -1171,7 +1174,7 @@ export async function downloadCodeQLBundle( statusReport: { ...result.statusReport, totalDurationMs: util.durationMsSince(startTime), - perLanguageBundleFallback: true, + perLanguage: { tools_per_language_bundle_fallback: true }, }, }; } diff --git a/src/status-report/tools-download.test.ts b/src/status-report/tools-download.test.ts index 9b3924217..856bf882f 100644 --- a/src/status-report/tools-download.test.ts +++ b/src/status-report/tools-download.test.ts @@ -24,7 +24,10 @@ test("createInitToolsDownloadFields reports only the total for a streaming downl test("createInitToolsDownloadFields preserves per-language metadata", (t) => { t.deepEqual( createInitToolsDownloadFields( - { totalDurationMs: 300, bundleLanguage: BuiltInLanguage.java }, + { + totalDurationMs: 300, + perLanguage: { tools_bundle_language: BuiltInLanguage.java }, + }, true, ), { @@ -42,7 +45,7 @@ test("createInitToolsDownloadFields preserves fallback and per-attempt timings", downloadDurationMs: 200, extractionDurationMs: 100, totalDurationMs: 1000, - perLanguageBundleFallback: true, + perLanguage: { tools_per_language_bundle_fallback: true }, }, undefined, ), @@ -62,7 +65,7 @@ test("createInitToolsDownloadFields preserves zero durations and false flags", ( downloadDurationMs: 0, extractionDurationMs: 0, totalDurationMs: 0, - perLanguageBundleFallback: false, + perLanguage: { tools_per_language_bundle_fallback: false }, }, false, ), diff --git a/src/status-report/tools-download.ts b/src/status-report/tools-download.ts index d9698ffea..a5f7dffbf 100644 --- a/src/status-report/tools-download.ts +++ b/src/status-report/tools-download.ts @@ -1,33 +1,37 @@ import type { ToolsDownloadStatusReport } from "../tools-download"; -/** Fields of the init status report populated when the tools source is `download`. */ -export interface InitToolsDownloadFields { - /** - * Time taken to download the bundle, in milliseconds. Not populated when the bundle is downloaded - * and extracted concurrently. - */ - tools_download_duration_ms?: ToolsDownloadStatusReport["downloadDurationMs"]; - /** - * Time taken to extract the bundle, in milliseconds. Not populated when the bundle is downloaded - * and extracted concurrently. - */ - tools_extraction_duration_ms?: ToolsDownloadStatusReport["extractionDurationMs"]; - /** - * Total time taken to make the bundle available on disk, including failed download attempts - * before a fallback, in milliseconds. - */ - tools_total_duration_ms?: ToolsDownloadStatusReport["totalDurationMs"]; - /** - * Whether the relevant tools dotcom feature flags have been misconfigured. - * Only populated if we attempt to determine the default version based on the dotcom feature flags. */ - tools_feature_flags_valid?: boolean; +/** Telemetry describing per-language bundle downloads. */ +export interface PerLanguageToolsStatusReport { /** The language of the single-language bundle that was downloaded, if any. */ - tools_bundle_language?: ToolsDownloadStatusReport["bundleLanguage"]; + tools_bundle_language?: string; /** * Whether we tried to download a single-language bundle, but it did not exist and we fell back to * the combined bundle. */ - tools_per_language_bundle_fallback?: ToolsDownloadStatusReport["perLanguageBundleFallback"]; + tools_per_language_bundle_fallback?: boolean; +} + +/** Fields of the init status report populated when the tools source is `download`. */ +export interface InitToolsDownloadFields extends PerLanguageToolsStatusReport { + /** + * Time taken to download the bundle, in milliseconds. Not populated when the bundle is downloaded + * and extracted concurrently. + */ + tools_download_duration_ms?: number; + /** + * Time taken to extract the bundle, in milliseconds. Not populated when the bundle is downloaded + * and extracted concurrently. + */ + tools_extraction_duration_ms?: number; + /** + * Total time taken to make the bundle available on disk, including failed download attempts + * before a fallback, in milliseconds. + */ + tools_total_duration_ms?: number; + /** + * Whether the relevant tools dotcom feature flags have been misconfigured. + * Only populated if we attempt to determine the default version based on the dotcom feature flags. */ + tools_feature_flags_valid?: boolean; } /** Converts download results to telemetry fields shared by the init and setup-codeql Actions. */ @@ -35,7 +39,7 @@ export function createInitToolsDownloadFields( report: ToolsDownloadStatusReport | undefined, toolsFeatureFlagsValid: boolean | undefined, ): InitToolsDownloadFields { - const fields: InitToolsDownloadFields = {}; + const fields: InitToolsDownloadFields = { ...report?.perLanguage }; if (report?.downloadDurationMs !== undefined) { fields.tools_download_duration_ms = report.downloadDurationMs; } @@ -45,13 +49,6 @@ export function createInitToolsDownloadFields( if (report?.totalDurationMs !== undefined) { fields.tools_total_duration_ms = report.totalDurationMs; } - if (report?.bundleLanguage !== undefined) { - fields.tools_bundle_language = report.bundleLanguage; - } - if (report?.perLanguageBundleFallback !== undefined) { - fields.tools_per_language_bundle_fallback = - report.perLanguageBundleFallback; - } if (toolsFeatureFlagsValid !== undefined) { fields.tools_feature_flags_valid = toolsFeatureFlagsValid; } diff --git a/src/tools-download.ts b/src/tools-download.ts index 61501557c..a92dad0ac 100644 --- a/src/tools-download.ts +++ b/src/tools-download.ts @@ -13,6 +13,7 @@ import * as semver from "semver"; import { ActionState } from "./action-common"; import { ActionsEnvVars, getEnv, ReadOnlyEnv } from "./environment"; import { formatDuration, Logger } from "./logging"; +import type { PerLanguageToolsStatusReport } from "./status-report/tools-download"; import * as tar from "./tar"; import { asHTTPError, @@ -55,13 +56,7 @@ export type ToolsDownloadStatusReport = { * before a fallback, in milliseconds. */ totalDurationMs: number; - /** The language of the single-language bundle that was downloaded, if any. */ - bundleLanguage?: string; - /** - * Whether we tried to download a single-language bundle, but it did not exist and we fell back to - * the combined bundle. - */ - perLanguageBundleFallback?: boolean; + perLanguage?: PerLanguageToolsStatusReport; }; export async function downloadAndExtract(