diff --git a/lib/analyze-action.js b/lib/analyze-action.js index 1bc3fc7dd..dcc02891d 100644 --- a/lib/analyze-action.js +++ b/lib/analyze-action.js @@ -107874,34 +107874,47 @@ var featureConfig = { } }; var FEATURE_FLAGS_FILE_NAME = "cached-feature-flags.json"; -var Features = class { - constructor(gitHubVersion, repositoryNwo, tempDir, logger) { +var OfflineFeatures = class { + constructor(logger) { this.logger = logger; - this.gitHubFeatureFlags = new GitHubFeatureFlags( - gitHubVersion, - repositoryNwo, - path5.join(tempDir, FEATURE_FLAGS_FILE_NAME), - logger - ); } - gitHubFeatureFlags; - async getDefaultCliVersion(variant) { - return await this.gitHubFeatureFlags.getDefaultCliVersion(variant); + async getDefaultCliVersion(_variant) { + return { + cliVersion, + tagName: bundleVersion + }; } /** + * Gets the `FeatureConfig` for `feature`. + */ + getFeatureConfig(feature) { + return featureConfig[feature]; + } + /** + * Determines whether `feature` is enabled without consulting the GitHub API. * * @param feature The feature to check. * @param codeql An optional CodeQL object. If provided, and a `minimumVersion` is specified for the * feature, the version of the CodeQL CLI will be checked against the minimum version. * If the version is less than the minimum version, the feature will be considered - * disabled. If not provided, and a `minimumVersion` is specified for the feature, the + * disabled. If not provided, and a `minimumVersion` is specified for the feature, then * this function will throw. * @returns true if the feature is enabled, false otherwise. * * @throws if a `minimumVersion` is specified for the feature, and `codeql` is not provided. */ async getValue(feature, codeql) { - const config = featureConfig[feature]; + const offlineValue = await this.getOfflineValue(feature, codeql); + if (offlineValue !== void 0) { + return offlineValue; + } + return this.getDefaultValue(feature); + } + /** + * Determines whether `feature` is enabled using the CLI and environment variables. + */ + async getOfflineValue(feature, codeql) { + const config = this.getFeatureConfig(feature); if (!codeql && config.minimumVersion) { throw new Error( `Internal error: A minimum version is specified for feature ${feature}, but no instance of CodeQL was provided.` @@ -107951,13 +107964,11 @@ var Features = class { ); return true; } - const apiValue = await this.gitHubFeatureFlags.getValue(feature); - if (apiValue !== void 0) { - this.logger.debug( - `Feature ${feature} is ${apiValue ? "enabled" : "disabled"} via the GitHub API.` - ); - return apiValue; - } + return void 0; + } + /** Gets the default value of `feature`. */ + async getDefaultValue(feature) { + const config = this.getFeatureConfig(feature); const defaultValue = config.defaultValue; this.logger.debug( `Feature ${feature} is ${defaultValue ? "enabled" : "disabled"} due to its default value.` @@ -107965,9 +107976,51 @@ var Features = class { return defaultValue; } }; +var Features = class extends OfflineFeatures { + gitHubFeatureFlags; + constructor(repositoryNwo, tempDir, logger) { + super(logger); + this.gitHubFeatureFlags = new GitHubFeatureFlags( + repositoryNwo, + path5.join(tempDir, FEATURE_FLAGS_FILE_NAME), + logger + ); + } + async getDefaultCliVersion(variant) { + if (supportsFeatureFlags(variant)) { + return await this.gitHubFeatureFlags.getDefaultCliVersionFromFlags(); + } + return super.getDefaultCliVersion(variant); + } + /** + * + * @param feature The feature to check. + * @param codeql An optional CodeQL object. If provided, and a `minimumVersion` is specified for the + * feature, the version of the CodeQL CLI will be checked against the minimum version. + * If the version is less than the minimum version, the feature will be considered + * disabled. If not provided, and a `minimumVersion` is specified for the feature, then + * this function will throw. + * @returns true if the feature is enabled, false otherwise. + * + * @throws if a `minimumVersion` is specified for the feature, and `codeql` is not provided. + */ + async getValue(feature, codeql) { + const offlineValue = await this.getOfflineValue(feature, codeql); + if (offlineValue !== void 0) { + return offlineValue; + } + const apiValue = await this.gitHubFeatureFlags.getValue(feature); + if (apiValue !== void 0) { + this.logger.debug( + `Feature ${feature} is ${apiValue ? "enabled" : "disabled"} via the GitHub API.` + ); + return apiValue; + } + return this.getDefaultValue(feature); + } +}; var GitHubFeatureFlags = class { - constructor(gitHubVersion, repositoryNwo, featureFlagsFile, logger) { - this.gitHubVersion = gitHubVersion; + constructor(repositoryNwo, featureFlagsFile, logger) { this.repositoryNwo = repositoryNwo; this.featureFlagsFile = featureFlagsFile; this.logger = logger; @@ -107993,15 +108046,6 @@ var GitHubFeatureFlags = class { } return version; } - async getDefaultCliVersion(variant) { - if (supportsFeatureFlags(variant)) { - return await this.getDefaultCliVersionFromFlags(); - } - return { - cliVersion, - tagName: bundleVersion - }; - } async getDefaultCliVersionFromFlags() { const response = await this.getAllFeatures(); const enabledFeatureFlagCliVersions = Object.entries(response).map( @@ -108091,20 +108135,6 @@ var GitHubFeatureFlags = class { } } async loadApiResponse() { - if (!supportsFeatureFlags(this.gitHubVersion.type)) { - this.logger.debug( - "Not running against github.com. Using default values for all features." - ); - this.hasAccessedRemoteFeatureFlags = false; - return {}; - } - if (isCCR()) { - this.logger.debug( - "Feature flags are not supported in Copilot Code Review. Using default values for all features." - ); - this.hasAccessedRemoteFeatureFlags = false; - return {}; - } try { const featuresToRequest = Object.entries(featureConfig).filter( ([, config]) => !config.legacyApi @@ -108156,6 +108186,21 @@ var GitHubFeatureFlags = class { function supportsFeatureFlags(githubVariant) { return githubVariant === "GitHub.com" /* DOTCOM */ || githubVariant === "GitHub Enterprise Cloud with data residency" /* GHEC_DR */; } +function initFeatures(gitHubVersion, repositoryNwo, tempDir, logger) { + if (!supportsFeatureFlags(gitHubVersion.type)) { + logger.debug( + "Not running against github.com. Using default values for all features." + ); + return new OfflineFeatures(logger); + } else if (isCCR()) { + logger.debug( + "Querying feature flags is not currently supported in Copilot Code Review. Using offline data for all features." + ); + return new OfflineFeatures(logger); + } else { + return new Features(repositoryNwo, tempDir, logger); + } +} // src/diff-informed-analysis-utils.ts async function getDiffInformedAnalysisBranches(codeql, features, logger) { @@ -110130,7 +110175,7 @@ async function setupCppAutobuild(codeql, logger) { const featureName = "C++ automatic installation of dependencies"; const gitHubVersion = await getGitHubVersion(); const repositoryNwo = getRepositoryNwo(); - const features = new Features( + const features = initFeatures( gitHubVersion, repositoryNwo, getTemporaryDirectory(), @@ -113028,7 +113073,7 @@ async function run(startedAt2) { const repositoryNwo = getRepositoryNwo(); const gitHubVersion = await getGitHubVersion(); checkActionVersion(getActionVersion(), gitHubVersion); - const features = new Features( + const features = initFeatures( gitHubVersion, repositoryNwo, getTemporaryDirectory(), diff --git a/lib/autobuild-action.js b/lib/autobuild-action.js index 0538f5bd5..1a3256345 100644 --- a/lib/autobuild-action.js +++ b/lib/autobuild-action.js @@ -104164,34 +104164,47 @@ var featureConfig = { } }; var FEATURE_FLAGS_FILE_NAME = "cached-feature-flags.json"; -var Features = class { - constructor(gitHubVersion, repositoryNwo, tempDir, logger) { +var OfflineFeatures = class { + constructor(logger) { this.logger = logger; - this.gitHubFeatureFlags = new GitHubFeatureFlags( - gitHubVersion, - repositoryNwo, - path3.join(tempDir, FEATURE_FLAGS_FILE_NAME), - logger - ); } - gitHubFeatureFlags; - async getDefaultCliVersion(variant) { - return await this.gitHubFeatureFlags.getDefaultCliVersion(variant); + async getDefaultCliVersion(_variant) { + return { + cliVersion, + tagName: bundleVersion + }; } /** + * Gets the `FeatureConfig` for `feature`. + */ + getFeatureConfig(feature) { + return featureConfig[feature]; + } + /** + * Determines whether `feature` is enabled without consulting the GitHub API. * * @param feature The feature to check. * @param codeql An optional CodeQL object. If provided, and a `minimumVersion` is specified for the * feature, the version of the CodeQL CLI will be checked against the minimum version. * If the version is less than the minimum version, the feature will be considered - * disabled. If not provided, and a `minimumVersion` is specified for the feature, the + * disabled. If not provided, and a `minimumVersion` is specified for the feature, then * this function will throw. * @returns true if the feature is enabled, false otherwise. * * @throws if a `minimumVersion` is specified for the feature, and `codeql` is not provided. */ async getValue(feature, codeql) { - const config = featureConfig[feature]; + const offlineValue = await this.getOfflineValue(feature, codeql); + if (offlineValue !== void 0) { + return offlineValue; + } + return this.getDefaultValue(feature); + } + /** + * Determines whether `feature` is enabled using the CLI and environment variables. + */ + async getOfflineValue(feature, codeql) { + const config = this.getFeatureConfig(feature); if (!codeql && config.minimumVersion) { throw new Error( `Internal error: A minimum version is specified for feature ${feature}, but no instance of CodeQL was provided.` @@ -104241,13 +104254,11 @@ var Features = class { ); return true; } - const apiValue = await this.gitHubFeatureFlags.getValue(feature); - if (apiValue !== void 0) { - this.logger.debug( - `Feature ${feature} is ${apiValue ? "enabled" : "disabled"} via the GitHub API.` - ); - return apiValue; - } + return void 0; + } + /** Gets the default value of `feature`. */ + async getDefaultValue(feature) { + const config = this.getFeatureConfig(feature); const defaultValue = config.defaultValue; this.logger.debug( `Feature ${feature} is ${defaultValue ? "enabled" : "disabled"} due to its default value.` @@ -104255,9 +104266,51 @@ var Features = class { return defaultValue; } }; +var Features = class extends OfflineFeatures { + gitHubFeatureFlags; + constructor(repositoryNwo, tempDir, logger) { + super(logger); + this.gitHubFeatureFlags = new GitHubFeatureFlags( + repositoryNwo, + path3.join(tempDir, FEATURE_FLAGS_FILE_NAME), + logger + ); + } + async getDefaultCliVersion(variant) { + if (supportsFeatureFlags(variant)) { + return await this.gitHubFeatureFlags.getDefaultCliVersionFromFlags(); + } + return super.getDefaultCliVersion(variant); + } + /** + * + * @param feature The feature to check. + * @param codeql An optional CodeQL object. If provided, and a `minimumVersion` is specified for the + * feature, the version of the CodeQL CLI will be checked against the minimum version. + * If the version is less than the minimum version, the feature will be considered + * disabled. If not provided, and a `minimumVersion` is specified for the feature, then + * this function will throw. + * @returns true if the feature is enabled, false otherwise. + * + * @throws if a `minimumVersion` is specified for the feature, and `codeql` is not provided. + */ + async getValue(feature, codeql) { + const offlineValue = await this.getOfflineValue(feature, codeql); + if (offlineValue !== void 0) { + return offlineValue; + } + const apiValue = await this.gitHubFeatureFlags.getValue(feature); + if (apiValue !== void 0) { + this.logger.debug( + `Feature ${feature} is ${apiValue ? "enabled" : "disabled"} via the GitHub API.` + ); + return apiValue; + } + return this.getDefaultValue(feature); + } +}; var GitHubFeatureFlags = class { - constructor(gitHubVersion, repositoryNwo, featureFlagsFile, logger) { - this.gitHubVersion = gitHubVersion; + constructor(repositoryNwo, featureFlagsFile, logger) { this.repositoryNwo = repositoryNwo; this.featureFlagsFile = featureFlagsFile; this.logger = logger; @@ -104283,15 +104336,6 @@ var GitHubFeatureFlags = class { } return version; } - async getDefaultCliVersion(variant) { - if (supportsFeatureFlags(variant)) { - return await this.getDefaultCliVersionFromFlags(); - } - return { - cliVersion, - tagName: bundleVersion - }; - } async getDefaultCliVersionFromFlags() { const response = await this.getAllFeatures(); const enabledFeatureFlagCliVersions = Object.entries(response).map( @@ -104381,20 +104425,6 @@ var GitHubFeatureFlags = class { } } async loadApiResponse() { - if (!supportsFeatureFlags(this.gitHubVersion.type)) { - this.logger.debug( - "Not running against github.com. Using default values for all features." - ); - this.hasAccessedRemoteFeatureFlags = false; - return {}; - } - if (isCCR()) { - this.logger.debug( - "Feature flags are not supported in Copilot Code Review. Using default values for all features." - ); - this.hasAccessedRemoteFeatureFlags = false; - return {}; - } try { const featuresToRequest = Object.entries(featureConfig).filter( ([, config]) => !config.legacyApi @@ -104446,6 +104476,21 @@ var GitHubFeatureFlags = class { function supportsFeatureFlags(githubVariant) { return githubVariant === "GitHub.com" /* DOTCOM */ || githubVariant === "GitHub Enterprise Cloud with data residency" /* GHEC_DR */; } +function initFeatures(gitHubVersion, repositoryNwo, tempDir, logger) { + if (!supportsFeatureFlags(gitHubVersion.type)) { + logger.debug( + "Not running against github.com. Using default values for all features." + ); + return new OfflineFeatures(logger); + } else if (isCCR()) { + logger.debug( + "Querying feature flags is not currently supported in Copilot Code Review. Using offline data for all features." + ); + return new OfflineFeatures(logger); + } else { + return new Features(repositoryNwo, tempDir, logger); + } +} // src/trap-caching.ts var actionsCache2 = __toESM(require_cache5()); @@ -105197,7 +105242,7 @@ async function setupCppAutobuild(codeql, logger) { const featureName = "C++ automatic installation of dependencies"; const gitHubVersion = await getGitHubVersion(); const repositoryNwo = getRepositoryNwo(); - const features = new Features( + const features = initFeatures( gitHubVersion, repositoryNwo, getTemporaryDirectory(), diff --git a/lib/init-action-post.js b/lib/init-action-post.js index 7533722ef..7f4262f04 100644 --- a/lib/init-action-post.js +++ b/lib/init-action-post.js @@ -165241,34 +165241,47 @@ var featureConfig = { } }; var FEATURE_FLAGS_FILE_NAME = "cached-feature-flags.json"; -var Features = class { - constructor(gitHubVersion, repositoryNwo, tempDir, logger) { +var OfflineFeatures = class { + constructor(logger) { this.logger = logger; - this.gitHubFeatureFlags = new GitHubFeatureFlags( - gitHubVersion, - repositoryNwo, - path5.join(tempDir, FEATURE_FLAGS_FILE_NAME), - logger - ); } - gitHubFeatureFlags; - async getDefaultCliVersion(variant) { - return await this.gitHubFeatureFlags.getDefaultCliVersion(variant); + async getDefaultCliVersion(_variant) { + return { + cliVersion, + tagName: bundleVersion + }; } /** + * Gets the `FeatureConfig` for `feature`. + */ + getFeatureConfig(feature) { + return featureConfig[feature]; + } + /** + * Determines whether `feature` is enabled without consulting the GitHub API. * * @param feature The feature to check. * @param codeql An optional CodeQL object. If provided, and a `minimumVersion` is specified for the * feature, the version of the CodeQL CLI will be checked against the minimum version. * If the version is less than the minimum version, the feature will be considered - * disabled. If not provided, and a `minimumVersion` is specified for the feature, the + * disabled. If not provided, and a `minimumVersion` is specified for the feature, then * this function will throw. * @returns true if the feature is enabled, false otherwise. * * @throws if a `minimumVersion` is specified for the feature, and `codeql` is not provided. */ async getValue(feature, codeql) { - const config = featureConfig[feature]; + const offlineValue = await this.getOfflineValue(feature, codeql); + if (offlineValue !== void 0) { + return offlineValue; + } + return this.getDefaultValue(feature); + } + /** + * Determines whether `feature` is enabled using the CLI and environment variables. + */ + async getOfflineValue(feature, codeql) { + const config = this.getFeatureConfig(feature); if (!codeql && config.minimumVersion) { throw new Error( `Internal error: A minimum version is specified for feature ${feature}, but no instance of CodeQL was provided.` @@ -165318,13 +165331,11 @@ var Features = class { ); return true; } - const apiValue = await this.gitHubFeatureFlags.getValue(feature); - if (apiValue !== void 0) { - this.logger.debug( - `Feature ${feature} is ${apiValue ? "enabled" : "disabled"} via the GitHub API.` - ); - return apiValue; - } + return void 0; + } + /** Gets the default value of `feature`. */ + async getDefaultValue(feature) { + const config = this.getFeatureConfig(feature); const defaultValue = config.defaultValue; this.logger.debug( `Feature ${feature} is ${defaultValue ? "enabled" : "disabled"} due to its default value.` @@ -165332,9 +165343,51 @@ var Features = class { return defaultValue; } }; +var Features = class extends OfflineFeatures { + gitHubFeatureFlags; + constructor(repositoryNwo, tempDir, logger) { + super(logger); + this.gitHubFeatureFlags = new GitHubFeatureFlags( + repositoryNwo, + path5.join(tempDir, FEATURE_FLAGS_FILE_NAME), + logger + ); + } + async getDefaultCliVersion(variant) { + if (supportsFeatureFlags(variant)) { + return await this.gitHubFeatureFlags.getDefaultCliVersionFromFlags(); + } + return super.getDefaultCliVersion(variant); + } + /** + * + * @param feature The feature to check. + * @param codeql An optional CodeQL object. If provided, and a `minimumVersion` is specified for the + * feature, the version of the CodeQL CLI will be checked against the minimum version. + * If the version is less than the minimum version, the feature will be considered + * disabled. If not provided, and a `minimumVersion` is specified for the feature, then + * this function will throw. + * @returns true if the feature is enabled, false otherwise. + * + * @throws if a `minimumVersion` is specified for the feature, and `codeql` is not provided. + */ + async getValue(feature, codeql) { + const offlineValue = await this.getOfflineValue(feature, codeql); + if (offlineValue !== void 0) { + return offlineValue; + } + const apiValue = await this.gitHubFeatureFlags.getValue(feature); + if (apiValue !== void 0) { + this.logger.debug( + `Feature ${feature} is ${apiValue ? "enabled" : "disabled"} via the GitHub API.` + ); + return apiValue; + } + return this.getDefaultValue(feature); + } +}; var GitHubFeatureFlags = class { - constructor(gitHubVersion, repositoryNwo, featureFlagsFile, logger) { - this.gitHubVersion = gitHubVersion; + constructor(repositoryNwo, featureFlagsFile, logger) { this.repositoryNwo = repositoryNwo; this.featureFlagsFile = featureFlagsFile; this.logger = logger; @@ -165360,15 +165413,6 @@ var GitHubFeatureFlags = class { } return version; } - async getDefaultCliVersion(variant) { - if (supportsFeatureFlags(variant)) { - return await this.getDefaultCliVersionFromFlags(); - } - return { - cliVersion, - tagName: bundleVersion - }; - } async getDefaultCliVersionFromFlags() { const response = await this.getAllFeatures(); const enabledFeatureFlagCliVersions = Object.entries(response).map( @@ -165458,20 +165502,6 @@ var GitHubFeatureFlags = class { } } async loadApiResponse() { - if (!supportsFeatureFlags(this.gitHubVersion.type)) { - this.logger.debug( - "Not running against github.com. Using default values for all features." - ); - this.hasAccessedRemoteFeatureFlags = false; - return {}; - } - if (isCCR()) { - this.logger.debug( - "Feature flags are not supported in Copilot Code Review. Using default values for all features." - ); - this.hasAccessedRemoteFeatureFlags = false; - return {}; - } try { const featuresToRequest = Object.entries(featureConfig).filter( ([, config]) => !config.legacyApi @@ -165523,6 +165553,21 @@ var GitHubFeatureFlags = class { function supportsFeatureFlags(githubVariant) { return githubVariant === "GitHub.com" /* DOTCOM */ || githubVariant === "GitHub Enterprise Cloud with data residency" /* GHEC_DR */; } +function initFeatures(gitHubVersion, repositoryNwo, tempDir, logger) { + if (!supportsFeatureFlags(gitHubVersion.type)) { + logger.debug( + "Not running against github.com. Using default values for all features." + ); + return new OfflineFeatures(logger); + } else if (isCCR()) { + logger.debug( + "Querying feature flags is not currently supported in Copilot Code Review. Using offline data for all features." + ); + return new OfflineFeatures(logger); + } else { + return new Features(repositoryNwo, tempDir, logger); + } +} // src/diff-informed-analysis-utils.ts function getDiffRangesJsonFilePath() { @@ -170047,7 +170092,7 @@ async function run2(startedAt) { const gitHubVersion = await getGitHubVersion(); checkGitHubVersionInRange(gitHubVersion, logger); const repositoryNwo = getRepositoryNwo(); - const features = new Features( + const features = initFeatures( gitHubVersion, repositoryNwo, getTemporaryDirectory(), diff --git a/lib/init-action.js b/lib/init-action.js index aff81014f..903bd9fcc 100644 --- a/lib/init-action.js +++ b/lib/init-action.js @@ -105391,34 +105391,47 @@ var featureConfig = { } }; var FEATURE_FLAGS_FILE_NAME = "cached-feature-flags.json"; -var Features = class { - constructor(gitHubVersion, repositoryNwo, tempDir, logger) { +var OfflineFeatures = class { + constructor(logger) { this.logger = logger; - this.gitHubFeatureFlags = new GitHubFeatureFlags( - gitHubVersion, - repositoryNwo, - path6.join(tempDir, FEATURE_FLAGS_FILE_NAME), - logger - ); } - gitHubFeatureFlags; - async getDefaultCliVersion(variant) { - return await this.gitHubFeatureFlags.getDefaultCliVersion(variant); + async getDefaultCliVersion(_variant) { + return { + cliVersion, + tagName: bundleVersion + }; } /** + * Gets the `FeatureConfig` for `feature`. + */ + getFeatureConfig(feature) { + return featureConfig[feature]; + } + /** + * Determines whether `feature` is enabled without consulting the GitHub API. * * @param feature The feature to check. * @param codeql An optional CodeQL object. If provided, and a `minimumVersion` is specified for the * feature, the version of the CodeQL CLI will be checked against the minimum version. * If the version is less than the minimum version, the feature will be considered - * disabled. If not provided, and a `minimumVersion` is specified for the feature, the + * disabled. If not provided, and a `minimumVersion` is specified for the feature, then * this function will throw. * @returns true if the feature is enabled, false otherwise. * * @throws if a `minimumVersion` is specified for the feature, and `codeql` is not provided. */ async getValue(feature, codeql) { - const config = featureConfig[feature]; + const offlineValue = await this.getOfflineValue(feature, codeql); + if (offlineValue !== void 0) { + return offlineValue; + } + return this.getDefaultValue(feature); + } + /** + * Determines whether `feature` is enabled using the CLI and environment variables. + */ + async getOfflineValue(feature, codeql) { + const config = this.getFeatureConfig(feature); if (!codeql && config.minimumVersion) { throw new Error( `Internal error: A minimum version is specified for feature ${feature}, but no instance of CodeQL was provided.` @@ -105468,13 +105481,11 @@ var Features = class { ); return true; } - const apiValue = await this.gitHubFeatureFlags.getValue(feature); - if (apiValue !== void 0) { - this.logger.debug( - `Feature ${feature} is ${apiValue ? "enabled" : "disabled"} via the GitHub API.` - ); - return apiValue; - } + return void 0; + } + /** Gets the default value of `feature`. */ + async getDefaultValue(feature) { + const config = this.getFeatureConfig(feature); const defaultValue = config.defaultValue; this.logger.debug( `Feature ${feature} is ${defaultValue ? "enabled" : "disabled"} due to its default value.` @@ -105482,9 +105493,51 @@ var Features = class { return defaultValue; } }; +var Features = class extends OfflineFeatures { + gitHubFeatureFlags; + constructor(repositoryNwo, tempDir, logger) { + super(logger); + this.gitHubFeatureFlags = new GitHubFeatureFlags( + repositoryNwo, + path6.join(tempDir, FEATURE_FLAGS_FILE_NAME), + logger + ); + } + async getDefaultCliVersion(variant) { + if (supportsFeatureFlags(variant)) { + return await this.gitHubFeatureFlags.getDefaultCliVersionFromFlags(); + } + return super.getDefaultCliVersion(variant); + } + /** + * + * @param feature The feature to check. + * @param codeql An optional CodeQL object. If provided, and a `minimumVersion` is specified for the + * feature, the version of the CodeQL CLI will be checked against the minimum version. + * If the version is less than the minimum version, the feature will be considered + * disabled. If not provided, and a `minimumVersion` is specified for the feature, then + * this function will throw. + * @returns true if the feature is enabled, false otherwise. + * + * @throws if a `minimumVersion` is specified for the feature, and `codeql` is not provided. + */ + async getValue(feature, codeql) { + const offlineValue = await this.getOfflineValue(feature, codeql); + if (offlineValue !== void 0) { + return offlineValue; + } + const apiValue = await this.gitHubFeatureFlags.getValue(feature); + if (apiValue !== void 0) { + this.logger.debug( + `Feature ${feature} is ${apiValue ? "enabled" : "disabled"} via the GitHub API.` + ); + return apiValue; + } + return this.getDefaultValue(feature); + } +}; var GitHubFeatureFlags = class { - constructor(gitHubVersion, repositoryNwo, featureFlagsFile, logger) { - this.gitHubVersion = gitHubVersion; + constructor(repositoryNwo, featureFlagsFile, logger) { this.repositoryNwo = repositoryNwo; this.featureFlagsFile = featureFlagsFile; this.logger = logger; @@ -105510,15 +105563,6 @@ var GitHubFeatureFlags = class { } return version; } - async getDefaultCliVersion(variant) { - if (supportsFeatureFlags(variant)) { - return await this.getDefaultCliVersionFromFlags(); - } - return { - cliVersion, - tagName: bundleVersion - }; - } async getDefaultCliVersionFromFlags() { const response = await this.getAllFeatures(); const enabledFeatureFlagCliVersions = Object.entries(response).map( @@ -105608,20 +105652,6 @@ var GitHubFeatureFlags = class { } } async loadApiResponse() { - if (!supportsFeatureFlags(this.gitHubVersion.type)) { - this.logger.debug( - "Not running against github.com. Using default values for all features." - ); - this.hasAccessedRemoteFeatureFlags = false; - return {}; - } - if (isCCR()) { - this.logger.debug( - "Feature flags are not supported in Copilot Code Review. Using default values for all features." - ); - this.hasAccessedRemoteFeatureFlags = false; - return {}; - } try { const featuresToRequest = Object.entries(featureConfig).filter( ([, config]) => !config.legacyApi @@ -105673,6 +105703,21 @@ var GitHubFeatureFlags = class { function supportsFeatureFlags(githubVariant) { return githubVariant === "GitHub.com" /* DOTCOM */ || githubVariant === "GitHub Enterprise Cloud with data residency" /* GHEC_DR */; } +function initFeatures(gitHubVersion, repositoryNwo, tempDir, logger) { + if (!supportsFeatureFlags(gitHubVersion.type)) { + logger.debug( + "Not running against github.com. Using default values for all features." + ); + return new OfflineFeatures(logger); + } else if (isCCR()) { + logger.debug( + "Querying feature flags is not currently supported in Copilot Code Review. Using offline data for all features." + ); + return new OfflineFeatures(logger); + } else { + return new Features(repositoryNwo, tempDir, logger); + } +} // src/diff-informed-analysis-utils.ts async function shouldPerformDiffInformedAnalysis(codeql, features, logger) { @@ -109191,7 +109236,7 @@ async function run(startedAt) { checkGitHubVersionInRange(gitHubVersion, logger); checkActionVersion(getActionVersion(), gitHubVersion); const repositoryNwo = getRepositoryNwo(); - features = new Features( + features = initFeatures( gitHubVersion, repositoryNwo, getTemporaryDirectory(), diff --git a/lib/setup-codeql-action.js b/lib/setup-codeql-action.js index c83039492..38e510783 100644 --- a/lib/setup-codeql-action.js +++ b/lib/setup-codeql-action.js @@ -104064,34 +104064,47 @@ var featureConfig = { } }; var FEATURE_FLAGS_FILE_NAME = "cached-feature-flags.json"; -var Features = class { - constructor(gitHubVersion, repositoryNwo, tempDir, logger) { +var OfflineFeatures = class { + constructor(logger) { this.logger = logger; - this.gitHubFeatureFlags = new GitHubFeatureFlags( - gitHubVersion, - repositoryNwo, - path4.join(tempDir, FEATURE_FLAGS_FILE_NAME), - logger - ); } - gitHubFeatureFlags; - async getDefaultCliVersion(variant) { - return await this.gitHubFeatureFlags.getDefaultCliVersion(variant); + async getDefaultCliVersion(_variant) { + return { + cliVersion, + tagName: bundleVersion + }; } /** + * Gets the `FeatureConfig` for `feature`. + */ + getFeatureConfig(feature) { + return featureConfig[feature]; + } + /** + * Determines whether `feature` is enabled without consulting the GitHub API. * * @param feature The feature to check. * @param codeql An optional CodeQL object. If provided, and a `minimumVersion` is specified for the * feature, the version of the CodeQL CLI will be checked against the minimum version. * If the version is less than the minimum version, the feature will be considered - * disabled. If not provided, and a `minimumVersion` is specified for the feature, the + * disabled. If not provided, and a `minimumVersion` is specified for the feature, then * this function will throw. * @returns true if the feature is enabled, false otherwise. * * @throws if a `minimumVersion` is specified for the feature, and `codeql` is not provided. */ async getValue(feature, codeql) { - const config = featureConfig[feature]; + const offlineValue = await this.getOfflineValue(feature, codeql); + if (offlineValue !== void 0) { + return offlineValue; + } + return this.getDefaultValue(feature); + } + /** + * Determines whether `feature` is enabled using the CLI and environment variables. + */ + async getOfflineValue(feature, codeql) { + const config = this.getFeatureConfig(feature); if (!codeql && config.minimumVersion) { throw new Error( `Internal error: A minimum version is specified for feature ${feature}, but no instance of CodeQL was provided.` @@ -104141,13 +104154,11 @@ var Features = class { ); return true; } - const apiValue = await this.gitHubFeatureFlags.getValue(feature); - if (apiValue !== void 0) { - this.logger.debug( - `Feature ${feature} is ${apiValue ? "enabled" : "disabled"} via the GitHub API.` - ); - return apiValue; - } + return void 0; + } + /** Gets the default value of `feature`. */ + async getDefaultValue(feature) { + const config = this.getFeatureConfig(feature); const defaultValue = config.defaultValue; this.logger.debug( `Feature ${feature} is ${defaultValue ? "enabled" : "disabled"} due to its default value.` @@ -104155,9 +104166,51 @@ var Features = class { return defaultValue; } }; +var Features = class extends OfflineFeatures { + gitHubFeatureFlags; + constructor(repositoryNwo, tempDir, logger) { + super(logger); + this.gitHubFeatureFlags = new GitHubFeatureFlags( + repositoryNwo, + path4.join(tempDir, FEATURE_FLAGS_FILE_NAME), + logger + ); + } + async getDefaultCliVersion(variant) { + if (supportsFeatureFlags(variant)) { + return await this.gitHubFeatureFlags.getDefaultCliVersionFromFlags(); + } + return super.getDefaultCliVersion(variant); + } + /** + * + * @param feature The feature to check. + * @param codeql An optional CodeQL object. If provided, and a `minimumVersion` is specified for the + * feature, the version of the CodeQL CLI will be checked against the minimum version. + * If the version is less than the minimum version, the feature will be considered + * disabled. If not provided, and a `minimumVersion` is specified for the feature, then + * this function will throw. + * @returns true if the feature is enabled, false otherwise. + * + * @throws if a `minimumVersion` is specified for the feature, and `codeql` is not provided. + */ + async getValue(feature, codeql) { + const offlineValue = await this.getOfflineValue(feature, codeql); + if (offlineValue !== void 0) { + return offlineValue; + } + const apiValue = await this.gitHubFeatureFlags.getValue(feature); + if (apiValue !== void 0) { + this.logger.debug( + `Feature ${feature} is ${apiValue ? "enabled" : "disabled"} via the GitHub API.` + ); + return apiValue; + } + return this.getDefaultValue(feature); + } +}; var GitHubFeatureFlags = class { - constructor(gitHubVersion, repositoryNwo, featureFlagsFile, logger) { - this.gitHubVersion = gitHubVersion; + constructor(repositoryNwo, featureFlagsFile, logger) { this.repositoryNwo = repositoryNwo; this.featureFlagsFile = featureFlagsFile; this.logger = logger; @@ -104183,15 +104236,6 @@ var GitHubFeatureFlags = class { } return version; } - async getDefaultCliVersion(variant) { - if (supportsFeatureFlags(variant)) { - return await this.getDefaultCliVersionFromFlags(); - } - return { - cliVersion, - tagName: bundleVersion - }; - } async getDefaultCliVersionFromFlags() { const response = await this.getAllFeatures(); const enabledFeatureFlagCliVersions = Object.entries(response).map( @@ -104281,20 +104325,6 @@ var GitHubFeatureFlags = class { } } async loadApiResponse() { - if (!supportsFeatureFlags(this.gitHubVersion.type)) { - this.logger.debug( - "Not running against github.com. Using default values for all features." - ); - this.hasAccessedRemoteFeatureFlags = false; - return {}; - } - if (isCCR()) { - this.logger.debug( - "Feature flags are not supported in Copilot Code Review. Using default values for all features." - ); - this.hasAccessedRemoteFeatureFlags = false; - return {}; - } try { const featuresToRequest = Object.entries(featureConfig).filter( ([, config]) => !config.legacyApi @@ -104346,6 +104376,21 @@ var GitHubFeatureFlags = class { function supportsFeatureFlags(githubVariant) { return githubVariant === "GitHub.com" /* DOTCOM */ || githubVariant === "GitHub Enterprise Cloud with data residency" /* GHEC_DR */; } +function initFeatures(gitHubVersion, repositoryNwo, tempDir, logger) { + if (!supportsFeatureFlags(gitHubVersion.type)) { + logger.debug( + "Not running against github.com. Using default values for all features." + ); + return new OfflineFeatures(logger); + } else if (isCCR()) { + logger.debug( + "Querying feature flags is not currently supported in Copilot Code Review. Using offline data for all features." + ); + return new OfflineFeatures(logger); + } else { + return new Features(repositoryNwo, tempDir, logger); + } +} // src/init.ts var toolrunner4 = __toESM(require_toolrunner()); @@ -106526,7 +106571,7 @@ async function run(startedAt) { checkGitHubVersionInRange(gitHubVersion, logger); checkActionVersion(getActionVersion(), gitHubVersion); const repositoryNwo = getRepositoryNwo(); - const features = new Features( + const features = initFeatures( gitHubVersion, repositoryNwo, getTemporaryDirectory(), diff --git a/lib/start-proxy-action.js b/lib/start-proxy-action.js index d49f35148..355becbbe 100644 --- a/lib/start-proxy-action.js +++ b/lib/start-proxy-action.js @@ -120856,34 +120856,47 @@ var featureConfig = { } }; var FEATURE_FLAGS_FILE_NAME = "cached-feature-flags.json"; -var Features = class { - constructor(gitHubVersion, repositoryNwo, tempDir, logger) { +var OfflineFeatures = class { + constructor(logger) { this.logger = logger; - this.gitHubFeatureFlags = new GitHubFeatureFlags( - gitHubVersion, - repositoryNwo, - path.join(tempDir, FEATURE_FLAGS_FILE_NAME), - logger - ); } - gitHubFeatureFlags; - async getDefaultCliVersion(variant) { - return await this.gitHubFeatureFlags.getDefaultCliVersion(variant); + async getDefaultCliVersion(_variant) { + return { + cliVersion, + tagName: bundleVersion + }; } /** + * Gets the `FeatureConfig` for `feature`. + */ + getFeatureConfig(feature) { + return featureConfig[feature]; + } + /** + * Determines whether `feature` is enabled without consulting the GitHub API. * * @param feature The feature to check. * @param codeql An optional CodeQL object. If provided, and a `minimumVersion` is specified for the * feature, the version of the CodeQL CLI will be checked against the minimum version. * If the version is less than the minimum version, the feature will be considered - * disabled. If not provided, and a `minimumVersion` is specified for the feature, the + * disabled. If not provided, and a `minimumVersion` is specified for the feature, then * this function will throw. * @returns true if the feature is enabled, false otherwise. * * @throws if a `minimumVersion` is specified for the feature, and `codeql` is not provided. */ async getValue(feature, codeql) { - const config = featureConfig[feature]; + const offlineValue = await this.getOfflineValue(feature, codeql); + if (offlineValue !== void 0) { + return offlineValue; + } + return this.getDefaultValue(feature); + } + /** + * Determines whether `feature` is enabled using the CLI and environment variables. + */ + async getOfflineValue(feature, codeql) { + const config = this.getFeatureConfig(feature); if (!codeql && config.minimumVersion) { throw new Error( `Internal error: A minimum version is specified for feature ${feature}, but no instance of CodeQL was provided.` @@ -120933,13 +120946,11 @@ var Features = class { ); return true; } - const apiValue = await this.gitHubFeatureFlags.getValue(feature); - if (apiValue !== void 0) { - this.logger.debug( - `Feature ${feature} is ${apiValue ? "enabled" : "disabled"} via the GitHub API.` - ); - return apiValue; - } + return void 0; + } + /** Gets the default value of `feature`. */ + async getDefaultValue(feature) { + const config = this.getFeatureConfig(feature); const defaultValue = config.defaultValue; this.logger.debug( `Feature ${feature} is ${defaultValue ? "enabled" : "disabled"} due to its default value.` @@ -120947,9 +120958,51 @@ var Features = class { return defaultValue; } }; +var Features = class extends OfflineFeatures { + gitHubFeatureFlags; + constructor(repositoryNwo, tempDir, logger) { + super(logger); + this.gitHubFeatureFlags = new GitHubFeatureFlags( + repositoryNwo, + path.join(tempDir, FEATURE_FLAGS_FILE_NAME), + logger + ); + } + async getDefaultCliVersion(variant) { + if (supportsFeatureFlags(variant)) { + return await this.gitHubFeatureFlags.getDefaultCliVersionFromFlags(); + } + return super.getDefaultCliVersion(variant); + } + /** + * + * @param feature The feature to check. + * @param codeql An optional CodeQL object. If provided, and a `minimumVersion` is specified for the + * feature, the version of the CodeQL CLI will be checked against the minimum version. + * If the version is less than the minimum version, the feature will be considered + * disabled. If not provided, and a `minimumVersion` is specified for the feature, then + * this function will throw. + * @returns true if the feature is enabled, false otherwise. + * + * @throws if a `minimumVersion` is specified for the feature, and `codeql` is not provided. + */ + async getValue(feature, codeql) { + const offlineValue = await this.getOfflineValue(feature, codeql); + if (offlineValue !== void 0) { + return offlineValue; + } + const apiValue = await this.gitHubFeatureFlags.getValue(feature); + if (apiValue !== void 0) { + this.logger.debug( + `Feature ${feature} is ${apiValue ? "enabled" : "disabled"} via the GitHub API.` + ); + return apiValue; + } + return this.getDefaultValue(feature); + } +}; var GitHubFeatureFlags = class { - constructor(gitHubVersion, repositoryNwo, featureFlagsFile, logger) { - this.gitHubVersion = gitHubVersion; + constructor(repositoryNwo, featureFlagsFile, logger) { this.repositoryNwo = repositoryNwo; this.featureFlagsFile = featureFlagsFile; this.logger = logger; @@ -120975,15 +121028,6 @@ var GitHubFeatureFlags = class { } return version; } - async getDefaultCliVersion(variant) { - if (supportsFeatureFlags(variant)) { - return await this.getDefaultCliVersionFromFlags(); - } - return { - cliVersion, - tagName: bundleVersion - }; - } async getDefaultCliVersionFromFlags() { const response = await this.getAllFeatures(); const enabledFeatureFlagCliVersions = Object.entries(response).map( @@ -121073,20 +121117,6 @@ var GitHubFeatureFlags = class { } } async loadApiResponse() { - if (!supportsFeatureFlags(this.gitHubVersion.type)) { - this.logger.debug( - "Not running against github.com. Using default values for all features." - ); - this.hasAccessedRemoteFeatureFlags = false; - return {}; - } - if (isCCR()) { - this.logger.debug( - "Feature flags are not supported in Copilot Code Review. Using default values for all features." - ); - this.hasAccessedRemoteFeatureFlags = false; - return {}; - } try { const featuresToRequest = Object.entries(featureConfig).filter( ([, config]) => !config.legacyApi @@ -121138,6 +121168,21 @@ var GitHubFeatureFlags = class { function supportsFeatureFlags(githubVariant) { return githubVariant === "GitHub.com" /* DOTCOM */ || githubVariant === "GitHub Enterprise Cloud with data residency" /* GHEC_DR */; } +function initFeatures(gitHubVersion, repositoryNwo, tempDir, logger) { + if (!supportsFeatureFlags(gitHubVersion.type)) { + logger.debug( + "Not running against github.com. Using default values for all features." + ); + return new OfflineFeatures(logger); + } else if (isCCR()) { + logger.debug( + "Querying feature flags is not currently supported in Copilot Code Review. Using offline data for all features." + ); + return new OfflineFeatures(logger); + } else { + return new Features(repositoryNwo, tempDir, logger); + } +} // src/start-proxy.ts var path2 = __toESM(require("path")); @@ -122071,7 +122116,7 @@ async function run(startedAt) { core11.saveState("proxy-log-file", proxyLogFilePath); const repositoryNwo = getRepositoryNwo(); const gitHubVersion = await getGitHubVersion(); - features = new Features( + features = initFeatures( gitHubVersion, repositoryNwo, getTemporaryDirectory(), diff --git a/lib/upload-sarif-action.js b/lib/upload-sarif-action.js index 7e786b0ab..f60fdc867 100644 --- a/lib/upload-sarif-action.js +++ b/lib/upload-sarif-action.js @@ -107048,34 +107048,47 @@ var featureConfig = { } }; var FEATURE_FLAGS_FILE_NAME = "cached-feature-flags.json"; -var Features = class { - constructor(gitHubVersion, repositoryNwo, tempDir, logger) { +var OfflineFeatures = class { + constructor(logger) { this.logger = logger; - this.gitHubFeatureFlags = new GitHubFeatureFlags( - gitHubVersion, - repositoryNwo, - path4.join(tempDir, FEATURE_FLAGS_FILE_NAME), - logger - ); } - gitHubFeatureFlags; - async getDefaultCliVersion(variant) { - return await this.gitHubFeatureFlags.getDefaultCliVersion(variant); + async getDefaultCliVersion(_variant) { + return { + cliVersion, + tagName: bundleVersion + }; } /** + * Gets the `FeatureConfig` for `feature`. + */ + getFeatureConfig(feature) { + return featureConfig[feature]; + } + /** + * Determines whether `feature` is enabled without consulting the GitHub API. * * @param feature The feature to check. * @param codeql An optional CodeQL object. If provided, and a `minimumVersion` is specified for the * feature, the version of the CodeQL CLI will be checked against the minimum version. * If the version is less than the minimum version, the feature will be considered - * disabled. If not provided, and a `minimumVersion` is specified for the feature, the + * disabled. If not provided, and a `minimumVersion` is specified for the feature, then * this function will throw. * @returns true if the feature is enabled, false otherwise. * * @throws if a `minimumVersion` is specified for the feature, and `codeql` is not provided. */ async getValue(feature, codeql) { - const config = featureConfig[feature]; + const offlineValue = await this.getOfflineValue(feature, codeql); + if (offlineValue !== void 0) { + return offlineValue; + } + return this.getDefaultValue(feature); + } + /** + * Determines whether `feature` is enabled using the CLI and environment variables. + */ + async getOfflineValue(feature, codeql) { + const config = this.getFeatureConfig(feature); if (!codeql && config.minimumVersion) { throw new Error( `Internal error: A minimum version is specified for feature ${feature}, but no instance of CodeQL was provided.` @@ -107125,13 +107138,11 @@ var Features = class { ); return true; } - const apiValue = await this.gitHubFeatureFlags.getValue(feature); - if (apiValue !== void 0) { - this.logger.debug( - `Feature ${feature} is ${apiValue ? "enabled" : "disabled"} via the GitHub API.` - ); - return apiValue; - } + return void 0; + } + /** Gets the default value of `feature`. */ + async getDefaultValue(feature) { + const config = this.getFeatureConfig(feature); const defaultValue = config.defaultValue; this.logger.debug( `Feature ${feature} is ${defaultValue ? "enabled" : "disabled"} due to its default value.` @@ -107139,9 +107150,51 @@ var Features = class { return defaultValue; } }; +var Features = class extends OfflineFeatures { + gitHubFeatureFlags; + constructor(repositoryNwo, tempDir, logger) { + super(logger); + this.gitHubFeatureFlags = new GitHubFeatureFlags( + repositoryNwo, + path4.join(tempDir, FEATURE_FLAGS_FILE_NAME), + logger + ); + } + async getDefaultCliVersion(variant) { + if (supportsFeatureFlags(variant)) { + return await this.gitHubFeatureFlags.getDefaultCliVersionFromFlags(); + } + return super.getDefaultCliVersion(variant); + } + /** + * + * @param feature The feature to check. + * @param codeql An optional CodeQL object. If provided, and a `minimumVersion` is specified for the + * feature, the version of the CodeQL CLI will be checked against the minimum version. + * If the version is less than the minimum version, the feature will be considered + * disabled. If not provided, and a `minimumVersion` is specified for the feature, then + * this function will throw. + * @returns true if the feature is enabled, false otherwise. + * + * @throws if a `minimumVersion` is specified for the feature, and `codeql` is not provided. + */ + async getValue(feature, codeql) { + const offlineValue = await this.getOfflineValue(feature, codeql); + if (offlineValue !== void 0) { + return offlineValue; + } + const apiValue = await this.gitHubFeatureFlags.getValue(feature); + if (apiValue !== void 0) { + this.logger.debug( + `Feature ${feature} is ${apiValue ? "enabled" : "disabled"} via the GitHub API.` + ); + return apiValue; + } + return this.getDefaultValue(feature); + } +}; var GitHubFeatureFlags = class { - constructor(gitHubVersion, repositoryNwo, featureFlagsFile, logger) { - this.gitHubVersion = gitHubVersion; + constructor(repositoryNwo, featureFlagsFile, logger) { this.repositoryNwo = repositoryNwo; this.featureFlagsFile = featureFlagsFile; this.logger = logger; @@ -107167,15 +107220,6 @@ var GitHubFeatureFlags = class { } return version; } - async getDefaultCliVersion(variant) { - if (supportsFeatureFlags(variant)) { - return await this.getDefaultCliVersionFromFlags(); - } - return { - cliVersion, - tagName: bundleVersion - }; - } async getDefaultCliVersionFromFlags() { const response = await this.getAllFeatures(); const enabledFeatureFlagCliVersions = Object.entries(response).map( @@ -107265,20 +107309,6 @@ var GitHubFeatureFlags = class { } } async loadApiResponse() { - if (!supportsFeatureFlags(this.gitHubVersion.type)) { - this.logger.debug( - "Not running against github.com. Using default values for all features." - ); - this.hasAccessedRemoteFeatureFlags = false; - return {}; - } - if (isCCR()) { - this.logger.debug( - "Feature flags are not supported in Copilot Code Review. Using default values for all features." - ); - this.hasAccessedRemoteFeatureFlags = false; - return {}; - } try { const featuresToRequest = Object.entries(featureConfig).filter( ([, config]) => !config.legacyApi @@ -107330,6 +107360,21 @@ var GitHubFeatureFlags = class { function supportsFeatureFlags(githubVariant) { return githubVariant === "GitHub.com" /* DOTCOM */ || githubVariant === "GitHub Enterprise Cloud with data residency" /* GHEC_DR */; } +function initFeatures(gitHubVersion, repositoryNwo, tempDir, logger) { + if (!supportsFeatureFlags(gitHubVersion.type)) { + logger.debug( + "Not running against github.com. Using default values for all features." + ); + return new OfflineFeatures(logger); + } else if (isCCR()) { + logger.debug( + "Querying feature flags is not currently supported in Copilot Code Review. Using offline data for all features." + ); + return new OfflineFeatures(logger); + } else { + return new Features(repositoryNwo, tempDir, logger); + } +} // src/status-report.ts var os = __toESM(require("os")); @@ -111387,7 +111432,7 @@ async function run(startedAt) { checkActionVersion(getActionVersion(), gitHubVersion); persistInputs(); const repositoryNwo = getRepositoryNwo(); - const features = new Features( + const features = initFeatures( gitHubVersion, repositoryNwo, getTemporaryDirectory(), diff --git a/src/actions-util.test.ts b/src/actions-util.test.ts index 71a409da6..ba5591a41 100644 --- a/src/actions-util.test.ts +++ b/src/actions-util.test.ts @@ -12,7 +12,7 @@ import { import { computeAutomationID } from "./api-client"; import { EnvVar } from "./environment"; import { getRunnerLogger } from "./logging"; -import { setupTests } from "./testing-utils"; +import { mockCCR, setupTests } from "./testing-utils"; import { initializeEnvironment } from "./util"; setupTests(test); @@ -258,8 +258,8 @@ test("isDynamicWorkflow() returns true if event name is `dynamic`", (t) => { }); test("isCCR() returns true when expected", (t) => { - process.env.GITHUB_EVENT_NAME = "dynamic"; - process.env[EnvVar.ANALYSIS_KEY] = "dynamic/copilot-pull-request-reviewer"; + mockCCR(); + t.assert(isCCR()); t.false(isDefaultSetup()); }); diff --git a/src/analyze-action.ts b/src/analyze-action.ts index 3cc1ad019..4093e3786 100644 --- a/src/analyze-action.ts +++ b/src/analyze-action.ts @@ -30,7 +30,7 @@ import { } from "./dependency-caching"; import { getDiffInformedAnalysisBranches } from "./diff-informed-analysis-utils"; import { EnvVar } from "./environment"; -import { Features } from "./feature-flags"; +import { initFeatures } from "./feature-flags"; import { KnownLanguage } from "./languages"; import { getActionsLogger, Logger } from "./logging"; import { cleanupAndUploadOverlayBaseDatabaseToCache } from "./overlay-database-utils"; @@ -293,7 +293,7 @@ async function run(startedAt: Date) { util.checkActionVersion(actionsUtil.getActionVersion(), gitHubVersion); - const features = new Features( + const features = initFeatures( gitHubVersion, repositoryNwo, actionsUtil.getTemporaryDirectory(), diff --git a/src/autobuild.ts b/src/autobuild.ts index ce3d45cc4..46935bba6 100644 --- a/src/autobuild.ts +++ b/src/autobuild.ts @@ -6,7 +6,7 @@ import { CodeQL, getCodeQL } from "./codeql"; import * as configUtils from "./config-utils"; import { DocUrl } from "./doc-url"; import { EnvVar } from "./environment"; -import { Feature, featureConfig, Features } from "./feature-flags"; +import { Feature, featureConfig, initFeatures } from "./feature-flags"; import { KnownLanguage, Language } from "./languages"; import { Logger } from "./logging"; import { getRepositoryNwo } from "./repository"; @@ -117,7 +117,7 @@ export async function setupCppAutobuild(codeql: CodeQL, logger: Logger) { const featureName = "C++ automatic installation of dependencies"; const gitHubVersion = await getGitHubVersion(); const repositoryNwo = getRepositoryNwo(); - const features = new Features( + const features = initFeatures( gitHubVersion, repositoryNwo, getTemporaryDirectory(), diff --git a/src/diff-informed-analysis-utils.test.ts b/src/diff-informed-analysis-utils.test.ts index eeb06cd1b..2d98a5f63 100644 --- a/src/diff-informed-analysis-utils.test.ts +++ b/src/diff-informed-analysis-utils.test.ts @@ -8,7 +8,7 @@ import { shouldPerformDiffInformedAnalysis, exportedForTesting, } from "./diff-informed-analysis-utils"; -import { Feature, Features } from "./feature-flags"; +import { Feature, initFeatures } from "./feature-flags"; import { getRunnerLogger } from "./logging"; import { parseRepositoryNwo } from "./repository"; import { @@ -63,7 +63,7 @@ const testShouldPerformDiffInformedAnalysis = test.macro({ delete process.env.CODEQL_ACTION_DIFF_INFORMED_QUERIES; } - const features = new Features( + const features = initFeatures( testCase.gitHubVersion, parseRepositoryNwo("github/example"), tmpDir, diff --git a/src/feature-flags.test.ts b/src/feature-flags.test.ts index 6632cf252..96e019347 100644 --- a/src/feature-flags.test.ts +++ b/src/feature-flags.test.ts @@ -1,33 +1,32 @@ import * as fs from "fs"; import * as path from "path"; -import test, { ExecutionContext } from "ava"; +import test from "ava"; import * as defaults from "./defaults.json"; -import { EnvVar } from "./environment"; import { Feature, featureConfig, - FeatureEnablement, - Features, FEATURE_FLAGS_FILE_NAME, FeatureConfig, - FeatureWithoutCLI, } from "./feature-flags"; -import { getRunnerLogger } from "./logging"; -import { parseRepositoryNwo } from "./repository"; import { + setUpFeatureFlagTests, + getFeatureIncludingCodeQlIfRequired, + assertAllFeaturesUndefinedInApi, + assertAllFeaturesHaveDefaultValues, +} from "./feature-flags/testing-util"; +import { + checkExpectedLogMessages, getRecordingLogger, initializeFeatures, LoggedMessage, + mockCCR, mockCodeQLVersion, mockFeatureFlagApiEndpoint, - setupActionsVars, setupTests, stubFeatureFlagApiEndpoint, } from "./testing-utils"; -import { ToolsFeature } from "./tools-features"; -import * as util from "./util"; import { GitHubVariant, initializeEnvironment, withTmpDir } from "./util"; setupTests(test); @@ -36,11 +35,9 @@ test.beforeEach(() => { initializeEnvironment("1.2.3"); }); -const testRepositoryNwo = parseRepositoryNwo("github/example"); - test(`All features use default values if running against GHES`, async (t) => { await withTmpDir(async (tmpDir) => { - const loggedMessages: LoggedMessage[] = []; + const loggedMessages = []; const features = setUpFeatureFlagTests( tmpDir, getRecordingLogger(loggedMessages), @@ -48,30 +45,9 @@ test(`All features use default values if running against GHES`, async (t) => { ); await assertAllFeaturesHaveDefaultValues(t, features); - assertLoggedMessage( - t, - loggedMessages, + checkExpectedLogMessages(t, loggedMessages, [ "Not running against github.com. Using default values for all features.", - ); - }); -}); - -test(`All features use default values if running in CCR`, async (t) => { - await withTmpDir(async (tmpDir) => { - const loggedMessages: LoggedMessage[] = []; - const features = setUpFeatureFlagTests( - tmpDir, - getRecordingLogger(loggedMessages), - ); - - process.env[EnvVar.ANALYSIS_KEY] = "dynamic/copilot-pull-request-reviewer"; - - await assertAllFeaturesHaveDefaultValues(t, features); - assertLoggedMessage( - t, - loggedMessages, - "Feature flags are not supported in Copilot Code Review. Using default values for all features.", - ); + ]); }); }); @@ -553,79 +529,18 @@ test("non-legacy feature flags should not start with codeql_action_", async (t) } }); -async function assertAllFeaturesHaveDefaultValues( - t: ExecutionContext, - features: FeatureEnablement, -) { - for (const feature of Object.values(Feature)) { - t.deepEqual( - await getFeatureIncludingCodeQlIfRequired(features, feature), - featureConfig[feature].defaultValue, - ); - } -} +test("initFeatures returns a `Features` instance by default", async (t) => { + await withTmpDir(async (tmpDir) => { + const features = setUpFeatureFlagTests(tmpDir); + t.is("Features", features.constructor.name); + }); +}); -function assertLoggedMessage( - t: ExecutionContext, - loggedMessages: LoggedMessage[], - expectedMessage: string, -) { - t.assert( - loggedMessages.find( - (v: LoggedMessage) => v.type === "debug" && v.message === expectedMessage, - ) !== undefined, - ); -} +test("initFeatures returns an `OfflineFeatures` instance in CCR", async (t) => { + await withTmpDir(async (tmpDir) => { + mockCCR(); -function assertAllFeaturesUndefinedInApi( - t: ExecutionContext, - loggedMessages: LoggedMessage[], -) { - for (const feature of Object.keys(featureConfig)) { - t.assert( - loggedMessages.find( - (v) => - v.type === "debug" && - (v.message as string).includes(feature) && - (v.message as string).includes("undefined in API response"), - ) !== undefined, - ); - } -} - -function setUpFeatureFlagTests( - tmpDir: string, - logger = getRunnerLogger(true), - gitHubVersion = { type: GitHubVariant.DOTCOM } as util.GitHubVersion, -): FeatureEnablement { - setupActionsVars(tmpDir, tmpDir); - - return new Features(gitHubVersion, testRepositoryNwo, tmpDir, logger); -} - -/** - * Returns an argument to pass to `getValue` that if required includes a CodeQL object meeting the - * minimum version or tool feature requirements specified by the feature. - */ -function getFeatureIncludingCodeQlIfRequired( - features: FeatureEnablement, - feature: Feature, -) { - const config = featureConfig[ - feature - ] satisfies FeatureConfig as FeatureConfig; - if ( - config.minimumVersion === undefined && - config.toolsFeature === undefined - ) { - return features.getValue(feature as FeatureWithoutCLI); - } - - return features.getValue( - feature, - mockCodeQLVersion( - "9.9.9", - Object.fromEntries(Object.values(ToolsFeature).map((v) => [v, true])), - ), - ); -} + const features = setUpFeatureFlagTests(tmpDir); + t.is("OfflineFeatures", features.constructor.name); + }); +}); diff --git a/src/feature-flags.ts b/src/feature-flags.ts index 84182bde0..e05c1e2af 100644 --- a/src/feature-flags.ts +++ b/src/feature-flags.ts @@ -373,51 +373,60 @@ type GitHubFeatureFlagsApiResponse = Partial>; export const FEATURE_FLAGS_FILE_NAME = "cached-feature-flags.json"; /** - * Determines the enablement status of a number of features. - * If feature enablement is not able to be determined locally, a request to the - * GitHub API is made to determine the enablement status. + * Determines the enablement status of a number of features locally without + * consulting the GitHub API. */ -export class Features implements FeatureEnablement { - private gitHubFeatureFlags: GitHubFeatureFlags; - - constructor( - gitHubVersion: util.GitHubVersion, - repositoryNwo: RepositoryNwo, - tempDir: string, - private readonly logger: Logger, - ) { - this.gitHubFeatureFlags = new GitHubFeatureFlags( - gitHubVersion, - repositoryNwo, - path.join(tempDir, FEATURE_FLAGS_FILE_NAME), - logger, - ); - } +class OfflineFeatures implements FeatureEnablement { + constructor(protected readonly logger: Logger) {} async getDefaultCliVersion( - variant: util.GitHubVariant, + _variant: util.GitHubVariant, ): Promise { - return await this.gitHubFeatureFlags.getDefaultCliVersion(variant); + return { + cliVersion: defaults.cliVersion, + tagName: defaults.bundleVersion, + }; } /** + * Gets the `FeatureConfig` for `feature`. + */ + getFeatureConfig(feature: Feature): FeatureConfig { + // Narrow the type to FeatureConfig to avoid type errors. To avoid unsafe use of `as`, we + // check that the required properties exist using `satisfies`. + return featureConfig[feature] satisfies FeatureConfig as FeatureConfig; + } + + /** + * Determines whether `feature` is enabled without consulting the GitHub API. * * @param feature The feature to check. * @param codeql An optional CodeQL object. If provided, and a `minimumVersion` is specified for the * feature, the version of the CodeQL CLI will be checked against the minimum version. * If the version is less than the minimum version, the feature will be considered - * disabled. If not provided, and a `minimumVersion` is specified for the feature, the + * disabled. If not provided, and a `minimumVersion` is specified for the feature, then * this function will throw. * @returns true if the feature is enabled, false otherwise. * * @throws if a `minimumVersion` is specified for the feature, and `codeql` is not provided. */ async getValue(feature: Feature, codeql?: CodeQL): Promise { - // Narrow the type to FeatureConfig to avoid type errors. To avoid unsafe use of `as`, we - // check that the required properties exist using `satisfies`. - const config = featureConfig[ - feature - ] satisfies FeatureConfig as FeatureConfig; + const offlineValue = await this.getOfflineValue(feature, codeql); + if (offlineValue !== undefined) { + return offlineValue; + } + + return this.getDefaultValue(feature); + } + + /** + * Determines whether `feature` is enabled using the CLI and environment variables. + */ + protected async getOfflineValue( + feature: Feature, + codeql?: CodeQL, + ): Promise { + const config = this.getFeatureConfig(feature); if (!codeql && config.minimumVersion) { throw new Error( @@ -483,6 +492,68 @@ export class Features implements FeatureEnablement { return true; } + return undefined; + } + + /** Gets the default value of `feature`. */ + protected async getDefaultValue(feature: Feature): Promise { + const config = this.getFeatureConfig(feature); + const defaultValue = config.defaultValue; + this.logger.debug( + `Feature ${feature} is ${ + defaultValue ? "enabled" : "disabled" + } due to its default value.`, + ); + return defaultValue; + } +} + +/** + * Determines the enablement status of a number of features. + * If feature enablement is not able to be determined locally, a request to the + * GitHub API is made to determine the enablement status. + */ +class Features extends OfflineFeatures { + private gitHubFeatureFlags: GitHubFeatureFlags; + + constructor(repositoryNwo: RepositoryNwo, tempDir: string, logger: Logger) { + super(logger); + + this.gitHubFeatureFlags = new GitHubFeatureFlags( + repositoryNwo, + path.join(tempDir, FEATURE_FLAGS_FILE_NAME), + logger, + ); + } + + async getDefaultCliVersion( + variant: util.GitHubVariant, + ): Promise { + if (supportsFeatureFlags(variant)) { + return await this.gitHubFeatureFlags.getDefaultCliVersionFromFlags(); + } + return super.getDefaultCliVersion(variant); + } + + /** + * + * @param feature The feature to check. + * @param codeql An optional CodeQL object. If provided, and a `minimumVersion` is specified for the + * feature, the version of the CodeQL CLI will be checked against the minimum version. + * If the version is less than the minimum version, the feature will be considered + * disabled. If not provided, and a `minimumVersion` is specified for the feature, then + * this function will throw. + * @returns true if the feature is enabled, false otherwise. + * + * @throws if a `minimumVersion` is specified for the feature, and `codeql` is not provided. + */ + async getValue(feature: Feature, codeql?: CodeQL): Promise { + // Check whether the feature is enabled locally. + const offlineValue = await this.getOfflineValue(feature, codeql); + if (offlineValue !== undefined) { + return offlineValue; + } + // Ask the GitHub API if the feature is enabled. const apiValue = await this.gitHubFeatureFlags.getValue(feature); if (apiValue !== undefined) { @@ -494,13 +565,8 @@ export class Features implements FeatureEnablement { return apiValue; } - const defaultValue = config.defaultValue; - this.logger.debug( - `Feature ${feature} is ${ - defaultValue ? "enabled" : "disabled" - } due to its default value.`, - ); - return defaultValue; + // Return the default value. + return this.getDefaultValue(feature); } } @@ -512,7 +578,6 @@ class GitHubFeatureFlags { private hasAccessedRemoteFeatureFlags: boolean; constructor( - private readonly gitHubVersion: util.GitHubVersion, private readonly repositoryNwo: RepositoryNwo, private readonly featureFlagsFile: string, private readonly logger: Logger, @@ -543,18 +608,6 @@ class GitHubFeatureFlags { return version; } - async getDefaultCliVersion( - variant: util.GitHubVariant, - ): Promise { - if (supportsFeatureFlags(variant)) { - return await this.getDefaultCliVersionFromFlags(); - } - return { - cliVersion: defaults.cliVersion, - tagName: defaults.bundleVersion, - }; - } - async getDefaultCliVersionFromFlags(): Promise { const response = await this.getAllFeatures(); @@ -680,21 +733,6 @@ class GitHubFeatureFlags { } private async loadApiResponse(): Promise { - // Do nothing when not running against github.com - if (!supportsFeatureFlags(this.gitHubVersion.type)) { - this.logger.debug( - "Not running against github.com. Using default values for all features.", - ); - this.hasAccessedRemoteFeatureFlags = false; - return {}; - } - if (isCCR()) { - this.logger.debug( - "Feature flags are not supported in Copilot Code Review. Using default values for all features.", - ); - this.hasAccessedRemoteFeatureFlags = false; - return {}; - } try { const featuresToRequest = Object.entries(featureConfig) .filter( @@ -764,3 +802,28 @@ function supportsFeatureFlags(githubVariant: util.GitHubVariant): boolean { githubVariant === util.GitHubVariant.GHEC_DR ); } + +/** + * Initialises an instance of a `FeatureEnablement` implementation. The implementation used + * is determined by the environment we are running in. + */ +export function initFeatures( + gitHubVersion: util.GitHubVersion, + repositoryNwo: RepositoryNwo, + tempDir: string, + logger: Logger, +): FeatureEnablement { + if (!supportsFeatureFlags(gitHubVersion.type)) { + logger.debug( + "Not running against github.com. Using default values for all features.", + ); + return new OfflineFeatures(logger); + } else if (isCCR()) { + logger.debug( + "Querying feature flags is not currently supported in Copilot Code Review. Using offline data for all features.", + ); + return new OfflineFeatures(logger); + } else { + return new Features(repositoryNwo, tempDir, logger); + } +} diff --git a/src/feature-flags/offline-features.test.ts b/src/feature-flags/offline-features.test.ts new file mode 100644 index 000000000..433d80644 --- /dev/null +++ b/src/feature-flags/offline-features.test.ts @@ -0,0 +1,42 @@ +import test from "ava"; +import * as sinon from "sinon"; + +import * as apiClient from "../api-client"; +import { + checkExpectedLogMessages, + getRecordingLogger, + LoggedMessage, + mockCCR, + setupTests, +} from "../testing-utils"; +import { initializeEnvironment, withTmpDir } from "../util"; + +import { + assertAllFeaturesHaveDefaultValues, + setUpFeatureFlagTests, +} from "./testing-util"; + +setupTests(test); + +test.beforeEach(() => { + initializeEnvironment("1.2.3"); + mockCCR(); +}); + +test("OfflineFeatures makes no API requests", async (t) => { + await withTmpDir(async (tmpDir) => { + const loggedMessages: LoggedMessage[] = []; + const logger = getRecordingLogger(loggedMessages); + const features = setUpFeatureFlagTests(tmpDir, logger); + t.is("OfflineFeatures", features.constructor.name); + + sinon + .stub(apiClient, "getApiClient") + .throws(new Error("Should not have called getApiClient")); + + await assertAllFeaturesHaveDefaultValues(t, features); + checkExpectedLogMessages(t, loggedMessages, [ + "Querying feature flags is not currently supported in Copilot Code Review. Using offline data for all features.", + ]); + }); +}); diff --git a/src/feature-flags/testing-util.ts b/src/feature-flags/testing-util.ts new file mode 100644 index 000000000..202f2c97b --- /dev/null +++ b/src/feature-flags/testing-util.ts @@ -0,0 +1,87 @@ +import { type ExecutionContext } from "ava"; + +import { + Feature, + featureConfig, + FeatureConfig, + FeatureEnablement, + FeatureWithoutCLI, + initFeatures, +} from "../feature-flags"; +import { getRunnerLogger } from "../logging"; +import { parseRepositoryNwo } from "../repository"; +import { + LoggedMessage, + mockCodeQLVersion, + setupActionsVars, +} from "../testing-utils"; +import { ToolsFeature } from "../tools-features"; +import { GitHubVariant } from "../util"; +import * as util from "../util"; + +const testRepositoryNwo = parseRepositoryNwo("github/example"); + +export async function assertAllFeaturesHaveDefaultValues( + t: ExecutionContext, + features: FeatureEnablement, +) { + for (const feature of Object.values(Feature)) { + t.deepEqual( + await getFeatureIncludingCodeQlIfRequired(features, feature), + featureConfig[feature].defaultValue, + ); + } +} + +export function assertAllFeaturesUndefinedInApi( + t: ExecutionContext, + loggedMessages: LoggedMessage[], +) { + for (const feature of Object.keys(featureConfig)) { + t.assert( + loggedMessages.find( + (v) => + v.type === "debug" && + (v.message as string).includes(feature) && + (v.message as string).includes("undefined in API response"), + ) !== undefined, + ); + } +} + +export function setUpFeatureFlagTests( + tmpDir: string, + logger = getRunnerLogger(true), + gitHubVersion = { type: GitHubVariant.DOTCOM } as util.GitHubVersion, +): FeatureEnablement { + setupActionsVars(tmpDir, tmpDir); + + return initFeatures(gitHubVersion, testRepositoryNwo, tmpDir, logger); +} + +/** + * Returns an argument to pass to `getValue` that if required includes a CodeQL object meeting the + * minimum version or tool feature requirements specified by the feature. + */ +export function getFeatureIncludingCodeQlIfRequired( + features: FeatureEnablement, + feature: Feature, +) { + const config = featureConfig[ + feature + ] satisfies FeatureConfig as FeatureConfig; + if ( + config.minimumVersion === undefined && + config.toolsFeature === undefined + ) { + return features.getValue(feature as FeatureWithoutCLI); + } + + return features.getValue( + feature, + mockCodeQLVersion( + "9.9.9", + Object.fromEntries(Object.values(ToolsFeature).map((v) => [v, true])), + ), + ); +} diff --git a/src/init-action-post.ts b/src/init-action-post.ts index cfae09693..d5aab32f3 100644 --- a/src/init-action-post.ts +++ b/src/init-action-post.ts @@ -21,7 +21,7 @@ import { getDependencyCacheUsage, } from "./dependency-caching"; import { EnvVar } from "./environment"; -import { Features } from "./feature-flags"; +import { initFeatures } from "./feature-flags"; import * as gitUtils from "./git-utils"; import * as initActionPostHelper from "./init-action-post-helper"; import { getActionsLogger } from "./logging"; @@ -62,7 +62,7 @@ async function run(startedAt: Date) { checkGitHubVersionInRange(gitHubVersion, logger); const repositoryNwo = getRepositoryNwo(); - const features = new Features( + const features = initFeatures( gitHubVersion, repositoryNwo, getTemporaryDirectory(), diff --git a/src/init-action.ts b/src/init-action.ts index 3df778fff..577c0f450 100644 --- a/src/init-action.ts +++ b/src/init-action.ts @@ -38,7 +38,7 @@ import { makeTelemetryDiagnostic, } from "./diagnostics"; import { EnvVar } from "./environment"; -import { Feature, FeatureEnablement, Features } from "./feature-flags"; +import { Feature, FeatureEnablement, initFeatures } from "./feature-flags"; import { loadPropertiesFromApi, RepositoryProperties, @@ -211,7 +211,7 @@ async function run(startedAt: Date) { let config: configUtils.Config | undefined; let configFile: string | undefined; let codeql: CodeQL; - let features: Features; + let features: FeatureEnablement; let sourceRoot: string; let toolsDownloadStatusReport: ToolsDownloadStatusReport | undefined; let toolsFeatureFlagsValid: boolean | undefined; @@ -238,7 +238,7 @@ async function run(startedAt: Date) { const repositoryNwo = getRepositoryNwo(); - features = new Features( + features = initFeatures( gitHubVersion, repositoryNwo, getTemporaryDirectory(), diff --git a/src/setup-codeql-action.ts b/src/setup-codeql-action.ts index 31c898667..bd504f3fd 100644 --- a/src/setup-codeql-action.ts +++ b/src/setup-codeql-action.ts @@ -10,7 +10,7 @@ import { import { getGitHubVersion } from "./api-client"; import { CodeQL } from "./codeql"; import { EnvVar } from "./environment"; -import { Features } from "./feature-flags"; +import { initFeatures } from "./feature-flags"; import { initCodeQL } from "./init"; import { getActionsLogger, Logger } from "./logging"; import { getRepositoryNwo } from "./repository"; @@ -114,7 +114,7 @@ async function run(startedAt: Date): Promise { const repositoryNwo = getRepositoryNwo(); - const features = new Features( + const features = initFeatures( gitHubVersion, repositoryNwo, getTemporaryDirectory(), diff --git a/src/start-proxy-action.ts b/src/start-proxy-action.ts index 3ee44a409..df6c9a332 100644 --- a/src/start-proxy-action.ts +++ b/src/start-proxy-action.ts @@ -5,7 +5,7 @@ import * as core from "@actions/core"; import * as actionsUtil from "./actions-util"; import { getGitHubVersion } from "./api-client"; -import { Feature, Features } from "./feature-flags"; +import { Feature, FeatureEnablement, initFeatures } from "./feature-flags"; import { KnownLanguage } from "./languages"; import { getActionsLogger, Logger } from "./logging"; import { getRepositoryNwo } from "./repository"; @@ -32,7 +32,7 @@ async function run(startedAt: Date) { // possible, and only use safe functions outside. const logger = getActionsLogger(); - let features: Features | undefined; + let features: FeatureEnablement | undefined; let language: KnownLanguage | undefined; try { @@ -47,7 +47,7 @@ async function run(startedAt: Date) { // Initialise FFs. const repositoryNwo = getRepositoryNwo(); const gitHubVersion = await getGitHubVersion(); - features = new Features( + features = initFeatures( gitHubVersion, repositoryNwo, actionsUtil.getTemporaryDirectory(), diff --git a/src/testing-utils.ts b/src/testing-utils.ts index 8765738e4..752a23988 100644 --- a/src/testing-utils.ts +++ b/src/testing-utils.ts @@ -14,6 +14,7 @@ import { CachingKind } from "./caching-utils"; import * as codeql from "./codeql"; import { Config } from "./config-utils"; import * as defaults from "./defaults.json"; +import { EnvVar } from "./environment"; import { CodeQLDefaultVersionInfo, Feature, @@ -504,3 +505,9 @@ export function makeTestToken(length: number = 36) { "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; return chars.repeat(Math.ceil(length / chars.length)).slice(0, length); } + +/** Sets the environment variables needed for isCCR() to be `true`. */ +export function mockCCR() { + process.env.GITHUB_EVENT_NAME = "dynamic"; + process.env[EnvVar.ANALYSIS_KEY] = "dynamic/copilot-pull-request-reviewer"; +} diff --git a/src/upload-sarif-action.ts b/src/upload-sarif-action.ts index 5273909ba..cec41b276 100644 --- a/src/upload-sarif-action.ts +++ b/src/upload-sarif-action.ts @@ -4,7 +4,7 @@ import * as actionsUtil from "./actions-util"; import { getActionVersion, getTemporaryDirectory } from "./actions-util"; import * as analyses from "./analyses"; import { getGitHubVersion } from "./api-client"; -import { Features } from "./feature-flags"; +import { initFeatures } from "./feature-flags"; import { Logger, getActionsLogger } from "./logging"; import { getRepositoryNwo } from "./repository"; import { @@ -70,7 +70,7 @@ async function run(startedAt: Date) { actionsUtil.persistInputs(); const repositoryNwo = getRepositoryNwo(); - const features = new Features( + const features = initFeatures( gitHubVersion, repositoryNwo, getTemporaryDirectory(),