mirror of
https://github.com/github/codeql-action.git
synced 2026-10-30 17:39:50 +00:00
Use per-language CodeQL bundles
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
@@ -12,8 +12,10 @@ import * as api from "./api-client";
|
||||
import * as diagnostics from "./diagnostics";
|
||||
import { ActionsEnvVars, EnvVar, getEnv, ReadOnlyEnv } from "./environment";
|
||||
import { Feature } from "./feature-flags";
|
||||
import { BuiltInLanguage } from "./languages";
|
||||
import { getRunnerLogger } from "./logging";
|
||||
import { getCacheRestoreKeyPrefix } from "./overlay/caching";
|
||||
import { MIN_PER_LANGUAGE_BUNDLE_CLI_VERSION } from "./per-language-bundles";
|
||||
import * as setupCodeql from "./setup-codeql";
|
||||
import * as tar from "./tar";
|
||||
import {
|
||||
@@ -55,6 +57,25 @@ function stubDownloadAndExtract() {
|
||||
});
|
||||
}
|
||||
|
||||
function stubHostedNightly(tagName: string) {
|
||||
sinon.stub(process, "platform").value("linux");
|
||||
sinon.stub(process, "arch").value("x64");
|
||||
process.env[ActionsEnvVars.RUNNER_ENVIRONMENT] = "github-hosted";
|
||||
sinon.stub(tar, "isZstdAvailable").resolves({
|
||||
available: true,
|
||||
foundZstdBinary: true,
|
||||
});
|
||||
const client = github.getOctokit("123", {
|
||||
request: {
|
||||
fetch: async () =>
|
||||
new Response(JSON.stringify([{ tag_name: tagName }]), {
|
||||
headers: { "content-type": "application/json" },
|
||||
}),
|
||||
},
|
||||
});
|
||||
sinon.stub(api, "getApiClient").value(() => client);
|
||||
}
|
||||
|
||||
test.serial("parse codeql bundle url version", (t) => {
|
||||
t.deepEqual(
|
||||
setupCodeql.getCodeQLURLVersion(
|
||||
@@ -374,20 +395,7 @@ test.serial(
|
||||
const expectedDate = "30260213";
|
||||
const expectedTag = `codeql-bundle-${expectedDate}`;
|
||||
|
||||
// Ensure that we consistently select "zstd" for the test.
|
||||
sinon.stub(process, "platform").value("linux");
|
||||
sinon.stub(tar, "isZstdAvailable").resolves({
|
||||
available: true,
|
||||
foundZstdBinary: true,
|
||||
});
|
||||
|
||||
const client = github.getOctokit("123");
|
||||
const listReleases = sinon.stub(client.rest.repos, "listReleases");
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
|
||||
listReleases.resolves({
|
||||
data: [{ tag_name: expectedTag }],
|
||||
} as any);
|
||||
sinon.stub(api, "getApiClient").value(() => client);
|
||||
stubHostedNightly(expectedTag);
|
||||
|
||||
await withTmpDir(async (tmpDir) => {
|
||||
setupActionsVars(tmpDir, tmpDir);
|
||||
@@ -456,20 +464,7 @@ test.serial(
|
||||
const expectedDate = "30260213";
|
||||
const expectedTag = `codeql-bundle-${expectedDate}`;
|
||||
|
||||
// Ensure that we consistently select "zstd" for the test.
|
||||
sinon.stub(process, "platform").value("linux");
|
||||
sinon.stub(tar, "isZstdAvailable").resolves({
|
||||
available: true,
|
||||
foundZstdBinary: true,
|
||||
});
|
||||
|
||||
const client = github.getOctokit("123");
|
||||
const listReleases = sinon.stub(client.rest.repos, "listReleases");
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
|
||||
listReleases.resolves({
|
||||
data: [{ tag_name: expectedTag }],
|
||||
} as any);
|
||||
sinon.stub(api, "getApiClient").value(() => client);
|
||||
stubHostedNightly(expectedTag);
|
||||
|
||||
await withTmpDir(async (tmpDir) => {
|
||||
setupActionsVars(tmpDir, tmpDir, { GITHUB_EVENT_NAME: "dynamic" });
|
||||
@@ -513,6 +508,8 @@ for (const bundlePath of [
|
||||
"codeql-bundle.tar.gz",
|
||||
"codeql-bundle.tar.zst",
|
||||
"codeql-bundle-/codeql-bundle.tar.gz",
|
||||
"codeql-bundle-linux64.tar.zst",
|
||||
"codeql-bundle-ruby-linux64.tar.zst",
|
||||
]) {
|
||||
test.serial(
|
||||
`setupCodeQLBundle reports an unknown version for ${bundlePath}`,
|
||||
@@ -542,6 +539,12 @@ for (const bundlePath of [
|
||||
t.is(downloadSpy.firstCall.args[0].toolsVersion, "unknown");
|
||||
t.is(result.toolsVersion, "unknown");
|
||||
t.is(result.toolsSource, setupCodeql.ToolsSource.Download);
|
||||
t.is(
|
||||
result.toolsDownloadStatusReport?.bundleLanguage,
|
||||
bundlePath === "codeql-bundle-ruby-linux64.tar.zst"
|
||||
? BuiltInLanguage.ruby
|
||||
: undefined,
|
||||
);
|
||||
t.is(path.dirname(result.codeqlFolder), tmpDir);
|
||||
t.true(fs.existsSync(result.codeqlFolder));
|
||||
t.false(fs.existsSync(`${result.codeqlFolder}.complete`));
|
||||
@@ -594,6 +597,131 @@ test.serial(
|
||||
},
|
||||
);
|
||||
|
||||
for (const toolsInput of ["nightly", "nightly-latest"]) {
|
||||
test.serial(
|
||||
`getCodeQLSource selects a per-language bundle for tools == ${toolsInput}`,
|
||||
async (t) => {
|
||||
const expectedTag = "codeql-bundle-30260213";
|
||||
const baseURL = `https://github.com/dsp-testing/codeql-cli-nightlies/releases/download/${expectedTag}`;
|
||||
stubHostedNightly(expectedTag);
|
||||
|
||||
await withTmpDir(async (tmpDir) => {
|
||||
setupActionsVars(tmpDir, tmpDir);
|
||||
const source = await setupCodeql.getCodeQLSource(
|
||||
toolsInput,
|
||||
SAMPLE_DEFAULT_CLI_VERSION,
|
||||
["java"],
|
||||
false, // useOverlayAwareDefaultCliVersion
|
||||
SAMPLE_DOTCOM_API_DETAILS,
|
||||
GitHubVariant.DOTCOM,
|
||||
true, // tarSupportsZstd
|
||||
createFeatures([Feature.PerLanguageBundles]),
|
||||
getRunnerLogger(true),
|
||||
);
|
||||
|
||||
t.deepEqual(source, {
|
||||
sourceType: "download",
|
||||
bundle: {
|
||||
kind: "per-language",
|
||||
language: BuiltInLanguage.java,
|
||||
url: `${baseURL}/codeql-bundle-java-linux64.tar.zst`,
|
||||
combinedBundleURL: `${baseURL}/codeql-bundle-linux64.tar.zst`,
|
||||
},
|
||||
bundleVersion: "30260213",
|
||||
cliVersion: undefined,
|
||||
compressionMethod: "zstd",
|
||||
toolsVersion: "0.0.0-30260213",
|
||||
} satisfies setupCodeql.CodeQLDownloadSource);
|
||||
});
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
test.serial(
|
||||
"getCodeQLSource downloads the combined nightly bundle when not eligible",
|
||||
async (t) => {
|
||||
const expectedTag = "codeql-bundle-30260213";
|
||||
stubHostedNightly(expectedTag);
|
||||
|
||||
await withTmpDir(async (tmpDir) => {
|
||||
setupActionsVars(tmpDir, tmpDir);
|
||||
for (const { languages, features } of [
|
||||
{ languages: ["java"], features: createFeatures([]) },
|
||||
{
|
||||
languages: ["java", "python"],
|
||||
features: createFeatures([Feature.PerLanguageBundles]),
|
||||
},
|
||||
]) {
|
||||
const source = await setupCodeql.getCodeQLSource(
|
||||
"nightly",
|
||||
SAMPLE_DEFAULT_CLI_VERSION,
|
||||
languages,
|
||||
false, // useOverlayAwareDefaultCliVersion
|
||||
SAMPLE_DOTCOM_API_DETAILS,
|
||||
GitHubVariant.DOTCOM,
|
||||
true, // tarSupportsZstd
|
||||
features,
|
||||
getRunnerLogger(true),
|
||||
);
|
||||
|
||||
t.is(source.sourceType, "download");
|
||||
if (source.sourceType === "download") {
|
||||
t.deepEqual(source.bundle, {
|
||||
kind: "combined",
|
||||
url: `https://github.com/dsp-testing/codeql-cli-nightlies/releases/download/${expectedTag}/codeql-bundle-linux64.tar.zst`,
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
);
|
||||
|
||||
for (const perLanguageBundles of [false, true]) {
|
||||
test.serial(
|
||||
`getCodeQLSource uses a ${perLanguageBundles ? "per-language" : "combined"} bundle for a forced nightly`,
|
||||
async (t) => {
|
||||
const expectedTag = "codeql-bundle-30260213";
|
||||
const baseURL = `https://github.com/dsp-testing/codeql-cli-nightlies/releases/download/${expectedTag}`;
|
||||
stubHostedNightly(expectedTag);
|
||||
|
||||
await withTmpDir(async (tmpDir) => {
|
||||
setupActionsVars(tmpDir, tmpDir, { GITHUB_EVENT_NAME: "dynamic" });
|
||||
const source = await setupCodeql.getCodeQLSource(
|
||||
undefined, // toolsInput: the nightly is selected by ForceNightly
|
||||
SAMPLE_DEFAULT_CLI_VERSION,
|
||||
["java"],
|
||||
false, // useOverlayAwareDefaultCliVersion
|
||||
SAMPLE_DOTCOM_API_DETAILS,
|
||||
GitHubVariant.DOTCOM,
|
||||
true, // tarSupportsZstd
|
||||
createFeatures(
|
||||
perLanguageBundles
|
||||
? [Feature.ForceNightly, Feature.PerLanguageBundles]
|
||||
: [Feature.ForceNightly],
|
||||
),
|
||||
getRunnerLogger(true),
|
||||
);
|
||||
|
||||
t.is(source.sourceType, "download");
|
||||
if (source.sourceType === "download") {
|
||||
const combinedURL = `${baseURL}/codeql-bundle-linux64.tar.zst`;
|
||||
t.deepEqual(
|
||||
source.bundle,
|
||||
perLanguageBundles
|
||||
? {
|
||||
kind: "per-language",
|
||||
language: BuiltInLanguage.java,
|
||||
url: `${baseURL}/codeql-bundle-java-linux64.tar.zst`,
|
||||
combinedBundleURL: combinedURL,
|
||||
}
|
||||
: { kind: "combined", url: combinedURL },
|
||||
);
|
||||
}
|
||||
});
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
test.serial(
|
||||
"getCodeQLSource correctly returns latest version from toolcache when tools == toolcache",
|
||||
async (t) => {
|
||||
@@ -878,6 +1006,439 @@ test.serial(
|
||||
},
|
||||
);
|
||||
|
||||
const PER_LANGUAGE_CLI_VERSION = {
|
||||
enabledVersions: [
|
||||
{
|
||||
cliVersion: MIN_PER_LANGUAGE_BUNDLE_CLI_VERSION,
|
||||
tagName: `codeql-bundle-v${MIN_PER_LANGUAGE_BUNDLE_CLI_VERSION}`,
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
test.serial("getCodeQLBundleName names the per-language bundle", (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) => {
|
||||
sinon.stub(process, "platform").value("linux");
|
||||
sinon.stub(process, "arch").value("x64");
|
||||
process.env[ActionsEnvVars.RUNNER_ENVIRONMENT] = "github-hosted";
|
||||
|
||||
await withTmpDir(async (tmpDir) => {
|
||||
setupActionsVars(tmpDir, tmpDir);
|
||||
const source = await setupCodeql.getCodeQLSource(
|
||||
undefined,
|
||||
PER_LANGUAGE_CLI_VERSION,
|
||||
["java-kotlin"],
|
||||
false, // useOverlayAwareDefaultCliVersion
|
||||
SAMPLE_DOTCOM_API_DETAILS,
|
||||
GitHubVariant.DOTCOM,
|
||||
true, // tarSupportsZstd
|
||||
createFeatures([Feature.PerLanguageBundles]),
|
||||
getRunnerLogger(true),
|
||||
);
|
||||
|
||||
t.is(source.sourceType, "download");
|
||||
if (source.sourceType === "download") {
|
||||
t.true(
|
||||
source.bundle.url.endsWith("/codeql-bundle-java-linux64.tar.zst"),
|
||||
`Unexpected URL ${source.bundle.url}`,
|
||||
);
|
||||
t.is(source.bundle.kind, "per-language");
|
||||
if (source.bundle.kind === "per-language") {
|
||||
t.is(source.bundle.language, BuiltInLanguage.java);
|
||||
t.true(
|
||||
source.bundle.combinedBundleURL?.endsWith(
|
||||
"/codeql-bundle-linux64.tar.zst",
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
);
|
||||
|
||||
test.serial(
|
||||
"getCodeQLSource downloads the combined bundle when the feature is disabled",
|
||||
async (t) => {
|
||||
sinon.stub(process, "platform").value("linux");
|
||||
sinon.stub(process, "arch").value("x64");
|
||||
process.env[ActionsEnvVars.RUNNER_ENVIRONMENT] = "github-hosted";
|
||||
|
||||
await withTmpDir(async (tmpDir) => {
|
||||
setupActionsVars(tmpDir, tmpDir);
|
||||
const source = await setupCodeql.getCodeQLSource(
|
||||
undefined,
|
||||
PER_LANGUAGE_CLI_VERSION,
|
||||
["java"],
|
||||
false, // useOverlayAwareDefaultCliVersion
|
||||
SAMPLE_DOTCOM_API_DETAILS,
|
||||
GitHubVariant.DOTCOM,
|
||||
true, // tarSupportsZstd
|
||||
createFeatures([]),
|
||||
getRunnerLogger(true),
|
||||
);
|
||||
|
||||
t.is(source.sourceType, "download");
|
||||
if (source.sourceType === "download") {
|
||||
t.true(source.bundle.url.endsWith("/codeql-bundle-linux64.tar.zst"));
|
||||
t.is(source.bundle.kind, "combined");
|
||||
}
|
||||
});
|
||||
},
|
||||
);
|
||||
|
||||
for (const fallback of [false, true]) {
|
||||
test.serial(
|
||||
`setupCodeQLBundle retains the selected release identity for an opaque asset URL${fallback ? " with fallback" : ""}`,
|
||||
async (t) => {
|
||||
sinon.stub(process, "platform").value("linux");
|
||||
sinon.stub(process, "arch").value("x64");
|
||||
sinon.stub(actionsUtil, "isRunningLocalAction").returns(false);
|
||||
process.env[ActionsEnvVars.RUNNER_ENVIRONMENT] = "github-hosted";
|
||||
sinon.stub(tar, "isZstdAvailable").resolves({
|
||||
available: true,
|
||||
foundZstdBinary: true,
|
||||
});
|
||||
const tag = PER_LANGUAGE_CLI_VERSION.enabledVersions[0].tagName;
|
||||
const assetURL =
|
||||
"https://api.github.com/repos/codeql-testing/action-fork/releases/assets/123";
|
||||
const combinedURL = `${assetURL}4`;
|
||||
const fetchRelease = sinon
|
||||
.stub<Parameters<typeof fetch>, ReturnType<typeof fetch>>()
|
||||
.callsFake(
|
||||
async () =>
|
||||
new Response(
|
||||
JSON.stringify({
|
||||
assets: [
|
||||
{ name: "codeql-bundle-java-linux64.tar.zst", url: assetURL },
|
||||
{
|
||||
name: "codeql-bundle-linux64.tar.zst",
|
||||
url: combinedURL,
|
||||
},
|
||||
],
|
||||
}),
|
||||
{ headers: { "content-type": "application/json" } },
|
||||
),
|
||||
);
|
||||
const client = github.getOctokit("123", {
|
||||
request: { fetch: fetchRelease },
|
||||
});
|
||||
sinon.stub(api, "getApiClient").value(() => client);
|
||||
const authorizationSpy = sinon.spy(api, "getAuthorizationHeaderFor");
|
||||
const extractStub = stubDownloadAndExtract();
|
||||
if (fallback) {
|
||||
extractStub.onFirstCall().rejects(new HTTPError("Not Found", 404));
|
||||
}
|
||||
|
||||
await withTmpDir(async (tmpDir) => {
|
||||
setupActionsVars(tmpDir, tmpDir, {
|
||||
GITHUB_ACTION_REPOSITORY: "codeql-testing/action-fork",
|
||||
});
|
||||
const result = await setupCodeql.setupCodeQLBundle(
|
||||
undefined,
|
||||
SAMPLE_DOTCOM_API_DETAILS,
|
||||
tmpDir,
|
||||
GitHubVariant.DOTCOM,
|
||||
PER_LANGUAGE_CLI_VERSION,
|
||||
["java"],
|
||||
false, // useOverlayAwareDefaultCliVersion
|
||||
createFeatures([Feature.PerLanguageBundles]),
|
||||
getRunnerLogger(true),
|
||||
);
|
||||
|
||||
t.true(fetchRelease.calledTwice);
|
||||
t.is(
|
||||
fetchRelease.firstCall.args[0],
|
||||
`https://api.github.com/repos/codeql-testing/action-fork/releases/tags/${tag}`,
|
||||
);
|
||||
t.is(extractStub.callCount, fallback ? 2 : 1);
|
||||
t.is(extractStub.firstCall.args[0], assetURL);
|
||||
t.is(extractStub.lastCall.args[0], fallback ? combinedURL : assetURL);
|
||||
t.is(authorizationSpy.callCount, extractStub.callCount);
|
||||
t.is(authorizationSpy.firstCall.args[2], assetURL);
|
||||
t.is(
|
||||
authorizationSpy.lastCall.args[2],
|
||||
fallback ? combinedURL : assetURL,
|
||||
);
|
||||
t.is(extractStub.lastCall.args[3], "token token");
|
||||
t.is(result.toolsVersion, MIN_PER_LANGUAGE_BUNDLE_CLI_VERSION);
|
||||
t.is(
|
||||
result.toolsDownloadStatusReport?.bundleLanguage,
|
||||
fallback ? undefined : BuiltInLanguage.java,
|
||||
);
|
||||
t.is(
|
||||
result.toolsDownloadStatusReport?.perLanguageBundleFallback,
|
||||
fallback ? true : undefined,
|
||||
);
|
||||
if (fallback) {
|
||||
t.is(
|
||||
result.codeqlFolder,
|
||||
toolcache.find("CodeQL", MIN_PER_LANGUAGE_BUNDLE_CLI_VERSION),
|
||||
);
|
||||
t.true(fs.existsSync(`${result.codeqlFolder}.complete`));
|
||||
} else {
|
||||
t.is(path.dirname(result.codeqlFolder), tmpDir);
|
||||
t.deepEqual(toolcache.findAllVersions("CodeQL"), []);
|
||||
t.false(fs.existsSync(`${result.codeqlFolder}.complete`));
|
||||
}
|
||||
});
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
for (const bundle of ["per-language", "combined", "fallback"] as const) {
|
||||
test.serial(
|
||||
`setupCodeQLBundle preserves the nightly version for a ${bundle} download`,
|
||||
async (t) => {
|
||||
const expectedDate = "30260213";
|
||||
const expectedTag = `codeql-bundle-${expectedDate}`;
|
||||
const expectedVersion = `0.0.0-${expectedDate}`;
|
||||
const baseURL = `https://github.com/dsp-testing/codeql-cli-nightlies/releases/download/${expectedTag}`;
|
||||
const combinedURL = `${baseURL}/codeql-bundle-linux64.tar.zst`;
|
||||
const perLanguageURL = `${baseURL}/codeql-bundle-javascript-linux64.tar.zst`;
|
||||
const loggedMessages: LoggedMessage[] = [];
|
||||
const logger = getRecordingLogger(loggedMessages);
|
||||
|
||||
stubHostedNightly(expectedTag);
|
||||
delete process.env[EnvVar.HAS_SET_UP_CODEQL];
|
||||
|
||||
const downloadSpy = sinon.spy(setupCodeql, "downloadCodeQL");
|
||||
const extractStub = stubDownloadAndExtract();
|
||||
if (bundle === "fallback") {
|
||||
extractStub.onFirstCall().rejects(new HTTPError("Not Found", 404));
|
||||
}
|
||||
const addDiagnostic = sinon.stub(diagnostics, "addNoLanguageDiagnostic");
|
||||
const features = createFeatures([
|
||||
Feature.PerLanguageBundles,
|
||||
Feature.CleanupToolcacheBundles,
|
||||
]);
|
||||
|
||||
await withTmpDir(async (tmpDir) => {
|
||||
setupActionsVars(tmpDir, tmpDir);
|
||||
const result = await setupCodeql.setupCodeQLBundle(
|
||||
"nightly",
|
||||
SAMPLE_DOTCOM_API_DETAILS,
|
||||
tmpDir,
|
||||
GitHubVariant.DOTCOM,
|
||||
SAMPLE_DEFAULT_CLI_VERSION,
|
||||
bundle === "combined" ? ["javascript", "python"] : ["javascript"],
|
||||
false, // useOverlayAwareDefaultCliVersion
|
||||
features,
|
||||
logger,
|
||||
);
|
||||
|
||||
const source = downloadSpy.firstCall.args[0];
|
||||
t.is(result.toolsVersion, expectedVersion);
|
||||
t.is(result.toolsVersion, source.toolsVersion);
|
||||
t.is(
|
||||
source.bundle.kind,
|
||||
bundle === "combined" ? "combined" : "per-language",
|
||||
);
|
||||
t.is(result.codeqlFolder, extractStub.lastCall.args[2]);
|
||||
t.is(extractStub.callCount, bundle === "fallback" ? 2 : 1);
|
||||
t.is(downloadSpy.callCount, extractStub.callCount);
|
||||
t.is(
|
||||
extractStub.firstCall.args[0],
|
||||
bundle === "combined" ? combinedURL : perLanguageURL,
|
||||
);
|
||||
t.is(
|
||||
extractStub.lastCall.args[0],
|
||||
bundle === "per-language" ? perLanguageURL : combinedURL,
|
||||
);
|
||||
t.is(
|
||||
result.toolsDownloadStatusReport?.bundleLanguage,
|
||||
bundle === "per-language" ? BuiltInLanguage.javascript : undefined,
|
||||
);
|
||||
t.is(
|
||||
result.toolsDownloadStatusReport?.perLanguageBundleFallback,
|
||||
bundle === "fallback" ? true : undefined,
|
||||
);
|
||||
t.is(
|
||||
addDiagnostic
|
||||
.getCalls()
|
||||
.filter(
|
||||
(call) =>
|
||||
call.args[1].source?.id ===
|
||||
"codeql-action/toolcache-bundle-cleanup",
|
||||
).length,
|
||||
1,
|
||||
);
|
||||
if (bundle === "fallback") {
|
||||
t.deepEqual(downloadSpy.secondCall.args[0], {
|
||||
...source,
|
||||
bundle: { kind: "combined", url: combinedURL },
|
||||
});
|
||||
checkExpectedLogMessages(t, loggedMessages, [
|
||||
`No javascript CodeQL bundle was found at ${perLanguageURL}`,
|
||||
]);
|
||||
}
|
||||
if (bundle === "per-language") {
|
||||
t.is(path.dirname(result.codeqlFolder), tmpDir);
|
||||
t.deepEqual(toolcache.findAllVersions("CodeQL"), []);
|
||||
t.false(fs.existsSync(`${result.codeqlFolder}.complete`));
|
||||
} else {
|
||||
t.is(
|
||||
result.codeqlFolder,
|
||||
toolsDownload.getToolcacheDirectory(expectedVersion),
|
||||
);
|
||||
t.true(fs.existsSync(`${result.codeqlFolder}.complete`));
|
||||
|
||||
const cachedResult = await setupCodeql.setupCodeQLBundle(
|
||||
"nightly",
|
||||
SAMPLE_DOTCOM_API_DETAILS,
|
||||
tmpDir,
|
||||
GitHubVariant.DOTCOM,
|
||||
SAMPLE_DEFAULT_CLI_VERSION,
|
||||
["javascript"],
|
||||
false, // useOverlayAwareDefaultCliVersion
|
||||
features,
|
||||
logger,
|
||||
);
|
||||
t.is(cachedResult.toolsSource, setupCodeql.ToolsSource.Toolcache);
|
||||
t.is(cachedResult.toolsVersion, expectedVersion);
|
||||
t.is(cachedResult.codeqlFolder, result.codeqlFolder);
|
||||
t.is(extractStub.callCount, bundle === "fallback" ? 2 : 1);
|
||||
}
|
||||
});
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
for (const asset of [
|
||||
"codeql-bundle-ruby-linux64.tar.zst",
|
||||
"codeql-bundle-%72uby-linux64.tar.zst",
|
||||
]) {
|
||||
test.serial(
|
||||
`setupCodeQLBundle keeps explicitly requested ${asset} out of the toolcache`,
|
||||
async (t) => {
|
||||
const extractStub = stubDownloadAndExtract();
|
||||
const url = `https://github.com/github/codeql-action/releases/download/codeql-bundle-v9.9.9/${asset}`;
|
||||
process.env[ActionsEnvVars.RUNNER_ENVIRONMENT] = "self-hosted";
|
||||
|
||||
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([]),
|
||||
getRunnerLogger(true),
|
||||
);
|
||||
|
||||
t.true(extractStub.calledOnce);
|
||||
t.is(extractStub.firstCall.args[0], url);
|
||||
t.is(result.toolsVersion, "9.9.9");
|
||||
t.is(
|
||||
result.toolsDownloadStatusReport?.bundleLanguage,
|
||||
BuiltInLanguage.ruby,
|
||||
);
|
||||
t.is(path.dirname(result.codeqlFolder), tmpDir);
|
||||
t.deepEqual(toolcache.findAllVersions("CodeQL"), []);
|
||||
t.false(fs.existsSync(`${result.codeqlFolder}.complete`));
|
||||
});
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
for (const error of [
|
||||
new HTTPError("Internal Server Error", 500),
|
||||
new Error("Connection reset"),
|
||||
]) {
|
||||
test.serial(
|
||||
`setupCodeQLBundle does not fall back after ${error.message}`,
|
||||
async (t) => {
|
||||
sinon.stub(process, "platform").value("linux");
|
||||
sinon.stub(process, "arch").value("x64");
|
||||
process.env[ActionsEnvVars.RUNNER_ENVIRONMENT] = "github-hosted";
|
||||
sinon.stub(tar, "isZstdAvailable").resolves({
|
||||
available: true,
|
||||
foundZstdBinary: true,
|
||||
});
|
||||
const extractStub = sinon
|
||||
.stub(toolsDownload, "downloadAndExtract")
|
||||
.rejects(error);
|
||||
|
||||
await withTmpDir(async (tmpDir) => {
|
||||
setupActionsVars(tmpDir, tmpDir);
|
||||
await t.throwsAsync(
|
||||
setupCodeql.setupCodeQLBundle(
|
||||
undefined,
|
||||
SAMPLE_DOTCOM_API_DETAILS,
|
||||
tmpDir,
|
||||
GitHubVariant.DOTCOM,
|
||||
PER_LANGUAGE_CLI_VERSION,
|
||||
["java"],
|
||||
false, // useOverlayAwareDefaultCliVersion
|
||||
createFeatures([Feature.PerLanguageBundles]),
|
||||
getRunnerLogger(true),
|
||||
),
|
||||
{ is: error },
|
||||
);
|
||||
t.true(extractStub.calledOnce);
|
||||
t.true(
|
||||
extractStub.firstCall.args[0].endsWith(
|
||||
"/codeql-bundle-java-linux64.tar.zst",
|
||||
),
|
||||
);
|
||||
});
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
test.serial(
|
||||
"setupCodeQLBundle does not substitute a bundle for an explicitly requested one that is missing",
|
||||
async (t) => {
|
||||
const error = new HTTPError("Not Found", 404);
|
||||
const extractStub = sinon
|
||||
.stub(toolsDownload, "downloadAndExtract")
|
||||
.rejects(error);
|
||||
|
||||
await withTmpDir(async (tmpDir) => {
|
||||
setupActionsVars(tmpDir, tmpDir);
|
||||
await t.throwsAsync(
|
||||
setupCodeql.setupCodeQLBundle(
|
||||
"https://github.com/github/codeql-action/releases/download/codeql-bundle-v9.9.9/codeql-bundle-ruby-linux64.tar.zst",
|
||||
SAMPLE_DOTCOM_API_DETAILS,
|
||||
tmpDir,
|
||||
GitHubVariant.DOTCOM,
|
||||
SAMPLE_DEFAULT_CLI_VERSION,
|
||||
undefined, // rawLanguages
|
||||
false, // useOverlayAwareDefaultCliVersion
|
||||
createFeatures([]),
|
||||
getRunnerLogger(true),
|
||||
),
|
||||
{ is: error },
|
||||
);
|
||||
|
||||
t.true(extractStub.calledOnce);
|
||||
});
|
||||
},
|
||||
);
|
||||
|
||||
test.serial(
|
||||
"getEnabledVersionsWithOverlayBaseDatabases returns flag-enabled versions present in cache, sorted desc",
|
||||
async (t) => {
|
||||
|
||||
Reference in New Issue
Block a user