mirror of
https://github.com/github/codeql-action.git
synced 2026-10-03 09:14:58 +00:00
Use applyAnalysisKindConfig in loadUserConfig
This commit is contained in:
34
lib/entry-points.js
generated
34
lib/entry-points.js
generated
@@ -148115,6 +148115,24 @@ var ORG_SCHEMA = {
|
||||
var DEFAULT_SETUP_SCHEMA = {
|
||||
org: optional(object(ORG_SCHEMA))
|
||||
};
|
||||
function hasAnalysisKindKey(analysisKind, config) {
|
||||
return analysisKind in config && typeof config[analysisKind] === "object";
|
||||
}
|
||||
function removeAnalysisKindConfigs(config) {
|
||||
const configWithoutScopes = { ...config };
|
||||
for (const kind of Object.values(AnalysisKind)) {
|
||||
delete configWithoutScopes[kind];
|
||||
}
|
||||
return configWithoutScopes;
|
||||
}
|
||||
function applyAnalysisKindConfig(analysisKind, config) {
|
||||
const configWithoutScopes = removeAnalysisKindConfigs(config);
|
||||
if (!hasAnalysisKindKey(analysisKind, config)) {
|
||||
return configWithoutScopes;
|
||||
}
|
||||
const analysisKindSpecificConfig = config[analysisKind];
|
||||
return { ...configWithoutScopes, ...analysisKindSpecificConfig };
|
||||
}
|
||||
var DEFAULT_SETUP_CONFIG_SCHEMA = {
|
||||
"threat-models": optional(array(string)),
|
||||
"default-setup": optional(
|
||||
@@ -149391,7 +149409,7 @@ async function downloadCacheWithTime(codeQL, languages, logger) {
|
||||
const trapCacheDownloadTime = import_perf_hooks.performance.now() - start;
|
||||
return { trapCaches, trapCacheDownloadTime };
|
||||
}
|
||||
async function loadUserConfig(actionState, configFile, workspacePath, apiDetails, tempDir) {
|
||||
async function loadUserConfig(actionState, analysisKinds, configFile, workspacePath, apiDetails, tempDir) {
|
||||
let config;
|
||||
if (isLocal(configFile)) {
|
||||
if (configFile !== userConfigFromActionPath(tempDir)) {
|
||||
@@ -149412,7 +149430,17 @@ async function loadUserConfig(actionState, configFile, workspacePath, apiDetails
|
||||
}
|
||||
config = await getRemoteConfig(actionState, configFile, apiDetails);
|
||||
}
|
||||
return config;
|
||||
const allowScopedConfig = await actionState.features.getValue(
|
||||
"scoped_configurations" /* ScopedConfigurations */
|
||||
);
|
||||
if (allowScopedConfig && analysisKinds.length === 1) {
|
||||
return applyAnalysisKindConfig(analysisKinds[0], config);
|
||||
} else if (allowScopedConfig) {
|
||||
actionState.logger.info(
|
||||
`Ignoring '${"scoped_configurations" /* ScopedConfigurations */}' feature, because multiple analysis kinds are enabled.`
|
||||
);
|
||||
}
|
||||
return removeAnalysisKindConfigs(config);
|
||||
}
|
||||
var OVERLAY_ANALYSIS_FEATURES = {
|
||||
cpp: "overlay_analysis_cpp" /* OverlayAnalysisCpp */,
|
||||
@@ -149713,6 +149741,7 @@ async function determineUserConfig(action, tempDir, inputs) {
|
||||
);
|
||||
const fromConfigFile = await loadUserConfig(
|
||||
action,
|
||||
inputs.analysisKinds,
|
||||
inputs.configFile,
|
||||
inputs.workspacePath,
|
||||
inputs.apiDetails,
|
||||
@@ -149749,6 +149778,7 @@ async function determineUserConfig(action, tempDir, inputs) {
|
||||
action.logger.debug(`Using configuration file: ${inputs.configFile}`);
|
||||
return await loadUserConfig(
|
||||
action,
|
||||
inputs.analysisKinds,
|
||||
inputs.configFile,
|
||||
inputs.workspacePath,
|
||||
inputs.apiDetails,
|
||||
|
||||
@@ -12,7 +12,7 @@ import { AnalysisKind, supportedAnalysisKinds } from "./analyses";
|
||||
import * as api from "./api-client";
|
||||
import { CachingKind } from "./caching-utils";
|
||||
import { createStubCodeQL } from "./codeql";
|
||||
import { UserConfig } from "./config/db-config";
|
||||
import { UserConfig, UserConfigWithActionExtensions } from "./config/db-config";
|
||||
import * as file from "./config/file";
|
||||
import * as configUtils from "./config-utils";
|
||||
import * as errorMessages from "./error-messages";
|
||||
@@ -2544,6 +2544,7 @@ test("loadUserConfig - loads local configuration files", async (t) => {
|
||||
) =>
|
||||
configUtils.loadUserConfig(
|
||||
actionState,
|
||||
[AnalysisKind.CodeScanning],
|
||||
filePath,
|
||||
workspaceDir,
|
||||
SAMPLE_DOTCOM_API_DETAILS,
|
||||
@@ -2587,7 +2588,13 @@ test.serial("loadUserConfig - loads remote configuration files", async (t) => {
|
||||
|
||||
const remoteAddress = "owner/repo/file@ref";
|
||||
await callee(configUtils.loadUserConfig)
|
||||
.withArgs(remoteAddress, tmpDir, SAMPLE_DOTCOM_API_DETAILS, tmpDir)
|
||||
.withArgs(
|
||||
[AnalysisKind.CodeScanning],
|
||||
remoteAddress,
|
||||
tmpDir,
|
||||
SAMPLE_DOTCOM_API_DETAILS,
|
||||
tmpDir,
|
||||
)
|
||||
.passes(t.deepEqual, {});
|
||||
|
||||
t.true(
|
||||
@@ -2665,6 +2672,7 @@ test.serial(
|
||||
|
||||
// Prepare the test call to `loadUserConfig`.
|
||||
const targetWithArgs = target.withArgs(
|
||||
[AnalysisKind.CodeScanning],
|
||||
address,
|
||||
tmpDir,
|
||||
SAMPLE_DOTCOM_API_DETAILS,
|
||||
@@ -2705,3 +2713,57 @@ test.serial(
|
||||
});
|
||||
},
|
||||
);
|
||||
|
||||
test("loadUserConfig - applies analysis-specific settings", async (t) => {
|
||||
await withTmpDir(async (workspaceDir) => {
|
||||
await withTmpDir(async (tmpDir) => {
|
||||
// Construct the test target.
|
||||
const loadUserConfig = (
|
||||
actionState: ActionState<["Logger", "Env", "FeatureFlags"]>,
|
||||
filePath: string,
|
||||
analysisKind: AnalysisKind,
|
||||
) =>
|
||||
configUtils.loadUserConfig(
|
||||
actionState,
|
||||
[analysisKind],
|
||||
filePath,
|
||||
workspaceDir,
|
||||
SAMPLE_DOTCOM_API_DETAILS,
|
||||
tmpDir,
|
||||
);
|
||||
const target = callee(loadUserConfig);
|
||||
|
||||
for (const analysisKind of Object.values(AnalysisKind)) {
|
||||
const analysisSpecificConfig: UserConfig = {
|
||||
paths: ["custom"],
|
||||
queries: [{ uses: "foo" }],
|
||||
};
|
||||
const baseConfig: UserConfig = { "threat-models": ["remote"] };
|
||||
|
||||
// Write a local configuration file with an `analysisKind`-specific section.
|
||||
const configPath = path.join(workspaceDir, "codeql.yml");
|
||||
fs.writeFileSync(
|
||||
configPath,
|
||||
JSON.stringify({
|
||||
...baseConfig,
|
||||
[analysisKind]: analysisSpecificConfig,
|
||||
} satisfies UserConfigWithActionExtensions),
|
||||
"utf8",
|
||||
);
|
||||
|
||||
// The resulting configuration should be the `baseConfig` with the `analysisSpecificConfig`
|
||||
// merged into it if the FF is enabled.
|
||||
await target
|
||||
.withArgs(configPath, analysisKind)
|
||||
.withFeatures([Feature.ScopedConfigurations])
|
||||
.passes(t.deepEqual, { ...baseConfig, ...analysisSpecificConfig });
|
||||
|
||||
// Without the FF, it should be the `baseConfig`. This also validates that the
|
||||
// `AnalysisKind`-specific sections are removed even if the FF is off.
|
||||
await target
|
||||
.withArgs(configPath, analysisKind)
|
||||
.passes(t.deepEqual, baseConfig);
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -24,11 +24,13 @@ import { getCachingKind } from "./caching-utils";
|
||||
import { type CodeQL } from "./codeql";
|
||||
import { type Config } from "./config/action-config";
|
||||
import {
|
||||
applyAnalysisKindConfig,
|
||||
calculateAugmentation,
|
||||
ExcludeQueryFilter,
|
||||
generateCodeScanningConfig,
|
||||
mergeDefaultSetupAndUserConfigs,
|
||||
parseUserConfig,
|
||||
removeAnalysisKindConfigs,
|
||||
UserConfig,
|
||||
} from "./config/db-config";
|
||||
import {
|
||||
@@ -484,6 +486,7 @@ async function downloadCacheWithTime(
|
||||
*/
|
||||
export async function loadUserConfig(
|
||||
actionState: ActionState<["Logger", "Env", "FeatureFlags"]>,
|
||||
analysisKinds: AnalysisKind[],
|
||||
configFile: string,
|
||||
workspacePath: string,
|
||||
apiDetails: api.GitHubApiCombinedDetails,
|
||||
@@ -516,7 +519,26 @@ export async function loadUserConfig(
|
||||
config = await getRemoteConfig(actionState, configFile, apiDetails);
|
||||
}
|
||||
|
||||
return config;
|
||||
// If the `ScopedConfigurations` feature is enabled, we allow options specific to the
|
||||
// current `AnalysisKind` to be applied on top of a base configuration.
|
||||
const allowScopedConfig = await actionState.features.getValue(
|
||||
Feature.ScopedConfigurations,
|
||||
);
|
||||
|
||||
if (allowScopedConfig && analysisKinds.length === 1) {
|
||||
// Apply the `analysisKind`-specific configuration.
|
||||
return applyAnalysisKindConfig(analysisKinds[0], config);
|
||||
} else if (allowScopedConfig) {
|
||||
actionState.logger.info(
|
||||
`Ignoring '${Feature.ScopedConfigurations}' feature, because multiple analysis kinds are enabled.`,
|
||||
);
|
||||
}
|
||||
|
||||
// Remove `AnalysisKind`-specific sections from `config` even if the FF is not enabled,
|
||||
// because the CLI will warn about unknown keys in the configuration. This is to guard
|
||||
// against the case where we ship the feature, enable the FF, start using the new keys,
|
||||
// and then need to roll the FF back.
|
||||
return removeAnalysisKindConfigs(config);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1075,6 +1097,7 @@ export async function determineUserConfig(
|
||||
);
|
||||
const fromConfigFile = await loadUserConfig(
|
||||
action,
|
||||
inputs.analysisKinds,
|
||||
inputs.configFile,
|
||||
inputs.workspacePath,
|
||||
inputs.apiDetails,
|
||||
@@ -1122,6 +1145,7 @@ export async function determineUserConfig(
|
||||
action.logger.debug(`Using configuration file: ${inputs.configFile}`);
|
||||
return await loadUserConfig(
|
||||
action,
|
||||
inputs.analysisKinds,
|
||||
inputs.configFile,
|
||||
inputs.workspacePath,
|
||||
inputs.apiDetails,
|
||||
|
||||
Reference in New Issue
Block a user