Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
b5a476b
Disable per-language bundles in the file baseline PR check
henrymercer Sep 29, 2026
5e3132d
Move `defaultSuites` to `config/db-config.ts`
henrymercer Sep 29, 2026
1609a51
Avoid per-language bundles when queries may need other languages' lib…
henrymercer Sep 29, 2026
d8b6f2a
Always use the combined bundle in `setup-codeql`
henrymercer Sep 30, 2026
7816c33
Fix the docs for the `languages` and `analysis-kinds` inputs of `setu…
henrymercer Sep 30, 2026
87a1923
Use a new feature flag for per-language bundles
henrymercer Oct 1, 2026
2da0d29
Omit the feature flag name from the per-language bundle debug log
henrymercer Oct 1, 2026
a98f604
Read the `config` and `queries` inputs once in `init`
henrymercer Oct 1, 2026
a4fbe39
Extract parsing of the `queries` input and the extra queries reposito…
henrymercer Oct 1, 2026
70897a7
Reuse the parsing of query inputs when choosing a bundle
henrymercer Oct 1, 2026
725421c
Explain that the `config` input can configure queries
henrymercer Oct 1, 2026
1bb99cb
Explain what a reason to use the combined bundle means where it's che…
henrymercer Oct 1, 2026
a6cd2a5
Check what the `config` input sets instead of exempting dynamic workf…
henrymercer Oct 1, 2026
ce28f3e
Explain why the file baseline PR check uses the combined bundle
henrymercer Oct 2, 2026
1c0814d
Parse lists of queries with a single function
henrymercer Oct 2, 2026
e869836
Share the check of the properties that Default Setup sets in the `con…
henrymercer Oct 2, 2026
113b18e
Parse the `config` input once
henrymercer Oct 2, 2026
f6a7f00
Point to the Default Setup config schema from the per-language bundle…
henrymercer Oct 2, 2026
a47cc9f
Merge remote-tracking branch 'origin/main' into henrymercer/per-langu…
Copilot Oct 2, 2026
c275b4a
Merge branch 'main' into henrymercer/per-language-pr-check-failures
henrymercer Oct 2, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/workflows/__export-file-baseline-information.yml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

181 changes: 119 additions & 62 deletions lib/entry-points.js

Large diffs are not rendered by default.

4 changes: 4 additions & 0 deletions pr-checks/checks/export-file-baseline-information.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@ installDotNet: true
env:
CODEQL_ACTION_SKIP_FILE_COVERAGE_ON_PRS: false
CODEQL_ACTION_SUBLANGUAGE_FILE_COVERAGE: true
# To balance speed and coverage, we analyze only a single language (JavaScript), but use the
# combined bundle so we can test that baseline information is reported for each language in the
# multi-language source directory.
CODEQL_ACTION_PER_LANGUAGE_BUNDLES: false
Comment thread
mbg marked this conversation as resolved.
steps:
- uses: ./../action/init
id: init
Expand Down
17 changes: 7 additions & 10 deletions setup-codeql/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,19 +21,16 @@ inputs:
required: false
languages:
description: >-
A comma-separated list of CodeQL languages that will be analyzed in subsequent
`github/codeql-action/init` and `github/codeql-action/analyze` invocations. If specified, the
Action may use this list to select a CodeQL CLI version that is best suited to analyzing those
languages, for example by preferring a version that has a cached overlay-base database for the
specified languages. This input is not remembered and must also be passed to
`github/codeql-action/init`.
A comma-separated list of CodeQL languages that the installed CodeQL CLI will be used to
analyze. If specified, the Action may use this list to select a CodeQL CLI version that is
best suited to analyzing those languages, for example by preferring a version that has a
cached overlay-base database for the specified languages.
required: false
analysis-kinds:
description: >-
[Internal] A comma-separated list of analysis kinds that subsequent
`github/codeql-action/init` invocations will enable. If specified, the Action may use this
list to select a CodeQL CLI version that is best suited to those analysis kinds. This input is
not remembered and must also be passed to `github/codeql-action/init`.
[Internal] A comma-separated list of analysis kinds that the installed CodeQL CLI will be used
for. If specified, the Action may use this list to select a CodeQL CLI version that is best
suited to those analysis kinds.

Available options are the same as for the `analysis-kinds` input on the `init` Action.
default: 'code-scanning'
Expand Down
2 changes: 1 addition & 1 deletion src/analyze.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,12 @@ import * as sinon from "sinon";
import { CodeQuality, CodeScanning, RiskAssessment } from "./analyses";
import {
runQueries,
defaultSuites,
resolveQuerySuiteAlias,
addSarifExtension,
diffRangeExtensionPackContents,
} from "./analyze";
import { createStubCodeQL } from "./codeql";
import { defaultSuites } from "./config/db-config";
import { Feature } from "./feature-flags";
import { BuiltInLanguage } from "./languages";
import { getRunnerLogger } from "./logging";
Expand Down
10 changes: 1 addition & 9 deletions src/analyze.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { getTemporaryDirectory } from "./actions-util";
import * as analyses from "./analyses";
import { setupCppAutobuild } from "./autobuild";
import { type CodeQL } from "./codeql";
import { defaultSuites } from "./config/db-config";
import * as configUtils from "./config-utils";
import {
getCsharpTempDependencyDir,
Expand Down Expand Up @@ -357,15 +358,6 @@ dataExtensions:
return diffRangeDir;
}

// A set of default query suite names that are understood by the CLI.
export const defaultSuites: Set<string> = new Set([
"security-experimental",
"security-extended",
"security-and-quality",
"code-quality",
"code-scanning",
]);

/**
* If `maybeSuite` is the name of a default query suite, it is resolved into the corresponding
* query suite name for the given `language`. Otherwise, `maybeSuite` is returned as is.
Expand Down
10 changes: 10 additions & 0 deletions src/codeql.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ async function installIntoToolcache({
? { enabledVersions: [{ cliVersion, tagName }] }
: SAMPLE_DEFAULT_CLI_VERSION,
undefined, // rawLanguages
undefined, // otherLanguagePacksReason
false, // useOverlayAwareDefaultCliVersion
createFeatures([]),
getRunnerLogger(true),
Expand Down Expand Up @@ -172,6 +173,7 @@ test.serial(
util.GitHubVariant.DOTCOM,
SAMPLE_DEFAULT_CLI_VERSION,
undefined, // rawLanguages
undefined, // otherLanguagePacksReason
false, // useOverlayAwareDefaultCliVersion
features,
getRunnerLogger(true),
Expand Down Expand Up @@ -207,6 +209,7 @@ test.serial(
util.GitHubVariant.DOTCOM,
SAMPLE_DEFAULT_CLI_VERSION,
undefined, // rawLanguages
undefined, // otherLanguagePacksReason
false, // useOverlayAwareDefaultCliVersion
features,
getRunnerLogger(true),
Expand Down Expand Up @@ -246,6 +249,7 @@ test.serial(
util.GitHubVariant.DOTCOM,
SAMPLE_DEFAULT_CLI_VERSION,
undefined, // rawLanguages
undefined, // otherLanguagePacksReason
false, // useOverlayAwareDefaultCliVersion
features,
getRunnerLogger(true),
Expand Down Expand Up @@ -355,6 +359,7 @@ for (const {
util.GitHubVariant.DOTCOM,
SAMPLE_DEFAULT_CLI_VERSION,
undefined, // rawLanguages
undefined, // otherLanguagePacksReason
false, // useOverlayAwareDefaultCliVersion
features,
getRunnerLogger(true),
Expand Down Expand Up @@ -397,6 +402,7 @@ for (const toolcacheVersion of [
util.GitHubVariant.DOTCOM,
SAMPLE_DEFAULT_CLI_VERSION,
undefined, // rawLanguages
undefined, // otherLanguagePacksReason
false, // useOverlayAwareDefaultCliVersion
features,
getRunnerLogger(true),
Expand Down Expand Up @@ -441,6 +447,7 @@ test.serial(
],
},
undefined, // rawLanguages
undefined, // otherLanguagePacksReason
false, // useOverlayAwareDefaultCliVersion
features,
getRunnerLogger(true),
Expand Down Expand Up @@ -487,6 +494,7 @@ test.serial(
],
},
undefined, // rawLanguages
undefined, // otherLanguagePacksReason
false, // useOverlayAwareDefaultCliVersion
features,
getRunnerLogger(true),
Expand Down Expand Up @@ -526,6 +534,7 @@ test.serial(
util.GitHubVariant.DOTCOM,
SAMPLE_DEFAULT_CLI_VERSION,
undefined, // rawLanguages
undefined, // otherLanguagePacksReason
false, // useOverlayAwareDefaultCliVersion
features,
getRunnerLogger(true),
Expand Down Expand Up @@ -567,6 +576,7 @@ test.serial(
util.GitHubVariant.DOTCOM,
SAMPLE_DEFAULT_CLI_VERSION,
undefined, // rawLanguages
undefined, // otherLanguagePacksReason
false, // useOverlayAwareDefaultCliVersion
features,
getRunnerLogger(true),
Expand Down
5 changes: 5 additions & 0 deletions src/codeql.ts
Original file line number Diff line number Diff line change
Expand Up @@ -302,6 +302,9 @@ export function isDiskConfigurationError(e: unknown): boolean {
* @param variant
* @param defaultCliVersion
* @param rawLanguages Raw set of languages.
* @param otherLanguagePacksReason Why the CodeQL CLI may need packs for languages other than
* `rawLanguages`, or `undefined` if it won't. If defined, the combined bundle is used. See
* `PerLanguageBundleOptions.otherLanguagePacksReason`.
* @param useOverlayAwareDefaultCliVersion Whether to select an overlay-aware default CLI version.
* @param features Information about the features that are enabled.
* @param logger
Expand All @@ -316,6 +319,7 @@ export async function setupCodeQL(
variant: util.GitHubVariant,
defaultCliVersion: CodeQLDefaultVersionInfo,
rawLanguages: string[] | undefined,
otherLanguagePacksReason: string | undefined,
useOverlayAwareDefaultCliVersion: boolean,
features: FeatureEnablement,
logger: Logger,
Expand All @@ -339,6 +343,7 @@ export async function setupCodeQL(
variant,
defaultCliVersion,
rawLanguages,
otherLanguagePacksReason,
useOverlayAwareDefaultCliVersion,
features,
logger,
Expand Down
89 changes: 68 additions & 21 deletions src/config-utils.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -473,6 +473,9 @@ const simpleConfigFileContents = `
queries:
- uses: ./foo_file`;

/** The configuration in `simpleConfigFileContents`, as parsed from the `config` input. */
const simpleConfigInput = yaml.load(simpleConfigFileContents) as UserConfig;

/** A less minimal configuration file. */
const otherConfigFileContents = `
name: my config
Expand Down Expand Up @@ -591,7 +594,7 @@ test.serial(
createTestInitConfigInputs({
languagesInput,
configFile: configFilePath,
configInput,
configInput: yaml.load(configInput) as UserConfig,
tempDir,
codeql,
workspacePath: tempDir,
Expand Down Expand Up @@ -2343,6 +2346,40 @@ test("applyIncrementalAnalysisSettings: adds exclusions for diff-informed-only r
]);
});

test("parseConfigInput - returns undefined when the input isn't set", async (t) => {
await callee(configUtils.parseConfigInput)
.withArgs(undefined)
.passes(t.is, undefined);
});

test("parseConfigInput - parses the input as YAML", async (t) => {
await callee(configUtils.parseConfigInput)
.withArgs(simpleConfigFileContents)
.passes(t.deepEqual, {
name: "my config",
queries: [{ uses: "./foo_file" }],
});
});

test("parseConfigInput - throws a ConfigurationError naming the input if it isn't valid YAML", async (t) => {
await callee(configUtils.parseConfigInput)
.withArgs("queries: [")
.throws(t, {
instanceOf: ConfigurationError,
message: /^Cannot parse "`config` input"/,
});
});

test("parseConfigInput - throws a ConfigurationError naming the input if validation fails", async (t) => {
await callee(configUtils.parseConfigInput)
.withFeatures([Feature.ValidateDbConfig])
.withArgs("queries: 1")
.throws(t, {
instanceOf: ConfigurationError,
message: /^The configuration file "`config` input" is invalid/,
});
});

test("determineUserConfig - empty config when neither input is specified", async (t) => {
await withTmpDir(async (tmpDir) => {
const target = callee(configUtils.determineUserConfig)
Expand Down Expand Up @@ -2413,7 +2450,7 @@ test("determineUserConfig - loads config input", async (t) => {
const expectedConfigPath = configUtils.userConfigFromActionPath(tmpDir);

const inputs = createTestInitConfigInputs({
configInput: simpleConfigFileContents,
configInput: simpleConfigInput,
configFile: undefined,
workspacePath: tmpDir,
});
Expand All @@ -2423,17 +2460,15 @@ test("determineUserConfig - loads config input", async (t) => {

await target
// The input source and path of the generated config file should have been logged.
.logs(
t,
"Using config from action input:",
`Using configuration file: ${expectedConfigPath}`,
)
// The message about no configuration input and
// the warning about both inputs should not have been logged.
.logs(t, `Using config from action input: ${expectedConfigPath}`)
// The message about no configuration input and the warning about both inputs should not have
// been logged. The generated config file isn't loaded, since the `config` input has already
// been parsed.
.notLogs(
t,
"No configuration file was provided",
"Both a config file and config input were provided. Ignoring config file.",
`Using configuration file: ${expectedConfigPath}`,
)
// The loaded configuration should match `simpleConfigFileContents`.
.passes(t.deepEqual, {
Expand All @@ -2452,7 +2487,7 @@ test("determineUserConfig - ignores config file input when both specified", asyn
const expectedConfigPath = configUtils.userConfigFromActionPath(tmpDir);

const inputs = createTestInitConfigInputs({
configInput: simpleConfigFileContents,
configInput: simpleConfigInput,
configFile: configFilePath,
workspacePath: tmpDir,
});
Expand All @@ -2466,10 +2501,14 @@ test("determineUserConfig - ignores config file input when both specified", asyn
.logs(
t,
`Using config from action input: ${expectedConfigPath}`,
`Using configuration file: ${expectedConfigPath}`,
"Both a config file and config input were provided. Ignoring config file.",
)
.notLogs(t, "No configuration file was provided")
// The generated config file isn't loaded, since the `config` input has already been parsed.
.notLogs(
t,
"No configuration file was provided",
`Using configuration file: ${expectedConfigPath}`,
)
// The loaded configuration should match `simpleConfigFileContents`.
.passes(t.deepEqual, {
name: "my config",
Expand All @@ -2481,12 +2520,12 @@ test("determineUserConfig - ignores config file input when both specified", asyn
});
});

/** A `config` input that we might get from Default Setup. */
const defaultSetupConfigInput = `
/** The configuration from a `config` input that we might get from Default Setup. */
const defaultSetupConfigInput = yaml.load(`
threat-models: [local, remote]
default-setup:
org:
model-packs: [foo, bar]`;
model-packs: [foo, bar]`) as UserConfig;

test("determineUserConfig - merges configs if FF is enabled in Default Setup", async (t) => {
await withTmpDir(async (tmpDir) => {
Expand Down Expand Up @@ -2555,7 +2594,7 @@ test("determineUserConfig - ignores config file input in Default Setup if FF is
.withArgs(
tmpDir,
createTestInitConfigInputs({
configInput: simpleConfigFileContents,
configInput: simpleConfigInput,
configFile: configFilePath,
workspacePath: tmpDir,
}),
Expand All @@ -2565,10 +2604,14 @@ test("determineUserConfig - ignores config file input in Default Setup if FF is
.logs(
t,
`Using config from action input: ${expectedConfigPath}`,
`Using configuration file: ${expectedConfigPath}`,
"Both a config file and config input were provided. Ignoring config file.",
)
.notLogs(t, "No configuration file was provided")
// The generated config file isn't loaded, since the `config` input has already been parsed.
.notLogs(
t,
"No configuration file was provided",
`Using configuration file: ${expectedConfigPath}`,
)
.passes(t.deepEqual, {
name: "my config",
queries: [{ uses: "./foo_file" }],
Expand All @@ -2587,7 +2630,7 @@ test("determineUserConfig - ignores config file input outside Default Setup if F
.withArgs(
tmpDir,
createTestInitConfigInputs({
configInput: simpleConfigFileContents,
configInput: simpleConfigInput,
configFile: configFilePath,
workspacePath: tmpDir,
}),
Expand All @@ -2597,10 +2640,14 @@ test("determineUserConfig - ignores config file input outside Default Setup if F
.logs(
t,
`Using config from action input: ${expectedConfigPath}`,
`Using configuration file: ${expectedConfigPath}`,
"Both a config file and config input were provided. Ignoring config file.",
)
.notLogs(t, "No configuration file was provided")
// The generated config file isn't loaded, since the `config` input has already been parsed.
.notLogs(
t,
"No configuration file was provided",
`Using configuration file: ${expectedConfigPath}`,
)
.passes(t.deepEqual, {
name: "my config",
queries: [{ uses: "./foo_file" }],
Expand Down
Loading
Loading