diff --git a/CHANGELOG.md b/CHANGELOG.md index 28a3105f8..700402bc1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,11 @@ See the [releases page](https://github.com/github/codeql-action/releases) for th ## [UNRELEASED] - Fixed [a bug](https://github.com/github/codeql-action/issues/3555) which caused the CodeQL Action to fail loading repository properties if a "Multi select" repository property was configured for the repository. [#3557](https://github.com/github/codeql-action/pull/3557) +- Added an experimental change which skips collecting file coverage information on pull requests to improve analysis performance. File coverage information will still be computed when analyzing the default branch and protected branches. + + Repositories owned by an organization can opt out of this change by creating a custom repository property with the name `github-codeql-file-coverage-on-prs` and the type "True/false", then setting this property to `true` in the repository's settings. For more information, see [Managing custom properties for repositories in your organization](https://docs.github.com/en/organizations/managing-organization-settings/managing-custom-properties-for-repositories-in-your-organization). + + We expect to roll this change out to everyone in March. [#TODO](https://github.com/github/codeql-action/pull/TODO) ## 4.32.6 - 05 Mar 2026 diff --git a/lib/analyze-action-post.js b/lib/analyze-action-post.js index 328c64771..46bfde5b0 100644 --- a/lib/analyze-action-post.js +++ b/lib/analyze-action-post.js @@ -161733,6 +161733,7 @@ var semver2 = __toESM(require_semver2()); var RepositoryPropertyName = /* @__PURE__ */ ((RepositoryPropertyName2) => { RepositoryPropertyName2["DISABLE_OVERLAY"] = "github-codeql-disable-overlay"; RepositoryPropertyName2["EXTRA_QUERIES"] = "github-codeql-extra-queries"; + RepositoryPropertyName2["FILE_COVERAGE_ON_PRS"] = "github-codeql-file-coverage-on-prs"; return RepositoryPropertyName2; })(RepositoryPropertyName || {}); var KNOWN_REPOSITORY_PROPERTY_NAMES = new Set( diff --git a/lib/analyze-action.js b/lib/analyze-action.js index bae47ad2d..f83b1ac07 100644 --- a/lib/analyze-action.js +++ b/lib/analyze-action.js @@ -107232,6 +107232,7 @@ var semver2 = __toESM(require_semver2()); var RepositoryPropertyName = /* @__PURE__ */ ((RepositoryPropertyName2) => { RepositoryPropertyName2["DISABLE_OVERLAY"] = "github-codeql-disable-overlay"; RepositoryPropertyName2["EXTRA_QUERIES"] = "github-codeql-extra-queries"; + RepositoryPropertyName2["FILE_COVERAGE_ON_PRS"] = "github-codeql-file-coverage-on-prs"; return RepositoryPropertyName2; })(RepositoryPropertyName || {}); var KNOWN_REPOSITORY_PROPERTY_NAMES = new Set( diff --git a/lib/autobuild-action.js b/lib/autobuild-action.js index 33701fe48..482b85ff0 100644 --- a/lib/autobuild-action.js +++ b/lib/autobuild-action.js @@ -103786,6 +103786,7 @@ var semver2 = __toESM(require_semver2()); var RepositoryPropertyName = /* @__PURE__ */ ((RepositoryPropertyName2) => { RepositoryPropertyName2["DISABLE_OVERLAY"] = "github-codeql-disable-overlay"; RepositoryPropertyName2["EXTRA_QUERIES"] = "github-codeql-extra-queries"; + RepositoryPropertyName2["FILE_COVERAGE_ON_PRS"] = "github-codeql-file-coverage-on-prs"; return RepositoryPropertyName2; })(RepositoryPropertyName || {}); var KNOWN_REPOSITORY_PROPERTY_NAMES = new Set( diff --git a/lib/init-action-post.js b/lib/init-action-post.js index 74818a1e2..aabc7baae 100644 --- a/lib/init-action-post.js +++ b/lib/init-action-post.js @@ -165100,6 +165100,7 @@ var semver2 = __toESM(require_semver2()); var RepositoryPropertyName = /* @__PURE__ */ ((RepositoryPropertyName2) => { RepositoryPropertyName2["DISABLE_OVERLAY"] = "github-codeql-disable-overlay"; RepositoryPropertyName2["EXTRA_QUERIES"] = "github-codeql-extra-queries"; + RepositoryPropertyName2["FILE_COVERAGE_ON_PRS"] = "github-codeql-file-coverage-on-prs"; return RepositoryPropertyName2; })(RepositoryPropertyName || {}); var KNOWN_REPOSITORY_PROPERTY_NAMES = new Set( diff --git a/lib/init-action.js b/lib/init-action.js index 883313758..8b279f437 100644 --- a/lib/init-action.js +++ b/lib/init-action.js @@ -104406,6 +104406,7 @@ function getUnknownLanguagesError(languages) { var RepositoryPropertyName = /* @__PURE__ */ ((RepositoryPropertyName2) => { RepositoryPropertyName2["DISABLE_OVERLAY"] = "github-codeql-disable-overlay"; RepositoryPropertyName2["EXTRA_QUERIES"] = "github-codeql-extra-queries"; + RepositoryPropertyName2["FILE_COVERAGE_ON_PRS"] = "github-codeql-file-coverage-on-prs"; return RepositoryPropertyName2; })(RepositoryPropertyName || {}); function isString(value) { @@ -104422,7 +104423,8 @@ var booleanProperty = { }; var repositoryPropertyParsers = { ["github-codeql-disable-overlay" /* DISABLE_OVERLAY */]: booleanProperty, - ["github-codeql-extra-queries" /* EXTRA_QUERIES */]: stringProperty + ["github-codeql-extra-queries" /* EXTRA_QUERIES */]: stringProperty, + ["github-codeql-file-coverage-on-prs" /* FILE_COVERAGE_ON_PRS */]: booleanProperty }; async function loadPropertiesFromApi(gitHubVersion, logger, repositoryNwo) { if (gitHubVersion.type === "GitHub Enterprise Server" /* GHES */) { @@ -109091,13 +109093,15 @@ function cleanupDatabaseClusterDirectory(config, logger, options = {}, rmSync2 = } } } -async function getFileCoverageInformationEnabled(debugMode, codeql, features) { +async function getFileCoverageInformationEnabled(debugMode, codeql, features, repositoryProperties) { return ( // Always enable file coverage information in debug mode debugMode || // We're most interested in speeding up PRs, and we want to keep // submitting file coverage information for the default branch since // it is used to populate the status page. - !isAnalyzingPullRequest() || !await features.getValue("skip_file_coverage_on_prs" /* SkipFileCoverageOnPrs */, codeql) + !isAnalyzingPullRequest() || // Allow repositories to opt in to file coverage information on PRs + // using a repository property. + repositoryProperties["github-codeql-file-coverage-on-prs" /* FILE_COVERAGE_ON_PRS */] === true || !await features.getValue("skip_file_coverage_on_prs" /* SkipFileCoverageOnPrs */, codeql) ); } @@ -109740,7 +109744,8 @@ async function run(startedAt) { enableFileCoverageInformation: await getFileCoverageInformationEnabled( debugMode, codeql, - features + features, + repositoryPropertiesResult.orElse({}) ), logger }); diff --git a/lib/resolve-environment-action.js b/lib/resolve-environment-action.js index 3dd3ed839..854dc9de4 100644 --- a/lib/resolve-environment-action.js +++ b/lib/resolve-environment-action.js @@ -103785,6 +103785,7 @@ var semver2 = __toESM(require_semver2()); var RepositoryPropertyName = /* @__PURE__ */ ((RepositoryPropertyName2) => { RepositoryPropertyName2["DISABLE_OVERLAY"] = "github-codeql-disable-overlay"; RepositoryPropertyName2["EXTRA_QUERIES"] = "github-codeql-extra-queries"; + RepositoryPropertyName2["FILE_COVERAGE_ON_PRS"] = "github-codeql-file-coverage-on-prs"; return RepositoryPropertyName2; })(RepositoryPropertyName || {}); var KNOWN_REPOSITORY_PROPERTY_NAMES = new Set( diff --git a/lib/setup-codeql-action.js b/lib/setup-codeql-action.js index bff5be22b..3a1825ec5 100644 --- a/lib/setup-codeql-action.js +++ b/lib/setup-codeql-action.js @@ -104781,6 +104781,7 @@ var semver5 = __toESM(require_semver2()); var RepositoryPropertyName = /* @__PURE__ */ ((RepositoryPropertyName2) => { RepositoryPropertyName2["DISABLE_OVERLAY"] = "github-codeql-disable-overlay"; RepositoryPropertyName2["EXTRA_QUERIES"] = "github-codeql-extra-queries"; + RepositoryPropertyName2["FILE_COVERAGE_ON_PRS"] = "github-codeql-file-coverage-on-prs"; return RepositoryPropertyName2; })(RepositoryPropertyName || {}); var KNOWN_REPOSITORY_PROPERTY_NAMES = new Set( diff --git a/lib/start-proxy-action-post.js b/lib/start-proxy-action-post.js index 3018a5102..4b36497cb 100644 --- a/lib/start-proxy-action-post.js +++ b/lib/start-proxy-action-post.js @@ -161368,6 +161368,7 @@ var semver2 = __toESM(require_semver2()); var RepositoryPropertyName = /* @__PURE__ */ ((RepositoryPropertyName2) => { RepositoryPropertyName2["DISABLE_OVERLAY"] = "github-codeql-disable-overlay"; RepositoryPropertyName2["EXTRA_QUERIES"] = "github-codeql-extra-queries"; + RepositoryPropertyName2["FILE_COVERAGE_ON_PRS"] = "github-codeql-file-coverage-on-prs"; return RepositoryPropertyName2; })(RepositoryPropertyName || {}); var KNOWN_REPOSITORY_PROPERTY_NAMES = new Set( diff --git a/lib/start-proxy-action.js b/lib/start-proxy-action.js index 932966e44..4c88bab59 100644 --- a/lib/start-proxy-action.js +++ b/lib/start-proxy-action.js @@ -121388,6 +121388,7 @@ var semver5 = __toESM(require_semver2()); var RepositoryPropertyName = /* @__PURE__ */ ((RepositoryPropertyName2) => { RepositoryPropertyName2["DISABLE_OVERLAY"] = "github-codeql-disable-overlay"; RepositoryPropertyName2["EXTRA_QUERIES"] = "github-codeql-extra-queries"; + RepositoryPropertyName2["FILE_COVERAGE_ON_PRS"] = "github-codeql-file-coverage-on-prs"; return RepositoryPropertyName2; })(RepositoryPropertyName || {}); var KNOWN_REPOSITORY_PROPERTY_NAMES = new Set( diff --git a/lib/upload-lib.js b/lib/upload-lib.js index ee9218896..ad0a615df 100644 --- a/lib/upload-lib.js +++ b/lib/upload-lib.js @@ -106826,6 +106826,7 @@ var semver2 = __toESM(require_semver2()); var RepositoryPropertyName = /* @__PURE__ */ ((RepositoryPropertyName2) => { RepositoryPropertyName2["DISABLE_OVERLAY"] = "github-codeql-disable-overlay"; RepositoryPropertyName2["EXTRA_QUERIES"] = "github-codeql-extra-queries"; + RepositoryPropertyName2["FILE_COVERAGE_ON_PRS"] = "github-codeql-file-coverage-on-prs"; return RepositoryPropertyName2; })(RepositoryPropertyName || {}); var KNOWN_REPOSITORY_PROPERTY_NAMES = new Set( diff --git a/lib/upload-sarif-action-post.js b/lib/upload-sarif-action-post.js index 0f6b9cbf9..d8915fb49 100644 --- a/lib/upload-sarif-action-post.js +++ b/lib/upload-sarif-action-post.js @@ -161518,6 +161518,7 @@ var semver2 = __toESM(require_semver2()); var RepositoryPropertyName = /* @__PURE__ */ ((RepositoryPropertyName2) => { RepositoryPropertyName2["DISABLE_OVERLAY"] = "github-codeql-disable-overlay"; RepositoryPropertyName2["EXTRA_QUERIES"] = "github-codeql-extra-queries"; + RepositoryPropertyName2["FILE_COVERAGE_ON_PRS"] = "github-codeql-file-coverage-on-prs"; return RepositoryPropertyName2; })(RepositoryPropertyName || {}); var KNOWN_REPOSITORY_PROPERTY_NAMES = new Set( diff --git a/lib/upload-sarif-action.js b/lib/upload-sarif-action.js index 7b3448637..3f97ab020 100644 --- a/lib/upload-sarif-action.js +++ b/lib/upload-sarif-action.js @@ -107572,6 +107572,7 @@ var semver5 = __toESM(require_semver2()); var RepositoryPropertyName = /* @__PURE__ */ ((RepositoryPropertyName2) => { RepositoryPropertyName2["DISABLE_OVERLAY"] = "github-codeql-disable-overlay"; RepositoryPropertyName2["EXTRA_QUERIES"] = "github-codeql-extra-queries"; + RepositoryPropertyName2["FILE_COVERAGE_ON_PRS"] = "github-codeql-file-coverage-on-prs"; return RepositoryPropertyName2; })(RepositoryPropertyName || {}); var KNOWN_REPOSITORY_PROPERTY_NAMES = new Set( diff --git a/src/feature-flags/properties.ts b/src/feature-flags/properties.ts index cb407c308..9245f7ece 100644 --- a/src/feature-flags/properties.ts +++ b/src/feature-flags/properties.ts @@ -9,12 +9,14 @@ import { GitHubVariant, GitHubVersion } from "../util"; export enum RepositoryPropertyName { DISABLE_OVERLAY = "github-codeql-disable-overlay", EXTRA_QUERIES = "github-codeql-extra-queries", + FILE_COVERAGE_ON_PRS = "github-codeql-file-coverage-on-prs", } /** Parsed types of the known repository properties. */ export type AllRepositoryProperties = { [RepositoryPropertyName.DISABLE_OVERLAY]: boolean; [RepositoryPropertyName.EXTRA_QUERIES]: string; + [RepositoryPropertyName.FILE_COVERAGE_ON_PRS]: boolean; }; /** Parsed repository properties. */ @@ -24,6 +26,7 @@ export type RepositoryProperties = Partial; export type RepositoryPropertyApiType = { [RepositoryPropertyName.DISABLE_OVERLAY]: string; [RepositoryPropertyName.EXTRA_QUERIES]: string; + [RepositoryPropertyName.FILE_COVERAGE_ON_PRS]: string; }; /** The type of functions which take the `value` from the API and try to convert it to the type we want. */ @@ -70,6 +73,7 @@ const repositoryPropertyParsers: { } = { [RepositoryPropertyName.DISABLE_OVERLAY]: booleanProperty, [RepositoryPropertyName.EXTRA_QUERIES]: stringProperty, + [RepositoryPropertyName.FILE_COVERAGE_ON_PRS]: booleanProperty, }; /** diff --git a/src/init-action.ts b/src/init-action.ts index de05c9b41..4806141a5 100644 --- a/src/init-action.ts +++ b/src/init-action.ts @@ -380,6 +380,7 @@ async function run(startedAt: Date) { debugMode, codeql, features, + repositoryPropertiesResult.orElse({}), ), logger, }); diff --git a/src/init.test.ts b/src/init.test.ts index d15737ea3..dbc4b4c30 100644 --- a/src/init.test.ts +++ b/src/init.test.ts @@ -457,6 +457,7 @@ test("file coverage information enabled when debugMode is true", async (t) => { true, // debugMode createStubCodeQL({}), createFeatures([Feature.SkipFileCoverageOnPrs]), + {}, ), ); }); @@ -471,6 +472,7 @@ test.serial( false, // debugMode createStubCodeQL({}), createFeatures([Feature.SkipFileCoverageOnPrs]), + {}, ), ); }, @@ -486,6 +488,25 @@ test.serial( false, // debugMode createStubCodeQL({}), createFeatures([]), + {}, + ), + ); + }, +); + +test.serial( + "file coverage information enabled when repository property is set", + async (t) => { + sinon.stub(actionsUtil, "isAnalyzingPullRequest").returns(true); + + t.true( + await getFileCoverageInformationEnabled( + false, // debugMode + createStubCodeQL({}), + createFeatures([Feature.SkipFileCoverageOnPrs]), + { + "github-codeql-file-coverage-on-prs": true, + }, ), ); }, @@ -501,6 +522,7 @@ test.serial( false, // debugMode createStubCodeQL({}), createFeatures([Feature.SkipFileCoverageOnPrs]), + {}, ), ); }, diff --git a/src/init.ts b/src/init.ts index cf84322b9..b5e90b68b 100644 --- a/src/init.ts +++ b/src/init.ts @@ -18,6 +18,10 @@ import { Feature, FeatureEnablement, } from "./feature-flags"; +import { + RepositoryProperties, + RepositoryPropertyName, +} from "./feature-flags/properties"; import { KnownLanguage, Language } from "./languages"; import { Logger, withGroupAsync } from "./logging"; import { ToolsSource } from "./setup-codeql"; @@ -301,6 +305,7 @@ export async function getFileCoverageInformationEnabled( debugMode: boolean, codeql: CodeQL, features: FeatureEnablement, + repositoryProperties: RepositoryProperties, ): Promise { return ( // Always enable file coverage information in debug mode @@ -309,6 +314,10 @@ export async function getFileCoverageInformationEnabled( // submitting file coverage information for the default branch since // it is used to populate the status page. !isAnalyzingPullRequest() || + // Allow repositories to opt in to file coverage information on PRs + // using a repository property. + repositoryProperties[RepositoryPropertyName.FILE_COVERAGE_ON_PRS] === + true || !(await features.getValue(Feature.SkipFileCoverageOnPrs, codeql)) ); }