Skip to content

Commit af8f50b

Browse files
committed
Use applyAnalysisKindConfig in loadUserConfig
1 parent f638e8b commit af8f50b

3 files changed

Lines changed: 121 additions & 5 deletions

File tree

lib/entry-points.js

Lines changed: 32 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/config-utils.test.ts

Lines changed: 64 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import { AnalysisKind, supportedAnalysisKinds } from "./analyses";
1212
import * as api from "./api-client";
1313
import { CachingKind } from "./caching-utils";
1414
import { createStubCodeQL } from "./codeql";
15-
import { UserConfig } from "./config/db-config";
15+
import { UserConfig, UserConfigWithActionExtensions } from "./config/db-config";
1616
import * as file from "./config/file";
1717
import * as configUtils from "./config-utils";
1818
import * as errorMessages from "./error-messages";
@@ -2544,6 +2544,7 @@ test("loadUserConfig - loads local configuration files", async (t) => {
25442544
) =>
25452545
configUtils.loadUserConfig(
25462546
actionState,
2547+
[AnalysisKind.CodeScanning],
25472548
filePath,
25482549
workspaceDir,
25492550
SAMPLE_DOTCOM_API_DETAILS,
@@ -2587,7 +2588,13 @@ test.serial("loadUserConfig - loads remote configuration files", async (t) => {
25872588

25882589
const remoteAddress = "owner/repo/file@ref";
25892590
await callee(configUtils.loadUserConfig)
2590-
.withArgs(remoteAddress, tmpDir, SAMPLE_DOTCOM_API_DETAILS, tmpDir)
2591+
.withArgs(
2592+
[AnalysisKind.CodeScanning],
2593+
remoteAddress,
2594+
tmpDir,
2595+
SAMPLE_DOTCOM_API_DETAILS,
2596+
tmpDir,
2597+
)
25912598
.passes(t.deepEqual, {});
25922599

25932600
t.true(
@@ -2665,6 +2672,7 @@ test.serial(
26652672

26662673
// Prepare the test call to `loadUserConfig`.
26672674
const targetWithArgs = target.withArgs(
2675+
[AnalysisKind.CodeScanning],
26682676
address,
26692677
tmpDir,
26702678
SAMPLE_DOTCOM_API_DETAILS,
@@ -2705,3 +2713,57 @@ test.serial(
27052713
});
27062714
},
27072715
);
2716+
2717+
test("loadUserConfig - applies analysis-specific settings", async (t) => {
2718+
await withTmpDir(async (workspaceDir) => {
2719+
await withTmpDir(async (tmpDir) => {
2720+
// Construct the test target.
2721+
const loadUserConfig = (
2722+
actionState: ActionState<["Logger", "Env", "FeatureFlags"]>,
2723+
filePath: string,
2724+
analysisKind: AnalysisKind,
2725+
) =>
2726+
configUtils.loadUserConfig(
2727+
actionState,
2728+
[analysisKind],
2729+
filePath,
2730+
workspaceDir,
2731+
SAMPLE_DOTCOM_API_DETAILS,
2732+
tmpDir,
2733+
);
2734+
const target = callee(loadUserConfig);
2735+
2736+
for (const analysisKind of Object.values(AnalysisKind)) {
2737+
const analysisSpecificConfig: UserConfig = {
2738+
paths: ["custom"],
2739+
queries: [{ uses: "foo" }],
2740+
};
2741+
const baseConfig: UserConfig = { "threat-models": ["remote"] };
2742+
2743+
// Write a local configuration file with an `analysisKind`-specific section.
2744+
const configPath = path.join(workspaceDir, "codeql.yml");
2745+
fs.writeFileSync(
2746+
configPath,
2747+
JSON.stringify({
2748+
...baseConfig,
2749+
[analysisKind]: analysisSpecificConfig,
2750+
} satisfies UserConfigWithActionExtensions),
2751+
"utf8",
2752+
);
2753+
2754+
// The resulting configuration should be the `baseConfig` with the `analysisSpecificConfig`
2755+
// merged into it if the FF is enabled.
2756+
await target
2757+
.withArgs(configPath, analysisKind)
2758+
.withFeatures([Feature.ScopedConfigurations])
2759+
.passes(t.deepEqual, { ...baseConfig, ...analysisSpecificConfig });
2760+
2761+
// Without the FF, it should be the `baseConfig`. This also validates that the
2762+
// `AnalysisKind`-specific sections are removed even if the FF is off.
2763+
await target
2764+
.withArgs(configPath, analysisKind)
2765+
.passes(t.deepEqual, baseConfig);
2766+
}
2767+
});
2768+
});
2769+
});

src/config-utils.ts

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,11 +24,13 @@ import { getCachingKind } from "./caching-utils";
2424
import { type CodeQL } from "./codeql";
2525
import { type Config } from "./config/action-config";
2626
import {
27+
applyAnalysisKindConfig,
2728
calculateAugmentation,
2829
ExcludeQueryFilter,
2930
generateCodeScanningConfig,
3031
mergeDefaultSetupAndUserConfigs,
3132
parseUserConfig,
33+
removeAnalysisKindConfigs,
3234
UserConfig,
3335
} from "./config/db-config";
3436
import {
@@ -484,6 +486,7 @@ async function downloadCacheWithTime(
484486
*/
485487
export async function loadUserConfig(
486488
actionState: ActionState<["Logger", "Env", "FeatureFlags"]>,
489+
analysisKinds: AnalysisKind[],
487490
configFile: string,
488491
workspacePath: string,
489492
apiDetails: api.GitHubApiCombinedDetails,
@@ -516,7 +519,26 @@ export async function loadUserConfig(
516519
config = await getRemoteConfig(actionState, configFile, apiDetails);
517520
}
518521

519-
return config;
522+
// If the `ScopedConfigurations` feature is enabled, we allow options specific to the
523+
// current `AnalysisKind` to be applied on top of a base configuration.
524+
const allowScopedConfig = await actionState.features.getValue(
525+
Feature.ScopedConfigurations,
526+
);
527+
528+
if (allowScopedConfig && analysisKinds.length === 1) {
529+
// Apply the `analysisKind`-specific configuration.
530+
return applyAnalysisKindConfig(analysisKinds[0], config);
531+
} else if (allowScopedConfig) {
532+
actionState.logger.info(
533+
`Ignoring '${Feature.ScopedConfigurations}' feature, because multiple analysis kinds are enabled.`,
534+
);
535+
}
536+
537+
// Remove `AnalysisKind`-specific sections from `config` even if the FF is not enabled,
538+
// because the CLI will warn about unknown keys in the configuration. This is to guard
539+
// against the case where we ship the feature, enable the FF, start using the new keys,
540+
// and then need to roll the FF back.
541+
return removeAnalysisKindConfigs(config);
520542
}
521543

522544
/**
@@ -1075,6 +1097,7 @@ export async function determineUserConfig(
10751097
);
10761098
const fromConfigFile = await loadUserConfig(
10771099
action,
1100+
inputs.analysisKinds,
10781101
inputs.configFile,
10791102
inputs.workspacePath,
10801103
inputs.apiDetails,
@@ -1122,6 +1145,7 @@ export async function determineUserConfig(
11221145
action.logger.debug(`Using configuration file: ${inputs.configFile}`);
11231146
return await loadUserConfig(
11241147
action,
1148+
inputs.analysisKinds,
11251149
inputs.configFile,
11261150
inputs.workspacePath,
11271151
inputs.apiDetails,

0 commit comments

Comments
 (0)