mirror of
https://github.com/github/codeql-action.git
synced 2026-11-09 06:29:52 +00:00
Merge pull request #4244 from github/henrymercer/graduate-per-language-bundles
Use per-language CodeQL bundles by default
This commit is contained in:
@@ -143,11 +143,6 @@ export enum Feature {
|
||||
OverlayAnalysisStatusCheck = "overlay_analysis_status_check",
|
||||
/** Controls whether overlay build failures on the default branch are stored in the Actions cache. */
|
||||
OverlayAnalysisStatusSave = "overlay_analysis_status_save",
|
||||
/**
|
||||
* Controls whether we may download a bundle containing only the single language being analysed,
|
||||
* rather than the combined bundle that contains every language.
|
||||
*/
|
||||
PerLanguageBundles = "per_language_bundles_v2",
|
||||
QaTelemetryEnabled = "qa_telemetry_enabled",
|
||||
/** Routes (some) API requests through the registry proxy. */
|
||||
ProxyApiRequests = "proxy_api_requests",
|
||||
@@ -393,11 +388,6 @@ export const featureConfig = {
|
||||
envVar: "CODEQL_ACTION_OVERLAY_ANALYSIS_SKIP_RESOURCE_CHECKS",
|
||||
minimumVersion: undefined,
|
||||
},
|
||||
[Feature.PerLanguageBundles]: {
|
||||
defaultValue: false,
|
||||
envVar: "CODEQL_ACTION_PER_LANGUAGE_BUNDLES",
|
||||
minimumVersion: undefined,
|
||||
},
|
||||
[Feature.QaTelemetryEnabled]: {
|
||||
defaultValue: false,
|
||||
envVar: "CODEQL_ACTION_QA_TELEMETRY",
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import test from "ava";
|
||||
|
||||
import { ActionsEnvVars } from "./environment";
|
||||
import { Feature } from "./feature-flags";
|
||||
import { BuiltInLanguage } from "./languages";
|
||||
import {
|
||||
getOtherLanguagePacksReason,
|
||||
@@ -12,7 +11,6 @@ import {
|
||||
} from "./per-language-bundles";
|
||||
import { BundlePlatform } from "./platform";
|
||||
import {
|
||||
createFeatures,
|
||||
getRecordingLogger,
|
||||
getTestEnv,
|
||||
initAllState,
|
||||
@@ -40,7 +38,6 @@ async function checkEligibility(
|
||||
env: getTestEnv({
|
||||
[ActionsEnvVars.RUNNER_ENVIRONMENT]: "github-hosted",
|
||||
}),
|
||||
features: createFeatures([Feature.PerLanguageBundles]),
|
||||
...stateOverrides,
|
||||
}),
|
||||
{ ...ELIGIBLE_OPTIONS, ...overrides },
|
||||
@@ -145,27 +142,6 @@ test("getPerLanguageBundleLanguage requires a supported release version", async
|
||||
t.is(await checkEligibility({ cliVersion: "2.27.1" }), BuiltInLanguage.java);
|
||||
});
|
||||
|
||||
test("getPerLanguageBundleLanguage requires the feature flag", async (t) => {
|
||||
t.is(await checkEligibility({}, { features: createFeatures([]) }), undefined);
|
||||
});
|
||||
|
||||
test("getPerLanguageBundleLanguage explains a disabled feature before checking eligibility", async (t) => {
|
||||
const messages: LoggedMessage[] = [];
|
||||
const language = await getPerLanguageBundleLanguage(
|
||||
initAllState({
|
||||
features: createFeatures([]),
|
||||
logger: getRecordingLogger(messages, { logToConsole: false }),
|
||||
}),
|
||||
{ ...ELIGIBLE_OPTIONS, rawLanguages: undefined, cliVersion: undefined },
|
||||
);
|
||||
|
||||
t.is(language, undefined);
|
||||
t.deepEqual(
|
||||
messages.map((message) => message.message),
|
||||
["Not using a per-language CodeQL bundle since the feature is disabled."],
|
||||
);
|
||||
});
|
||||
|
||||
test("getPerLanguageBundleLanguage skips only the release version check for the latest nightly", async (t) => {
|
||||
const nightly = { isLatestNightly: true, cliVersion: undefined };
|
||||
t.is(await checkEligibility(nightly), BuiltInLanguage.java);
|
||||
@@ -181,10 +157,6 @@ test("getPerLanguageBundleLanguage skips only the release version check for the
|
||||
]) {
|
||||
t.is(await checkEligibility({ ...nightly, ...overrides }), undefined);
|
||||
}
|
||||
t.is(
|
||||
await checkEligibility(nightly, { features: createFeatures([]) }),
|
||||
undefined,
|
||||
);
|
||||
t.is(
|
||||
await checkEligibility(nightly, {
|
||||
env: getTestEnv({ [ActionsEnvVars.RUNNER_ENVIRONMENT]: "self-hosted" }),
|
||||
|
||||
@@ -9,7 +9,6 @@ import {
|
||||
QuerySpec,
|
||||
UserConfig,
|
||||
} from "./config/db-config";
|
||||
import { Feature } from "./feature-flags";
|
||||
import { RepositoryPropertyName } from "./feature-flags/properties";
|
||||
import { BuiltInLanguage, parseBuiltInLanguage } from "./languages";
|
||||
import { BundlePlatform } from "./platform";
|
||||
@@ -139,14 +138,10 @@ export interface PerLanguageBundleOptions {
|
||||
}
|
||||
|
||||
/** Returns the eligible bundle language, or undefined for the combined bundle. */
|
||||
export async function getPerLanguageBundleLanguage(
|
||||
{
|
||||
env,
|
||||
features,
|
||||
logger,
|
||||
}: ActionState<["Logger", "ReadOnlyEnv", "FeatureFlags"]>,
|
||||
export function getPerLanguageBundleLanguage(
|
||||
action: ActionState<["Logger", "ReadOnlyEnv"]>,
|
||||
options: PerLanguageBundleOptions,
|
||||
): Promise<BuiltInLanguage | undefined> {
|
||||
): BuiltInLanguage | undefined {
|
||||
const {
|
||||
rawLanguages,
|
||||
otherLanguagePacksReason,
|
||||
@@ -158,14 +153,12 @@ export async function getPerLanguageBundleLanguage(
|
||||
} = options;
|
||||
|
||||
const explain = (reason: string) => {
|
||||
logger.debug(`Not using a per-language CodeQL bundle since ${reason}.`);
|
||||
action.logger.debug(
|
||||
`Not using a per-language CodeQL bundle since ${reason}.`,
|
||||
);
|
||||
return undefined;
|
||||
};
|
||||
|
||||
if (!(await features.getValue(Feature.PerLanguageBundles))) {
|
||||
return explain("the feature is disabled");
|
||||
}
|
||||
|
||||
// A defined reason means the CodeQL CLI may need packs for other languages, for example because
|
||||
// of the configured queries. That applies whichever languages were requested, so check it first
|
||||
// to avoid suggesting that requesting a single language would be enough.
|
||||
@@ -197,7 +190,7 @@ export async function getPerLanguageBundleLanguage(
|
||||
return explain(`we are running against ${variant}`);
|
||||
}
|
||||
|
||||
if (!isGitHubHostedRunner(env)) {
|
||||
if (!isGitHubHostedRunner(action.env)) {
|
||||
// Per-language installs stay out of the toolcache; self-hosted runners should retain
|
||||
// the reusable combined bundle instead.
|
||||
return explain("the job is not running on a GitHub-hosted runner");
|
||||
|
||||
@@ -439,7 +439,7 @@ test.serial(
|
||||
tmpDir,
|
||||
GitHubVariant.DOTCOM,
|
||||
SAMPLE_DEFAULT_CLI_VERSION,
|
||||
["javascript"],
|
||||
undefined, // rawLanguages
|
||||
undefined, // otherLanguagePacksReason
|
||||
false, // useOverlayAwareDefaultCliVersion
|
||||
features,
|
||||
@@ -633,7 +633,7 @@ for (const toolsInput of ["nightly", "nightly-latest"]) {
|
||||
SAMPLE_DOTCOM_API_DETAILS,
|
||||
GitHubVariant.DOTCOM,
|
||||
true, // tarSupportsZstd
|
||||
createFeatures([Feature.PerLanguageBundles]),
|
||||
createFeatures([]),
|
||||
new RecordingLogger(),
|
||||
);
|
||||
|
||||
@@ -664,24 +664,16 @@ test.serial(
|
||||
|
||||
await withTmpDir(async (tmpDir) => {
|
||||
setupActionsVars(tmpDir, tmpDir);
|
||||
for (const { languages, otherLanguagePacksReason, features } of [
|
||||
// The per-language feature is disabled.
|
||||
{
|
||||
languages: ["java"],
|
||||
otherLanguagePacksReason: undefined,
|
||||
features: createFeatures([]),
|
||||
},
|
||||
for (const { languages, otherLanguagePacksReason } of [
|
||||
// More than one language requires a combined bundle.
|
||||
{
|
||||
languages: ["java", "python"],
|
||||
otherLanguagePacksReason: undefined,
|
||||
features: createFeatures([Feature.PerLanguageBundles]),
|
||||
},
|
||||
// The configured queries may need library packs for other languages.
|
||||
{
|
||||
languages: ["java"],
|
||||
otherLanguagePacksReason: "an example reason",
|
||||
features: createFeatures([Feature.PerLanguageBundles]),
|
||||
},
|
||||
]) {
|
||||
const source = await setupCodeql.getCodeQLSource(
|
||||
@@ -693,7 +685,7 @@ test.serial(
|
||||
SAMPLE_DOTCOM_API_DETAILS,
|
||||
GitHubVariant.DOTCOM,
|
||||
true, // tarSupportsZstd
|
||||
features,
|
||||
createFeatures([]),
|
||||
new RecordingLogger(),
|
||||
);
|
||||
|
||||
@@ -709,58 +701,48 @@ test.serial(
|
||||
},
|
||||
);
|
||||
|
||||
for (const perLanguageBundles of [false, true]) {
|
||||
test.serial(
|
||||
`getCodeQLSource uses the latest ${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}`;
|
||||
const latestNightlyRequest = stubHostedNightly(expectedTag);
|
||||
test.serial(
|
||||
"getCodeQLSource uses the latest per-language 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}`;
|
||||
const latestNightlyRequest = 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"],
|
||||
undefined, // otherLanguagePacksReason
|
||||
false, // useOverlayAwareDefaultCliVersion
|
||||
SAMPLE_DOTCOM_API_DETAILS,
|
||||
GitHubVariant.DOTCOM,
|
||||
true, // tarSupportsZstd
|
||||
createFeatures(
|
||||
perLanguageBundles
|
||||
? [Feature.ForceNightly, Feature.PerLanguageBundles]
|
||||
: [Feature.ForceNightly],
|
||||
),
|
||||
new RecordingLogger(),
|
||||
);
|
||||
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"],
|
||||
undefined, // otherLanguagePacksReason
|
||||
false, // useOverlayAwareDefaultCliVersion
|
||||
SAMPLE_DOTCOM_API_DETAILS,
|
||||
GitHubVariant.DOTCOM,
|
||||
true, // tarSupportsZstd
|
||||
createFeatures([Feature.ForceNightly]),
|
||||
new RecordingLogger(),
|
||||
);
|
||||
|
||||
t.is(source.sourceType, "download");
|
||||
t.true(latestNightlyRequest.calledOnce);
|
||||
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 },
|
||||
);
|
||||
}
|
||||
});
|
||||
},
|
||||
);
|
||||
}
|
||||
t.is(source.sourceType, "download");
|
||||
t.true(latestNightlyRequest.calledOnce);
|
||||
if (source.sourceType === "download") {
|
||||
t.deepEqual(source.bundle, {
|
||||
kind: "per-language",
|
||||
language: BuiltInLanguage.java,
|
||||
url: `${baseURL}/codeql-bundle-java-linux64.tar.zst`,
|
||||
combinedBundleURL: `${baseURL}/codeql-bundle-linux64.tar.zst`,
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
);
|
||||
|
||||
for (const date of ["20200101", "30260213"]) {
|
||||
for (const bundle of ["combined", "per-language"] as const) {
|
||||
test.serial(
|
||||
`getCodeQLSource preserves an explicit ${bundle} nightly URL for ${date}`,
|
||||
`getCodeQLSource preserves an explicit ${bundle} nightly URL for ${date}${
|
||||
bundle === "per-language" ? " on GHES" : ""
|
||||
}`,
|
||||
async (t) => {
|
||||
const latestNightlyRequest = stubHostedNightly(
|
||||
"codeql-bundle-30260213",
|
||||
@@ -770,7 +752,9 @@ for (const date of ["20200101", "30260213"]) {
|
||||
? "codeql-bundle-linux64.tar.zst"
|
||||
: "codeql-bundle-java-linux64.tar.zst";
|
||||
const url = `https://github.com/dsp-testing/codeql-cli-nightlies/releases/download/codeql-bundle-${date}/${asset}`;
|
||||
const features = createFeatures([Feature.PerLanguageBundles]);
|
||||
const features = createFeatures([]);
|
||||
const variant =
|
||||
bundle === "per-language" ? GitHubVariant.GHES : GitHubVariant.DOTCOM;
|
||||
const logger = getRecordingLogger([], { logToConsole: false });
|
||||
const error = new HTTPError("Not Found", 404);
|
||||
const extractStub = sinon
|
||||
@@ -786,7 +770,7 @@ for (const date of ["20200101", "30260213"]) {
|
||||
undefined, // otherLanguagePacksReason
|
||||
false,
|
||||
SAMPLE_DOTCOM_API_DETAILS,
|
||||
GitHubVariant.DOTCOM,
|
||||
variant,
|
||||
true,
|
||||
features,
|
||||
logger,
|
||||
@@ -808,7 +792,7 @@ for (const date of ["20200101", "30260213"]) {
|
||||
url,
|
||||
SAMPLE_DOTCOM_API_DETAILS,
|
||||
tmpDir,
|
||||
GitHubVariant.DOTCOM,
|
||||
variant,
|
||||
SAMPLE_DEFAULT_CLI_VERSION,
|
||||
["java"],
|
||||
undefined, // otherLanguagePacksReason
|
||||
@@ -1262,7 +1246,7 @@ test.serial(
|
||||
SAMPLE_DOTCOM_API_DETAILS,
|
||||
GitHubVariant.DOTCOM,
|
||||
true, // tarSupportsZstd
|
||||
createFeatures([Feature.PerLanguageBundles]),
|
||||
createFeatures([]),
|
||||
new RecordingLogger(),
|
||||
);
|
||||
|
||||
@@ -1295,13 +1279,16 @@ test.serial(
|
||||
|
||||
await withTmpDir(async (tmpDir) => {
|
||||
setupActionsVars(tmpDir, tmpDir);
|
||||
for (const { otherLanguagePacksReason, features } of [
|
||||
// The per-language feature is disabled.
|
||||
{ otherLanguagePacksReason: undefined, features: createFeatures([]) },
|
||||
for (const { otherLanguagePacksReason, variant } of [
|
||||
// Automatic per-language selection is limited to GitHub.com.
|
||||
{
|
||||
otherLanguagePacksReason: undefined,
|
||||
variant: GitHubVariant.GHES,
|
||||
},
|
||||
// The configured queries may need library packs for other languages.
|
||||
{
|
||||
otherLanguagePacksReason: "an example reason",
|
||||
features: createFeatures([Feature.PerLanguageBundles]),
|
||||
variant: GitHubVariant.DOTCOM,
|
||||
},
|
||||
]) {
|
||||
const source = await setupCodeql.getCodeQLSource(
|
||||
@@ -1311,9 +1298,9 @@ test.serial(
|
||||
otherLanguagePacksReason,
|
||||
false, // useOverlayAwareDefaultCliVersion
|
||||
SAMPLE_DOTCOM_API_DETAILS,
|
||||
GitHubVariant.DOTCOM,
|
||||
variant,
|
||||
true, // tarSupportsZstd
|
||||
features,
|
||||
createFeatures([]),
|
||||
new RecordingLogger(),
|
||||
);
|
||||
|
||||
@@ -1383,7 +1370,7 @@ for (const fallback of [false, true]) {
|
||||
["java"],
|
||||
undefined, // otherLanguagePacksReason
|
||||
false, // useOverlayAwareDefaultCliVersion
|
||||
createFeatures([Feature.PerLanguageBundles]),
|
||||
createFeatures([]),
|
||||
new RecordingLogger(),
|
||||
);
|
||||
|
||||
@@ -1463,7 +1450,7 @@ for (const bundle of ["per-language", "combined", "fallback"] as const) {
|
||||
};
|
||||
});
|
||||
const addDiagnostic = sinon.stub(diagnostics, "addNoLanguageDiagnostic");
|
||||
const features = createFeatures([Feature.PerLanguageBundles]);
|
||||
const features = createFeatures([]);
|
||||
|
||||
await withTmpDir(async (tmpDir) => {
|
||||
setupActionsVars(tmpDir, tmpDir);
|
||||
@@ -1648,7 +1635,7 @@ for (const error of [
|
||||
["java"],
|
||||
undefined, // otherLanguagePacksReason
|
||||
false, // useOverlayAwareDefaultCliVersion
|
||||
createFeatures([Feature.PerLanguageBundles]),
|
||||
createFeatures([]),
|
||||
new RecordingLogger(),
|
||||
),
|
||||
{ is: error },
|
||||
|
||||
@@ -364,7 +364,7 @@ export async function getCodeQLSource(
|
||||
);
|
||||
}
|
||||
bundle = await getLatestNightlyBundle(
|
||||
{ env: getEnv(), features, logger },
|
||||
{ env: getEnv(), logger },
|
||||
rawLanguages,
|
||||
otherLanguagePacksReason,
|
||||
variant,
|
||||
@@ -605,17 +605,14 @@ export async function getCodeQLSource(
|
||||
|
||||
const action = { env: getEnv(), logger };
|
||||
const platform = getBundlePlatform();
|
||||
const perLanguageBundleLanguage = await getPerLanguageBundleLanguage(
|
||||
{ ...action, features },
|
||||
{
|
||||
rawLanguages,
|
||||
otherLanguagePacksReason,
|
||||
cliVersion,
|
||||
compressionMethod,
|
||||
platform,
|
||||
variant,
|
||||
},
|
||||
);
|
||||
const perLanguageBundleLanguage = getPerLanguageBundleLanguage(action, {
|
||||
rawLanguages,
|
||||
otherLanguagePacksReason,
|
||||
cliVersion,
|
||||
compressionMethod,
|
||||
platform,
|
||||
variant,
|
||||
});
|
||||
|
||||
// Resolves the combined or per-language bundle URL for the requested release.
|
||||
const resolveBundleURL = (language?: BuiltInLanguage) =>
|
||||
@@ -1043,7 +1040,7 @@ function getTempExtractionDir(tempDir: string) {
|
||||
* Records the combined bundle URL from that release for use if the selected asset is missing.
|
||||
*/
|
||||
async function getLatestNightlyBundle(
|
||||
action: ActionState<["Logger", "ReadOnlyEnv", "FeatureFlags"]>,
|
||||
action: ActionState<["Logger", "ReadOnlyEnv"]>,
|
||||
rawLanguages: string[] | undefined,
|
||||
otherLanguagePacksReason: string | undefined,
|
||||
variant: util.GitHubVariant,
|
||||
@@ -1059,7 +1056,7 @@ async function getLatestNightlyBundle(
|
||||
: "gzip";
|
||||
|
||||
const platform = getBundlePlatform();
|
||||
const language = await getPerLanguageBundleLanguage(action, {
|
||||
const language = getPerLanguageBundleLanguage(action, {
|
||||
rawLanguages,
|
||||
otherLanguagePacksReason,
|
||||
cliVersion: undefined,
|
||||
|
||||
Reference in New Issue
Block a user