From f42df5b5c1f951934a54e79fb18d88601e9b9f62 Mon Sep 17 00:00:00 2001 From: Henry Mercer Date: Wed, 23 Sep 2026 19:15:14 +0100 Subject: [PATCH 1/2] Move bundle types and helpers out of setup-codeql.ts Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --- lib/entry-points.js | 51 ++++++++++++++++--------------- src/codeql-bundle.ts | 38 +++++++++++++++++++++++ src/per-language-bundles.ts | 13 ++++++++ src/setup-codeql.ts | 60 +++++++++---------------------------- 4 files changed, 90 insertions(+), 72 deletions(-) diff --git a/lib/entry-points.js b/lib/entry-points.js index e89c2ab073..ca89d15812 100644 --- a/lib/entry-points.js +++ b/lib/entry-points.js @@ -151206,6 +151206,20 @@ var import_fast_deep_equal = __toESM(require_fast_deep_equal()); var semver10 = __toESM(require_semver2()); // src/codeql-bundle.ts +function getCodeQLBundleName(compressionMethod, platform2, language) { + const extensions = { + gzip: ".tar.gz", + zstd: ".tar.zst" + }; + const extension = extensions[compressionMethod]; + if (platform2 === void 0) { + return `codeql-bundle${extension}`; + } + if (language !== void 0) { + return `codeql-bundle-${language}-${platform2}${extension}`; + } + return `codeql-bundle-${platform2}${extension}`; +} var PER_LANGUAGE_BUNDLE_NAME = /^codeql-bundle-(.+)-(?:linux64|osx64|win64)\.tar\.(?:gz|zst)$/; function getCodeQLBundleFromUrl(url2) { let assetName; @@ -151607,6 +151621,11 @@ async function getPerLanguageBundleLanguage({ } return language; } +function logPerLanguageBundleFallback({ logger }, language, location) { + logger.warning( + `No per-language CodeQL bundle for '${language}' was found at ${location}, so falling back to the bundle that contains all languages. This analysis will still produce correct results, but will take longer to set up.` + ); +} // src/tar.ts var import_child_process = require("child_process"); @@ -152005,26 +152024,8 @@ var CODEQL_NIGHTLIES_REPOSITORY_NAME = "codeql-cli-nightlies"; var CODEQL_BUNDLE_VERSION_ALIAS = ["linked", "latest"]; var CODEQL_NIGHTLY_TOOLS_INPUTS = ["nightly", "nightly-latest"]; var CODEQL_TOOLCACHE_INPUT = "toolcache"; -function getCodeQLBundleExtension(compressionMethod) { - switch (compressionMethod) { - case "gzip": - return ".tar.gz"; - case "zstd": - return ".tar.zst"; - default: - assertNever(compressionMethod); - } -} -function getCodeQLBundleName(compressionMethod, language) { - const extension = getCodeQLBundleExtension(compressionMethod); - const platform2 = getBundlePlatform(); - if (platform2 === void 0) { - return `codeql-bundle${extension}`; - } - if (language !== void 0) { - return `codeql-bundle-${language}-${platform2}${extension}`; - } - return `codeql-bundle-${platform2}${extension}`; +function getCodeQLBundleName2(compressionMethod, language) { + return getCodeQLBundleName(compressionMethod, getBundlePlatform(), language); } function getCodeQLActionRepository(logger) { if (isRunningLocalAction()) { @@ -152447,7 +152448,7 @@ async function getCodeQLSource(toolsInput, defaultCliVersion, rawLanguages, useO const resolveBundleURL = (language) => getCodeQLBundleDownloadURL( bundleTagName, apiDetails, - getCodeQLBundleName(compressionMethod, language), + getCodeQLBundleName2(compressionMethod, language), logger ); const combinedBundleURL = await resolveBundleURL(); @@ -152680,9 +152681,7 @@ async function downloadCodeQLBundle(action, source, apiDetails, tarVersion, temp if (bundle.kind !== "per-language" || bundle.combinedBundleURL === void 0 || asHTTPError(e)?.status !== 404) { throw e; } - logger.warning( - `No per-language CodeQL bundle for '${bundle.language}' was found at ${bundle.url}, so falling back to the bundle that contains all languages. This analysis will still produce correct results, but will take longer to set up.` - ); + logPerLanguageBundleFallback(action, bundle.language, bundle.url); const result = await downloadCodeQL( { ...source, @@ -152740,12 +152739,12 @@ async function getLatestNightlyBundle(action, rawLanguages, variant) { throw new Error("Could not find the latest nightly release."); } const assetUrl = (name) => `https://github.com/${CODEQL_NIGHTLIES_REPOSITORY_OWNER}/${CODEQL_NIGHTLIES_REPOSITORY_NAME}/releases/download/${latestRelease.tag_name}/${name}`; - const url2 = assetUrl(getCodeQLBundleName(compressionMethod, language)); + const url2 = assetUrl(getCodeQLBundleName2(compressionMethod, language)); return language === void 0 ? { kind: "combined", url: url2 } : { kind: "per-language", url: url2, language, - combinedBundleURL: assetUrl(getCodeQLBundleName(compressionMethod)) + combinedBundleURL: assetUrl(getCodeQLBundleName2(compressionMethod)) }; } catch (e) { throw new Error( diff --git a/src/codeql-bundle.ts b/src/codeql-bundle.ts index 4e9f5d5de1..2d262c848e 100644 --- a/src/codeql-bundle.ts +++ b/src/codeql-bundle.ts @@ -1,4 +1,6 @@ import { BuiltInLanguage, parseBuiltInLanguage } from "./languages"; +import { BundlePlatform } from "./platform"; +import type { CompressionMethod } from "./tar"; /** Describes the contents and location of a downloadable CodeQL bundle. */ export type CodeQLBundle = @@ -11,6 +13,42 @@ export type CodeQLBundle = combinedBundleURL?: string; }; +/** A resolved download, including its bundle identity and version. */ +export interface CodeQLDownloadSource { + /** Distinguishes downloads from local archives and cached installations. */ + sourceType: "download"; + /** The bundle to download. */ + bundle: CodeQLBundle; + /** The compression format of the bundle archive. */ + compressionMethod: CompressionMethod; + /** Bundle version of the tools, if known. */ + bundleVersion?: string; + /** Requested CLI version, if known. */ + cliVersion?: string; + /** Resolved version for telemetry, independent of whether the bundle can be cached. */ + toolsVersion: string; +} + +/** Returns the exact bundle asset name for a platform and optional language. */ +export function getCodeQLBundleName( + compressionMethod: CompressionMethod, + platform: BundlePlatform | undefined, + language?: BuiltInLanguage, +): string { + const extensions: Record = { + gzip: ".tar.gz", + zstd: ".tar.zst", + }; + const extension = extensions[compressionMethod]; + if (platform === undefined) { + return `codeql-bundle${extension}`; + } + if (language !== undefined) { + return `codeql-bundle-${language}-${platform}${extension}`; + } + return `codeql-bundle-${platform}${extension}`; +} + const PER_LANGUAGE_BUNDLE_NAME = /^codeql-bundle-(.+)-(?:linux64|osx64|win64)\.tar\.(?:gz|zst)$/; diff --git a/src/per-language-bundles.ts b/src/per-language-bundles.ts index e4468d2f34..e0db649c7a 100644 --- a/src/per-language-bundles.ts +++ b/src/per-language-bundles.ts @@ -131,3 +131,16 @@ export async function getPerLanguageBundleLanguage( return language; } + +/** Explains why an eligible per-language bundle is being replaced by a combined bundle. */ +export function logPerLanguageBundleFallback( + { logger }: ActionState<["Logger"]>, + language: BuiltInLanguage, + location: string, +): void { + logger.warning( + `No per-language CodeQL bundle for '${language}' was found at ${location}, so ` + + "falling back to the bundle that contains all languages. This analysis will still " + + "produce correct results, but will take longer to set up.", + ); +} diff --git a/src/setup-codeql.ts b/src/setup-codeql.ts index 648435d805..58f37d6388 100644 --- a/src/setup-codeql.ts +++ b/src/setup-codeql.ts @@ -17,7 +17,12 @@ import { isRunningLocalAction, } from "./actions-util"; import * as api from "./api-client"; -import { CodeQLBundle, getCodeQLBundleFromUrl } from "./codeql-bundle"; +import { + CodeQLBundle, + CodeQLDownloadSource, + getCodeQLBundleFromUrl, + getCodeQLBundleName as getBundleName, +} from "./codeql-bundle"; import * as defaults from "./defaults.json"; import { addNoLanguageDiagnostic, @@ -35,7 +40,10 @@ import { import { BuiltInLanguage } from "./languages"; import { Logger } from "./logging"; import { getCodeQlVersionsForOverlayBaseDatabases } from "./overlay/caching"; -import { getPerLanguageBundleLanguage } from "./per-language-bundles"; +import { + getPerLanguageBundleLanguage, + logPerLanguageBundleFallback, +} from "./per-language-bundles"; import { getBundlePlatform } from "./platform"; import * as tar from "./tar"; import { @@ -49,6 +57,8 @@ import { import * as util from "./util"; import { isGoodVersion } from "./util"; +export type { CodeQLDownloadSource } from "./codeql-bundle"; + export enum ToolsSource { Unknown = "UNKNOWN", Local = "LOCAL", @@ -64,19 +74,6 @@ const CODEQL_BUNDLE_VERSION_ALIAS: string[] = ["linked", "latest"]; const CODEQL_NIGHTLY_TOOLS_INPUTS = ["nightly", "nightly-latest"]; const CODEQL_TOOLCACHE_INPUT = "toolcache"; -function getCodeQLBundleExtension( - compressionMethod: tar.CompressionMethod, -): string { - switch (compressionMethod) { - case "gzip": - return ".tar.gz"; - case "zstd": - return ".tar.zst"; - default: - util.assertNever(compressionMethod); - } -} - /** * Returns the name of the CodeQL bundle asset to download. * @@ -87,16 +84,7 @@ export function getCodeQLBundleName( compressionMethod: tar.CompressionMethod, language?: BuiltInLanguage, ): string { - const extension = getCodeQLBundleExtension(compressionMethod); - const platform = getBundlePlatform(); - - if (platform === undefined) { - return `codeql-bundle${extension}`; - } - if (language !== undefined) { - return `codeql-bundle-${language}-${platform}${extension}`; - } - return `codeql-bundle-${platform}${extension}`; + return getBundleName(compressionMethod, getBundlePlatform(), language); } export function getCodeQLActionRepository(logger: Logger): string { @@ -223,22 +211,6 @@ export function convertToSemVer(version: string, logger: Logger): string { return s; } -/** A resolved download, including its bundle identity and version. */ -export interface CodeQLDownloadSource { - /** Distinguishes downloads from local archives and cached installations. */ - sourceType: "download"; - /** The bundle to download. */ - bundle: CodeQLBundle; - /** The compression format of the bundle archive. */ - compressionMethod: tar.CompressionMethod; - /** Bundle version of the tools, if known. */ - bundleVersion?: string; - /** Requested CLI version, if known. */ - cliVersion?: string; - /** Resolved version for telemetry, independent of whether the bundle can be cached. */ - toolsVersion: string; -} - export type CodeQLToolsSource = | { codeqlTarPath: string; @@ -1153,11 +1125,7 @@ export async function downloadCodeQLBundle( ) { throw e; } - logger.warning( - `No per-language CodeQL bundle for '${bundle.language}' was found at ${bundle.url}, so ` + - "falling back to the bundle that contains all languages. This analysis will still " + - "produce correct results, but will take longer to set up.", - ); + logPerLanguageBundleFallback(action, bundle.language, bundle.url); const result = await downloadCodeQL( { From 6aa6d5553a5bc4773e2cc41709554a6957e20924 Mon Sep 17 00:00:00 2001 From: Henry Mercer Date: Thu, 24 Sep 2026 10:09:24 +0100 Subject: [PATCH 2/2] Remove the getCodeQLBundleName wrapper from setup-codeql.ts Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --- lib/entry-points.js | 19 +++++++++++-------- src/codeql-bundle.test.ts | 21 ++++++++++++++++++++- src/setup-codeql.test.ts | 28 ++-------------------------- src/setup-codeql.ts | 31 ++++++++++++------------------- 4 files changed, 45 insertions(+), 54 deletions(-) diff --git a/lib/entry-points.js b/lib/entry-points.js index ca89d15812..a6590f0bd7 100644 --- a/lib/entry-points.js +++ b/lib/entry-points.js @@ -152024,9 +152024,6 @@ var CODEQL_NIGHTLIES_REPOSITORY_NAME = "codeql-cli-nightlies"; var CODEQL_BUNDLE_VERSION_ALIAS = ["linked", "latest"]; var CODEQL_NIGHTLY_TOOLS_INPUTS = ["nightly", "nightly-latest"]; var CODEQL_TOOLCACHE_INPUT = "toolcache"; -function getCodeQLBundleName2(compressionMethod, language) { - return getCodeQLBundleName(compressionMethod, getBundlePlatform(), language); -} function getCodeQLActionRepository(logger) { if (isRunningLocalAction()) { logger.info( @@ -152435,20 +152432,21 @@ async function getCodeQLSource(toolsInput, defaultCliVersion, rawLanguages, useO ); } compressionMethod = cliVersion2 !== void 0 && await useZstdBundle(cliVersion2, tarSupportsZstd) ? "zstd" : "gzip"; + const platform2 = getBundlePlatform(); const perLanguageBundleLanguage = await getPerLanguageBundleLanguage( { env: getEnv(), features, logger }, { rawLanguages, cliVersion: cliVersion2, compressionMethod, - platform: getBundlePlatform(), + platform: platform2, variant } ); const resolveBundleURL = (language) => getCodeQLBundleDownloadURL( bundleTagName, apiDetails, - getCodeQLBundleName2(compressionMethod, language), + getCodeQLBundleName(compressionMethod, platform2, language), logger ); const combinedBundleURL = await resolveBundleURL(); @@ -152718,11 +152716,12 @@ async function getLatestNightlyBundle(action, rawLanguages, variant) { CODEQL_VERSION_ZSTD_BUNDLE, zstdAvailability.available ) ? "zstd" : "gzip"; + const platform2 = getBundlePlatform(); const language = await getPerLanguageBundleLanguage(action, { rawLanguages, cliVersion: void 0, compressionMethod, - platform: getBundlePlatform(), + platform: platform2, variant, isLatestNightly: true }); @@ -152739,12 +152738,16 @@ async function getLatestNightlyBundle(action, rawLanguages, variant) { throw new Error("Could not find the latest nightly release."); } const assetUrl = (name) => `https://github.com/${CODEQL_NIGHTLIES_REPOSITORY_OWNER}/${CODEQL_NIGHTLIES_REPOSITORY_NAME}/releases/download/${latestRelease.tag_name}/${name}`; - const url2 = assetUrl(getCodeQLBundleName2(compressionMethod, language)); + const url2 = assetUrl( + getCodeQLBundleName(compressionMethod, platform2, language) + ); return language === void 0 ? { kind: "combined", url: url2 } : { kind: "per-language", url: url2, language, - combinedBundleURL: assetUrl(getCodeQLBundleName2(compressionMethod)) + combinedBundleURL: assetUrl( + getCodeQLBundleName(compressionMethod, platform2) + ) }; } catch (e) { throw new Error( diff --git a/src/codeql-bundle.test.ts b/src/codeql-bundle.test.ts index 1014043eab..e528ee76fd 100644 --- a/src/codeql-bundle.test.ts +++ b/src/codeql-bundle.test.ts @@ -1,7 +1,26 @@ import test from "ava"; -import { getCodeQLBundleFromUrl } from "./codeql-bundle"; +import { getCodeQLBundleFromUrl, getCodeQLBundleName } from "./codeql-bundle"; import { BuiltInLanguage } from "./languages"; +import { BundlePlatform } from "./platform"; + +test("getCodeQLBundleName returns a per-language bundle name only when a language is specified", (t) => { + t.is( + getCodeQLBundleName("zstd", BundlePlatform.Linux64, BuiltInLanguage.java), + "codeql-bundle-java-linux64.tar.zst", + ); + t.is( + getCodeQLBundleName("zstd", BundlePlatform.Linux64), + "codeql-bundle-linux64.tar.zst", + ); +}); + +test("getCodeQLBundleName names the Swift bundle for macOS", (t) => { + t.is( + getCodeQLBundleName("zstd", BundlePlatform.Osx64, BuiltInLanguage.swift), + "codeql-bundle-swift-osx64.tar.zst", + ); +}); for (const [assetName, language] of [ ["codeql-bundle-java-linux64.tar.zst", BuiltInLanguage.java], diff --git a/src/setup-codeql.test.ts b/src/setup-codeql.test.ts index 6ac5bebf18..c33ac0700a 100644 --- a/src/setup-codeql.test.ts +++ b/src/setup-codeql.test.ts @@ -435,7 +435,7 @@ test.serial( // Check that the `CodeQLToolsSource` object matches our expectations. const expectedVersion = `0.0.0-${expectedDate}`; - const expectedURL = `https://github.com/dsp-testing/codeql-cli-nightlies/releases/download/${expectedTag}/${setupCodeql.getCodeQLBundleName("zstd")}`; + const expectedURL = `https://github.com/dsp-testing/codeql-cli-nightlies/releases/download/${expectedTag}/codeql-bundle-linux64.tar.zst`; t.deepEqual(source, { bundle: { kind: "combined", url: expectedURL }, bundleVersion: expectedDate, @@ -505,7 +505,7 @@ test.serial( // Check that the `CodeQLToolsSource` object matches our expectations. const expectedVersion = `0.0.0-${expectedDate}`; - const expectedURL = `https://github.com/dsp-testing/codeql-cli-nightlies/releases/download/${expectedTag}/${setupCodeql.getCodeQLBundleName("zstd")}`; + const expectedURL = `https://github.com/dsp-testing/codeql-cli-nightlies/releases/download/${expectedTag}/codeql-bundle-linux64.tar.zst`; t.deepEqual(source, { bundle: { kind: "combined", url: expectedURL }, bundleVersion: expectedDate, @@ -1143,30 +1143,6 @@ const PER_LANGUAGE_CLI_VERSION = { ], }; -test.serial( - "getCodeQLBundleName returns a per-language bundle name only when a language is specified", - (t) => { - sinon.stub(process, "platform").value("linux"); - sinon.stub(process, "arch").value("x64"); - t.is( - setupCodeql.getCodeQLBundleName("zstd", BuiltInLanguage.java), - "codeql-bundle-java-linux64.tar.zst", - ); - t.is( - setupCodeql.getCodeQLBundleName("zstd"), - "codeql-bundle-linux64.tar.zst", - ); - }, -); - -test.serial("getCodeQLBundleName names the Swift bundle for macOS", (t) => { - sinon.stub(process, "platform").value("darwin"); - t.is( - setupCodeql.getCodeQLBundleName("zstd", BuiltInLanguage.swift), - "codeql-bundle-swift-osx64.tar.zst", - ); -}); - test.serial( "getCodeQLSource downloads the per-language bundle for a single explicit language", async (t) => { diff --git a/src/setup-codeql.ts b/src/setup-codeql.ts index 58f37d6388..d306d40d63 100644 --- a/src/setup-codeql.ts +++ b/src/setup-codeql.ts @@ -21,7 +21,7 @@ import { CodeQLBundle, CodeQLDownloadSource, getCodeQLBundleFromUrl, - getCodeQLBundleName as getBundleName, + getCodeQLBundleName, } from "./codeql-bundle"; import * as defaults from "./defaults.json"; import { @@ -74,19 +74,6 @@ const CODEQL_BUNDLE_VERSION_ALIAS: string[] = ["linked", "latest"]; const CODEQL_NIGHTLY_TOOLS_INPUTS = ["nightly", "nightly-latest"]; const CODEQL_TOOLCACHE_INPUT = "toolcache"; -/** - * Returns the name of the CodeQL bundle asset to download. - * - * @param compressionMethod The compression method of the bundle. - * @param language Optional language for a per-language bundle. If omitted, returns a combined bundle name. - */ -export function getCodeQLBundleName( - compressionMethod: tar.CompressionMethod, - language?: BuiltInLanguage, -): string { - return getBundleName(compressionMethod, getBundlePlatform(), language); -} - export function getCodeQLActionRepository(logger: Logger): string { if (isRunningLocalAction()) { // This handles the case where the Action does not come from an Action repository, @@ -729,13 +716,14 @@ export async function getCodeQLSource( ? "zstd" : "gzip"; + const platform = getBundlePlatform(); const perLanguageBundleLanguage = await getPerLanguageBundleLanguage( { env: getEnv(), features, logger }, { rawLanguages, cliVersion, compressionMethod, - platform: getBundlePlatform(), + platform, variant, }, ); @@ -745,7 +733,7 @@ export async function getCodeQLSource( getCodeQLBundleDownloadURL( bundleTagName, apiDetails, - getCodeQLBundleName(compressionMethod, language), + getCodeQLBundleName(compressionMethod, platform, language), logger, ); @@ -1183,11 +1171,12 @@ async function getLatestNightlyBundle( ? "zstd" : "gzip"; + const platform = getBundlePlatform(); const language = await getPerLanguageBundleLanguage(action, { rawLanguages, cliVersion: undefined, compressionMethod, - platform: getBundlePlatform(), + platform, variant, isLatestNightly: true, }); @@ -1209,14 +1198,18 @@ async function getLatestNightlyBundle( } const assetUrl = (name: string) => `https://github.com/${CODEQL_NIGHTLIES_REPOSITORY_OWNER}/${CODEQL_NIGHTLIES_REPOSITORY_NAME}/releases/download/${latestRelease.tag_name}/${name}`; - const url = assetUrl(getCodeQLBundleName(compressionMethod, language)); + const url = assetUrl( + getCodeQLBundleName(compressionMethod, platform, language), + ); return language === undefined ? { kind: "combined", url } : { kind: "per-language", url, language, - combinedBundleURL: assetUrl(getCodeQLBundleName(compressionMethod)), + combinedBundleURL: assetUrl( + getCodeQLBundleName(compressionMethod, platform), + ), }; } catch (e) { throw new Error(