diff --git a/lib/entry-points.js b/lib/entry-points.js index 528f258a87..46c44a8183 100644 --- a/lib/entry-points.js +++ b/lib/entry-points.js @@ -148495,22 +148495,27 @@ async function getConfigFileInput({ logger, actions, features -}, repositoryProperties) { +}, repositoryProperties, analysisKinds) { const input = actions.getOptionalInput("config-file"); if (input !== void 0) { logger.info(`Using configuration file input from workflow: ${input}`); return input; } const propertyValue = repositoryProperties["github-codeql-config-file" /* CONFIG_FILE */]; + const analysisKindSupported = analysisKinds === void 0 || analysisKinds.includes("code-scanning" /* CodeScanning */) && analysisKinds.length === 1; if (propertyValue !== void 0 && propertyValue.trim().length > 0) { const useRepositoryProperty = await features.getValue( "config_file_repository_property" /* ConfigFileRepositoryProperty */ ); - if (useRepositoryProperty) { + if (analysisKindSupported && useRepositoryProperty) { logger.info( `Using configuration file input from repository property: ${propertyValue}` ); return propertyValue; + } else if (!analysisKindSupported) { + logger.info( + "Ignoring configuration file input from repository property, because it is unsupported for the current analysis kind." + ); } else { logger.info( "Ignoring configuration file input from repository property, because the corresponding feature flag is disabled." @@ -160750,11 +160755,6 @@ async function run3(actionState) { logger.info(`Job run UUID is ${jobRunUuid}.`); core21.exportVariable("JOB_RUN_UUID" /* JOB_RUN_UUID */, jobRunUuid); core21.exportVariable("CODEQL_ACTION_INIT_HAS_RUN" /* INIT_ACTION_HAS_RUN */, "true"); - const actionStateWithFeatures = { ...actionState, features }; - configFile = await getConfigFileInput( - actionStateWithFeatures, - repositoryProperties - ); sourceRoot = path24.resolve( getRequiredEnvParam("GITHUB_WORKSPACE"), getOptionalInput("source-root") || "" @@ -160767,6 +160767,12 @@ async function run3(actionState) { `Failed to parse analysis kinds for 'starting' status report: ${getErrorMessage(err)}` ); } + const actionStateWithFeatures = { ...actionState, features }; + configFile = await getConfigFileInput( + actionStateWithFeatures, + repositoryProperties, + analysisKinds + ); await sendStartingStatusReport(startedAt, { analysisKinds }, logger); if (process.env["CODEQL_ACTION_SETUP_CODEQL_HAS_RUN" /* SETUP_CODEQL_ACTION_HAS_RUN */] === "true") { throw new ConfigurationError( diff --git a/src/config/file.test.ts b/src/config/file.test.ts index 22e2f795f8..0833ad3d06 100644 --- a/src/config/file.test.ts +++ b/src/config/file.test.ts @@ -2,6 +2,7 @@ import * as github from "@actions/github"; import test from "ava"; import sinon from "sinon"; +import { AnalysisKind } from "../analyses"; import * as api from "../api-client"; import { RegistryProxyVars } from "../environment"; import { Feature } from "../feature-flags"; @@ -18,7 +19,7 @@ setupTests(test); test("getConfigFileInput returns undefined by default", async (t) => { await callee(getConfigFileInput) - .withArgs({}) + .withArgs({}, undefined) .withFeatures([Feature.ConfigFileRepositoryProperty]) .passes(t.is, undefined); }); @@ -40,7 +41,7 @@ test("getConfigFileInput returns input value", async (t) => { .withArgs("config-file") .returns(testInput); }) - .withArgs(repositoryProperties) + .withArgs(repositoryProperties, undefined) .logs(t, "Using configuration file input from workflow") .passes(t.is, testInput); }); @@ -49,16 +50,48 @@ test("getConfigFileInput returns repository property value", async (t) => { // Since there is no direct input, we should use the repository property. await callee(getConfigFileInput) .withFeatures([Feature.ConfigFileRepositoryProperty]) - .withArgs(repositoryProperties) + .withArgs(repositoryProperties, undefined) .logs(t, "Using configuration file input from repository property") .passes(t.is, repositoryProperties[RepositoryPropertyName.CONFIG_FILE]); }); +test("getConfigFileInput returns repository property value for Code Scanning", async (t) => { + // Since there is no direct input, we should use the repository property. + await callee(getConfigFileInput) + .withFeatures([Feature.ConfigFileRepositoryProperty]) + .withArgs(repositoryProperties, [AnalysisKind.CodeScanning]) + .logs(t, "Using configuration file input from repository property") + .passes(t.is, repositoryProperties[RepositoryPropertyName.CONFIG_FILE]); +}); + +test("getConfigFileInput ignores repository property for other analysis kinds", async (t) => { + const unsupportedCases = [ + [AnalysisKind.CodeQuality], + [AnalysisKind.RiskAssessment], + [AnalysisKind.CodeScanning, AnalysisKind.CodeQuality], + ]; + + const target = callee(getConfigFileInput).withFeatures([ + Feature.ConfigFileRepositoryProperty, + ]); + + for (const unsupportedCase of unsupportedCases) { + // Since the analysis kind is unsupported, we should ignore the repository property. + await target + .withArgs(repositoryProperties, unsupportedCase) + .logs( + t, + "Ignoring configuration file input from repository property, because it is unsupported for the current analysis kind.", + ) + .passes(t.is, undefined); + } +}); + test("getConfigFileInput ignores empty repository property value", async (t) => { // Since the repository property value is an empty/whitespace string, we should ignore it. await callee(getConfigFileInput) .withFeatures([Feature.ConfigFileRepositoryProperty]) - .withArgs({ [RepositoryPropertyName.CONFIG_FILE]: " " }) + .withArgs({ [RepositoryPropertyName.CONFIG_FILE]: " " }, undefined) .passes(t.is, undefined); }); @@ -66,7 +99,7 @@ test("getConfigFileInput ignores repository property value when FF is off", asyn // Since the FF is off, we should ignore the repository property value. await callee(getConfigFileInput) .withFeatures([]) - .withArgs(repositoryProperties) + .withArgs(repositoryProperties, undefined) .notLogs(t, "Using configuration file input from repository property") .logs( t, diff --git a/src/config/file.ts b/src/config/file.ts index 8cb7bc3a11..be0e415a38 100644 --- a/src/config/file.ts +++ b/src/config/file.ts @@ -1,4 +1,5 @@ import { ActionState } from "../action-common"; +import { AnalysisKind } from "../analyses"; import * as api from "../api-client"; import * as errorMessages from "../error-messages"; import { Feature } from "../feature-flags"; @@ -34,6 +35,7 @@ export async function getConfigFileInput( features, }: ActionState<["Logger", "Actions", "FeatureFlags"]>, repositoryProperties: Partial, + analysisKinds: AnalysisKind[] | undefined, ): Promise { const input = actions.getOptionalInput("config-file"); @@ -45,17 +47,29 @@ export async function getConfigFileInput( const propertyValue = repositoryProperties[RepositoryPropertyName.CONFIG_FILE]; + // Only allow the repository property to be used for standard Code Scanning analyses, + // since we don't currently support some customisation options for Code Quality. + // We don't expect customisations for Risk Assessments either. + const analysisKindSupported = + analysisKinds === undefined || + (analysisKinds.includes(AnalysisKind.CodeScanning) && + analysisKinds.length === 1); + if (propertyValue !== undefined && propertyValue.trim().length > 0) { // Only use the repository property value if the FF is enabled. const useRepositoryProperty = await features.getValue( Feature.ConfigFileRepositoryProperty, ); - if (useRepositoryProperty) { + if (analysisKindSupported && useRepositoryProperty) { logger.info( `Using configuration file input from repository property: ${propertyValue}`, ); return propertyValue; + } else if (!analysisKindSupported) { + logger.info( + "Ignoring configuration file input from repository property, because it is unsupported for the current analysis kind.", + ); } else { logger.info( "Ignoring configuration file input from repository property, because the corresponding feature flag is disabled.", diff --git a/src/init-action.ts b/src/init-action.ts index c7837c6eed..4b52ba6ec6 100644 --- a/src/init-action.ts +++ b/src/init-action.ts @@ -262,12 +262,6 @@ async function run( core.exportVariable(EnvVar.INIT_ACTION_HAS_RUN, "true"); - const actionStateWithFeatures = { ...actionState, features }; - configFile = await getConfigFileInput( - actionStateWithFeatures, - repositoryProperties, - ); - // path.resolve() respects the intended semantics of source-root. If // source-root is relative, it is relative to the GITHUB_WORKSPACE. If // source-root is absolute, it is used as given. @@ -290,6 +284,14 @@ async function run( ); } + // Compute the value of the `config-file` input. + const actionStateWithFeatures = { ...actionState, features }; + configFile = await getConfigFileInput( + actionStateWithFeatures, + repositoryProperties, + analysisKinds, + ); + // Send a status report indicating that an analysis is starting. await sendStartingStatusReport(startedAt, { analysisKinds }, logger);