mirror of
https://github.com/github/codeql-action.git
synced 2026-10-03 17:41:28 +00:00
Merge pull request #4145 from github/henrymercer/bundle-resolution-pr
Separate CodeQL bundle resolution from installation
This commit is contained in:
91
lib/entry-points.js
generated
91
lib/entry-points.js
generated
@@ -151967,7 +151967,7 @@ async function getCodeQLBundleDownloadURL(tagName, apiDetails, compressionMethod
|
|||||||
return `https://github.com/${CODEQL_DEFAULT_ACTION_REPOSITORY}/releases/download/${tagName}/${codeQLBundleName}`;
|
return `https://github.com/${CODEQL_DEFAULT_ACTION_REPOSITORY}/releases/download/${tagName}/${codeQLBundleName}`;
|
||||||
}
|
}
|
||||||
function tryGetBundleVersionFromTagName(tagName, logger) {
|
function tryGetBundleVersionFromTagName(tagName, logger) {
|
||||||
const match2 = tagName.match(/^codeql-bundle-(.*)$/);
|
const match2 = tagName.match(/^codeql-bundle-(.+)$/);
|
||||||
if (match2 === null || match2.length < 2) {
|
if (match2 === null || match2.length < 2) {
|
||||||
logger.debug(`Could not determine bundle version from tag ${tagName}.`);
|
logger.debug(`Could not determine bundle version from tag ${tagName}.`);
|
||||||
return void 0;
|
return void 0;
|
||||||
@@ -152207,7 +152207,7 @@ async function getCodeQLSource(toolsInput, defaultCliVersion, rawLanguages, useO
|
|||||||
url2 = toolsInput;
|
url2 = toolsInput;
|
||||||
if (tagName) {
|
if (tagName) {
|
||||||
const bundleVersion3 = tryGetBundleVersionFromTagName(tagName, logger);
|
const bundleVersion3 = tryGetBundleVersionFromTagName(tagName, logger);
|
||||||
if (bundleVersion3 && semver9.valid(bundleVersion3)) {
|
if (bundleVersion3 !== void 0 && semver9.valid(bundleVersion3)) {
|
||||||
cliVersion2 = convertToSemVer(bundleVersion3, logger);
|
cliVersion2 = convertToSemVer(bundleVersion3, logger);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -152222,8 +152222,9 @@ async function getCodeQLSource(toolsInput, defaultCliVersion, rawLanguages, useO
|
|||||||
cliVersion2 = version.cliVersion;
|
cliVersion2 = version.cliVersion;
|
||||||
tagName = version.tagName;
|
tagName = version.tagName;
|
||||||
}
|
}
|
||||||
const bundleVersion2 = tagName && tryGetBundleVersionFromTagName(tagName, logger);
|
const bundleVersion2 = tagName !== void 0 ? tryGetBundleVersionFromTagName(tagName, logger) : void 0;
|
||||||
const humanReadableVersion = cliVersion2 ?? (bundleVersion2 && convertToSemVer(bundleVersion2, logger)) ?? tagName ?? url2 ?? "unknown";
|
const resolvedVersion = cliVersion2 ?? (bundleVersion2 !== void 0 ? convertToSemVer(bundleVersion2, logger) : void 0);
|
||||||
|
const humanReadableVersion = resolvedVersion ?? tagName ?? url2 ?? "unknown";
|
||||||
logger.debug(
|
logger.debug(
|
||||||
`Attempting to obtain CodeQL tools. CLI version: ${cliVersion2 ?? "unknown"}, bundle tag name: ${tagName ?? "unknown"}, URL: ${url2 ?? "unspecified"}.`
|
`Attempting to obtain CodeQL tools. CLI version: ${cliVersion2 ?? "unknown"}, bundle tag name: ${tagName ?? "unknown"}, URL: ${url2 ?? "unspecified"}.`
|
||||||
);
|
);
|
||||||
@@ -152330,17 +152331,17 @@ async function getCodeQLSource(toolsInput, defaultCliVersion, rawLanguages, useO
|
|||||||
logger.info(`Using CodeQL CLI sourced from ${url2} .`);
|
logger.info(`Using CodeQL CLI sourced from ${url2} .`);
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
bundleVersion: tagName && tryGetBundleVersionFromTagName(tagName, logger),
|
bundle: { kind: "combined", url: url2 },
|
||||||
|
bundleVersion: bundleVersion2,
|
||||||
cliVersion: cliVersion2,
|
cliVersion: cliVersion2,
|
||||||
codeqlURL: url2,
|
|
||||||
compressionMethod,
|
compressionMethod,
|
||||||
sourceType: "download",
|
sourceType: "download",
|
||||||
toolsVersion: cliVersion2 ?? humanReadableVersion
|
toolsVersion: resolvedVersion ?? "unknown"
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
async function tryGetFallbackToolcacheVersion(cliVersion2, tagName, logger) {
|
async function tryGetFallbackToolcacheVersion(cliVersion2, tagName, logger) {
|
||||||
const bundleVersion2 = tryGetBundleVersionFromTagName(tagName, logger);
|
const bundleVersion2 = tryGetBundleVersionFromTagName(tagName, logger);
|
||||||
if (!bundleVersion2) {
|
if (bundleVersion2 === void 0) {
|
||||||
return void 0;
|
return void 0;
|
||||||
}
|
}
|
||||||
const fallbackVersion = convertToSemVer(bundleVersion2, logger);
|
const fallbackVersion = convertToSemVer(bundleVersion2, logger);
|
||||||
@@ -152349,7 +152350,9 @@ async function tryGetFallbackToolcacheVersion(cliVersion2, tagName, logger) {
|
|||||||
);
|
);
|
||||||
return fallbackVersion;
|
return fallbackVersion;
|
||||||
}
|
}
|
||||||
var downloadCodeQL = async function(codeqlURL, compressionMethod, maybeBundleVersion, maybeCliVersion, apiDetails, tarVersion, tempDir, features, logger) {
|
var downloadCodeQL = async function(source, apiDetails, tarVersion, tempDir, logger) {
|
||||||
|
const { bundle, compressionMethod } = source;
|
||||||
|
const codeqlURL = bundle.url;
|
||||||
const parsedCodeQLURL = new URL(codeqlURL);
|
const parsedCodeQLURL = new URL(codeqlURL);
|
||||||
const searchParams = new URLSearchParams(parsedCodeQLURL.search);
|
const searchParams = new URLSearchParams(parsedCodeQLURL.search);
|
||||||
const headers = {
|
const headers = {
|
||||||
@@ -152365,13 +152368,8 @@ var downloadCodeQL = async function(codeqlURL, compressionMethod, maybeBundleVer
|
|||||||
codeqlURL
|
codeqlURL
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
const toolcacheInfo = getToolcacheDestinationInfo(
|
const toolcacheDestination = getToolcacheDestination(source, logger);
|
||||||
maybeBundleVersion,
|
const extractedBundlePath = toolcacheDestination ?? getTempExtractionDir(tempDir);
|
||||||
maybeCliVersion,
|
|
||||||
logger
|
|
||||||
);
|
|
||||||
const extractedBundlePath = toolcacheInfo?.path ?? getTempExtractionDir(tempDir);
|
|
||||||
await tryDeleteToolcacheBundles({ env: getEnv(), features, logger });
|
|
||||||
const statusReport = await downloadAndExtract(
|
const statusReport = await downloadAndExtract(
|
||||||
codeqlURL,
|
codeqlURL,
|
||||||
compressionMethod,
|
compressionMethod,
|
||||||
@@ -152381,36 +152379,29 @@ var downloadCodeQL = async function(codeqlURL, compressionMethod, maybeBundleVer
|
|||||||
tarVersion,
|
tarVersion,
|
||||||
logger
|
logger
|
||||||
);
|
);
|
||||||
if (!toolcacheInfo) {
|
if (toolcacheDestination) {
|
||||||
|
writeToolcacheMarkerFile(toolcacheDestination, logger);
|
||||||
|
} else {
|
||||||
logger.debug(
|
logger.debug(
|
||||||
`Could not cache CodeQL tools because we could not determine the bundle version from the URL ${codeqlURL}.`
|
`Could not cache CodeQL tools because we could not determine the bundle version from the URL ${codeqlURL}.`
|
||||||
);
|
);
|
||||||
return {
|
|
||||||
codeqlFolder: extractedBundlePath,
|
|
||||||
statusReport,
|
|
||||||
toolsVersion: maybeCliVersion ?? "unknown"
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
writeToolcacheMarkerFile(toolcacheInfo.path, logger);
|
|
||||||
return {
|
return {
|
||||||
codeqlFolder: extractedBundlePath,
|
codeqlFolder: extractedBundlePath,
|
||||||
statusReport,
|
statusReport
|
||||||
toolsVersion: maybeCliVersion ?? toolcacheInfo.version
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
function getToolcacheDestinationInfo(maybeBundleVersion, maybeCliVersion, logger) {
|
function getToolcacheDestination(source, logger) {
|
||||||
if (maybeBundleVersion) {
|
if (!source.bundleVersion) {
|
||||||
const version = getCanonicalToolcacheVersion(
|
return void 0;
|
||||||
maybeCliVersion,
|
|
||||||
maybeBundleVersion,
|
|
||||||
logger
|
|
||||||
);
|
|
||||||
return {
|
|
||||||
path: getToolcacheDirectory(version),
|
|
||||||
version
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
return void 0;
|
return getToolcacheDirectory(
|
||||||
|
getCanonicalToolcacheVersion(
|
||||||
|
source.cliVersion,
|
||||||
|
source.bundleVersion,
|
||||||
|
logger
|
||||||
|
)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
async function tryDeleteToolcacheBundles({
|
async function tryDeleteToolcacheBundles({
|
||||||
env,
|
env,
|
||||||
@@ -152461,7 +152452,6 @@ async function setupCodeQLBundle(toolsInput, apiDetails, tempDir, variant, defau
|
|||||||
logger
|
logger
|
||||||
);
|
);
|
||||||
let codeqlFolder;
|
let codeqlFolder;
|
||||||
let toolsVersion = source.toolsVersion;
|
|
||||||
let toolsDownloadStatusReport;
|
let toolsDownloadStatusReport;
|
||||||
let toolsSource;
|
let toolsSource;
|
||||||
switch (source.sourceType) {
|
switch (source.sourceType) {
|
||||||
@@ -152482,18 +152472,13 @@ async function setupCodeQLBundle(toolsInput, apiDetails, tempDir, variant, defau
|
|||||||
toolsSource = "TOOLCACHE" /* Toolcache */;
|
toolsSource = "TOOLCACHE" /* Toolcache */;
|
||||||
break;
|
break;
|
||||||
case "download": {
|
case "download": {
|
||||||
const result = await downloadCodeQL(
|
const result = await downloadCodeQLBundle(
|
||||||
source.codeqlURL,
|
{ env: getEnv(), features, logger },
|
||||||
source.compressionMethod,
|
source,
|
||||||
source.bundleVersion,
|
|
||||||
source.cliVersion,
|
|
||||||
apiDetails,
|
apiDetails,
|
||||||
zstdAvailability.version,
|
zstdAvailability.version,
|
||||||
tempDir,
|
tempDir
|
||||||
features,
|
|
||||||
logger
|
|
||||||
);
|
);
|
||||||
toolsVersion = result.toolsVersion;
|
|
||||||
codeqlFolder = result.codeqlFolder;
|
codeqlFolder = result.codeqlFolder;
|
||||||
toolsDownloadStatusReport = result.statusReport;
|
toolsDownloadStatusReport = result.statusReport;
|
||||||
toolsSource = "DOWNLOAD" /* Download */;
|
toolsSource = "DOWNLOAD" /* Download */;
|
||||||
@@ -152507,9 +152492,19 @@ async function setupCodeQLBundle(toolsInput, apiDetails, tempDir, variant, defau
|
|||||||
codeqlFolder,
|
codeqlFolder,
|
||||||
toolsDownloadStatusReport,
|
toolsDownloadStatusReport,
|
||||||
toolsSource,
|
toolsSource,
|
||||||
toolsVersion
|
toolsVersion: source.toolsVersion
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
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) {
|
async function useZstdBundle(cliVersion2, tarSupportsZstd) {
|
||||||
return (
|
return (
|
||||||
// In testing, gzip performs better than zstd on Windows.
|
// In testing, gzip performs better than zstd on Windows.
|
||||||
|
|||||||
@@ -90,7 +90,7 @@ async function installIntoToolcache({
|
|||||||
tmpDir: string;
|
tmpDir: string;
|
||||||
}) {
|
}) {
|
||||||
const url = mockBundleDownloadApi({ apiDetails, isPinned, tagName });
|
const url = mockBundleDownloadApi({ apiDetails, isPinned, tagName });
|
||||||
await codeql.setupCodeQL(
|
return await codeql.setupCodeQL(
|
||||||
cliVersion !== undefined ? undefined : url,
|
cliVersion !== undefined ? undefined : url,
|
||||||
apiDetails,
|
apiDetails,
|
||||||
tmpDir,
|
tmpDir,
|
||||||
@@ -259,6 +259,65 @@ test.serial(
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
for (const { cliVersion, tagName, expectedToolcacheVersion } of [
|
||||||
|
{
|
||||||
|
cliVersion: "2.21.0",
|
||||||
|
tagName: "codeql-bundle-20240101",
|
||||||
|
expectedToolcacheVersion: "2.21.0",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
cliVersion: "2.21.0-rc.1",
|
||||||
|
tagName: "codeql-bundle-20240101",
|
||||||
|
expectedToolcacheVersion: "0.0.0-20240101",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
cliVersion: "2.21.0+20240101",
|
||||||
|
tagName: "codeql-bundle-20240101",
|
||||||
|
expectedToolcacheVersion: "0.0.0-20240101",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
cliVersion: "2.21.0",
|
||||||
|
tagName: "custom-release",
|
||||||
|
expectedToolcacheVersion: undefined,
|
||||||
|
},
|
||||||
|
]) {
|
||||||
|
test.serial(
|
||||||
|
`preserves CLI version ${cliVersion} when installing ${tagName}`,
|
||||||
|
async (t) => {
|
||||||
|
await util.withTmpDir(async (tmpDir) => {
|
||||||
|
setupActionsVars(tmpDir, tmpDir);
|
||||||
|
|
||||||
|
const result = await installIntoToolcache({
|
||||||
|
cliVersion,
|
||||||
|
isPinned: false,
|
||||||
|
tagName,
|
||||||
|
tmpDir,
|
||||||
|
});
|
||||||
|
|
||||||
|
t.is(result.toolsVersion, cliVersion);
|
||||||
|
t.is(result.toolsSource, ToolsSource.Download);
|
||||||
|
t.true(
|
||||||
|
Number.isInteger(result.toolsDownloadStatusReport?.totalDurationMs),
|
||||||
|
);
|
||||||
|
t.deepEqual(
|
||||||
|
toolcache.findAllVersions("CodeQL"),
|
||||||
|
expectedToolcacheVersion === undefined
|
||||||
|
? []
|
||||||
|
: [expectedToolcacheVersion],
|
||||||
|
);
|
||||||
|
if (expectedToolcacheVersion !== undefined) {
|
||||||
|
const cachedFolder = toolcache.find(
|
||||||
|
"CodeQL",
|
||||||
|
expectedToolcacheVersion,
|
||||||
|
);
|
||||||
|
t.truthy(cachedFolder);
|
||||||
|
t.true(fs.existsSync(`${cachedFolder}.complete`));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
const EXPLICITLY_REQUESTED_BUNDLE_TEST_CASES = [
|
const EXPLICITLY_REQUESTED_BUNDLE_TEST_CASES = [
|
||||||
{
|
{
|
||||||
tagName: "codeql-bundle-2.17.6",
|
tagName: "codeql-bundle-2.17.6",
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ import * as sinon from "sinon";
|
|||||||
import * as actionsUtil from "./actions-util";
|
import * as actionsUtil from "./actions-util";
|
||||||
import * as api from "./api-client";
|
import * as api from "./api-client";
|
||||||
import * as diagnostics from "./diagnostics";
|
import * as diagnostics from "./diagnostics";
|
||||||
import { ActionsEnvVars, EnvVar, ReadOnlyEnv } from "./environment";
|
import { ActionsEnvVars, Env, EnvVar, ReadOnlyEnv } from "./environment";
|
||||||
import { Feature } from "./feature-flags";
|
import { Feature } from "./feature-flags";
|
||||||
import { getRunnerLogger } from "./logging";
|
import { getRunnerLogger } from "./logging";
|
||||||
import { getCacheRestoreKeyPrefix } from "./overlay/caching";
|
import { getCacheRestoreKeyPrefix } from "./overlay/caching";
|
||||||
@@ -25,6 +25,8 @@ import {
|
|||||||
createFeatures,
|
createFeatures,
|
||||||
createTestConfig,
|
createTestConfig,
|
||||||
getRecordingLogger,
|
getRecordingLogger,
|
||||||
|
getTestEnv,
|
||||||
|
initAllState,
|
||||||
makeMacro,
|
makeMacro,
|
||||||
mockBundleDownloadApi,
|
mockBundleDownloadApi,
|
||||||
setupActionsVars,
|
setupActionsVars,
|
||||||
@@ -34,6 +36,7 @@ import * as toolsDownload from "./tools-download";
|
|||||||
import {
|
import {
|
||||||
getErrorMessage,
|
getErrorMessage,
|
||||||
GitHubVariant,
|
GitHubVariant,
|
||||||
|
HTTPError,
|
||||||
initializeEnvironment,
|
initializeEnvironment,
|
||||||
withTmpDir,
|
withTmpDir,
|
||||||
} from "./util";
|
} from "./util";
|
||||||
@@ -44,6 +47,15 @@ test.beforeEach(() => {
|
|||||||
initializeEnvironment("1.2.3");
|
initializeEnvironment("1.2.3");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
function stubDownloadAndExtract() {
|
||||||
|
return sinon
|
||||||
|
.stub(toolsDownload, "downloadAndExtract")
|
||||||
|
.callsFake(async (_url, _compressionMethod, dest) => {
|
||||||
|
fs.mkdirSync(dest, { recursive: true });
|
||||||
|
return { downloadDurationMs: 200, totalDurationMs: 300 };
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
test.serial("parse codeql bundle url version", (t) => {
|
test.serial("parse codeql bundle url version", (t) => {
|
||||||
t.deepEqual(
|
t.deepEqual(
|
||||||
setupCodeql.getCodeQLURLVersion(
|
setupCodeql.getCodeQLURLVersion(
|
||||||
@@ -102,9 +114,9 @@ test.serial(
|
|||||||
await withTmpDir(async (tmpDir) => {
|
await withTmpDir(async (tmpDir) => {
|
||||||
setupActionsVars(tmpDir, tmpDir);
|
setupActionsVars(tmpDir, tmpDir);
|
||||||
const tagName = "codeql-bundle-v1.2.3";
|
const tagName = "codeql-bundle-v1.2.3";
|
||||||
mockBundleDownloadApi({ tagName });
|
const url = mockBundleDownloadApi({ tagName });
|
||||||
const source = await setupCodeql.getCodeQLSource(
|
const source = await setupCodeql.getCodeQLSource(
|
||||||
`https://github.com/github/codeql-action/releases/download/${tagName}/codeql-bundle-linux64.tar.gz`,
|
url,
|
||||||
SAMPLE_DEFAULT_CLI_VERSION,
|
SAMPLE_DEFAULT_CLI_VERSION,
|
||||||
undefined, // rawLanguages
|
undefined, // rawLanguages
|
||||||
false, // useOverlayAwareDefaultCliVersion
|
false, // useOverlayAwareDefaultCliVersion
|
||||||
@@ -115,8 +127,14 @@ test.serial(
|
|||||||
getRunnerLogger(true),
|
getRunnerLogger(true),
|
||||||
);
|
);
|
||||||
|
|
||||||
t.is(source.sourceType, "download");
|
t.deepEqual(source, {
|
||||||
t.is(source["cliVersion"], "1.2.3");
|
bundle: { kind: "combined", url },
|
||||||
|
bundleVersion: "v1.2.3",
|
||||||
|
cliVersion: "1.2.3",
|
||||||
|
compressionMethod: "gzip",
|
||||||
|
sourceType: "download",
|
||||||
|
toolsVersion: "1.2.3",
|
||||||
|
} satisfies setupCodeql.CodeQLDownloadSource);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
@@ -198,7 +216,8 @@ for (const {
|
|||||||
t.is(source.sourceType, "download");
|
t.is(source.sourceType, "download");
|
||||||
if (source.sourceType === "download") {
|
if (source.sourceType === "download") {
|
||||||
t.is(source.compressionMethod, expectedCompressionMethod);
|
t.is(source.compressionMethod, expectedCompressionMethod);
|
||||||
t.true(source.codeqlURL.endsWith(`/${expectedBundleName}`));
|
t.is(source.bundle.kind, "combined");
|
||||||
|
t.true(source.bundle.url.endsWith(`/${expectedBundleName}`));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
@@ -252,23 +271,14 @@ test.serial(
|
|||||||
const logger = getRecordingLogger(loggedMessages);
|
const logger = getRecordingLogger(loggedMessages);
|
||||||
const features = createFeatures([]);
|
const features = createFeatures([]);
|
||||||
|
|
||||||
// Stub the downloadCodeQL function to prevent downloading artefacts
|
const extractStub = stubDownloadAndExtract();
|
||||||
// during testing from being called.
|
|
||||||
sinon.stub(setupCodeql, "downloadCodeQL").resolves({
|
|
||||||
codeqlFolder: "codeql",
|
|
||||||
statusReport: {
|
|
||||||
downloadDurationMs: 200,
|
|
||||||
totalDurationMs: 300,
|
|
||||||
},
|
|
||||||
toolsVersion: LINKED_CLI_VERSION.cliVersion,
|
|
||||||
});
|
|
||||||
|
|
||||||
await withTmpDir(async (tmpDir) => {
|
await withTmpDir(async (tmpDir) => {
|
||||||
setupActionsVars(tmpDir, tmpDir);
|
setupActionsVars(tmpDir, tmpDir);
|
||||||
const result = await setupCodeql.setupCodeQLBundle(
|
const result = await setupCodeql.setupCodeQLBundle(
|
||||||
"linked",
|
"linked",
|
||||||
SAMPLE_DOTCOM_API_DETAILS,
|
SAMPLE_DOTCOM_API_DETAILS,
|
||||||
"tmp/codeql_action_test/",
|
tmpDir,
|
||||||
GitHubVariant.DOTCOM,
|
GitHubVariant.DOTCOM,
|
||||||
SAMPLE_DEFAULT_CLI_VERSION,
|
SAMPLE_DEFAULT_CLI_VERSION,
|
||||||
undefined, // rawLanguages
|
undefined, // rawLanguages
|
||||||
@@ -280,6 +290,15 @@ test.serial(
|
|||||||
// Basic sanity check that the version we got back is indeed
|
// Basic sanity check that the version we got back is indeed
|
||||||
// the linked (default) CLI version.
|
// the linked (default) CLI version.
|
||||||
t.is(result.toolsVersion, LINKED_CLI_VERSION.cliVersion);
|
t.is(result.toolsVersion, LINKED_CLI_VERSION.cliVersion);
|
||||||
|
t.true(extractStub.calledOnce);
|
||||||
|
t.is(
|
||||||
|
result.codeqlFolder,
|
||||||
|
toolcache.find("CodeQL", LINKED_CLI_VERSION.cliVersion),
|
||||||
|
);
|
||||||
|
t.deepEqual(result.toolsDownloadStatusReport, {
|
||||||
|
downloadDurationMs: 200,
|
||||||
|
totalDurationMs: 300,
|
||||||
|
});
|
||||||
|
|
||||||
// Ensure message logging CodeQL CLI version was present in user logs.
|
// Ensure message logging CodeQL CLI version was present in user logs.
|
||||||
const expected_message: string = `Using CodeQL CLI version ${LINKED_CLI_VERSION.cliVersion}`;
|
const expected_message: string = `Using CodeQL CLI version ${LINKED_CLI_VERSION.cliVersion}`;
|
||||||
@@ -305,23 +324,14 @@ test.serial(
|
|||||||
"https://github.com/github/codeql-action/releases/download/codeql-bundle-v2.16.0/codeql-bundle-linux64.tar.gz";
|
"https://github.com/github/codeql-action/releases/download/codeql-bundle-v2.16.0/codeql-bundle-linux64.tar.gz";
|
||||||
const expectedVersion = "2.16.0";
|
const expectedVersion = "2.16.0";
|
||||||
|
|
||||||
// Stub the downloadCodeQL function to prevent downloading artefacts
|
const extractStub = stubDownloadAndExtract();
|
||||||
// during testing from being called.
|
|
||||||
sinon.stub(setupCodeql, "downloadCodeQL").resolves({
|
|
||||||
codeqlFolder: "codeql",
|
|
||||||
statusReport: {
|
|
||||||
downloadDurationMs: 200,
|
|
||||||
totalDurationMs: 300,
|
|
||||||
},
|
|
||||||
toolsVersion: expectedVersion,
|
|
||||||
});
|
|
||||||
|
|
||||||
await withTmpDir(async (tmpDir) => {
|
await withTmpDir(async (tmpDir) => {
|
||||||
setupActionsVars(tmpDir, tmpDir);
|
setupActionsVars(tmpDir, tmpDir);
|
||||||
const result = await setupCodeql.setupCodeQLBundle(
|
const result = await setupCodeql.setupCodeQLBundle(
|
||||||
bundleUrl,
|
bundleUrl,
|
||||||
SAMPLE_DOTCOM_API_DETAILS,
|
SAMPLE_DOTCOM_API_DETAILS,
|
||||||
"tmp/codeql_action_test/",
|
tmpDir,
|
||||||
GitHubVariant.DOTCOM,
|
GitHubVariant.DOTCOM,
|
||||||
SAMPLE_DEFAULT_CLI_VERSION,
|
SAMPLE_DEFAULT_CLI_VERSION,
|
||||||
undefined, // rawLanguages
|
undefined, // rawLanguages
|
||||||
@@ -333,6 +343,13 @@ test.serial(
|
|||||||
// Basic sanity check that the version we got back is indeed the version that the
|
// Basic sanity check that the version we got back is indeed the version that the
|
||||||
// bundle contains..
|
// bundle contains..
|
||||||
t.is(result.toolsVersion, expectedVersion);
|
t.is(result.toolsVersion, expectedVersion);
|
||||||
|
t.true(extractStub.calledOnce);
|
||||||
|
t.is(extractStub.firstCall.args[0], bundleUrl);
|
||||||
|
t.is(result.codeqlFolder, toolcache.find("CodeQL", expectedVersion));
|
||||||
|
t.deepEqual(result.toolsDownloadStatusReport, {
|
||||||
|
downloadDurationMs: 200,
|
||||||
|
totalDurationMs: 300,
|
||||||
|
});
|
||||||
|
|
||||||
// Ensure message logging CodeQL CLI version was present in user logs.
|
// Ensure message logging CodeQL CLI version was present in user logs.
|
||||||
const expected_message: string = `Using CodeQL CLI version 2.16.0 sourced from ${bundleUrl} .`;
|
const expected_message: string = `Using CodeQL CLI version 2.16.0 sourced from ${bundleUrl} .`;
|
||||||
@@ -348,11 +365,12 @@ test.serial(
|
|||||||
);
|
);
|
||||||
|
|
||||||
test.serial(
|
test.serial(
|
||||||
"getCodeQLSource correctly returns nightly CLI version when tools == nightly",
|
"getCodeQLSource and setupCodeQLBundle preserve the nightly version when tools == nightly",
|
||||||
async (t) => {
|
async (t) => {
|
||||||
const loggedMessages: LoggedMessage[] = [];
|
const loggedMessages: LoggedMessage[] = [];
|
||||||
const logger = getRecordingLogger(loggedMessages);
|
const logger = getRecordingLogger(loggedMessages);
|
||||||
const features = createFeatures([]);
|
const features = createFeatures([]);
|
||||||
|
const extractStub = stubDownloadAndExtract();
|
||||||
|
|
||||||
const expectedDate = "30260213";
|
const expectedDate = "30260213";
|
||||||
const expectedTag = `codeql-bundle-${expectedDate}`;
|
const expectedTag = `codeql-bundle-${expectedDate}`;
|
||||||
@@ -390,14 +408,34 @@ test.serial(
|
|||||||
const expectedVersion = `0.0.0-${expectedDate}`;
|
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}/${setupCodeql.getCodeQLBundleName("zstd")}`;
|
||||||
t.deepEqual(source, {
|
t.deepEqual(source, {
|
||||||
|
bundle: { kind: "combined", url: expectedURL },
|
||||||
bundleVersion: expectedDate,
|
bundleVersion: expectedDate,
|
||||||
cliVersion: undefined,
|
cliVersion: undefined,
|
||||||
codeqlURL: expectedURL,
|
|
||||||
compressionMethod: "zstd",
|
compressionMethod: "zstd",
|
||||||
sourceType: "download",
|
sourceType: "download",
|
||||||
toolsVersion: expectedVersion,
|
toolsVersion: expectedVersion,
|
||||||
} satisfies setupCodeql.CodeQLToolsSource);
|
} satisfies setupCodeql.CodeQLToolsSource);
|
||||||
|
|
||||||
|
const result = await setupCodeql.setupCodeQLBundle(
|
||||||
|
"nightly",
|
||||||
|
SAMPLE_DOTCOM_API_DETAILS,
|
||||||
|
tmpDir,
|
||||||
|
GitHubVariant.DOTCOM,
|
||||||
|
SAMPLE_DEFAULT_CLI_VERSION,
|
||||||
|
["javascript"],
|
||||||
|
false, // useOverlayAwareDefaultCliVersion
|
||||||
|
features,
|
||||||
|
logger,
|
||||||
|
);
|
||||||
|
|
||||||
|
t.true(extractStub.calledOnce);
|
||||||
|
t.is(extractStub.firstCall.args[0], expectedURL);
|
||||||
|
t.is(result.toolsVersion, source.toolsVersion);
|
||||||
|
t.is(result.toolsSource, setupCodeql.ToolsSource.Download);
|
||||||
|
t.is(result.codeqlFolder, toolcache.find("CodeQL", expectedVersion));
|
||||||
|
t.true(fs.existsSync(`${result.codeqlFolder}.complete`));
|
||||||
|
t.deepEqual(toolcache.findAllVersions("CodeQL"), [expectedVersion]);
|
||||||
|
|
||||||
// Afterwards, ensure that we see the expected messages in the log.
|
// Afterwards, ensure that we see the expected messages in the log.
|
||||||
checkExpectedLogMessages(t, loggedMessages, [
|
checkExpectedLogMessages(t, loggedMessages, [
|
||||||
"Using the latest CodeQL CLI nightly, as requested by 'tools: nightly'.",
|
"Using the latest CodeQL CLI nightly, as requested by 'tools: nightly'.",
|
||||||
@@ -453,9 +491,9 @@ test.serial(
|
|||||||
const expectedVersion = `0.0.0-${expectedDate}`;
|
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}/${setupCodeql.getCodeQLBundleName("zstd")}`;
|
||||||
t.deepEqual(source, {
|
t.deepEqual(source, {
|
||||||
|
bundle: { kind: "combined", url: expectedURL },
|
||||||
bundleVersion: expectedDate,
|
bundleVersion: expectedDate,
|
||||||
cliVersion: undefined,
|
cliVersion: undefined,
|
||||||
codeqlURL: expectedURL,
|
|
||||||
compressionMethod: "zstd",
|
compressionMethod: "zstd",
|
||||||
sourceType: "download",
|
sourceType: "download",
|
||||||
toolsVersion: expectedVersion,
|
toolsVersion: expectedVersion,
|
||||||
@@ -472,6 +510,91 @@ test.serial(
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
for (const bundlePath of [
|
||||||
|
"codeql-bundle.tar.gz",
|
||||||
|
"codeql-bundle.tar.zst",
|
||||||
|
"codeql-bundle-/codeql-bundle.tar.gz",
|
||||||
|
]) {
|
||||||
|
test.serial(
|
||||||
|
`setupCodeQLBundle reports an unknown version for ${bundlePath}`,
|
||||||
|
async (t) => {
|
||||||
|
const extractStub = stubDownloadAndExtract();
|
||||||
|
const downloadSpy = sinon.spy(setupCodeql, "downloadCodeQL");
|
||||||
|
const url = `https://example.com/${bundlePath}`;
|
||||||
|
const messages: LoggedMessage[] = [];
|
||||||
|
|
||||||
|
await withTmpDir(async (tmpDir) => {
|
||||||
|
setupActionsVars(tmpDir, tmpDir);
|
||||||
|
const result = await setupCodeql.setupCodeQLBundle(
|
||||||
|
url,
|
||||||
|
SAMPLE_DOTCOM_API_DETAILS,
|
||||||
|
tmpDir,
|
||||||
|
GitHubVariant.DOTCOM,
|
||||||
|
SAMPLE_DEFAULT_CLI_VERSION,
|
||||||
|
undefined, // rawLanguages
|
||||||
|
false, // useOverlayAwareDefaultCliVersion
|
||||||
|
createFeatures([]),
|
||||||
|
getRecordingLogger(messages),
|
||||||
|
);
|
||||||
|
|
||||||
|
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);
|
||||||
|
t.is(path.dirname(result.codeqlFolder), tmpDir);
|
||||||
|
t.true(fs.existsSync(result.codeqlFolder));
|
||||||
|
t.false(fs.existsSync(`${result.codeqlFolder}.complete`));
|
||||||
|
t.deepEqual(toolcache.findAllVersions("CodeQL"), []);
|
||||||
|
checkExpectedLogMessages(t, messages, [
|
||||||
|
`Using CodeQL CLI sourced from ${url}`,
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
test.serial(
|
||||||
|
"setupCodeQLBundle preserves local installation without cleaning the toolcache",
|
||||||
|
async (t) => {
|
||||||
|
const cleanupSpy = sinon.spy(toolsDownload, "deleteToolcacheBundles");
|
||||||
|
const downloadSpy = sinon.spy(setupCodeql, "downloadCodeQL");
|
||||||
|
|
||||||
|
await withTmpDir(async (tmpDir) => {
|
||||||
|
setupActionsVars(tmpDir, tmpDir);
|
||||||
|
process.env[ActionsEnvVars.RUNNER_ENVIRONMENT] = "github-hosted";
|
||||||
|
const cachedDirectory = createToolcacheEntry(
|
||||||
|
tmpDir,
|
||||||
|
"CodeQL",
|
||||||
|
CLEANUP_STALE_VERSION,
|
||||||
|
);
|
||||||
|
const result = await setupCodeql.setupCodeQLBundle(
|
||||||
|
path.join(__dirname, "../src/testdata/codeql-bundle.tar.gz"),
|
||||||
|
SAMPLE_DOTCOM_API_DETAILS,
|
||||||
|
tmpDir,
|
||||||
|
GitHubVariant.DOTCOM,
|
||||||
|
SAMPLE_DEFAULT_CLI_VERSION,
|
||||||
|
undefined, // rawLanguages
|
||||||
|
false, // useOverlayAwareDefaultCliVersion
|
||||||
|
createFeatures([Feature.CleanupToolcacheBundles]),
|
||||||
|
getRunnerLogger(true),
|
||||||
|
);
|
||||||
|
|
||||||
|
t.is(result.toolsVersion, "local");
|
||||||
|
t.is(result.toolsSource, setupCodeql.ToolsSource.Local);
|
||||||
|
t.is(result.toolsDownloadStatusReport, undefined);
|
||||||
|
t.is(path.dirname(result.codeqlFolder), tmpDir);
|
||||||
|
t.true(fs.existsSync(result.codeqlFolder));
|
||||||
|
t.false(fs.existsSync(`${result.codeqlFolder}.complete`));
|
||||||
|
t.true(fs.existsSync(cachedDirectory));
|
||||||
|
t.true(cleanupSpy.notCalled);
|
||||||
|
t.true(downloadSpy.notCalled);
|
||||||
|
t.is(process.env[EnvVar.HAS_SET_UP_CODEQL], "true");
|
||||||
|
});
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
test.serial(
|
test.serial(
|
||||||
"getCodeQLSource correctly returns latest version from toolcache when tools == toolcache",
|
"getCodeQLSource correctly returns latest version from toolcache when tools == toolcache",
|
||||||
async (t) => {
|
async (t) => {
|
||||||
@@ -974,30 +1097,35 @@ async function runDownloadCodeQL(
|
|||||||
toolcacheRoot: string,
|
toolcacheRoot: string,
|
||||||
features: Feature[],
|
features: Feature[],
|
||||||
bundleVersion: string | undefined,
|
bundleVersion: string | undefined,
|
||||||
|
env = getTestEnv({
|
||||||
|
[ActionsEnvVars.RUNNER_TOOL_CACHE]: toolcacheRoot,
|
||||||
|
}),
|
||||||
): Promise<{
|
): Promise<{
|
||||||
codeqlFolder: string;
|
codeqlFolder: string;
|
||||||
cleanupDiagnostic: toolsDownload.ToolcacheCleanupResult | undefined;
|
cleanupDiagnostic: toolsDownload.ToolcacheCleanupResult | undefined;
|
||||||
}> {
|
}> {
|
||||||
sinon
|
stubDownloadAndExtract();
|
||||||
.stub(toolsDownload, "downloadAndExtract")
|
|
||||||
.callsFake(async (_url, _compressionMethod, dest) => {
|
|
||||||
// The real implementation creates the destination directory, which matters here because the
|
|
||||||
// cleanup deletes it first and `writeToolcacheMarkerFile` writes into its parent afterwards.
|
|
||||||
fs.mkdirSync(dest, { recursive: true });
|
|
||||||
return { totalDurationMs: 1 };
|
|
||||||
});
|
|
||||||
const addDiagnostic = sinon.stub(diagnostics, "addNoLanguageDiagnostic");
|
const addDiagnostic = sinon.stub(diagnostics, "addNoLanguageDiagnostic");
|
||||||
|
|
||||||
const { codeqlFolder } = await setupCodeql.downloadCodeQL(
|
const { codeqlFolder } = await setupCodeql.downloadCodeQLBundle(
|
||||||
"https://example.com/codeql-bundle.tar.gz",
|
initAllState({
|
||||||
"gzip",
|
env,
|
||||||
bundleVersion,
|
features: createFeatures(features),
|
||||||
CLEANUP_CLI_VERSION,
|
}),
|
||||||
|
{
|
||||||
|
bundle: {
|
||||||
|
kind: "combined",
|
||||||
|
url: "https://example.com/codeql-bundle.tar.gz",
|
||||||
|
},
|
||||||
|
compressionMethod: "gzip",
|
||||||
|
bundleVersion,
|
||||||
|
cliVersion: CLEANUP_CLI_VERSION,
|
||||||
|
sourceType: "download",
|
||||||
|
toolsVersion: CLEANUP_CLI_VERSION,
|
||||||
|
},
|
||||||
SAMPLE_DOTCOM_API_DETAILS,
|
SAMPLE_DOTCOM_API_DETAILS,
|
||||||
undefined, // tarVersion
|
undefined, // tarVersion
|
||||||
toolcacheRoot, // tempDir
|
toolcacheRoot, // tempDir
|
||||||
createFeatures(features),
|
|
||||||
getRunnerLogger(true),
|
|
||||||
);
|
);
|
||||||
|
|
||||||
const diagnostic = addDiagnostic
|
const diagnostic = addDiagnostic
|
||||||
@@ -1026,7 +1154,7 @@ async function testToolcacheCleanup(
|
|||||||
}: {
|
}: {
|
||||||
features: Feature[];
|
features: Feature[];
|
||||||
runnerEnvironment: string | undefined;
|
runnerEnvironment: string | undefined;
|
||||||
setUp?: () => void;
|
setUp?: (env: Env) => void;
|
||||||
},
|
},
|
||||||
check: (context: {
|
check: (context: {
|
||||||
cleanupDiagnostic: toolsDownload.ToolcacheCleanupResult | undefined;
|
cleanupDiagnostic: toolsDownload.ToolcacheCleanupResult | undefined;
|
||||||
@@ -1041,7 +1169,10 @@ async function testToolcacheCleanup(
|
|||||||
} else {
|
} else {
|
||||||
process.env[ActionsEnvVars.RUNNER_ENVIRONMENT] = runnerEnvironment;
|
process.env[ActionsEnvVars.RUNNER_ENVIRONMENT] = runnerEnvironment;
|
||||||
}
|
}
|
||||||
setUp?.();
|
const env = getTestEnv({
|
||||||
|
[ActionsEnvVars.RUNNER_TOOL_CACHE]: tmpDir,
|
||||||
|
});
|
||||||
|
setUp?.(env);
|
||||||
|
|
||||||
// The extraction of the bundle would normally create this directory.
|
// The extraction of the bundle would normally create this directory.
|
||||||
const destinationDirectory = createToolcacheEntry(
|
const destinationDirectory = createToolcacheEntry(
|
||||||
@@ -1060,6 +1191,7 @@ async function testToolcacheCleanup(
|
|||||||
tmpDir,
|
tmpDir,
|
||||||
features,
|
features,
|
||||||
CLEANUP_BUNDLE_VERSION,
|
CLEANUP_BUNDLE_VERSION,
|
||||||
|
env,
|
||||||
);
|
);
|
||||||
|
|
||||||
t.true(
|
t.true(
|
||||||
@@ -1072,7 +1204,7 @@ async function testToolcacheCleanup(
|
|||||||
}
|
}
|
||||||
|
|
||||||
test.serial(
|
test.serial(
|
||||||
"downloadCodeQL does not clean up the toolcache when the feature flag is disabled",
|
"downloadCodeQLBundle does not clean up the toolcache when the feature flag is disabled",
|
||||||
async (t) => {
|
async (t) => {
|
||||||
await testToolcacheCleanup(
|
await testToolcacheCleanup(
|
||||||
t,
|
t,
|
||||||
@@ -1087,7 +1219,7 @@ test.serial(
|
|||||||
);
|
);
|
||||||
|
|
||||||
test.serial(
|
test.serial(
|
||||||
"downloadCodeQL does not clean up the toolcache when the runner is not GitHub-hosted",
|
"downloadCodeQLBundle does not clean up the toolcache when the runner is not GitHub-hosted",
|
||||||
async (t) => {
|
async (t) => {
|
||||||
await testToolcacheCleanup(
|
await testToolcacheCleanup(
|
||||||
t,
|
t,
|
||||||
@@ -1105,7 +1237,7 @@ test.serial(
|
|||||||
);
|
);
|
||||||
|
|
||||||
test.serial(
|
test.serial(
|
||||||
"downloadCodeQL does not clean up the toolcache when the runner environment is unknown",
|
"downloadCodeQLBundle does not clean up the toolcache when the runner environment is unknown",
|
||||||
async (t) => {
|
async (t) => {
|
||||||
// A runner that doesn't report its environment must be treated as not GitHub-hosted, since its
|
// A runner that doesn't report its environment must be treated as not GitHub-hosted, since its
|
||||||
// toolcache may well outlive the job.
|
// toolcache may well outlive the job.
|
||||||
@@ -1125,7 +1257,7 @@ test.serial(
|
|||||||
);
|
);
|
||||||
|
|
||||||
test.serial(
|
test.serial(
|
||||||
"downloadCodeQL deletes other CodeQL bundles from the toolcache when enabled on a GitHub-hosted runner",
|
"downloadCodeQLBundle deletes other CodeQL bundles from the toolcache when enabled on a GitHub-hosted runner",
|
||||||
async (t) => {
|
async (t) => {
|
||||||
await testToolcacheCleanup(
|
await testToolcacheCleanup(
|
||||||
t,
|
t,
|
||||||
@@ -1153,7 +1285,7 @@ test.serial(
|
|||||||
);
|
);
|
||||||
|
|
||||||
test.serial(
|
test.serial(
|
||||||
"downloadCodeQL reports no deleted versions when the toolcache has no CodeQL bundles",
|
"downloadCodeQLBundle reports no deleted versions when the toolcache has no CodeQL bundles",
|
||||||
async (t) => {
|
async (t) => {
|
||||||
await withTmpDir(async (tmpDir) => {
|
await withTmpDir(async (tmpDir) => {
|
||||||
setupActionsVars(tmpDir, tmpDir);
|
setupActionsVars(tmpDir, tmpDir);
|
||||||
@@ -1175,7 +1307,7 @@ test.serial(
|
|||||||
);
|
);
|
||||||
|
|
||||||
test.serial(
|
test.serial(
|
||||||
"downloadCodeQL continues when deleting a CodeQL bundle from the toolcache fails",
|
"downloadCodeQLBundle continues when deleting a CodeQL bundle from the toolcache fails",
|
||||||
async (t) => {
|
async (t) => {
|
||||||
await withTmpDir(async (tmpDir) => {
|
await withTmpDir(async (tmpDir) => {
|
||||||
setupActionsVars(tmpDir, tmpDir);
|
setupActionsVars(tmpDir, tmpDir);
|
||||||
@@ -1306,7 +1438,7 @@ test.serial(
|
|||||||
);
|
);
|
||||||
|
|
||||||
test.serial(
|
test.serial(
|
||||||
"downloadCodeQL does not follow a symlinked CodeQL toolcache directory",
|
"downloadCodeQLBundle does not follow a symlinked CodeQL toolcache directory",
|
||||||
async (t) => {
|
async (t) => {
|
||||||
await withTmpDir(async (tmpDir) => {
|
await withTmpDir(async (tmpDir) => {
|
||||||
const toolcacheRoot = path.join(tmpDir, "toolcache");
|
const toolcacheRoot = path.join(tmpDir, "toolcache");
|
||||||
@@ -1342,7 +1474,7 @@ test.serial(
|
|||||||
);
|
);
|
||||||
|
|
||||||
test.serial(
|
test.serial(
|
||||||
"downloadCodeQL does not clean up the toolcache once a step has already set up CodeQL",
|
"downloadCodeQLBundle does not clean up the toolcache once a step has already set up CodeQL",
|
||||||
async (t) => {
|
async (t) => {
|
||||||
// `.github/workflows/codeql.yml` sets up CodeQL twice and then runs both returned paths. If the
|
// `.github/workflows/codeql.yml` sets up CodeQL twice and then runs both returned paths. If the
|
||||||
// second setup downloads, it must not delete the bundle the first one handed out.
|
// second setup downloads, it must not delete the bundle the first one handed out.
|
||||||
@@ -1351,8 +1483,8 @@ test.serial(
|
|||||||
{
|
{
|
||||||
features: [Feature.CleanupToolcacheBundles],
|
features: [Feature.CleanupToolcacheBundles],
|
||||||
runnerEnvironment: "github-hosted",
|
runnerEnvironment: "github-hosted",
|
||||||
setUp: () => {
|
setUp: (env) => {
|
||||||
process.env[EnvVar.HAS_SET_UP_CODEQL] = "true";
|
env.set(EnvVar.HAS_SET_UP_CODEQL, "true");
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
({ cleanupDiagnostic, destinationDirectory, staleDirectory }) => {
|
({ cleanupDiagnostic, destinationDirectory, staleDirectory }) => {
|
||||||
@@ -1364,6 +1496,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(
|
test.serial(
|
||||||
"setupCodeQLBundle records that this job has set up CodeQL",
|
"setupCodeQLBundle records that this job has set up CodeQL",
|
||||||
async (t) => {
|
async (t) => {
|
||||||
@@ -1371,11 +1530,7 @@ test.serial(
|
|||||||
setupActionsVars(tmpDir, tmpDir);
|
setupActionsVars(tmpDir, tmpDir);
|
||||||
delete process.env[EnvVar.HAS_SET_UP_CODEQL];
|
delete process.env[EnvVar.HAS_SET_UP_CODEQL];
|
||||||
|
|
||||||
sinon.stub(setupCodeql, "downloadCodeQL").resolves({
|
stubDownloadAndExtract();
|
||||||
codeqlFolder: "codeql",
|
|
||||||
statusReport: { totalDurationMs: 1 },
|
|
||||||
toolsVersion: LINKED_CLI_VERSION.cliVersion,
|
|
||||||
});
|
|
||||||
|
|
||||||
await setupCodeql.setupCodeQLBundle(
|
await setupCodeql.setupCodeQLBundle(
|
||||||
"linked",
|
"linked",
|
||||||
@@ -1399,7 +1554,50 @@ test.serial(
|
|||||||
);
|
);
|
||||||
|
|
||||||
test.serial(
|
test.serial(
|
||||||
"downloadCodeQL cleans up the toolcache even when the download will not be cached",
|
"setupCodeQLBundle cleans up once and propagates a failed combined download",
|
||||||
|
async (t) => {
|
||||||
|
const error = new HTTPError("Not Found", 404);
|
||||||
|
const extractStub = stubDownloadAndExtract().rejects(error);
|
||||||
|
const cleanupSpy = sinon.spy(toolsDownload, "deleteToolcacheBundles");
|
||||||
|
|
||||||
|
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,
|
||||||
|
);
|
||||||
|
|
||||||
|
await t.throwsAsync(
|
||||||
|
setupCodeql.setupCodeQLBundle(
|
||||||
|
"linked",
|
||||||
|
SAMPLE_DOTCOM_API_DETAILS,
|
||||||
|
tmpDir,
|
||||||
|
GitHubVariant.DOTCOM,
|
||||||
|
SAMPLE_DEFAULT_CLI_VERSION,
|
||||||
|
undefined, // rawLanguages
|
||||||
|
false, // useOverlayAwareDefaultCliVersion
|
||||||
|
createFeatures([Feature.CleanupToolcacheBundles]),
|
||||||
|
getRunnerLogger(true),
|
||||||
|
),
|
||||||
|
{ is: error },
|
||||||
|
);
|
||||||
|
|
||||||
|
t.true(cleanupSpy.calledOnce);
|
||||||
|
t.true(cleanupSpy.calledBefore(extractStub));
|
||||||
|
t.true(extractStub.calledOnce);
|
||||||
|
t.false(fs.existsSync(staleDirectory));
|
||||||
|
t.false(fs.existsSync(`${extractStub.firstCall.args[2]}.complete`));
|
||||||
|
t.deepEqual(toolcache.findAllVersions("CodeQL"), []);
|
||||||
|
t.is(process.env[EnvVar.HAS_SET_UP_CODEQL], undefined);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
test.serial(
|
||||||
|
"downloadCodeQLBundle cleans up the toolcache even when the download will not be cached",
|
||||||
async (t) => {
|
async (t) => {
|
||||||
// A `tools` URL we can't derive a bundle version from is extracted to a temporary directory
|
// A `tools` URL we can't derive a bundle version from is extracted to a temporary directory
|
||||||
// rather than the toolcache, but the toolcache is on the same filesystem, so emptying it still
|
// rather than the toolcache, but the toolcache is on the same filesystem, so emptying it still
|
||||||
@@ -1434,7 +1632,7 @@ test.serial(
|
|||||||
);
|
);
|
||||||
|
|
||||||
test.serial(
|
test.serial(
|
||||||
"downloadCodeQL reports a failure when the toolcache cannot be inspected",
|
"downloadCodeQLBundle reports a failure when the toolcache cannot be inspected",
|
||||||
async (t) => {
|
async (t) => {
|
||||||
await withTmpDir(async (tmpDir) => {
|
await withTmpDir(async (tmpDir) => {
|
||||||
setupActionsVars(tmpDir, tmpDir);
|
setupActionsVars(tmpDir, tmpDir);
|
||||||
@@ -1466,7 +1664,7 @@ test.serial(
|
|||||||
);
|
);
|
||||||
|
|
||||||
test.serial(
|
test.serial(
|
||||||
"downloadCodeQL does not clean up a toolcache on a different filesystem to the workspace",
|
"downloadCodeQLBundle does not clean up a toolcache on a different filesystem to the workspace",
|
||||||
async (t) => {
|
async (t) => {
|
||||||
// Some runner images keep the toolcache on a different volume to the workspace, in which case
|
// Some runner images keep the toolcache on a different volume to the workspace, in which case
|
||||||
// deleting the tools frees up disk space that the analysis cannot use.
|
// deleting the tools frees up disk space that the analysis cannot use.
|
||||||
@@ -1516,7 +1714,7 @@ test.serial(
|
|||||||
);
|
);
|
||||||
|
|
||||||
test.serial(
|
test.serial(
|
||||||
"downloadCodeQL does not delete through a symlinked version directory",
|
"downloadCodeQLBundle does not delete through a symlinked version directory",
|
||||||
async (t) => {
|
async (t) => {
|
||||||
await withTmpDir(async (tmpDir) => {
|
await withTmpDir(async (tmpDir) => {
|
||||||
const toolcacheRoot = path.join(tmpDir, "toolcache");
|
const toolcacheRoot = path.join(tmpDir, "toolcache");
|
||||||
|
|||||||
@@ -164,7 +164,7 @@ function tryGetBundleVersionFromTagName(
|
|||||||
tagName: string,
|
tagName: string,
|
||||||
logger: Logger,
|
logger: Logger,
|
||||||
): string | undefined {
|
): string | undefined {
|
||||||
const match = tagName.match(/^codeql-bundle-(.*)$/);
|
const match = tagName.match(/^codeql-bundle-(.+)$/);
|
||||||
if (match === null || match.length < 2) {
|
if (match === null || match.length < 2) {
|
||||||
logger.debug(`Could not determine bundle version from tag ${tagName}.`);
|
logger.debug(`Could not determine bundle version from tag ${tagName}.`);
|
||||||
return undefined;
|
return undefined;
|
||||||
@@ -215,6 +215,25 @@ export function convertToSemVer(version: string, logger: Logger): string {
|
|||||||
return s;
|
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;
|
||||||
|
/** CLI version of the tools, if known. */
|
||||||
|
cliVersion?: string;
|
||||||
|
/** Resolved version for telemetry, independent of whether the bundle can be cached. */
|
||||||
|
toolsVersion: string;
|
||||||
|
}
|
||||||
|
|
||||||
export type CodeQLToolsSource =
|
export type CodeQLToolsSource =
|
||||||
| {
|
| {
|
||||||
codeqlTarPath: string;
|
codeqlTarPath: string;
|
||||||
@@ -229,17 +248,7 @@ export type CodeQLToolsSource =
|
|||||||
/** Human-readable description of the source of the tools for telemetry purposes. */
|
/** Human-readable description of the source of the tools for telemetry purposes. */
|
||||||
toolsVersion: string;
|
toolsVersion: string;
|
||||||
}
|
}
|
||||||
| {
|
| CodeQLDownloadSource;
|
||||||
/** Bundle version of the tools, if known. */
|
|
||||||
bundleVersion?: string;
|
|
||||||
/** CLI version of the tools, if known. */
|
|
||||||
cliVersion?: string;
|
|
||||||
compressionMethod: tar.CompressionMethod;
|
|
||||||
codeqlURL: string;
|
|
||||||
sourceType: "download";
|
|
||||||
/** Human-readable description of the source of the tools for telemetry purposes. */
|
|
||||||
toolsVersion: string;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Look for a version of the CodeQL tools in the cache which could override the requested CLI version.
|
* Look for a version of the CodeQL tools in the cache which could override the requested CLI version.
|
||||||
@@ -583,7 +592,7 @@ export async function getCodeQLSource(
|
|||||||
if (tagName) {
|
if (tagName) {
|
||||||
const bundleVersion = tryGetBundleVersionFromTagName(tagName, logger);
|
const bundleVersion = tryGetBundleVersionFromTagName(tagName, logger);
|
||||||
// If the bundle version is a semantic version, it is a CLI version number.
|
// 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);
|
cliVersion = convertToSemVer(bundleVersion, logger);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -600,13 +609,15 @@ export async function getCodeQLSource(
|
|||||||
}
|
}
|
||||||
|
|
||||||
const bundleVersion =
|
const bundleVersion =
|
||||||
tagName && tryGetBundleVersionFromTagName(tagName, logger);
|
tagName !== undefined
|
||||||
const humanReadableVersion =
|
? tryGetBundleVersionFromTagName(tagName, logger)
|
||||||
|
: undefined;
|
||||||
|
const resolvedVersion =
|
||||||
cliVersion ??
|
cliVersion ??
|
||||||
(bundleVersion && convertToSemVer(bundleVersion, logger)) ??
|
(bundleVersion !== undefined
|
||||||
tagName ??
|
? convertToSemVer(bundleVersion, logger)
|
||||||
url ??
|
: undefined);
|
||||||
"unknown";
|
const humanReadableVersion = resolvedVersion ?? tagName ?? url ?? "unknown";
|
||||||
|
|
||||||
logger.debug(
|
logger.debug(
|
||||||
"Attempting to obtain CodeQL tools. " +
|
"Attempting to obtain CodeQL tools. " +
|
||||||
@@ -750,12 +761,12 @@ export async function getCodeQLSource(
|
|||||||
logger.info(`Using CodeQL CLI sourced from ${url} .`);
|
logger.info(`Using CodeQL CLI sourced from ${url} .`);
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
bundleVersion: tagName && tryGetBundleVersionFromTagName(tagName, logger),
|
bundle: { kind: "combined", url },
|
||||||
|
bundleVersion,
|
||||||
cliVersion,
|
cliVersion,
|
||||||
codeqlURL: url,
|
|
||||||
compressionMethod,
|
compressionMethod,
|
||||||
sourceType: "download",
|
sourceType: "download",
|
||||||
toolsVersion: cliVersion ?? humanReadableVersion,
|
toolsVersion: resolvedVersion ?? "unknown",
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -769,7 +780,7 @@ async function tryGetFallbackToolcacheVersion(
|
|||||||
logger: Logger,
|
logger: Logger,
|
||||||
): Promise<string | undefined> {
|
): Promise<string | undefined> {
|
||||||
const bundleVersion = tryGetBundleVersionFromTagName(tagName, logger);
|
const bundleVersion = tryGetBundleVersionFromTagName(tagName, logger);
|
||||||
if (!bundleVersion) {
|
if (bundleVersion === undefined) {
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
const fallbackVersion = convertToSemVer(bundleVersion, logger);
|
const fallbackVersion = convertToSemVer(bundleVersion, logger);
|
||||||
@@ -783,20 +794,17 @@ async function tryGetFallbackToolcacheVersion(
|
|||||||
// Exported using `export const` for testing purposes. Specifically, we want to
|
// Exported using `export const` for testing purposes. Specifically, we want to
|
||||||
// be able to stub this function and have other functions in this file use that stub.
|
// be able to stub this function and have other functions in this file use that stub.
|
||||||
export const downloadCodeQL = async function (
|
export const downloadCodeQL = async function (
|
||||||
codeqlURL: string,
|
source: CodeQLDownloadSource,
|
||||||
compressionMethod: tar.CompressionMethod,
|
|
||||||
maybeBundleVersion: string | undefined,
|
|
||||||
maybeCliVersion: string | undefined,
|
|
||||||
apiDetails: api.GitHubApiDetails,
|
apiDetails: api.GitHubApiDetails,
|
||||||
tarVersion: tar.TarVersion | undefined,
|
tarVersion: tar.TarVersion | undefined,
|
||||||
tempDir: string,
|
tempDir: string,
|
||||||
features: FeatureEnablement,
|
|
||||||
logger: Logger,
|
logger: Logger,
|
||||||
): Promise<{
|
): Promise<{
|
||||||
codeqlFolder: string;
|
codeqlFolder: string;
|
||||||
statusReport: ToolsDownloadStatusReport;
|
statusReport: ToolsDownloadStatusReport;
|
||||||
toolsVersion: string;
|
|
||||||
}> {
|
}> {
|
||||||
|
const { bundle, compressionMethod } = source;
|
||||||
|
const codeqlURL = bundle.url;
|
||||||
const parsedCodeQLURL = new URL(codeqlURL);
|
const parsedCodeQLURL = new URL(codeqlURL);
|
||||||
const searchParams = new URLSearchParams(parsedCodeQLURL.search);
|
const searchParams = new URLSearchParams(parsedCodeQLURL.search);
|
||||||
const headers: OutgoingHttpHeaders = {
|
const headers: OutgoingHttpHeaders = {
|
||||||
@@ -815,16 +823,9 @@ export const downloadCodeQL = async function (
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const toolcacheInfo = getToolcacheDestinationInfo(
|
const toolcacheDestination = getToolcacheDestination(source, logger);
|
||||||
maybeBundleVersion,
|
|
||||||
maybeCliVersion,
|
|
||||||
logger,
|
|
||||||
);
|
|
||||||
|
|
||||||
const extractedBundlePath =
|
const extractedBundlePath =
|
||||||
toolcacheInfo?.path ?? getTempExtractionDir(tempDir);
|
toolcacheDestination ?? getTempExtractionDir(tempDir);
|
||||||
|
|
||||||
await tryDeleteToolcacheBundles({ env: getEnv(), features, logger });
|
|
||||||
|
|
||||||
const statusReport = await downloadAndExtract(
|
const statusReport = await downloadAndExtract(
|
||||||
codeqlURL,
|
codeqlURL,
|
||||||
@@ -836,46 +837,40 @@ export const downloadCodeQL = async function (
|
|||||||
logger,
|
logger,
|
||||||
);
|
);
|
||||||
|
|
||||||
if (!toolcacheInfo) {
|
if (toolcacheDestination) {
|
||||||
|
writeToolcacheMarkerFile(toolcacheDestination, logger);
|
||||||
|
} else {
|
||||||
logger.debug(
|
logger.debug(
|
||||||
"Could not cache CodeQL tools because we could not determine the bundle version from the " +
|
"Could not cache CodeQL tools because we could not determine the bundle version from the " +
|
||||||
`URL ${codeqlURL}.`,
|
`URL ${codeqlURL}.`,
|
||||||
);
|
);
|
||||||
return {
|
|
||||||
codeqlFolder: extractedBundlePath,
|
|
||||||
statusReport,
|
|
||||||
toolsVersion: maybeCliVersion ?? "unknown",
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
writeToolcacheMarkerFile(toolcacheInfo.path, logger);
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
codeqlFolder: extractedBundlePath,
|
codeqlFolder: extractedBundlePath,
|
||||||
statusReport,
|
statusReport,
|
||||||
toolsVersion: maybeCliVersion ?? toolcacheInfo.version,
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
function getToolcacheDestinationInfo(
|
/**
|
||||||
maybeBundleVersion: string | undefined,
|
* Returns the canonical toolcache directory for a resolved download, or `undefined` if its bundle
|
||||||
maybeCliVersion: string | undefined,
|
* version is unknown.
|
||||||
|
*/
|
||||||
|
function getToolcacheDestination(
|
||||||
|
source: CodeQLDownloadSource,
|
||||||
logger: Logger,
|
logger: Logger,
|
||||||
): { path: string; version: string } | undefined {
|
): string | undefined {
|
||||||
if (maybeBundleVersion) {
|
if (!source.bundleVersion) {
|
||||||
const version = getCanonicalToolcacheVersion(
|
return undefined;
|
||||||
maybeCliVersion,
|
|
||||||
maybeBundleVersion,
|
|
||||||
logger,
|
|
||||||
);
|
|
||||||
|
|
||||||
return {
|
|
||||||
path: getToolcacheDirectory(version),
|
|
||||||
version,
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return undefined;
|
return getToolcacheDirectory(
|
||||||
|
getCanonicalToolcacheVersion(
|
||||||
|
source.cliVersion,
|
||||||
|
source.bundleVersion,
|
||||||
|
logger,
|
||||||
|
),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1000,7 +995,6 @@ export async function setupCodeQLBundle(
|
|||||||
);
|
);
|
||||||
|
|
||||||
let codeqlFolder: string;
|
let codeqlFolder: string;
|
||||||
let toolsVersion = source.toolsVersion;
|
|
||||||
let toolsDownloadStatusReport: ToolsDownloadStatusReport | undefined;
|
let toolsDownloadStatusReport: ToolsDownloadStatusReport | undefined;
|
||||||
let toolsSource: ToolsSource;
|
let toolsSource: ToolsSource;
|
||||||
switch (source.sourceType) {
|
switch (source.sourceType) {
|
||||||
@@ -1021,18 +1015,13 @@ export async function setupCodeQLBundle(
|
|||||||
toolsSource = ToolsSource.Toolcache;
|
toolsSource = ToolsSource.Toolcache;
|
||||||
break;
|
break;
|
||||||
case "download": {
|
case "download": {
|
||||||
const result = await downloadCodeQL(
|
const result = await downloadCodeQLBundle(
|
||||||
source.codeqlURL,
|
{ env: getEnv(), features, logger },
|
||||||
source.compressionMethod,
|
source,
|
||||||
source.bundleVersion,
|
|
||||||
source.cliVersion,
|
|
||||||
apiDetails,
|
apiDetails,
|
||||||
zstdAvailability.version,
|
zstdAvailability.version,
|
||||||
tempDir,
|
tempDir,
|
||||||
features,
|
|
||||||
logger,
|
|
||||||
);
|
);
|
||||||
toolsVersion = result.toolsVersion;
|
|
||||||
codeqlFolder = result.codeqlFolder;
|
codeqlFolder = result.codeqlFolder;
|
||||||
toolsDownloadStatusReport = result.statusReport;
|
toolsDownloadStatusReport = result.statusReport;
|
||||||
toolsSource = ToolsSource.Download;
|
toolsSource = ToolsSource.Download;
|
||||||
@@ -1050,10 +1039,35 @@ export async function setupCodeQLBundle(
|
|||||||
codeqlFolder,
|
codeqlFolder,
|
||||||
toolsDownloadStatusReport,
|
toolsDownloadStatusReport,
|
||||||
toolsSource,
|
toolsSource,
|
||||||
toolsVersion,
|
toolsVersion: source.toolsVersion,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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,
|
||||||
|
): Promise<{
|
||||||
|
codeqlFolder: string;
|
||||||
|
statusReport: ToolsDownloadStatusReport;
|
||||||
|
}> {
|
||||||
|
await tryDeleteToolcacheBundles(action);
|
||||||
|
return await downloadCodeQL(
|
||||||
|
source,
|
||||||
|
apiDetails,
|
||||||
|
tarVersion,
|
||||||
|
tempDir,
|
||||||
|
action.logger,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
async function useZstdBundle(
|
async function useZstdBundle(
|
||||||
cliVersion: string,
|
cliVersion: string,
|
||||||
tarSupportsZstd: boolean,
|
tarSupportsZstd: boolean,
|
||||||
|
|||||||
Reference in New Issue
Block a user