Clarify resolved bundle handling

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
Henry Mercer
2026-09-16 12:16:13 +01:00
parent 1970c450ec
commit f3e0c870be
3 changed files with 84 additions and 25 deletions

27
lib/entry-points.js generated
View File

@@ -151967,7 +151967,7 @@ async function getCodeQLBundleDownloadURL(tagName, apiDetails, compressionMethod
return `https://github.com/${CODEQL_DEFAULT_ACTION_REPOSITORY}/releases/download/${tagName}/${codeQLBundleName}`;
}
function tryGetBundleVersionFromTagName(tagName, logger) {
const match2 = tagName.match(/^codeql-bundle-(.*)$/);
const match2 = tagName.match(/^codeql-bundle-(.+)$/);
if (match2 === null || match2.length < 2) {
logger.debug(`Could not determine bundle version from tag ${tagName}.`);
return void 0;
@@ -152207,7 +152207,7 @@ async function getCodeQLSource(toolsInput, defaultCliVersion, rawLanguages, useO
url2 = toolsInput;
if (tagName) {
const bundleVersion3 = tryGetBundleVersionFromTagName(tagName, logger);
if (bundleVersion3 && semver9.valid(bundleVersion3)) {
if (bundleVersion3 !== void 0 && semver9.valid(bundleVersion3)) {
cliVersion2 = convertToSemVer(bundleVersion3, logger);
}
}
@@ -152222,8 +152222,8 @@ async function getCodeQLSource(toolsInput, defaultCliVersion, rawLanguages, useO
cliVersion2 = version.cliVersion;
tagName = version.tagName;
}
const bundleVersion2 = tagName && tryGetBundleVersionFromTagName(tagName, logger);
const resolvedVersion = cliVersion2 ?? (bundleVersion2 ? convertToSemVer(bundleVersion2, logger) : void 0);
const bundleVersion2 = tagName !== void 0 ? tryGetBundleVersionFromTagName(tagName, logger) : void 0;
const resolvedVersion = cliVersion2 ?? (bundleVersion2 !== void 0 ? convertToSemVer(bundleVersion2, logger) : void 0);
const humanReadableVersion = resolvedVersion ?? tagName ?? url2 ?? "unknown";
logger.debug(
`Attempting to obtain CodeQL tools. CLI version: ${cliVersion2 ?? "unknown"}, bundle tag name: ${tagName ?? "unknown"}, URL: ${url2 ?? "unspecified"}.`
@@ -152341,7 +152341,7 @@ async function getCodeQLSource(toolsInput, defaultCliVersion, rawLanguages, useO
}
async function tryGetFallbackToolcacheVersion(cliVersion2, tagName, logger) {
const bundleVersion2 = tryGetBundleVersionFromTagName(tagName, logger);
if (!bundleVersion2) {
if (bundleVersion2 === void 0) {
return void 0;
}
const fallbackVersion = convertToSemVer(bundleVersion2, logger);
@@ -152473,12 +152473,11 @@ async function setupCodeQLBundle(toolsInput, apiDetails, tempDir, variant, defau
break;
case "download": {
const result = await downloadCodeQLBundle(
{ env: getEnv(), features, logger },
source,
apiDetails,
zstdAvailability.version,
tempDir,
features,
logger
tempDir
);
codeqlFolder = result.codeqlFolder;
toolsDownloadStatusReport = result.statusReport;
@@ -152496,9 +152495,15 @@ async function setupCodeQLBundle(toolsInput, apiDetails, tempDir, variant, defau
toolsVersion: source.toolsVersion
};
}
async function downloadCodeQLBundle(source, apiDetails, tarVersion, tempDir, features, logger) {
await tryDeleteToolcacheBundles({ env: getEnv(), features, logger });
return await downloadCodeQL(source, apiDetails, tarVersion, tempDir, logger);
async function downloadCodeQLBundle(action, source, apiDetails, tarVersion, tempDir) {
await tryDeleteToolcacheBundles(action);
return await downloadCodeQL(
source,
apiDetails,
tarVersion,
tempDir,
action.logger
);
}
async function useZstdBundle(cliVersion2, tarSupportsZstd) {
return (

View File

@@ -10,7 +10,7 @@ import * as sinon from "sinon";
import * as actionsUtil from "./actions-util";
import * as api from "./api-client";
import * as diagnostics from "./diagnostics";
import { ActionsEnvVars, EnvVar, ReadOnlyEnv } from "./environment";
import { ActionsEnvVars, EnvVar, getEnv, ReadOnlyEnv } from "./environment";
import { Feature } from "./feature-flags";
import { getRunnerLogger } from "./logging";
import { getCacheRestoreKeyPrefix } from "./overlay/caching";
@@ -25,6 +25,7 @@ import {
createFeatures,
createTestConfig,
getRecordingLogger,
getTestEnv,
makeMacro,
mockBundleDownloadApi,
setupActionsVars,
@@ -537,6 +538,7 @@ for (const bundlePath of [
t.true(extractStub.calledOnce);
t.is(extractStub.firstCall.args[0], url);
t.is(downloadSpy.firstCall.args[0].bundleVersion, undefined);
t.is(downloadSpy.firstCall.args[0].toolsVersion, "unknown");
t.is(result.toolsVersion, "unknown");
t.is(result.toolsSource, setupCodeql.ToolsSource.Download);
@@ -1094,6 +1096,7 @@ async function runDownloadCodeQL(
toolcacheRoot: string,
features: Feature[],
bundleVersion: string | undefined,
env: ReadOnlyEnv = getEnv(),
): Promise<{
codeqlFolder: string;
cleanupDiagnostic: toolsDownload.ToolcacheCleanupResult | undefined;
@@ -1102,6 +1105,11 @@ async function runDownloadCodeQL(
const addDiagnostic = sinon.stub(diagnostics, "addNoLanguageDiagnostic");
const { codeqlFolder } = await setupCodeql.downloadCodeQLBundle(
{
env,
features: createFeatures(features),
logger: getRunnerLogger(true),
},
{
bundle: {
kind: "combined",
@@ -1116,8 +1124,6 @@ async function runDownloadCodeQL(
SAMPLE_DOTCOM_API_DETAILS,
undefined, // tarVersion
toolcacheRoot, // tempDir
createFeatures(features),
getRunnerLogger(true),
);
const diagnostic = addDiagnostic
@@ -1484,6 +1490,33 @@ test.serial(
},
);
test.serial(
"downloadCodeQLBundle checks the supplied environment before cleaning the toolcache",
async (t) => {
await withTmpDir(async (tmpDir) => {
setupActionsVars(tmpDir, tmpDir);
process.env[ActionsEnvVars.RUNNER_ENVIRONMENT] = "github-hosted";
delete process.env[EnvVar.HAS_SET_UP_CODEQL];
const staleDirectory = createToolcacheEntry(
tmpDir,
"CodeQL",
CLEANUP_STALE_VERSION,
);
const { codeqlFolder, cleanupDiagnostic } = await runDownloadCodeQL(
tmpDir,
[Feature.CleanupToolcacheBundles],
CLEANUP_BUNDLE_VERSION,
getTestEnv({ [EnvVar.HAS_SET_UP_CODEQL]: "true" }),
);
t.true(fs.existsSync(staleDirectory));
t.true(fs.existsSync(`${codeqlFolder}.complete`));
t.is(cleanupDiagnostic, undefined);
});
},
);
test.serial(
"setupCodeQLBundle records that this job has set up CodeQL",
async (t) => {

View File

@@ -164,7 +164,7 @@ function tryGetBundleVersionFromTagName(
tagName: string,
logger: Logger,
): string | undefined {
const match = tagName.match(/^codeql-bundle-(.*)$/);
const match = tagName.match(/^codeql-bundle-(.+)$/);
if (match === null || match.length < 2) {
logger.debug(`Could not determine bundle version from tag ${tagName}.`);
return undefined;
@@ -215,12 +215,16 @@ export function convertToSemVer(version: string, logger: Logger): string {
return s;
}
/** Describes the contents and location of a downloadable CodeQL bundle. */
type CodeQLBundle = { kind: "combined"; url: 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: tar.CompressionMethod;
/** Bundle version of the tools, if known. */
bundleVersion?: string;
@@ -588,7 +592,7 @@ export async function getCodeQLSource(
if (tagName) {
const bundleVersion = tryGetBundleVersionFromTagName(tagName, logger);
// If the bundle version is a semantic version, it is a CLI version number.
if (bundleVersion && semver.valid(bundleVersion)) {
if (bundleVersion !== undefined && semver.valid(bundleVersion)) {
cliVersion = convertToSemVer(bundleVersion, logger);
}
}
@@ -605,10 +609,14 @@ export async function getCodeQLSource(
}
const bundleVersion =
tagName && tryGetBundleVersionFromTagName(tagName, logger);
tagName !== undefined
? tryGetBundleVersionFromTagName(tagName, logger)
: undefined;
const resolvedVersion =
cliVersion ??
(bundleVersion ? convertToSemVer(bundleVersion, logger) : undefined);
(bundleVersion !== undefined
? convertToSemVer(bundleVersion, logger)
: undefined);
const humanReadableVersion = resolvedVersion ?? tagName ?? url ?? "unknown";
logger.debug(
@@ -772,7 +780,7 @@ async function tryGetFallbackToolcacheVersion(
logger: Logger,
): Promise<string | undefined> {
const bundleVersion = tryGetBundleVersionFromTagName(tagName, logger);
if (!bundleVersion) {
if (bundleVersion === undefined) {
return undefined;
}
const fallbackVersion = convertToSemVer(bundleVersion, logger);
@@ -844,6 +852,10 @@ export const downloadCodeQL = async function (
};
};
/**
* Returns the canonical toolcache directory for a resolved download, or `undefined` if its bundle
* version is unknown.
*/
function getToolcacheDestination(
source: CodeQLDownloadSource,
logger: Logger,
@@ -1004,12 +1016,11 @@ export async function setupCodeQLBundle(
break;
case "download": {
const result = await downloadCodeQLBundle(
{ env: getEnv(), features, logger },
source,
apiDetails,
zstdAvailability.version,
tempDir,
features,
logger,
);
codeqlFolder = result.codeqlFolder;
toolsDownloadStatusReport = result.statusReport;
@@ -1032,19 +1043,29 @@ export async function setupCodeQLBundle(
};
}
/**
* Performs eligible toolcache cleanup once, then downloads and extracts the resolved bundle.
*
* @returns The extraction directory and download timings.
*/
export async function downloadCodeQLBundle(
action: ActionState<["Logger", "ReadOnlyEnv", "FeatureFlags"]>,
source: CodeQLDownloadSource,
apiDetails: api.GitHubApiDetails,
tarVersion: tar.TarVersion | undefined,
tempDir: string,
features: FeatureEnablement,
logger: Logger,
): Promise<{
codeqlFolder: string;
statusReport: ToolsDownloadStatusReport;
}> {
await tryDeleteToolcacheBundles({ env: getEnv(), features, logger });
return await downloadCodeQL(source, apiDetails, tarVersion, tempDir, logger);
await tryDeleteToolcacheBundles(action);
return await downloadCodeQL(
source,
apiDetails,
tarVersion,
tempDir,
action.logger,
);
}
async function useZstdBundle(