diff --git a/lib/analyze-action-post.js b/lib/analyze-action-post.js index 75be56ced1..93a741ffb5 100644 --- a/lib/analyze-action-post.js +++ b/lib/analyze-action-post.js @@ -100540,8 +100540,8 @@ var require_follow_redirects = __commonJS({ } return parsed; } - function resolveUrl(relative, base) { - return useNativeURL ? new URL2(relative, base) : parseUrl2(url.resolve(base, relative)); + function resolveUrl(relative2, base) { + return useNativeURL ? new URL2(relative2, base) : parseUrl2(url.resolve(base, relative2)); } function validateUrl(input) { if (/^\[/.test(input.hostname) && !/^\[[:0-9a-f]+\]$/i.test(input.hostname)) { @@ -104424,8 +104424,8 @@ var require_readdir_glob = __commonJS({ useStat = true; } const filename = dir + "/" + name; - const relative = filename.slice(1); - const absolute = path7 + "/" + relative; + const relative2 = filename.slice(1); + const absolute = path7 + "/" + relative2; let stats = null; if (useStat || followSymlinks) { stats = await stat(absolute, followSymlinks); @@ -104437,12 +104437,12 @@ var require_readdir_glob = __commonJS({ stats = { isDirectory: () => false }; } if (stats.isDirectory()) { - if (!shouldSkip(relative)) { - yield { relative, absolute, stats }; + if (!shouldSkip(relative2)) { + yield { relative: relative2, absolute, stats }; yield* exploreWalkAsync(filename, path7, followSymlinks, useStat, shouldSkip, false); } } else { - yield { relative, absolute, stats }; + yield { relative: relative2, absolute, stats }; } } } @@ -104512,11 +104512,11 @@ var require_readdir_glob = __commonJS({ } setTimeout(() => this._next(), 0); } - _shouldSkipDirectory(relative) { - return this.skipMatchers.some((m) => m.match(relative)); + _shouldSkipDirectory(relative2) { + return this.skipMatchers.some((m) => m.match(relative2)); } - _fileMatches(relative, isDirectory) { - const file = relative + (isDirectory ? "/" : ""); + _fileMatches(relative2, isDirectory) { + const file = relative2 + (isDirectory ? "/" : ""); return (this.matchers.length === 0 || this.matchers.some((m) => m.match(file))) && !this.ignoreMatchers.some((m) => m.match(file)) && (!this.options.nodir || !isDirectory); } _next() { @@ -104525,16 +104525,16 @@ var require_readdir_glob = __commonJS({ if (!obj.done) { const isDirectory = obj.value.stats.isDirectory(); if (this._fileMatches(obj.value.relative, isDirectory)) { - let relative = obj.value.relative; + let relative2 = obj.value.relative; let absolute = obj.value.absolute; if (this.options.mark && isDirectory) { - relative += "/"; + relative2 += "/"; absolute += "/"; } if (this.options.stat) { - this.emit("match", { relative, absolute, stat: obj.value.stats }); + this.emit("match", { relative: relative2, absolute, stat: obj.value.stats }); } else { - this.emit("match", { relative, absolute }); + this.emit("match", { relative: relative2, absolute }); } } this._next(this.iterator); @@ -110019,8 +110019,8 @@ var require_primordials = __commonJS({ ArrayPrototypeIndexOf(self2, el) { return self2.indexOf(el); }, - ArrayPrototypeJoin(self2, sep3) { - return self2.join(sep3); + ArrayPrototypeJoin(self2, sep4) { + return self2.join(sep4); }, ArrayPrototypeMap(self2, fn) { return self2.map(fn); @@ -122273,7 +122273,7 @@ var require_commonjs23 = __commonJS({ * * @internal */ - constructor(cwd = process.cwd(), pathImpl, sep3, { nocase, childrenCacheSize = 16 * 1024, fs: fs8 = defaultFS } = {}) { + constructor(cwd = process.cwd(), pathImpl, sep4, { nocase, childrenCacheSize = 16 * 1024, fs: fs8 = defaultFS } = {}) { this.#fs = fsFromOption(fs8); if (cwd instanceof URL || cwd.startsWith("file://")) { cwd = (0, node_url_1.fileURLToPath)(cwd); @@ -122284,7 +122284,7 @@ var require_commonjs23 = __commonJS({ this.#resolveCache = new ResolveCache(); this.#resolvePosixCache = new ResolveCache(); this.#children = new ChildrenCache(childrenCacheSize); - const split = cwdPath.substring(this.rootPath.length).split(sep3); + const split = cwdPath.substring(this.rootPath.length).split(sep4); if (split.length === 1 && !split[0]) { split.pop(); } @@ -123127,10 +123127,10 @@ var require_ignore = __commonJS({ ignored(p) { const fullpath = p.fullpath(); const fullpaths = `${fullpath}/`; - const relative = p.relative() || "."; - const relatives = `${relative}/`; + const relative2 = p.relative() || "."; + const relatives = `${relative2}/`; for (const m of this.relative) { - if (m.match(relative) || m.match(relatives)) + if (m.match(relative2) || m.match(relatives)) return true; } for (const m of this.absolute) { @@ -123141,9 +123141,9 @@ var require_ignore = __commonJS({ } childrenIgnored(p) { const fullpath = p.fullpath() + "/"; - const relative = (p.relative() || ".") + "/"; + const relative2 = (p.relative() || ".") + "/"; for (const m of this.relativeChildren) { - if (m.match(relative)) + if (m.match(relative2)) return true; } for (const m of this.absoluteChildren) { @@ -162155,6 +162155,18 @@ var decodeGitFilePath = function(filePath) { } return filePath; }; +var getGitRoot = async function(sourceRoot) { + try { + const stdout = await runGitCommand( + sourceRoot, + ["rev-parse", "--show-toplevel"], + `Cannot find Git repository root from the source root ${sourceRoot}.` + ); + return stdout.trim(); + } catch { + return void 0; + } +}; var getFileOidsUnderPath = async function(basePath) { const stdout = await runGitCommand( basePath, @@ -162277,10 +162289,12 @@ async function readBaseDatabaseOidsFile(config, logger) { async function writeOverlayChangesFile(config, sourceRoot, logger) { const baseFileOids = await readBaseDatabaseOidsFile(config, logger); const overlayFileOids = await getFileOidsUnderPath(sourceRoot); - const changedFiles = computeChangedFiles(baseFileOids, overlayFileOids); + const oidChangedFiles = computeChangedFiles(baseFileOids, overlayFileOids); logger.info( - `Found ${changedFiles.length} changed file(s) under ${sourceRoot}.` + `Found ${oidChangedFiles.length} changed file(s) under ${sourceRoot} from OID comparison.` ); + const diffRangeFiles = await getDiffRangeFilePaths(sourceRoot, logger); + const changedFiles = [.../* @__PURE__ */ new Set([...oidChangedFiles, ...diffRangeFiles])]; const changedFilesJson = JSON.stringify({ changes: changedFiles }); const overlayChangesFile = path2.join( getTemporaryDirectory(), @@ -162306,6 +162320,48 @@ function computeChangedFiles(baseFileOids, overlayFileOids) { } return changes; } +async function getDiffRangeFilePaths(sourceRoot, logger) { + const jsonFilePath = path2.join(getTemporaryDirectory(), "pr-diff-range.json"); + if (!fs2.existsSync(jsonFilePath)) { + return []; + } + let diffRanges; + try { + diffRanges = JSON.parse(fs2.readFileSync(jsonFilePath, "utf8")); + } catch (e) { + logger.warning( + `Failed to parse diff ranges JSON file at ${jsonFilePath}: ${e}` + ); + return []; + } + logger.debug( + `Read ${diffRanges.length} diff range(s) from ${jsonFilePath} for overlay changes.` + ); + const repoRelativePaths = [...new Set(diffRanges.map((r) => r.path))]; + const repoRoot = await getGitRoot(sourceRoot); + if (repoRoot === void 0) { + logger.warning( + "Cannot determine git root; returning diff range paths as-is." + ); + return repoRelativePaths; + } + const sourceRootRelPrefix = path2.relative(repoRoot, sourceRoot).replaceAll(path2.sep, "/"); + if (sourceRootRelPrefix === "") { + return repoRelativePaths; + } + const prefixWithSlash = `${sourceRootRelPrefix}/`; + const result = []; + for (const p of repoRelativePaths) { + if (p.startsWith(prefixWithSlash)) { + result.push(p.slice(prefixWithSlash.length)); + } else { + logger.debug( + `Skipping diff range path "${p}" (not under source root "${sourceRootRelPrefix}").` + ); + } + } + return result; +} // src/tools-features.ts var semver4 = __toESM(require_semver2()); diff --git a/lib/analyze-action.js b/lib/analyze-action.js index 268cfad571..c3e3a37c9a 100644 --- a/lib/analyze-action.js +++ b/lib/analyze-action.js @@ -100540,8 +100540,8 @@ var require_follow_redirects = __commonJS({ } return parsed; } - function resolveUrl(relative2, base) { - return useNativeURL ? new URL2(relative2, base) : parseUrl2(url2.resolve(base, relative2)); + function resolveUrl(relative3, base) { + return useNativeURL ? new URL2(relative3, base) : parseUrl2(url2.resolve(base, relative3)); } function validateUrl(input) { if (/^\[/.test(input.hostname) && !/^\[[:0-9a-f]+\]$/i.test(input.hostname)) { @@ -106859,29 +106859,6 @@ var persistInputs = function() { ); core4.saveState(persistedInputsKey, JSON.stringify(inputEnvironmentVariables)); }; -function getPullRequestBranches() { - const pullRequest = github.context.payload.pull_request; - if (pullRequest) { - return { - base: pullRequest.base.ref, - // We use the head label instead of the head ref here, because the head - // ref lacks owner information and by itself does not uniquely identify - // the head branch (which may be in a forked repository). - head: pullRequest.head.label - }; - } - const codeScanningRef = process.env.CODE_SCANNING_REF; - const codeScanningBaseBranch = process.env.CODE_SCANNING_BASE_BRANCH; - if (codeScanningRef && codeScanningBaseBranch) { - return { - base: codeScanningBaseBranch, - // PR analysis under Default Setup analyzes the PR head commit instead of - // the merge commit, so we can use the provided ref directly. - head: codeScanningRef - }; - } - return void 0; -} var qualityCategoryMapping = { "c#": "csharp", cpp: "c-cpp", @@ -107775,6 +107752,18 @@ var decodeGitFilePath = function(filePath) { } return filePath; }; +var getGitRoot = async function(sourceRoot) { + try { + const stdout = await runGitCommand( + sourceRoot, + ["rev-parse", "--show-toplevel"], + `Cannot find Git repository root from the source root ${sourceRoot}.` + ); + return stdout.trim(); + } catch { + return void 0; + } +}; var getFileOidsUnderPath = async function(basePath) { const stdout = await runGitCommand( basePath, @@ -107897,10 +107886,12 @@ async function readBaseDatabaseOidsFile(config, logger) { async function writeOverlayChangesFile(config, sourceRoot, logger) { const baseFileOids = await readBaseDatabaseOidsFile(config, logger); const overlayFileOids = await getFileOidsUnderPath(sourceRoot); - const changedFiles = computeChangedFiles(baseFileOids, overlayFileOids); + const oidChangedFiles = computeChangedFiles(baseFileOids, overlayFileOids); logger.info( - `Found ${changedFiles.length} changed file(s) under ${sourceRoot}.` + `Found ${oidChangedFiles.length} changed file(s) under ${sourceRoot} from OID comparison.` ); + const diffRangeFiles = await getDiffRangeFilePaths(sourceRoot, logger); + const changedFiles = [.../* @__PURE__ */ new Set([...oidChangedFiles, ...diffRangeFiles])]; const changedFilesJson = JSON.stringify({ changes: changedFiles }); const overlayChangesFile = path4.join( getTemporaryDirectory(), @@ -107926,6 +107917,48 @@ function computeChangedFiles(baseFileOids, overlayFileOids) { } return changes; } +async function getDiffRangeFilePaths(sourceRoot, logger) { + const jsonFilePath = path4.join(getTemporaryDirectory(), "pr-diff-range.json"); + if (!fs3.existsSync(jsonFilePath)) { + return []; + } + let diffRanges; + try { + diffRanges = JSON.parse(fs3.readFileSync(jsonFilePath, "utf8")); + } catch (e) { + logger.warning( + `Failed to parse diff ranges JSON file at ${jsonFilePath}: ${e}` + ); + return []; + } + logger.debug( + `Read ${diffRanges.length} diff range(s) from ${jsonFilePath} for overlay changes.` + ); + const repoRelativePaths = [...new Set(diffRanges.map((r) => r.path))]; + const repoRoot = await getGitRoot(sourceRoot); + if (repoRoot === void 0) { + logger.warning( + "Cannot determine git root; returning diff range paths as-is." + ); + return repoRelativePaths; + } + const sourceRootRelPrefix = path4.relative(repoRoot, sourceRoot).replaceAll(path4.sep, "/"); + if (sourceRootRelPrefix === "") { + return repoRelativePaths; + } + const prefixWithSlash = `${sourceRootRelPrefix}/`; + const result = []; + for (const p of repoRelativePaths) { + if (p.startsWith(prefixWithSlash)) { + result.push(p.slice(prefixWithSlash.length)); + } else { + logger.debug( + `Skipping diff range path "${p}" (not under source root "${sourceRootRelPrefix}").` + ); + } + } + return result; +} var CACHE_VERSION = 1; var CACHE_PREFIX = "codeql-overlay-base-database"; var MAX_CACHE_OPERATION_MS = 6e5; @@ -108611,34 +108644,9 @@ function initFeatures(gitHubVersion, repositoryNwo, tempDir, logger) { } // src/diff-informed-analysis-utils.ts -async function getDiffInformedAnalysisBranches(codeql, features, logger) { - if (!await features.getValue("diff_informed_queries" /* DiffInformedQueries */, codeql)) { - return void 0; - } - const gitHubVersion = await getGitHubVersion(); - if (gitHubVersion.type === "GitHub Enterprise Server" /* GHES */ && satisfiesGHESVersion(gitHubVersion.version, "<3.19", true)) { - return void 0; - } - const branches = getPullRequestBranches(); - if (!branches) { - logger.info( - "Not performing diff-informed analysis because we are not analyzing a pull request." - ); - } - return branches; -} function getDiffRangesJsonFilePath() { return path6.join(getTemporaryDirectory(), "pr-diff-range.json"); } -function writeDiffRangesJsonFile(logger, ranges) { - const jsonContents = JSON.stringify(ranges, null, 2); - const jsonFilePath = getDiffRangesJsonFilePath(); - fs5.writeFileSync(jsonFilePath, jsonContents); - logger.debug( - `Wrote pr-diff-range JSON file to ${jsonFilePath}: -${jsonContents}` - ); -} function readDiffRangesJsonFile(logger) { const jsonFilePath = getDiffRangesJsonFilePath(); if (!fs5.existsSync(jsonFilePath)) { @@ -108650,117 +108658,14 @@ function readDiffRangesJsonFile(logger) { `Read pr-diff-range JSON file from ${jsonFilePath}: ${jsonContents}` ); - return JSON.parse(jsonContents); -} -async function getPullRequestEditedDiffRanges(branches, logger) { - const fileDiffs = await getFileDiffsWithBasehead(branches, logger); - if (fileDiffs === void 0) { - return void 0; - } - if (fileDiffs.length >= 300) { + try { + return JSON.parse(jsonContents); + } catch (e) { logger.warning( - `Cannot retrieve the full diff because there are too many (${fileDiffs.length}) changed files in the pull request.` + `Failed to parse diff ranges JSON file at ${jsonFilePath}: ${e}` ); return void 0; } - const results = []; - for (const filediff of fileDiffs) { - const diffRanges = getDiffRanges(filediff, logger); - if (diffRanges === void 0) { - return void 0; - } - results.push(...diffRanges); - } - return results; -} -async function getFileDiffsWithBasehead(branches, logger) { - const repositoryNwo = getRepositoryNwoFromEnv( - "CODE_SCANNING_REPOSITORY", - "GITHUB_REPOSITORY" - ); - const basehead = `${branches.base}...${branches.head}`; - try { - const response = await getApiClient().rest.repos.compareCommitsWithBasehead( - { - owner: repositoryNwo.owner, - repo: repositoryNwo.repo, - basehead, - per_page: 1 - } - ); - logger.debug( - `Response from compareCommitsWithBasehead(${basehead}): -${JSON.stringify(response, null, 2)}` - ); - return response.data.files; - } catch (error3) { - if (error3.status) { - logger.warning(`Error retrieving diff ${basehead}: ${error3.message}`); - logger.debug( - `Error running compareCommitsWithBasehead(${basehead}): -Request: ${JSON.stringify(error3.request, null, 2)} -Error Response: ${JSON.stringify(error3.response, null, 2)}` - ); - return void 0; - } else { - throw error3; - } - } -} -function getDiffRanges(fileDiff, logger) { - if (fileDiff.patch === void 0) { - if (fileDiff.changes === 0) { - return []; - } - return [ - { - path: fileDiff.filename, - startLine: 0, - endLine: 0 - } - ]; - } - let currentLine = 0; - let additionRangeStartLine = void 0; - const diffRanges = []; - const diffLines = fileDiff.patch.split("\n"); - diffLines.push(" "); - for (const diffLine of diffLines) { - if (diffLine.startsWith("-")) { - continue; - } - if (diffLine.startsWith("+")) { - if (additionRangeStartLine === void 0) { - additionRangeStartLine = currentLine; - } - currentLine++; - continue; - } - if (additionRangeStartLine !== void 0) { - diffRanges.push({ - path: fileDiff.filename, - startLine: additionRangeStartLine, - endLine: currentLine - 1 - }); - additionRangeStartLine = void 0; - } - if (diffLine.startsWith("@@ ")) { - const match = diffLine.match(/^@@ -\d+(?:,\d+)? \+(\d+)(?:,\d+)? @@/); - if (match === null) { - logger.warning( - `Cannot parse diff hunk header for ${fileDiff.filename}: ${diffLine}` - ); - return void 0; - } - currentLine = parseInt(match[1], 10); - continue; - } - if (diffLine.startsWith(" ")) { - currentLine++; - continue; - } - } - return diffRanges; } // src/overlay/status.ts @@ -110915,14 +110820,17 @@ async function finalizeDatabaseCreation(codeql, features, config, threadsFlag, m trap_import_duration_ms: Math.round(trapImportTime) }; } -async function setupDiffInformedQueryRun(branches, logger) { +async function setupDiffInformedQueryRun(logger) { return await withGroupAsync( "Generating diff range extension pack", async () => { - logger.info( - `Calculating diff ranges for ${branches.base}...${branches.head}` - ); - const diffRanges = await getPullRequestEditedDiffRanges(branches, logger); + const diffRanges = readDiffRangesJsonFile(logger); + if (diffRanges === void 0) { + logger.info( + "No precomputed diff ranges found; skipping diff-informed analysis stage." + ); + return void 0; + } const checkoutPath = getRequiredInput("checkout_path"); const packDir = writeDiffRangeDataExtensionPack( logger, @@ -110992,7 +110900,6 @@ dataExtensions: `Wrote pr-diff-range extension pack to ${extensionFilePath}: ${extensionContents}` ); - writeDiffRangesJsonFile(logger, ranges); return diffRangeDir; } var defaultSuites = /* @__PURE__ */ new Set([ @@ -113544,12 +113451,7 @@ async function run(startedAt2) { getOptionalInput("ram") || process.env["CODEQL_RAM"], logger ); - const branches = await getDiffInformedAnalysisBranches( - codeql, - features, - logger - ); - const diffRangePackDir = branches ? await setupDiffInformedQueryRun(branches, logger) : void 0; + const diffRangePackDir = await setupDiffInformedQueryRun(logger); await warnIfGoInstalledAfterInit(config, logger); await runAutobuildIfLegacyGoWorkflow(config, logger); dbCreationTimings = await runFinalize( diff --git a/lib/autobuild-action.js b/lib/autobuild-action.js index 7720f03cb0..8b416c8d6a 100644 --- a/lib/autobuild-action.js +++ b/lib/autobuild-action.js @@ -100540,8 +100540,8 @@ var require_follow_redirects = __commonJS({ } return parsed; } - function resolveUrl(relative, base) { - return useNativeURL ? new URL2(relative, base) : parseUrl2(url.resolve(base, relative)); + function resolveUrl(relative2, base) { + return useNativeURL ? new URL2(relative2, base) : parseUrl2(url.resolve(base, relative2)); } function validateUrl(input) { if (/^\[/.test(input.hostname) && !/^\[[:0-9a-f]+\]$/i.test(input.hostname)) { @@ -104209,6 +104209,18 @@ var decodeGitFilePath = function(filePath) { } return filePath; }; +var getGitRoot = async function(sourceRoot) { + try { + const stdout = await runGitCommand( + sourceRoot, + ["rev-parse", "--show-toplevel"], + `Cannot find Git repository root from the source root ${sourceRoot}.` + ); + return stdout.trim(); + } catch { + return void 0; + } +}; var getFileOidsUnderPath = async function(basePath) { const stdout = await runGitCommand( basePath, @@ -104331,10 +104343,12 @@ async function readBaseDatabaseOidsFile(config, logger) { async function writeOverlayChangesFile(config, sourceRoot, logger) { const baseFileOids = await readBaseDatabaseOidsFile(config, logger); const overlayFileOids = await getFileOidsUnderPath(sourceRoot); - const changedFiles = computeChangedFiles(baseFileOids, overlayFileOids); + const oidChangedFiles = computeChangedFiles(baseFileOids, overlayFileOids); logger.info( - `Found ${changedFiles.length} changed file(s) under ${sourceRoot}.` + `Found ${oidChangedFiles.length} changed file(s) under ${sourceRoot} from OID comparison.` ); + const diffRangeFiles = await getDiffRangeFilePaths(sourceRoot, logger); + const changedFiles = [.../* @__PURE__ */ new Set([...oidChangedFiles, ...diffRangeFiles])]; const changedFilesJson = JSON.stringify({ changes: changedFiles }); const overlayChangesFile = path2.join( getTemporaryDirectory(), @@ -104360,6 +104374,48 @@ function computeChangedFiles(baseFileOids, overlayFileOids) { } return changes; } +async function getDiffRangeFilePaths(sourceRoot, logger) { + const jsonFilePath = path2.join(getTemporaryDirectory(), "pr-diff-range.json"); + if (!fs2.existsSync(jsonFilePath)) { + return []; + } + let diffRanges; + try { + diffRanges = JSON.parse(fs2.readFileSync(jsonFilePath, "utf8")); + } catch (e) { + logger.warning( + `Failed to parse diff ranges JSON file at ${jsonFilePath}: ${e}` + ); + return []; + } + logger.debug( + `Read ${diffRanges.length} diff range(s) from ${jsonFilePath} for overlay changes.` + ); + const repoRelativePaths = [...new Set(diffRanges.map((r) => r.path))]; + const repoRoot = await getGitRoot(sourceRoot); + if (repoRoot === void 0) { + logger.warning( + "Cannot determine git root; returning diff range paths as-is." + ); + return repoRelativePaths; + } + const sourceRootRelPrefix = path2.relative(repoRoot, sourceRoot).replaceAll(path2.sep, "/"); + if (sourceRootRelPrefix === "") { + return repoRelativePaths; + } + const prefixWithSlash = `${sourceRootRelPrefix}/`; + const result = []; + for (const p of repoRelativePaths) { + if (p.startsWith(prefixWithSlash)) { + result.push(p.slice(prefixWithSlash.length)); + } else { + logger.debug( + `Skipping diff range path "${p}" (not under source root "${sourceRootRelPrefix}").` + ); + } + } + return result; +} // src/tools-features.ts var semver4 = __toESM(require_semver2()); diff --git a/lib/init-action-post.js b/lib/init-action-post.js index 341449f7e1..2015196f6b 100644 --- a/lib/init-action-post.js +++ b/lib/init-action-post.js @@ -100540,8 +100540,8 @@ var require_follow_redirects = __commonJS({ } return parsed; } - function resolveUrl(relative2, base) { - return useNativeURL ? new URL2(relative2, base) : parseUrl2(url2.resolve(base, relative2)); + function resolveUrl(relative3, base) { + return useNativeURL ? new URL2(relative3, base) : parseUrl2(url2.resolve(base, relative3)); } function validateUrl(input) { if (/^\[/.test(input.hostname) && !/^\[[:0-9a-f]+\]$/i.test(input.hostname)) { @@ -104424,8 +104424,8 @@ var require_readdir_glob = __commonJS({ useStat = true; } const filename = dir + "/" + name; - const relative2 = filename.slice(1); - const absolute = path19 + "/" + relative2; + const relative3 = filename.slice(1); + const absolute = path19 + "/" + relative3; let stats = null; if (useStat || followSymlinks) { stats = await stat(absolute, followSymlinks); @@ -104437,12 +104437,12 @@ var require_readdir_glob = __commonJS({ stats = { isDirectory: () => false }; } if (stats.isDirectory()) { - if (!shouldSkip(relative2)) { - yield { relative: relative2, absolute, stats }; + if (!shouldSkip(relative3)) { + yield { relative: relative3, absolute, stats }; yield* exploreWalkAsync(filename, path19, followSymlinks, useStat, shouldSkip, false); } } else { - yield { relative: relative2, absolute, stats }; + yield { relative: relative3, absolute, stats }; } } } @@ -104512,11 +104512,11 @@ var require_readdir_glob = __commonJS({ } setTimeout(() => this._next(), 0); } - _shouldSkipDirectory(relative2) { - return this.skipMatchers.some((m) => m.match(relative2)); + _shouldSkipDirectory(relative3) { + return this.skipMatchers.some((m) => m.match(relative3)); } - _fileMatches(relative2, isDirectory) { - const file = relative2 + (isDirectory ? "/" : ""); + _fileMatches(relative3, isDirectory) { + const file = relative3 + (isDirectory ? "/" : ""); return (this.matchers.length === 0 || this.matchers.some((m) => m.match(file))) && !this.ignoreMatchers.some((m) => m.match(file)) && (!this.options.nodir || !isDirectory); } _next() { @@ -104525,16 +104525,16 @@ var require_readdir_glob = __commonJS({ if (!obj.done) { const isDirectory = obj.value.stats.isDirectory(); if (this._fileMatches(obj.value.relative, isDirectory)) { - let relative2 = obj.value.relative; + let relative3 = obj.value.relative; let absolute = obj.value.absolute; if (this.options.mark && isDirectory) { - relative2 += "/"; + relative3 += "/"; absolute += "/"; } if (this.options.stat) { - this.emit("match", { relative: relative2, absolute, stat: obj.value.stats }); + this.emit("match", { relative: relative3, absolute, stat: obj.value.stats }); } else { - this.emit("match", { relative: relative2, absolute }); + this.emit("match", { relative: relative3, absolute }); } } this._next(this.iterator); @@ -110019,8 +110019,8 @@ var require_primordials = __commonJS({ ArrayPrototypeIndexOf(self2, el) { return self2.indexOf(el); }, - ArrayPrototypeJoin(self2, sep4) { - return self2.join(sep4); + ArrayPrototypeJoin(self2, sep5) { + return self2.join(sep5); }, ArrayPrototypeMap(self2, fn) { return self2.map(fn); @@ -122273,7 +122273,7 @@ var require_commonjs23 = __commonJS({ * * @internal */ - constructor(cwd = process.cwd(), pathImpl, sep4, { nocase, childrenCacheSize = 16 * 1024, fs: fs20 = defaultFS } = {}) { + constructor(cwd = process.cwd(), pathImpl, sep5, { nocase, childrenCacheSize = 16 * 1024, fs: fs20 = defaultFS } = {}) { this.#fs = fsFromOption(fs20); if (cwd instanceof URL || cwd.startsWith("file://")) { cwd = (0, node_url_1.fileURLToPath)(cwd); @@ -122284,7 +122284,7 @@ var require_commonjs23 = __commonJS({ this.#resolveCache = new ResolveCache(); this.#resolvePosixCache = new ResolveCache(); this.#children = new ChildrenCache(childrenCacheSize); - const split = cwdPath.substring(this.rootPath.length).split(sep4); + const split = cwdPath.substring(this.rootPath.length).split(sep5); if (split.length === 1 && !split[0]) { split.pop(); } @@ -123127,10 +123127,10 @@ var require_ignore = __commonJS({ ignored(p) { const fullpath = p.fullpath(); const fullpaths = `${fullpath}/`; - const relative2 = p.relative() || "."; - const relatives = `${relative2}/`; + const relative3 = p.relative() || "."; + const relatives = `${relative3}/`; for (const m of this.relative) { - if (m.match(relative2) || m.match(relatives)) + if (m.match(relative3) || m.match(relatives)) return true; } for (const m of this.absolute) { @@ -123141,9 +123141,9 @@ var require_ignore = __commonJS({ } childrenIgnored(p) { const fullpath = p.fullpath() + "/"; - const relative2 = (p.relative() || ".") + "/"; + const relative3 = (p.relative() || ".") + "/"; for (const m of this.relativeChildren) { - if (m.match(relative2)) + if (m.match(relative3)) return true; } for (const m of this.absoluteChildren) { @@ -165669,6 +165669,18 @@ var decodeGitFilePath = function(filePath) { } return filePath; }; +var getGitRoot = async function(sourceRoot) { + try { + const stdout = await runGitCommand( + sourceRoot, + ["rev-parse", "--show-toplevel"], + `Cannot find Git repository root from the source root ${sourceRoot}.` + ); + return stdout.trim(); + } catch { + return void 0; + } +}; var getFileOidsUnderPath = async function(basePath) { const stdout = await runGitCommand( basePath, @@ -165791,10 +165803,12 @@ async function readBaseDatabaseOidsFile(config, logger) { async function writeOverlayChangesFile(config, sourceRoot, logger) { const baseFileOids = await readBaseDatabaseOidsFile(config, logger); const overlayFileOids = await getFileOidsUnderPath(sourceRoot); - const changedFiles = computeChangedFiles(baseFileOids, overlayFileOids); + const oidChangedFiles = computeChangedFiles(baseFileOids, overlayFileOids); logger.info( - `Found ${changedFiles.length} changed file(s) under ${sourceRoot}.` + `Found ${oidChangedFiles.length} changed file(s) under ${sourceRoot} from OID comparison.` ); + const diffRangeFiles = await getDiffRangeFilePaths(sourceRoot, logger); + const changedFiles = [.../* @__PURE__ */ new Set([...oidChangedFiles, ...diffRangeFiles])]; const changedFilesJson = JSON.stringify({ changes: changedFiles }); const overlayChangesFile = path4.join( getTemporaryDirectory(), @@ -165820,6 +165834,48 @@ function computeChangedFiles(baseFileOids, overlayFileOids) { } return changes; } +async function getDiffRangeFilePaths(sourceRoot, logger) { + const jsonFilePath = path4.join(getTemporaryDirectory(), "pr-diff-range.json"); + if (!fs3.existsSync(jsonFilePath)) { + return []; + } + let diffRanges; + try { + diffRanges = JSON.parse(fs3.readFileSync(jsonFilePath, "utf8")); + } catch (e) { + logger.warning( + `Failed to parse diff ranges JSON file at ${jsonFilePath}: ${e}` + ); + return []; + } + logger.debug( + `Read ${diffRanges.length} diff range(s) from ${jsonFilePath} for overlay changes.` + ); + const repoRelativePaths = [...new Set(diffRanges.map((r) => r.path))]; + const repoRoot = await getGitRoot(sourceRoot); + if (repoRoot === void 0) { + logger.warning( + "Cannot determine git root; returning diff range paths as-is." + ); + return repoRelativePaths; + } + const sourceRootRelPrefix = path4.relative(repoRoot, sourceRoot).replaceAll(path4.sep, "/"); + if (sourceRootRelPrefix === "") { + return repoRelativePaths; + } + const prefixWithSlash = `${sourceRootRelPrefix}/`; + const result = []; + for (const p of repoRelativePaths) { + if (p.startsWith(prefixWithSlash)) { + result.push(p.slice(prefixWithSlash.length)); + } else { + logger.debug( + `Skipping diff range path "${p}" (not under source root "${sourceRootRelPrefix}").` + ); + } + } + return result; +} // src/tools-features.ts var semver4 = __toESM(require_semver2()); @@ -166388,7 +166444,14 @@ function readDiffRangesJsonFile(logger) { `Read pr-diff-range JSON file from ${jsonFilePath}: ${jsonContents}` ); - return JSON.parse(jsonContents); + try { + return JSON.parse(jsonContents); + } catch (e) { + logger.warning( + `Failed to parse diff ranges JSON file at ${jsonFilePath}: ${e}` + ); + return void 0; + } } // src/overlay/status.ts diff --git a/lib/init-action.js b/lib/init-action.js index ec26268cb9..8ebb9ac658 100644 --- a/lib/init-action.js +++ b/lib/init-action.js @@ -204,7 +204,7 @@ var require_file_command = __commonJS({ exports2.issueFileCommand = issueFileCommand; exports2.prepareKeyValueMessage = prepareKeyValueMessage; var crypto3 = __importStar2(require("crypto")); - var fs16 = __importStar2(require("fs")); + var fs17 = __importStar2(require("fs")); var os6 = __importStar2(require("os")); var utils_1 = require_utils(); function issueFileCommand(command, message) { @@ -212,10 +212,10 @@ var require_file_command = __commonJS({ if (!filePath) { throw new Error(`Unable to find environment variable for file command ${command}`); } - if (!fs16.existsSync(filePath)) { + if (!fs17.existsSync(filePath)) { throw new Error(`Missing file at path: ${filePath}`); } - fs16.appendFileSync(filePath, `${(0, utils_1.toCommandValue)(message)}${os6.EOL}`, { + fs17.appendFileSync(filePath, `${(0, utils_1.toCommandValue)(message)}${os6.EOL}`, { encoding: "utf8" }); } @@ -1337,14 +1337,14 @@ var require_util = __commonJS({ } const port = url.port != null ? url.port : url.protocol === "https:" ? 443 : 80; let origin = url.origin != null ? url.origin : `${url.protocol || ""}//${url.hostname || ""}:${port}`; - let path17 = url.path != null ? url.path : `${url.pathname || ""}${url.search || ""}`; + let path18 = url.path != null ? url.path : `${url.pathname || ""}${url.search || ""}`; if (origin[origin.length - 1] === "/") { origin = origin.slice(0, origin.length - 1); } - if (path17 && path17[0] !== "/") { - path17 = `/${path17}`; + if (path18 && path18[0] !== "/") { + path18 = `/${path18}`; } - return new URL(`${origin}${path17}`); + return new URL(`${origin}${path18}`); } if (!isHttpOrHttpsPrefixed(url.origin || url.protocol)) { throw new InvalidArgumentError("Invalid URL protocol: the URL must start with `http:` or `https:`."); @@ -1795,39 +1795,39 @@ var require_diagnostics = __commonJS({ }); diagnosticsChannel.channel("undici:client:sendHeaders").subscribe((evt) => { const { - request: { method, path: path17, origin } + request: { method, path: path18, origin } } = evt; - debuglog("sending request to %s %s/%s", method, origin, path17); + debuglog("sending request to %s %s/%s", method, origin, path18); }); diagnosticsChannel.channel("undici:request:headers").subscribe((evt) => { const { - request: { method, path: path17, origin }, + request: { method, path: path18, origin }, response: { statusCode } } = evt; debuglog( "received response to %s %s/%s - HTTP %d", method, origin, - path17, + path18, statusCode ); }); diagnosticsChannel.channel("undici:request:trailers").subscribe((evt) => { const { - request: { method, path: path17, origin } + request: { method, path: path18, origin } } = evt; - debuglog("trailers received from %s %s/%s", method, origin, path17); + debuglog("trailers received from %s %s/%s", method, origin, path18); }); diagnosticsChannel.channel("undici:request:error").subscribe((evt) => { const { - request: { method, path: path17, origin }, + request: { method, path: path18, origin }, error: error3 } = evt; debuglog( "request to %s %s/%s errored - %s", method, origin, - path17, + path18, error3.message ); }); @@ -1876,9 +1876,9 @@ var require_diagnostics = __commonJS({ }); diagnosticsChannel.channel("undici:client:sendHeaders").subscribe((evt) => { const { - request: { method, path: path17, origin } + request: { method, path: path18, origin } } = evt; - debuglog("sending request to %s %s/%s", method, origin, path17); + debuglog("sending request to %s %s/%s", method, origin, path18); }); } diagnosticsChannel.channel("undici:websocket:open").subscribe((evt) => { @@ -1941,7 +1941,7 @@ var require_request = __commonJS({ var kHandler = /* @__PURE__ */ Symbol("handler"); var Request = class { constructor(origin, { - path: path17, + path: path18, method, body, headers, @@ -1956,11 +1956,11 @@ var require_request = __commonJS({ expectContinue, servername }, handler2) { - if (typeof path17 !== "string") { + if (typeof path18 !== "string") { throw new InvalidArgumentError("path must be a string"); - } else if (path17[0] !== "/" && !(path17.startsWith("http://") || path17.startsWith("https://")) && method !== "CONNECT") { + } else if (path18[0] !== "/" && !(path18.startsWith("http://") || path18.startsWith("https://")) && method !== "CONNECT") { throw new InvalidArgumentError("path must be an absolute URL or start with a slash"); - } else if (invalidPathRegex.test(path17)) { + } else if (invalidPathRegex.test(path18)) { throw new InvalidArgumentError("invalid request path"); } if (typeof method !== "string") { @@ -2023,7 +2023,7 @@ var require_request = __commonJS({ this.completed = false; this.aborted = false; this.upgrade = upgrade || null; - this.path = query ? buildURL(path17, query) : path17; + this.path = query ? buildURL(path18, query) : path18; this.origin = origin; this.idempotent = idempotent == null ? method === "HEAD" || method === "GET" : idempotent; this.blocking = blocking == null ? false : blocking; @@ -6536,7 +6536,7 @@ var require_client_h1 = __commonJS({ return method !== "GET" && method !== "HEAD" && method !== "OPTIONS" && method !== "TRACE" && method !== "CONNECT"; } function writeH1(client, request2) { - const { method, path: path17, host, upgrade, blocking, reset } = request2; + const { method, path: path18, host, upgrade, blocking, reset } = request2; let { body, headers, contentLength } = request2; const expectsPayload = method === "PUT" || method === "POST" || method === "PATCH" || method === "QUERY" || method === "PROPFIND" || method === "PROPPATCH"; if (util.isFormDataLike(body)) { @@ -6602,7 +6602,7 @@ var require_client_h1 = __commonJS({ if (blocking) { socket[kBlocking] = true; } - let header = `${method} ${path17} HTTP/1.1\r + let header = `${method} ${path18} HTTP/1.1\r `; if (typeof host === "string") { header += `host: ${host}\r @@ -7128,7 +7128,7 @@ var require_client_h2 = __commonJS({ } function writeH2(client, request2) { const session = client[kHTTP2Session]; - const { method, path: path17, host, upgrade, expectContinue, signal, headers: reqHeaders } = request2; + const { method, path: path18, host, upgrade, expectContinue, signal, headers: reqHeaders } = request2; let { body } = request2; if (upgrade) { util.errorRequest(client, request2, new Error("Upgrade not supported for H2")); @@ -7195,7 +7195,7 @@ var require_client_h2 = __commonJS({ }); return true; } - headers[HTTP2_HEADER_PATH] = path17; + headers[HTTP2_HEADER_PATH] = path18; headers[HTTP2_HEADER_SCHEME] = "https"; const expectsPayload = method === "PUT" || method === "POST" || method === "PATCH"; if (body && typeof body.read === "function") { @@ -7548,9 +7548,9 @@ var require_redirect_handler = __commonJS({ return this.handler.onHeaders(statusCode, headers, resume, statusText); } const { origin, pathname, search } = util.parseURL(new URL(this.location, this.opts.origin && new URL(this.opts.path, this.opts.origin))); - const path17 = search ? `${pathname}${search}` : pathname; + const path18 = search ? `${pathname}${search}` : pathname; this.opts.headers = cleanRequestHeaders(this.opts.headers, statusCode === 303, this.opts.origin !== origin); - this.opts.path = path17; + this.opts.path = path18; this.opts.origin = origin; this.opts.maxRedirections = 0; this.opts.query = null; @@ -8784,10 +8784,10 @@ var require_proxy_agent = __commonJS({ }; const { origin, - path: path17 = "/", + path: path18 = "/", headers = {} } = opts; - opts.path = origin + path17; + opts.path = origin + path18; if (!("host" in headers) && !("Host" in headers)) { const { host } = new URL2(origin); headers.host = host; @@ -10708,20 +10708,20 @@ var require_mock_utils = __commonJS({ } return true; } - function safeUrl(path17) { - if (typeof path17 !== "string") { - return path17; + function safeUrl(path18) { + if (typeof path18 !== "string") { + return path18; } - const pathSegments = path17.split("?"); + const pathSegments = path18.split("?"); if (pathSegments.length !== 2) { - return path17; + return path18; } const qp = new URLSearchParams(pathSegments.pop()); qp.sort(); return [...pathSegments, qp.toString()].join("?"); } - function matchKey(mockDispatch2, { path: path17, method, body, headers }) { - const pathMatch = matchValue(mockDispatch2.path, path17); + function matchKey(mockDispatch2, { path: path18, method, body, headers }) { + const pathMatch = matchValue(mockDispatch2.path, path18); const methodMatch = matchValue(mockDispatch2.method, method); const bodyMatch = typeof mockDispatch2.body !== "undefined" ? matchValue(mockDispatch2.body, body) : true; const headersMatch = matchHeaders(mockDispatch2, headers); @@ -10743,7 +10743,7 @@ var require_mock_utils = __commonJS({ function getMockDispatch(mockDispatches, key) { const basePath = key.query ? buildURL(key.path, key.query) : key.path; const resolvedPath = typeof basePath === "string" ? safeUrl(basePath) : basePath; - let matchedMockDispatches = mockDispatches.filter(({ consumed }) => !consumed).filter(({ path: path17 }) => matchValue(safeUrl(path17), resolvedPath)); + let matchedMockDispatches = mockDispatches.filter(({ consumed }) => !consumed).filter(({ path: path18 }) => matchValue(safeUrl(path18), resolvedPath)); if (matchedMockDispatches.length === 0) { throw new MockNotMatchedError(`Mock dispatch not matched for path '${resolvedPath}'`); } @@ -10781,9 +10781,9 @@ var require_mock_utils = __commonJS({ } } function buildKey(opts) { - const { path: path17, method, body, headers, query } = opts; + const { path: path18, method, body, headers, query } = opts; return { - path: path17, + path: path18, method, body, headers, @@ -11246,10 +11246,10 @@ var require_pending_interceptors_formatter = __commonJS({ } format(pendingInterceptors) { const withPrettyHeaders = pendingInterceptors.map( - ({ method, path: path17, data: { statusCode }, persist, times, timesInvoked, origin }) => ({ + ({ method, path: path18, data: { statusCode }, persist, times, timesInvoked, origin }) => ({ Method: method, Origin: origin, - Path: path17, + Path: path18, "Status code": statusCode, Persistent: persist ? PERSISTENT : NOT_PERSISTENT, Invocations: timesInvoked, @@ -16130,9 +16130,9 @@ var require_util6 = __commonJS({ } } } - function validateCookiePath(path17) { - for (let i = 0; i < path17.length; ++i) { - const code = path17.charCodeAt(i); + function validateCookiePath(path18) { + for (let i = 0; i < path18.length; ++i) { + const code = path18.charCodeAt(i); if (code < 32 || // exclude CTLs (0-31) code === 127 || // DEL code === 59) { @@ -18726,11 +18726,11 @@ var require_undici = __commonJS({ if (typeof opts.path !== "string") { throw new InvalidArgumentError("invalid opts.path"); } - let path17 = opts.path; + let path18 = opts.path; if (!opts.path.startsWith("/")) { - path17 = `/${path17}`; + path18 = `/${path18}`; } - url = new URL(util.parseOrigin(url).origin + path17); + url = new URL(util.parseOrigin(url).origin + path18); } else { if (!opts) { opts = typeof url === "object" ? url : {}; @@ -20033,7 +20033,7 @@ var require_path_utils = __commonJS({ exports2.toPosixPath = toPosixPath; exports2.toWin32Path = toWin32Path; exports2.toPlatformPath = toPlatformPath; - var path17 = __importStar2(require("path")); + var path18 = __importStar2(require("path")); function toPosixPath(pth) { return pth.replace(/[\\]/g, "/"); } @@ -20041,7 +20041,7 @@ var require_path_utils = __commonJS({ return pth.replace(/[/]/g, "\\"); } function toPlatformPath(pth) { - return pth.replace(/[/\\]/g, path17.sep); + return pth.replace(/[/\\]/g, path18.sep); } } }); @@ -20123,13 +20123,13 @@ var require_io_util = __commonJS({ exports2.isRooted = isRooted; exports2.tryGetExecutablePath = tryGetExecutablePath; exports2.getCmdPath = getCmdPath; - var fs16 = __importStar2(require("fs")); - var path17 = __importStar2(require("path")); - _a = fs16.promises, exports2.chmod = _a.chmod, exports2.copyFile = _a.copyFile, exports2.lstat = _a.lstat, exports2.mkdir = _a.mkdir, exports2.open = _a.open, exports2.readdir = _a.readdir, exports2.rename = _a.rename, exports2.rm = _a.rm, exports2.rmdir = _a.rmdir, exports2.stat = _a.stat, exports2.symlink = _a.symlink, exports2.unlink = _a.unlink; + var fs17 = __importStar2(require("fs")); + var path18 = __importStar2(require("path")); + _a = fs17.promises, exports2.chmod = _a.chmod, exports2.copyFile = _a.copyFile, exports2.lstat = _a.lstat, exports2.mkdir = _a.mkdir, exports2.open = _a.open, exports2.readdir = _a.readdir, exports2.rename = _a.rename, exports2.rm = _a.rm, exports2.rmdir = _a.rmdir, exports2.stat = _a.stat, exports2.symlink = _a.symlink, exports2.unlink = _a.unlink; exports2.IS_WINDOWS = process.platform === "win32"; function readlink(fsPath) { return __awaiter2(this, void 0, void 0, function* () { - const result = yield fs16.promises.readlink(fsPath); + const result = yield fs17.promises.readlink(fsPath); if (exports2.IS_WINDOWS && !result.endsWith("\\")) { return `${result}\\`; } @@ -20137,7 +20137,7 @@ var require_io_util = __commonJS({ }); } exports2.UV_FS_O_EXLOCK = 268435456; - exports2.READONLY = fs16.constants.O_RDONLY; + exports2.READONLY = fs17.constants.O_RDONLY; function exists(fsPath) { return __awaiter2(this, void 0, void 0, function* () { try { @@ -20179,7 +20179,7 @@ var require_io_util = __commonJS({ } if (stats && stats.isFile()) { if (exports2.IS_WINDOWS) { - const upperExt = path17.extname(filePath).toUpperCase(); + const upperExt = path18.extname(filePath).toUpperCase(); if (extensions.some((validExt) => validExt.toUpperCase() === upperExt)) { return filePath; } @@ -20203,11 +20203,11 @@ var require_io_util = __commonJS({ if (stats && stats.isFile()) { if (exports2.IS_WINDOWS) { try { - const directory = path17.dirname(filePath); - const upperName = path17.basename(filePath).toUpperCase(); + const directory = path18.dirname(filePath); + const upperName = path18.basename(filePath).toUpperCase(); for (const actualName of yield (0, exports2.readdir)(directory)) { if (upperName === actualName.toUpperCase()) { - filePath = path17.join(directory, actualName); + filePath = path18.join(directory, actualName); break; } } @@ -20319,7 +20319,7 @@ var require_io = __commonJS({ exports2.which = which7; exports2.findInPath = findInPath; var assert_1 = require("assert"); - var path17 = __importStar2(require("path")); + var path18 = __importStar2(require("path")); var ioUtil = __importStar2(require_io_util()); function cp(source_1, dest_1) { return __awaiter2(this, arguments, void 0, function* (source, dest, options = {}) { @@ -20328,7 +20328,7 @@ var require_io = __commonJS({ if (destStat && destStat.isFile() && !force) { return; } - const newDest = destStat && destStat.isDirectory() && copySourceDirectory ? path17.join(dest, path17.basename(source)) : dest; + const newDest = destStat && destStat.isDirectory() && copySourceDirectory ? path18.join(dest, path18.basename(source)) : dest; if (!(yield ioUtil.exists(source))) { throw new Error(`no such file or directory: ${source}`); } @@ -20340,7 +20340,7 @@ var require_io = __commonJS({ yield cpDirRecursive(source, newDest, 0, force); } } else { - if (path17.relative(source, newDest) === "") { + if (path18.relative(source, newDest) === "") { throw new Error(`'${newDest}' and '${source}' are the same file`); } yield copyFile2(source, newDest, force); @@ -20352,7 +20352,7 @@ var require_io = __commonJS({ if (yield ioUtil.exists(dest)) { let destExists = true; if (yield ioUtil.isDirectory(dest)) { - dest = path17.join(dest, path17.basename(source)); + dest = path18.join(dest, path18.basename(source)); destExists = yield ioUtil.exists(dest); } if (destExists) { @@ -20363,7 +20363,7 @@ var require_io = __commonJS({ } } } - yield mkdirP(path17.dirname(dest)); + yield mkdirP(path18.dirname(dest)); yield ioUtil.rename(source, dest); }); } @@ -20422,7 +20422,7 @@ var require_io = __commonJS({ } const extensions = []; if (ioUtil.IS_WINDOWS && process.env["PATHEXT"]) { - for (const extension of process.env["PATHEXT"].split(path17.delimiter)) { + for (const extension of process.env["PATHEXT"].split(path18.delimiter)) { if (extension) { extensions.push(extension); } @@ -20435,12 +20435,12 @@ var require_io = __commonJS({ } return []; } - if (tool.includes(path17.sep)) { + if (tool.includes(path18.sep)) { return []; } const directories = []; if (process.env.PATH) { - for (const p of process.env.PATH.split(path17.delimiter)) { + for (const p of process.env.PATH.split(path18.delimiter)) { if (p) { directories.push(p); } @@ -20448,7 +20448,7 @@ var require_io = __commonJS({ } const matches = []; for (const directory of directories) { - const filePath = yield ioUtil.tryGetExecutablePath(path17.join(directory, tool), extensions); + const filePath = yield ioUtil.tryGetExecutablePath(path18.join(directory, tool), extensions); if (filePath) { matches.push(filePath); } @@ -20578,7 +20578,7 @@ var require_toolrunner = __commonJS({ var os6 = __importStar2(require("os")); var events = __importStar2(require("events")); var child = __importStar2(require("child_process")); - var path17 = __importStar2(require("path")); + var path18 = __importStar2(require("path")); var io7 = __importStar2(require_io()); var ioUtil = __importStar2(require_io_util()); var timers_1 = require("timers"); @@ -20793,7 +20793,7 @@ var require_toolrunner = __commonJS({ exec() { return __awaiter2(this, void 0, void 0, function* () { if (!ioUtil.isRooted(this.toolPath) && (this.toolPath.includes("/") || IS_WINDOWS && this.toolPath.includes("\\"))) { - this.toolPath = path17.resolve(process.cwd(), this.options.cwd || process.cwd(), this.toolPath); + this.toolPath = path18.resolve(process.cwd(), this.options.cwd || process.cwd(), this.toolPath); } this.toolPath = yield io7.which(this.toolPath, true); return new Promise((resolve9, reject) => __awaiter2(this, void 0, void 0, function* () { @@ -21346,7 +21346,7 @@ var require_core = __commonJS({ var file_command_1 = require_file_command(); var utils_1 = require_utils(); var os6 = __importStar2(require("os")); - var path17 = __importStar2(require("path")); + var path18 = __importStar2(require("path")); var oidc_utils_1 = require_oidc_utils(); var ExitCode; (function(ExitCode2) { @@ -21372,7 +21372,7 @@ var require_core = __commonJS({ } else { (0, command_1.issueCommand)("add-path", {}, inputPath); } - process.env["PATH"] = `${inputPath}${path17.delimiter}${process.env["PATH"]}`; + process.env["PATH"] = `${inputPath}${path18.delimiter}${process.env["PATH"]}`; } function getInput2(name, options) { const val = process.env[`INPUT_${name.replace(/ /g, "_").toUpperCase()}`] || ""; @@ -21509,8 +21509,8 @@ var require_context = __commonJS({ if ((0, fs_1.existsSync)(process.env.GITHUB_EVENT_PATH)) { this.payload = JSON.parse((0, fs_1.readFileSync)(process.env.GITHUB_EVENT_PATH, { encoding: "utf8" })); } else { - const path17 = process.env.GITHUB_EVENT_PATH; - process.stdout.write(`GITHUB_EVENT_PATH ${path17} does not exist${os_1.EOL}`); + const path18 = process.env.GITHUB_EVENT_PATH; + process.stdout.write(`GITHUB_EVENT_PATH ${path18} does not exist${os_1.EOL}`); } } this.eventName = process.env.GITHUB_EVENT_NAME; @@ -22335,14 +22335,14 @@ var require_util9 = __commonJS({ } const port = url.port != null ? url.port : url.protocol === "https:" ? 443 : 80; let origin = url.origin != null ? url.origin : `${url.protocol || ""}//${url.hostname || ""}:${port}`; - let path17 = url.path != null ? url.path : `${url.pathname || ""}${url.search || ""}`; + let path18 = url.path != null ? url.path : `${url.pathname || ""}${url.search || ""}`; if (origin[origin.length - 1] === "/") { origin = origin.slice(0, origin.length - 1); } - if (path17 && path17[0] !== "/") { - path17 = `/${path17}`; + if (path18 && path18[0] !== "/") { + path18 = `/${path18}`; } - return new URL(`${origin}${path17}`); + return new URL(`${origin}${path18}`); } if (!isHttpOrHttpsPrefixed(url.origin || url.protocol)) { throw new InvalidArgumentError("Invalid URL protocol: the URL must start with `http:` or `https:`."); @@ -22793,39 +22793,39 @@ var require_diagnostics2 = __commonJS({ }); diagnosticsChannel.channel("undici:client:sendHeaders").subscribe((evt) => { const { - request: { method, path: path17, origin } + request: { method, path: path18, origin } } = evt; - debuglog("sending request to %s %s/%s", method, origin, path17); + debuglog("sending request to %s %s/%s", method, origin, path18); }); diagnosticsChannel.channel("undici:request:headers").subscribe((evt) => { const { - request: { method, path: path17, origin }, + request: { method, path: path18, origin }, response: { statusCode } } = evt; debuglog( "received response to %s %s/%s - HTTP %d", method, origin, - path17, + path18, statusCode ); }); diagnosticsChannel.channel("undici:request:trailers").subscribe((evt) => { const { - request: { method, path: path17, origin } + request: { method, path: path18, origin } } = evt; - debuglog("trailers received from %s %s/%s", method, origin, path17); + debuglog("trailers received from %s %s/%s", method, origin, path18); }); diagnosticsChannel.channel("undici:request:error").subscribe((evt) => { const { - request: { method, path: path17, origin }, + request: { method, path: path18, origin }, error: error3 } = evt; debuglog( "request to %s %s/%s errored - %s", method, origin, - path17, + path18, error3.message ); }); @@ -22874,9 +22874,9 @@ var require_diagnostics2 = __commonJS({ }); diagnosticsChannel.channel("undici:client:sendHeaders").subscribe((evt) => { const { - request: { method, path: path17, origin } + request: { method, path: path18, origin } } = evt; - debuglog("sending request to %s %s/%s", method, origin, path17); + debuglog("sending request to %s %s/%s", method, origin, path18); }); } diagnosticsChannel.channel("undici:websocket:open").subscribe((evt) => { @@ -22939,7 +22939,7 @@ var require_request3 = __commonJS({ var kHandler = /* @__PURE__ */ Symbol("handler"); var Request = class { constructor(origin, { - path: path17, + path: path18, method, body, headers, @@ -22954,11 +22954,11 @@ var require_request3 = __commonJS({ expectContinue, servername }, handler2) { - if (typeof path17 !== "string") { + if (typeof path18 !== "string") { throw new InvalidArgumentError("path must be a string"); - } else if (path17[0] !== "/" && !(path17.startsWith("http://") || path17.startsWith("https://")) && method !== "CONNECT") { + } else if (path18[0] !== "/" && !(path18.startsWith("http://") || path18.startsWith("https://")) && method !== "CONNECT") { throw new InvalidArgumentError("path must be an absolute URL or start with a slash"); - } else if (invalidPathRegex.test(path17)) { + } else if (invalidPathRegex.test(path18)) { throw new InvalidArgumentError("invalid request path"); } if (typeof method !== "string") { @@ -23021,7 +23021,7 @@ var require_request3 = __commonJS({ this.completed = false; this.aborted = false; this.upgrade = upgrade || null; - this.path = query ? buildURL(path17, query) : path17; + this.path = query ? buildURL(path18, query) : path18; this.origin = origin; this.idempotent = idempotent == null ? method === "HEAD" || method === "GET" : idempotent; this.blocking = blocking == null ? false : blocking; @@ -27534,7 +27534,7 @@ var require_client_h12 = __commonJS({ return method !== "GET" && method !== "HEAD" && method !== "OPTIONS" && method !== "TRACE" && method !== "CONNECT"; } function writeH1(client, request2) { - const { method, path: path17, host, upgrade, blocking, reset } = request2; + const { method, path: path18, host, upgrade, blocking, reset } = request2; let { body, headers, contentLength } = request2; const expectsPayload = method === "PUT" || method === "POST" || method === "PATCH" || method === "QUERY" || method === "PROPFIND" || method === "PROPPATCH"; if (util.isFormDataLike(body)) { @@ -27600,7 +27600,7 @@ var require_client_h12 = __commonJS({ if (blocking) { socket[kBlocking] = true; } - let header = `${method} ${path17} HTTP/1.1\r + let header = `${method} ${path18} HTTP/1.1\r `; if (typeof host === "string") { header += `host: ${host}\r @@ -28126,7 +28126,7 @@ var require_client_h22 = __commonJS({ } function writeH2(client, request2) { const session = client[kHTTP2Session]; - const { method, path: path17, host, upgrade, expectContinue, signal, headers: reqHeaders } = request2; + const { method, path: path18, host, upgrade, expectContinue, signal, headers: reqHeaders } = request2; let { body } = request2; if (upgrade) { util.errorRequest(client, request2, new Error("Upgrade not supported for H2")); @@ -28193,7 +28193,7 @@ var require_client_h22 = __commonJS({ }); return true; } - headers[HTTP2_HEADER_PATH] = path17; + headers[HTTP2_HEADER_PATH] = path18; headers[HTTP2_HEADER_SCHEME] = "https"; const expectsPayload = method === "PUT" || method === "POST" || method === "PATCH"; if (body && typeof body.read === "function") { @@ -28546,9 +28546,9 @@ var require_redirect_handler2 = __commonJS({ return this.handler.onHeaders(statusCode, headers, resume, statusText); } const { origin, pathname, search } = util.parseURL(new URL(this.location, this.opts.origin && new URL(this.opts.path, this.opts.origin))); - const path17 = search ? `${pathname}${search}` : pathname; + const path18 = search ? `${pathname}${search}` : pathname; this.opts.headers = cleanRequestHeaders(this.opts.headers, statusCode === 303, this.opts.origin !== origin); - this.opts.path = path17; + this.opts.path = path18; this.opts.origin = origin; this.opts.maxRedirections = 0; this.opts.query = null; @@ -29782,10 +29782,10 @@ var require_proxy_agent2 = __commonJS({ }; const { origin, - path: path17 = "/", + path: path18 = "/", headers = {} } = opts; - opts.path = origin + path17; + opts.path = origin + path18; if (!("host" in headers) && !("Host" in headers)) { const { host } = new URL2(origin); headers.host = host; @@ -31706,20 +31706,20 @@ var require_mock_utils2 = __commonJS({ } return true; } - function safeUrl(path17) { - if (typeof path17 !== "string") { - return path17; + function safeUrl(path18) { + if (typeof path18 !== "string") { + return path18; } - const pathSegments = path17.split("?"); + const pathSegments = path18.split("?"); if (pathSegments.length !== 2) { - return path17; + return path18; } const qp = new URLSearchParams(pathSegments.pop()); qp.sort(); return [...pathSegments, qp.toString()].join("?"); } - function matchKey(mockDispatch2, { path: path17, method, body, headers }) { - const pathMatch = matchValue(mockDispatch2.path, path17); + function matchKey(mockDispatch2, { path: path18, method, body, headers }) { + const pathMatch = matchValue(mockDispatch2.path, path18); const methodMatch = matchValue(mockDispatch2.method, method); const bodyMatch = typeof mockDispatch2.body !== "undefined" ? matchValue(mockDispatch2.body, body) : true; const headersMatch = matchHeaders(mockDispatch2, headers); @@ -31741,7 +31741,7 @@ var require_mock_utils2 = __commonJS({ function getMockDispatch(mockDispatches, key) { const basePath = key.query ? buildURL(key.path, key.query) : key.path; const resolvedPath = typeof basePath === "string" ? safeUrl(basePath) : basePath; - let matchedMockDispatches = mockDispatches.filter(({ consumed }) => !consumed).filter(({ path: path17 }) => matchValue(safeUrl(path17), resolvedPath)); + let matchedMockDispatches = mockDispatches.filter(({ consumed }) => !consumed).filter(({ path: path18 }) => matchValue(safeUrl(path18), resolvedPath)); if (matchedMockDispatches.length === 0) { throw new MockNotMatchedError(`Mock dispatch not matched for path '${resolvedPath}'`); } @@ -31779,9 +31779,9 @@ var require_mock_utils2 = __commonJS({ } } function buildKey(opts) { - const { path: path17, method, body, headers, query } = opts; + const { path: path18, method, body, headers, query } = opts; return { - path: path17, + path: path18, method, body, headers, @@ -32244,10 +32244,10 @@ var require_pending_interceptors_formatter2 = __commonJS({ } format(pendingInterceptors) { const withPrettyHeaders = pendingInterceptors.map( - ({ method, path: path17, data: { statusCode }, persist, times, timesInvoked, origin }) => ({ + ({ method, path: path18, data: { statusCode }, persist, times, timesInvoked, origin }) => ({ Method: method, Origin: origin, - Path: path17, + Path: path18, "Status code": statusCode, Persistent: persist ? PERSISTENT : NOT_PERSISTENT, Invocations: timesInvoked, @@ -37128,9 +37128,9 @@ var require_util14 = __commonJS({ } } } - function validateCookiePath(path17) { - for (let i = 0; i < path17.length; ++i) { - const code = path17.charCodeAt(i); + function validateCookiePath(path18) { + for (let i = 0; i < path18.length; ++i) { + const code = path18.charCodeAt(i); if (code < 32 || // exclude CTLs (0-31) code === 127 || // DEL code === 59) { @@ -39724,11 +39724,11 @@ var require_undici2 = __commonJS({ if (typeof opts.path !== "string") { throw new InvalidArgumentError("invalid opts.path"); } - let path17 = opts.path; + let path18 = opts.path; if (!opts.path.startsWith("/")) { - path17 = `/${path17}`; + path18 = `/${path18}`; } - url = new URL(util.parseOrigin(url).origin + path17); + url = new URL(util.parseOrigin(url).origin + path18); } else { if (!opts) { opts = typeof url === "object" ? url : {}; @@ -47305,14 +47305,14 @@ var require_helpers = __commonJS({ "node_modules/jsonschema/lib/helpers.js"(exports2, module2) { "use strict"; var uri = require("url"); - var ValidationError = exports2.ValidationError = function ValidationError2(message, instance, schema2, path17, name, argument) { - if (Array.isArray(path17)) { - this.path = path17; - this.property = path17.reduce(function(sum, item) { + var ValidationError = exports2.ValidationError = function ValidationError2(message, instance, schema2, path18, name, argument) { + if (Array.isArray(path18)) { + this.path = path18; + this.property = path18.reduce(function(sum, item) { return sum + makeSuffix(item); }, "instance"); - } else if (path17 !== void 0) { - this.property = path17; + } else if (path18 !== void 0) { + this.property = path18; } if (message) { this.message = message; @@ -47403,16 +47403,16 @@ var require_helpers = __commonJS({ name: { value: "SchemaError", enumerable: false } } ); - var SchemaContext = exports2.SchemaContext = function SchemaContext2(schema2, options, path17, base, schemas) { + var SchemaContext = exports2.SchemaContext = function SchemaContext2(schema2, options, path18, base, schemas) { this.schema = schema2; this.options = options; - if (Array.isArray(path17)) { - this.path = path17; - this.propertyPath = path17.reduce(function(sum, item) { + if (Array.isArray(path18)) { + this.path = path18; + this.propertyPath = path18.reduce(function(sum, item) { return sum + makeSuffix(item); }, "instance"); } else { - this.propertyPath = path17; + this.propertyPath = path18; } this.base = base; this.schemas = schemas; @@ -47421,10 +47421,10 @@ var require_helpers = __commonJS({ return uri.resolve(this.base, target); }; SchemaContext.prototype.makeChild = function makeChild(schema2, propertyName) { - var path17 = propertyName === void 0 ? this.path : this.path.concat([propertyName]); + var path18 = propertyName === void 0 ? this.path : this.path.concat([propertyName]); var id = schema2.$id || schema2.id; var base = uri.resolve(this.base, id || ""); - var ctx = new SchemaContext(schema2, this.options, path17, base, Object.create(this.schemas)); + var ctx = new SchemaContext(schema2, this.options, path18, base, Object.create(this.schemas)); if (id && !ctx.schemas[base]) { ctx.schemas[base] = schema2; } @@ -48878,7 +48878,7 @@ var require_internal_path_helper = __commonJS({ exports2.hasRoot = hasRoot; exports2.normalizeSeparators = normalizeSeparators; exports2.safeTrimTrailingSeparator = safeTrimTrailingSeparator; - var path17 = __importStar2(require("path")); + var path18 = __importStar2(require("path")); var assert_1 = __importDefault2(require("assert")); var IS_WINDOWS = process.platform === "win32"; function dirname4(p) { @@ -48886,7 +48886,7 @@ var require_internal_path_helper = __commonJS({ if (IS_WINDOWS && /^\\\\[^\\]+(\\[^\\]+)?$/.test(p)) { return p; } - let result = path17.dirname(p); + let result = path18.dirname(p); if (IS_WINDOWS && /^\\\\[^\\]+\\[^\\]+\\$/.test(result)) { result = safeTrimTrailingSeparator(result); } @@ -48923,7 +48923,7 @@ var require_internal_path_helper = __commonJS({ (0, assert_1.default)(hasAbsoluteRoot(root), `ensureAbsoluteRoot parameter 'root' must have an absolute root`); if (root.endsWith("/") || IS_WINDOWS && root.endsWith("\\")) { } else { - root += path17.sep; + root += path18.sep; } return root + itemPath; } @@ -48957,10 +48957,10 @@ var require_internal_path_helper = __commonJS({ return ""; } p = normalizeSeparators(p); - if (!p.endsWith(path17.sep)) { + if (!p.endsWith(path18.sep)) { return p; } - if (p === path17.sep) { + if (p === path18.sep) { return p; } if (IS_WINDOWS && /^[A-Z]:\\$/i.test(p)) { @@ -49305,7 +49305,7 @@ var require_minimatch = __commonJS({ "node_modules/minimatch/minimatch.js"(exports2, module2) { module2.exports = minimatch; minimatch.Minimatch = Minimatch; - var path17 = (function() { + var path18 = (function() { try { return require("path"); } catch (e) { @@ -49313,7 +49313,7 @@ var require_minimatch = __commonJS({ })() || { sep: "/" }; - minimatch.sep = path17.sep; + minimatch.sep = path18.sep; var GLOBSTAR = minimatch.GLOBSTAR = Minimatch.GLOBSTAR = {}; var expand2 = require_brace_expansion(); var plTypes = { @@ -49402,8 +49402,8 @@ var require_minimatch = __commonJS({ assertValidPattern(pattern); if (!options) options = {}; pattern = pattern.trim(); - if (!options.allowWindowsEscape && path17.sep !== "/") { - pattern = pattern.split(path17.sep).join("/"); + if (!options.allowWindowsEscape && path18.sep !== "/") { + pattern = pattern.split(path18.sep).join("/"); } this.options = options; this.maxGlobstarRecursion = options.maxGlobstarRecursion !== void 0 ? options.maxGlobstarRecursion : 200; @@ -49774,8 +49774,8 @@ var require_minimatch = __commonJS({ if (this.empty) return f === ""; if (f === "/" && partial) return true; var options = this.options; - if (path17.sep !== "/") { - f = f.split(path17.sep).join("/"); + if (path18.sep !== "/") { + f = f.split(path18.sep).join("/"); } f = f.split(slashSplit); this.debug(this.pattern, "split", f); @@ -50018,7 +50018,7 @@ var require_internal_path = __commonJS({ }; Object.defineProperty(exports2, "__esModule", { value: true }); exports2.Path = void 0; - var path17 = __importStar2(require("path")); + var path18 = __importStar2(require("path")); var pathHelper = __importStar2(require_internal_path_helper()); var assert_1 = __importDefault2(require("assert")); var IS_WINDOWS = process.platform === "win32"; @@ -50033,12 +50033,12 @@ var require_internal_path = __commonJS({ (0, assert_1.default)(itemPath, `Parameter 'itemPath' must not be empty`); itemPath = pathHelper.safeTrimTrailingSeparator(itemPath); if (!pathHelper.hasRoot(itemPath)) { - this.segments = itemPath.split(path17.sep); + this.segments = itemPath.split(path18.sep); } else { let remaining = itemPath; let dir = pathHelper.dirname(remaining); while (dir !== remaining) { - const basename = path17.basename(remaining); + const basename = path18.basename(remaining); this.segments.unshift(basename); remaining = dir; dir = pathHelper.dirname(remaining); @@ -50056,7 +50056,7 @@ var require_internal_path = __commonJS({ (0, assert_1.default)(segment === pathHelper.dirname(segment), `Parameter 'itemPath' root segment contains information for multiple segments`); this.segments.push(segment); } else { - (0, assert_1.default)(!segment.includes(path17.sep), `Parameter 'itemPath' contains unexpected path separators`); + (0, assert_1.default)(!segment.includes(path18.sep), `Parameter 'itemPath' contains unexpected path separators`); this.segments.push(segment); } } @@ -50067,12 +50067,12 @@ var require_internal_path = __commonJS({ */ toString() { let result = this.segments[0]; - let skipSlash = result.endsWith(path17.sep) || IS_WINDOWS && /^[A-Z]:$/i.test(result); + let skipSlash = result.endsWith(path18.sep) || IS_WINDOWS && /^[A-Z]:$/i.test(result); for (let i = 1; i < this.segments.length; i++) { if (skipSlash) { skipSlash = false; } else { - result += path17.sep; + result += path18.sep; } result += this.segments[i]; } @@ -50130,7 +50130,7 @@ var require_internal_pattern = __commonJS({ Object.defineProperty(exports2, "__esModule", { value: true }); exports2.Pattern = void 0; var os6 = __importStar2(require("os")); - var path17 = __importStar2(require("path")); + var path18 = __importStar2(require("path")); var pathHelper = __importStar2(require_internal_path_helper()); var assert_1 = __importDefault2(require("assert")); var minimatch_1 = require_minimatch(); @@ -50159,7 +50159,7 @@ var require_internal_pattern = __commonJS({ } pattern = _Pattern.fixupPattern(pattern, homedir2); this.segments = new internal_path_1.Path(pattern).segments; - this.trailingSeparator = pathHelper.normalizeSeparators(pattern).endsWith(path17.sep); + this.trailingSeparator = pathHelper.normalizeSeparators(pattern).endsWith(path18.sep); pattern = pathHelper.safeTrimTrailingSeparator(pattern); let foundGlob = false; const searchSegments = this.segments.map((x) => _Pattern.getLiteral(x)).filter((x) => !foundGlob && !(foundGlob = x === "")); @@ -50183,8 +50183,8 @@ var require_internal_pattern = __commonJS({ match(itemPath) { if (this.segments[this.segments.length - 1] === "**") { itemPath = pathHelper.normalizeSeparators(itemPath); - if (!itemPath.endsWith(path17.sep) && this.isImplicitPattern === false) { - itemPath = `${itemPath}${path17.sep}`; + if (!itemPath.endsWith(path18.sep) && this.isImplicitPattern === false) { + itemPath = `${itemPath}${path18.sep}`; } } else { itemPath = pathHelper.safeTrimTrailingSeparator(itemPath); @@ -50219,9 +50219,9 @@ var require_internal_pattern = __commonJS({ (0, assert_1.default)(literalSegments.every((x, i) => (x !== "." || i === 0) && x !== ".."), `Invalid pattern '${pattern}'. Relative pathing '.' and '..' is not allowed.`); (0, assert_1.default)(!pathHelper.hasRoot(pattern) || literalSegments[0], `Invalid pattern '${pattern}'. Root segment must not contain globs.`); pattern = pathHelper.normalizeSeparators(pattern); - if (pattern === "." || pattern.startsWith(`.${path17.sep}`)) { + if (pattern === "." || pattern.startsWith(`.${path18.sep}`)) { pattern = _Pattern.globEscape(process.cwd()) + pattern.substr(1); - } else if (pattern === "~" || pattern.startsWith(`~${path17.sep}`)) { + } else if (pattern === "~" || pattern.startsWith(`~${path18.sep}`)) { 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}'`); @@ -50305,8 +50305,8 @@ var require_internal_search_state = __commonJS({ Object.defineProperty(exports2, "__esModule", { value: true }); exports2.SearchState = void 0; var SearchState = class { - constructor(path17, level) { - this.path = path17; + constructor(path18, level) { + this.path = path18; this.level = level; } }; @@ -50448,9 +50448,9 @@ var require_internal_globber = __commonJS({ Object.defineProperty(exports2, "__esModule", { value: true }); exports2.DefaultGlobber = void 0; var core16 = __importStar2(require_core()); - var fs16 = __importStar2(require("fs")); + var fs17 = __importStar2(require("fs")); var globOptionsHelper = __importStar2(require_internal_glob_options_helper()); - var path17 = __importStar2(require("path")); + var path18 = __importStar2(require("path")); var patternHelper = __importStar2(require_internal_pattern_helper()); var internal_match_kind_1 = require_internal_match_kind(); var internal_pattern_1 = require_internal_pattern(); @@ -50502,7 +50502,7 @@ var require_internal_globber = __commonJS({ for (const searchPath of patternHelper.getSearchPaths(patterns)) { core16.debug(`Search path '${searchPath}'`); try { - yield __await2(fs16.promises.lstat(searchPath)); + yield __await2(fs17.promises.lstat(searchPath)); } catch (err) { if (err.code === "ENOENT") { continue; @@ -50526,7 +50526,7 @@ var require_internal_globber = __commonJS({ if (!stats) { continue; } - if (options.excludeHiddenFiles && path17.basename(item.path).match(/^\./)) { + if (options.excludeHiddenFiles && path18.basename(item.path).match(/^\./)) { continue; } if (stats.isDirectory()) { @@ -50536,7 +50536,7 @@ var require_internal_globber = __commonJS({ continue; } const childLevel = item.level + 1; - const childItems = (yield __await2(fs16.promises.readdir(item.path))).map((x) => new internal_search_state_1.SearchState(path17.join(item.path, x), childLevel)); + const childItems = (yield __await2(fs17.promises.readdir(item.path))).map((x) => new internal_search_state_1.SearchState(path18.join(item.path, x), childLevel)); stack.push(...childItems.reverse()); } else if (match & internal_match_kind_1.MatchKind.File) { yield yield __await2(item.path); @@ -50571,7 +50571,7 @@ var require_internal_globber = __commonJS({ let stats; if (options.followSymbolicLinks) { try { - stats = yield fs16.promises.stat(item.path); + stats = yield fs17.promises.stat(item.path); } catch (err) { if (err.code === "ENOENT") { if (options.omitBrokenSymbolicLinks) { @@ -50583,10 +50583,10 @@ var require_internal_globber = __commonJS({ throw err; } } else { - stats = yield fs16.promises.lstat(item.path); + stats = yield fs17.promises.lstat(item.path); } if (stats.isDirectory() && options.followSymbolicLinks) { - const realPath = yield fs16.promises.realpath(item.path); + const realPath = yield fs17.promises.realpath(item.path); while (traversalChain.length >= item.level) { traversalChain.pop(); } @@ -50695,10 +50695,10 @@ var require_internal_hash_files = __commonJS({ exports2.hashFiles = hashFiles2; var crypto3 = __importStar2(require("crypto")); var core16 = __importStar2(require_core()); - var fs16 = __importStar2(require("fs")); + var fs17 = __importStar2(require("fs")); var stream2 = __importStar2(require("stream")); var util = __importStar2(require("util")); - var path17 = __importStar2(require("path")); + var path18 = __importStar2(require("path")); function hashFiles2(globber_1, currentWorkspace_1) { return __awaiter2(this, arguments, void 0, function* (globber, currentWorkspace, verbose = false) { var _a, e_1, _b, _c; @@ -50714,17 +50714,17 @@ var require_internal_hash_files = __commonJS({ _e = false; const file = _c; writeDelegate(file); - if (!file.startsWith(`${githubWorkspace}${path17.sep}`)) { + if (!file.startsWith(`${githubWorkspace}${path18.sep}`)) { writeDelegate(`Ignore '${file}' since it is not under GITHUB_WORKSPACE.`); continue; } - if (fs16.statSync(file).isDirectory()) { + if (fs17.statSync(file).isDirectory()) { writeDelegate(`Skip directory '${file}'.`); continue; } const hash = crypto3.createHash("sha256"); const pipeline = util.promisify(stream2.pipeline); - yield pipeline(fs16.createReadStream(file), hash); + yield pipeline(fs17.createReadStream(file), hash); result.write(hash.digest()); count++; if (!hasMatch) { @@ -52099,8 +52099,8 @@ var require_cacheUtils = __commonJS({ var glob2 = __importStar2(require_glob()); var io7 = __importStar2(require_io()); var crypto3 = __importStar2(require("crypto")); - var fs16 = __importStar2(require("fs")); - var path17 = __importStar2(require("path")); + var fs17 = __importStar2(require("fs")); + var path18 = __importStar2(require("path")); var semver10 = __importStar2(require_semver3()); var util = __importStar2(require("util")); var constants_1 = require_constants12(); @@ -52120,15 +52120,15 @@ var require_cacheUtils = __commonJS({ baseLocation = "/home"; } } - tempDirectory = path17.join(baseLocation, "actions", "temp"); + tempDirectory = path18.join(baseLocation, "actions", "temp"); } - const dest = path17.join(tempDirectory, crypto3.randomUUID()); + const dest = path18.join(tempDirectory, crypto3.randomUUID()); yield io7.mkdirP(dest); return dest; }); } function getArchiveFileSizeInBytes(filePath) { - return fs16.statSync(filePath).size; + return fs17.statSync(filePath).size; } function resolvePaths(patterns) { return __awaiter2(this, void 0, void 0, function* () { @@ -52144,7 +52144,7 @@ var require_cacheUtils = __commonJS({ _c = _g.value; _e = false; const file = _c; - const relativeFile = path17.relative(workspace, file).replace(new RegExp(`\\${path17.sep}`, "g"), "/"); + const relativeFile = path18.relative(workspace, file).replace(new RegExp(`\\${path18.sep}`, "g"), "/"); core16.debug(`Matched: ${relativeFile}`); if (relativeFile === "") { paths.push("."); @@ -52166,7 +52166,7 @@ var require_cacheUtils = __commonJS({ } function unlinkFile(filePath) { return __awaiter2(this, void 0, void 0, function* () { - return util.promisify(fs16.unlink)(filePath); + return util.promisify(fs17.unlink)(filePath); }); } function getVersion(app_1) { @@ -52208,7 +52208,7 @@ var require_cacheUtils = __commonJS({ } function getGnuTarPathOnWindows() { return __awaiter2(this, void 0, void 0, function* () { - if (fs16.existsSync(constants_1.GnuTarPathOnWindows)) { + if (fs17.existsSync(constants_1.GnuTarPathOnWindows)) { return constants_1.GnuTarPathOnWindows; } const versionOutput = yield getVersion("tar"); @@ -52671,13 +52671,13 @@ function __disposeResources(env) { } return next(); } -function __rewriteRelativeImportExtension(path17, preserveJsx) { - if (typeof path17 === "string" && /^\.\.?\//.test(path17)) { - return path17.replace(/\.(tsx)$|((?:\.d)?)((?:\.[^./]+?)?)\.([cm]?)ts$/i, function(m, tsx, d, ext, cm) { +function __rewriteRelativeImportExtension(path18, preserveJsx) { + if (typeof path18 === "string" && /^\.\.?\//.test(path18)) { + return path18.replace(/\.(tsx)$|((?:\.d)?)((?:\.[^./]+?)?)\.([cm]?)ts$/i, function(m, tsx, d, ext, cm) { return tsx ? preserveJsx ? ".jsx" : ".js" : d && (!ext || !cm) ? m : d + ext + "." + cm.toLowerCase() + "js"; }); } - return path17; + return path18; } var extendStatics, __assign, __createBinding, __setModuleDefault, ownKeys, _SuppressedError, tslib_es6_default; var init_tslib_es6 = __esm({ @@ -57091,8 +57091,8 @@ var require_getClient = __commonJS({ } const { allowInsecureConnection, httpClient } = clientOptions; const endpointUrl = clientOptions.endpoint ?? endpoint2; - const client = (path17, ...args) => { - const getUrl = (requestOptions) => (0, urlHelpers_js_1.buildRequestUrl)(endpointUrl, path17, args, { allowInsecureConnection, ...requestOptions }); + const client = (path18, ...args) => { + const getUrl = (requestOptions) => (0, urlHelpers_js_1.buildRequestUrl)(endpointUrl, path18, args, { allowInsecureConnection, ...requestOptions }); return { get: (requestOptions = {}) => { return buildOperation("GET", getUrl(requestOptions), pipeline, requestOptions, allowInsecureConnection, httpClient); @@ -60963,15 +60963,15 @@ var require_urlHelpers2 = __commonJS({ let isAbsolutePath = false; let requestUrl = replaceAll(baseUri, urlReplacements); if (operationSpec.path) { - let path17 = replaceAll(operationSpec.path, urlReplacements); - if (operationSpec.path === "/{nextLink}" && path17.startsWith("/")) { - path17 = path17.substring(1); + let path18 = replaceAll(operationSpec.path, urlReplacements); + if (operationSpec.path === "/{nextLink}" && path18.startsWith("/")) { + path18 = path18.substring(1); } - if (isAbsoluteUrl(path17)) { - requestUrl = path17; + if (isAbsoluteUrl(path18)) { + requestUrl = path18; isAbsolutePath = true; } else { - requestUrl = appendPath(requestUrl, path17); + requestUrl = appendPath(requestUrl, path18); } } const { queryParams, sequenceParams } = calculateQueryParameters(operationSpec, operationArguments, fallbackObject); @@ -61017,9 +61017,9 @@ var require_urlHelpers2 = __commonJS({ } const searchStart = pathToAppend.indexOf("?"); if (searchStart !== -1) { - const path17 = pathToAppend.substring(0, searchStart); + const path18 = pathToAppend.substring(0, searchStart); const search = pathToAppend.substring(searchStart + 1); - newPath = newPath + path17; + newPath = newPath + path18; if (search) { parsedUrl.search = parsedUrl.search ? `${parsedUrl.search}&${search}` : search; } @@ -63696,10 +63696,10 @@ var require_utils_common = __commonJS({ var constants_js_1 = require_constants15(); function escapeURLPath(url) { const urlParsed = new URL(url); - let path17 = urlParsed.pathname; - path17 = path17 || "/"; - path17 = escape(path17); - urlParsed.pathname = path17; + let path18 = urlParsed.pathname; + path18 = path18 || "/"; + path18 = escape(path18); + urlParsed.pathname = path18; return urlParsed.toString(); } function getProxyUriFromDevConnString(connectionString) { @@ -63784,9 +63784,9 @@ var require_utils_common = __commonJS({ } function appendToURLPath(url, name) { const urlParsed = new URL(url); - let path17 = urlParsed.pathname; - path17 = path17 ? path17.endsWith("/") ? `${path17}${name}` : `${path17}/${name}` : name; - urlParsed.pathname = path17; + let path18 = urlParsed.pathname; + path18 = path18 ? path18.endsWith("/") ? `${path18}${name}` : `${path18}/${name}` : name; + urlParsed.pathname = path18; return urlParsed.toString(); } function setURLParameter(url, name, value) { @@ -65013,9 +65013,9 @@ var require_StorageSharedKeyCredentialPolicy = __commonJS({ * @param request - */ getCanonicalizedResourceString(request2) { - const path17 = (0, utils_common_js_1.getURLPath)(request2.url) || "/"; + const path18 = (0, utils_common_js_1.getURLPath)(request2.url) || "/"; let canonicalizedResourceString = ""; - canonicalizedResourceString += `/${this.factory.accountName}${path17}`; + canonicalizedResourceString += `/${this.factory.accountName}${path18}`; const queries = (0, utils_common_js_1.getURLQueries)(request2.url); const lowercaseQueries = {}; if (queries) { @@ -65754,10 +65754,10 @@ var require_utils_common2 = __commonJS({ var constants_js_1 = require_constants16(); function escapeURLPath(url) { const urlParsed = new URL(url); - let path17 = urlParsed.pathname; - path17 = path17 || "/"; - path17 = escape(path17); - urlParsed.pathname = path17; + let path18 = urlParsed.pathname; + path18 = path18 || "/"; + path18 = escape(path18); + urlParsed.pathname = path18; return urlParsed.toString(); } function getProxyUriFromDevConnString(connectionString) { @@ -65842,9 +65842,9 @@ var require_utils_common2 = __commonJS({ } function appendToURLPath(url, name) { const urlParsed = new URL(url); - let path17 = urlParsed.pathname; - path17 = path17 ? path17.endsWith("/") ? `${path17}${name}` : `${path17}/${name}` : name; - urlParsed.pathname = path17; + let path18 = urlParsed.pathname; + path18 = path18 ? path18.endsWith("/") ? `${path18}${name}` : `${path18}/${name}` : name; + urlParsed.pathname = path18; return urlParsed.toString(); } function setURLParameter(url, name, value) { @@ -66765,9 +66765,9 @@ var require_StorageSharedKeyCredentialPolicy2 = __commonJS({ * @param request - */ getCanonicalizedResourceString(request2) { - const path17 = (0, utils_common_js_1.getURLPath)(request2.url) || "/"; + const path18 = (0, utils_common_js_1.getURLPath)(request2.url) || "/"; let canonicalizedResourceString = ""; - canonicalizedResourceString += `/${this.factory.accountName}${path17}`; + canonicalizedResourceString += `/${this.factory.accountName}${path18}`; const queries = (0, utils_common_js_1.getURLQueries)(request2.url); const lowercaseQueries = {}; if (queries) { @@ -67397,9 +67397,9 @@ var require_StorageSharedKeyCredentialPolicyV2 = __commonJS({ return canonicalizedHeadersStringToSign; } function getCanonicalizedResourceString(request2) { - const path17 = (0, utils_common_js_1.getURLPath)(request2.url) || "/"; + const path18 = (0, utils_common_js_1.getURLPath)(request2.url) || "/"; let canonicalizedResourceString = ""; - canonicalizedResourceString += `/${options.accountName}${path17}`; + canonicalizedResourceString += `/${options.accountName}${path18}`; const queries = (0, utils_common_js_1.getURLQueries)(request2.url); const lowercaseQueries = {}; if (queries) { @@ -67744,9 +67744,9 @@ var require_StorageSharedKeyCredentialPolicyV22 = __commonJS({ return canonicalizedHeadersStringToSign; } function getCanonicalizedResourceString(request2) { - const path17 = (0, utils_common_js_1.getURLPath)(request2.url) || "/"; + const path18 = (0, utils_common_js_1.getURLPath)(request2.url) || "/"; let canonicalizedResourceString = ""; - canonicalizedResourceString += `/${options.accountName}${path17}`; + canonicalizedResourceString += `/${options.accountName}${path18}`; const queries = (0, utils_common_js_1.getURLQueries)(request2.url); const lowercaseQueries = {}; if (queries) { @@ -89401,8 +89401,8 @@ var require_BlobBatch = __commonJS({ if (this.operationCount >= constants_js_1.BATCH_MAX_REQUEST) { throw new RangeError(`Cannot exceed ${constants_js_1.BATCH_MAX_REQUEST} sub requests in a single batch`); } - const path17 = (0, utils_common_js_1.getURLPath)(subRequest.url); - if (!path17 || path17 === "") { + const path18 = (0, utils_common_js_1.getURLPath)(subRequest.url); + if (!path18 || path18 === "") { throw new RangeError(`Invalid url for sub request: '${subRequest.url}'`); } } @@ -89480,8 +89480,8 @@ var require_BlobBatchClient = __commonJS({ pipeline = (0, Pipeline_js_1.newPipeline)(credentialOrPipeline, options); } const storageClientContext = new StorageContextClient_js_1.StorageContextClient(url, (0, Pipeline_js_1.getCoreClientOptions)(pipeline)); - const path17 = (0, utils_common_js_1.getURLPath)(url); - if (path17 && path17 !== "/") { + const path18 = (0, utils_common_js_1.getURLPath)(url); + if (path18 && path18 !== "/") { this.serviceOrContainerContext = storageClientContext.container; } else { this.serviceOrContainerContext = storageClientContext.service; @@ -92768,7 +92768,7 @@ var require_downloadUtils = __commonJS({ var http_client_1 = require_lib(); var storage_blob_1 = require_commonjs15(); var buffer = __importStar2(require("buffer")); - var fs16 = __importStar2(require("fs")); + var fs17 = __importStar2(require("fs")); var stream2 = __importStar2(require("stream")); var util = __importStar2(require("util")); var utils = __importStar2(require_cacheUtils()); @@ -92879,7 +92879,7 @@ var require_downloadUtils = __commonJS({ exports2.DownloadProgress = DownloadProgress; function downloadCacheHttpClient(archiveLocation, archivePath) { return __awaiter2(this, void 0, void 0, function* () { - const writeStream = fs16.createWriteStream(archivePath); + const writeStream = fs17.createWriteStream(archivePath); const httpClient = new http_client_1.HttpClient("actions/cache"); const downloadResponse = yield (0, requestUtils_1.retryHttpClientResponse)("downloadCache", () => __awaiter2(this, void 0, void 0, function* () { return httpClient.get(archiveLocation); @@ -92904,7 +92904,7 @@ var require_downloadUtils = __commonJS({ function downloadCacheHttpClientConcurrent(archiveLocation, archivePath, options) { return __awaiter2(this, void 0, void 0, function* () { var _a; - const archiveDescriptor = yield fs16.promises.open(archivePath, "w"); + const archiveDescriptor = yield fs17.promises.open(archivePath, "w"); const httpClient = new http_client_1.HttpClient("actions/cache", void 0, { socketTimeout: options.timeoutInMs, keepAlive: true @@ -93020,7 +93020,7 @@ var require_downloadUtils = __commonJS({ } else { const maxSegmentSize = Math.min(134217728, buffer.constants.MAX_LENGTH); const downloadProgress = new DownloadProgress(contentLength); - const fd = fs16.openSync(archivePath, "w"); + const fd = fs17.openSync(archivePath, "w"); try { downloadProgress.startDisplayTimer(); const controller = new abort_controller_1.AbortController(); @@ -93038,12 +93038,12 @@ var require_downloadUtils = __commonJS({ controller.abort(); throw new Error("Aborting cache download as the download time exceeded the timeout."); } else if (Buffer.isBuffer(result)) { - fs16.writeFileSync(fd, result); + fs17.writeFileSync(fd, result); } } } finally { downloadProgress.stopDisplayTimer(); - fs16.closeSync(fd); + fs17.closeSync(fd); } } }); @@ -93365,7 +93365,7 @@ var require_cacheHttpClient = __commonJS({ var core16 = __importStar2(require_core()); var http_client_1 = require_lib(); var auth_1 = require_auth(); - var fs16 = __importStar2(require("fs")); + var fs17 = __importStar2(require("fs")); var url_1 = require("url"); var utils = __importStar2(require_cacheUtils()); var uploadUtils_1 = require_uploadUtils(); @@ -93500,7 +93500,7 @@ Other caches with similar key:`); return __awaiter2(this, void 0, void 0, function* () { const fileSize = utils.getArchiveFileSizeInBytes(archivePath); const resourceUrl = getCacheApiUrl(`caches/${cacheId.toString()}`); - const fd = fs16.openSync(archivePath, "r"); + const fd = fs17.openSync(archivePath, "r"); const uploadOptions = (0, options_1.getUploadOptions)(options); const concurrency = utils.assertDefined("uploadConcurrency", uploadOptions.uploadConcurrency); const maxChunkSize = utils.assertDefined("uploadChunkSize", uploadOptions.uploadChunkSize); @@ -93514,7 +93514,7 @@ Other caches with similar key:`); const start = offset; const end = offset + chunkSize - 1; offset += maxChunkSize; - yield uploadChunk(httpClient, resourceUrl, () => fs16.createReadStream(archivePath, { + yield uploadChunk(httpClient, resourceUrl, () => fs17.createReadStream(archivePath, { fd, start, end, @@ -93525,7 +93525,7 @@ Other caches with similar key:`); } }))); } finally { - fs16.closeSync(fd); + fs17.closeSync(fd); } return; }); @@ -98790,7 +98790,7 @@ var require_tar = __commonJS({ var exec_1 = require_exec(); var io7 = __importStar2(require_io()); var fs_1 = require("fs"); - var path17 = __importStar2(require("path")); + var path18 = __importStar2(require("path")); var utils = __importStar2(require_cacheUtils()); var constants_1 = require_constants12(); var IS_WINDOWS = process.platform === "win32"; @@ -98836,13 +98836,13 @@ var require_tar = __commonJS({ const BSD_TAR_ZSTD = tarPath.type === constants_1.ArchiveToolType.BSD && compressionMethod !== constants_1.CompressionMethod.Gzip && IS_WINDOWS; switch (type2) { case "create": - args.push("--posix", "-cf", BSD_TAR_ZSTD ? tarFile : cacheFileName.replace(new RegExp(`\\${path17.sep}`, "g"), "/"), "--exclude", BSD_TAR_ZSTD ? tarFile : cacheFileName.replace(new RegExp(`\\${path17.sep}`, "g"), "/"), "-P", "-C", workingDirectory.replace(new RegExp(`\\${path17.sep}`, "g"), "/"), "--files-from", constants_1.ManifestFilename); + args.push("--posix", "-cf", BSD_TAR_ZSTD ? tarFile : cacheFileName.replace(new RegExp(`\\${path18.sep}`, "g"), "/"), "--exclude", BSD_TAR_ZSTD ? tarFile : cacheFileName.replace(new RegExp(`\\${path18.sep}`, "g"), "/"), "-P", "-C", workingDirectory.replace(new RegExp(`\\${path18.sep}`, "g"), "/"), "--files-from", constants_1.ManifestFilename); break; case "extract": - args.push("-xf", BSD_TAR_ZSTD ? tarFile : archivePath.replace(new RegExp(`\\${path17.sep}`, "g"), "/"), "-P", "-C", workingDirectory.replace(new RegExp(`\\${path17.sep}`, "g"), "/")); + args.push("-xf", BSD_TAR_ZSTD ? tarFile : archivePath.replace(new RegExp(`\\${path18.sep}`, "g"), "/"), "-P", "-C", workingDirectory.replace(new RegExp(`\\${path18.sep}`, "g"), "/")); break; case "list": - args.push("-tf", BSD_TAR_ZSTD ? tarFile : archivePath.replace(new RegExp(`\\${path17.sep}`, "g"), "/"), "-P"); + args.push("-tf", BSD_TAR_ZSTD ? tarFile : archivePath.replace(new RegExp(`\\${path18.sep}`, "g"), "/"), "-P"); break; } if (tarPath.type === constants_1.ArchiveToolType.GNU) { @@ -98888,7 +98888,7 @@ var require_tar = __commonJS({ return BSD_TAR_ZSTD ? [ "zstd -d --long=30 --force -o", constants_1.TarFilename, - archivePath.replace(new RegExp(`\\${path17.sep}`, "g"), "/") + archivePath.replace(new RegExp(`\\${path18.sep}`, "g"), "/") ] : [ "--use-compress-program", IS_WINDOWS ? '"zstd -d --long=30"' : "unzstd --long=30" @@ -98897,7 +98897,7 @@ var require_tar = __commonJS({ return BSD_TAR_ZSTD ? [ "zstd -d --force -o", constants_1.TarFilename, - archivePath.replace(new RegExp(`\\${path17.sep}`, "g"), "/") + archivePath.replace(new RegExp(`\\${path18.sep}`, "g"), "/") ] : ["--use-compress-program", IS_WINDOWS ? '"zstd -d"' : "unzstd"]; default: return ["-z"]; @@ -98912,7 +98912,7 @@ var require_tar = __commonJS({ case constants_1.CompressionMethod.Zstd: return BSD_TAR_ZSTD ? [ "zstd -T0 --long=30 --force -o", - cacheFileName.replace(new RegExp(`\\${path17.sep}`, "g"), "/"), + cacheFileName.replace(new RegExp(`\\${path18.sep}`, "g"), "/"), constants_1.TarFilename ] : [ "--use-compress-program", @@ -98921,7 +98921,7 @@ var require_tar = __commonJS({ case constants_1.CompressionMethod.ZstdWithoutLong: return BSD_TAR_ZSTD ? [ "zstd -T0 --force -o", - cacheFileName.replace(new RegExp(`\\${path17.sep}`, "g"), "/"), + cacheFileName.replace(new RegExp(`\\${path18.sep}`, "g"), "/"), constants_1.TarFilename ] : ["--use-compress-program", IS_WINDOWS ? '"zstd -T0"' : "zstdmt"]; default: @@ -98959,7 +98959,7 @@ var require_tar = __commonJS({ } function createTar(archiveFolder, sourceDirectories, compressionMethod) { return __awaiter2(this, void 0, void 0, function* () { - (0, fs_1.writeFileSync)(path17.join(archiveFolder, constants_1.ManifestFilename), sourceDirectories.join("\n")); + (0, fs_1.writeFileSync)(path18.join(archiveFolder, constants_1.ManifestFilename), sourceDirectories.join("\n")); const commands = yield getCommands(compressionMethod, "create"); yield execCommands(commands, archiveFolder); }); @@ -99041,7 +99041,7 @@ var require_cache5 = __commonJS({ exports2.restoreCache = restoreCache5; exports2.saveCache = saveCache5; var core16 = __importStar2(require_core()); - var path17 = __importStar2(require("path")); + var path18 = __importStar2(require("path")); var utils = __importStar2(require_cacheUtils()); var cacheHttpClient = __importStar2(require_cacheHttpClient()); var cacheTwirpClient = __importStar2(require_cacheTwirpClient()); @@ -99136,7 +99136,7 @@ var require_cache5 = __commonJS({ core16.info("Lookup only - skipping download"); return cacheEntry.cacheKey; } - archivePath = path17.join(yield utils.createTempDirectory(), utils.getCacheFileName(compressionMethod)); + archivePath = path18.join(yield utils.createTempDirectory(), utils.getCacheFileName(compressionMethod)); core16.debug(`Archive Path: ${archivePath}`); yield cacheHttpClient.downloadCache(cacheEntry.archiveLocation, archivePath, options); if (core16.isDebug()) { @@ -99205,7 +99205,7 @@ var require_cache5 = __commonJS({ core16.info("Lookup only - skipping download"); return response.matchedKey; } - archivePath = path17.join(yield utils.createTempDirectory(), utils.getCacheFileName(compressionMethod)); + archivePath = path18.join(yield utils.createTempDirectory(), utils.getCacheFileName(compressionMethod)); core16.debug(`Archive path: ${archivePath}`); core16.debug(`Starting download of archive to: ${archivePath}`); yield cacheHttpClient.downloadCache(response.signedDownloadUrl, archivePath, options); @@ -99267,7 +99267,7 @@ var require_cache5 = __commonJS({ throw new Error(`Path Validation Error: Path(s) specified in the action for caching do(es) not exist, hence no cache is being saved.`); } const archiveFolder = yield utils.createTempDirectory(); - const archivePath = path17.join(archiveFolder, utils.getCacheFileName(compressionMethod)); + const archivePath = path18.join(archiveFolder, utils.getCacheFileName(compressionMethod)); core16.debug(`Archive Path: ${archivePath}`); try { yield (0, tar_1.createTar)(archiveFolder, cachePaths, compressionMethod); @@ -99331,7 +99331,7 @@ var require_cache5 = __commonJS({ throw new Error(`Path Validation Error: Path(s) specified in the action for caching do(es) not exist, hence no cache is being saved.`); } const archiveFolder = yield utils.createTempDirectory(); - const archivePath = path17.join(archiveFolder, utils.getCacheFileName(compressionMethod)); + const archivePath = path18.join(archiveFolder, utils.getCacheFileName(compressionMethod)); core16.debug(`Archive Path: ${archivePath}`); try { yield (0, tar_1.createTar)(archiveFolder, cachePaths, compressionMethod); @@ -99481,7 +99481,7 @@ var require_manifest = __commonJS({ var core_1 = require_core(); var os6 = require("os"); var cp = require("child_process"); - var fs16 = require("fs"); + var fs17 = require("fs"); function _findMatch(versionSpec, stable, candidates, archFilter) { return __awaiter2(this, void 0, void 0, function* () { const platFilter = os6.platform(); @@ -99543,10 +99543,10 @@ var require_manifest = __commonJS({ const lsbReleaseFile = "/etc/lsb-release"; const osReleaseFile = "/etc/os-release"; let contents = ""; - if (fs16.existsSync(lsbReleaseFile)) { - contents = fs16.readFileSync(lsbReleaseFile).toString(); - } else if (fs16.existsSync(osReleaseFile)) { - contents = fs16.readFileSync(osReleaseFile).toString(); + if (fs17.existsSync(lsbReleaseFile)) { + contents = fs17.readFileSync(lsbReleaseFile).toString(); + } else if (fs17.existsSync(osReleaseFile)) { + contents = fs17.readFileSync(osReleaseFile).toString(); } return contents; } @@ -99755,10 +99755,10 @@ var require_tool_cache = __commonJS({ var core16 = __importStar2(require_core()); var io7 = __importStar2(require_io()); var crypto3 = __importStar2(require("crypto")); - var fs16 = __importStar2(require("fs")); + var fs17 = __importStar2(require("fs")); var mm = __importStar2(require_manifest()); var os6 = __importStar2(require("os")); - var path17 = __importStar2(require("path")); + var path18 = __importStar2(require("path")); var httpm = __importStar2(require_lib()); var semver10 = __importStar2(require_semver2()); var stream2 = __importStar2(require("stream")); @@ -99779,8 +99779,8 @@ var require_tool_cache = __commonJS({ var userAgent2 = "actions/tool-cache"; function downloadTool2(url, dest, auth2, headers) { return __awaiter2(this, void 0, void 0, function* () { - dest = dest || path17.join(_getTempDirectory(), crypto3.randomUUID()); - yield io7.mkdirP(path17.dirname(dest)); + dest = dest || path18.join(_getTempDirectory(), crypto3.randomUUID()); + yield io7.mkdirP(path18.dirname(dest)); core16.debug(`Downloading ${url}`); core16.debug(`Destination ${dest}`); const maxAttempts = 3; @@ -99801,7 +99801,7 @@ var require_tool_cache = __commonJS({ } function downloadToolAttempt(url, dest, auth2, headers) { return __awaiter2(this, void 0, void 0, function* () { - if (fs16.existsSync(dest)) { + if (fs17.existsSync(dest)) { throw new Error(`Destination file path ${dest} already exists`); } const http = new httpm.HttpClient(userAgent2, [], { @@ -99825,7 +99825,7 @@ var require_tool_cache = __commonJS({ const readStream = responseMessageFactory(); let succeeded = false; try { - yield pipeline(readStream, fs16.createWriteStream(dest)); + yield pipeline(readStream, fs17.createWriteStream(dest)); core16.debug("download complete"); succeeded = true; return dest; @@ -99870,7 +99870,7 @@ var require_tool_cache = __commonJS({ process.chdir(originalCwd); } } else { - const escapedScript = path17.join(__dirname, "..", "scripts", "Invoke-7zdec.ps1").replace(/'/g, "''").replace(/"|\n|\r/g, ""); + const escapedScript = path18.join(__dirname, "..", "scripts", "Invoke-7zdec.ps1").replace(/'/g, "''").replace(/"|\n|\r/g, ""); const escapedFile = file.replace(/'/g, "''").replace(/"|\n|\r/g, ""); const escapedTarget = dest.replace(/'/g, "''").replace(/"|\n|\r/g, ""); const command = `& '${escapedScript}' -Source '${escapedFile}' -Target '${escapedTarget}'`; @@ -100037,12 +100037,12 @@ var require_tool_cache = __commonJS({ arch2 = arch2 || os6.arch(); core16.debug(`Caching tool ${tool} ${version} ${arch2}`); core16.debug(`source dir: ${sourceDir}`); - if (!fs16.statSync(sourceDir).isDirectory()) { + if (!fs17.statSync(sourceDir).isDirectory()) { throw new Error("sourceDir is not a directory"); } const destPath = yield _createToolPath(tool, version, arch2); - for (const itemName of fs16.readdirSync(sourceDir)) { - const s = path17.join(sourceDir, itemName); + for (const itemName of fs17.readdirSync(sourceDir)) { + const s = path18.join(sourceDir, itemName); yield io7.cp(s, destPath, { recursive: true }); } _completeToolPath(tool, version, arch2); @@ -100055,11 +100055,11 @@ var require_tool_cache = __commonJS({ arch2 = arch2 || os6.arch(); core16.debug(`Caching tool ${tool} ${version} ${arch2}`); core16.debug(`source file: ${sourceFile}`); - if (!fs16.statSync(sourceFile).isFile()) { + if (!fs17.statSync(sourceFile).isFile()) { throw new Error("sourceFile is not a file"); } const destFolder = yield _createToolPath(tool, version, arch2); - const destPath = path17.join(destFolder, targetFile); + const destPath = path18.join(destFolder, targetFile); core16.debug(`destination file ${destPath}`); yield io7.cp(sourceFile, destPath); _completeToolPath(tool, version, arch2); @@ -100082,9 +100082,9 @@ var require_tool_cache = __commonJS({ let toolPath = ""; if (versionSpec) { versionSpec = semver10.clean(versionSpec) || ""; - const cachePath = path17.join(_getCacheDirectory(), toolName, versionSpec, arch2); + const cachePath = path18.join(_getCacheDirectory(), toolName, versionSpec, arch2); core16.debug(`checking cache: ${cachePath}`); - if (fs16.existsSync(cachePath) && fs16.existsSync(`${cachePath}.complete`)) { + if (fs17.existsSync(cachePath) && fs17.existsSync(`${cachePath}.complete`)) { core16.debug(`Found tool in cache ${toolName} ${versionSpec} ${arch2}`); toolPath = cachePath; } else { @@ -100096,13 +100096,13 @@ var require_tool_cache = __commonJS({ function findAllVersions2(toolName, arch2) { const versions = []; arch2 = arch2 || os6.arch(); - const toolPath = path17.join(_getCacheDirectory(), toolName); - if (fs16.existsSync(toolPath)) { - const children = fs16.readdirSync(toolPath); + const toolPath = path18.join(_getCacheDirectory(), toolName); + if (fs17.existsSync(toolPath)) { + const children = fs17.readdirSync(toolPath); for (const child of children) { if (isExplicitVersion(child)) { - const fullPath = path17.join(toolPath, child, arch2 || ""); - if (fs16.existsSync(fullPath) && fs16.existsSync(`${fullPath}.complete`)) { + const fullPath = path18.join(toolPath, child, arch2 || ""); + if (fs17.existsSync(fullPath) && fs17.existsSync(`${fullPath}.complete`)) { versions.push(child); } } @@ -100153,7 +100153,7 @@ var require_tool_cache = __commonJS({ function _createExtractFolder(dest) { return __awaiter2(this, void 0, void 0, function* () { if (!dest) { - dest = path17.join(_getTempDirectory(), crypto3.randomUUID()); + dest = path18.join(_getTempDirectory(), crypto3.randomUUID()); } yield io7.mkdirP(dest); return dest; @@ -100161,7 +100161,7 @@ var require_tool_cache = __commonJS({ } function _createToolPath(tool, version, arch2) { return __awaiter2(this, void 0, void 0, function* () { - const folderPath = path17.join(_getCacheDirectory(), tool, semver10.clean(version) || version, arch2 || ""); + const folderPath = path18.join(_getCacheDirectory(), tool, semver10.clean(version) || version, arch2 || ""); core16.debug(`destination ${folderPath}`); const markerPath = `${folderPath}.complete`; yield io7.rmRF(folderPath); @@ -100171,9 +100171,9 @@ var require_tool_cache = __commonJS({ }); } function _completeToolPath(tool, version, arch2) { - const folderPath = path17.join(_getCacheDirectory(), tool, semver10.clean(version) || version, arch2 || ""); + const folderPath = path18.join(_getCacheDirectory(), tool, semver10.clean(version) || version, arch2 || ""); const markerPath = `${folderPath}.complete`; - fs16.writeFileSync(markerPath, ""); + fs17.writeFileSync(markerPath, ""); core16.debug("finished caching tool"); } function isExplicitVersion(versionSpec) { @@ -100691,8 +100691,8 @@ var require_follow_redirects = __commonJS({ } return parsed; } - function resolveUrl(relative2, base) { - return useNativeURL ? new URL2(relative2, base) : parseUrl2(url.resolve(base, relative2)); + function resolveUrl(relative3, base) { + return useNativeURL ? new URL2(relative3, base) : parseUrl2(url.resolve(base, relative3)); } function validateUrl(input) { if (/^\[/.test(input.hostname) && !/^\[[:0-9a-f]+\]$/i.test(input.hostname)) { @@ -100784,8 +100784,8 @@ __export(init_action_exports, { CODEQL_VERSION_JAR_MINIMIZATION: () => CODEQL_VERSION_JAR_MINIMIZATION }); module.exports = __toCommonJS(init_action_exports); -var fs15 = __toESM(require("fs")); -var path16 = __toESM(require("path")); +var fs16 = __toESM(require("fs")); +var path17 = __toESM(require("path")); var core15 = __toESM(require_core()); var github3 = __toESM(require_github()); var io6 = __toESM(require_io()); @@ -100869,21 +100869,21 @@ async function getFolderSize(itemPath, options) { getFolderSize.loose = async (itemPath, options) => await core(itemPath, options); getFolderSize.strict = async (itemPath, options) => await core(itemPath, options, { strict: true }); async function core(rootItemPath, options = {}, returnType = {}) { - const fs16 = options.fs || await import("node:fs/promises"); + const fs17 = options.fs || await import("node:fs/promises"); let folderSize = 0n; const foundInos = /* @__PURE__ */ new Set(); const errors = []; await processItem(rootItemPath); async function processItem(itemPath) { if (options.ignore?.test(itemPath)) return; - const stats = returnType.strict ? await fs16.lstat(itemPath, { bigint: true }) : await fs16.lstat(itemPath, { bigint: true }).catch((error3) => errors.push(error3)); + const stats = returnType.strict ? await fs17.lstat(itemPath, { bigint: true }) : await fs17.lstat(itemPath, { bigint: true }).catch((error3) => errors.push(error3)); if (typeof stats !== "object") return; if (!foundInos.has(stats.ino)) { foundInos.add(stats.ino); folderSize += stats.size; } if (stats.isDirectory()) { - const directoryItems = returnType.strict ? await fs16.readdir(itemPath) : await fs16.readdir(itemPath).catch((error3) => errors.push(error3)); + const directoryItems = returnType.strict ? await fs17.readdir(itemPath) : await fs17.readdir(itemPath).catch((error3) => errors.push(error3)); if (typeof directoryItems !== "object") return; await Promise.all( directoryItems.map( @@ -104641,8 +104641,8 @@ function getDependencyCachingEnabled() { } // src/config-utils.ts -var fs7 = __toESM(require("fs")); -var path9 = __toESM(require("path")); +var fs8 = __toESM(require("fs")); +var path10 = __toESM(require("path")); var import_perf_hooks = require("perf_hooks"); var core9 = __toESM(require_core()); @@ -105176,6 +105176,10 @@ function makeTelemetryDiagnostic(id, name, attributes) { }); } +// src/diff-informed-analysis-utils.ts +var fs5 = __toESM(require("fs")); +var path7 = __toESM(require("path")); + // src/feature-flags.ts var fs4 = __toESM(require("fs")); var path6 = __toESM(require("path")); @@ -105316,8 +105320,8 @@ var getFileOidsUnderPath = async function(basePath) { const match = line.match(regex); if (match) { const oid = match[1]; - const path17 = decodeGitFilePath(match[2]); - fileOidMap[path17] = oid; + const path18 = decodeGitFilePath(match[2]); + fileOidMap[path18] = oid; } else { throw new Error(`Unexpected "git ls-files" output: ${line}`); } @@ -105451,10 +105455,12 @@ async function readBaseDatabaseOidsFile(config, logger) { async function writeOverlayChangesFile(config, sourceRoot, logger) { const baseFileOids = await readBaseDatabaseOidsFile(config, logger); const overlayFileOids = await getFileOidsUnderPath(sourceRoot); - const changedFiles = computeChangedFiles(baseFileOids, overlayFileOids); + const oidChangedFiles = computeChangedFiles(baseFileOids, overlayFileOids); logger.info( - `Found ${changedFiles.length} changed file(s) under ${sourceRoot}.` + `Found ${oidChangedFiles.length} changed file(s) under ${sourceRoot} from OID comparison.` ); + const diffRangeFiles = await getDiffRangeFilePaths(sourceRoot, logger); + const changedFiles = [.../* @__PURE__ */ new Set([...oidChangedFiles, ...diffRangeFiles])]; const changedFilesJson = JSON.stringify({ changes: changedFiles }); const overlayChangesFile = path5.join( getTemporaryDirectory(), @@ -105480,6 +105486,48 @@ function computeChangedFiles(baseFileOids, overlayFileOids) { } return changes; } +async function getDiffRangeFilePaths(sourceRoot, logger) { + const jsonFilePath = path5.join(getTemporaryDirectory(), "pr-diff-range.json"); + if (!fs3.existsSync(jsonFilePath)) { + return []; + } + let diffRanges; + try { + diffRanges = JSON.parse(fs3.readFileSync(jsonFilePath, "utf8")); + } catch (e) { + logger.warning( + `Failed to parse diff ranges JSON file at ${jsonFilePath}: ${e}` + ); + return []; + } + logger.debug( + `Read ${diffRanges.length} diff range(s) from ${jsonFilePath} for overlay changes.` + ); + const repoRelativePaths = [...new Set(diffRanges.map((r) => r.path))]; + const repoRoot = await getGitRoot(sourceRoot); + if (repoRoot === void 0) { + logger.warning( + "Cannot determine git root; returning diff range paths as-is." + ); + return repoRelativePaths; + } + const sourceRootRelPrefix = path5.relative(repoRoot, sourceRoot).replaceAll(path5.sep, "/"); + if (sourceRootRelPrefix === "") { + return repoRelativePaths; + } + const prefixWithSlash = `${sourceRootRelPrefix}/`; + const result = []; + for (const p of repoRelativePaths) { + if (p.startsWith(prefixWithSlash)) { + result.push(p.slice(prefixWithSlash.length)); + } else { + logger.debug( + `Skipping diff range path "${p}" (not under source root "${sourceRootRelPrefix}").` + ); + } + } + return result; +} var CACHE_VERSION = 1; var CACHE_PREFIX = "codeql-overlay-base-database"; var MAX_CACHE_OPERATION_MS = 6e5; @@ -106196,6 +106244,128 @@ async function getDiffInformedAnalysisBranches(codeql, features, logger) { } return branches; } +function getDiffRangesJsonFilePath() { + return path7.join(getTemporaryDirectory(), "pr-diff-range.json"); +} +function writeDiffRangesJsonFile(logger, ranges) { + const jsonContents = JSON.stringify(ranges, null, 2); + const jsonFilePath = getDiffRangesJsonFilePath(); + fs5.writeFileSync(jsonFilePath, jsonContents); + logger.debug( + `Wrote pr-diff-range JSON file to ${jsonFilePath}: +${jsonContents}` + ); +} +async function getPullRequestEditedDiffRanges(branches, logger) { + const fileDiffs = await getFileDiffsWithBasehead(branches, logger); + if (fileDiffs === void 0) { + return void 0; + } + if (fileDiffs.length >= 300) { + logger.warning( + `Cannot retrieve the full diff because there are too many (${fileDiffs.length}) changed files in the pull request.` + ); + return void 0; + } + const results = []; + for (const filediff of fileDiffs) { + const diffRanges = getDiffRanges(filediff, logger); + if (diffRanges === void 0) { + return void 0; + } + results.push(...diffRanges); + } + return results; +} +async function getFileDiffsWithBasehead(branches, logger) { + const repositoryNwo = getRepositoryNwoFromEnv( + "CODE_SCANNING_REPOSITORY", + "GITHUB_REPOSITORY" + ); + const basehead = `${branches.base}...${branches.head}`; + try { + const response = await getApiClient().rest.repos.compareCommitsWithBasehead( + { + owner: repositoryNwo.owner, + repo: repositoryNwo.repo, + basehead, + per_page: 1 + } + ); + logger.debug( + `Response from compareCommitsWithBasehead(${basehead}): +${JSON.stringify(response, null, 2)}` + ); + return response.data.files; + } catch (error3) { + if (error3.status) { + logger.warning(`Error retrieving diff ${basehead}: ${error3.message}`); + logger.debug( + `Error running compareCommitsWithBasehead(${basehead}): +Request: ${JSON.stringify(error3.request, null, 2)} +Error Response: ${JSON.stringify(error3.response, null, 2)}` + ); + return void 0; + } else { + throw error3; + } + } +} +function getDiffRanges(fileDiff, logger) { + if (fileDiff.patch === void 0) { + if (fileDiff.changes === 0) { + return []; + } + return [ + { + path: fileDiff.filename, + startLine: 0, + endLine: 0 + } + ]; + } + let currentLine = 0; + let additionRangeStartLine = void 0; + const diffRanges = []; + const diffLines = fileDiff.patch.split("\n"); + diffLines.push(" "); + for (const diffLine of diffLines) { + if (diffLine.startsWith("-")) { + continue; + } + if (diffLine.startsWith("+")) { + if (additionRangeStartLine === void 0) { + additionRangeStartLine = currentLine; + } + currentLine++; + continue; + } + if (additionRangeStartLine !== void 0) { + diffRanges.push({ + path: fileDiff.filename, + startLine: additionRangeStartLine, + endLine: currentLine - 1 + }); + additionRangeStartLine = void 0; + } + if (diffLine.startsWith("@@ ")) { + const match = diffLine.match(/^@@ -\d+(?:,\d+)? \+(\d+)(?:,\d+)? @@/); + if (match === null) { + logger.warning( + `Cannot parse diff hunk header for ${fileDiff.filename}: ${diffLine}` + ); + return void 0; + } + currentLine = parseInt(match[1], 10); + continue; + } + if (diffLine.startsWith(" ")) { + currentLine++; + continue; + } + } + return diffRanges; +} // src/languages.ts var KnownLanguage = /* @__PURE__ */ ((KnownLanguage2) => { @@ -106271,13 +106441,13 @@ Improved incremental analysis will be automatically retried when the next versio } // src/overlay/status.ts -var fs5 = __toESM(require("fs")); -var path7 = __toESM(require("path")); +var fs6 = __toESM(require("fs")); +var path8 = __toESM(require("path")); var actionsCache2 = __toESM(require_cache5()); var MAX_CACHE_OPERATION_MS2 = 3e4; var STATUS_FILE_NAME = "overlay-status.json"; function getStatusFilePath(languages) { - return path7.join( + return path8.join( getTemporaryDirectory(), "overlay-status", [...languages].sort().join("+"), @@ -106304,7 +106474,7 @@ async function getOverlayStatus(codeql, languages, diskUsage, logger) { const cacheKey3 = await getCacheKey(codeql, languages, diskUsage); const statusFile = getStatusFilePath(languages); try { - await fs5.promises.mkdir(path7.dirname(statusFile), { recursive: true }); + await fs6.promises.mkdir(path8.dirname(statusFile), { recursive: true }); const foundKey = await waitForResultWithTimeLimit( MAX_CACHE_OPERATION_MS2, actionsCache2.restoreCache([statusFile], cacheKey3), @@ -106316,13 +106486,13 @@ async function getOverlayStatus(codeql, languages, diskUsage, logger) { logger.debug("No overlay status found in Actions cache."); return void 0; } - if (!fs5.existsSync(statusFile)) { + if (!fs6.existsSync(statusFile)) { logger.debug( "Overlay status cache entry found but status file is missing." ); return void 0; } - const contents = await fs5.promises.readFile(statusFile, "utf-8"); + const contents = await fs6.promises.readFile(statusFile, "utf-8"); const parsed = JSON.parse(contents); if (!isObject2(parsed) || typeof parsed["attemptedToBuildOverlayBaseDatabase"] !== "boolean" || typeof parsed["builtOverlayBaseDatabase"] !== "boolean") { logger.debug( @@ -106344,8 +106514,8 @@ async function getCacheKey(codeql, languages, diskUsage) { } // src/trap-caching.ts -var fs6 = __toESM(require("fs")); -var path8 = __toESM(require("path")); +var fs7 = __toESM(require("fs")); +var path9 = __toESM(require("path")); var actionsCache3 = __toESM(require_cache5()); var CACHE_VERSION2 = 1; var CODEQL_TRAP_CACHE_PREFIX = "codeql-trap"; @@ -106361,13 +106531,13 @@ async function downloadTrapCaches(codeql, languages, logger) { `Found ${languagesSupportingCaching.length} languages that support TRAP caching` ); if (languagesSupportingCaching.length === 0) return result; - const cachesDir = path8.join( + const cachesDir = path9.join( getTemporaryDirectory(), "trapCaches" ); for (const language of languagesSupportingCaching) { - const cacheDir = path8.join(cachesDir, language); - fs6.mkdirSync(cacheDir, { recursive: true }); + const cacheDir = path9.join(cachesDir, language); + fs7.mkdirSync(cacheDir, { recursive: true }); result[language] = cacheDir; } if (await isAnalyzingDefaultBranch()) { @@ -106379,7 +106549,7 @@ async function downloadTrapCaches(codeql, languages, logger) { let baseSha = "unknown"; const eventPath = process.env.GITHUB_EVENT_PATH; if (getWorkflowEventName() === "pull_request" && eventPath !== void 0) { - const event = JSON.parse(fs6.readFileSync(path8.resolve(eventPath), "utf-8")); + const event = JSON.parse(fs7.readFileSync(path9.resolve(eventPath), "utf-8")); baseSha = event.pull_request?.base?.sha || baseSha; } for (const language of languages) { @@ -106486,9 +106656,9 @@ async function getSupportedLanguageMap(codeql, logger) { } var baseWorkflowsPath = ".github/workflows"; function hasActionsWorkflows(sourceRoot) { - const workflowsPath = path9.resolve(sourceRoot, baseWorkflowsPath); - const stats = fs7.lstatSync(workflowsPath, { throwIfNoEntry: false }); - return stats !== void 0 && stats.isDirectory() && fs7.readdirSync(workflowsPath).length > 0; + const workflowsPath = path10.resolve(sourceRoot, baseWorkflowsPath); + const stats = fs8.lstatSync(workflowsPath, { throwIfNoEntry: false }); + return stats !== void 0 && stats.isDirectory() && fs8.readdirSync(workflowsPath).length > 0; } async function getRawLanguagesInRepo(repository, sourceRoot, logger) { logger.debug( @@ -106644,8 +106814,8 @@ async function downloadCacheWithTime(codeQL, languages, logger) { async function loadUserConfig(logger, configFile, workspacePath, apiDetails, tempDir, validateConfig) { if (isLocal(configFile)) { if (configFile !== userConfigFromActionPath(tempDir)) { - configFile = path9.resolve(workspacePath, configFile); - if (!(configFile + path9.sep).startsWith(workspacePath + path9.sep)) { + configFile = path10.resolve(workspacePath, configFile); + if (!(configFile + path10.sep).startsWith(workspacePath + path10.sep)) { throw new ConfigurationError( getConfigFileOutsideWorkspaceErrorMessage(configFile) ); @@ -106911,10 +107081,10 @@ async function setCppTrapCachingEnvironmentVariables(config, logger) { } } function dbLocationOrDefault(dbLocation, tempDir) { - return dbLocation || path9.resolve(tempDir, "codeql_databases"); + return dbLocation || path10.resolve(tempDir, "codeql_databases"); } function userConfigFromActionPath(tempDir) { - return path9.resolve(tempDir, "user-config-from-action.yml"); + return path10.resolve(tempDir, "user-config-from-action.yml"); } function hasQueryCustomisation(userConfig) { return isDefined2(userConfig["disable-default-queries"]) || isDefined2(userConfig.queries) || isDefined2(userConfig["query-filters"]); @@ -106928,7 +107098,7 @@ async function initConfig(features, inputs) { ); } inputs.configFile = userConfigFromActionPath(tempDir); - fs7.writeFileSync(inputs.configFile, inputs.configInput); + fs8.writeFileSync(inputs.configFile, inputs.configInput); logger.debug(`Using config from action input: ${inputs.configFile}`); } let userConfig = {}; @@ -107071,7 +107241,7 @@ function isLocal(configPath) { return configPath.indexOf("@") === -1; } function getLocalConfig(logger, configFile, validateConfig) { - if (!fs7.existsSync(configFile)) { + if (!fs8.existsSync(configFile)) { throw new ConfigurationError( getConfigFileDoesNotExistErrorMessage(configFile) ); @@ -107079,7 +107249,7 @@ function getLocalConfig(logger, configFile, validateConfig) { return parseUserConfig( logger, configFile, - fs7.readFileSync(configFile, "utf-8"), + fs8.readFileSync(configFile, "utf-8"), validateConfig ); } @@ -107119,13 +107289,13 @@ async function getRemoteConfig(logger, configFile, apiDetails, validateConfig) { ); } function getPathToParsedConfigFile(tempDir) { - return path9.join(tempDir, "config"); + return path10.join(tempDir, "config"); } async function saveConfig(config, logger) { const configString = JSON.stringify(config); const configFile = getPathToParsedConfigFile(config.tempDir); - fs7.mkdirSync(path9.dirname(configFile), { recursive: true }); - fs7.writeFileSync(configFile, configString, "utf8"); + fs8.mkdirSync(path10.dirname(configFile), { recursive: true }); + fs8.writeFileSync(configFile, configString, "utf8"); logger.debug("Saved config:"); logger.debug(configString); } @@ -107135,9 +107305,9 @@ async function generateRegistries(registriesInput, tempDir, logger) { let qlconfigFile; if (registries) { const qlconfig = createRegistriesBlock(registries); - qlconfigFile = path9.join(tempDir, "qlconfig.yml"); + qlconfigFile = path10.join(tempDir, "qlconfig.yml"); const qlconfigContents = dump(qlconfig); - fs7.writeFileSync(qlconfigFile, qlconfigContents, "utf8"); + fs8.writeFileSync(qlconfigFile, qlconfigContents, "utf8"); logger.debug("Generated qlconfig.yml:"); logger.debug(qlconfigContents); registriesAuthTokens = registries.map((registry) => `${registry.url}=${registry.token}`).join(","); @@ -107455,16 +107625,16 @@ var internal = { }; // src/init.ts -var fs13 = __toESM(require("fs")); -var path14 = __toESM(require("path")); +var fs14 = __toESM(require("fs")); +var path15 = __toESM(require("path")); var core12 = __toESM(require_core()); var toolrunner4 = __toESM(require_toolrunner()); var github2 = __toESM(require_github()); var io5 = __toESM(require_io()); // src/codeql.ts -var fs12 = __toESM(require("fs")); -var path13 = __toESM(require("path")); +var fs13 = __toESM(require("fs")); +var path14 = __toESM(require("path")); var core11 = __toESM(require_core()); var toolrunner3 = __toESM(require_toolrunner()); @@ -107711,15 +107881,15 @@ function wrapCliConfigurationError(cliError) { } // src/setup-codeql.ts -var fs10 = __toESM(require("fs")); -var path11 = __toESM(require("path")); +var fs11 = __toESM(require("fs")); +var path12 = __toESM(require("path")); var toolcache3 = __toESM(require_tool_cache()); var import_fast_deep_equal = __toESM(require_fast_deep_equal()); var semver8 = __toESM(require_semver2()); // src/tar.ts var import_child_process = require("child_process"); -var fs8 = __toESM(require("fs")); +var fs9 = __toESM(require("fs")); var stream = __toESM(require("stream")); var import_toolrunner = __toESM(require_toolrunner()); var io4 = __toESM(require_io()); @@ -107792,7 +107962,7 @@ async function isZstdAvailable(logger) { } } async function extract(tarPath, dest, compressionMethod, tarVersion, logger) { - fs8.mkdirSync(dest, { recursive: true }); + fs9.mkdirSync(dest, { recursive: true }); switch (compressionMethod) { case "gzip": return await toolcache.extractTar(tarPath, dest); @@ -107876,9 +108046,9 @@ function inferCompressionMethod(tarPath) { } // src/tools-download.ts -var fs9 = __toESM(require("fs")); +var fs10 = __toESM(require("fs")); var os4 = __toESM(require("os")); -var path10 = __toESM(require("path")); +var path11 = __toESM(require("path")); var import_perf_hooks2 = require("perf_hooks"); var core10 = __toESM(require_core()); var import_http_client = __toESM(require_lib()); @@ -107983,7 +108153,7 @@ async function downloadAndExtract(codeqlURL, compressionMethod, dest, authorizat }; } async function downloadAndExtractZstdWithStreaming(codeqlURL, dest, authorization, headers, tarVersion, logger) { - fs9.mkdirSync(dest, { recursive: true }); + fs10.mkdirSync(dest, { recursive: true }); const agent = new import_http_client.HttpClient().getAgent(codeqlURL); headers = Object.assign( { "User-Agent": "CodeQL Action" }, @@ -108011,7 +108181,7 @@ async function downloadAndExtractZstdWithStreaming(codeqlURL, dest, authorizatio await extractTarZst(response, dest, tarVersion, logger); } function getToolcacheDirectory(version) { - return path10.join( + return path11.join( getRequiredEnvParam("RUNNER_TOOL_CACHE"), TOOLCACHE_TOOL_NAME, semver7.clean(version) || version, @@ -108020,7 +108190,7 @@ function getToolcacheDirectory(version) { } function writeToolcacheMarkerFile(extractedPath, logger) { const markerFilePath = `${extractedPath}.complete`; - fs9.writeFileSync(markerFilePath, ""); + fs10.writeFileSync(markerFilePath, ""); logger.info(`Created toolcache marker file ${markerFilePath}`); } function sanitizeUrlForStatusReport(url) { @@ -108155,7 +108325,7 @@ async function findOverridingToolsInCache(humanReadableVersion, logger) { const candidates = toolcache3.findAllVersions("CodeQL").filter(isGoodVersion).map((version) => ({ folder: toolcache3.find("CodeQL", version), version - })).filter(({ folder }) => fs10.existsSync(path11.join(folder, "pinned-version"))); + })).filter(({ folder }) => fs11.existsSync(path12.join(folder, "pinned-version"))); if (candidates.length === 1) { const candidate = candidates[0]; logger.debug( @@ -108554,7 +108724,7 @@ async function useZstdBundle(cliVersion2, tarSupportsZstd) { ); } function getTempExtractionDir(tempDir) { - return path11.join(tempDir, v4_default()); + return path12.join(tempDir, v4_default()); } async function getNightlyToolsUrl(logger) { const zstdAvailability = await isZstdAvailable(logger); @@ -108602,8 +108772,8 @@ function isReservedToolsValue(tools) { } // src/tracer-config.ts -var fs11 = __toESM(require("fs")); -var path12 = __toESM(require("path")); +var fs12 = __toESM(require("fs")); +var path13 = __toESM(require("path")); async function shouldEnableIndirectTracing(codeql, config) { if (config.buildMode === "none" /* None */) { return false; @@ -108615,8 +108785,8 @@ async function shouldEnableIndirectTracing(codeql, config) { } async function getTracerConfigForCluster(config) { const tracingEnvVariables = JSON.parse( - fs11.readFileSync( - path12.resolve( + fs12.readFileSync( + path13.resolve( config.dbLocation, "temp/tracingEnvironment/start-tracing.json" ), @@ -108663,7 +108833,7 @@ async function setupCodeQL(toolsInput, apiDetails, tempDir, variant, defaultCliV toolsDownloadStatusReport )}` ); - let codeqlCmd = path13.join(codeqlFolder, "codeql", "codeql"); + let codeqlCmd = path14.join(codeqlFolder, "codeql", "codeql"); if (process.platform === "win32") { codeqlCmd += ".exe"; } else if (process.platform !== "linux" && process.platform !== "darwin") { @@ -108719,12 +108889,12 @@ async function getCodeQLForCmd(cmd, checkVersion) { }, async isTracedLanguage(language) { const extractorPath = await this.resolveExtractor(language); - const tracingConfigPath = path13.join( + const tracingConfigPath = path14.join( extractorPath, "tools", "tracing-config.lua" ); - return fs12.existsSync(tracingConfigPath); + return fs13.existsSync(tracingConfigPath); }, async isScannedLanguage(language) { return !await this.isTracedLanguage(language); @@ -108801,7 +108971,7 @@ async function getCodeQLForCmd(cmd, checkVersion) { }, async runAutobuild(config, language) { applyAutobuildAzurePipelinesTimeoutFix(); - const autobuildCmd = path13.join( + const autobuildCmd = path14.join( await this.resolveExtractor(language), "tools", process.platform === "win32" ? "autobuild.cmd" : "autobuild.sh" @@ -109200,7 +109370,7 @@ async function writeCodeScanningConfigFile(config, logger) { logger.startGroup("Augmented user configuration file contents"); logger.info(dump(augmentedConfig)); logger.endGroup(); - fs12.writeFileSync(codeScanningConfigFile, dump(augmentedConfig)); + fs13.writeFileSync(codeScanningConfigFile, dump(augmentedConfig)); return codeScanningConfigFile; } var TRAP_CACHE_SIZE_MB = 1024; @@ -109223,7 +109393,7 @@ async function getTrapCachingExtractorConfigArgsForLang(config, language) { ]; } function getGeneratedCodeScanningConfigPath(config) { - return path13.resolve(config.tempDir, "user-config.yaml"); + return path14.resolve(config.tempDir, "user-config.yaml"); } function getExtractionVerbosityArguments(enableDebugLogging) { return enableDebugLogging ? [`--verbosity=${EXTRACTION_DEBUG_MODE_VERBOSITY}`] : []; @@ -109278,7 +109448,7 @@ async function initConfig2(features, inputs) { }); } async function runDatabaseInitCluster(databaseInitEnvironment, codeql, config, sourceRoot, processName, qlconfigFile, logger) { - fs13.mkdirSync(config.dbLocation, { recursive: true }); + fs14.mkdirSync(config.dbLocation, { recursive: true }); await wrapEnvironment( databaseInitEnvironment, async () => await codeql.databaseInitCluster( @@ -109313,25 +109483,25 @@ async function checkPacksForOverlayCompatibility(codeql, config, logger) { } function checkPackForOverlayCompatibility(packDir, codeQlOverlayVersion, logger) { try { - let qlpackPath = path14.join(packDir, "qlpack.yml"); - if (!fs13.existsSync(qlpackPath)) { - qlpackPath = path14.join(packDir, "codeql-pack.yml"); + let qlpackPath = path15.join(packDir, "qlpack.yml"); + if (!fs14.existsSync(qlpackPath)) { + qlpackPath = path15.join(packDir, "codeql-pack.yml"); } const qlpackContents = load( - fs13.readFileSync(qlpackPath, "utf8") + fs14.readFileSync(qlpackPath, "utf8") ); if (!qlpackContents.buildMetadata) { return true; } - const packInfoPath = path14.join(packDir, ".packinfo"); - if (!fs13.existsSync(packInfoPath)) { + const packInfoPath = path15.join(packDir, ".packinfo"); + if (!fs14.existsSync(packInfoPath)) { logger.warning( `The query pack at ${packDir} does not have a .packinfo file, so it cannot support overlay analysis. Recompiling the query pack with the latest CodeQL CLI should solve this problem.` ); return false; } const packInfoFileContents = JSON.parse( - fs13.readFileSync(packInfoPath, "utf8") + fs14.readFileSync(packInfoPath, "utf8") ); const packOverlayVersion = packInfoFileContents.overlayVersion; if (typeof packOverlayVersion !== "number") { @@ -109356,7 +109526,7 @@ function checkPackForOverlayCompatibility(packDir, codeQlOverlayVersion, logger) } async function checkInstallPython311(languages, codeql) { if (languages.includes("python" /* python */) && process.platform === "win32" && !(await codeql.getVersion()).features?.supportsPython312) { - const script = path14.resolve( + const script = path15.resolve( __dirname, "../python-setup", "check_python12.ps1" @@ -109366,8 +109536,8 @@ async function checkInstallPython311(languages, codeql) { ]).exec(); } } -function cleanupDatabaseClusterDirectory(config, logger, options = {}, rmSync2 = fs13.rmSync) { - if (fs13.existsSync(config.dbLocation) && (fs13.statSync(config.dbLocation).isFile() || fs13.readdirSync(config.dbLocation).length > 0)) { +function cleanupDatabaseClusterDirectory(config, logger, options = {}, rmSync2 = fs14.rmSync) { + if (fs14.existsSync(config.dbLocation) && (fs14.statSync(config.dbLocation).isFile() || fs14.readdirSync(config.dbLocation).length > 0)) { if (!options.disableExistingDirectoryWarning) { logger.warning( `The database cluster directory ${config.dbLocation} must be empty. Attempting to clean it up.` @@ -109725,8 +109895,8 @@ async function sendUnhandledErrorStatusReport(actionName, actionStartedAt, error } // src/workflow.ts -var fs14 = __toESM(require("fs")); -var path15 = __toESM(require("path")); +var fs15 = __toESM(require("fs")); +var path16 = __toESM(require("path")); var import_zlib = __toESM(require("zlib")); var core14 = __toESM(require_core()); function toCodedErrors(errors) { @@ -109877,15 +110047,15 @@ async function getWorkflow(logger) { ); } const workflowPath = await getWorkflowAbsolutePath(logger); - return load(fs14.readFileSync(workflowPath, "utf-8")); + return load(fs15.readFileSync(workflowPath, "utf-8")); } async function getWorkflowAbsolutePath(logger) { const relativePath = await getWorkflowRelativePath(); - const absolutePath = path15.join( + const absolutePath = path16.join( getRequiredEnvParam("GITHUB_WORKSPACE"), relativePath ); - if (fs14.existsSync(absolutePath)) { + if (fs15.existsSync(absolutePath)) { logger.debug( `Derived the following absolute path for the currently executing workflow: ${absolutePath}.` ); @@ -110020,7 +110190,7 @@ async function run(startedAt) { core15.exportVariable("JOB_RUN_UUID" /* JOB_RUN_UUID */, jobRunUuid); core15.exportVariable("CODEQL_ACTION_INIT_HAS_RUN" /* INIT_ACTION_HAS_RUN */, "true"); configFile = getOptionalInput("config-file"); - sourceRoot = path16.resolve( + sourceRoot = path17.resolve( getRequiredEnvParam("GITHUB_WORKSPACE"), getOptionalInput("source-root") || "" ); @@ -110140,6 +110310,7 @@ async function run(startedAt) { logFileCoverageOnPrsDeprecationWarning(logger); } await checkInstallPython311(config.languages, codeql); + await computeAndPersistDiffRanges(codeql, features, logger); } catch (unwrappedError) { const error3 = wrapError(unwrappedError); core15.setFailed(error3.message); @@ -110211,21 +110382,21 @@ async function run(startedAt) { )) { try { logger.debug(`Applying static binary workaround for Go`); - const tempBinPath = path16.resolve( + const tempBinPath = path17.resolve( getTemporaryDirectory(), "codeql-action-go-tracing", "bin" ); - fs15.mkdirSync(tempBinPath, { recursive: true }); + fs16.mkdirSync(tempBinPath, { recursive: true }); core15.addPath(tempBinPath); - const goWrapperPath = path16.resolve(tempBinPath, "go"); - fs15.writeFileSync( + const goWrapperPath = path17.resolve(tempBinPath, "go"); + fs16.writeFileSync( goWrapperPath, `#!/bin/bash exec ${goBinaryPath} "$@"` ); - fs15.chmodSync(goWrapperPath, "755"); + fs16.chmodSync(goWrapperPath, "755"); core15.exportVariable("CODEQL_ACTION_GO_BINARY" /* GO_BINARY_LOCATION */, goWrapperPath); } catch (e) { logger.warning( @@ -110426,6 +110597,33 @@ async function loadRepositoryProperties(repositoryNwo, logger) { return new Failure(error3); } } +async function computeAndPersistDiffRanges(codeql, features, logger) { + try { + await withGroupAsync("Compute PR diff ranges", async () => { + const branches = await getDiffInformedAnalysisBranches( + codeql, + features, + logger + ); + if (!branches) { + return; + } + const ranges = await getPullRequestEditedDiffRanges(branches, logger); + if (ranges === void 0) { + return; + } + writeDiffRangesJsonFile(logger, ranges); + const distinctFiles = new Set(ranges.map((r) => r.path)).size; + logger.info( + `Persisted ${ranges.length} diff range(s) across ${distinctFiles} file(s).` + ); + }); + } catch (e) { + logger.warning( + `Failed to compute and persist PR diff ranges: ${getErrorMessage(e)}` + ); + } +} async function recordZstdAvailability(config, zstdAvailability) { addNoLanguageDiagnostic( config, diff --git a/lib/resolve-environment-action.js b/lib/resolve-environment-action.js index cefba2d562..ce30730883 100644 --- a/lib/resolve-environment-action.js +++ b/lib/resolve-environment-action.js @@ -100540,8 +100540,8 @@ var require_follow_redirects = __commonJS({ } return parsed; } - function resolveUrl(relative, base) { - return useNativeURL ? new URL2(relative, base) : parseUrl2(url.resolve(base, relative)); + function resolveUrl(relative2, base) { + return useNativeURL ? new URL2(relative2, base) : parseUrl2(url.resolve(base, relative2)); } function validateUrl(input) { if (/^\[/.test(input.hostname) && !/^\[[:0-9a-f]+\]$/i.test(input.hostname)) { @@ -104202,6 +104202,18 @@ var decodeGitFilePath = function(filePath) { } return filePath; }; +var getGitRoot = async function(sourceRoot) { + try { + const stdout = await runGitCommand( + sourceRoot, + ["rev-parse", "--show-toplevel"], + `Cannot find Git repository root from the source root ${sourceRoot}.` + ); + return stdout.trim(); + } catch { + return void 0; + } +}; var getFileOidsUnderPath = async function(basePath) { const stdout = await runGitCommand( basePath, @@ -104324,10 +104336,12 @@ async function readBaseDatabaseOidsFile(config, logger) { async function writeOverlayChangesFile(config, sourceRoot, logger) { const baseFileOids = await readBaseDatabaseOidsFile(config, logger); const overlayFileOids = await getFileOidsUnderPath(sourceRoot); - const changedFiles = computeChangedFiles(baseFileOids, overlayFileOids); + const oidChangedFiles = computeChangedFiles(baseFileOids, overlayFileOids); logger.info( - `Found ${changedFiles.length} changed file(s) under ${sourceRoot}.` + `Found ${oidChangedFiles.length} changed file(s) under ${sourceRoot} from OID comparison.` ); + const diffRangeFiles = await getDiffRangeFilePaths(sourceRoot, logger); + const changedFiles = [.../* @__PURE__ */ new Set([...oidChangedFiles, ...diffRangeFiles])]; const changedFilesJson = JSON.stringify({ changes: changedFiles }); const overlayChangesFile = path2.join( getTemporaryDirectory(), @@ -104353,6 +104367,48 @@ function computeChangedFiles(baseFileOids, overlayFileOids) { } return changes; } +async function getDiffRangeFilePaths(sourceRoot, logger) { + const jsonFilePath = path2.join(getTemporaryDirectory(), "pr-diff-range.json"); + if (!fs2.existsSync(jsonFilePath)) { + return []; + } + let diffRanges; + try { + diffRanges = JSON.parse(fs2.readFileSync(jsonFilePath, "utf8")); + } catch (e) { + logger.warning( + `Failed to parse diff ranges JSON file at ${jsonFilePath}: ${e}` + ); + return []; + } + logger.debug( + `Read ${diffRanges.length} diff range(s) from ${jsonFilePath} for overlay changes.` + ); + const repoRelativePaths = [...new Set(diffRanges.map((r) => r.path))]; + const repoRoot = await getGitRoot(sourceRoot); + if (repoRoot === void 0) { + logger.warning( + "Cannot determine git root; returning diff range paths as-is." + ); + return repoRelativePaths; + } + const sourceRootRelPrefix = path2.relative(repoRoot, sourceRoot).replaceAll(path2.sep, "/"); + if (sourceRootRelPrefix === "") { + return repoRelativePaths; + } + const prefixWithSlash = `${sourceRootRelPrefix}/`; + const result = []; + for (const p of repoRelativePaths) { + if (p.startsWith(prefixWithSlash)) { + result.push(p.slice(prefixWithSlash.length)); + } else { + logger.debug( + `Skipping diff range path "${p}" (not under source root "${sourceRootRelPrefix}").` + ); + } + } + return result; +} // src/tools-features.ts var semver4 = __toESM(require_semver2()); diff --git a/lib/setup-codeql-action.js b/lib/setup-codeql-action.js index 8fcb624980..25807f6acc 100644 --- a/lib/setup-codeql-action.js +++ b/lib/setup-codeql-action.js @@ -100540,8 +100540,8 @@ var require_follow_redirects = __commonJS({ } return parsed; } - function resolveUrl(relative2, base) { - return useNativeURL ? new URL2(relative2, base) : parseUrl2(url.resolve(base, relative2)); + function resolveUrl(relative3, base) { + return useNativeURL ? new URL2(relative3, base) : parseUrl2(url.resolve(base, relative3)); } function validateUrl(input) { if (/^\[/.test(input.hostname) && !/^\[[:0-9a-f]+\]$/i.test(input.hostname)) { @@ -104069,6 +104069,18 @@ var decodeGitFilePath = function(filePath) { } return filePath; }; +var getGitRoot = async function(sourceRoot) { + try { + const stdout = await runGitCommand( + sourceRoot, + ["rev-parse", "--show-toplevel"], + `Cannot find Git repository root from the source root ${sourceRoot}.` + ); + return stdout.trim(); + } catch { + return void 0; + } +}; var getFileOidsUnderPath = async function(basePath) { const stdout = await runGitCommand( basePath, @@ -104216,10 +104228,12 @@ async function readBaseDatabaseOidsFile(config, logger) { async function writeOverlayChangesFile(config, sourceRoot, logger) { const baseFileOids = await readBaseDatabaseOidsFile(config, logger); const overlayFileOids = await getFileOidsUnderPath(sourceRoot); - const changedFiles = computeChangedFiles(baseFileOids, overlayFileOids); + const oidChangedFiles = computeChangedFiles(baseFileOids, overlayFileOids); logger.info( - `Found ${changedFiles.length} changed file(s) under ${sourceRoot}.` + `Found ${oidChangedFiles.length} changed file(s) under ${sourceRoot} from OID comparison.` ); + const diffRangeFiles = await getDiffRangeFilePaths(sourceRoot, logger); + const changedFiles = [.../* @__PURE__ */ new Set([...oidChangedFiles, ...diffRangeFiles])]; const changedFilesJson = JSON.stringify({ changes: changedFiles }); const overlayChangesFile = path3.join( getTemporaryDirectory(), @@ -104245,6 +104259,48 @@ function computeChangedFiles(baseFileOids, overlayFileOids) { } return changes; } +async function getDiffRangeFilePaths(sourceRoot, logger) { + const jsonFilePath = path3.join(getTemporaryDirectory(), "pr-diff-range.json"); + if (!fs3.existsSync(jsonFilePath)) { + return []; + } + let diffRanges; + try { + diffRanges = JSON.parse(fs3.readFileSync(jsonFilePath, "utf8")); + } catch (e) { + logger.warning( + `Failed to parse diff ranges JSON file at ${jsonFilePath}: ${e}` + ); + return []; + } + logger.debug( + `Read ${diffRanges.length} diff range(s) from ${jsonFilePath} for overlay changes.` + ); + const repoRelativePaths = [...new Set(diffRanges.map((r) => r.path))]; + const repoRoot = await getGitRoot(sourceRoot); + if (repoRoot === void 0) { + logger.warning( + "Cannot determine git root; returning diff range paths as-is." + ); + return repoRelativePaths; + } + const sourceRootRelPrefix = path3.relative(repoRoot, sourceRoot).replaceAll(path3.sep, "/"); + if (sourceRootRelPrefix === "") { + return repoRelativePaths; + } + const prefixWithSlash = `${sourceRootRelPrefix}/`; + const result = []; + for (const p of repoRelativePaths) { + if (p.startsWith(prefixWithSlash)) { + result.push(p.slice(prefixWithSlash.length)); + } else { + logger.debug( + `Skipping diff range path "${p}" (not under source root "${sourceRootRelPrefix}").` + ); + } + } + return result; +} // src/tools-features.ts var semver3 = __toESM(require_semver2()); diff --git a/lib/upload-lib.js b/lib/upload-lib.js index 3527c53649..4b0cfa3454 100644 --- a/lib/upload-lib.js +++ b/lib/upload-lib.js @@ -100540,8 +100540,8 @@ var require_follow_redirects = __commonJS({ } return parsed; } - function resolveUrl(relative2, base) { - return useNativeURL ? new URL2(relative2, base) : parseUrl2(url2.resolve(base, relative2)); + function resolveUrl(relative3, base) { + return useNativeURL ? new URL2(relative3, base) : parseUrl2(url2.resolve(base, relative3)); } function validateUrl(input) { if (/^\[/.test(input.hostname) && !/^\[[:0-9a-f]+\]$/i.test(input.hostname)) { @@ -107360,6 +107360,18 @@ var decodeGitFilePath = function(filePath) { } return filePath; }; +var getGitRoot = async function(sourceRoot) { + try { + const stdout = await runGitCommand( + sourceRoot, + ["rev-parse", "--show-toplevel"], + `Cannot find Git repository root from the source root ${sourceRoot}.` + ); + return stdout.trim(); + } catch { + return void 0; + } +}; var getFileOidsUnderPath = async function(basePath) { const stdout = await runGitCommand( basePath, @@ -107482,10 +107494,12 @@ async function readBaseDatabaseOidsFile(config, logger) { async function writeOverlayChangesFile(config, sourceRoot, logger) { const baseFileOids = await readBaseDatabaseOidsFile(config, logger); const overlayFileOids = await getFileOidsUnderPath(sourceRoot); - const changedFiles = computeChangedFiles(baseFileOids, overlayFileOids); + const oidChangedFiles = computeChangedFiles(baseFileOids, overlayFileOids); logger.info( - `Found ${changedFiles.length} changed file(s) under ${sourceRoot}.` + `Found ${oidChangedFiles.length} changed file(s) under ${sourceRoot} from OID comparison.` ); + const diffRangeFiles = await getDiffRangeFilePaths(sourceRoot, logger); + const changedFiles = [.../* @__PURE__ */ new Set([...oidChangedFiles, ...diffRangeFiles])]; const changedFilesJson = JSON.stringify({ changes: changedFiles }); const overlayChangesFile = path4.join( getTemporaryDirectory(), @@ -107511,6 +107525,48 @@ function computeChangedFiles(baseFileOids, overlayFileOids) { } return changes; } +async function getDiffRangeFilePaths(sourceRoot, logger) { + const jsonFilePath = path4.join(getTemporaryDirectory(), "pr-diff-range.json"); + if (!fs3.existsSync(jsonFilePath)) { + return []; + } + let diffRanges; + try { + diffRanges = JSON.parse(fs3.readFileSync(jsonFilePath, "utf8")); + } catch (e) { + logger.warning( + `Failed to parse diff ranges JSON file at ${jsonFilePath}: ${e}` + ); + return []; + } + logger.debug( + `Read ${diffRanges.length} diff range(s) from ${jsonFilePath} for overlay changes.` + ); + const repoRelativePaths = [...new Set(diffRanges.map((r) => r.path))]; + const repoRoot = await getGitRoot(sourceRoot); + if (repoRoot === void 0) { + logger.warning( + "Cannot determine git root; returning diff range paths as-is." + ); + return repoRelativePaths; + } + const sourceRootRelPrefix = path4.relative(repoRoot, sourceRoot).replaceAll(path4.sep, "/"); + if (sourceRootRelPrefix === "") { + return repoRelativePaths; + } + const prefixWithSlash = `${sourceRootRelPrefix}/`; + const result = []; + for (const p of repoRelativePaths) { + if (p.startsWith(prefixWithSlash)) { + result.push(p.slice(prefixWithSlash.length)); + } else { + logger.debug( + `Skipping diff range path "${p}" (not under source root "${sourceRootRelPrefix}").` + ); + } + } + return result; +} // src/tools-features.ts var semver4 = __toESM(require_semver2()); @@ -107750,7 +107806,14 @@ function readDiffRangesJsonFile(logger) { `Read pr-diff-range JSON file from ${jsonFilePath}: ${jsonContents}` ); - return JSON.parse(jsonContents); + try { + return JSON.parse(jsonContents); + } catch (e) { + logger.warning( + `Failed to parse diff ranges JSON file at ${jsonFilePath}: ${e}` + ); + return void 0; + } } // src/overlay/status.ts diff --git a/lib/upload-sarif-action.js b/lib/upload-sarif-action.js index da345bf9a9..5f495c7b41 100644 --- a/lib/upload-sarif-action.js +++ b/lib/upload-sarif-action.js @@ -100540,8 +100540,8 @@ var require_follow_redirects = __commonJS({ } return parsed; } - function resolveUrl(relative2, base) { - return useNativeURL ? new URL2(relative2, base) : parseUrl2(url2.resolve(base, relative2)); + function resolveUrl(relative3, base) { + return useNativeURL ? new URL2(relative3, base) : parseUrl2(url2.resolve(base, relative3)); } function validateUrl(input) { if (/^\[/.test(input.hostname) && !/^\[[:0-9a-f]+\]$/i.test(input.hostname)) { @@ -107044,6 +107044,18 @@ var decodeGitFilePath = function(filePath) { } return filePath; }; +var getGitRoot = async function(sourceRoot) { + try { + const stdout = await runGitCommand( + sourceRoot, + ["rev-parse", "--show-toplevel"], + `Cannot find Git repository root from the source root ${sourceRoot}.` + ); + return stdout.trim(); + } catch { + return void 0; + } +}; var getFileOidsUnderPath = async function(basePath) { const stdout = await runGitCommand( basePath, @@ -107191,10 +107203,12 @@ async function readBaseDatabaseOidsFile(config, logger) { async function writeOverlayChangesFile(config, sourceRoot, logger) { const baseFileOids = await readBaseDatabaseOidsFile(config, logger); const overlayFileOids = await getFileOidsUnderPath(sourceRoot); - const changedFiles = computeChangedFiles(baseFileOids, overlayFileOids); + const oidChangedFiles = computeChangedFiles(baseFileOids, overlayFileOids); logger.info( - `Found ${changedFiles.length} changed file(s) under ${sourceRoot}.` + `Found ${oidChangedFiles.length} changed file(s) under ${sourceRoot} from OID comparison.` ); + const diffRangeFiles = await getDiffRangeFilePaths(sourceRoot, logger); + const changedFiles = [.../* @__PURE__ */ new Set([...oidChangedFiles, ...diffRangeFiles])]; const changedFilesJson = JSON.stringify({ changes: changedFiles }); const overlayChangesFile = path3.join( getTemporaryDirectory(), @@ -107220,6 +107234,48 @@ function computeChangedFiles(baseFileOids, overlayFileOids) { } return changes; } +async function getDiffRangeFilePaths(sourceRoot, logger) { + const jsonFilePath = path3.join(getTemporaryDirectory(), "pr-diff-range.json"); + if (!fs3.existsSync(jsonFilePath)) { + return []; + } + let diffRanges; + try { + diffRanges = JSON.parse(fs3.readFileSync(jsonFilePath, "utf8")); + } catch (e) { + logger.warning( + `Failed to parse diff ranges JSON file at ${jsonFilePath}: ${e}` + ); + return []; + } + logger.debug( + `Read ${diffRanges.length} diff range(s) from ${jsonFilePath} for overlay changes.` + ); + const repoRelativePaths = [...new Set(diffRanges.map((r) => r.path))]; + const repoRoot = await getGitRoot(sourceRoot); + if (repoRoot === void 0) { + logger.warning( + "Cannot determine git root; returning diff range paths as-is." + ); + return repoRelativePaths; + } + const sourceRootRelPrefix = path3.relative(repoRoot, sourceRoot).replaceAll(path3.sep, "/"); + if (sourceRootRelPrefix === "") { + return repoRelativePaths; + } + const prefixWithSlash = `${sourceRootRelPrefix}/`; + const result = []; + for (const p of repoRelativePaths) { + if (p.startsWith(prefixWithSlash)) { + result.push(p.slice(prefixWithSlash.length)); + } else { + logger.debug( + `Skipping diff range path "${p}" (not under source root "${sourceRootRelPrefix}").` + ); + } + } + return result; +} // src/tools-features.ts var semver3 = __toESM(require_semver2()); @@ -107948,7 +108004,14 @@ function readDiffRangesJsonFile(logger) { `Read pr-diff-range JSON file from ${jsonFilePath}: ${jsonContents}` ); - return JSON.parse(jsonContents); + try { + return JSON.parse(jsonContents); + } catch (e) { + logger.warning( + `Failed to parse diff ranges JSON file at ${jsonFilePath}: ${e}` + ); + return void 0; + } } // src/overlay/status.ts diff --git a/src/analyze-action.ts b/src/analyze-action.ts index cf8e388438..24f8fe612b 100644 --- a/src/analyze-action.ts +++ b/src/analyze-action.ts @@ -28,7 +28,6 @@ import { DependencyCacheUploadStatusReport, uploadDependencyCaches, } from "./dependency-caching"; -import { getDiffInformedAnalysisBranches } from "./diff-informed-analysis-utils"; import { EnvVar } from "./environment"; import { initFeatures } from "./feature-flags"; import { KnownLanguage } from "./languages"; @@ -305,14 +304,8 @@ async function run(startedAt: Date) { logger, ); - const branches = await getDiffInformedAnalysisBranches( - codeql, - features, - logger, - ); - const diffRangePackDir = branches - ? await setupDiffInformedQueryRun(branches, logger) - : undefined; + // Setup diff informed analysis if needed (based on whether init created the file) + const diffRangePackDir = await setupDiffInformedQueryRun(logger); await warnIfGoInstalledAfterInit(config, logger); await runAutobuildIfLegacyGoWorkflow(config, logger); diff --git a/src/analyze.ts b/src/analyze.ts index 8de1b98e81..d2088c3a3a 100644 --- a/src/analyze.ts +++ b/src/analyze.ts @@ -5,11 +5,7 @@ import { performance } from "perf_hooks"; import * as io from "@actions/io"; import * as yaml from "js-yaml"; -import { - getTemporaryDirectory, - getRequiredInput, - PullRequestBranches, -} from "./actions-util"; +import { getTemporaryDirectory, getRequiredInput } from "./actions-util"; import * as analyses from "./analyses"; import { setupCppAutobuild } from "./autobuild"; import { type CodeQL } from "./codeql"; @@ -21,8 +17,7 @@ import { import { addDiagnostic, makeDiagnostic } from "./diagnostics"; import { DiffThunkRange, - writeDiffRangesJsonFile, - getPullRequestEditedDiffRanges, + readDiffRangesJsonFile, } from "./diff-informed-analysis-utils"; import { EnvVar } from "./environment"; import { FeatureEnablement, Feature } from "./feature-flags"; @@ -237,16 +232,19 @@ async function finalizeDatabaseCreation( * the diff range information, or `undefined` if the feature is disabled. */ export async function setupDiffInformedQueryRun( - branches: PullRequestBranches, logger: Logger, ): Promise { return await withGroupAsync( "Generating diff range extension pack", async () => { - logger.info( - `Calculating diff ranges for ${branches.base}...${branches.head}`, - ); - const diffRanges = await getPullRequestEditedDiffRanges(branches, logger); + const diffRanges = readDiffRangesJsonFile(logger); + if (diffRanges === undefined) { + logger.info( + "No precomputed diff ranges found; skipping diff-informed analysis stage.", + ); + return undefined; + } + const checkoutPath = getRequiredInput("checkout_path"); const packDir = writeDiffRangeDataExtensionPack( logger, @@ -368,10 +366,6 @@ dataExtensions: `Wrote pr-diff-range extension pack to ${extensionFilePath}:\n${extensionContents}`, ); - // Write the diff ranges to a JSON file, for action-side alert filtering by the - // upload-lib module. - writeDiffRangesJsonFile(logger, ranges); - return diffRangeDir; } diff --git a/src/diff-informed-analysis-utils.ts b/src/diff-informed-analysis-utils.ts index ac0eb1ea26..adae032dcd 100644 --- a/src/diff-informed-analysis-utils.ts +++ b/src/diff-informed-analysis-utils.ts @@ -105,7 +105,14 @@ export function readDiffRangesJsonFile( logger.debug( `Read pr-diff-range JSON file from ${jsonFilePath}:\n${jsonContents}`, ); - return JSON.parse(jsonContents) as DiffThunkRange[]; + try { + return JSON.parse(jsonContents) as DiffThunkRange[]; + } catch (e) { + logger.warning( + `Failed to parse diff ranges JSON file at ${jsonFilePath}: ${e}`, + ); + return undefined; + } } /** diff --git a/src/init-action.ts b/src/init-action.ts index 6fe89165bd..2dddc888a5 100644 --- a/src/init-action.ts +++ b/src/init-action.ts @@ -37,6 +37,11 @@ import { makeDiagnostic, makeTelemetryDiagnostic, } from "./diagnostics"; +import { + getDiffInformedAnalysisBranches, + getPullRequestEditedDiffRanges, + writeDiffRangesJsonFile, +} from "./diff-informed-analysis-utils"; import { EnvVar } from "./environment"; import { Feature, FeatureEnablement, initFeatures } from "./feature-flags"; import { @@ -54,7 +59,7 @@ import { runDatabaseInitCluster, } from "./init"; import { JavaEnvVars, KnownLanguage } from "./languages"; -import { getActionsLogger, Logger } from "./logging"; +import { getActionsLogger, Logger, withGroupAsync } from "./logging"; import { downloadOverlayBaseDatabaseFromCache, OverlayBaseDatabaseDownloadStats, @@ -413,6 +418,7 @@ async function run(startedAt: Date) { } await checkInstallPython311(config.languages, codeql); + await computeAndPersistDiffRanges(codeql, features, logger); } catch (unwrappedError) { const error = wrapError(unwrappedError); core.setFailed(error.message); @@ -833,6 +839,42 @@ async function loadRepositoryProperties( } } +/** + * Compute and persist diff ranges when diff-informed analysis is enabled + * (feature flag + PR context). This writes the standard pr-diff-range.json + * file for later reuse in the analyze step. Failures are logged but non-fatal. + */ +async function computeAndPersistDiffRanges( + codeql: CodeQL, + features: FeatureEnablement, + logger: Logger, +): Promise { + try { + await withGroupAsync("Compute PR diff ranges", async () => { + const branches = await getDiffInformedAnalysisBranches( + codeql, + features, + logger, + ); + if (!branches) { + return; + } + const ranges = await getPullRequestEditedDiffRanges(branches, logger); + if (ranges === undefined) { + return; + } + writeDiffRangesJsonFile(logger, ranges); + const distinctFiles = new Set(ranges.map((r) => r.path)).size; + logger.info( + `Persisted ${ranges.length} diff range(s) across ${distinctFiles} file(s).`, + ); + }); + } catch (e) { + logger.warning( + `Failed to compute and persist PR diff ranges: ${getErrorMessage(e)}`, + ); + } +} async function recordZstdAvailability( config: configUtils.Config, zstdAvailability: ZstdAvailability, diff --git a/src/overlay/index.test.ts b/src/overlay/index.test.ts index 8e92a69e27..088a3828bb 100644 --- a/src/overlay/index.test.ts +++ b/src/overlay/index.test.ts @@ -34,12 +34,14 @@ test.serial( "writeOverlayChangesFile generates correct changes file", async (t) => { await withTmpDir(async (tmpDir) => { - const dbLocation = path.join(tmpDir, "db"); - await fs.promises.mkdir(dbLocation, { recursive: true }); - const sourceRoot = path.join(tmpDir, "src"); - await fs.promises.mkdir(sourceRoot, { recursive: true }); - const tempDir = path.join(tmpDir, "temp"); - await fs.promises.mkdir(tempDir, { recursive: true }); + const [dbLocation, sourceRoot, tempDir] = ["db", "src", "temp"].map((d) => + path.join(tmpDir, d), + ); + await Promise.all( + [dbLocation, sourceRoot, tempDir].map((d) => + fs.promises.mkdir(d, { recursive: true }), + ), + ); const logger = getRunnerLogger(true); const config = createTestConfig({ dbLocation }); @@ -73,6 +75,9 @@ test.serial( const getTempDirStub = sinon .stub(actionsUtil, "getTemporaryDirectory") .returns(tempDir); + const getGitRootStub = sinon + .stub(gitUtils, "getGitRoot") + .resolves(sourceRoot); const changesFilePath = await writeOverlayChangesFile( config, sourceRoot, @@ -80,6 +85,7 @@ test.serial( ); getFileOidsStubForOverlay.restore(); getTempDirStub.restore(); + getGitRootStub.restore(); const fileContent = await fs.promises.readFile(changesFilePath, "utf-8"); const parsedContent = JSON.parse(fileContent) as { changes: string[] }; @@ -93,6 +99,232 @@ test.serial( }, ); +test.serial( + "writeOverlayChangesFile merges additional diff files into overlay changes", + async (t) => { + await withTmpDir(async (tmpDir) => { + const [dbLocation, sourceRoot, tempDir] = ["db", "src", "temp"].map((d) => + path.join(tmpDir, d), + ); + await Promise.all( + [dbLocation, sourceRoot, tempDir].map((d) => + fs.promises.mkdir(d, { recursive: true }), + ), + ); + + const logger = getRunnerLogger(true); + const config = createTestConfig({ dbLocation }); + + // Mock the getFileOidsUnderPath function to return base OIDs + // "reverted.js" has the same OID in both base and current, simulating + // a revert PR where the file content matches the overlay-base + const baseOids = { + "unchanged.js": "aaa111", + "modified.js": "bbb222", + "reverted.js": "eee555", + }; + const getFileOidsStubForBase = sinon + .stub(gitUtils, "getFileOidsUnderPath") + .resolves(baseOids); + + // Write the base database OIDs file + await writeBaseDatabaseOidsFile(config, sourceRoot); + getFileOidsStubForBase.restore(); + + // Mock the getFileOidsUnderPath function to return overlay OIDs + // "reverted.js" has the same OID as the base -- OID comparison alone + // would NOT include it, only additionalChangedFiles causes it to appear + const currentOids = { + "unchanged.js": "aaa111", + "modified.js": "ddd444", // Changed OID + "reverted.js": "eee555", // Same OID as base -- not detected by OID comparison + }; + const getFileOidsStubForOverlay = sinon + .stub(gitUtils, "getFileOidsUnderPath") + .resolves(currentOids); + + const getTempDirStub = sinon + .stub(actionsUtil, "getTemporaryDirectory") + .returns(tempDir); + const getGitRootStub = sinon + .stub(gitUtils, "getGitRoot") + .resolves(sourceRoot); + + // Write a pr-diff-range.json file with diff ranges including + // "reverted.js" (unchanged OIDs) and "modified.js" (already in OID changes) + await fs.promises.writeFile( + path.join(tempDir, "pr-diff-range.json"), + JSON.stringify([ + { path: "reverted.js", startLine: 1, endLine: 10 }, + { path: "modified.js", startLine: 1, endLine: 5 }, + { path: "diff-only.js", startLine: 1, endLine: 3 }, + ]), + ); + + const changesFilePath = await writeOverlayChangesFile( + config, + sourceRoot, + logger, + ); + getFileOidsStubForOverlay.restore(); + getTempDirStub.restore(); + getGitRootStub.restore(); + + const fileContent = await fs.promises.readFile(changesFilePath, "utf-8"); + const parsedContent = JSON.parse(fileContent) as { changes: string[] }; + + t.deepEqual( + parsedContent.changes.sort(), + ["diff-only.js", "modified.js", "reverted.js"], + "Should include OID-changed files, diff-only files, and deduplicate overlapping files", + ); + }); + }, +); + +test.serial( + "writeOverlayChangesFile works without additional diff files", + async (t) => { + await withTmpDir(async (tmpDir) => { + const [dbLocation, sourceRoot, tempDir] = ["db", "src", "temp"].map((d) => + path.join(tmpDir, d), + ); + await Promise.all( + [dbLocation, sourceRoot, tempDir].map((d) => + fs.promises.mkdir(d, { recursive: true }), + ), + ); + + const logger = getRunnerLogger(true); + const config = createTestConfig({ dbLocation }); + + // Mock the getFileOidsUnderPath function to return base OIDs + const baseOids = { + "unchanged.js": "aaa111", + "modified.js": "bbb222", + }; + const getFileOidsStubForBase = sinon + .stub(gitUtils, "getFileOidsUnderPath") + .resolves(baseOids); + + await writeBaseDatabaseOidsFile(config, sourceRoot); + getFileOidsStubForBase.restore(); + + const currentOids = { + "unchanged.js": "aaa111", + "modified.js": "ddd444", + }; + const getFileOidsStubForOverlay = sinon + .stub(gitUtils, "getFileOidsUnderPath") + .resolves(currentOids); + + const getTempDirStub = sinon + .stub(actionsUtil, "getTemporaryDirectory") + .returns(tempDir); + const getGitRootStub = sinon + .stub(gitUtils, "getGitRoot") + .resolves(sourceRoot); + + // No pr-diff-range.json file exists - should work the same as before + const changesFilePath = await writeOverlayChangesFile( + config, + sourceRoot, + logger, + ); + getFileOidsStubForOverlay.restore(); + getTempDirStub.restore(); + getGitRootStub.restore(); + + const fileContent = await fs.promises.readFile(changesFilePath, "utf-8"); + const parsedContent = JSON.parse(fileContent) as { changes: string[] }; + + t.deepEqual( + parsedContent.changes.sort(), + ["modified.js"], + "Should only include OID-changed files when no additional files provided", + ); + }); + }, +); + +test.serial( + "writeOverlayChangesFile converts diff range paths to sourceRoot-relative when sourceRoot is a subdirectory", + async (t) => { + await withTmpDir(async (tmpDir) => { + // Simulate: repo root = tmpDir, sourceRoot = tmpDir/src + const repoRoot = tmpDir; + const sourceRoot = path.join(tmpDir, "src"); + const [dbLocation, tempDir] = ["db", "temp"].map((d) => + path.join(tmpDir, d), + ); + await Promise.all( + [dbLocation, sourceRoot, tempDir].map((d) => + fs.promises.mkdir(d, { recursive: true }), + ), + ); + + const logger = getRunnerLogger(true); + const config = createTestConfig({ dbLocation }); + + // Base OIDs (sourceRoot-relative paths) + const baseOids = { + "app.js": "aaa111", + "lib/util.js": "bbb222", + }; + const getFileOidsStubForBase = sinon + .stub(gitUtils, "getFileOidsUnderPath") + .resolves(baseOids); + await writeBaseDatabaseOidsFile(config, sourceRoot); + getFileOidsStubForBase.restore(); + + // Current OIDs — same as base (no OID changes) + const currentOids = { + "app.js": "aaa111", + "lib/util.js": "bbb222", + }; + const getFileOidsStubForOverlay = sinon + .stub(gitUtils, "getFileOidsUnderPath") + .resolves(currentOids); + + const getTempDirStub = sinon + .stub(actionsUtil, "getTemporaryDirectory") + .returns(tempDir); + // getGitRoot returns the repo root (parent of sourceRoot) + const getGitRootStub = sinon + .stub(gitUtils, "getGitRoot") + .resolves(repoRoot); + + // Diff ranges use repo-root-relative paths (as returned by the GitHub compare API) + await fs.promises.writeFile( + path.join(tempDir, "pr-diff-range.json"), + JSON.stringify([ + { path: "src/app.js", startLine: 1, endLine: 10 }, + { path: "src/lib/util.js", startLine: 5, endLine: 8 }, + { path: "other/outside.js", startLine: 1, endLine: 3 }, // not under sourceRoot + ]), + ); + + const changesFilePath = await writeOverlayChangesFile( + config, + sourceRoot, + logger, + ); + getFileOidsStubForOverlay.restore(); + getTempDirStub.restore(); + getGitRootStub.restore(); + + const fileContent = await fs.promises.readFile(changesFilePath, "utf-8"); + const parsedContent = JSON.parse(fileContent) as { changes: string[] }; + + t.deepEqual( + parsedContent.changes.sort(), + ["app.js", "lib/util.js"], + "Should convert repo-root-relative paths to sourceRoot-relative and filter out files outside sourceRoot", + ); + }); + }, +); + interface DownloadOverlayBaseDatabaseTestCase { overlayDatabaseMode: OverlayDatabaseMode; useOverlayDatabaseCaching: boolean; diff --git a/src/overlay/index.ts b/src/overlay/index.ts index 63a46b2b39..df2f073598 100644 --- a/src/overlay/index.ts +++ b/src/overlay/index.ts @@ -13,7 +13,7 @@ import { getAutomationID } from "../api-client"; import { createCacheKeyHash } from "../caching-utils"; import { type CodeQL } from "../codeql"; import { type Config } from "../config-utils"; -import { getCommitOid, getFileOidsUnderPath } from "../git-utils"; +import { getCommitOid, getFileOidsUnderPath, getGitRoot } from "../git-utils"; import { Logger, withGroupAsync } from "../logging"; import { CleanupLevel, @@ -130,11 +130,17 @@ export async function writeOverlayChangesFile( ): Promise { const baseFileOids = await readBaseDatabaseOidsFile(config, logger); const overlayFileOids = await getFileOidsUnderPath(sourceRoot); - const changedFiles = computeChangedFiles(baseFileOids, overlayFileOids); + const oidChangedFiles = computeChangedFiles(baseFileOids, overlayFileOids); logger.info( - `Found ${changedFiles.length} changed file(s) under ${sourceRoot}.`, + `Found ${oidChangedFiles.length} changed file(s) under ${sourceRoot} from OID comparison.`, ); + // Merge in any file paths from precomputed PR diff ranges to ensure the + // overlay always includes all files from the PR diff, even in edge cases + // like revert PRs where OID comparison shows no change. + const diffRangeFiles = await getDiffRangeFilePaths(sourceRoot, logger); + const changedFiles = [...new Set([...oidChangedFiles, ...diffRangeFiles])]; + const changedFilesJson = JSON.stringify({ changes: changedFiles }); const overlayChangesFile = path.join( getTemporaryDirectory(), @@ -165,6 +171,65 @@ function computeChangedFiles( return changes; } +async function getDiffRangeFilePaths( + sourceRoot: string, + logger: Logger, +): Promise { + const jsonFilePath = path.join(getTemporaryDirectory(), "pr-diff-range.json"); + if (!fs.existsSync(jsonFilePath)) { + return []; + } + let diffRanges: Array<{ path: string }>; + try { + diffRanges = JSON.parse(fs.readFileSync(jsonFilePath, "utf8")) as Array<{ + path: string; + }>; + } catch (e) { + logger.warning( + `Failed to parse diff ranges JSON file at ${jsonFilePath}: ${e}`, + ); + return []; + } + logger.debug( + `Read ${diffRanges.length} diff range(s) from ${jsonFilePath} for overlay changes.`, + ); + const repoRelativePaths = [...new Set(diffRanges.map((r) => r.path))]; + + // Diff-range paths are relative to the repo root (from the GitHub compare + // API), but overlay changed files must be relative to sourceRoot (to match + // getFileOidsUnderPath output). Convert and filter accordingly. + const repoRoot = await getGitRoot(sourceRoot); + if (repoRoot === undefined) { + logger.warning( + "Cannot determine git root; returning diff range paths as-is.", + ); + return repoRelativePaths; + } + + // e.g. if repoRoot=/workspace and sourceRoot=/workspace/src, prefix="src" + const sourceRootRelPrefix = path + .relative(repoRoot, sourceRoot) + .replaceAll(path.sep, "/"); + + // If sourceRoot IS the repo root, prefix is "" and all paths pass through. + if (sourceRootRelPrefix === "") { + return repoRelativePaths; + } + + const prefixWithSlash = `${sourceRootRelPrefix}/`; + const result: string[] = []; + for (const p of repoRelativePaths) { + if (p.startsWith(prefixWithSlash)) { + result.push(p.slice(prefixWithSlash.length)); + } else { + logger.debug( + `Skipping diff range path "${p}" (not under source root "${sourceRootRelPrefix}").`, + ); + } + } + return result; +} + // Constants for database caching const CACHE_VERSION = 1; const CACHE_PREFIX = "codeql-overlay-base-database";