From d799ff5e6a96b70d3a939a3610a84be350c8cd34 Mon Sep 17 00:00:00 2001 From: Chuan-kai Lin Date: Thu, 10 Jul 2025 14:14:14 -0700 Subject: [PATCH] Overlay: check per-language features --- src/config-utils.test.ts | 68 +++++++++++++++++++++++++++++++++++----- src/config-utils.ts | 30 ++++++++++++++++-- 2 files changed, 89 insertions(+), 9 deletions(-) diff --git a/src/config-utils.test.ts b/src/config-utils.test.ts index 9293016dd..04bfe235d 100644 --- a/src/config-utils.test.ts +++ b/src/config-utils.test.ts @@ -1345,7 +1345,8 @@ test( getOverlayDatabaseModeMacro, "Ignore feature flag when analyzing non-default branch", { - features: [Feature.OverlayAnalysis], + languages: [Language.javascript], + features: [Feature.OverlayAnalysis, Feature.OverlayAnalysisJavascript], }, { overlayDatabaseMode: OverlayDatabaseMode.None, @@ -1357,7 +1358,8 @@ test( getOverlayDatabaseModeMacro, "Overlay-base database on default branch when feature enabled", { - features: [Feature.OverlayAnalysis], + languages: [Language.javascript], + features: [Feature.OverlayAnalysis, Feature.OverlayAnalysisJavascript], isDefaultBranch: true, }, { @@ -1368,8 +1370,24 @@ test( test( getOverlayDatabaseModeMacro, - "No overlay-base database on default branch when feature disabled", + "No overlay-base database on default branch when overall feature disabled", { + languages: [Language.javascript], + features: [Feature.OverlayAnalysisJavascript], + isDefaultBranch: true, + }, + { + overlayDatabaseMode: OverlayDatabaseMode.None, + useOverlayDatabaseCaching: false, + }, +); + +test( + getOverlayDatabaseModeMacro, + "No overlay-base database on default branch when language-specific feature disabled", + { + languages: [Language.javascript], + features: [Feature.OverlayAnalysis], isDefaultBranch: true, }, { @@ -1382,7 +1400,8 @@ test( getOverlayDatabaseModeMacro, "Overlay analysis on PR when feature enabled", { - features: [Feature.OverlayAnalysis], + languages: [Language.javascript], + features: [Feature.OverlayAnalysis, Feature.OverlayAnalysisJavascript], isPullRequest: true, }, { @@ -1393,8 +1412,24 @@ test( test( getOverlayDatabaseModeMacro, - "No overlay analysis on PR when feature disabled", + "No overlay analysis on PR when overall feature disabled", { + languages: [Language.javascript], + features: [Feature.OverlayAnalysisJavascript], + isPullRequest: true, + }, + { + overlayDatabaseMode: OverlayDatabaseMode.None, + useOverlayDatabaseCaching: false, + }, +); + +test( + getOverlayDatabaseModeMacro, + "No overlay analysis on PR when language-specific feature disabled", + { + languages: [Language.javascript], + features: [Feature.OverlayAnalysis], isPullRequest: true, }, { @@ -1433,7 +1468,8 @@ test( getOverlayDatabaseModeMacro, "Overlay PR analysis by feature flag for dsp-testing", { - features: [Feature.OverlayAnalysis], + languages: [Language.javascript], + features: [Feature.OverlayAnalysis, Feature.OverlayAnalysisJavascript], isPullRequest: true, repositoryOwner: "dsp-testing", }, @@ -1447,7 +1483,8 @@ test( getOverlayDatabaseModeMacro, "No overlay PR analysis by feature flag for other-org", { - features: [Feature.OverlayAnalysis], + languages: [Language.javascript], + features: [Feature.OverlayAnalysis, Feature.OverlayAnalysisJavascript], isPullRequest: true, repositoryOwner: "other-org", }, @@ -1510,3 +1547,20 @@ test( useOverlayDatabaseCaching: false, }, ); + +// Exercise language-specific overlay analysis features code paths +for (const language in Language) { + test( + getOverlayDatabaseModeMacro, + `Check default overlay analysis feature for ${language}`, + { + languages: [language as Language], + features: [Feature.OverlayAnalysis], + isPullRequest: true, + }, + { + overlayDatabaseMode: OverlayDatabaseMode.None, + useOverlayDatabaseCaching: false, + }, + ); +} diff --git a/src/config-utils.ts b/src/config-utils.ts index 94e71a39e..675dd1ea5 100644 --- a/src/config-utils.ts +++ b/src/config-utils.ts @@ -646,10 +646,24 @@ function parseQueriesFromInput( return trimmedInput.split(",").map((query) => ({ uses: query.trim() })); } +const OVERLAY_ANALYSIS_FEATURES: Record = { + actions: Feature.OverlayAnalysisActions, + cpp: Feature.OverlayAnalysisCpp, + csharp: Feature.OverlayAnalysisCsharp, + go: Feature.OverlayAnalysisGo, + java: Feature.OverlayAnalysisJava, + javascript: Feature.OverlayAnalysisJavascript, + python: Feature.OverlayAnalysisPython, + ruby: Feature.OverlayAnalysisRuby, + rust: Feature.OverlayAnalysisRust, + swift: Feature.OverlayAnalysisSwift, +}; + async function isOverlayAnalysisFeatureEnabled( repository: RepositoryNwo, features: FeatureEnablement, codeql: CodeQL, + languages: Language[], ): Promise { // TODO: Remove the repository owner check once support for overlay analysis // stabilizes, and no more backward-incompatible changes are expected. @@ -659,7 +673,14 @@ async function isOverlayAnalysisFeatureEnabled( if (!(await features.getValue(Feature.OverlayAnalysis, codeql))) { return false; } - // TODO: Add per-language feature checks here + for (const language of languages) { + const feature = OVERLAY_ANALYSIS_FEATURES[language]; + if (feature && (await features.getValue(feature, codeql))) { + continue; + } + // TODO: Add code-scanning feature checks here + return false; + } return true; } @@ -713,7 +734,12 @@ export async function getOverlayDatabaseMode( "from the CODEQL_OVERLAY_DATABASE_MODE environment variable.", ); } else if ( - await isOverlayAnalysisFeatureEnabled(repository, features, codeql) + await isOverlayAnalysisFeatureEnabled( + repository, + features, + codeql, + languages, + ) ) { if (isAnalyzingPullRequest()) { overlayDatabaseMode = OverlayDatabaseMode.Overlay;