diff --git a/lib/analyze-action-post.js b/lib/analyze-action-post.js index 87c266e30a..beab5657dc 100644 --- a/lib/analyze-action-post.js +++ b/lib/analyze-action-post.js @@ -124313,7 +124313,7 @@ var core8 = __toESM(require_core()); var toolrunner2 = __toESM(require_toolrunner()); var io3 = __toESM(require_io()); var semver3 = __toESM(require_semver2()); -var runGitCommand = async function(workingDirectory, args, customErrorMessage) { +var runGitCommand = async function(workingDirectory, args, customErrorMessage, options) { let stdout = ""; let stderr = ""; core8.debug(`Running git command: git ${args.join(" ")}`); @@ -124328,7 +124328,8 @@ var runGitCommand = async function(workingDirectory, args, customErrorMessage) { stderr += data.toString(); } }, - cwd: workingDirectory + cwd: workingDirectory, + ...options }).exec(); return stdout; } catch (error3) { @@ -124596,6 +124597,11 @@ var featureConfig = { legacyApi: true, minimumVersion: void 0 }, + ["ignore_generated_files" /* IgnoreGeneratedFiles */]: { + defaultValue: false, + envVar: "CODEQL_ACTION_IGNORE_GENERATED_FILES", + minimumVersion: void 0 + }, ["overlay_analysis" /* OverlayAnalysis */]: { defaultValue: false, envVar: "CODEQL_ACTION_OVERLAY_ANALYSIS", diff --git a/lib/analyze-action.js b/lib/analyze-action.js index b7ce752948..1ac83ed0a6 100644 --- a/lib/analyze-action.js +++ b/lib/analyze-action.js @@ -89968,7 +89968,11 @@ function isDynamicWorkflow() { return getWorkflowEventName() === "dynamic"; } function isDefaultSetup() { - return isDynamicWorkflow(); + return isDynamicWorkflow() && !isCCR(); +} +var CCR_KEY_PREFIX = "dynamic/copilot-pull-request-reviewer"; +function isCCR() { + return process.env["CODEQL_ACTION_ANALYSIS_KEY" /* ANALYSIS_KEY */]?.startsWith(CCR_KEY_PREFIX) || false; } function prettyPrintInvocation(cmd, args) { return [cmd, ...args].map((x) => x.includes(" ") ? `'${x}'` : x).join(" "); @@ -90236,15 +90240,14 @@ async function getWorkflowRelativePath() { return workflowResponse.data.path; } async function getAnalysisKey() { - const analysisKeyEnvVar = "CODEQL_ACTION_ANALYSIS_KEY"; - let analysisKey = process.env[analysisKeyEnvVar]; + let analysisKey = process.env["CODEQL_ACTION_ANALYSIS_KEY" /* ANALYSIS_KEY */]; if (analysisKey !== void 0) { return analysisKey; } const workflowPath = await getWorkflowRelativePath(); const jobName = getRequiredEnvParam("GITHUB_JOB"); analysisKey = `${workflowPath}:${jobName}`; - core5.exportVariable(analysisKeyEnvVar, analysisKey); + core5.exportVariable("CODEQL_ACTION_ANALYSIS_KEY" /* ANALYSIS_KEY */, analysisKey); return analysisKey; } async function getAutomationID() { @@ -90705,7 +90708,7 @@ var core8 = __toESM(require_core()); var toolrunner2 = __toESM(require_toolrunner()); var io3 = __toESM(require_io()); var semver3 = __toESM(require_semver2()); -var runGitCommand = async function(workingDirectory, args, customErrorMessage) { +var runGitCommand = async function(workingDirectory, args, customErrorMessage, options) { let stdout = ""; let stderr = ""; core8.debug(`Running git command: git ${args.join(" ")}`); @@ -90720,7 +90723,8 @@ var runGitCommand = async function(workingDirectory, args, customErrorMessage) { stderr += data.toString(); } }, - cwd: workingDirectory + cwd: workingDirectory, + ...options }).exec(); return stdout; } catch (error3) { @@ -91156,6 +91160,11 @@ var featureConfig = { legacyApi: true, minimumVersion: void 0 }, + ["ignore_generated_files" /* IgnoreGeneratedFiles */]: { + defaultValue: false, + envVar: "CODEQL_ACTION_IGNORE_GENERATED_FILES", + minimumVersion: void 0 + }, ["overlay_analysis" /* OverlayAnalysis */]: { defaultValue: false, envVar: "CODEQL_ACTION_OVERLAY_ANALYSIS", diff --git a/lib/autobuild-action.js b/lib/autobuild-action.js index 2b78aab644..5445cc0f96 100644 --- a/lib/autobuild-action.js +++ b/lib/autobuild-action.js @@ -86893,15 +86893,14 @@ async function getWorkflowRelativePath() { return workflowResponse.data.path; } async function getAnalysisKey() { - const analysisKeyEnvVar = "CODEQL_ACTION_ANALYSIS_KEY"; - let analysisKey = process.env[analysisKeyEnvVar]; + let analysisKey = process.env["CODEQL_ACTION_ANALYSIS_KEY" /* ANALYSIS_KEY */]; if (analysisKey !== void 0) { return analysisKey; } const workflowPath = await getWorkflowRelativePath(); const jobName = getRequiredEnvParam("GITHUB_JOB"); analysisKey = `${workflowPath}:${jobName}`; - core5.exportVariable(analysisKeyEnvVar, analysisKey); + core5.exportVariable("CODEQL_ACTION_ANALYSIS_KEY" /* ANALYSIS_KEY */, analysisKey); return analysisKey; } @@ -87212,7 +87211,7 @@ var core8 = __toESM(require_core()); var toolrunner2 = __toESM(require_toolrunner()); var io3 = __toESM(require_io()); var semver3 = __toESM(require_semver2()); -var runGitCommand = async function(workingDirectory, args, customErrorMessage) { +var runGitCommand = async function(workingDirectory, args, customErrorMessage, options) { let stdout = ""; let stderr = ""; core8.debug(`Running git command: git ${args.join(" ")}`); @@ -87227,7 +87226,8 @@ var runGitCommand = async function(workingDirectory, args, customErrorMessage) { stderr += data.toString(); } }, - cwd: workingDirectory + cwd: workingDirectory, + ...options }).exec(); return stdout; } catch (error3) { @@ -87493,6 +87493,11 @@ var featureConfig = { legacyApi: true, minimumVersion: void 0 }, + ["ignore_generated_files" /* IgnoreGeneratedFiles */]: { + defaultValue: false, + envVar: "CODEQL_ACTION_IGNORE_GENERATED_FILES", + minimumVersion: void 0 + }, ["overlay_analysis" /* OverlayAnalysis */]: { defaultValue: false, envVar: "CODEQL_ACTION_OVERLAY_ANALYSIS", diff --git a/lib/init-action-post.js b/lib/init-action-post.js index c068de7a02..4b0e498104 100644 --- a/lib/init-action-post.js +++ b/lib/init-action-post.js @@ -127046,7 +127046,11 @@ function isDynamicWorkflow() { return getWorkflowEventName() === "dynamic"; } function isDefaultSetup() { - return isDynamicWorkflow(); + return isDynamicWorkflow() && !isCCR(); +} +var CCR_KEY_PREFIX = "dynamic/copilot-pull-request-reviewer"; +function isCCR() { + return process.env["CODEQL_ACTION_ANALYSIS_KEY" /* ANALYSIS_KEY */]?.startsWith(CCR_KEY_PREFIX) || false; } function prettyPrintInvocation(cmd, args) { return [cmd, ...args].map((x) => x.includes(" ") ? `'${x}'` : x).join(" "); @@ -127248,15 +127252,14 @@ async function getWorkflowRelativePath() { return workflowResponse.data.path; } async function getAnalysisKey() { - const analysisKeyEnvVar = "CODEQL_ACTION_ANALYSIS_KEY"; - let analysisKey = process.env[analysisKeyEnvVar]; + let analysisKey = process.env["CODEQL_ACTION_ANALYSIS_KEY" /* ANALYSIS_KEY */]; if (analysisKey !== void 0) { return analysisKey; } const workflowPath = await getWorkflowRelativePath(); const jobName = getRequiredEnvParam("GITHUB_JOB"); analysisKey = `${workflowPath}:${jobName}`; - core5.exportVariable(analysisKeyEnvVar, analysisKey); + core5.exportVariable("CODEQL_ACTION_ANALYSIS_KEY" /* ANALYSIS_KEY */, analysisKey); return analysisKey; } function computeAutomationID(analysis_key, environment) { @@ -127668,7 +127671,7 @@ var core8 = __toESM(require_core()); var toolrunner2 = __toESM(require_toolrunner()); var io3 = __toESM(require_io()); var semver3 = __toESM(require_semver2()); -var runGitCommand = async function(workingDirectory, args, customErrorMessage) { +var runGitCommand = async function(workingDirectory, args, customErrorMessage, options) { let stdout = ""; let stderr = ""; core8.debug(`Running git command: git ${args.join(" ")}`); @@ -127683,7 +127686,8 @@ var runGitCommand = async function(workingDirectory, args, customErrorMessage) { stderr += data.toString(); } }, - cwd: workingDirectory + cwd: workingDirectory, + ...options }).exec(); return stdout; } catch (error3) { @@ -127988,6 +127992,11 @@ var featureConfig = { legacyApi: true, minimumVersion: void 0 }, + ["ignore_generated_files" /* IgnoreGeneratedFiles */]: { + defaultValue: false, + envVar: "CODEQL_ACTION_IGNORE_GENERATED_FILES", + minimumVersion: void 0 + }, ["overlay_analysis" /* OverlayAnalysis */]: { defaultValue: false, envVar: "CODEQL_ACTION_OVERLAY_ANALYSIS", diff --git a/lib/init-action.js b/lib/init-action.js index b53008ecc1..37656350c6 100644 --- a/lib/init-action.js +++ b/lib/init-action.js @@ -108,11 +108,11 @@ var require_command = __commonJS({ Object.defineProperty(exports2, "__esModule", { value: true }); exports2.issueCommand = issueCommand; exports2.issue = issue; - var os5 = __importStar2(require("os")); + var os6 = __importStar2(require("os")); var utils_1 = require_utils(); function issueCommand(command, properties, message) { const cmd = new Command(command, properties, message); - process.stdout.write(cmd.toString() + os5.EOL); + process.stdout.write(cmd.toString() + os6.EOL); } function issue(name, message = "") { issueCommand(name, {}, message); @@ -205,7 +205,7 @@ var require_file_command = __commonJS({ exports2.prepareKeyValueMessage = prepareKeyValueMessage; var crypto3 = __importStar2(require("crypto")); var fs15 = __importStar2(require("fs")); - var os5 = __importStar2(require("os")); + var os6 = __importStar2(require("os")); var utils_1 = require_utils(); function issueFileCommand(command, message) { const filePath = process.env[`GITHUB_${command}`]; @@ -215,7 +215,7 @@ var require_file_command = __commonJS({ if (!fs15.existsSync(filePath)) { throw new Error(`Missing file at path: ${filePath}`); } - fs15.appendFileSync(filePath, `${(0, utils_1.toCommandValue)(message)}${os5.EOL}`, { + fs15.appendFileSync(filePath, `${(0, utils_1.toCommandValue)(message)}${os6.EOL}`, { encoding: "utf8" }); } @@ -228,7 +228,7 @@ var require_file_command = __commonJS({ if (convertedValue.includes(delimiter)) { throw new Error(`Unexpected input: value should not contain the delimiter "${delimiter}"`); } - return `${key}<<${delimiter}${os5.EOL}${convertedValue}${os5.EOL}${delimiter}`; + return `${key}<<${delimiter}${os6.EOL}${convertedValue}${os6.EOL}${delimiter}`; } } }); @@ -19082,7 +19082,7 @@ var require_toolrunner = __commonJS({ Object.defineProperty(exports2, "__esModule", { value: true }); exports2.ToolRunner = void 0; exports2.argStringToArray = argStringToArray; - var os5 = __importStar2(require("os")); + var os6 = __importStar2(require("os")); var events = __importStar2(require("events")); var child = __importStar2(require("child_process")); var path16 = __importStar2(require("path")); @@ -19137,12 +19137,12 @@ var require_toolrunner = __commonJS({ _processLineBuffer(data, strBuffer, onLine) { try { let s = strBuffer + data.toString(); - let n = s.indexOf(os5.EOL); + let n = s.indexOf(os6.EOL); while (n > -1) { const line = s.substring(0, n); onLine(line); - s = s.substring(n + os5.EOL.length); - n = s.indexOf(os5.EOL); + s = s.substring(n + os6.EOL.length); + n = s.indexOf(os6.EOL); } return s; } catch (err) { @@ -19311,7 +19311,7 @@ var require_toolrunner = __commonJS({ } const optionsNonNull = this._cloneExecOptions(this.options); if (!optionsNonNull.silent && optionsNonNull.outStream) { - optionsNonNull.outStream.write(this._getCommandString(optionsNonNull) + os5.EOL); + optionsNonNull.outStream.write(this._getCommandString(optionsNonNull) + os6.EOL); } const state = new ExecState(optionsNonNull, this.toolPath); state.on("debug", (message) => { @@ -19852,7 +19852,7 @@ var require_core = __commonJS({ var command_1 = require_command(); var file_command_1 = require_file_command(); var utils_1 = require_utils(); - var os5 = __importStar2(require("os")); + var os6 = __importStar2(require("os")); var path16 = __importStar2(require("path")); var oidc_utils_1 = require_oidc_utils(); var ExitCode; @@ -19914,7 +19914,7 @@ Support boolean input list: \`true | True | TRUE | false | False | FALSE\``); if (filePath) { return (0, file_command_1.issueFileCommand)("OUTPUT", (0, file_command_1.prepareKeyValueMessage)(name, value)); } - process.stdout.write(os5.EOL); + process.stdout.write(os6.EOL); (0, command_1.issueCommand)("set-output", { name }, (0, utils_1.toCommandValue)(value)); } function setCommandEcho(enabled) { @@ -19940,7 +19940,7 @@ Support boolean input list: \`true | True | TRUE | false | False | FALSE\``); (0, command_1.issueCommand)("notice", (0, utils_1.toCommandProperties)(properties), message instanceof Error ? message.toString() : message); } function info6(message) { - process.stdout.write(message + os5.EOL); + process.stdout.write(message + os6.EOL); } function startGroup4(name) { (0, command_1.issue)("group", name); @@ -29815,11 +29815,11 @@ var require_command2 = __commonJS({ }; Object.defineProperty(exports2, "__esModule", { value: true }); exports2.issue = exports2.issueCommand = void 0; - var os5 = __importStar2(require("os")); + var os6 = __importStar2(require("os")); var utils_1 = require_utils5(); function issueCommand(command, properties, message) { const cmd = new Command(command, properties, message); - process.stdout.write(cmd.toString() + os5.EOL); + process.stdout.write(cmd.toString() + os6.EOL); } exports2.issueCommand = issueCommand; function issue(name, message = "") { @@ -29903,7 +29903,7 @@ var require_file_command2 = __commonJS({ exports2.prepareKeyValueMessage = exports2.issueFileCommand = void 0; var crypto3 = __importStar2(require("crypto")); var fs15 = __importStar2(require("fs")); - var os5 = __importStar2(require("os")); + var os6 = __importStar2(require("os")); var utils_1 = require_utils5(); function issueFileCommand(command, message) { const filePath = process.env[`GITHUB_${command}`]; @@ -29913,7 +29913,7 @@ var require_file_command2 = __commonJS({ if (!fs15.existsSync(filePath)) { throw new Error(`Missing file at path: ${filePath}`); } - fs15.appendFileSync(filePath, `${(0, utils_1.toCommandValue)(message)}${os5.EOL}`, { + fs15.appendFileSync(filePath, `${(0, utils_1.toCommandValue)(message)}${os6.EOL}`, { encoding: "utf8" }); } @@ -29927,7 +29927,7 @@ var require_file_command2 = __commonJS({ if (convertedValue.includes(delimiter)) { throw new Error(`Unexpected input: value should not contain the delimiter "${delimiter}"`); } - return `${key}<<${delimiter}${os5.EOL}${convertedValue}${os5.EOL}${delimiter}`; + return `${key}<<${delimiter}${os6.EOL}${convertedValue}${os6.EOL}${delimiter}`; } exports2.prepareKeyValueMessage = prepareKeyValueMessage; } @@ -31656,7 +31656,7 @@ var require_toolrunner2 = __commonJS({ }; Object.defineProperty(exports2, "__esModule", { value: true }); exports2.argStringToArray = exports2.ToolRunner = void 0; - var os5 = __importStar2(require("os")); + var os6 = __importStar2(require("os")); var events = __importStar2(require("events")); var child = __importStar2(require("child_process")); var path16 = __importStar2(require("path")); @@ -31711,12 +31711,12 @@ var require_toolrunner2 = __commonJS({ _processLineBuffer(data, strBuffer, onLine) { try { let s = strBuffer + data.toString(); - let n = s.indexOf(os5.EOL); + let n = s.indexOf(os6.EOL); while (n > -1) { const line = s.substring(0, n); onLine(line); - s = s.substring(n + os5.EOL.length); - n = s.indexOf(os5.EOL); + s = s.substring(n + os6.EOL.length); + n = s.indexOf(os6.EOL); } return s; } catch (err) { @@ -31885,7 +31885,7 @@ var require_toolrunner2 = __commonJS({ } const optionsNonNull = this._cloneExecOptions(this.options); if (!optionsNonNull.silent && optionsNonNull.outStream) { - optionsNonNull.outStream.write(this._getCommandString(optionsNonNull) + os5.EOL); + optionsNonNull.outStream.write(this._getCommandString(optionsNonNull) + os6.EOL); } const state = new ExecState(optionsNonNull, this.toolPath); state.on("debug", (message) => { @@ -32373,7 +32373,7 @@ var require_core2 = __commonJS({ var command_1 = require_command2(); var file_command_1 = require_file_command2(); var utils_1 = require_utils5(); - var os5 = __importStar2(require("os")); + var os6 = __importStar2(require("os")); var path16 = __importStar2(require("path")); var oidc_utils_1 = require_oidc_utils2(); var ExitCode; @@ -32441,7 +32441,7 @@ Support boolean input list: \`true | True | TRUE | false | False | FALSE\``); if (filePath) { return (0, file_command_1.issueFileCommand)("OUTPUT", (0, file_command_1.prepareKeyValueMessage)(name, value)); } - process.stdout.write(os5.EOL); + process.stdout.write(os6.EOL); (0, command_1.issueCommand)("set-output", { name }, (0, utils_1.toCommandValue)(value)); } exports2.setOutput = setOutput2; @@ -32475,7 +32475,7 @@ Support boolean input list: \`true | True | TRUE | false | False | FALSE\``); } exports2.notice = notice; function info6(message) { - process.stdout.write(message + os5.EOL); + process.stdout.write(message + os6.EOL); } exports2.info = info6; function startGroup4(name) { @@ -33774,7 +33774,7 @@ var require_internal_pattern = __commonJS({ }; Object.defineProperty(exports2, "__esModule", { value: true }); exports2.Pattern = void 0; - var os5 = __importStar2(require("os")); + var os6 = __importStar2(require("os")); var path16 = __importStar2(require("path")); var pathHelper = __importStar2(require_internal_path_helper()); var assert_1 = __importDefault2(require("assert")); @@ -33867,7 +33867,7 @@ var require_internal_pattern = __commonJS({ if (pattern === "." || pattern.startsWith(`.${path16.sep}`)) { pattern = _Pattern.globEscape(process.cwd()) + pattern.substr(1); } else if (pattern === "~" || pattern.startsWith(`~${path16.sep}`)) { - homedir2 = homedir2 || os5.homedir(); + homedir2 = homedir2 || os6.homedir(); (0, assert_1.default)(homedir2, "Unable to determine HOME directory"); (0, assert_1.default)(pathHelper.hasAbsoluteRoot(homedir2), `Expected HOME directory to be a rooted path. Actual '${homedir2}'`); pattern = _Pattern.globEscape(homedir2) + pattern.substr(1); @@ -38743,7 +38743,7 @@ var require_has_flag = __commonJS({ var require_supports_color = __commonJS({ "node_modules/supports-color/index.js"(exports2, module2) { "use strict"; - var os5 = require("os"); + var os6 = require("os"); var tty = require("tty"); var hasFlag = require_has_flag(); var { env } = process; @@ -38791,7 +38791,7 @@ var require_supports_color = __commonJS({ return min; } if (process.platform === "win32") { - const osRelease = os5.release().split("."); + const osRelease = os6.release().split("."); if (Number(osRelease[0]) >= 10 && Number(osRelease[2]) >= 10586) { return Number(osRelease[2]) >= 14931 ? 3 : 2; } @@ -82650,12 +82650,12 @@ var require_manifest = __commonJS({ exports2._readLinuxVersionFile = _readLinuxVersionFile; var semver10 = __importStar2(require_semver2()); var core_1 = require_core(); - var os5 = require("os"); + var os6 = require("os"); var cp = require("child_process"); var fs15 = require("fs"); function _findMatch(versionSpec, stable, candidates, archFilter) { return __awaiter2(this, void 0, void 0, function* () { - const platFilter = os5.platform(); + const platFilter = os6.platform(); let result; let match; let file; @@ -82691,7 +82691,7 @@ var require_manifest = __commonJS({ }); } function _getOsVersion() { - const plat = os5.platform(); + const plat = os6.platform(); let version = ""; if (plat === "darwin") { version = cp.execSync("sw_vers -productVersion").toString(); @@ -82928,7 +82928,7 @@ var require_tool_cache = __commonJS({ var crypto3 = __importStar2(require("crypto")); var fs15 = __importStar2(require("fs")); var mm = __importStar2(require_manifest()); - var os5 = __importStar2(require("os")); + var os6 = __importStar2(require("os")); var path16 = __importStar2(require("path")); var httpm = __importStar2(require_lib()); var semver10 = __importStar2(require_semver2()); @@ -83205,7 +83205,7 @@ var require_tool_cache = __commonJS({ function cacheDir(sourceDir, tool, version, arch2) { return __awaiter2(this, void 0, void 0, function* () { version = semver10.clean(version) || version; - arch2 = arch2 || os5.arch(); + arch2 = arch2 || os6.arch(); core14.debug(`Caching tool ${tool} ${version} ${arch2}`); core14.debug(`source dir: ${sourceDir}`); if (!fs15.statSync(sourceDir).isDirectory()) { @@ -83223,7 +83223,7 @@ var require_tool_cache = __commonJS({ function cacheFile(sourceFile, targetFile, tool, version, arch2) { return __awaiter2(this, void 0, void 0, function* () { version = semver10.clean(version) || version; - arch2 = arch2 || os5.arch(); + arch2 = arch2 || os6.arch(); core14.debug(`Caching tool ${tool} ${version} ${arch2}`); core14.debug(`source file: ${sourceFile}`); if (!fs15.statSync(sourceFile).isFile()) { @@ -83244,7 +83244,7 @@ var require_tool_cache = __commonJS({ if (!versionSpec) { throw new Error("versionSpec parameter is required"); } - arch2 = arch2 || os5.arch(); + arch2 = arch2 || os6.arch(); if (!isExplicitVersion(versionSpec)) { const localVersions = findAllVersions2(toolName, arch2); const match = evaluateVersions(localVersions, versionSpec); @@ -83266,7 +83266,7 @@ var require_tool_cache = __commonJS({ } function findAllVersions2(toolName, arch2) { const versions = []; - arch2 = arch2 || os5.arch(); + arch2 = arch2 || os6.arch(); const toolPath = path16.join(_getCacheDirectory(), toolName); if (fs15.existsSync(toolPath)) { const children = fs15.readdirSync(toolPath); @@ -83316,7 +83316,7 @@ var require_tool_cache = __commonJS({ }); } function findFromManifest(versionSpec_1, stable_1, manifest_1) { - return __awaiter2(this, arguments, void 0, function* (versionSpec, stable, manifest, archFilter = os5.arch()) { + return __awaiter2(this, arguments, void 0, function* (versionSpec, stable, manifest, archFilter = os6.arch()) { const match = yield mm._findMatch(versionSpec, stable, manifest, archFilter); return match; }); @@ -87186,6 +87186,13 @@ async function asyncSome(array, predicate) { function isDefined(value) { return value !== void 0 && value !== null; } +function joinAtMost(array, separator, limit) { + if (limit > 0 && array.length > limit) { + array = array.slice(0, limit); + array.push("..."); + } + return array.join(separator); +} // src/actions-util.ts var pkg = require_package(); @@ -87303,7 +87310,11 @@ function isDynamicWorkflow() { return getWorkflowEventName() === "dynamic"; } function isDefaultSetup() { - return isDynamicWorkflow(); + return isDynamicWorkflow() && !isCCR(); +} +var CCR_KEY_PREFIX = "dynamic/copilot-pull-request-reviewer"; +function isCCR() { + return process.env["CODEQL_ACTION_ANALYSIS_KEY" /* ANALYSIS_KEY */]?.startsWith(CCR_KEY_PREFIX) || false; } function prettyPrintInvocation(cmd, args) { return [cmd, ...args].map((x) => x.includes(" ") ? `'${x}'` : x).join(" "); @@ -87552,15 +87563,14 @@ async function getWorkflowRelativePath() { return workflowResponse.data.path; } async function getAnalysisKey() { - const analysisKeyEnvVar = "CODEQL_ACTION_ANALYSIS_KEY"; - let analysisKey = process.env[analysisKeyEnvVar]; + let analysisKey = process.env["CODEQL_ACTION_ANALYSIS_KEY" /* ANALYSIS_KEY */]; if (analysisKey !== void 0) { return analysisKey; } const workflowPath = await getWorkflowRelativePath(); const jobName = getRequiredEnvParam("GITHUB_JOB"); analysisKey = `${workflowPath}:${jobName}`; - core5.exportVariable(analysisKeyEnvVar, analysisKey); + core5.exportVariable("CODEQL_ACTION_ANALYSIS_KEY" /* ANALYSIS_KEY */, analysisKey); return analysisKey; } async function getAutomationID() { @@ -88148,6 +88158,7 @@ var path5 = __toESM(require("path")); var actionsCache = __toESM(require_cache4()); // src/git-utils.ts +var os2 = __toESM(require("os")); var core8 = __toESM(require_core()); var toolrunner2 = __toESM(require_toolrunner()); var io3 = __toESM(require_io()); @@ -88174,7 +88185,7 @@ async function getGitVersionOrThrow() { } throw new Error(`Could not parse Git version from output: ${stdout.trim()}`); } -var runGitCommand = async function(workingDirectory, args, customErrorMessage) { +var runGitCommand = async function(workingDirectory, args, customErrorMessage, options) { let stdout = ""; let stderr = ""; core8.debug(`Running git command: git ${args.join(" ")}`); @@ -88189,7 +88200,8 @@ var runGitCommand = async function(workingDirectory, args, customErrorMessage) { stderr += data.toString(); } }, - cwd: workingDirectory + cwd: workingDirectory, + ...options }).exec(); return stdout; } catch (error3) { @@ -88344,6 +88356,32 @@ async function isAnalyzingDefaultBranch() { } return currentRef === defaultBranch; } +async function listFiles(workingDirectory) { + const stdout = await runGitCommand( + workingDirectory, + ["ls-files"], + "Unable to list tracked files." + ); + return stdout.split(os2.EOL).filter((line) => line.trim().length > 0); +} +async function getGeneratedFiles(workingDirectory) { + const files = await listFiles(workingDirectory); + const stdout = await runGitCommand( + workingDirectory, + ["check-attr", "linguist-generated", "--stdin"], + "Unable to check attributes of files.", + { input: Buffer.from(files.join(os2.EOL)) } + ); + const generatedFiles = []; + const regex = /^([^:]+): linguist-generated: true$/; + for (const result of stdout.split(os2.EOL)) { + const match = result.match(regex); + if (match && match[1].trim().length > 0) { + generatedFiles.push(match[1].trim()); + } + } + return generatedFiles; +} // src/overlay-database-utils.ts var CODEQL_OVERLAY_MINIMUM_VERSION = "2.23.8"; @@ -88615,6 +88653,11 @@ var featureConfig = { legacyApi: true, minimumVersion: void 0 }, + ["ignore_generated_files" /* IgnoreGeneratedFiles */]: { + defaultValue: false, + envVar: "CODEQL_ACTION_IGNORE_GENERATED_FILES", + minimumVersion: void 0 + }, ["overlay_analysis" /* OverlayAnalysis */]: { defaultValue: false, envVar: "CODEQL_ACTION_OVERLAY_ANALYSIS", @@ -89594,6 +89637,33 @@ async function initConfig(features, inputs) { throw e; } } + if (await features.getValue("ignore_generated_files" /* IgnoreGeneratedFiles */) && isCCR()) { + try { + const generatedFilesCheckStartedAt = import_perf_hooks.performance.now(); + const generatedFiles = await getGeneratedFiles(inputs.sourceRoot); + const generatedFilesDuration = Math.round( + import_perf_hooks.performance.now() - generatedFilesCheckStartedAt + ); + if (generatedFiles.length > 0) { + config.computedConfig["paths-ignore"] ??= []; + config.computedConfig["paths-ignore"].push(...generatedFiles); + logger.info( + `Detected ${generatedFiles.length} generated file(s), which will be excluded from analysis: ${joinAtMost(generatedFiles, ", ", 10)}` + ); + } else { + logger.info(`Found no generated files.`); + } + await logGeneratedFilesTelemetry( + config, + generatedFilesDuration, + generatedFiles.length + ); + } catch (error3) { + logger.info(`Cannot ignore generated files: ${getErrorMessage(error3)}`); + } + } else { + logger.debug(`Skipping check for generated files.`); + } const { overlayDatabaseMode, useOverlayDatabaseCaching } = await getOverlayDatabaseMode( inputs.codeql, inputs.features, @@ -89823,9 +89893,28 @@ async function logGitVersionTelemetry(config, gitVersion) { ); } } +async function logGeneratedFilesTelemetry(config, duration, generatedFilesCount) { + if (config.languages.length < 1) { + return; + } + addDiagnostic( + config, + // Arbitrarily choose the first language. We could also choose all languages, but that + // increases the risk of misinterpreting the data. + config.languages[0], + makeTelemetryDiagnostic( + "codeql-action/generated-files-telemetry", + "Generated files telemetry", + { + duration, + generatedFilesCount + } + ) + ); +} // src/dependency-caching.ts -var os2 = __toESM(require("os")); +var os3 = __toESM(require("os")); var import_path2 = require("path"); var actionsCache3 = __toESM(require_cache4()); var glob = __toESM(require_glob()); @@ -89837,9 +89926,9 @@ function getJavaTempDependencyDir() { async function getJavaDependencyDirs() { return [ // Maven - (0, import_path2.join)(os2.homedir(), ".m2", "repository"), + (0, import_path2.join)(os3.homedir(), ".m2", "repository"), // Gradle - (0, import_path2.join)(os2.homedir(), ".gradle", "caches"), + (0, import_path2.join)(os3.homedir(), ".gradle", "caches"), // CodeQL Java build-mode: none getJavaTempDependencyDir() ]; @@ -89850,7 +89939,7 @@ function getCsharpTempDependencyDir() { async function getCsharpDependencyDirs(codeql, features) { const dirs = [ // Nuget - (0, import_path2.join)(os2.homedir(), ".nuget", "packages") + (0, import_path2.join)(os3.homedir(), ".nuget", "packages") ]; if (await features.getValue("csharp_cache_bmn" /* CsharpCacheBuildModeNone */, codeql)) { dirs.push(getCsharpTempDependencyDir()); @@ -89905,7 +89994,7 @@ var defaultCacheConfigs = { getHashPatterns: getCsharpHashPatterns }, go: { - getDependencyPaths: async () => [(0, import_path2.join)(os2.homedir(), "go", "pkg", "mod")], + getDependencyPaths: async () => [(0, import_path2.join)(os3.homedir(), "go", "pkg", "mod")], getHashPatterns: async () => internal.makePatternCheck(["**/go.sum"]) } }; @@ -90432,7 +90521,7 @@ function inferCompressionMethod(tarPath) { // src/tools-download.ts var fs8 = __toESM(require("fs")); -var os3 = __toESM(require("os")); +var os4 = __toESM(require("os")); var path9 = __toESM(require("path")); var import_perf_hooks2 = require("perf_hooks"); var core9 = __toESM(require_core()); @@ -90570,7 +90659,7 @@ function getToolcacheDirectory(version) { getRequiredEnvParam("RUNNER_TOOL_CACHE"), TOOLCACHE_TOOL_NAME, semver7.clean(version) || version, - os3.arch() || "" + os4.arch() || "" ); } function writeToolcacheMarkerFile(extractedPath, logger) { @@ -91933,7 +92022,7 @@ function cleanupDatabaseClusterDirectory(config, logger, options = {}, rmSync2 = } // src/status-report.ts -var os4 = __toESM(require("os")); +var os5 = __toESM(require("os")); var core11 = __toESM(require_core()); function isFirstPartyAnalysis(actionName) { if (actionName !== "upload-sarif" /* UploadSarif */) { @@ -92037,7 +92126,7 @@ async function createStatusReportBase(actionName, status, actionStartedAt, confi statusReport.runner_arch = process.env["RUNNER_ARCH"]; } if (!(runnerOs === "Linux" && isSelfHostedRunner())) { - statusReport.runner_os_release = os4.release(); + statusReport.runner_os_release = os5.release(); } if (codeQlCliVersion !== void 0) { statusReport.codeql_version = codeQlCliVersion.version; diff --git a/lib/resolve-environment-action.js b/lib/resolve-environment-action.js index 952a82ffb5..0a1774f2aa 100644 --- a/lib/resolve-environment-action.js +++ b/lib/resolve-environment-action.js @@ -86901,15 +86901,14 @@ async function getWorkflowRelativePath() { return workflowResponse.data.path; } async function getAnalysisKey() { - const analysisKeyEnvVar = "CODEQL_ACTION_ANALYSIS_KEY"; - let analysisKey = process.env[analysisKeyEnvVar]; + let analysisKey = process.env["CODEQL_ACTION_ANALYSIS_KEY" /* ANALYSIS_KEY */]; if (analysisKey !== void 0) { return analysisKey; } const workflowPath = await getWorkflowRelativePath(); const jobName = getRequiredEnvParam("GITHUB_JOB"); analysisKey = `${workflowPath}:${jobName}`; - core5.exportVariable(analysisKeyEnvVar, analysisKey); + core5.exportVariable("CODEQL_ACTION_ANALYSIS_KEY" /* ANALYSIS_KEY */, analysisKey); return analysisKey; } @@ -87205,7 +87204,7 @@ var core8 = __toESM(require_core()); var toolrunner2 = __toESM(require_toolrunner()); var io3 = __toESM(require_io()); var semver3 = __toESM(require_semver2()); -var runGitCommand = async function(workingDirectory, args, customErrorMessage) { +var runGitCommand = async function(workingDirectory, args, customErrorMessage, options) { let stdout = ""; let stderr = ""; core8.debug(`Running git command: git ${args.join(" ")}`); @@ -87220,7 +87219,8 @@ var runGitCommand = async function(workingDirectory, args, customErrorMessage) { stderr += data.toString(); } }, - cwd: workingDirectory + cwd: workingDirectory, + ...options }).exec(); return stdout; } catch (error3) { @@ -87484,6 +87484,11 @@ var featureConfig = { legacyApi: true, minimumVersion: void 0 }, + ["ignore_generated_files" /* IgnoreGeneratedFiles */]: { + defaultValue: false, + envVar: "CODEQL_ACTION_IGNORE_GENERATED_FILES", + minimumVersion: void 0 + }, ["overlay_analysis" /* OverlayAnalysis */]: { defaultValue: false, envVar: "CODEQL_ACTION_OVERLAY_ANALYSIS", diff --git a/lib/setup-codeql-action.js b/lib/setup-codeql-action.js index af5e90cc74..0a9b97198a 100644 --- a/lib/setup-codeql-action.js +++ b/lib/setup-codeql-action.js @@ -87018,15 +87018,14 @@ async function getWorkflowRelativePath() { return workflowResponse.data.path; } async function getAnalysisKey() { - const analysisKeyEnvVar = "CODEQL_ACTION_ANALYSIS_KEY"; - let analysisKey = process.env[analysisKeyEnvVar]; + let analysisKey = process.env["CODEQL_ACTION_ANALYSIS_KEY" /* ANALYSIS_KEY */]; if (analysisKey !== void 0) { return analysisKey; } const workflowPath = await getWorkflowRelativePath(); const jobName = getRequiredEnvParam("GITHUB_JOB"); analysisKey = `${workflowPath}:${jobName}`; - core5.exportVariable(analysisKeyEnvVar, analysisKey); + core5.exportVariable("CODEQL_ACTION_ANALYSIS_KEY" /* ANALYSIS_KEY */, analysisKey); return analysisKey; } function isEnablementError(msg) { @@ -87089,7 +87088,7 @@ var core7 = __toESM(require_core()); var toolrunner2 = __toESM(require_toolrunner()); var io3 = __toESM(require_io()); var semver2 = __toESM(require_semver2()); -var runGitCommand = async function(workingDirectory, args, customErrorMessage) { +var runGitCommand = async function(workingDirectory, args, customErrorMessage, options) { let stdout = ""; let stderr = ""; core7.debug(`Running git command: git ${args.join(" ")}`); @@ -87104,7 +87103,8 @@ var runGitCommand = async function(workingDirectory, args, customErrorMessage) { stderr += data.toString(); } }, - cwd: workingDirectory + cwd: workingDirectory, + ...options }).exec(); return stdout; } catch (error3) { @@ -87396,6 +87396,11 @@ var featureConfig = { legacyApi: true, minimumVersion: void 0 }, + ["ignore_generated_files" /* IgnoreGeneratedFiles */]: { + defaultValue: false, + envVar: "CODEQL_ACTION_IGNORE_GENERATED_FILES", + minimumVersion: void 0 + }, ["overlay_analysis" /* OverlayAnalysis */]: { defaultValue: false, envVar: "CODEQL_ACTION_OVERLAY_ANALYSIS", diff --git a/lib/start-proxy-action-post.js b/lib/start-proxy-action-post.js index 50ce9f34d8..87fd6605d7 100644 --- a/lib/start-proxy-action-post.js +++ b/lib/start-proxy-action-post.js @@ -124005,6 +124005,11 @@ var featureConfig = { legacyApi: true, minimumVersion: void 0 }, + ["ignore_generated_files" /* IgnoreGeneratedFiles */]: { + defaultValue: false, + envVar: "CODEQL_ACTION_IGNORE_GENERATED_FILES", + minimumVersion: void 0 + }, ["overlay_analysis" /* OverlayAnalysis */]: { defaultValue: false, envVar: "CODEQL_ACTION_OVERLAY_ANALYSIS", diff --git a/lib/start-proxy-action.js b/lib/start-proxy-action.js index 15f6c4c357..f855c5a0a0 100644 --- a/lib/start-proxy-action.js +++ b/lib/start-proxy-action.js @@ -103934,15 +103934,14 @@ async function getWorkflowRelativePath() { return workflowResponse.data.path; } async function getAnalysisKey() { - const analysisKeyEnvVar = "CODEQL_ACTION_ANALYSIS_KEY"; - let analysisKey = process.env[analysisKeyEnvVar]; + let analysisKey = process.env["CODEQL_ACTION_ANALYSIS_KEY" /* ANALYSIS_KEY */]; if (analysisKey !== void 0) { return analysisKey; } const workflowPath = await getWorkflowRelativePath(); const jobName = getRequiredEnvParam("GITHUB_JOB"); analysisKey = `${workflowPath}:${jobName}`; - core5.exportVariable(analysisKeyEnvVar, analysisKey); + core5.exportVariable("CODEQL_ACTION_ANALYSIS_KEY" /* ANALYSIS_KEY */, analysisKey); return analysisKey; } @@ -104159,7 +104158,7 @@ var core9 = __toESM(require_core()); var toolrunner2 = __toESM(require_toolrunner()); var io3 = __toESM(require_io()); var semver3 = __toESM(require_semver2()); -var runGitCommand = async function(workingDirectory, args, customErrorMessage) { +var runGitCommand = async function(workingDirectory, args, customErrorMessage, options) { let stdout = ""; let stderr = ""; core9.debug(`Running git command: git ${args.join(" ")}`); @@ -104174,7 +104173,8 @@ var runGitCommand = async function(workingDirectory, args, customErrorMessage) { stderr += data.toString(); } }, - cwd: workingDirectory + cwd: workingDirectory, + ...options }).exec(); return stdout; } catch (error3) { @@ -104311,6 +104311,11 @@ var featureConfig = { legacyApi: true, minimumVersion: void 0 }, + ["ignore_generated_files" /* IgnoreGeneratedFiles */]: { + defaultValue: false, + envVar: "CODEQL_ACTION_IGNORE_GENERATED_FILES", + minimumVersion: void 0 + }, ["overlay_analysis" /* OverlayAnalysis */]: { defaultValue: false, envVar: "CODEQL_ACTION_OVERLAY_ANALYSIS", diff --git a/lib/upload-lib.js b/lib/upload-lib.js index 496f710649..480b83cd56 100644 --- a/lib/upload-lib.js +++ b/lib/upload-lib.js @@ -89654,7 +89654,11 @@ function isDynamicWorkflow() { return getWorkflowEventName() === "dynamic"; } function isDefaultSetup() { - return isDynamicWorkflow(); + return isDynamicWorkflow() && !isCCR(); +} +var CCR_KEY_PREFIX = "dynamic/copilot-pull-request-reviewer"; +function isCCR() { + return process.env["CODEQL_ACTION_ANALYSIS_KEY" /* ANALYSIS_KEY */]?.startsWith(CCR_KEY_PREFIX) || false; } function prettyPrintInvocation(cmd, args) { return [cmd, ...args].map((x) => x.includes(" ") ? `'${x}'` : x).join(" "); @@ -89874,15 +89878,14 @@ async function getWorkflowRelativePath() { return workflowResponse.data.path; } async function getAnalysisKey() { - const analysisKeyEnvVar = "CODEQL_ACTION_ANALYSIS_KEY"; - let analysisKey = process.env[analysisKeyEnvVar]; + let analysisKey = process.env["CODEQL_ACTION_ANALYSIS_KEY" /* ANALYSIS_KEY */]; if (analysisKey !== void 0) { return analysisKey; } const workflowPath = await getWorkflowRelativePath(); const jobName = getRequiredEnvParam("GITHUB_JOB"); analysisKey = `${workflowPath}:${jobName}`; - core5.exportVariable(analysisKeyEnvVar, analysisKey); + core5.exportVariable("CODEQL_ACTION_ANALYSIS_KEY" /* ANALYSIS_KEY */, analysisKey); return analysisKey; } function computeAutomationID(analysis_key, environment) { @@ -90235,7 +90238,7 @@ var core8 = __toESM(require_core()); var toolrunner2 = __toESM(require_toolrunner()); var io3 = __toESM(require_io()); var semver3 = __toESM(require_semver2()); -var runGitCommand = async function(workingDirectory, args, customErrorMessage) { +var runGitCommand = async function(workingDirectory, args, customErrorMessage, options) { let stdout = ""; let stderr = ""; core8.debug(`Running git command: git ${args.join(" ")}`); @@ -90250,7 +90253,8 @@ var runGitCommand = async function(workingDirectory, args, customErrorMessage) { stderr += data.toString(); } }, - cwd: workingDirectory + cwd: workingDirectory, + ...options }).exec(); return stdout; } catch (error3) { @@ -90549,6 +90553,11 @@ var featureConfig = { legacyApi: true, minimumVersion: void 0 }, + ["ignore_generated_files" /* IgnoreGeneratedFiles */]: { + defaultValue: false, + envVar: "CODEQL_ACTION_IGNORE_GENERATED_FILES", + minimumVersion: void 0 + }, ["overlay_analysis" /* OverlayAnalysis */]: { defaultValue: false, envVar: "CODEQL_ACTION_OVERLAY_ANALYSIS", diff --git a/lib/upload-sarif-action-post.js b/lib/upload-sarif-action-post.js index fe3d597b7d..ba1e4ac450 100644 --- a/lib/upload-sarif-action-post.js +++ b/lib/upload-sarif-action-post.js @@ -124167,6 +124167,11 @@ var featureConfig = { legacyApi: true, minimumVersion: void 0 }, + ["ignore_generated_files" /* IgnoreGeneratedFiles */]: { + defaultValue: false, + envVar: "CODEQL_ACTION_IGNORE_GENERATED_FILES", + minimumVersion: void 0 + }, ["overlay_analysis" /* OverlayAnalysis */]: { defaultValue: false, envVar: "CODEQL_ACTION_OVERLAY_ANALYSIS", diff --git a/lib/upload-sarif-action.js b/lib/upload-sarif-action.js index 61f452f248..3d278c11c0 100644 --- a/lib/upload-sarif-action.js +++ b/lib/upload-sarif-action.js @@ -89685,7 +89685,11 @@ function isDynamicWorkflow() { return getWorkflowEventName() === "dynamic"; } function isDefaultSetup() { - return isDynamicWorkflow(); + return isDynamicWorkflow() && !isCCR(); +} +var CCR_KEY_PREFIX = "dynamic/copilot-pull-request-reviewer"; +function isCCR() { + return process.env["CODEQL_ACTION_ANALYSIS_KEY" /* ANALYSIS_KEY */]?.startsWith(CCR_KEY_PREFIX) || false; } function prettyPrintInvocation(cmd, args) { return [cmd, ...args].map((x) => x.includes(" ") ? `'${x}'` : x).join(" "); @@ -89920,15 +89924,14 @@ async function getWorkflowRelativePath() { return workflowResponse.data.path; } async function getAnalysisKey() { - const analysisKeyEnvVar = "CODEQL_ACTION_ANALYSIS_KEY"; - let analysisKey = process.env[analysisKeyEnvVar]; + let analysisKey = process.env["CODEQL_ACTION_ANALYSIS_KEY" /* ANALYSIS_KEY */]; if (analysisKey !== void 0) { return analysisKey; } const workflowPath = await getWorkflowRelativePath(); const jobName = getRequiredEnvParam("GITHUB_JOB"); analysisKey = `${workflowPath}:${jobName}`; - core5.exportVariable(analysisKeyEnvVar, analysisKey); + core5.exportVariable("CODEQL_ACTION_ANALYSIS_KEY" /* ANALYSIS_KEY */, analysisKey); return analysisKey; } function computeAutomationID(analysis_key, environment) { @@ -90005,7 +90008,7 @@ var core7 = __toESM(require_core()); var toolrunner2 = __toESM(require_toolrunner()); var io3 = __toESM(require_io()); var semver2 = __toESM(require_semver2()); -var runGitCommand = async function(workingDirectory, args, customErrorMessage) { +var runGitCommand = async function(workingDirectory, args, customErrorMessage, options) { let stdout = ""; let stderr = ""; core7.debug(`Running git command: git ${args.join(" ")}`); @@ -90020,7 +90023,8 @@ var runGitCommand = async function(workingDirectory, args, customErrorMessage) { stderr += data.toString(); } }, - cwd: workingDirectory + cwd: workingDirectory, + ...options }).exec(); return stdout; } catch (error3) { @@ -90346,6 +90350,11 @@ var featureConfig = { legacyApi: true, minimumVersion: void 0 }, + ["ignore_generated_files" /* IgnoreGeneratedFiles */]: { + defaultValue: false, + envVar: "CODEQL_ACTION_IGNORE_GENERATED_FILES", + minimumVersion: void 0 + }, ["overlay_analysis" /* OverlayAnalysis */]: { defaultValue: false, envVar: "CODEQL_ACTION_OVERLAY_ANALYSIS", diff --git a/src/actions-util.test.ts b/src/actions-util.test.ts index d8e7aa412b..71a409da6d 100644 --- a/src/actions-util.test.ts +++ b/src/actions-util.test.ts @@ -5,6 +5,9 @@ import { fixCodeQualityCategory, getPullRequestBranches, isAnalyzingPullRequest, + isCCR, + isDefaultSetup, + isDynamicWorkflow, } from "./actions-util"; import { computeAutomationID } from "./api-client"; import { EnvVar } from "./environment"; @@ -246,3 +249,24 @@ test("fixCodeQualityCategory", (t) => { }, ); }); + +test("isDynamicWorkflow() returns true if event name is `dynamic`", (t) => { + process.env.GITHUB_EVENT_NAME = "dynamic"; + t.assert(isDynamicWorkflow()); + process.env.GITHUB_EVENT_NAME = "push"; + t.false(isDynamicWorkflow()); +}); + +test("isCCR() returns true when expected", (t) => { + process.env.GITHUB_EVENT_NAME = "dynamic"; + process.env[EnvVar.ANALYSIS_KEY] = "dynamic/copilot-pull-request-reviewer"; + t.assert(isCCR()); + t.false(isDefaultSetup()); +}); + +test("isDefaultSetup() returns true when expected", (t) => { + process.env.GITHUB_EVENT_NAME = "dynamic"; + process.env[EnvVar.ANALYSIS_KEY] = "dynamic/github-code-scanning"; + t.assert(isDefaultSetup()); + t.false(isCCR()); +}); diff --git a/src/actions-util.ts b/src/actions-util.ts index 736d35d0f1..25f08359f1 100644 --- a/src/actions-util.ts +++ b/src/actions-util.ts @@ -8,6 +8,7 @@ import * as io from "@actions/io"; import { JSONSchemaForNPMPackageJsonFiles } from "@schemastore/package"; import type { Config } from "./config-utils"; +import { EnvVar } from "./environment"; import { Logger } from "./logging"; import { doesDirectoryExist, @@ -254,7 +255,15 @@ export function isDynamicWorkflow(): boolean { /** Determines whether we are running in default setup. */ export function isDefaultSetup(): boolean { - return isDynamicWorkflow(); + return isDynamicWorkflow() && !isCCR(); +} + +/* The analysis key prefix used for CCR. */ +const CCR_KEY_PREFIX = "dynamic/copilot-pull-request-reviewer"; + +/** Determines whether we are running in CCR. */ +export function isCCR(): boolean { + return process.env[EnvVar.ANALYSIS_KEY]?.startsWith(CCR_KEY_PREFIX) || false; } export function prettyPrintInvocation(cmd: string, args: string[]): string { diff --git a/src/api-client.ts b/src/api-client.ts index 32a6a080b7..592c113b33 100644 --- a/src/api-client.ts +++ b/src/api-client.ts @@ -3,6 +3,7 @@ import * as githubUtils from "@actions/github/lib/utils"; import * as retry from "@octokit/plugin-retry"; import { getActionVersion, getRequiredInput } from "./actions-util"; +import { EnvVar } from "./environment"; import { Logger } from "./logging"; import { getRepositoryNwo, RepositoryNwo } from "./repository"; import { @@ -189,9 +190,7 @@ export async function getWorkflowRelativePath(): Promise { * the GitHub API, but after that the result will be cached. */ export async function getAnalysisKey(): Promise { - const analysisKeyEnvVar = "CODEQL_ACTION_ANALYSIS_KEY"; - - let analysisKey = process.env[analysisKeyEnvVar]; + let analysisKey = process.env[EnvVar.ANALYSIS_KEY]; if (analysisKey !== undefined) { return analysisKey; } @@ -200,7 +199,7 @@ export async function getAnalysisKey(): Promise { const jobName = getRequiredEnvParam("GITHUB_JOB"); analysisKey = `${workflowPath}:${jobName}`; - core.exportVariable(analysisKeyEnvVar, analysisKey); + core.exportVariable(EnvVar.ANALYSIS_KEY, analysisKey); return analysisKey; } diff --git a/src/config-utils.ts b/src/config-utils.ts index 5f32406ba1..772c187b83 100644 --- a/src/config-utils.ts +++ b/src/config-utils.ts @@ -4,7 +4,11 @@ import { performance } from "perf_hooks"; import * as yaml from "js-yaml"; -import { getActionVersion, isAnalyzingPullRequest } from "./actions-util"; +import { + getActionVersion, + isAnalyzingPullRequest, + isCCR, +} from "./actions-util"; import { AnalysisConfig, AnalysisKind, @@ -29,6 +33,7 @@ import * as errorMessages from "./error-messages"; import { Feature, FeatureEnablement } from "./feature-flags"; import { RepositoryProperties } from "./feature-flags/properties"; import { + getGeneratedFiles, getGitRoot, getGitVersionOrThrow, GIT_MINIMUM_VERSION_FOR_OVERLAY, @@ -55,6 +60,7 @@ import { getCodeQLMemoryLimit, getErrorMessage, isInTestMode, + joinAtMost, } from "./util"; export * from "./config/db-config"; @@ -948,6 +954,39 @@ export async function initConfig( } } + // If we are in CCR or the corresponding FF is enabled, try to determine + // which files in the repository are marked as generated and add them to + // the `paths-ignore` configuration. + if ((await features.getValue(Feature.IgnoreGeneratedFiles)) && isCCR()) { + try { + const generatedFilesCheckStartedAt = performance.now(); + const generatedFiles = await getGeneratedFiles(inputs.sourceRoot); + const generatedFilesDuration = Math.round( + performance.now() - generatedFilesCheckStartedAt, + ); + + if (generatedFiles.length > 0) { + config.computedConfig["paths-ignore"] ??= []; + config.computedConfig["paths-ignore"].push(...generatedFiles); + logger.info( + `Detected ${generatedFiles.length} generated file(s), which will be excluded from analysis: ${joinAtMost(generatedFiles, ", ", 10)}`, + ); + } else { + logger.info(`Found no generated files.`); + } + + await logGeneratedFilesTelemetry( + config, + generatedFilesDuration, + generatedFiles.length, + ); + } catch (error) { + logger.info(`Cannot ignore generated files: ${getErrorMessage(error)}`); + } + } else { + logger.debug(`Skipping check for generated files.`); + } + // The choice of overlay database mode depends on the selection of languages // and queries, which in turn depends on the user config and the augmentation // properties. So we need to calculate the overlay database mode after the @@ -1385,3 +1424,32 @@ async function logGitVersionTelemetry( ); } } + +/** + * Logs the time it took to identify generated files and how many were discovered as + * a telemetry diagnostic. + * */ +async function logGeneratedFilesTelemetry( + config: Config, + duration: number, + generatedFilesCount: number, +): Promise { + if (config.languages.length < 1) { + return; + } + + addDiagnostic( + config, + // Arbitrarily choose the first language. We could also choose all languages, but that + // increases the risk of misinterpreting the data. + config.languages[0], + makeTelemetryDiagnostic( + "codeql-action/generated-files-telemetry", + "Generated files telemetry", + { + duration, + generatedFilesCount, + }, + ), + ); +} diff --git a/src/environment.ts b/src/environment.ts index 16617c647b..4d7b44c808 100644 --- a/src/environment.ts +++ b/src/environment.ts @@ -135,4 +135,10 @@ export enum EnvVar { * Intended for use in environments where git may not be installed, such as Docker containers. */ TOLERATE_MISSING_GIT_VERSION = "CODEQL_ACTION_TOLERATE_MISSING_GIT_VERSION", + + /** + * Used to store the analysis key used by the CodeQL Action. This is normally populated by + * `getAnalysisKey`, but can also be set manually for testing and non-standard applications. + */ + ANALYSIS_KEY = "CODEQL_ACTION_ANALYSIS_KEY", } diff --git a/src/feature-flags.ts b/src/feature-flags.ts index 0695d62daa..7ad9ecfa48 100644 --- a/src/feature-flags.ts +++ b/src/feature-flags.ts @@ -45,6 +45,7 @@ export enum Feature { DisableJavaBuildlessEnabled = "disable_java_buildless_enabled", DisableKotlinAnalysisEnabled = "disable_kotlin_analysis_enabled", ExportDiagnosticsEnabled = "export_diagnostics_enabled", + IgnoreGeneratedFiles = "ignore_generated_files", OverlayAnalysis = "overlay_analysis", OverlayAnalysisActions = "overlay_analysis_actions", OverlayAnalysisCodeScanningActions = "overlay_analysis_code_scanning_actions", @@ -158,6 +159,11 @@ export const featureConfig = { legacyApi: true, minimumVersion: undefined, }, + [Feature.IgnoreGeneratedFiles]: { + defaultValue: false, + envVar: "CODEQL_ACTION_IGNORE_GENERATED_FILES", + minimumVersion: undefined, + }, [Feature.OverlayAnalysis]: { defaultValue: false, envVar: "CODEQL_ACTION_OVERLAY_ANALYSIS", diff --git a/src/git-utils.test.ts b/src/git-utils.test.ts index 1c96571c27..e4dbf84bc2 100644 --- a/src/git-utils.test.ts +++ b/src/git-utils.test.ts @@ -435,3 +435,42 @@ test("GitVersionInfo.isAtLeast correctly compares versions", async (t) => { t.false(version.isAtLeast("2.41.0")); t.false(version.isAtLeast("3.0.0")); }); + +test("listFiles returns array of file paths", async (t) => { + sinon + .stub(gitUtils, "runGitCommand") + .resolves(["dir/file.txt", "README.txt", ""].join(os.EOL)); + + await t.notThrowsAsync(async () => { + const result = await gitUtils.listFiles("/some/path"); + t.is(result.length, 2); + t.is(result[0], "dir/file.txt"); + }); +}); + +test("getGeneratedFiles returns generated files only", async (t) => { + const runGitCommandStub = sinon.stub(gitUtils, "runGitCommand"); + + runGitCommandStub + .onFirstCall() + .resolves(["dir/file.txt", "test.json", "README.txt", ""].join(os.EOL)); + runGitCommandStub + .onSecondCall() + .resolves( + [ + "dir/file.txt: linguist-generated: unspecified", + "test.json: linguist-generated: true", + "README.txt: linguist-generated: false", + "", + ].join(os.EOL), + ); + + await t.notThrowsAsync(async () => { + const result = await gitUtils.getGeneratedFiles("/some/path"); + + t.assert(runGitCommandStub.calledTwice); + + t.is(result.length, 1); + t.is(result[0], "test.json"); + }); +}); diff --git a/src/git-utils.ts b/src/git-utils.ts index eb9d8c695e..6b792ea543 100644 --- a/src/git-utils.ts +++ b/src/git-utils.ts @@ -1,4 +1,7 @@ +import * as os from "os"; + import * as core from "@actions/core"; +import { ExecOptions } from "@actions/exec"; import * as toolrunner from "@actions/exec/lib/toolrunner"; import * as io from "@actions/io"; import * as semver from "semver"; @@ -60,6 +63,7 @@ export const runGitCommand = async function ( workingDirectory: string | undefined, args: string[], customErrorMessage: string, + options?: ExecOptions, ): Promise { let stdout = ""; let stderr = ""; @@ -76,6 +80,7 @@ export const runGitCommand = async function ( }, }, cwd: workingDirectory, + ...options, }).exec(); return stdout; } catch (error) { @@ -394,3 +399,45 @@ export async function isAnalyzingDefaultBranch(): Promise { return currentRef === defaultBranch; } + +/** + * Gets a list of all tracked files in the repository. + * + * @param workingDirectory The working directory, which is part of a Git repository. + */ +export async function listFiles(workingDirectory: string): Promise { + const stdout = await runGitCommand( + workingDirectory, + ["ls-files"], + "Unable to list tracked files.", + ); + return stdout.split(os.EOL).filter((line) => line.trim().length > 0); +} + +/** + * Gets a list of files that have the `linguist-generated: true` attribute. + * + * @param workingDirectory The working directory, which is part of a Git repository. + */ +export async function getGeneratedFiles( + workingDirectory: string, +): Promise { + const files = await listFiles(workingDirectory); + const stdout = await runGitCommand( + workingDirectory, + ["check-attr", "linguist-generated", "--stdin"], + "Unable to check attributes of files.", + { input: Buffer.from(files.join(os.EOL)) }, + ); + + const generatedFiles: string[] = []; + const regex = /^([^:]+): linguist-generated: true$/; + for (const result of stdout.split(os.EOL)) { + const match = result.match(regex); + if (match && match[1].trim().length > 0) { + generatedFiles.push(match[1].trim()); + } + } + + return generatedFiles; +} diff --git a/src/status-report.test.ts b/src/status-report.test.ts index 8421dcceef..e051c54a27 100644 --- a/src/status-report.test.ts +++ b/src/status-report.test.ts @@ -27,7 +27,7 @@ setupTests(test); function setupEnvironmentAndStub(tmpDir: string) { setupActionsVars(tmpDir, tmpDir); - process.env["CODEQL_ACTION_ANALYSIS_KEY"] = "analysis-key"; + process.env[EnvVar.ANALYSIS_KEY] = "analysis-key"; process.env["GITHUB_EVENT_NAME"] = "dynamic"; process.env["GITHUB_REF"] = "refs/heads/main"; process.env["GITHUB_REPOSITORY"] = "octocat/HelloWorld"; diff --git a/src/util.test.ts b/src/util.test.ts index 1376ae7801..d6fc6aad0f 100644 --- a/src/util.test.ts +++ b/src/util.test.ts @@ -539,3 +539,27 @@ test("checkDiskUsage succeeds and produces positive numbers", async (t) => { t.true(diskUsage.numTotalBytes > 0); } }); + +test("joinAtMost - behaves like join if limit is <= 0", (t) => { + const sep = ", "; + const array: string[] = new Array(10).fill("test"); + t.is(util.joinAtMost(array, sep, 0), array.join(sep)); + t.is(util.joinAtMost(array, sep, -1), array.join(sep)); +}); + +test("joinAtMost - behaves like join if limit is >= the size of the array", (t) => { + const sep = ", "; + const array: string[] = new Array(10).fill("test"); + t.is(util.joinAtMost(array, sep, 10), array.join(sep)); + t.is(util.joinAtMost(array, sep, 11), array.join(sep)); +}); + +test("joinAtMost - truncates list if array is > than limit", (t) => { + const sep = ", "; + const array: string[] = Array.from(new Array(10), (_, i) => `test${i + 1}`); + const result = util.joinAtMost(array, sep, 5); + t.not(result, array.join(sep)); + t.assert(result.endsWith(", ...")); + t.assert(result.includes("test5")); + t.false(result.includes("test6")); +}); diff --git a/src/util.ts b/src/util.ts index a06a60bfe2..327fce0c77 100644 --- a/src/util.ts +++ b/src/util.ts @@ -1270,3 +1270,25 @@ export enum CleanupLevel { Clear = "clear", Overlay = "overlay", } + +/** + * Like `join`, but limits the number of elements that are joined together to `limit` + * and appends `...` if the limit is exceeded. + * + * @param array The array to join. + * @param separator The separator to join the array with. + * @param limit The maximum number of elements from `array` to join. + * @returns The result of joining at most `limit`-many elements from `array`. + */ +export function joinAtMost( + array: string[], + separator: string, + limit: number, +): string { + if (limit > 0 && array.length > limit) { + array = array.slice(0, limit); + array.push("..."); + } + + return array.join(separator); +}