renovate 44.46.3 → 44.46.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/modules/manager/bundler/extract.js +4 -4
- package/dist/modules/manager/bundler/extract.js.map +1 -1
- package/dist/modules/manager/dockerfile/extract.js +4 -3
- package/dist/modules/manager/dockerfile/extract.js.map +1 -1
- package/dist/modules/platform/gerrit/scm.js +1 -1
- package/dist/modules/platform/gerrit/scm.js.map +1 -1
- package/dist/modules/platform/github/index.js +1 -1
- package/dist/modules/platform/github/index.js.map +1 -1
- package/dist/modules/versioning/conan/range.js +4 -3
- package/dist/modules/versioning/conan/range.js.map +1 -1
- package/dist/modules/versioning/pvp/index.js +3 -3
- package/dist/modules/versioning/pvp/index.js.map +1 -1
- package/dist/util/json-writer/editor-config.js +3 -2
- package/dist/util/json-writer/editor-config.js.map +1 -1
- package/package.json +2 -2
- package/renovate-schema.json +2 -2
|
@@ -45,7 +45,7 @@ async function extractPackageFile(content, packageFile) {
|
|
|
45
45
|
const depObject = {
|
|
46
46
|
...dep,
|
|
47
47
|
depTypes,
|
|
48
|
-
managerData: { lineNumber:
|
|
48
|
+
managerData: { lineNumber: (dep.managerData?.lineNumber ?? NaN) + groupLineNumber + 1 }
|
|
49
49
|
};
|
|
50
50
|
if (repositoryUrl) depObject.registryUrls = [repositoryUrl];
|
|
51
51
|
return depObject;
|
|
@@ -138,7 +138,7 @@ async function extractPackageFile(content, packageFile) {
|
|
|
138
138
|
if (sourceRes) res.deps = res.deps.concat(sourceRes.deps.map((dep) => ({
|
|
139
139
|
...dep,
|
|
140
140
|
registryUrls: [repositoryUrl],
|
|
141
|
-
managerData: { lineNumber:
|
|
141
|
+
managerData: { lineNumber: (dep.managerData?.lineNumber ?? NaN) + sourceLineNumber + 1 }
|
|
142
142
|
})));
|
|
143
143
|
}
|
|
144
144
|
}
|
|
@@ -163,7 +163,7 @@ async function extractPackageFile(content, packageFile) {
|
|
|
163
163
|
const platformsRes = await extractPackageFile(platformsContent);
|
|
164
164
|
if (platformsRes) res.deps = res.deps.concat(platformsRes.deps.map((dep) => ({
|
|
165
165
|
...dep,
|
|
166
|
-
managerData: { lineNumber:
|
|
166
|
+
managerData: { lineNumber: (dep.managerData?.lineNumber ?? NaN) + platformsLineNumber + 1 }
|
|
167
167
|
})));
|
|
168
168
|
}
|
|
169
169
|
if (regEx(/^if\s+(.*?)/).test(line)) {
|
|
@@ -187,7 +187,7 @@ async function extractPackageFile(content, packageFile) {
|
|
|
187
187
|
const ifRes = await extractPackageFile(ifContent);
|
|
188
188
|
if (ifRes) res.deps = res.deps.concat(ifRes.deps.map((dep) => ({
|
|
189
189
|
...dep,
|
|
190
|
-
managerData: { lineNumber:
|
|
190
|
+
managerData: { lineNumber: (dep.managerData?.lineNumber ?? NaN) + ifLineNumber + 1 }
|
|
191
191
|
})));
|
|
192
192
|
}
|
|
193
193
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"extract.js","names":[],"sources":["../../../../lib/modules/manager/bundler/extract.ts"],"sourcesContent":["import { isString } from '@sindresorhus/is';\nimport { logger } from '../../../logger/index.ts';\nimport { readLocalFile } from '../../../util/fs/index.ts';\nimport { newlineRegex, regEx } from '../../../util/regex.ts';\nimport { isHttpUrl } from '../../../util/url.ts';\nimport { GitRefsDatasource } from '../../datasource/git-refs/index.ts';\nimport { RubyVersionDatasource } from '../../datasource/ruby-version/index.ts';\nimport { RubygemsDatasource } from '../../datasource/rubygems/index.ts';\nimport type { PackageDependency, PackageFileContent } from '../types.ts';\nimport { delimiters, extractRubyVersion, getLockFilePath } from './common.ts';\nimport { extractLockFileEntries } from './locked-version.ts';\n\nfunction formatContent(input: string): string {\n return `${input.replace(regEx(/^ {2}/), '')}\\n`; //remove leading whitespace and add a new line at the end\n}\n\nconst variableMatchRegex = regEx(\n `^(?<key>\\\\w+)\\\\s*=\\\\s*['\"](?<value>[^'\"]+)['\"]`,\n);\nconst gemMatchRegex = regEx(\n `^\\\\s*gem\\\\s+(['\"])(?<depName>[^'\"]+)(['\"])(\\\\s*,\\\\s*(?<currentValue>(['\"])[^'\"]+['\"](\\\\s*,\\\\s*['\"][^'\"]+['\"])?))?`,\n);\nconst sourceMatchRegex = regEx(\n `source:\\\\s*((?:['\"](?<registryUrl>[^'\"]+)['\"])|(?<sourceName>\\\\w+))?`,\n);\nconst gitRefsMatchRegex = regEx(\n `((git:\\\\s*['\"](?<gitUrl>[^'\"]+)['\"])|(\\\\s*,\\\\s*github:\\\\s*['\"](?<repoName>[^'\"]+)['\"]))(\\\\s*,\\\\s*branch:\\\\s*['\"](?<branchName>[^'\"]+)['\"])?(\\\\s*,\\\\s*ref:\\\\s*['\"](?<refName>[^'\"]+)['\"])?(\\\\s*,\\\\s*tag:\\\\s*['\"](?<tagName>[^'\"]+)['\"])?`,\n);\nconst pathMatchRegex = regEx(`path:\\\\s*['\"](?<path>[^'\"]+)['\"]`);\n\nexport async function extractPackageFile(\n content: string,\n packageFile?: string,\n): Promise<PackageFileContent | null> {\n let lineNumber: number;\n async function processGroupBlock(\n line: string,\n repositoryUrl?: string,\n trimGroupLine = false,\n ): Promise<void> {\n const groupMatch = regEx(/^group\\s+(.*?)\\s+do/).exec(line);\n if (groupMatch) {\n const depTypes = groupMatch[1]\n .split(',')\n .map((group) => group.trim())\n .map((group) => group.replace(regEx(/^:/), ''));\n\n const groupLineNumber = lineNumber;\n let groupContent = '';\n let groupLine = '';\n\n while (\n lineNumber < lines.length &&\n (trimGroupLine ? groupLine.trim() !== 'end' : groupLine !== 'end')\n ) {\n lineNumber += 1;\n groupLine = lines[lineNumber];\n\n // istanbul ignore if\n if (!isString(groupLine)) {\n logger.debug(\n { content, packageFile, type: 'groupLine' },\n 'Bundler parsing error',\n );\n groupLine = 'end';\n }\n if (trimGroupLine ? groupLine.trim() !== 'end' : groupLine !== 'end') {\n groupContent += formatContent(groupLine);\n }\n }\n\n const groupRes = await extractPackageFile(groupContent);\n if (groupRes) {\n res.deps = res.deps.concat(\n groupRes.deps.map((dep) => {\n const depObject = {\n ...dep,\n depTypes,\n managerData: {\n lineNumber:\n Number(dep.managerData?.lineNumber) + groupLineNumber + 1,\n },\n };\n if (repositoryUrl) {\n depObject.registryUrls = [repositoryUrl];\n }\n return depObject;\n }),\n );\n }\n }\n }\n const res: PackageFileContent = {\n registryUrls: [],\n deps: [],\n };\n\n const variables: Record<string, string> = {};\n\n const lines = content.split(newlineRegex);\n for (lineNumber = 0; lineNumber < lines.length; lineNumber += 1) {\n const line = lines[lineNumber];\n let sourceMatch: RegExpMatchArray | null = null;\n for (const delimiter of delimiters) {\n sourceMatch =\n sourceMatch ??\n regEx(\n `^source ((${delimiter}(?<registryUrl>[^${delimiter}]+)${delimiter})|(?<sourceName>\\\\w+))\\\\s*$`,\n ).exec(line);\n }\n if (sourceMatch) {\n if (sourceMatch.groups?.registryUrl) {\n res.registryUrls?.push(sourceMatch.groups.registryUrl);\n }\n if (sourceMatch.groups?.sourceName) {\n const registryUrl = variables[sourceMatch.groups.sourceName];\n if (registryUrl) {\n res.registryUrls?.push(registryUrl);\n }\n }\n }\n\n const rubyMatch = extractRubyVersion(line);\n if (rubyMatch) {\n res.deps.push({\n depName: 'ruby',\n currentValue: rubyMatch,\n datasource: RubyVersionDatasource.id,\n registryUrls: null,\n });\n }\n\n const variableMatch = variableMatchRegex.exec(line);\n if (variableMatch?.groups?.key) {\n variables[variableMatch.groups?.key] = variableMatch.groups?.value;\n }\n\n const gemMatch = gemMatchRegex.exec(line)?.groups;\n\n if (gemMatch) {\n const dep: PackageDependency = {\n depName: gemMatch.depName,\n managerData: { lineNumber },\n datasource: RubygemsDatasource.id,\n };\n\n if (gemMatch.currentValue) {\n const currentValue = gemMatch.currentValue;\n dep.currentValue = currentValue;\n }\n\n const pathMatch = pathMatchRegex.exec(line)?.groups;\n if (pathMatch) {\n dep.skipReason = 'internal-package';\n }\n\n const sourceMatch = sourceMatchRegex.exec(line)?.groups;\n if (sourceMatch) {\n if (sourceMatch.registryUrl) {\n dep.registryUrls = [sourceMatch.registryUrl];\n } else if (sourceMatch.sourceName) {\n dep.registryUrls = [variables[sourceMatch.sourceName]];\n }\n }\n\n const gitRefsMatch = gitRefsMatchRegex.exec(line)?.groups;\n if (gitRefsMatch) {\n if (gitRefsMatch.gitUrl) {\n const gitUrl = gitRefsMatch.gitUrl;\n dep.packageName = gitUrl;\n\n if (isHttpUrl(gitUrl)) {\n dep.sourceUrl = gitUrl.replace(regEx(/\\.git$/), '');\n }\n } else {\n // we always have repoName, as `gitRefsMatchRegex`'s first group requires either `gitUrl` or `repoName`\n dep.packageName = `https://github.com/${gitRefsMatch.repoName}`;\n dep.sourceUrl = dep.packageName;\n }\n if (gitRefsMatch.refName) {\n dep.currentDigest = gitRefsMatch.refName;\n } else if (gitRefsMatch.branchName) {\n dep.currentValue = gitRefsMatch.branchName;\n } else if (gitRefsMatch.tagName) {\n dep.currentValue = gitRefsMatch.tagName;\n }\n dep.datasource = GitRefsDatasource.id;\n }\n res.deps.push(dep);\n }\n\n await processGroupBlock(line);\n\n for (const delimiter of delimiters) {\n const sourceBlockMatch = regEx(\n `^source\\\\s+((${delimiter}(?<registryUrl>[^${delimiter}]+)${delimiter})|(?<sourceName>\\\\w+))\\\\s+do`,\n ).exec(line);\n if (sourceBlockMatch) {\n let repositoryUrl = '';\n if (sourceBlockMatch.groups?.registryUrl) {\n repositoryUrl = sourceBlockMatch.groups.registryUrl;\n }\n if (\n sourceBlockMatch.groups?.sourceName &&\n variables[sourceBlockMatch.groups.sourceName]\n ) {\n repositoryUrl = variables[sourceBlockMatch.groups.sourceName];\n }\n const sourceLineNumber = lineNumber;\n let sourceContent = '';\n let sourceLine = '';\n\n while (lineNumber < lines.length && sourceLine.trim() !== 'end') {\n lineNumber += 1;\n sourceLine = lines[lineNumber];\n // istanbul ignore if\n if (!isString(sourceLine)) {\n logger.debug(\n { content, packageFile, type: 'sourceLine' },\n 'Bundler parsing error',\n );\n sourceLine = 'end';\n }\n\n await processGroupBlock(sourceLine.trim(), repositoryUrl, true);\n\n if (sourceLine.trim() !== 'end') {\n sourceContent += formatContent(sourceLine);\n }\n }\n\n const sourceRes = await extractPackageFile(sourceContent);\n\n if (sourceRes) {\n res.deps = res.deps.concat(\n sourceRes.deps.map((dep) => ({\n ...dep,\n registryUrls: [repositoryUrl],\n managerData: {\n lineNumber:\n Number(dep.managerData?.lineNumber) + sourceLineNumber + 1,\n },\n })),\n );\n }\n }\n }\n const platformsMatch = regEx(/^platforms\\s+(.*?)\\s+do/).test(line);\n if (platformsMatch) {\n const platformsLineNumber = lineNumber;\n let platformsContent = '';\n let platformsLine = '';\n while (lineNumber < lines.length && platformsLine !== 'end') {\n lineNumber += 1;\n platformsLine = lines[lineNumber];\n // istanbul ignore if\n if (!isString(platformsLine)) {\n logger.debug(\n { content, packageFile, type: 'platformsLine' },\n 'Bundler parsing error',\n );\n platformsLine = 'end';\n }\n if (platformsLine !== 'end') {\n platformsContent += formatContent(platformsLine);\n }\n }\n const platformsRes = await extractPackageFile(platformsContent);\n if (platformsRes) {\n res.deps = res.deps.concat(\n platformsRes.deps.map((dep) => ({\n ...dep,\n managerData: {\n lineNumber:\n Number(dep.managerData?.lineNumber) + platformsLineNumber + 1,\n },\n })),\n );\n }\n }\n const ifMatch = regEx(/^if\\s+(.*?)/).test(line);\n if (ifMatch) {\n const ifLineNumber = lineNumber;\n let ifContent = '';\n let ifLine = '';\n while (lineNumber < lines.length && ifLine !== 'end') {\n lineNumber += 1;\n ifLine = lines[lineNumber];\n // istanbul ignore if\n if (!isString(ifLine)) {\n logger.debug(\n { content, packageFile, type: 'ifLine' },\n 'Bundler parsing error',\n );\n ifLine = 'end';\n }\n if (ifLine !== 'end') {\n ifContent += formatContent(ifLine);\n }\n }\n const ifRes = await extractPackageFile(ifContent);\n if (ifRes) {\n res.deps = res.deps.concat(\n ifRes.deps.map((dep) => ({\n ...dep,\n managerData: {\n lineNumber:\n Number(dep.managerData?.lineNumber) + ifLineNumber + 1,\n },\n })),\n );\n }\n }\n }\n if (!res.deps.length && !res.registryUrls?.length) {\n return null;\n }\n\n if (packageFile) {\n const gemfileLockPath = await getLockFilePath(packageFile);\n const lockContent = await readLocalFile(gemfileLockPath, 'utf8');\n if (lockContent) {\n logger.debug(\n `Found lock file ${gemfileLockPath} for packageFile: ${packageFile}`,\n );\n res.lockFiles = [gemfileLockPath];\n const lockedEntries = extractLockFileEntries(lockContent);\n for (const dep of res.deps) {\n // TODO: types (#22198)\n const lockedDepValue = lockedEntries.get(`${dep.depName!}`);\n if (lockedDepValue) {\n dep.lockedVersion = lockedDepValue;\n }\n }\n }\n }\n return res;\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"extract.js","names":[],"sources":["../../../../lib/modules/manager/bundler/extract.ts"],"sourcesContent":["import { isString } from '@sindresorhus/is';\nimport { logger } from '../../../logger/index.ts';\nimport { readLocalFile } from '../../../util/fs/index.ts';\nimport { newlineRegex, regEx } from '../../../util/regex.ts';\nimport { isHttpUrl } from '../../../util/url.ts';\nimport { GitRefsDatasource } from '../../datasource/git-refs/index.ts';\nimport { RubyVersionDatasource } from '../../datasource/ruby-version/index.ts';\nimport { RubygemsDatasource } from '../../datasource/rubygems/index.ts';\nimport type { PackageDependency, PackageFileContent } from '../types.ts';\nimport { delimiters, extractRubyVersion, getLockFilePath } from './common.ts';\nimport { extractLockFileEntries } from './locked-version.ts';\n\nfunction formatContent(input: string): string {\n return `${input.replace(regEx(/^ {2}/), '')}\\n`; //remove leading whitespace and add a new line at the end\n}\n\nconst variableMatchRegex = regEx(\n `^(?<key>\\\\w+)\\\\s*=\\\\s*['\"](?<value>[^'\"]+)['\"]`,\n);\nconst gemMatchRegex = regEx(\n `^\\\\s*gem\\\\s+(['\"])(?<depName>[^'\"]+)(['\"])(\\\\s*,\\\\s*(?<currentValue>(['\"])[^'\"]+['\"](\\\\s*,\\\\s*['\"][^'\"]+['\"])?))?`,\n);\nconst sourceMatchRegex = regEx(\n `source:\\\\s*((?:['\"](?<registryUrl>[^'\"]+)['\"])|(?<sourceName>\\\\w+))?`,\n);\nconst gitRefsMatchRegex = regEx(\n `((git:\\\\s*['\"](?<gitUrl>[^'\"]+)['\"])|(\\\\s*,\\\\s*github:\\\\s*['\"](?<repoName>[^'\"]+)['\"]))(\\\\s*,\\\\s*branch:\\\\s*['\"](?<branchName>[^'\"]+)['\"])?(\\\\s*,\\\\s*ref:\\\\s*['\"](?<refName>[^'\"]+)['\"])?(\\\\s*,\\\\s*tag:\\\\s*['\"](?<tagName>[^'\"]+)['\"])?`,\n);\nconst pathMatchRegex = regEx(`path:\\\\s*['\"](?<path>[^'\"]+)['\"]`);\n\nexport async function extractPackageFile(\n content: string,\n packageFile?: string,\n): Promise<PackageFileContent | null> {\n let lineNumber: number;\n async function processGroupBlock(\n line: string,\n repositoryUrl?: string,\n trimGroupLine = false,\n ): Promise<void> {\n const groupMatch = regEx(/^group\\s+(.*?)\\s+do/).exec(line);\n if (groupMatch) {\n const depTypes = groupMatch[1]\n .split(',')\n .map((group) => group.trim())\n .map((group) => group.replace(regEx(/^:/), ''));\n\n const groupLineNumber = lineNumber;\n let groupContent = '';\n let groupLine = '';\n\n while (\n lineNumber < lines.length &&\n (trimGroupLine ? groupLine.trim() !== 'end' : groupLine !== 'end')\n ) {\n lineNumber += 1;\n groupLine = lines[lineNumber];\n\n // istanbul ignore if\n if (!isString(groupLine)) {\n logger.debug(\n { content, packageFile, type: 'groupLine' },\n 'Bundler parsing error',\n );\n groupLine = 'end';\n }\n if (trimGroupLine ? groupLine.trim() !== 'end' : groupLine !== 'end') {\n groupContent += formatContent(groupLine);\n }\n }\n\n const groupRes = await extractPackageFile(groupContent);\n if (groupRes) {\n res.deps = res.deps.concat(\n groupRes.deps.map((dep) => {\n const depObject = {\n ...dep,\n depTypes,\n managerData: {\n lineNumber:\n (dep.managerData?.lineNumber ?? NaN) + groupLineNumber + 1,\n },\n };\n if (repositoryUrl) {\n depObject.registryUrls = [repositoryUrl];\n }\n return depObject;\n }),\n );\n }\n }\n }\n const res: PackageFileContent = {\n registryUrls: [],\n deps: [],\n };\n\n const variables: Record<string, string> = {};\n\n const lines = content.split(newlineRegex);\n for (lineNumber = 0; lineNumber < lines.length; lineNumber += 1) {\n const line = lines[lineNumber];\n let sourceMatch: RegExpMatchArray | null = null;\n for (const delimiter of delimiters) {\n sourceMatch =\n sourceMatch ??\n regEx(\n `^source ((${delimiter}(?<registryUrl>[^${delimiter}]+)${delimiter})|(?<sourceName>\\\\w+))\\\\s*$`,\n ).exec(line);\n }\n if (sourceMatch) {\n if (sourceMatch.groups?.registryUrl) {\n res.registryUrls?.push(sourceMatch.groups.registryUrl);\n }\n if (sourceMatch.groups?.sourceName) {\n const registryUrl = variables[sourceMatch.groups.sourceName];\n if (registryUrl) {\n res.registryUrls?.push(registryUrl);\n }\n }\n }\n\n const rubyMatch = extractRubyVersion(line);\n if (rubyMatch) {\n res.deps.push({\n depName: 'ruby',\n currentValue: rubyMatch,\n datasource: RubyVersionDatasource.id,\n registryUrls: null,\n });\n }\n\n const variableMatch = variableMatchRegex.exec(line);\n if (variableMatch?.groups?.key) {\n variables[variableMatch.groups?.key] = variableMatch.groups?.value;\n }\n\n const gemMatch = gemMatchRegex.exec(line)?.groups;\n\n if (gemMatch) {\n const dep: PackageDependency = {\n depName: gemMatch.depName,\n managerData: { lineNumber },\n datasource: RubygemsDatasource.id,\n };\n\n if (gemMatch.currentValue) {\n const currentValue = gemMatch.currentValue;\n dep.currentValue = currentValue;\n }\n\n const pathMatch = pathMatchRegex.exec(line)?.groups;\n if (pathMatch) {\n dep.skipReason = 'internal-package';\n }\n\n const sourceMatch = sourceMatchRegex.exec(line)?.groups;\n if (sourceMatch) {\n if (sourceMatch.registryUrl) {\n dep.registryUrls = [sourceMatch.registryUrl];\n } else if (sourceMatch.sourceName) {\n dep.registryUrls = [variables[sourceMatch.sourceName]];\n }\n }\n\n const gitRefsMatch = gitRefsMatchRegex.exec(line)?.groups;\n if (gitRefsMatch) {\n if (gitRefsMatch.gitUrl) {\n const gitUrl = gitRefsMatch.gitUrl;\n dep.packageName = gitUrl;\n\n if (isHttpUrl(gitUrl)) {\n dep.sourceUrl = gitUrl.replace(regEx(/\\.git$/), '');\n }\n } else {\n // we always have repoName, as `gitRefsMatchRegex`'s first group requires either `gitUrl` or `repoName`\n dep.packageName = `https://github.com/${gitRefsMatch.repoName}`;\n dep.sourceUrl = dep.packageName;\n }\n if (gitRefsMatch.refName) {\n dep.currentDigest = gitRefsMatch.refName;\n } else if (gitRefsMatch.branchName) {\n dep.currentValue = gitRefsMatch.branchName;\n } else if (gitRefsMatch.tagName) {\n dep.currentValue = gitRefsMatch.tagName;\n }\n dep.datasource = GitRefsDatasource.id;\n }\n res.deps.push(dep);\n }\n\n await processGroupBlock(line);\n\n for (const delimiter of delimiters) {\n const sourceBlockMatch = regEx(\n `^source\\\\s+((${delimiter}(?<registryUrl>[^${delimiter}]+)${delimiter})|(?<sourceName>\\\\w+))\\\\s+do`,\n ).exec(line);\n if (sourceBlockMatch) {\n let repositoryUrl = '';\n if (sourceBlockMatch.groups?.registryUrl) {\n repositoryUrl = sourceBlockMatch.groups.registryUrl;\n }\n if (\n sourceBlockMatch.groups?.sourceName &&\n variables[sourceBlockMatch.groups.sourceName]\n ) {\n repositoryUrl = variables[sourceBlockMatch.groups.sourceName];\n }\n const sourceLineNumber = lineNumber;\n let sourceContent = '';\n let sourceLine = '';\n\n while (lineNumber < lines.length && sourceLine.trim() !== 'end') {\n lineNumber += 1;\n sourceLine = lines[lineNumber];\n // istanbul ignore if\n if (!isString(sourceLine)) {\n logger.debug(\n { content, packageFile, type: 'sourceLine' },\n 'Bundler parsing error',\n );\n sourceLine = 'end';\n }\n\n await processGroupBlock(sourceLine.trim(), repositoryUrl, true);\n\n if (sourceLine.trim() !== 'end') {\n sourceContent += formatContent(sourceLine);\n }\n }\n\n const sourceRes = await extractPackageFile(sourceContent);\n\n if (sourceRes) {\n res.deps = res.deps.concat(\n sourceRes.deps.map((dep) => ({\n ...dep,\n registryUrls: [repositoryUrl],\n managerData: {\n lineNumber:\n (dep.managerData?.lineNumber ?? NaN) + sourceLineNumber + 1,\n },\n })),\n );\n }\n }\n }\n const platformsMatch = regEx(/^platforms\\s+(.*?)\\s+do/).test(line);\n if (platformsMatch) {\n const platformsLineNumber = lineNumber;\n let platformsContent = '';\n let platformsLine = '';\n while (lineNumber < lines.length && platformsLine !== 'end') {\n lineNumber += 1;\n platformsLine = lines[lineNumber];\n // istanbul ignore if\n if (!isString(platformsLine)) {\n logger.debug(\n { content, packageFile, type: 'platformsLine' },\n 'Bundler parsing error',\n );\n platformsLine = 'end';\n }\n if (platformsLine !== 'end') {\n platformsContent += formatContent(platformsLine);\n }\n }\n const platformsRes = await extractPackageFile(platformsContent);\n if (platformsRes) {\n res.deps = res.deps.concat(\n platformsRes.deps.map((dep) => ({\n ...dep,\n managerData: {\n lineNumber:\n (dep.managerData?.lineNumber ?? NaN) + platformsLineNumber + 1,\n },\n })),\n );\n }\n }\n const ifMatch = regEx(/^if\\s+(.*?)/).test(line);\n if (ifMatch) {\n const ifLineNumber = lineNumber;\n let ifContent = '';\n let ifLine = '';\n while (lineNumber < lines.length && ifLine !== 'end') {\n lineNumber += 1;\n ifLine = lines[lineNumber];\n // istanbul ignore if\n if (!isString(ifLine)) {\n logger.debug(\n { content, packageFile, type: 'ifLine' },\n 'Bundler parsing error',\n );\n ifLine = 'end';\n }\n if (ifLine !== 'end') {\n ifContent += formatContent(ifLine);\n }\n }\n const ifRes = await extractPackageFile(ifContent);\n if (ifRes) {\n res.deps = res.deps.concat(\n ifRes.deps.map((dep) => ({\n ...dep,\n managerData: {\n lineNumber:\n (dep.managerData?.lineNumber ?? NaN) + ifLineNumber + 1,\n },\n })),\n );\n }\n }\n }\n if (!res.deps.length && !res.registryUrls?.length) {\n return null;\n }\n\n if (packageFile) {\n const gemfileLockPath = await getLockFilePath(packageFile);\n const lockContent = await readLocalFile(gemfileLockPath, 'utf8');\n if (lockContent) {\n logger.debug(\n `Found lock file ${gemfileLockPath} for packageFile: ${packageFile}`,\n );\n res.lockFiles = [gemfileLockPath];\n const lockedEntries = extractLockFileEntries(lockContent);\n for (const dep of res.deps) {\n // TODO: types (#22198)\n const lockedDepValue = lockedEntries.get(`${dep.depName!}`);\n if (lockedDepValue) {\n dep.lockedVersion = lockedDepValue;\n }\n }\n }\n }\n return res;\n}\n"],"mappings":"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"}
|
|
@@ -3,7 +3,7 @@ import { logger } from "../../../logger/index.js";
|
|
|
3
3
|
import { api, id } from "../../versioning/debian/index.js";
|
|
4
4
|
import { id as id$1 } from "../../versioning/ubuntu/index.js";
|
|
5
5
|
import { DockerDatasource } from "../../datasource/docker/index.js";
|
|
6
|
-
import { isNonEmptyStringAndNotWhitespace, isString } from "@sindresorhus/is";
|
|
6
|
+
import { isNonEmptyStringAndNotWhitespace, isNumericString, isString } from "@sindresorhus/is";
|
|
7
7
|
//#region lib/modules/manager/dockerfile/extract.ts
|
|
8
8
|
const variableMarker = "$";
|
|
9
9
|
function extractVariables(image) {
|
|
@@ -203,7 +203,8 @@ function extractPackageFile(content, _packageFile, config) {
|
|
|
203
203
|
const copyFromMatch = instruction.match(copyFromRegex);
|
|
204
204
|
if (copyFromMatch?.groups?.image) {
|
|
205
205
|
if (stageNames.includes(copyFromMatch.groups.image)) logger.debug({ image: copyFromMatch.groups.image }, "Skipping alias COPY --from");
|
|
206
|
-
else if (
|
|
206
|
+
else if (isNumericString(copyFromMatch.groups.image)) logger.debug({ image: copyFromMatch.groups.image }, "Skipping index reference COPY --from");
|
|
207
|
+
else {
|
|
207
208
|
const dep = getDep(copyFromMatch.groups.image, true, config.registryAliases);
|
|
208
209
|
processDepForAutoReplace(dep, [[lineNumberInstrStart, lineNumber]], lines, lineFeed);
|
|
209
210
|
logger.debug({
|
|
@@ -212,7 +213,7 @@ function extractPackageFile(content, _packageFile, config) {
|
|
|
212
213
|
currentDigest: dep.currentDigest
|
|
213
214
|
}, "Dockerfile COPY --from");
|
|
214
215
|
deps.push(dep);
|
|
215
|
-
}
|
|
216
|
+
}
|
|
216
217
|
}
|
|
217
218
|
const runMountFromRegex = regEx(`^[ \\t]*RUN(?:${escapeChar}[ \\t]*\\r?\\n| |\\t|#.*?\\r?\\n|--[a-z]+(?:=[a-zA-Z0-9_.:-]+?)?)+--mount=(?:\\S*=\\S*,)*from=(?<image>[^, ]+)`, "im");
|
|
218
219
|
const runMountFromMatch = instruction.match(runMountFromRegex);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"extract.js","names":["ubuntuVersioning.id","debianVersioning.id"],"sources":["../../../../lib/modules/manager/dockerfile/extract.ts"],"sourcesContent":["import { isNonEmptyStringAndNotWhitespace, isString } from '@sindresorhus/is';\nimport { logger } from '../../../logger/index.ts';\nimport { newlineRegex, regEx } from '../../../util/regex.ts';\nimport { DockerDatasource } from '../../datasource/docker/index.ts';\nimport * as debianVersioning from '../../versioning/debian/index.ts';\nimport * as ubuntuVersioning from '../../versioning/ubuntu/index.ts';\nimport type {\n ExtractConfig,\n PackageDependency,\n PackageFileContent,\n} from '../types.ts';\n\nconst variableMarker = '$';\n\nexport function extractVariables(image: string): Record<string, string> {\n const variables: Record<string, string> = {};\n const variableRegex = regEx(\n /(?<fullvariable>\\\\?\\$(?<simplearg>\\w+)|\\\\?\\${(?<complexarg>\\w+)(?::.+?)?}+)/gi,\n );\n\n let match: RegExpExecArray | null;\n do {\n match = variableRegex.exec(image);\n if (match?.groups?.fullvariable) {\n variables[match.groups.fullvariable] =\n match.groups?.simplearg || match.groups?.complexarg;\n }\n } while (match);\n\n return variables;\n}\n\nfunction getAutoReplaceTemplate(dep: PackageDependency): string | undefined {\n let template = dep.replaceString;\n\n if (dep.currentValue) {\n let placeholder = '{{#if newValue}}{{newValue}}{{/if}}';\n if (!dep.currentDigest) {\n placeholder += '{{#if newDigest}}@{{newDigest}}{{/if}}';\n }\n template = template?.replace(dep.currentValue, placeholder);\n }\n\n if (dep.currentDigest) {\n template = template?.replace(\n dep.currentDigest,\n '{{#if newDigest}}{{newDigest}}{{/if}}',\n );\n }\n\n return template;\n}\n\nfunction processDepForAutoReplace(\n dep: PackageDependency,\n lineNumberRanges: number[][],\n lines: string[],\n linefeed: string,\n): void {\n const lineNumberRangesToReplace: number[][] = [];\n for (const lineNumberRange of lineNumberRanges) {\n for (const lineNumber of lineNumberRange) {\n if (\n (isString(dep.currentValue) &&\n lines[lineNumber].includes(dep.currentValue)) ||\n (isString(dep.currentDigest) &&\n lines[lineNumber].includes(dep.currentDigest))\n ) {\n lineNumberRangesToReplace.push(lineNumberRange);\n }\n }\n }\n\n lineNumberRangesToReplace.sort((a, b) => {\n return a[0] - b[0];\n });\n\n const minLine = lineNumberRangesToReplace[0]?.[0];\n const maxLine = lineNumberRangesToReplace.at(-1)?.[1];\n if (\n lineNumberRanges.length === 1 ||\n minLine === undefined ||\n maxLine === undefined\n ) {\n return;\n }\n\n const unfoldedLineNumbers = Array.from(\n { length: maxLine - minLine + 1 },\n (_v, k) => k + minLine,\n );\n\n dep.replaceString = unfoldedLineNumbers\n .map((lineNumber) => lines[lineNumber])\n .join(linefeed);\n\n if (!dep.currentDigest) {\n dep.replaceString += linefeed;\n }\n\n dep.autoReplaceStringTemplate = getAutoReplaceTemplate(dep);\n}\n\nexport function splitImageParts(currentFrom: string): PackageDependency {\n let isVariable = false;\n let cleanedCurrentFrom = currentFrom;\n\n // Check if we have a variable in format of \"${VARIABLE:-<image>:<defaultVal>@<digest>}\"\n // If so, remove everything except the image, defaultVal and digest.\n if (cleanedCurrentFrom?.includes(variableMarker)) {\n const defaultValueRegex = regEx(/^\\${.+?:-\"?(?<value>.*?)\"?}$/);\n const defaultValueMatch =\n defaultValueRegex.exec(cleanedCurrentFrom)?.groups;\n if (defaultValueMatch?.value) {\n isVariable = true;\n cleanedCurrentFrom = defaultValueMatch.value;\n }\n\n if (cleanedCurrentFrom?.includes(variableMarker)) {\n // If cleanedCurrentFrom contains a variable, after cleaning, e.g. \"$REGISTRY/alpine\", we do not support this.\n return {\n skipReason: 'contains-variable',\n };\n }\n }\n\n const [currentDepTag, currentDigest] = cleanedCurrentFrom.split('@');\n const depTagSplit = currentDepTag.split(':');\n let depName: string;\n let currentValue: string | undefined;\n if (depTagSplit.length === 1 || depTagSplit.at(-1)!.includes('/')) {\n depName = currentDepTag;\n } else {\n currentValue = depTagSplit.pop();\n depName = depTagSplit.join(':');\n }\n\n const dep: PackageDependency = {\n depName,\n packageName: depName,\n currentValue,\n currentDigest,\n };\n\n if (isVariable) {\n dep.replaceString = cleanedCurrentFrom;\n\n if (!dep.currentValue) {\n delete dep.currentValue;\n }\n\n if (!dep.currentDigest) {\n delete dep.currentDigest;\n }\n }\n\n return dep;\n}\n\nconst quayRegex = regEx(/^quay\\.io(?::[1-9][0-9]{0,4})?/i);\n\nexport function getDep(\n currentFrom: string | null | undefined,\n specifyReplaceString = true,\n registryAliases?: Record<string, string>,\n): PackageDependency {\n if (\n !isString(currentFrom) ||\n !isNonEmptyStringAndNotWhitespace(currentFrom)\n ) {\n return {\n skipReason: 'invalid-value',\n };\n }\n\n // Resolve registry aliases first so that we don't need special casing later on:\n for (const [name, value] of Object.entries(registryAliases ?? {})) {\n if (currentFrom.startsWith(`${name}/`)) {\n const depName = currentFrom.substring(name.length + 1);\n const dep = getDep(`${value}/${depName}`, false);\n // retain depName, not sure if condition is necessary\n if (dep.depName?.startsWith(value)) {\n dep.packageName = dep.depName;\n dep.depName = `${name}/${dep.depName.substring(value.length + 1)}`;\n }\n if (specifyReplaceString) {\n dep.replaceString = currentFrom;\n dep.autoReplaceStringTemplate = getAutoReplaceTemplate(dep);\n }\n return dep;\n }\n }\n\n const dep = splitImageParts(currentFrom);\n if (specifyReplaceString) {\n dep.replaceString ??= currentFrom;\n dep.autoReplaceStringTemplate =\n '{{depName}}{{#if newValue}}:{{newValue}}{{/if}}{{#if newDigest}}@{{newDigest}}{{/if}}';\n }\n dep.datasource = DockerDatasource.id;\n\n // Pretty up special prefixes\n if (dep.depName) {\n const specialPrefixes = ['amd64', 'arm64', 'library'];\n for (const prefix of specialPrefixes) {\n if (dep.depName.startsWith(`${prefix}/`)) {\n dep.depName = dep.depName.replace(`${prefix}/`, '');\n if (specifyReplaceString) {\n dep.autoReplaceStringTemplate =\n '{{packageName}}{{#if newValue}}:{{newValue}}{{/if}}{{#if newDigest}}@{{newDigest}}{{/if}}';\n }\n }\n }\n }\n\n if (dep.depName === 'ubuntu' || dep.depName?.endsWith('/ubuntu')) {\n dep.versioning = ubuntuVersioning.id;\n }\n\n if (\n (dep.depName === 'debian' || dep.depName?.endsWith('/debian')) &&\n debianVersioning.api.isVersion(dep.currentValue)\n ) {\n dep.versioning = debianVersioning.id;\n }\n\n // Don't display quay.io ports\n if (dep.depName && quayRegex.test(dep.depName)) {\n const depName = dep.depName.replace(quayRegex, 'quay.io');\n if (depName !== dep.depName) {\n dep.depName = depName;\n dep.autoReplaceStringTemplate =\n '{{packageName}}{{#if newValue}}:{{newValue}}{{/if}}{{#if newDigest}}@{{newDigest}}{{/if}}';\n }\n }\n\n return dep;\n}\n\nexport function extractPackageFile(\n content: string,\n _packageFile: string,\n config: ExtractConfig,\n): PackageFileContent | null {\n const sanitizedContent = content.replace(regEx(/^\\uFEFF/), ''); // remove bom marker\n const deps: PackageDependency[] = [];\n const stageNames: string[] = [];\n const args: Record<string, string> = {};\n const argsLines: Record<string, number[]> = {};\n\n let escapeChar = '\\\\\\\\';\n let lookForEscapeChar = true;\n let lookForSyntaxDirective = true;\n\n const lineFeed = sanitizedContent.includes('\\r\\n') ? '\\r\\n' : '\\n';\n const lines = sanitizedContent.split(newlineRegex);\n for (let lineNumber = 0; lineNumber < lines.length; ) {\n const lineNumberInstrStart = lineNumber;\n let instruction = lines[lineNumber];\n\n if (lookForEscapeChar) {\n const directivesMatch = regEx(\n /^[ \\t]*#[ \\t]*(?<directive>syntax|escape)[ \\t]*=[ \\t]*(?<escapeChar>\\S)/i,\n ).exec(instruction);\n if (!directivesMatch) {\n lookForEscapeChar = false;\n } else if (directivesMatch.groups?.directive.toLowerCase() === 'escape') {\n if (directivesMatch.groups?.escapeChar === '`') {\n escapeChar = '`';\n }\n lookForEscapeChar = false;\n }\n }\n\n if (lookForSyntaxDirective) {\n const syntaxRegex = regEx(\n '^#[ \\\\t]*syntax[ \\\\t]*=[ \\\\t]*(?<image>\\\\S+)',\n 'im',\n );\n const syntaxMatch = instruction.match(syntaxRegex);\n if (syntaxMatch?.groups?.image) {\n const syntaxImage = syntaxMatch.groups.image;\n const lineNumberRanges: number[][] = [\n [lineNumberInstrStart, lineNumber],\n ];\n const dep = getDep(syntaxImage, true, config.registryAliases);\n dep.depType = 'syntax';\n processDepForAutoReplace(dep, lineNumberRanges, lines, lineFeed);\n logger.trace(\n {\n depName: dep.depName,\n currentValue: dep.currentValue,\n currentDigest: dep.currentDigest,\n },\n 'Dockerfile # syntax',\n );\n deps.push(dep);\n }\n lookForSyntaxDirective = false;\n }\n\n const lineContinuationRegex = regEx(`${escapeChar}[ \\\\t]*$|^[ \\\\t]*#`, 'm');\n let lineLookahead = instruction;\n while (\n !lookForEscapeChar &&\n !instruction.trimStart().startsWith('#') &&\n lineContinuationRegex.test(lineLookahead)\n ) {\n lineLookahead = lines[++lineNumber] || '';\n instruction += `\\n${lineLookahead}`;\n }\n\n const argRegex = regEx(\n `^[ \\\\t]*ARG(?:${escapeChar}[ \\\\t]*\\\\r?\\\\n| |\\\\t|#.*?\\\\r?\\\\n)+(?<name>\\\\w+)[ =](?<value>\\\\S*)`,\n 'im',\n );\n const argMatch = argRegex.exec(instruction);\n if (argMatch?.groups?.name) {\n argsLines[argMatch.groups.name] = [lineNumberInstrStart, lineNumber];\n let argMatchValue = argMatch.groups?.value;\n\n if (\n (argMatchValue.startsWith('\"') && argMatchValue.endsWith('\"')) ||\n (argMatchValue.startsWith(\"'\") && argMatchValue.endsWith(\"'\"))\n ) {\n argMatchValue = argMatchValue.slice(1, -1);\n }\n\n args[argMatch.groups.name] = argMatchValue || '';\n }\n\n const fromRegex = regEx(\n `^[ \\\\t]*FROM(?:${escapeChar}[ \\\\t]*\\\\r?\\\\n| |\\\\t|#.*?\\\\r?\\\\n|--platform=\\\\S+)+(?<image>\\\\S+)(?:(?:${escapeChar}[ \\\\t]*\\\\r?\\\\n| |\\\\t|#.*?\\\\r?\\\\n)+as[ \\\\t]+(?<name>\\\\S+))?`,\n 'im',\n );\n const fromMatch = instruction.match(fromRegex);\n if (fromMatch?.groups?.image) {\n let fromImage = fromMatch.groups.image;\n const lineNumberRanges: number[][] = [[lineNumberInstrStart, lineNumber]];\n\n if (fromImage.includes(variableMarker)) {\n const variables = extractVariables(fromImage);\n for (const [fullVariable, argName] of Object.entries(variables)) {\n const resolvedArgValue = args[argName];\n if (resolvedArgValue || resolvedArgValue === '') {\n fromImage = fromImage.replaceAll(fullVariable, resolvedArgValue);\n lineNumberRanges.push(argsLines[argName]);\n }\n }\n }\n\n if (fromMatch.groups?.name) {\n logger.debug(\n `Found a multistage build stage name: ${fromMatch.groups.name}`,\n );\n stageNames.push(fromMatch.groups.name);\n }\n if (fromImage === 'scratch') {\n logger.debug('Skipping scratch');\n } else if (fromImage && stageNames.includes(fromImage)) {\n logger.debug(`Skipping alias FROM image:${fromImage}`);\n } else {\n const dep = getDep(fromImage, true, config.registryAliases);\n processDepForAutoReplace(dep, lineNumberRanges, lines, lineFeed);\n logger.trace(\n {\n depName: dep.depName,\n currentValue: dep.currentValue,\n currentDigest: dep.currentDigest,\n },\n 'Dockerfile FROM',\n );\n deps.push(dep);\n }\n }\n\n const copyFromRegex = regEx(\n `^[ \\\\t]*COPY(?:${escapeChar}[ \\\\t]*\\\\r?\\\\n| |\\\\t|#.*?\\\\r?\\\\n|--[a-z]+(?:=[a-zA-Z0-9_.:-]+?)?)+--from=(?<image>\\\\S+)`,\n 'im',\n );\n const copyFromMatch = instruction.match(copyFromRegex);\n if (copyFromMatch?.groups?.image) {\n if (stageNames.includes(copyFromMatch.groups.image)) {\n logger.debug(\n { image: copyFromMatch.groups.image },\n 'Skipping alias COPY --from',\n );\n } else if (Number.isNaN(Number(copyFromMatch.groups.image))) {\n const dep = getDep(\n copyFromMatch.groups.image,\n true,\n config.registryAliases,\n );\n const lineNumberRanges: number[][] = [\n [lineNumberInstrStart, lineNumber],\n ];\n processDepForAutoReplace(dep, lineNumberRanges, lines, lineFeed);\n logger.debug(\n {\n depName: dep.depName,\n currentValue: dep.currentValue,\n currentDigest: dep.currentDigest,\n },\n 'Dockerfile COPY --from',\n );\n deps.push(dep);\n } else {\n logger.debug(\n { image: copyFromMatch.groups.image },\n 'Skipping index reference COPY --from',\n );\n }\n }\n\n const runMountFromRegex = regEx(\n `^[ \\\\t]*RUN(?:${escapeChar}[ \\\\t]*\\\\r?\\\\n| |\\\\t|#.*?\\\\r?\\\\n|--[a-z]+(?:=[a-zA-Z0-9_.:-]+?)?)+--mount=(?:\\\\S*=\\\\S*,)*from=(?<image>[^, ]+)`,\n 'im',\n );\n const runMountFromMatch = instruction.match(runMountFromRegex);\n if (runMountFromMatch?.groups?.image) {\n if (stageNames.includes(runMountFromMatch.groups.image)) {\n logger.debug(\n { image: runMountFromMatch.groups.image },\n 'Skipping alias RUN --mount=from',\n );\n } else {\n const dep = getDep(\n runMountFromMatch.groups.image,\n true,\n config.registryAliases,\n );\n const lineNumberRanges: number[][] = [\n [lineNumberInstrStart, lineNumber],\n ];\n processDepForAutoReplace(dep, lineNumberRanges, lines, lineFeed);\n logger.debug(\n {\n depName: dep.depName,\n currentValue: dep.currentValue,\n currentDigest: dep.currentDigest,\n },\n 'Dockerfile RUN --mount=from',\n );\n deps.push(dep);\n }\n }\n\n lineNumber += 1;\n }\n\n if (!deps.length) {\n return null;\n }\n for (const d of deps) {\n d.depType ??= 'stage';\n }\n deps.at(-1)!.depType = 'final';\n return { deps };\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"extract.js","names":["ubuntuVersioning.id","debianVersioning.id"],"sources":["../../../../lib/modules/manager/dockerfile/extract.ts"],"sourcesContent":["import {\n isNonEmptyStringAndNotWhitespace,\n isNumericString,\n isString,\n} from '@sindresorhus/is';\nimport { logger } from '../../../logger/index.ts';\nimport { newlineRegex, regEx } from '../../../util/regex.ts';\nimport { DockerDatasource } from '../../datasource/docker/index.ts';\nimport * as debianVersioning from '../../versioning/debian/index.ts';\nimport * as ubuntuVersioning from '../../versioning/ubuntu/index.ts';\nimport type {\n ExtractConfig,\n PackageDependency,\n PackageFileContent,\n} from '../types.ts';\n\nconst variableMarker = '$';\n\nexport function extractVariables(image: string): Record<string, string> {\n const variables: Record<string, string> = {};\n const variableRegex = regEx(\n /(?<fullvariable>\\\\?\\$(?<simplearg>\\w+)|\\\\?\\${(?<complexarg>\\w+)(?::.+?)?}+)/gi,\n );\n\n let match: RegExpExecArray | null;\n do {\n match = variableRegex.exec(image);\n if (match?.groups?.fullvariable) {\n variables[match.groups.fullvariable] =\n match.groups?.simplearg || match.groups?.complexarg;\n }\n } while (match);\n\n return variables;\n}\n\nfunction getAutoReplaceTemplate(dep: PackageDependency): string | undefined {\n let template = dep.replaceString;\n\n if (dep.currentValue) {\n let placeholder = '{{#if newValue}}{{newValue}}{{/if}}';\n if (!dep.currentDigest) {\n placeholder += '{{#if newDigest}}@{{newDigest}}{{/if}}';\n }\n template = template?.replace(dep.currentValue, placeholder);\n }\n\n if (dep.currentDigest) {\n template = template?.replace(\n dep.currentDigest,\n '{{#if newDigest}}{{newDigest}}{{/if}}',\n );\n }\n\n return template;\n}\n\nfunction processDepForAutoReplace(\n dep: PackageDependency,\n lineNumberRanges: number[][],\n lines: string[],\n linefeed: string,\n): void {\n const lineNumberRangesToReplace: number[][] = [];\n for (const lineNumberRange of lineNumberRanges) {\n for (const lineNumber of lineNumberRange) {\n if (\n (isString(dep.currentValue) &&\n lines[lineNumber].includes(dep.currentValue)) ||\n (isString(dep.currentDigest) &&\n lines[lineNumber].includes(dep.currentDigest))\n ) {\n lineNumberRangesToReplace.push(lineNumberRange);\n }\n }\n }\n\n lineNumberRangesToReplace.sort((a, b) => {\n return a[0] - b[0];\n });\n\n const minLine = lineNumberRangesToReplace[0]?.[0];\n const maxLine = lineNumberRangesToReplace.at(-1)?.[1];\n if (\n lineNumberRanges.length === 1 ||\n minLine === undefined ||\n maxLine === undefined\n ) {\n return;\n }\n\n const unfoldedLineNumbers = Array.from(\n { length: maxLine - minLine + 1 },\n (_v, k) => k + minLine,\n );\n\n dep.replaceString = unfoldedLineNumbers\n .map((lineNumber) => lines[lineNumber])\n .join(linefeed);\n\n if (!dep.currentDigest) {\n dep.replaceString += linefeed;\n }\n\n dep.autoReplaceStringTemplate = getAutoReplaceTemplate(dep);\n}\n\nexport function splitImageParts(currentFrom: string): PackageDependency {\n let isVariable = false;\n let cleanedCurrentFrom = currentFrom;\n\n // Check if we have a variable in format of \"${VARIABLE:-<image>:<defaultVal>@<digest>}\"\n // If so, remove everything except the image, defaultVal and digest.\n if (cleanedCurrentFrom?.includes(variableMarker)) {\n const defaultValueRegex = regEx(/^\\${.+?:-\"?(?<value>.*?)\"?}$/);\n const defaultValueMatch =\n defaultValueRegex.exec(cleanedCurrentFrom)?.groups;\n if (defaultValueMatch?.value) {\n isVariable = true;\n cleanedCurrentFrom = defaultValueMatch.value;\n }\n\n if (cleanedCurrentFrom?.includes(variableMarker)) {\n // If cleanedCurrentFrom contains a variable, after cleaning, e.g. \"$REGISTRY/alpine\", we do not support this.\n return {\n skipReason: 'contains-variable',\n };\n }\n }\n\n const [currentDepTag, currentDigest] = cleanedCurrentFrom.split('@');\n const depTagSplit = currentDepTag.split(':');\n let depName: string;\n let currentValue: string | undefined;\n if (depTagSplit.length === 1 || depTagSplit.at(-1)!.includes('/')) {\n depName = currentDepTag;\n } else {\n currentValue = depTagSplit.pop();\n depName = depTagSplit.join(':');\n }\n\n const dep: PackageDependency = {\n depName,\n packageName: depName,\n currentValue,\n currentDigest,\n };\n\n if (isVariable) {\n dep.replaceString = cleanedCurrentFrom;\n\n if (!dep.currentValue) {\n delete dep.currentValue;\n }\n\n if (!dep.currentDigest) {\n delete dep.currentDigest;\n }\n }\n\n return dep;\n}\n\nconst quayRegex = regEx(/^quay\\.io(?::[1-9][0-9]{0,4})?/i);\n\nexport function getDep(\n currentFrom: string | null | undefined,\n specifyReplaceString = true,\n registryAliases?: Record<string, string>,\n): PackageDependency {\n if (\n !isString(currentFrom) ||\n !isNonEmptyStringAndNotWhitespace(currentFrom)\n ) {\n return {\n skipReason: 'invalid-value',\n };\n }\n\n // Resolve registry aliases first so that we don't need special casing later on:\n for (const [name, value] of Object.entries(registryAliases ?? {})) {\n if (currentFrom.startsWith(`${name}/`)) {\n const depName = currentFrom.substring(name.length + 1);\n const dep = getDep(`${value}/${depName}`, false);\n // retain depName, not sure if condition is necessary\n if (dep.depName?.startsWith(value)) {\n dep.packageName = dep.depName;\n dep.depName = `${name}/${dep.depName.substring(value.length + 1)}`;\n }\n if (specifyReplaceString) {\n dep.replaceString = currentFrom;\n dep.autoReplaceStringTemplate = getAutoReplaceTemplate(dep);\n }\n return dep;\n }\n }\n\n const dep = splitImageParts(currentFrom);\n if (specifyReplaceString) {\n dep.replaceString ??= currentFrom;\n dep.autoReplaceStringTemplate =\n '{{depName}}{{#if newValue}}:{{newValue}}{{/if}}{{#if newDigest}}@{{newDigest}}{{/if}}';\n }\n dep.datasource = DockerDatasource.id;\n\n // Pretty up special prefixes\n if (dep.depName) {\n const specialPrefixes = ['amd64', 'arm64', 'library'];\n for (const prefix of specialPrefixes) {\n if (dep.depName.startsWith(`${prefix}/`)) {\n dep.depName = dep.depName.replace(`${prefix}/`, '');\n if (specifyReplaceString) {\n dep.autoReplaceStringTemplate =\n '{{packageName}}{{#if newValue}}:{{newValue}}{{/if}}{{#if newDigest}}@{{newDigest}}{{/if}}';\n }\n }\n }\n }\n\n if (dep.depName === 'ubuntu' || dep.depName?.endsWith('/ubuntu')) {\n dep.versioning = ubuntuVersioning.id;\n }\n\n if (\n (dep.depName === 'debian' || dep.depName?.endsWith('/debian')) &&\n debianVersioning.api.isVersion(dep.currentValue)\n ) {\n dep.versioning = debianVersioning.id;\n }\n\n // Don't display quay.io ports\n if (dep.depName && quayRegex.test(dep.depName)) {\n const depName = dep.depName.replace(quayRegex, 'quay.io');\n if (depName !== dep.depName) {\n dep.depName = depName;\n dep.autoReplaceStringTemplate =\n '{{packageName}}{{#if newValue}}:{{newValue}}{{/if}}{{#if newDigest}}@{{newDigest}}{{/if}}';\n }\n }\n\n return dep;\n}\n\nexport function extractPackageFile(\n content: string,\n _packageFile: string,\n config: ExtractConfig,\n): PackageFileContent | null {\n const sanitizedContent = content.replace(regEx(/^\\uFEFF/), ''); // remove bom marker\n const deps: PackageDependency[] = [];\n const stageNames: string[] = [];\n const args: Record<string, string> = {};\n const argsLines: Record<string, number[]> = {};\n\n let escapeChar = '\\\\\\\\';\n let lookForEscapeChar = true;\n let lookForSyntaxDirective = true;\n\n const lineFeed = sanitizedContent.includes('\\r\\n') ? '\\r\\n' : '\\n';\n const lines = sanitizedContent.split(newlineRegex);\n for (let lineNumber = 0; lineNumber < lines.length; ) {\n const lineNumberInstrStart = lineNumber;\n let instruction = lines[lineNumber];\n\n if (lookForEscapeChar) {\n const directivesMatch = regEx(\n /^[ \\t]*#[ \\t]*(?<directive>syntax|escape)[ \\t]*=[ \\t]*(?<escapeChar>\\S)/i,\n ).exec(instruction);\n if (!directivesMatch) {\n lookForEscapeChar = false;\n } else if (directivesMatch.groups?.directive.toLowerCase() === 'escape') {\n if (directivesMatch.groups?.escapeChar === '`') {\n escapeChar = '`';\n }\n lookForEscapeChar = false;\n }\n }\n\n if (lookForSyntaxDirective) {\n const syntaxRegex = regEx(\n '^#[ \\\\t]*syntax[ \\\\t]*=[ \\\\t]*(?<image>\\\\S+)',\n 'im',\n );\n const syntaxMatch = instruction.match(syntaxRegex);\n if (syntaxMatch?.groups?.image) {\n const syntaxImage = syntaxMatch.groups.image;\n const lineNumberRanges: number[][] = [\n [lineNumberInstrStart, lineNumber],\n ];\n const dep = getDep(syntaxImage, true, config.registryAliases);\n dep.depType = 'syntax';\n processDepForAutoReplace(dep, lineNumberRanges, lines, lineFeed);\n logger.trace(\n {\n depName: dep.depName,\n currentValue: dep.currentValue,\n currentDigest: dep.currentDigest,\n },\n 'Dockerfile # syntax',\n );\n deps.push(dep);\n }\n lookForSyntaxDirective = false;\n }\n\n const lineContinuationRegex = regEx(`${escapeChar}[ \\\\t]*$|^[ \\\\t]*#`, 'm');\n let lineLookahead = instruction;\n while (\n !lookForEscapeChar &&\n !instruction.trimStart().startsWith('#') &&\n lineContinuationRegex.test(lineLookahead)\n ) {\n lineLookahead = lines[++lineNumber] || '';\n instruction += `\\n${lineLookahead}`;\n }\n\n const argRegex = regEx(\n `^[ \\\\t]*ARG(?:${escapeChar}[ \\\\t]*\\\\r?\\\\n| |\\\\t|#.*?\\\\r?\\\\n)+(?<name>\\\\w+)[ =](?<value>\\\\S*)`,\n 'im',\n );\n const argMatch = argRegex.exec(instruction);\n if (argMatch?.groups?.name) {\n argsLines[argMatch.groups.name] = [lineNumberInstrStart, lineNumber];\n let argMatchValue = argMatch.groups?.value;\n\n if (\n (argMatchValue.startsWith('\"') && argMatchValue.endsWith('\"')) ||\n (argMatchValue.startsWith(\"'\") && argMatchValue.endsWith(\"'\"))\n ) {\n argMatchValue = argMatchValue.slice(1, -1);\n }\n\n args[argMatch.groups.name] = argMatchValue || '';\n }\n\n const fromRegex = regEx(\n `^[ \\\\t]*FROM(?:${escapeChar}[ \\\\t]*\\\\r?\\\\n| |\\\\t|#.*?\\\\r?\\\\n|--platform=\\\\S+)+(?<image>\\\\S+)(?:(?:${escapeChar}[ \\\\t]*\\\\r?\\\\n| |\\\\t|#.*?\\\\r?\\\\n)+as[ \\\\t]+(?<name>\\\\S+))?`,\n 'im',\n );\n const fromMatch = instruction.match(fromRegex);\n if (fromMatch?.groups?.image) {\n let fromImage = fromMatch.groups.image;\n const lineNumberRanges: number[][] = [[lineNumberInstrStart, lineNumber]];\n\n if (fromImage.includes(variableMarker)) {\n const variables = extractVariables(fromImage);\n for (const [fullVariable, argName] of Object.entries(variables)) {\n const resolvedArgValue = args[argName];\n if (resolvedArgValue || resolvedArgValue === '') {\n fromImage = fromImage.replaceAll(fullVariable, resolvedArgValue);\n lineNumberRanges.push(argsLines[argName]);\n }\n }\n }\n\n if (fromMatch.groups?.name) {\n logger.debug(\n `Found a multistage build stage name: ${fromMatch.groups.name}`,\n );\n stageNames.push(fromMatch.groups.name);\n }\n if (fromImage === 'scratch') {\n logger.debug('Skipping scratch');\n } else if (fromImage && stageNames.includes(fromImage)) {\n logger.debug(`Skipping alias FROM image:${fromImage}`);\n } else {\n const dep = getDep(fromImage, true, config.registryAliases);\n processDepForAutoReplace(dep, lineNumberRanges, lines, lineFeed);\n logger.trace(\n {\n depName: dep.depName,\n currentValue: dep.currentValue,\n currentDigest: dep.currentDigest,\n },\n 'Dockerfile FROM',\n );\n deps.push(dep);\n }\n }\n\n const copyFromRegex = regEx(\n `^[ \\\\t]*COPY(?:${escapeChar}[ \\\\t]*\\\\r?\\\\n| |\\\\t|#.*?\\\\r?\\\\n|--[a-z]+(?:=[a-zA-Z0-9_.:-]+?)?)+--from=(?<image>\\\\S+)`,\n 'im',\n );\n const copyFromMatch = instruction.match(copyFromRegex);\n if (copyFromMatch?.groups?.image) {\n if (stageNames.includes(copyFromMatch.groups.image)) {\n logger.debug(\n { image: copyFromMatch.groups.image },\n 'Skipping alias COPY --from',\n );\n } else if (isNumericString(copyFromMatch.groups.image)) {\n logger.debug(\n { image: copyFromMatch.groups.image },\n 'Skipping index reference COPY --from',\n );\n } else {\n const dep = getDep(\n copyFromMatch.groups.image,\n true,\n config.registryAliases,\n );\n const lineNumberRanges: number[][] = [\n [lineNumberInstrStart, lineNumber],\n ];\n processDepForAutoReplace(dep, lineNumberRanges, lines, lineFeed);\n logger.debug(\n {\n depName: dep.depName,\n currentValue: dep.currentValue,\n currentDigest: dep.currentDigest,\n },\n 'Dockerfile COPY --from',\n );\n deps.push(dep);\n }\n }\n\n const runMountFromRegex = regEx(\n `^[ \\\\t]*RUN(?:${escapeChar}[ \\\\t]*\\\\r?\\\\n| |\\\\t|#.*?\\\\r?\\\\n|--[a-z]+(?:=[a-zA-Z0-9_.:-]+?)?)+--mount=(?:\\\\S*=\\\\S*,)*from=(?<image>[^, ]+)`,\n 'im',\n );\n const runMountFromMatch = instruction.match(runMountFromRegex);\n if (runMountFromMatch?.groups?.image) {\n if (stageNames.includes(runMountFromMatch.groups.image)) {\n logger.debug(\n { image: runMountFromMatch.groups.image },\n 'Skipping alias RUN --mount=from',\n );\n } else {\n const dep = getDep(\n runMountFromMatch.groups.image,\n true,\n config.registryAliases,\n );\n const lineNumberRanges: number[][] = [\n [lineNumberInstrStart, lineNumber],\n ];\n processDepForAutoReplace(dep, lineNumberRanges, lines, lineFeed);\n logger.debug(\n {\n depName: dep.depName,\n currentValue: dep.currentValue,\n currentDigest: dep.currentDigest,\n },\n 'Dockerfile RUN --mount=from',\n );\n deps.push(dep);\n }\n }\n\n lineNumber += 1;\n }\n\n if (!deps.length) {\n return null;\n }\n for (const d of deps) {\n d.depType ??= 'stage';\n }\n deps.at(-1)!.depType = 'final';\n return { deps };\n}\n"],"mappings":"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"}
|
|
@@ -105,7 +105,7 @@ var GerritScm = class extends DefaultGitScm {
|
|
|
105
105
|
*/
|
|
106
106
|
function nextPatchSetRef(currentRef) {
|
|
107
107
|
const lastSlash = currentRef.lastIndexOf("/");
|
|
108
|
-
const patchSet =
|
|
108
|
+
const patchSet = parseInt(currentRef.slice(lastSlash + 1), 10);
|
|
109
109
|
return `${currentRef.slice(0, lastSlash + 1)}${patchSet + 1}`;
|
|
110
110
|
}
|
|
111
111
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scm.js","names":["git.pushCommit","git.prepareCommit","git.setVirtualBranch"],"sources":["../../../../lib/modules/platform/gerrit/scm.ts"],"sourcesContent":["import { randomUUID } from 'node:crypto';\nimport { isNonEmptyArray, isString } from '@sindresorhus/is';\nimport { logger } from '../../../logger/index.ts';\nimport * as git from '../../../util/git/index.ts';\nimport type { CommitFilesConfig, FileChange } from '../../../util/git/types.ts';\nimport { hash } from '../../../util/hash.ts';\nimport type { LongCommitSha } from '../../../util/schema-utils/git.ts';\nimport { DefaultGitScm } from '../default-scm.ts';\nimport { client } from './client.ts';\nimport type { GerritLabels } from './schema.ts';\nimport { mapBranchStatusToLabel } from './utils.ts';\n\nconst CODE_REVIEW_LABEL = 'Code-Review';\n\n/**\n * Gerrit SCM strategy:\n * Instead of implementing custom branch operations, we fetch all open Gerrit changes\n * as virtual branches (refs/remotes/origin/<branchName>) after repository initialization.\n * This allows us to leverage DefaultGitScm for most operations, treating virtual branches\n * as regular Git branches, while minimizing Gerrit API requests.\n */\n\nlet repository: string;\nlet projectLabels: GerritLabels = {};\nexport function configureScm(repo: string, labels: GerritLabels = {}): void {\n repository = repo;\n projectLabels = labels;\n}\n\n/**\n * Returns the max vote value for the \"Code-Review\" label (some Gerrit\n * projects only allow up to +1), or `null` if the label isn't defined on\n * the project, so the caller can skip voting instead of failing the push.\n */\nfunction getAutoApproveLabelValue(): number | null {\n const codeReviewLabel = projectLabels[CODE_REVIEW_LABEL];\n if (!codeReviewLabel) {\n logger.warn(\n { repository, label: CODE_REVIEW_LABEL },\n 'Cannot auto-approve: label is not defined on the project',\n );\n return null;\n }\n return mapBranchStatusToLabel('green', codeReviewLabel);\n}\n\nexport async function pushForReview(options: {\n sourceRef: string;\n targetBranch: string;\n files: FileChange[];\n autoApprove?: boolean;\n labels?: string[];\n}): Promise<boolean> {\n const pushOptions = ['notify=NONE', 'ready'];\n if (options.autoApprove) {\n const value = getAutoApproveLabelValue();\n if (value !== null) {\n pushOptions.push(`label=${CODE_REVIEW_LABEL}+${value}`);\n }\n }\n if (isNonEmptyArray(options.labels)) {\n for (const label of options.labels) {\n pushOptions.push(`hashtag=${label}`);\n }\n }\n\n return git.pushCommit({\n sourceRef: options.sourceRef,\n targetRef: `refs/for/${options.targetBranch}`,\n files: options.files,\n pushOptions,\n });\n}\n\nexport class GerritScm extends DefaultGitScm {\n override async commitAndPush(\n commit: CommitFilesConfig,\n ): Promise<LongCommitSha | null> {\n logger.debug(`commitAndPush(${commit.branchName})`);\n\n const existingChange = await client.getBranchChange(repository, {\n branchName: commit.branchName,\n state: 'open',\n targetBranch: commit.baseBranch,\n requestDetails: ['CURRENT_REVISION'],\n });\n\n const message = isString(commit.message)\n ? [commit.message]\n : commit.message;\n\n // In Gerrit, the change subject/title is the first line of the commit message\n // v8 ignore else -- TODO: add test #40625\n if (commit.prTitle) {\n const firstMessageLines = message[0].split('\\n');\n firstMessageLines[0] = commit.prTitle;\n message[0] = firstMessageLines.join('\\n');\n }\n\n const changeId = existingChange?.change_id ?? generateChangeId();\n commit.message = message;\n commit.trailers = [\n ...(commit.trailers ?? []).filter(\n (trailer) =>\n !trailer.startsWith('Renovate-Branch:') &&\n !trailer.startsWith('Change-Id:'),\n ),\n `Renovate-Branch: ${commit.branchName}`,\n `Change-Id: ${changeId}`,\n ];\n // prepareCommit already checks hasDiff('HEAD', 'origin/<branchName>') when\n // force is not set, which works because virtual branches are fetched as\n // refs/remotes/origin/<branchName> during init. This avoids pushing empty\n // patch sets without a separate diff check.\n const commitResult = await git.prepareCommit(commit);\n if (commitResult) {\n const { commitSha } = commitResult;\n if (existingChange) {\n // Since the change already exists, we push to the same target branch to\n // avoid creating a new change if the base branch has changed.\n // updatePr() will later take care of moving the existing change to a\n // different base branch if needed.\n const pushResult = await pushForReview({\n sourceRef: commit.branchName,\n targetBranch: existingChange.branch,\n files: commit.files,\n autoApprove: commit.autoApprove,\n });\n /* v8 ignore else -- should never happen */\n if (pushResult) {\n const currentRef =\n existingChange.revisions![existingChange.current_revision!].ref;\n await git.setVirtualBranch(\n commit.branchName,\n nextPatchSetRef(currentRef),\n commitSha,\n );\n return commitSha;\n }\n } else {\n logger.debug(`Commit prepared, push deferred to createPr()`);\n return commitSha;\n }\n }\n return null; // empty commit, no changes in this Gerrit Change\n }\n}\n\n/**\n * Derive the next patch-set ref from a Gerrit change ref.\n * Gerrit refs follow the pattern `refs/changes/<NN>/<change>/<patchset>`.\n * After a push, Gerrit creates the next patch-set, so we increment the\n * trailing number to keep the virtual branch in sync.\n */\nexport function nextPatchSetRef(currentRef: string): string {\n const lastSlash = currentRef.lastIndexOf('/');\n const patchSet =
|
|
1
|
+
{"version":3,"file":"scm.js","names":["git.pushCommit","git.prepareCommit","git.setVirtualBranch"],"sources":["../../../../lib/modules/platform/gerrit/scm.ts"],"sourcesContent":["import { randomUUID } from 'node:crypto';\nimport { isNonEmptyArray, isString } from '@sindresorhus/is';\nimport { logger } from '../../../logger/index.ts';\nimport * as git from '../../../util/git/index.ts';\nimport type { CommitFilesConfig, FileChange } from '../../../util/git/types.ts';\nimport { hash } from '../../../util/hash.ts';\nimport type { LongCommitSha } from '../../../util/schema-utils/git.ts';\nimport { DefaultGitScm } from '../default-scm.ts';\nimport { client } from './client.ts';\nimport type { GerritLabels } from './schema.ts';\nimport { mapBranchStatusToLabel } from './utils.ts';\n\nconst CODE_REVIEW_LABEL = 'Code-Review';\n\n/**\n * Gerrit SCM strategy:\n * Instead of implementing custom branch operations, we fetch all open Gerrit changes\n * as virtual branches (refs/remotes/origin/<branchName>) after repository initialization.\n * This allows us to leverage DefaultGitScm for most operations, treating virtual branches\n * as regular Git branches, while minimizing Gerrit API requests.\n */\n\nlet repository: string;\nlet projectLabels: GerritLabels = {};\nexport function configureScm(repo: string, labels: GerritLabels = {}): void {\n repository = repo;\n projectLabels = labels;\n}\n\n/**\n * Returns the max vote value for the \"Code-Review\" label (some Gerrit\n * projects only allow up to +1), or `null` if the label isn't defined on\n * the project, so the caller can skip voting instead of failing the push.\n */\nfunction getAutoApproveLabelValue(): number | null {\n const codeReviewLabel = projectLabels[CODE_REVIEW_LABEL];\n if (!codeReviewLabel) {\n logger.warn(\n { repository, label: CODE_REVIEW_LABEL },\n 'Cannot auto-approve: label is not defined on the project',\n );\n return null;\n }\n return mapBranchStatusToLabel('green', codeReviewLabel);\n}\n\nexport async function pushForReview(options: {\n sourceRef: string;\n targetBranch: string;\n files: FileChange[];\n autoApprove?: boolean;\n labels?: string[];\n}): Promise<boolean> {\n const pushOptions = ['notify=NONE', 'ready'];\n if (options.autoApprove) {\n const value = getAutoApproveLabelValue();\n if (value !== null) {\n pushOptions.push(`label=${CODE_REVIEW_LABEL}+${value}`);\n }\n }\n if (isNonEmptyArray(options.labels)) {\n for (const label of options.labels) {\n pushOptions.push(`hashtag=${label}`);\n }\n }\n\n return git.pushCommit({\n sourceRef: options.sourceRef,\n targetRef: `refs/for/${options.targetBranch}`,\n files: options.files,\n pushOptions,\n });\n}\n\nexport class GerritScm extends DefaultGitScm {\n override async commitAndPush(\n commit: CommitFilesConfig,\n ): Promise<LongCommitSha | null> {\n logger.debug(`commitAndPush(${commit.branchName})`);\n\n const existingChange = await client.getBranchChange(repository, {\n branchName: commit.branchName,\n state: 'open',\n targetBranch: commit.baseBranch,\n requestDetails: ['CURRENT_REVISION'],\n });\n\n const message = isString(commit.message)\n ? [commit.message]\n : commit.message;\n\n // In Gerrit, the change subject/title is the first line of the commit message\n // v8 ignore else -- TODO: add test #40625\n if (commit.prTitle) {\n const firstMessageLines = message[0].split('\\n');\n firstMessageLines[0] = commit.prTitle;\n message[0] = firstMessageLines.join('\\n');\n }\n\n const changeId = existingChange?.change_id ?? generateChangeId();\n commit.message = message;\n commit.trailers = [\n ...(commit.trailers ?? []).filter(\n (trailer) =>\n !trailer.startsWith('Renovate-Branch:') &&\n !trailer.startsWith('Change-Id:'),\n ),\n `Renovate-Branch: ${commit.branchName}`,\n `Change-Id: ${changeId}`,\n ];\n // prepareCommit already checks hasDiff('HEAD', 'origin/<branchName>') when\n // force is not set, which works because virtual branches are fetched as\n // refs/remotes/origin/<branchName> during init. This avoids pushing empty\n // patch sets without a separate diff check.\n const commitResult = await git.prepareCommit(commit);\n if (commitResult) {\n const { commitSha } = commitResult;\n if (existingChange) {\n // Since the change already exists, we push to the same target branch to\n // avoid creating a new change if the base branch has changed.\n // updatePr() will later take care of moving the existing change to a\n // different base branch if needed.\n const pushResult = await pushForReview({\n sourceRef: commit.branchName,\n targetBranch: existingChange.branch,\n files: commit.files,\n autoApprove: commit.autoApprove,\n });\n /* v8 ignore else -- should never happen */\n if (pushResult) {\n const currentRef =\n existingChange.revisions![existingChange.current_revision!].ref;\n await git.setVirtualBranch(\n commit.branchName,\n nextPatchSetRef(currentRef),\n commitSha,\n );\n return commitSha;\n }\n } else {\n logger.debug(`Commit prepared, push deferred to createPr()`);\n return commitSha;\n }\n }\n return null; // empty commit, no changes in this Gerrit Change\n }\n}\n\n/**\n * Derive the next patch-set ref from a Gerrit change ref.\n * Gerrit refs follow the pattern `refs/changes/<NN>/<change>/<patchset>`.\n * After a push, Gerrit creates the next patch-set, so we increment the\n * trailing number to keep the virtual branch in sync.\n */\nexport function nextPatchSetRef(currentRef: string): string {\n const lastSlash = currentRef.lastIndexOf('/');\n const patchSet = parseInt(currentRef.slice(lastSlash + 1), 10);\n return `${currentRef.slice(0, lastSlash + 1)}${patchSet + 1}`;\n}\n\n/**\n * This function should generate a Gerrit Change-ID analogous to the commit hook. We avoid the commit hook cause of security concerns.\n * random=$( (whoami ; hostname ; date; cat $1 ; echo $RANDOM) | git hash-object --stdin) prefixed with an 'I'.\n * TODO: Gerrit don't accept longer Change-IDs (sha256), but what happens with this https://git-scm.com/docs/hash-function-transition/ ?\n */\nfunction generateChangeId(): string {\n return `I${hash(randomUUID(), 'sha1')}`;\n}\n"],"mappings":";;;;;;;;;AAYA,MAAM,oBAAoB;;;;;;;;AAU1B,IAAI;AACJ,IAAI,gBAA8B,CAAC;AACnC,SAAgB,aAAa,MAAc,SAAuB,CAAC,GAAS;CAC1E,aAAa;CACb,gBAAgB;AAClB;;;;;;AAOA,SAAS,2BAA0C;CACjD,MAAM,kBAAkB,cAAc;CACtC,IAAI,CAAC,iBAAiB;EACpB,OAAO,KACL;GAAE;GAAY,OAAO;EAAkB,GACvC,0DACF;EACA,OAAO;CACT;CACA,OAAO,uBAAuB,SAAS,eAAe;AACxD;AAEA,eAAsB,cAAc,SAMf;CACnB,MAAM,cAAc,CAAC,eAAe,OAAO;CAC3C,IAAI,QAAQ,aAAa;EACvB,MAAM,QAAQ,yBAAyB;EACvC,IAAI,UAAU,MACZ,YAAY,KAAK,SAAS,kBAAkB,GAAG,OAAO;CAE1D;CACA,IAAI,gBAAgB,QAAQ,MAAM,GAChC,KAAK,MAAM,SAAS,QAAQ,QAC1B,YAAY,KAAK,WAAW,OAAO;CAIvC,OAAOA,WAAe;EACpB,WAAW,QAAQ;EACnB,WAAW,YAAY,QAAQ;EAC/B,OAAO,QAAQ;EACf;CACF,CAAC;AACH;AAEA,IAAa,YAAb,cAA+B,cAAc;CAC3C,MAAe,cACb,QAC+B;EAC/B,OAAO,MAAM,iBAAiB,OAAO,WAAW,EAAE;EAElD,MAAM,iBAAiB,MAAM,OAAO,gBAAgB,YAAY;GAC9D,YAAY,OAAO;GACnB,OAAO;GACP,cAAc,OAAO;GACrB,gBAAgB,CAAC,kBAAkB;EACrC,CAAC;EAED,MAAM,UAAU,SAAS,OAAO,OAAO,IACnC,CAAC,OAAO,OAAO,IACf,OAAO;;EAIX,IAAI,OAAO,SAAS;GAClB,MAAM,oBAAoB,QAAQ,EAAE,CAAC,MAAM,IAAI;GAC/C,kBAAkB,KAAK,OAAO;GAC9B,QAAQ,KAAK,kBAAkB,KAAK,IAAI;EAC1C;EAEA,MAAM,WAAW,gBAAgB,aAAa,iBAAiB;EAC/D,OAAO,UAAU;EACjB,OAAO,WAAW;GAChB,IAAI,OAAO,YAAY,CAAC,EAAA,CAAG,QACxB,YACC,CAAC,QAAQ,WAAW,kBAAkB,KACtC,CAAC,QAAQ,WAAW,YAAY,CACpC;GACA,oBAAoB,OAAO;GAC3B,cAAc;EAChB;EAKA,MAAM,eAAe,MAAMC,cAAkB,MAAM;EACnD,IAAI,cAAc;GAChB,MAAM,EAAE,cAAc;GACtB,IAAI,gBAYE;;QAAA,MAPqB,cAAc;KACrC,WAAW,OAAO;KAClB,cAAc,eAAe;KAC7B,OAAO,OAAO;KACd,aAAa,OAAO;IACtB,CAAC,GAEe;KACd,MAAM,aACJ,eAAe,UAAW,eAAe,iBAAkB,CAAC;KAC9D,MAAMC,iBACJ,OAAO,YACP,gBAAgB,UAAU,GAC1B,SACF;KACA,OAAO;IACT;UACK;IACL,OAAO,MAAM,8CAA8C;IAC3D,OAAO;GACT;EACF;EACA,OAAO;CACT;AACF;;;;;;;AAQA,SAAgB,gBAAgB,YAA4B;CAC1D,MAAM,YAAY,WAAW,YAAY,GAAG;CAC5C,MAAM,WAAW,SAAS,WAAW,MAAM,YAAY,CAAC,GAAG,EAAE;CAC7D,OAAO,GAAG,WAAW,MAAM,GAAG,YAAY,CAAC,IAAI,WAAW;AAC5D;;;;;;AAOA,SAAS,mBAA2B;CAClC,OAAO,IAAI,KAAK,WAAW,GAAG,MAAM;AACtC"}
|
|
@@ -1164,7 +1164,7 @@ async function tryPrAutomerge(prNumber, prNodeId, platformPrOptions) {
|
|
|
1164
1164
|
return;
|
|
1165
1165
|
}
|
|
1166
1166
|
try {
|
|
1167
|
-
const mergeMethod = config.mergeMethod?.toUpperCase() || "MERGE";
|
|
1167
|
+
const mergeMethod = (mapMergeStartegy(platformPrOptions.automergeStrategy) ?? config.mergeMethod)?.toUpperCase() || "MERGE";
|
|
1168
1168
|
let commitHeadline;
|
|
1169
1169
|
let commitBody;
|
|
1170
1170
|
const automergeCommitMessage = platformPrOptions?.automergeCommitMessage;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":["hostRules.find","Issue","git.initRepo","git.getBranchCommit","git.forcePushToRemote","git.prepareCommit","git.resetToCommit","git.fetchBranch"],"sources":["../../../../lib/modules/platform/github/index.ts"],"sourcesContent":["import { setTimeout } from 'node:timers/promises';\nimport { isArray, isNonEmptyObject, isNonEmptyString } from '@sindresorhus/is';\nimport semver from 'semver';\nimport { GlobalConfig } from '../../../config/global.ts';\nimport {\n PLATFORM_INTEGRATION_UNAUTHORIZED,\n PLATFORM_RATE_LIMIT_EXCEEDED,\n PLATFORM_UNKNOWN_ERROR,\n PR_ALREADY_IN_MERGE_QUEUE,\n REPOSITORY_ACCESS_FORBIDDEN,\n REPOSITORY_ARCHIVED,\n REPOSITORY_BLOCKED,\n REPOSITORY_CANNOT_FORK,\n REPOSITORY_CHANGED,\n REPOSITORY_DISABLED,\n REPOSITORY_EMPTY,\n REPOSITORY_FORKED,\n REPOSITORY_FORK_MISSING,\n REPOSITORY_FORK_MODE_FORKED,\n REPOSITORY_NOT_FOUND,\n REPOSITORY_RENAMED,\n} from '../../../constants/error-messages.ts';\nimport { instrument } from '../../../instrumentation/index.ts';\nimport { logger } from '../../../logger/index.ts';\nimport { ExternalHostError } from '../../../types/errors/external-host-error.ts';\nimport type { BranchStatus } from '../../../types/index.ts';\nimport { isGithubFineGrainedPersonalAccessToken } from '../../../util/check-token.ts';\nimport { coerceToNull } from '../../../util/coerce.ts';\nimport { parseJson } from '../../../util/common.ts';\nimport { getEnv } from '../../../util/env.ts';\nimport { formatCommitMessage } from '../../../util/git/commit-trailers.ts';\nimport * as git from '../../../util/git/index.ts';\nimport {\n diffCommitTree,\n getCommitTreeSha,\n pushCommitToRenovateRef,\n} from '../../../util/git/index.ts';\nimport type {\n CommitFilesConfig,\n CommitResult,\n} from '../../../util/git/types.ts';\nimport * as hostRules from '../../../util/host-rules.ts';\nimport { memCacheProvider } from '../../../util/http/cache/memory-http-cache-provider.ts';\nimport { repoCacheProvider } from '../../../util/http/cache/repository-http-cache-provider.ts';\nimport type { GithubHttpOptions } from '../../../util/http/github.ts';\nimport * as githubHttp from '../../../util/http/github.ts';\nimport type { HttpResponse } from '../../../util/http/types.ts';\nimport { coerceObject } from '../../../util/object.ts';\nimport { regEx } from '../../../util/regex.ts';\nimport { sanitize } from '../../../util/sanitize.ts';\nimport type { LongCommitSha } from '../../../util/schema-utils/git.ts';\nimport { toLongCommitSha } from '../../../util/schema-utils/git.ts';\nimport { fromBase64, looseEquals } from '../../../util/string.ts';\nimport { ensureTrailingSlash, isHttpUrl, parseUrl } from '../../../util/url.ts';\nimport { incLimitedValue } from '../../../workers/global/limits.ts';\nimport { normalizePythonDepName } from '../../datasource/pypi/common.ts';\nimport type {\n AutodiscoverConfig,\n BranchStatusConfig,\n CreatePRConfig,\n EnsureCommentConfig,\n EnsureCommentRemovalConfig,\n EnsureIssueConfig,\n EnsureIssueResult,\n FindPRConfig,\n MergePRConfig,\n PlatformParams,\n PlatformPrOptions,\n PlatformResult,\n Pr,\n ReattemptPlatformAutomergeConfig,\n RepoParams,\n RepoResult,\n UpdatePrConfig,\n} from '../types.ts';\nimport { repoFingerprint } from '../util.ts';\nimport { smartTruncate } from '../utils/pr-body.ts';\nimport { remoteBranchExists } from './branch.ts';\nimport { coerceRestPr, githubApi, mapMergeStartegy } from './common.ts';\nimport {\n enableAutoMergeMutation,\n getIssuesQuery,\n repoInfoQuery,\n repoMergeQueueQuery,\n} from './graphql.ts';\nimport { GithubIssueCache } from './issue.ts';\nimport { massageMarkdownLinks } from './massage-markdown-links.ts';\nimport { getPrCache, isPrInMergeQueue, updatePrCache } from './pr.ts';\nimport {\n GithubBranchProtection,\n GithubBranchRulesets,\n GithubVulnerabilityAlerts,\n GithubIssue as Issue,\n} from './schema.ts';\nimport type {\n AggregatedVulnerabilities,\n CombinedBranchStatus,\n Comment,\n GhAutomergeResponse,\n GhBranchStatus,\n GhPr,\n GhRepo,\n GhRestPr,\n GhRestRepo,\n LocalRepoConfig,\n PlatformConfig,\n} from './types.ts';\nimport { getAppDetails, getUserDetails, getUserEmail } from './user.ts';\nimport { getRepoUrl, warnIfDefaultGitAuthorEmail } from './utils.ts';\n\nexport const id = 'github';\n\nlet config: LocalRepoConfig;\nlet platformConfig: PlatformConfig;\n\n// GitHub's max is 60k but in the hosted app we've observed that content-length is ~1k longer\nconst GitHubMaxPrBodyLen = 58000;\n\nexport function resetConfigs(): void {\n config = {} as never;\n platformConfig = {\n hostType: 'github',\n endpoint: 'https://api.github.com/',\n };\n}\n\nresetConfigs();\n\nfunction escapeHash(input: string): string {\n return input?.replace(regEx(/#/g), '%23');\n}\n\nexport function isGHApp(): boolean {\n return !!platformConfig.isGHApp;\n}\n\nexport async function detectGhe(token: string): Promise<void> {\n const parsedEndpoint = parseUrl(platformConfig.endpoint);\n /* v8 ignore next -- endpoint is validated in initPlatform before detectGhe is called */\n if (!parsedEndpoint) {\n throw new Error(`Invalid GitHub endpoint: ${platformConfig.endpoint}`);\n }\n const host = parsedEndpoint.host;\n platformConfig.isGhe = host !== 'api.github.com';\n platformConfig.isGheCloud = host.endsWith('.ghe.com');\n if (platformConfig.isGhe) {\n const gheHeaderKey = 'x-github-enterprise-version';\n const gheQueryRes = await githubApi.headJson('/', { token });\n const gheHeaders = coerceObject(gheQueryRes?.headers);\n const [, gheVersion] =\n Object.entries(gheHeaders).find(\n ([k]) => k.toLowerCase() === gheHeaderKey,\n ) ?? [];\n platformConfig.gheVersion = semver.valid(gheVersion as string) ?? null;\n logger.debug(\n `Detected GitHub Enterprise Server, version: ${platformConfig.gheVersion}`,\n );\n }\n}\n\nexport async function initPlatform({\n endpoint,\n token: originalToken,\n username,\n gitAuthor,\n}: PlatformParams): Promise<PlatformResult> {\n let token = originalToken;\n if (!token) {\n throw new Error('Init: You must configure a GitHub token');\n }\n token = token.replace(regEx(/^ghs_/), 'x-access-token:ghs_');\n platformConfig.isGHApp = token.startsWith('x-access-token:');\n\n if (endpoint) {\n if (!isHttpUrl(endpoint)) {\n throw new Error(`Init: Invalid GitHub endpoint URL: ${endpoint}`);\n }\n platformConfig.endpoint = ensureTrailingSlash(endpoint);\n githubHttp.setBaseUrl(platformConfig.endpoint);\n } else {\n logger.debug(`Using default github endpoint: ${platformConfig.endpoint}`);\n }\n\n await detectGhe(token);\n /**\n * GHE requires version >=3.10 to support fine-grained access tokens\n * https://docs.github.com/en/enterprise-server@3.10/admin/release-notes#authentication\n */\n if (\n isGithubFineGrainedPersonalAccessToken(token) &&\n platformConfig.isGhe &&\n (!platformConfig.gheVersion ||\n semver.lt(platformConfig.gheVersion, '3.10.0'))\n ) {\n throw new Error(\n 'Init: Fine-grained Personal Access Tokens do not support GitHub Enterprise Server API version <3.10 and cannot be used with Renovate.',\n );\n }\n\n let renovateUsername: string;\n if (username) {\n renovateUsername = username;\n } else if (platformConfig.isGHApp) {\n platformConfig.userDetails ??= await getAppDetails(token);\n renovateUsername = platformConfig.userDetails.username;\n } else {\n platformConfig.userDetails ??= await getUserDetails(\n platformConfig.endpoint,\n token,\n );\n renovateUsername = platformConfig.userDetails.username;\n }\n\n let ghHostname: string;\n /* v8 ignore next -- false negative due to V8/source-map artifact */\n if (platformConfig.isGheCloud) {\n ghHostname = 'ghe.com';\n } else if (platformConfig.isGhe) {\n // valid url ensured at the function start\n const parsedEndpoint = parseUrl(platformConfig.endpoint)!;\n ghHostname = parsedEndpoint.hostname;\n } else {\n ghHostname = 'github.com';\n }\n\n let discoveredGitAuthor: string | undefined;\n if (!gitAuthor) {\n if (platformConfig.isGHApp) {\n platformConfig.userDetails ??= await getAppDetails(token);\n discoveredGitAuthor = `${platformConfig.userDetails.name} <${platformConfig.userDetails.id}+${platformConfig.userDetails.username}@users.noreply.${ghHostname}>`;\n } else {\n platformConfig.userDetails ??= await getUserDetails(\n platformConfig.endpoint,\n token,\n );\n // v8 ignore next -- TODO: coverage error #40625\n platformConfig.userEmail =\n platformConfig.userDetails.email ??\n (await getUserEmail(platformConfig.endpoint, token));\n if (platformConfig.userEmail) {\n discoveredGitAuthor = `${platformConfig.userDetails.name} <${platformConfig.userEmail}>`;\n }\n }\n }\n\n git.setPlatformIgnoredAuthors([`noreply@${ghHostname}`]);\n\n logger.debug({ platformConfig, renovateUsername }, 'Platform config');\n const platformResult: PlatformResult = {\n endpoint: platformConfig.endpoint,\n gitAuthor: gitAuthor ?? discoveredGitAuthor,\n renovateUsername,\n token,\n };\n\n warnIfDefaultGitAuthorEmail(platformResult.gitAuthor, platformConfig.isGhe);\n\n if (\n getEnv().RENOVATE_X_GITHUB_HOST_RULES &&\n platformResult.endpoint === 'https://api.github.com/'\n ) {\n logger.debug('Adding GitHub token as GHCR password');\n platformResult.hostRules = [\n {\n matchHost: 'ghcr.io',\n hostType: 'docker',\n username: 'USERNAME',\n password: token.replace(regEx(/^x-access-token:/), ''),\n },\n ];\n logger.debug('Adding GitHub token as npm.pkg.github.com Basic token');\n platformResult.hostRules.push({\n matchHost: 'npm.pkg.github.com',\n hostType: 'npm',\n token: token.replace(regEx(/^x-access-token:/), ''),\n });\n const usernamePasswordHostTypes = ['rubygems', 'maven', 'nuget'];\n for (const hostType of usernamePasswordHostTypes) {\n logger.debug(\n `Adding GitHub token as ${hostType}.pkg.github.com password`,\n );\n platformResult.hostRules.push({\n hostType,\n matchHost: `${hostType}.pkg.github.com`,\n username: renovateUsername,\n password: token.replace(regEx(/^x-access-token:/), ''),\n });\n }\n }\n return platformResult;\n}\n\nasync function fetchRepositories(): Promise<GhRestRepo[]> {\n try {\n if (isGHApp()) {\n const res = await githubApi.getJsonUnchecked<{\n repositories: GhRestRepo[];\n }>(`installation/repositories?per_page=100`, {\n paginationField: 'repositories',\n paginate: 'all',\n });\n return res.body.repositories;\n }\n const res = await githubApi.getJsonUnchecked<GhRestRepo[]>(\n `user/repos?per_page=100`,\n { paginate: 'all' },\n );\n return res.body;\n } catch (err) /* v8 ignore next -- defensive: repo listing failures are logged and rethrown, not simulated in specs */ {\n logger.error({ err }, `GitHub getRepos error`);\n throw err;\n }\n}\n\n// Get all repositories that the user has access to\nexport async function getRepos(config?: AutodiscoverConfig): Promise<string[]> {\n logger.debug('Autodiscovering GitHub repositories');\n const nonEmptyRepositories = (await fetchRepositories()).filter(\n isNonEmptyObject,\n );\n const nonArchivedRepositories = nonEmptyRepositories.filter(\n (repo) => !repo.archived,\n );\n if (nonArchivedRepositories.length < nonEmptyRepositories.length) {\n logger.debug(\n `Filtered out ${\n nonEmptyRepositories.length - nonArchivedRepositories.length\n } archived repositories`,\n );\n }\n if (!config?.topics) {\n return nonArchivedRepositories.map((repo) => repo.full_name);\n }\n\n logger.debug({ topics: config.topics }, 'Filtering by topics');\n const topicRepositories = nonArchivedRepositories.filter((repo) =>\n repo.topics?.some((topic) => config?.topics?.includes(topic)),\n );\n\n // v8 ignore else -- TODO: add test #40625\n if (topicRepositories.length < nonArchivedRepositories.length) {\n logger.debug(\n `Filtered out ${\n nonArchivedRepositories.length - topicRepositories.length\n } repositories not matching topic filters`,\n );\n }\n return topicRepositories.map((repo) => repo.full_name);\n}\n\nasync function getBranchProtection(\n branchName: string,\n): Promise<GithubBranchProtection> {\n if (config.parentRepo) {\n return {};\n }\n\n const res = await githubApi.getJson(\n `repos/${config.repository}/branches/${escapeHash(branchName)}/protection`,\n { cacheProvider: repoCacheProvider },\n GithubBranchProtection,\n );\n return res.body;\n}\n\nasync function getBranchRulesets(\n branchName: string,\n): Promise<GithubBranchRulesets> {\n if (config.parentRepo) {\n return [];\n }\n\n try {\n const res = await githubApi.getJson(\n `repos/${config.repository}/rules/branches/${escapeHash(branchName)}`,\n { cacheProvider: repoCacheProvider },\n GithubBranchRulesets,\n );\n return res.body;\n } catch (err) {\n if (err.statusCode === 404) {\n logger.debug(`No branch rulesets found for ${branchName}`);\n return [];\n }\n throw err;\n }\n}\n\nexport async function getRawFile(\n fileName: string,\n repoName?: string,\n branchOrTag?: string,\n): Promise<string | null> {\n const repo = repoName ?? config.repository;\n\n // only use cache for the same org\n const httpOptions: GithubHttpOptions = {};\n const isSameOrg = repo?.split('/')?.[0] === config.repositoryOwner;\n // v8 ignore else -- TODO: add test #40625\n if (isSameOrg) {\n httpOptions.cacheProvider = repoCacheProvider;\n }\n\n let url = `repos/${repo}/contents/${fileName}`;\n if (branchOrTag) {\n url += `?ref=${branchOrTag}`;\n }\n const res = await githubApi.getJsonUnchecked<{ content: string }>(\n url,\n httpOptions,\n );\n const buf = res.body.content;\n const str = fromBase64(buf);\n return str;\n}\n\nexport async function getJsonFile(\n fileName: string,\n repoName?: string,\n branchOrTag?: string,\n): Promise<any> {\n const raw = await getRawFile(fileName, repoName, branchOrTag);\n return parseJson(raw, fileName);\n}\n\nexport async function listForks(\n token: string,\n repository: string,\n): Promise<GhRestRepo[]> {\n try {\n // Get list of existing repos\n const url = `repos/${repository}/forks?per_page=100`;\n const repos = (\n await githubApi.getJsonUnchecked<GhRestRepo[]>(url, {\n token,\n paginate: true,\n pageLimit: 100,\n })\n ).body;\n logger.debug(`Found ${repos.length} forked repo(s)`);\n return repos;\n } catch (err) {\n if (err.statusCode === 404) {\n logger.debug('Cannot list repo forks - it is likely private');\n } else {\n logger.debug({ err }, 'Unknown error listing repository forks');\n }\n throw new Error(REPOSITORY_CANNOT_FORK);\n }\n}\n\nexport async function findFork(\n token: string,\n repository: string,\n forkOrg?: string,\n): Promise<GhRestRepo | null> {\n const forks = await listForks(token, repository);\n if (forkOrg) {\n logger.debug(`Searching for forked repo in forkOrg (${forkOrg})`);\n const forkedRepo = forks.find((repo) => repo.owner.login === forkOrg);\n if (forkedRepo) {\n logger.debug(`Found repo in forkOrg: ${forkedRepo.full_name}`);\n return forkedRepo;\n }\n logger.debug(`No repo found in forkOrg`);\n }\n logger.debug(`Searching for forked repo in user account`);\n try {\n const { username } = await getUserDetails(platformConfig.endpoint, token);\n const forkedRepo = forks.find((repo) => repo.owner.login === username);\n if (forkedRepo) {\n logger.debug(`Found repo in user account: ${forkedRepo.full_name}`);\n return forkedRepo;\n }\n } catch {\n throw new Error(REPOSITORY_CANNOT_FORK);\n }\n logger.debug(`No repo found in user account`);\n return null;\n}\n\nexport async function createFork(\n token: string,\n repository: string,\n forkOrg?: string,\n): Promise<GhRestRepo> {\n let forkedRepo: GhRestRepo | undefined;\n try {\n forkedRepo = (\n await githubApi.postJson<GhRestRepo>(`repos/${repository}/forks`, {\n token,\n body: {\n organization: forkOrg ?? undefined,\n name: config.parentRepo!.replace('/', '-_-'),\n default_branch_only: true, // no baseBranchPatterns support yet\n },\n })\n ).body;\n } catch (err) {\n logger.debug({ err }, 'Error creating fork');\n }\n if (!forkedRepo) {\n throw new Error(REPOSITORY_CANNOT_FORK);\n }\n logger.info({ forkedRepo: forkedRepo.full_name }, 'Created forked repo');\n logger.debug(`Sleeping 30s after creating fork`);\n await setTimeout(30000);\n return forkedRepo;\n}\n\n// Initialize GitHub by getting base branch and SHA\nexport async function initRepo({\n repository,\n forkCreation,\n forkOrg,\n forkToken,\n gitUrl,\n renovateUsername,\n cloneSubmodules,\n cloneSubmodulesFilter,\n}: RepoParams): Promise<RepoResult> {\n logger.debug(`initRepo(\"${repository}\")`);\n // config is used by the platform api itself, not necessary for the app layer to know\n config = {\n repository,\n cloneSubmodules,\n cloneSubmodulesFilter,\n ignorePrAuthor: GlobalConfig.get('ignorePrAuthor'),\n mergeQueueEnabled: {},\n } as any;\n const opts = hostRules.find({\n hostType: 'github',\n url: platformConfig.endpoint,\n readOnly: true,\n });\n config.renovateUsername = renovateUsername;\n [config.repositoryOwner, config.repositoryName] = repository.split('/');\n let repo: GhRepo | undefined;\n let forkSshUrl: string | null = null;\n try {\n let infoQuery = repoInfoQuery;\n\n // GitHub Enterprise Server <3.3.0 doesn't support autoMergeAllowed and hasIssuesEnabled objects\n // TODO #22198\n if (\n platformConfig.isGhe &&\n // semver not null safe, accepts null and undefined\n semver.satisfies(platformConfig.gheVersion!, '<3.3.0')\n ) {\n infoQuery = infoQuery.replace(regEx(/\\n\\s*autoMergeAllowed\\s*\\n/), '\\n');\n infoQuery = infoQuery.replace(regEx(/\\n\\s*hasIssuesEnabled\\s*\\n/), '\\n');\n }\n\n // GitHub Enterprise Server <3.9.0 doesn't support hasVulnerabilityAlertsEnabled objects\n if (\n platformConfig.isGhe &&\n // semver not null safe, accepts null and undefined\n semver.satisfies(platformConfig.gheVersion!, '<3.9.0')\n ) {\n infoQuery = infoQuery.replace(\n regEx(/\\n\\s*hasVulnerabilityAlertsEnabled\\s*\\n/),\n '\\n',\n );\n }\n\n // GitHub Enterprise Server <3.12.0 doesn't support merge queues\n if (\n platformConfig.isGhe &&\n // semver not null safe, accepts null and undefined\n semver.satisfies(platformConfig.gheVersion!, '<3.12.0')\n ) {\n infoQuery = infoQuery.replace(\n regEx(/\\n\\s*mergeQueue\\s*\\{\\s*id\\s*\\}\\s*\\n/),\n '\\n',\n );\n }\n\n const res = await githubApi.requestGraphql<{\n repository: GhRepo;\n }>(infoQuery, {\n variables: {\n owner: config.repositoryOwner,\n name: config.repositoryName,\n ...(!config.ignorePrAuthor && { user: renovateUsername }),\n },\n readOnly: true,\n count: 1, // bypass graphql check\n });\n\n if (res?.errors) {\n if (res.errors.find((err) => err.type === 'RATE_LIMITED')) {\n logger.debug({ res }, 'GraphQL rate limit exceeded.');\n throw new Error(PLATFORM_RATE_LIMIT_EXCEEDED);\n }\n logger.debug({ res }, 'Unexpected GraphQL errors');\n throw new Error(PLATFORM_UNKNOWN_ERROR);\n }\n\n repo = res?.data?.repository;\n /* v8 ignore next -- defensive: GraphQL errors are handled above, a null repository is not mocked in specs */\n if (!repo) {\n logger.debug({ res }, 'No repository returned');\n throw new Error(REPOSITORY_NOT_FOUND);\n }\n /* v8 ignore next -- empty-repo detection via missing defaultBranchRef is not mocked in specs */\n if (!repo.defaultBranchRef?.name) {\n logger.debug(\n { res },\n 'No default branch returned - treating repo as empty',\n );\n throw new Error(REPOSITORY_EMPTY);\n }\n if (\n repo.nameWithOwner &&\n repo.nameWithOwner.toUpperCase() !== repository.toUpperCase()\n ) {\n logger.debug(\n { desiredRepo: repository, foundRepo: repo.nameWithOwner },\n 'Repository has been renamed',\n );\n throw new Error(REPOSITORY_RENAMED);\n }\n if (repo.isArchived) {\n logger.debug(\n 'Repository is archived - throwing error to abort renovation',\n );\n throw new Error(REPOSITORY_ARCHIVED);\n }\n // Use default branch as PR target unless later overridden.\n config.defaultBranch = repo.defaultBranchRef.name;\n // Base branch may be configured but defaultBranch is always fixed\n logger.debug(`${repository} default branch = ${config.defaultBranch}`);\n // GitHub allows administrators to block certain types of merge, so we need to check it\n if (repo.squashMergeAllowed) {\n config.mergeMethod = 'squash';\n } else if (repo.mergeCommitAllowed) {\n config.mergeMethod = 'merge';\n } else if (repo.rebaseMergeAllowed) {\n config.mergeMethod = 'rebase';\n } else {\n // This happens if we don't have Administrator read access, it is not a critical error\n logger.debug('Could not find allowed merge methods for repo');\n }\n config.autoMergeAllowed = repo.autoMergeAllowed;\n config.hasIssuesEnabled = repo.hasIssuesEnabled;\n config.hasVulnerabilityAlertsEnabled = repo.hasVulnerabilityAlertsEnabled;\n config.mergeQueueEnabled[config.defaultBranch] = isNonEmptyObject(\n repo.mergeQueue,\n );\n\n const recentIssues = Issue.array()\n .catch([])\n .parse(res?.data?.repository?.issues?.nodes);\n GithubIssueCache.addIssuesToReconcile(recentIssues);\n } catch (err) /* v8 ignore next -- initRepo error mapping needs failure shapes not mocked in specs */ {\n logger.debug({ err }, 'Caught initRepo error');\n if (\n err.message === REPOSITORY_ARCHIVED ||\n err.message === REPOSITORY_RENAMED ||\n err.message === REPOSITORY_NOT_FOUND\n ) {\n throw err;\n }\n if (err.statusCode === 403) {\n throw new Error(REPOSITORY_ACCESS_FORBIDDEN);\n }\n if (err.statusCode === 404) {\n throw new Error(REPOSITORY_NOT_FOUND);\n }\n if (err.message.startsWith('Repository access blocked')) {\n throw new Error(REPOSITORY_BLOCKED);\n }\n if (err.message === REPOSITORY_FORK_MODE_FORKED) {\n throw err;\n }\n if (err.message === REPOSITORY_FORKED) {\n throw err;\n }\n if (err.message === REPOSITORY_DISABLED) {\n throw err;\n }\n if (err.message === 'Response code 451 (Unavailable for Legal Reasons)') {\n throw new Error(REPOSITORY_ACCESS_FORBIDDEN);\n }\n logger.debug({ err }, 'Unknown GitHub initRepo error');\n throw err;\n }\n // This shouldn't be necessary, but occasional strange errors happened until it was added\n config.prList = null;\n\n if (forkToken) {\n logger.debug('Bot is in fork mode');\n if (repo.isFork) {\n logger.debug(\n `Forked repos cannot be processed when running with a forkToken, so this repo will be skipped`,\n );\n logger.debug(\n `Parent repo for this forked repo is ${repo.parent?.nameWithOwner}`,\n );\n throw new Error(REPOSITORY_FORKED);\n }\n config.forkOrg = forkOrg;\n config.forkToken = forkToken;\n // save parent name then delete\n config.parentRepo = config.repository;\n config.repository = null;\n let forkedRepo = await findFork(forkToken, repository, forkOrg);\n if (forkedRepo) {\n config.repository = forkedRepo.full_name;\n forkSshUrl = forkedRepo.ssh_url;\n const forkDefaultBranch = forkedRepo.default_branch;\n if (forkDefaultBranch !== config.defaultBranch) {\n const body = {\n ref: `refs/heads/${config.defaultBranch}`,\n sha: repo.defaultBranchRef.target.oid,\n };\n logger.debug(\n {\n defaultBranch: config.defaultBranch,\n forkDefaultBranch,\n body,\n },\n 'Fork has different default branch to parent, attempting to create branch',\n );\n try {\n await githubApi.postJson(`repos/${config.repository}/git/refs`, {\n body,\n token: forkToken,\n });\n logger.debug('Created new default branch in fork');\n } catch (err) /* v8 ignore next -- fork default-branch creation failures are not mocked in specs */ {\n if (err.response?.body?.message === 'Reference already exists') {\n logger.debug(\n `Branch ${config.defaultBranch} already exists in the fork`,\n );\n } else {\n logger.warn(\n { err, body: err.response?.body },\n 'Could not create parent defaultBranch in fork',\n );\n }\n }\n logger.debug(\n `Setting ${config.defaultBranch} as default branch for ${config.repository}`,\n );\n try {\n await githubApi.patchJson(`repos/${config.repository}`, {\n body: {\n name: config.repository.split('/')[1],\n default_branch: config.defaultBranch,\n },\n token: forkToken,\n });\n logger.debug('Successfully changed default branch for fork');\n } catch (err) /* v8 ignore next -- defensive: fork default-branch update failures are logged and swallowed, not simulated in specs */ {\n logger.warn({ err }, 'Could not set default branch');\n }\n }\n } else if (forkCreation) {\n logger.debug('Forked repo is not found - attempting to create it');\n forkedRepo = await createFork(forkToken, repository, forkOrg);\n config.repository = forkedRepo.full_name;\n forkSshUrl = forkedRepo.ssh_url;\n } else {\n logger.debug('Forked repo is not found and forkCreation is disabled');\n throw new Error(REPOSITORY_FORK_MISSING);\n }\n }\n\n let authToken: string | null;\n if (forkToken) {\n logger.debug('Using forkToken for git init');\n authToken = coerceToNull(config.forkToken);\n } /* v8 ignore next -- token-type detection depends on opts.token shapes not varied in specs */ else {\n const tokenType = opts.token?.startsWith('x-access-token:')\n ? 'app'\n : 'personal access';\n logger.debug(`Using ${tokenType} token for git init`);\n authToken = opts.token ?? null;\n }\n // endpoint is validated during initPlatform\n const parsedEndpoint = parseUrl(platformConfig.endpoint)!;\n const workingSshUrl = forkToken ? forkSshUrl : repo.sshUrl;\n const url = getRepoUrl(\n config.repository!,\n gitUrl,\n workingSshUrl,\n parsedEndpoint,\n authToken,\n );\n let upstreamUrl: string | undefined;\n if (forkCreation && config.parentRepo) {\n upstreamUrl = getRepoUrl(\n config.parentRepo,\n gitUrl,\n repo.sshUrl,\n parsedEndpoint,\n authToken,\n );\n }\n await git.initRepo({\n ...config,\n url,\n upstreamUrl,\n });\n const repoConfig: RepoResult = {\n defaultBranch: config.defaultBranch,\n isFork: repo.isFork === true,\n repoFingerprint: repoFingerprint(repo.id, platformConfig.endpoint),\n };\n return repoConfig;\n}\n\nasync function checkRulesetsForForceRebase(\n branchName: string,\n): Promise<boolean> {\n try {\n const rulesets = await getBranchRulesets(branchName);\n logger.trace(\n `Ruleset: Found ${rulesets.length} rulesets for branch ${branchName}`,\n );\n\n return rulesets.some((rule) => {\n if (\n rule.type === 'required_status_checks' &&\n rule.parameters?.strict_required_status_checks_policy === true\n ) {\n logger.debug(\n `Ruleset: strict required status checks found for ${branchName}`,\n );\n return true;\n }\n\n return false;\n });\n } catch (err) {\n handleBranchProtectionError('rulesets', err, branchName);\n return false;\n }\n}\n\nasync function checkBranchProtectionForForceRebase(\n branchName: string,\n): Promise<boolean> {\n try {\n const branchProtection = await getBranchProtection(branchName);\n logger.trace(`Found branch protection for branch ${branchName}`);\n\n const strictStatusChecks = branchProtection?.required_status_checks?.strict;\n if (strictStatusChecks) {\n logger.debug(\n `Branch protection: PRs must be up-to-date before merging for ${branchName}`,\n );\n return true;\n }\n return false;\n } catch (err) {\n handleBranchProtectionError('branch-protection', err, branchName);\n return false;\n }\n}\n\nexport async function getBranchForceRebase(\n branchName: string,\n): Promise<boolean> {\n config.branchForceRebase ??= {};\n\n const cachedResult = config.branchForceRebase[branchName];\n if (cachedResult !== undefined) {\n return cachedResult;\n }\n\n // Initialize to false before checking branch protection\n config.branchForceRebase[branchName] = false;\n\n // Check rulesets first (newer API)\n const hasRulesetForceRebase = await checkRulesetsForForceRebase(branchName);\n if (hasRulesetForceRebase) {\n config.branchForceRebase[branchName] = true;\n return true;\n }\n\n // Fall back to legacy branch protection\n const hasBranchProtectionForceRebase =\n await checkBranchProtectionForForceRebase(branchName);\n if (hasBranchProtectionForceRebase) {\n config.branchForceRebase[branchName] = true;\n }\n\n return config.branchForceRebase[branchName];\n}\n\nfunction handleBranchProtectionError(\n protection: 'branch-protection' | 'rulesets',\n err: any,\n branchName: string,\n): void {\n if (err.statusCode === 404) {\n logger.debug(`No ${protection} found for ${branchName}`);\n return;\n }\n\n const isUnauthorized =\n err.message === PLATFORM_INTEGRATION_UNAUTHORIZED || err.statusCode === 403;\n\n if (isUnauthorized) {\n logger.once.debug(\n `Branch protection: Do not have permissions to detect ${protection} for ${branchName}`,\n );\n return;\n }\n\n throw err;\n}\n\nfunction cachePr(pr?: GhPr | null): void {\n config.prList ??= [];\n // v8 ignore else -- TODO: add test #40625\n if (pr) {\n updatePrCache(pr);\n for (let idx = 0; idx < config.prList.length; idx += 1) {\n const cachedPr = config.prList[idx];\n if (cachedPr.number === pr.number) {\n config.prList[idx] = pr;\n return;\n }\n }\n config.prList.push(pr);\n }\n}\n\n// Fetch fresh Pull Request and cache it when possible\nasync function fetchPr(prNo: number): Promise<GhPr | null> {\n try {\n const { body: ghRestPr } = await githubApi.getJsonUnchecked<GhRestPr>(\n `repos/${config.parentRepo ?? config.repository}/pulls/${prNo}`,\n );\n const result = coerceRestPr(ghRestPr);\n cachePr(result);\n return result;\n } catch (err) {\n logger.warn({ err, prNo }, `GitHub fetchPr error`);\n return null;\n }\n}\n\n// Gets details for a PR\nexport async function getPr(prNo: number): Promise<GhPr | null> {\n if (!prNo) {\n return null;\n }\n const prList = await getPrList();\n let pr = prList.find(({ number }) => number === prNo) ?? null;\n if (pr) {\n logger.debug('Returning PR from cache');\n }\n pr ??= await fetchPr(prNo);\n return pr;\n}\n\nfunction matchesState(state: string, desiredState: string): boolean {\n if (desiredState === 'all') {\n return true;\n }\n if (desiredState.startsWith('!')) {\n return state !== desiredState.substring(1);\n }\n return state === desiredState;\n}\n\nexport async function getPrList(): Promise<GhPr[]> {\n if (!config.prList) {\n const repo = config.parentRepo ?? config.repository;\n\n let username = config.renovateUsername;\n if (config.forkToken || config.ignorePrAuthor) {\n username = undefined;\n }\n\n // TODO: check null `repo` (#22198)\n const prCache = await instrument('getPrCache', () =>\n getPrCache(githubApi, repo!, username),\n );\n config.prList = Object.values(prCache).sort(\n ({ number: a }, { number: b }) => b - a,\n );\n }\n\n return config.prList;\n}\n\nexport async function findPr({\n branchName,\n prTitle,\n state = 'all',\n includeOtherAuthors,\n}: FindPRConfig): Promise<GhPr | null> {\n logger.debug(`findPr(${branchName}, ${prTitle}, ${state})`);\n\n if (includeOtherAuthors) {\n const repo = config.parentRepo ?? config.repository;\n const org = repo?.split('/')[0];\n // PR might have been created by anyone, so don't use the cached Renovate PR list\n const { body: prList } = await githubApi.getJsonUnchecked<GhRestPr[]>(\n `repos/${repo}/pulls?head=${org}:${branchName}&state=open`,\n { cacheProvider: repoCacheProvider },\n );\n\n if (!prList.length) {\n logger.debug(`No PR found for branch ${branchName}`);\n return null;\n }\n\n return coerceRestPr(prList[0]);\n }\n\n const prList = await getPrList();\n const pr = prList.find((p) => {\n if (p.sourceBranch !== branchName) {\n return false;\n }\n\n if (prTitle && prTitle.toUpperCase() !== p.title.toUpperCase()) {\n return false;\n }\n\n if (!matchesState(p.state, state)) {\n return false;\n }\n\n if (!config.forkToken && !looseEquals(config.repository, p.sourceRepo)) {\n return false;\n }\n\n return true;\n });\n if (pr) {\n logger.debug(`Found PR #${pr.number}`);\n }\n return pr ?? null;\n}\n\nasync function ensureBranchSha(\n branchName: string,\n sha: LongCommitSha,\n): Promise<void> {\n const repository = config.repository!;\n try {\n const commitUrl = `/repos/${repository}/git/commits/${sha}`;\n await githubApi.head(commitUrl, { memCache: false });\n } catch (err) {\n logger.error({ err, sha, branchName }, 'Commit not found');\n throw err;\n }\n\n const refUrl = `/repos/${config.repository}/git/refs/heads/${branchName}`;\n const branchExists = await remoteBranchExists(repository, branchName);\n\n if (branchExists) {\n try {\n await githubApi.patchJson(refUrl, { body: { sha, force: true } });\n return;\n } catch (err) {\n if (err.err?.response?.statusCode === 422) {\n logger.debug(\n { err },\n 'Branch update failed due to reference not existing - will try to create',\n );\n } else {\n logger.warn({ refUrl, err }, 'Error updating branch');\n throw err;\n }\n }\n }\n\n await githubApi.postJson(`/repos/${repository}/git/refs`, {\n body: { sha, ref: `refs/heads/${branchName}` },\n });\n}\n\n// Returns the Pull Request for a branch. Null if not exists.\nexport async function getBranchPr(branchName: string): Promise<GhPr | null> {\n logger.debug(`getBranchPr(${branchName})`);\n\n const openPr = await findPr({\n branchName,\n state: 'open',\n });\n\n if (openPr) {\n return openPr;\n }\n\n return null;\n}\n\nexport async function tryReuseAutoclosedPr(\n autoclosedPr: Pr,\n newTitle: string,\n): Promise<Pr | null> {\n const { sha, number, sourceBranch: branchName } = autoclosedPr;\n try {\n await ensureBranchSha(branchName, sha!);\n logger.debug(`Recreated autoclosed branch ${branchName} with sha ${sha}`);\n } catch (err) {\n logger.debug(\n { err, branchName, sha, autoclosedPr },\n 'Could not recreate autoclosed branch - skipping reopen',\n );\n return null;\n }\n\n try {\n const { body: ghPr } = await githubApi.patchJson<GhRestPr>(\n `repos/${config.repository}/pulls/${number}`,\n {\n body: {\n state: 'open',\n title: newTitle,\n },\n },\n );\n logger.info(\n { branchName, oldTitle: autoclosedPr.title, newTitle, number },\n 'Successfully reopened autoclosed PR',\n );\n\n const result = coerceRestPr(ghPr);\n\n const localSha = git.getBranchCommit(branchName);\n // v8 ignore else -- TODO: add test #40625\n if (localSha && localSha !== sha) {\n await git.forcePushToRemote(branchName, 'origin');\n result.sha = localSha;\n }\n\n cachePr(result);\n return result;\n } catch {\n logger.debug('Could not reopen autoclosed PR');\n return null;\n }\n}\n\nasync function getStatus(\n branchName: string,\n useCache = true,\n): Promise<CombinedBranchStatus> {\n const branch = escapeHash(branchName);\n const url = `repos/${config.repository}/commits/${branch}/status`;\n\n const { body: status } =\n await githubApi.getJsonUnchecked<CombinedBranchStatus>(url, {\n memCache: useCache,\n cacheProvider: repoCacheProvider,\n });\n\n return status;\n}\n\n// Returns the combined status for a branch.\nexport async function getBranchStatus(\n branchName: string,\n internalChecksAsSuccess: boolean,\n): Promise<BranchStatus> {\n logger.debug(`getBranchStatus(${branchName})`);\n let commitStatus: CombinedBranchStatus;\n try {\n commitStatus = await getStatus(branchName);\n } catch (err) /* v8 ignore next -- 404-to-REPOSITORY_CHANGED mapping for deleted branches is not mocked in specs */ {\n if (err.statusCode === 404) {\n logger.debug(\n 'Received 404 when checking branch status, assuming that branch has been deleted',\n );\n throw new Error(REPOSITORY_CHANGED);\n }\n logger.debug('Unknown error when checking branch status');\n throw err;\n }\n logger.debug(\n { state: commitStatus.state, statuses: commitStatus.statuses },\n 'branch status check result',\n );\n if (commitStatus.statuses && !internalChecksAsSuccess) {\n commitStatus.statuses = commitStatus.statuses.filter(\n (status) =>\n status.state !== 'success' || !status.context?.startsWith('renovate/'),\n );\n // v8 ignore else -- TODO: add test #40625\n if (!commitStatus.statuses.length) {\n logger.debug(\n 'Successful checks are all internal renovate/ checks, so returning \"pending\" branch status',\n );\n commitStatus.state = 'pending';\n }\n }\n let checkRuns: { name: string; status: string; conclusion: string }[] = [];\n // API is supported in oldest available GHE version 2.19\n try {\n const checkRunsUrl = `repos/${config.repository}/commits/${escapeHash(\n branchName,\n )}/check-runs?per_page=100`;\n const opts = {\n headers: {\n accept: 'application/vnd.github.antiope-preview+json',\n },\n paginate: true,\n paginationField: 'check_runs',\n cacheProvider: memCacheProvider,\n };\n const checkRunsRaw = (\n await githubApi.getJsonUnchecked<{\n check_runs: { name: string; status: string; conclusion: string }[];\n }>(checkRunsUrl, opts)\n ).body;\n if (checkRunsRaw.check_runs?.length) {\n checkRuns = checkRunsRaw.check_runs.map((run) => ({\n name: run.name,\n status: run.status,\n conclusion: run.conclusion,\n }));\n logger.debug({ checkRuns }, 'check runs result');\n } /* v8 ignore next -- specs always mock a non-empty check_runs response */ else {\n logger.debug({ result: checkRunsRaw }, 'No check runs found');\n }\n } catch (err) /* v8 ignore next -- check-run permission errors (403) are mapped to empty results, not mocked in specs */ {\n if (err instanceof ExternalHostError) {\n throw err;\n }\n if (\n err.statusCode === 403 ||\n err.message === PLATFORM_INTEGRATION_UNAUTHORIZED\n ) {\n logger.debug('No permission to view check runs');\n } else {\n logger.warn({ err }, 'Error retrieving check runs');\n }\n }\n if (checkRuns.length === 0) {\n if (commitStatus.state === 'success') {\n return 'green';\n }\n if (commitStatus.state === 'failure') {\n return 'red';\n }\n return 'yellow';\n }\n if (\n commitStatus.state === 'failure' ||\n checkRuns.some((run) => run.conclusion === 'failure')\n ) {\n return 'red';\n }\n if (\n (commitStatus.state === 'success' || commitStatus.statuses.length === 0) &&\n checkRuns.every((run) =>\n ['skipped', 'neutral', 'success'].includes(run.conclusion),\n )\n ) {\n return 'green';\n }\n return 'yellow';\n}\n\nasync function getStatusCheck(\n branchName: string,\n useCache = true,\n): Promise<GhBranchStatus[]> {\n const branchCommit = git.getBranchCommit(branchName);\n\n const url = `repos/${config.repository}/commits/${branchCommit}/statuses`;\n\n const opts: GithubHttpOptions = useCache\n ? { cacheProvider: memCacheProvider }\n : { memCache: false };\n\n return (await githubApi.getJsonUnchecked<GhBranchStatus[]>(url, opts)).body;\n}\n\ntype GithubToRenovateStatusMapping = Record<string, BranchStatus>;\nconst githubToRenovateStatusMapping: GithubToRenovateStatusMapping = {\n success: 'green',\n error: 'red',\n failure: 'red',\n pending: 'yellow',\n};\n\nexport async function getBranchStatusCheck(\n branchName: string,\n context: string,\n): Promise<BranchStatus | null> {\n try {\n const res = await getStatusCheck(branchName);\n for (const check of res) {\n if (check.context === context) {\n return githubToRenovateStatusMapping[check.state] || 'yellow';\n }\n }\n return null;\n } catch (err) /* v8 ignore next -- 404-to-REPOSITORY_CHANGED mapping for missing commits is not mocked in specs */ {\n if (err.statusCode === 404) {\n logger.debug('Commit not found when checking statuses');\n throw new Error(REPOSITORY_CHANGED);\n }\n throw err;\n }\n}\n\nexport async function setBranchStatus({\n branchName,\n context,\n description,\n state,\n url: targetUrl,\n}: BranchStatusConfig): Promise<void> {\n /* v8 ignore next -- specs do not run setBranchStatus in forking mode */\n if (config.parentRepo) {\n logger.debug('Cannot set branch status when in forking mode');\n return;\n }\n const existingStatus = await getBranchStatusCheck(branchName, context);\n if (existingStatus === state) {\n return;\n }\n logger.debug({ branch: branchName, context, state }, 'Setting branch status');\n let url: string | undefined;\n try {\n const branchCommit = git.getBranchCommit(branchName);\n url = `repos/${config.repository}/statuses/${branchCommit}`;\n const renovateToGitHubStateMapping = {\n green: 'success',\n yellow: 'pending',\n red: 'failure',\n };\n const options: any = {\n state: renovateToGitHubStateMapping[state],\n description,\n context,\n };\n // v8 ignore else -- TODO: add test #40625\n if (targetUrl) {\n options.target_url = targetUrl;\n }\n await githubApi.postJson(url, { body: options });\n\n // update status cache\n await getStatus(branchName, false);\n await getStatusCheck(branchName, false);\n } catch (err) /* v8 ignore next -- defensive: status POST failures abort with REPOSITORY_CHANGED, not simulated in specs */ {\n logger.debug({ err, url }, 'Caught error setting branch status - aborting');\n throw new Error(REPOSITORY_CHANGED);\n }\n}\n\n// Issue\n\nasync function getIssues(): Promise<Issue[]> {\n const result = await githubApi.queryRepoField<unknown>(\n getIssuesQuery,\n 'issues',\n {\n variables: {\n owner: config.repositoryOwner,\n name: config.repositoryName,\n ...(!config.ignorePrAuthor && { user: config.renovateUsername }),\n },\n readOnly: true,\n },\n );\n\n logger.debug(`Retrieved ${result.length} issues`);\n return Issue.array().parse(result);\n}\n\nexport async function getIssueList(): Promise<Issue[]> {\n /* v8 ignore next -- specs initialize repos with issues enabled */\n if (config.hasIssuesEnabled === false) {\n return [];\n }\n let issueList = GithubIssueCache.getIssues();\n // v8 ignore else -- TODO: add test #40625\n if (!issueList) {\n logger.debug('Retrieving issueList');\n issueList = await getIssues();\n GithubIssueCache.setIssues(issueList);\n }\n return issueList;\n}\n\nexport async function getIssue(number: number): Promise<Issue | null> {\n if (config.hasIssuesEnabled === false) {\n return null;\n }\n try {\n const repo = config.parentRepo ?? config.repository;\n const { body: issue } = await githubApi.getJson(\n `repos/${repo}/issues/${number}`,\n {\n cacheProvider: repoCacheProvider,\n },\n Issue,\n );\n GithubIssueCache.updateIssue(issue);\n return issue;\n } catch (err) {\n logger.debug({ err, number }, 'Error getting issue');\n if (err.response?.statusCode === 410) {\n logger.debug(`Issue #${number} has been deleted`);\n GithubIssueCache.deleteIssue(number);\n }\n return null;\n }\n}\n\nexport async function findIssue(title: string): Promise<Issue | null> {\n logger.debug(`findIssue(${title})`);\n const [issue] = (await getIssueList()).filter(\n (i) => i.state === 'open' && i.title === title,\n );\n if (!issue) {\n return null;\n }\n logger.debug(`Found issue ${issue.number}`);\n return getIssue(issue.number);\n}\n\nasync function closeIssue(issueNumber: number): Promise<void> {\n logger.debug(`closeIssue(${issueNumber})`);\n const repo = config.parentRepo ?? config.repository;\n try {\n const { body: closedIssue } = await githubApi.patchJson(\n `repos/${repo}/issues/${issueNumber}`,\n { body: { state: 'closed' } },\n Issue,\n );\n GithubIssueCache.updateIssue(closedIssue);\n } catch (err) {\n const statusCode = err.response?.statusCode;\n if (statusCode === 404 || statusCode === 410) {\n logger.debug(\n `Issue #${issueNumber} no longer exists on the platform, removing from cache`,\n );\n GithubIssueCache.deleteIssue(issueNumber);\n return;\n }\n throw err;\n }\n}\n\nexport async function ensureIssue({\n title,\n reuseTitle,\n body: rawBody,\n labels,\n once = false,\n shouldReOpen = true,\n}: EnsureIssueConfig): Promise<EnsureIssueResult | null> {\n logger.debug(`ensureIssue(${title})`);\n /* v8 ignore next -- specs initialize repos with issues enabled */\n if (config.hasIssuesEnabled === false) {\n logger.info(\n 'Cannot ensure issue because issues are disabled in this repository',\n );\n return null;\n }\n const body = sanitize(rawBody);\n try {\n const issueList = await getIssueList();\n let issues = issueList.filter((i) => i.title === title);\n if (!issues.length) {\n issues = issueList.filter((i) => i.title === reuseTitle);\n if (issues.length) {\n logger.debug(`Reusing issue title: \"${reuseTitle}\"`);\n }\n }\n if (issues.length) {\n let issue = issues.find((i) => i.state === 'open');\n if (!issue) {\n if (once) {\n logger.debug('Issue already closed - skipping recreation');\n return null;\n }\n if (shouldReOpen) {\n logger.debug('Reopening previously closed issue');\n }\n issue = issues.at(-1)!;\n }\n for (const i of issues) {\n if (i.state === 'open' && i.number !== issue.number) {\n logger.warn({ issueNo: i.number }, 'Closing duplicate issue');\n await closeIssue(i.number);\n }\n }\n\n const repo = config.parentRepo ?? config.repository;\n const { body: serverIssue } = await githubApi.getJson(\n `repos/${repo}/issues/${issue.number}`,\n { cacheProvider: repoCacheProvider },\n Issue,\n );\n GithubIssueCache.updateIssue(serverIssue);\n\n if (\n issue.title === title &&\n serverIssue.body === body &&\n issue.state === 'open'\n ) {\n logger.debug('Issue is open and up to date - nothing to do');\n return null;\n }\n if (shouldReOpen || issue.state === 'open') {\n logger.debug('Patching issue');\n const data: Record<string, unknown> = { body, state: 'open', title };\n if (labels) {\n data.labels = labels;\n }\n const repo = config.parentRepo ?? config.repository;\n const { body: updatedIssue } = await githubApi.patchJson(\n `repos/${repo}/issues/${issue.number}`,\n { body: data },\n Issue,\n );\n GithubIssueCache.updateIssue(updatedIssue);\n logger.debug('Issue updated');\n return 'updated';\n }\n }\n const { body: createdIssue } = await githubApi.postJson(\n `repos/${config.parentRepo ?? config.repository}/issues`,\n {\n body: {\n title,\n body,\n labels: labels ?? [],\n },\n },\n Issue,\n );\n logger.info('Issue created');\n // reset issueList so that it will be fetched again as-needed\n GithubIssueCache.updateIssue(createdIssue);\n return 'created';\n } catch (err) /* v8 ignore next -- issue creation failure handling is not mocked in specs */ {\n if (err.body?.message?.startsWith('Issues are disabled for this repo')) {\n logger.debug(`Issues are disabled, so could not create issue: ${title}`);\n } else {\n logger.warn({ err }, 'Could not ensure issue');\n }\n }\n return null;\n}\n\nexport async function ensureIssueClosing(title: string): Promise<void> {\n logger.trace(`ensureIssueClosing(${title})`);\n /* v8 ignore next -- specs initialize repos with issues enabled */\n if (config.hasIssuesEnabled === false) {\n return;\n }\n const issueList = await getIssueList();\n for (const issue of issueList) {\n if (issue.state === 'open' && issue.title === title) {\n await closeIssue(issue.number);\n logger.debug(`Issue closed, issueNo: ${issue.number}`);\n }\n }\n}\n\nasync function tryAddMilestone(\n issueNo: number,\n milestoneNo: number | undefined,\n): Promise<void> {\n if (!milestoneNo) {\n return;\n }\n\n logger.debug(\n {\n milestone: milestoneNo,\n pr: issueNo,\n },\n 'Adding milestone to PR',\n );\n try {\n const repo = config.parentRepo ?? config.repository;\n const { body: updatedIssue } = await githubApi.patchJson(\n `repos/${repo}/issues/${issueNo}`,\n { body: { milestone: milestoneNo } },\n Issue,\n );\n GithubIssueCache.updateIssue(updatedIssue);\n } catch (err) {\n /* v8 ignore next -- defensive: the raw-error fallback is for non-HTTP failures not seen in specs */\n const actualError = err.response?.body ?? err;\n logger.warn(\n {\n milestone: milestoneNo,\n pr: issueNo,\n err: actualError,\n },\n 'Unable to add milestone to PR',\n );\n }\n}\n\nexport async function addAssignees(\n issueNo: number,\n assignees: string[],\n): Promise<void> {\n logger.debug(`Adding assignees '${assignees.join(', ')}' to #${issueNo}`);\n const repository = config.parentRepo ?? config.repository;\n const url = `repos/${repository}/issues/${issueNo}/assignees`;\n let lastErr: Error | undefined;\n for (let attempt = 0; attempt < 3; attempt += 1) {\n try {\n const { body: updatedIssue } = await githubApi.postJson(\n url,\n { body: { assignees } },\n Issue,\n );\n GithubIssueCache.updateIssue(updatedIssue);\n return;\n } catch (err) {\n if (err.statusCode !== 404) {\n throw err;\n }\n lastErr = err;\n logger.debug(\n { attempt: attempt + 1 },\n `Retrying addAssignees for #${issueNo} after 404`,\n );\n await setTimeout(1000);\n }\n }\n throw lastErr!;\n}\n\nexport async function addReviewers(\n prNo: number,\n reviewers: string[],\n): Promise<void> {\n logger.debug(`Adding reviewers '${reviewers.join(', ')}' to #${prNo}`);\n\n const userReviewers = reviewers.filter((e) => !e.startsWith('team:'));\n const teamReviewers = reviewers\n .filter((e) => e.startsWith('team:'))\n .map((e) => e.replace(regEx(/^team:/), ''));\n try {\n await githubApi.postJson(\n `repos/${\n config.parentRepo ?? config.repository\n }/pulls/${prNo}/requested_reviewers`,\n {\n body: {\n reviewers: userReviewers,\n team_reviewers: teamReviewers,\n },\n },\n );\n } catch (err) /* v8 ignore next -- defensive: reviewer assignment failures are logged and swallowed, not simulated in specs */ {\n logger.warn({ err }, 'Failed to assign reviewer');\n }\n}\n\nexport async function addLabels(\n issueNo: number,\n labels: string[] | null | undefined,\n): Promise<void> {\n logger.debug(`Adding labels '${labels?.join(', ')}' to #${issueNo}`);\n try {\n const repository = config.parentRepo ?? config.repository;\n if (isArray(labels) && labels.length) {\n await githubApi.postJson(`repos/${repository}/issues/${issueNo}/labels`, {\n body: labels,\n });\n }\n } catch (err) /* v8 ignore next -- defensive: label-adding failures are logged and swallowed, not simulated in specs */ {\n logger.warn(\n { err, issueNo, labels },\n 'Error while adding labels. Skipping',\n );\n }\n}\n\nexport async function deleteLabel(\n issueNo: number,\n label: string,\n): Promise<void> {\n logger.debug(`Deleting label ${label} from #${issueNo}`);\n const repository = config.parentRepo ?? config.repository;\n try {\n await githubApi.deleteJson(\n `repos/${repository}/issues/${issueNo}/labels/${label}`,\n );\n } catch (err) /* v8 ignore next -- defensive: label deletion failures are logged and swallowed, not simulated in specs */ {\n logger.warn({ err, issueNo, label }, 'Failed to delete label');\n }\n}\n\nasync function addComment(issueNo: number, body: string): Promise<void> {\n // POST /repos/:owner/:repo/issues/:number/comments\n await githubApi.postJson(\n `repos/${\n config.parentRepo ?? config.repository\n }/issues/${issueNo}/comments`,\n {\n body: { body },\n },\n );\n}\n\nasync function editComment(commentId: number, body: string): Promise<void> {\n // PATCH /repos/:owner/:repo/issues/comments/:id\n await githubApi.patchJson(\n `repos/${\n config.parentRepo ?? config.repository\n }/issues/comments/${commentId}`,\n {\n body: { body },\n },\n );\n}\n\nasync function deleteComment(commentId: number): Promise<void> {\n // DELETE /repos/:owner/:repo/issues/comments/:id\n await githubApi.deleteJson(\n `repos/${\n config.parentRepo ?? config.repository\n }/issues/comments/${commentId}`,\n );\n}\n\nasync function getComments(issueNo: number): Promise<Comment[]> {\n // GET /repos/:owner/:repo/issues/:number/comments\n logger.debug(`Getting comments for #${issueNo}`);\n const repo = config.parentRepo ?? config.repository;\n const url = `repos/${repo}/issues/${issueNo}/comments?per_page=100`;\n try {\n const { body: comments } = await githubApi.getJsonUnchecked<Comment[]>(\n url,\n {\n paginate: true,\n cacheProvider: repoCacheProvider,\n },\n );\n logger.debug(`Found ${comments.length} comments`);\n return comments;\n } catch (err) /* v8 ignore next -- comment-fetch 404s are wrapped as ExternalHostError, not mocked in specs */ {\n if (err.statusCode === 404) {\n logger.debug('404 response when retrieving comments');\n throw new ExternalHostError(err, 'github');\n }\n throw err;\n }\n}\n\nexport async function ensureComment({\n number,\n topic,\n content,\n}: EnsureCommentConfig): Promise<boolean> {\n const sanitizedContent = sanitize(content);\n try {\n const comments = await getComments(number);\n let body: string;\n let commentId: number | null = null;\n let commentNeedsUpdating = false;\n if (topic) {\n logger.debug(`Ensuring comment \"${topic}\" in #${number}`);\n body = `### ${topic}\\n\\n${sanitizedContent}`;\n comments.forEach((comment) => {\n if (comment.body.startsWith(`### ${topic}\\n\\n`)) {\n commentId = comment.id;\n commentNeedsUpdating = comment.body !== body;\n }\n });\n } else {\n logger.debug(`Ensuring content-only comment in #${number}`);\n body = `${sanitizedContent}`;\n comments.forEach((comment) => {\n // v8 ignore else -- TODO: add test #40625\n if (comment.body === body) {\n commentId = comment.id;\n commentNeedsUpdating = false;\n }\n });\n }\n if (!commentId) {\n await addComment(number, body);\n logger.info(\n { repository: config.repository, issueNo: number, topic },\n 'Comment added',\n );\n } else if (commentNeedsUpdating) {\n await editComment(commentId, body);\n logger.debug(\n { repository: config.repository, issueNo: number },\n 'Comment updated',\n );\n } else {\n logger.debug('Comment is already up-to-date');\n }\n return true;\n } catch (err) /* v8 ignore next -- comment API failure handling (locked issues) is not mocked in specs */ {\n if (err instanceof ExternalHostError) {\n throw err;\n }\n if (err.body?.message?.includes('is locked')) {\n logger.debug('Issue is locked - cannot add comment');\n } else {\n logger.warn({ err }, 'Error ensuring comment');\n }\n return false;\n }\n}\n\nfunction byTopic(comment: Comment, topic: string): boolean {\n return comment.body.startsWith(`### ${topic}\\n\\n`);\n}\n\nfunction byContent(comment: Comment, content: string): boolean {\n return comment.body.trim() === content;\n}\n\nexport async function ensureCommentRemoval(\n deleteConfig: EnsureCommentRemovalConfig,\n): Promise<void> {\n const { number: issueNo } = deleteConfig;\n const key =\n deleteConfig.type === 'by-topic'\n ? deleteConfig.topic\n : deleteConfig.content;\n logger.trace(`Ensuring comment \"${key}\" in #${issueNo} is removed`);\n const comments = await getComments(issueNo);\n let commentId: number | null | undefined = null;\n\n // v8 ignore else -- TODO: add test #40625\n if (deleteConfig.type === 'by-topic') {\n const topic = deleteConfig.topic;\n commentId = comments.find((comment) => byTopic(comment, topic))?.id;\n } else if (deleteConfig.type === 'by-content') {\n const content = deleteConfig.content;\n commentId = comments.find((comment) => byContent(comment, content))?.id;\n }\n\n try {\n // v8 ignore else -- TODO: add test #40625\n if (commentId) {\n logger.debug(`Removing comment from issueNo: ${issueNo}`);\n await deleteComment(commentId);\n }\n } catch (err) /* v8 ignore next -- defensive: comment deletion failures are logged and swallowed, not simulated in specs */ {\n logger.warn({ err }, 'Error deleting comment');\n }\n}\n\n// Pull Request\n\nasync function tryPrAutomerge(\n prNumber: number,\n prNodeId: string,\n platformPrOptions: PlatformPrOptions | undefined,\n): Promise<void> {\n if (!platformPrOptions?.usePlatformAutomerge) {\n return;\n }\n\n // If GitHub Enterprise Server <3.3.0 it doesn't support automerge\n // TODO #22198\n // semver not null safe, accepts null and undefined\n if (\n platformConfig.isGhe &&\n semver.satisfies(platformConfig.gheVersion!, '<3.3.0')\n ) {\n logger.debug(\n { prNumber },\n 'GitHub-native automerge: not supported on this version of GHE. Use 3.3.0 or newer.',\n );\n return;\n }\n\n if (!config.autoMergeAllowed) {\n logger.debug(\n { prNumber },\n 'GitHub-native automerge: not enabled in repo settings',\n );\n return;\n }\n\n try {\n const mergeMethod = config.mergeMethod?.toUpperCase() || 'MERGE';\n\n let commitHeadline: string | undefined;\n let commitBody: string | undefined;\n // For SQUASH and MERGE methods, pass the commit message explicitly to avoid\n // GitHub using the PR description as the commit body when \"Use PR title and\n // body as commit message\" is enabled in repository settings.\n const automergeCommitMessage = platformPrOptions?.automergeCommitMessage;\n if (mergeMethod !== 'REBASE' && automergeCommitMessage) {\n const newlineIndex = automergeCommitMessage.indexOf('\\n');\n if (newlineIndex === -1) {\n commitHeadline = automergeCommitMessage;\n } else {\n commitHeadline = automergeCommitMessage.slice(0, newlineIndex);\n commitBody = automergeCommitMessage.slice(newlineIndex + 1).trim();\n }\n\n // Add PR number to the commit headline to match the default GitHub behavior\n commitHeadline = `${commitHeadline} (#${prNumber})`;\n }\n\n const variables = {\n pullRequestId: prNodeId,\n mergeMethod,\n commitHeadline,\n commitBody,\n };\n // set count to one bypass graphql check\n const queryOptions = { variables, count: 1 };\n\n const res = await githubApi.requestGraphql<GhAutomergeResponse>(\n enableAutoMergeMutation,\n queryOptions,\n );\n\n if (res?.errors) {\n logger.debug(\n { prNumber, errors: res.errors },\n 'GitHub-native automerge: fail',\n );\n return;\n }\n\n logger.debug(`GitHub-native automerge: success...PrNo: ${prNumber}`);\n } catch (err) /* v8 ignore next: missing test #22198 */ {\n logger.warn({ prNumber, err }, 'GitHub-native automerge: REST API error');\n }\n}\n\n// Creates PR and returns PR number\nexport async function createPr({\n sourceBranch,\n targetBranch,\n prTitle: title,\n prBody: rawBody,\n labels,\n draftPR = false,\n platformPrOptions,\n milestone,\n}: CreatePRConfig): Promise<GhPr | null> {\n const body = sanitize(rawBody);\n const base = targetBranch;\n // Include the repository owner to handle forkToken and regular mode\n // TODO: can `repository` be null? (#22198)\n\n const head = `${config.repository!.split('/')[0]}:${sourceBranch}`;\n const options: any = {\n body: {\n title,\n head,\n base,\n body,\n draft: draftPR,\n },\n };\n /* v8 ignore next -- fork mode is not exercised in createPr specs */\n if (config.forkToken) {\n options.token = config.forkToken;\n options.body.maintainer_can_modify =\n !config.forkOrg &&\n platformPrOptions?.forkModeDisallowMaintainerEdits !== true;\n }\n logger.debug({ title, head, base, draft: draftPR }, 'Creating PR');\n const ghPr = (\n await githubApi.postJson<GhRestPr>(\n `repos/${config.parentRepo ?? config.repository}/pulls`,\n options,\n )\n ).body;\n logger.debug(\n { branch: sourceBranch, pr: ghPr.number, draft: draftPR },\n 'PR created',\n );\n\n const result = coerceRestPr(ghPr);\n const { number, node_id } = result;\n\n await addLabels(number, labels);\n await tryAddMilestone(number, milestone);\n await tryPrAutomerge(number, node_id, platformPrOptions);\n\n cachePr(result);\n return result;\n}\n\nasync function isMergeQueueEnabled(baseBranch: string): Promise<boolean> {\n const cachedResult = config.mergeQueueEnabled[baseBranch];\n if (cachedResult !== undefined) {\n return cachedResult;\n }\n\n // TODO #22198\n // semver not null safe, accepts null and undefined\n if (\n platformConfig.isGhe &&\n semver.satisfies(platformConfig.gheVersion!, '<3.12.0')\n ) {\n // Merge queues are only supported on GHES >=3.12.0\n config.mergeQueueEnabled[baseBranch] = false;\n return false;\n }\n\n // Assume enabled unless proven otherwise, so the merge queue check is not\n // skipped by mistake\n let result = true;\n try {\n const res = await githubApi.requestGraphql<{\n repository: { mergeQueue: { id: string } | null };\n }>(repoMergeQueueQuery, {\n variables: {\n owner: config.repositoryOwner,\n name: config.repositoryName,\n branch: baseBranch,\n },\n readOnly: true,\n count: 1, // bypass graphql check\n });\n if (res?.errors) {\n logger.debug(\n { baseBranch, errors: res.errors },\n 'Failed to fetch merge queue status - assuming merge queue is enabled',\n );\n } else {\n result = isNonEmptyObject(res?.data?.repository?.mergeQueue);\n }\n } catch (err) {\n logger.debug(\n { baseBranch, err },\n 'Error fetching merge queue status - assuming merge queue is enabled',\n );\n }\n\n config.mergeQueueEnabled[baseBranch] = result;\n return result;\n}\n\nexport async function assertPrNotInMergeQueue(\n branchName: string,\n baseBranch?: string,\n): Promise<void> {\n if (!(await isMergeQueueEnabled(baseBranch ?? config.defaultBranch))) {\n return;\n }\n\n const pr = await findPr({ branchName, state: 'open' });\n if (!pr) {\n return;\n }\n\n if (\n await isPrInMergeQueue(\n githubApi,\n config.repositoryOwner,\n config.repositoryName,\n pr.number,\n )\n ) {\n logger.debug(`PR #${pr.number} is in the merge queue - aborting push`);\n throw new Error(PR_ALREADY_IN_MERGE_QUEUE);\n }\n}\n\nexport async function updatePr({\n number: prNo,\n prTitle: title,\n prBody: rawBody,\n addLabels: labelsToAdd,\n removeLabels,\n state,\n targetBranch,\n}: UpdatePrConfig): Promise<void> {\n logger.debug(`updatePr(${prNo}, ${title}, body)`);\n const body = sanitize(rawBody);\n const patchBody: any = { title };\n // v8 ignore else -- TODO: add test #40625\n if (body) {\n patchBody.body = body;\n }\n if (targetBranch) {\n patchBody.base = targetBranch;\n }\n if (state) {\n patchBody.state = state;\n }\n const options: any = {\n body: patchBody,\n };\n /* v8 ignore next -- fork mode is not exercised in updatePr specs */\n if (config.forkToken) {\n options.token = config.forkToken;\n }\n\n // Update PR labels\n try {\n if (labelsToAdd) {\n await addLabels(prNo, labelsToAdd);\n }\n\n if (removeLabels) {\n for (const label of removeLabels) {\n await deleteLabel(prNo, label);\n }\n }\n\n const { body: ghPr } = await githubApi.patchJson<GhRestPr>(\n `repos/${config.parentRepo ?? config.repository}/pulls/${prNo}`,\n options,\n );\n const result = coerceRestPr(ghPr);\n cachePr(result);\n logger.debug(`PR updated...prNo: ${prNo}`);\n } catch (err) /* v8 ignore next -- non-host update failures are logged and swallowed, not mocked in specs */ {\n if (err instanceof ExternalHostError) {\n throw err;\n }\n logger.warn({ err }, 'Error updating PR');\n }\n}\n\nexport async function reattemptPlatformAutomerge({\n number,\n platformPrOptions,\n}: ReattemptPlatformAutomergeConfig): Promise<void> {\n try {\n const result = (await getPr(number))!;\n const { node_id } = result;\n\n await tryPrAutomerge(number, node_id, platformPrOptions);\n\n logger.debug(`PR platform automerge re-attempted...prNo: ${number}`);\n } catch (err) /* v8 ignore next -- defensive: automerge re-attempt failures are logged and swallowed, not simulated in specs */ {\n logger.warn({ err }, 'Error re-attempting PR platform automerge');\n }\n}\n\nexport async function mergePr({\n branchName,\n id: prNo,\n strategy,\n}: MergePRConfig): Promise<boolean> {\n logger.debug(`mergePr(${prNo}, ${branchName})`);\n const url = `repos/${\n config.parentRepo ?? config.repository\n }/pulls/${prNo}/merge`;\n const options: GithubHttpOptions = {\n body: {},\n };\n /* v8 ignore next -- fork mode is not exercised in mergePr specs */\n if (config.forkToken) {\n options.token = config.forkToken;\n }\n let automerged = false;\n let automergeResult: HttpResponse<unknown>;\n const mergeStrategy = mapMergeStartegy(strategy) ?? config.mergeMethod;\n\n // v8 ignore else -- TODO: add test #40625\n if (mergeStrategy) {\n // This path is taken if we have auto-detected the allowed merge types from the repo or\n // automergeStrategy is configured by user\n options.body.merge_method = mergeStrategy;\n try {\n logger.debug({ options, url }, `mergePr`);\n automergeResult = await githubApi.putJson(url, options);\n automerged = true;\n } catch (err) /* v8 ignore next -- merge rejection handling (404/405 status-check bodies) is not fully mocked in specs */ {\n if (err.statusCode === 404 || err.statusCode === 405) {\n const body = err.response?.body;\n if (\n isNonEmptyString(body?.message) &&\n regEx(/^Required status check \".+\" is expected\\.$/).test(body.message)\n ) {\n logger.debug(\n { response: body },\n `GitHub blocking PR merge -- Missing required status check(s)`,\n );\n return false;\n }\n if (\n isNonEmptyString(body?.message) &&\n (body.message.includes('approving review') ||\n body.message.includes('code owner review') ||\n body.message.includes(\n 'New changes require approval from someone other than the last pusher',\n ))\n ) {\n logger.debug(\n { response: body },\n `GitHub blocking PR merge -- Needs approving review(s)`,\n );\n return false;\n }\n logger.debug(\n { response: body },\n 'GitHub blocking PR merge -- will keep trying',\n );\n } else {\n logger.warn(\n { mergeMethod: config.mergeMethod, err },\n 'Failed to merge PR',\n );\n return false;\n }\n }\n }\n if (!automerged) {\n // We need to guess the merge method and try squash -> merge -> rebase\n options.body.merge_method = 'squash';\n try {\n logger.debug({ options, url }, `mergePr`);\n automergeResult = await githubApi.putJson(url, options);\n } catch (err1) {\n logger.debug({ err: err1 }, `Failed to squash merge PR`);\n try {\n options.body.merge_method = 'merge';\n logger.debug({ options, url }, `mergePr`);\n automergeResult = await githubApi.putJson(url, options);\n } catch (err2) {\n logger.debug({ err: err2 }, `Failed to merge commit PR`);\n try {\n options.body.merge_method = 'rebase';\n logger.debug({ options, url }, `mergePr`);\n automergeResult = await githubApi.putJson(url, options);\n } catch (err3) {\n logger.debug({ err: err3 }, `Failed to rebase merge PR`);\n logger.info({ pr: prNo }, 'All merge attempts failed');\n return false;\n }\n }\n }\n }\n logger.debug(\n { automergeResult: automergeResult!.body, pr: prNo },\n 'PR merged',\n );\n const cachedPr = config.prList?.find(({ number }) => number === prNo);\n if (cachedPr) {\n cachePr({ ...cachedPr, state: 'merged' });\n }\n return true;\n}\n\nexport function massageMarkdown(input: string): string {\n if (platformConfig.isGhe) {\n return smartTruncate(input, maxBodyLength());\n }\n const massagedInput = massageMarkdownLinks(input)\n // to be safe, replace all github.com links with redirect.github.com\n .replace(\n regEx(/href=\"https?:\\/\\/github.com\\//g),\n 'href=\"https://redirect.github.com/',\n )\n .replace(\n regEx(/]\\(https:\\/\\/github\\.com\\//g),\n '](https://redirect.github.com/',\n )\n .replace(\n regEx(/]: https:\\/\\/github\\.com\\//g),\n ']: https://redirect.github.com/',\n )\n .replaceAll('> ℹ **Note**\\n> \\n', '> [!NOTE]\\n')\n .replaceAll('> ℹ️ **Note**\\n> \\n', '> [!NOTE]\\n')\n .replaceAll('> ⚠ **Warning**\\n> \\n', '> [!WARNING]\\n')\n .replaceAll('> ⚠️ **Warning**\\n> \\n', '> [!WARNING]\\n')\n .replaceAll('> ❗ **Caution**\\n> \\n', '> [!CAUTION]\\n')\n .replaceAll('> ❗ **Important**\\n> \\n', '> [!IMPORTANT]\\n');\n return smartTruncate(massagedInput, maxBodyLength());\n}\n\nexport function maxBodyLength(): number {\n return GitHubMaxPrBodyLen;\n}\n\nexport async function getVulnerabilityAlerts(): Promise<GithubVulnerabilityAlerts> {\n /* v8 ignore next -- specs initialize repos with vulnerability alerts enabled */\n if (config.hasVulnerabilityAlertsEnabled === false) {\n logger.debug('No vulnerability alerts enabled for repo');\n return [];\n }\n let vulnerabilityAlerts: GithubVulnerabilityAlerts | undefined;\n try {\n vulnerabilityAlerts = (\n await githubApi.getJson(\n `/repos/${config.repositoryOwner}/${config.repositoryName}/dependabot/alerts?state=open&direction=asc&per_page=100`,\n {\n paginate: true,\n headers: { accept: 'application/vnd.github+json' },\n cacheProvider: repoCacheProvider,\n },\n GithubVulnerabilityAlerts,\n )\n ).body;\n } catch (err) /* v8 ignore next -- alert-permission failures are logged and swallowed, not mocked in specs */ {\n logger.debug({ err }, 'Error retrieving vulnerability alerts');\n logger.warn(\n {\n url: `${GlobalConfig.get('productLinks').documentation}configuration-options/#vulnerabilityalerts`,\n },\n 'Cannot access vulnerability alerts. Please ensure permissions have been granted.',\n );\n }\n try {\n if (vulnerabilityAlerts?.length) {\n const shortAlerts: AggregatedVulnerabilities = {};\n logger.trace(\n { alerts: vulnerabilityAlerts },\n 'GitHub vulnerability details',\n );\n for (const alert of vulnerabilityAlerts) {\n // v8 ignore if -- TODO: can never happen but makes typescript happy #40625\n if (alert.security_vulnerability === null) {\n // As described in the documentation, there are cases in which\n // GitHub API responds with `\"securityVulnerability\": null`.\n // But it's may be faulty, so skip processing it here.\n continue;\n }\n const {\n package: { name, ecosystem },\n vulnerable_version_range: vulnerableVersionRange,\n first_patched_version: firstPatchedVersion,\n } = alert.security_vulnerability;\n const patch = firstPatchedVersion?.identifier;\n\n const normalizedName =\n ecosystem === 'pip' ? normalizePythonDepName(name) : name;\n alert.security_vulnerability.package.name = normalizedName;\n const key = `${ecosystem.toLowerCase()}/${normalizedName}`;\n const range = vulnerableVersionRange;\n const elem = shortAlerts[key] || {};\n elem[range] = coerceToNull(patch);\n shortAlerts[key] = elem;\n }\n logger.debug({ alerts: shortAlerts }, 'GitHub vulnerability details');\n } else {\n logger.debug('No vulnerability alerts found');\n }\n } catch (err) /* v8 ignore next -- defensive: processing already-parsed alerts does not throw in specs */ {\n logger.error({ err }, 'Error processing vulnerabity alerts');\n }\n return vulnerabilityAlerts ?? [];\n}\n\nasync function pushFiles(\n { branchName, message, trailers }: CommitFilesConfig,\n { parentCommitSha, commitSha }: CommitResult,\n): Promise<LongCommitSha | null> {\n try {\n // Hybrid git/REST commit strategy (see #13824, #14271):\n // 1. The git push below uploads blobs to GitHub via a custom ref\n // (refs/renovate/branches/*) which does NOT trigger CI/Actions.\n // 2. We then recreate the tree+commit via REST API so that:\n // - The commit is signed by GitHub (\"committed via GitHub\" badge)\n // - Force-push and file mode bits are supported (GraphQL can't do this)\n // - We can use base_tree to send only changed files, avoiding org\n // ruleset file-path restrictions on unchanged files (#42554)\n // Reusing the pushed commit/tree SHAs directly does not work because\n // the branch ref must point to an API-created commit for signing.\n await pushCommitToRenovateRef(commitSha, branchName);\n const baseTreeSha = await getCommitTreeSha(parentCommitSha);\n const treeItems = await diffCommitTree(parentCommitSha, commitSha);\n\n if (treeItems.length === 0) {\n logger.debug(\n { branchName },\n 'Platform-native commit: no changed files between commits',\n );\n return null;\n }\n\n const treeRes = await githubApi.postJson<{ sha: string }>(\n `/repos/${config.repository}/git/trees`,\n { body: { base_tree: baseTreeSha, tree: treeItems } },\n );\n const treeSha = treeRes.body.sha;\n\n const commitMessage = formatCommitMessage(message, trailers);\n\n // Now we recreate the commit using the tree we recreated the step before\n const commitRes = await githubApi.postJson<{ sha: string }>(\n `/repos/${config.repository}/git/commits`,\n {\n body: {\n message: commitMessage,\n tree: treeSha,\n parents: [parentCommitSha],\n },\n },\n );\n incLimitedValue('Commits');\n const remoteCommitSha = toLongCommitSha(commitRes.body.sha);\n await ensureBranchSha(branchName, remoteCommitSha);\n return remoteCommitSha;\n } catch (err) {\n logger.debug({ branchName, err }, 'Platform-native commit: unknown error');\n return null;\n }\n}\n\nexport async function commitFiles(\n config: CommitFilesConfig,\n): Promise<LongCommitSha | null> {\n const commitResult = await git.prepareCommit(config); // Commit locally and don't push\n const { branchName, files } = config;\n if (!commitResult) {\n logger.debug(\n { branchName, files: files.map(({ path }) => path) },\n `Platform-native commit: unable to prepare for commit`,\n );\n return null;\n }\n // Perform the commits using REST API\n const pushResult = await pushFiles(config, commitResult);\n if (!pushResult) {\n return null;\n }\n // Replace locally created branch with the remotely created one\n // and return the remote commit SHA\n await git.resetToCommit(commitResult.parentCommitSha);\n const commitSha = await git.fetchBranch(branchName);\n return commitSha;\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","names":["hostRules.find","Issue","git.initRepo","git.getBranchCommit","git.forcePushToRemote","git.prepareCommit","git.resetToCommit","git.fetchBranch"],"sources":["../../../../lib/modules/platform/github/index.ts"],"sourcesContent":["import { setTimeout } from 'node:timers/promises';\nimport { isArray, isNonEmptyObject, isNonEmptyString } from '@sindresorhus/is';\nimport semver from 'semver';\nimport { GlobalConfig } from '../../../config/global.ts';\nimport {\n PLATFORM_INTEGRATION_UNAUTHORIZED,\n PLATFORM_RATE_LIMIT_EXCEEDED,\n PLATFORM_UNKNOWN_ERROR,\n PR_ALREADY_IN_MERGE_QUEUE,\n REPOSITORY_ACCESS_FORBIDDEN,\n REPOSITORY_ARCHIVED,\n REPOSITORY_BLOCKED,\n REPOSITORY_CANNOT_FORK,\n REPOSITORY_CHANGED,\n REPOSITORY_DISABLED,\n REPOSITORY_EMPTY,\n REPOSITORY_FORKED,\n REPOSITORY_FORK_MISSING,\n REPOSITORY_FORK_MODE_FORKED,\n REPOSITORY_NOT_FOUND,\n REPOSITORY_RENAMED,\n} from '../../../constants/error-messages.ts';\nimport { instrument } from '../../../instrumentation/index.ts';\nimport { logger } from '../../../logger/index.ts';\nimport { ExternalHostError } from '../../../types/errors/external-host-error.ts';\nimport type { BranchStatus } from '../../../types/index.ts';\nimport { isGithubFineGrainedPersonalAccessToken } from '../../../util/check-token.ts';\nimport { coerceToNull } from '../../../util/coerce.ts';\nimport { parseJson } from '../../../util/common.ts';\nimport { getEnv } from '../../../util/env.ts';\nimport { formatCommitMessage } from '../../../util/git/commit-trailers.ts';\nimport * as git from '../../../util/git/index.ts';\nimport {\n diffCommitTree,\n getCommitTreeSha,\n pushCommitToRenovateRef,\n} from '../../../util/git/index.ts';\nimport type {\n CommitFilesConfig,\n CommitResult,\n} from '../../../util/git/types.ts';\nimport * as hostRules from '../../../util/host-rules.ts';\nimport { memCacheProvider } from '../../../util/http/cache/memory-http-cache-provider.ts';\nimport { repoCacheProvider } from '../../../util/http/cache/repository-http-cache-provider.ts';\nimport type { GithubHttpOptions } from '../../../util/http/github.ts';\nimport * as githubHttp from '../../../util/http/github.ts';\nimport type { HttpResponse } from '../../../util/http/types.ts';\nimport { coerceObject } from '../../../util/object.ts';\nimport { regEx } from '../../../util/regex.ts';\nimport { sanitize } from '../../../util/sanitize.ts';\nimport type { LongCommitSha } from '../../../util/schema-utils/git.ts';\nimport { toLongCommitSha } from '../../../util/schema-utils/git.ts';\nimport { fromBase64, looseEquals } from '../../../util/string.ts';\nimport { ensureTrailingSlash, isHttpUrl, parseUrl } from '../../../util/url.ts';\nimport { incLimitedValue } from '../../../workers/global/limits.ts';\nimport { normalizePythonDepName } from '../../datasource/pypi/common.ts';\nimport type {\n AutodiscoverConfig,\n BranchStatusConfig,\n CreatePRConfig,\n EnsureCommentConfig,\n EnsureCommentRemovalConfig,\n EnsureIssueConfig,\n EnsureIssueResult,\n FindPRConfig,\n MergePRConfig,\n PlatformParams,\n PlatformPrOptions,\n PlatformResult,\n Pr,\n ReattemptPlatformAutomergeConfig,\n RepoParams,\n RepoResult,\n UpdatePrConfig,\n} from '../types.ts';\nimport { repoFingerprint } from '../util.ts';\nimport { smartTruncate } from '../utils/pr-body.ts';\nimport { remoteBranchExists } from './branch.ts';\nimport { coerceRestPr, githubApi, mapMergeStartegy } from './common.ts';\nimport {\n enableAutoMergeMutation,\n getIssuesQuery,\n repoInfoQuery,\n repoMergeQueueQuery,\n} from './graphql.ts';\nimport { GithubIssueCache } from './issue.ts';\nimport { massageMarkdownLinks } from './massage-markdown-links.ts';\nimport { getPrCache, isPrInMergeQueue, updatePrCache } from './pr.ts';\nimport {\n GithubBranchProtection,\n GithubBranchRulesets,\n GithubVulnerabilityAlerts,\n GithubIssue as Issue,\n} from './schema.ts';\nimport type {\n AggregatedVulnerabilities,\n CombinedBranchStatus,\n Comment,\n GhAutomergeResponse,\n GhBranchStatus,\n GhPr,\n GhRepo,\n GhRestPr,\n GhRestRepo,\n LocalRepoConfig,\n PlatformConfig,\n} from './types.ts';\nimport { getAppDetails, getUserDetails, getUserEmail } from './user.ts';\nimport { getRepoUrl, warnIfDefaultGitAuthorEmail } from './utils.ts';\n\nexport const id = 'github';\n\nlet config: LocalRepoConfig;\nlet platformConfig: PlatformConfig;\n\n// GitHub's max is 60k but in the hosted app we've observed that content-length is ~1k longer\nconst GitHubMaxPrBodyLen = 58000;\n\nexport function resetConfigs(): void {\n config = {} as never;\n platformConfig = {\n hostType: 'github',\n endpoint: 'https://api.github.com/',\n };\n}\n\nresetConfigs();\n\nfunction escapeHash(input: string): string {\n return input?.replace(regEx(/#/g), '%23');\n}\n\nexport function isGHApp(): boolean {\n return !!platformConfig.isGHApp;\n}\n\nexport async function detectGhe(token: string): Promise<void> {\n const parsedEndpoint = parseUrl(platformConfig.endpoint);\n /* v8 ignore next -- endpoint is validated in initPlatform before detectGhe is called */\n if (!parsedEndpoint) {\n throw new Error(`Invalid GitHub endpoint: ${platformConfig.endpoint}`);\n }\n const host = parsedEndpoint.host;\n platformConfig.isGhe = host !== 'api.github.com';\n platformConfig.isGheCloud = host.endsWith('.ghe.com');\n if (platformConfig.isGhe) {\n const gheHeaderKey = 'x-github-enterprise-version';\n const gheQueryRes = await githubApi.headJson('/', { token });\n const gheHeaders = coerceObject(gheQueryRes?.headers);\n const [, gheVersion] =\n Object.entries(gheHeaders).find(\n ([k]) => k.toLowerCase() === gheHeaderKey,\n ) ?? [];\n platformConfig.gheVersion = semver.valid(gheVersion as string) ?? null;\n logger.debug(\n `Detected GitHub Enterprise Server, version: ${platformConfig.gheVersion}`,\n );\n }\n}\n\nexport async function initPlatform({\n endpoint,\n token: originalToken,\n username,\n gitAuthor,\n}: PlatformParams): Promise<PlatformResult> {\n let token = originalToken;\n if (!token) {\n throw new Error('Init: You must configure a GitHub token');\n }\n token = token.replace(regEx(/^ghs_/), 'x-access-token:ghs_');\n platformConfig.isGHApp = token.startsWith('x-access-token:');\n\n if (endpoint) {\n if (!isHttpUrl(endpoint)) {\n throw new Error(`Init: Invalid GitHub endpoint URL: ${endpoint}`);\n }\n platformConfig.endpoint = ensureTrailingSlash(endpoint);\n githubHttp.setBaseUrl(platformConfig.endpoint);\n } else {\n logger.debug(`Using default github endpoint: ${platformConfig.endpoint}`);\n }\n\n await detectGhe(token);\n /**\n * GHE requires version >=3.10 to support fine-grained access tokens\n * https://docs.github.com/en/enterprise-server@3.10/admin/release-notes#authentication\n */\n if (\n isGithubFineGrainedPersonalAccessToken(token) &&\n platformConfig.isGhe &&\n (!platformConfig.gheVersion ||\n semver.lt(platformConfig.gheVersion, '3.10.0'))\n ) {\n throw new Error(\n 'Init: Fine-grained Personal Access Tokens do not support GitHub Enterprise Server API version <3.10 and cannot be used with Renovate.',\n );\n }\n\n let renovateUsername: string;\n if (username) {\n renovateUsername = username;\n } else if (platformConfig.isGHApp) {\n platformConfig.userDetails ??= await getAppDetails(token);\n renovateUsername = platformConfig.userDetails.username;\n } else {\n platformConfig.userDetails ??= await getUserDetails(\n platformConfig.endpoint,\n token,\n );\n renovateUsername = platformConfig.userDetails.username;\n }\n\n let ghHostname: string;\n /* v8 ignore next -- false negative due to V8/source-map artifact */\n if (platformConfig.isGheCloud) {\n ghHostname = 'ghe.com';\n } else if (platformConfig.isGhe) {\n // valid url ensured at the function start\n const parsedEndpoint = parseUrl(platformConfig.endpoint)!;\n ghHostname = parsedEndpoint.hostname;\n } else {\n ghHostname = 'github.com';\n }\n\n let discoveredGitAuthor: string | undefined;\n if (!gitAuthor) {\n if (platformConfig.isGHApp) {\n platformConfig.userDetails ??= await getAppDetails(token);\n discoveredGitAuthor = `${platformConfig.userDetails.name} <${platformConfig.userDetails.id}+${platformConfig.userDetails.username}@users.noreply.${ghHostname}>`;\n } else {\n platformConfig.userDetails ??= await getUserDetails(\n platformConfig.endpoint,\n token,\n );\n // v8 ignore next -- TODO: coverage error #40625\n platformConfig.userEmail =\n platformConfig.userDetails.email ??\n (await getUserEmail(platformConfig.endpoint, token));\n if (platformConfig.userEmail) {\n discoveredGitAuthor = `${platformConfig.userDetails.name} <${platformConfig.userEmail}>`;\n }\n }\n }\n\n git.setPlatformIgnoredAuthors([`noreply@${ghHostname}`]);\n\n logger.debug({ platformConfig, renovateUsername }, 'Platform config');\n const platformResult: PlatformResult = {\n endpoint: platformConfig.endpoint,\n gitAuthor: gitAuthor ?? discoveredGitAuthor,\n renovateUsername,\n token,\n };\n\n warnIfDefaultGitAuthorEmail(platformResult.gitAuthor, platformConfig.isGhe);\n\n if (\n getEnv().RENOVATE_X_GITHUB_HOST_RULES &&\n platformResult.endpoint === 'https://api.github.com/'\n ) {\n logger.debug('Adding GitHub token as GHCR password');\n platformResult.hostRules = [\n {\n matchHost: 'ghcr.io',\n hostType: 'docker',\n username: 'USERNAME',\n password: token.replace(regEx(/^x-access-token:/), ''),\n },\n ];\n logger.debug('Adding GitHub token as npm.pkg.github.com Basic token');\n platformResult.hostRules.push({\n matchHost: 'npm.pkg.github.com',\n hostType: 'npm',\n token: token.replace(regEx(/^x-access-token:/), ''),\n });\n const usernamePasswordHostTypes = ['rubygems', 'maven', 'nuget'];\n for (const hostType of usernamePasswordHostTypes) {\n logger.debug(\n `Adding GitHub token as ${hostType}.pkg.github.com password`,\n );\n platformResult.hostRules.push({\n hostType,\n matchHost: `${hostType}.pkg.github.com`,\n username: renovateUsername,\n password: token.replace(regEx(/^x-access-token:/), ''),\n });\n }\n }\n return platformResult;\n}\n\nasync function fetchRepositories(): Promise<GhRestRepo[]> {\n try {\n if (isGHApp()) {\n const res = await githubApi.getJsonUnchecked<{\n repositories: GhRestRepo[];\n }>(`installation/repositories?per_page=100`, {\n paginationField: 'repositories',\n paginate: 'all',\n });\n return res.body.repositories;\n }\n const res = await githubApi.getJsonUnchecked<GhRestRepo[]>(\n `user/repos?per_page=100`,\n { paginate: 'all' },\n );\n return res.body;\n } catch (err) /* v8 ignore next -- defensive: repo listing failures are logged and rethrown, not simulated in specs */ {\n logger.error({ err }, `GitHub getRepos error`);\n throw err;\n }\n}\n\n// Get all repositories that the user has access to\nexport async function getRepos(config?: AutodiscoverConfig): Promise<string[]> {\n logger.debug('Autodiscovering GitHub repositories');\n const nonEmptyRepositories = (await fetchRepositories()).filter(\n isNonEmptyObject,\n );\n const nonArchivedRepositories = nonEmptyRepositories.filter(\n (repo) => !repo.archived,\n );\n if (nonArchivedRepositories.length < nonEmptyRepositories.length) {\n logger.debug(\n `Filtered out ${\n nonEmptyRepositories.length - nonArchivedRepositories.length\n } archived repositories`,\n );\n }\n if (!config?.topics) {\n return nonArchivedRepositories.map((repo) => repo.full_name);\n }\n\n logger.debug({ topics: config.topics }, 'Filtering by topics');\n const topicRepositories = nonArchivedRepositories.filter((repo) =>\n repo.topics?.some((topic) => config?.topics?.includes(topic)),\n );\n\n // v8 ignore else -- TODO: add test #40625\n if (topicRepositories.length < nonArchivedRepositories.length) {\n logger.debug(\n `Filtered out ${\n nonArchivedRepositories.length - topicRepositories.length\n } repositories not matching topic filters`,\n );\n }\n return topicRepositories.map((repo) => repo.full_name);\n}\n\nasync function getBranchProtection(\n branchName: string,\n): Promise<GithubBranchProtection> {\n if (config.parentRepo) {\n return {};\n }\n\n const res = await githubApi.getJson(\n `repos/${config.repository}/branches/${escapeHash(branchName)}/protection`,\n { cacheProvider: repoCacheProvider },\n GithubBranchProtection,\n );\n return res.body;\n}\n\nasync function getBranchRulesets(\n branchName: string,\n): Promise<GithubBranchRulesets> {\n if (config.parentRepo) {\n return [];\n }\n\n try {\n const res = await githubApi.getJson(\n `repos/${config.repository}/rules/branches/${escapeHash(branchName)}`,\n { cacheProvider: repoCacheProvider },\n GithubBranchRulesets,\n );\n return res.body;\n } catch (err) {\n if (err.statusCode === 404) {\n logger.debug(`No branch rulesets found for ${branchName}`);\n return [];\n }\n throw err;\n }\n}\n\nexport async function getRawFile(\n fileName: string,\n repoName?: string,\n branchOrTag?: string,\n): Promise<string | null> {\n const repo = repoName ?? config.repository;\n\n // only use cache for the same org\n const httpOptions: GithubHttpOptions = {};\n const isSameOrg = repo?.split('/')?.[0] === config.repositoryOwner;\n // v8 ignore else -- TODO: add test #40625\n if (isSameOrg) {\n httpOptions.cacheProvider = repoCacheProvider;\n }\n\n let url = `repos/${repo}/contents/${fileName}`;\n if (branchOrTag) {\n url += `?ref=${branchOrTag}`;\n }\n const res = await githubApi.getJsonUnchecked<{ content: string }>(\n url,\n httpOptions,\n );\n const buf = res.body.content;\n const str = fromBase64(buf);\n return str;\n}\n\nexport async function getJsonFile(\n fileName: string,\n repoName?: string,\n branchOrTag?: string,\n): Promise<any> {\n const raw = await getRawFile(fileName, repoName, branchOrTag);\n return parseJson(raw, fileName);\n}\n\nexport async function listForks(\n token: string,\n repository: string,\n): Promise<GhRestRepo[]> {\n try {\n // Get list of existing repos\n const url = `repos/${repository}/forks?per_page=100`;\n const repos = (\n await githubApi.getJsonUnchecked<GhRestRepo[]>(url, {\n token,\n paginate: true,\n pageLimit: 100,\n })\n ).body;\n logger.debug(`Found ${repos.length} forked repo(s)`);\n return repos;\n } catch (err) {\n if (err.statusCode === 404) {\n logger.debug('Cannot list repo forks - it is likely private');\n } else {\n logger.debug({ err }, 'Unknown error listing repository forks');\n }\n throw new Error(REPOSITORY_CANNOT_FORK);\n }\n}\n\nexport async function findFork(\n token: string,\n repository: string,\n forkOrg?: string,\n): Promise<GhRestRepo | null> {\n const forks = await listForks(token, repository);\n if (forkOrg) {\n logger.debug(`Searching for forked repo in forkOrg (${forkOrg})`);\n const forkedRepo = forks.find((repo) => repo.owner.login === forkOrg);\n if (forkedRepo) {\n logger.debug(`Found repo in forkOrg: ${forkedRepo.full_name}`);\n return forkedRepo;\n }\n logger.debug(`No repo found in forkOrg`);\n }\n logger.debug(`Searching for forked repo in user account`);\n try {\n const { username } = await getUserDetails(platformConfig.endpoint, token);\n const forkedRepo = forks.find((repo) => repo.owner.login === username);\n if (forkedRepo) {\n logger.debug(`Found repo in user account: ${forkedRepo.full_name}`);\n return forkedRepo;\n }\n } catch {\n throw new Error(REPOSITORY_CANNOT_FORK);\n }\n logger.debug(`No repo found in user account`);\n return null;\n}\n\nexport async function createFork(\n token: string,\n repository: string,\n forkOrg?: string,\n): Promise<GhRestRepo> {\n let forkedRepo: GhRestRepo | undefined;\n try {\n forkedRepo = (\n await githubApi.postJson<GhRestRepo>(`repos/${repository}/forks`, {\n token,\n body: {\n organization: forkOrg ?? undefined,\n name: config.parentRepo!.replace('/', '-_-'),\n default_branch_only: true, // no baseBranchPatterns support yet\n },\n })\n ).body;\n } catch (err) {\n logger.debug({ err }, 'Error creating fork');\n }\n if (!forkedRepo) {\n throw new Error(REPOSITORY_CANNOT_FORK);\n }\n logger.info({ forkedRepo: forkedRepo.full_name }, 'Created forked repo');\n logger.debug(`Sleeping 30s after creating fork`);\n await setTimeout(30000);\n return forkedRepo;\n}\n\n// Initialize GitHub by getting base branch and SHA\nexport async function initRepo({\n repository,\n forkCreation,\n forkOrg,\n forkToken,\n gitUrl,\n renovateUsername,\n cloneSubmodules,\n cloneSubmodulesFilter,\n}: RepoParams): Promise<RepoResult> {\n logger.debug(`initRepo(\"${repository}\")`);\n // config is used by the platform api itself, not necessary for the app layer to know\n config = {\n repository,\n cloneSubmodules,\n cloneSubmodulesFilter,\n ignorePrAuthor: GlobalConfig.get('ignorePrAuthor'),\n mergeQueueEnabled: {},\n } as any;\n const opts = hostRules.find({\n hostType: 'github',\n url: platformConfig.endpoint,\n readOnly: true,\n });\n config.renovateUsername = renovateUsername;\n [config.repositoryOwner, config.repositoryName] = repository.split('/');\n let repo: GhRepo | undefined;\n let forkSshUrl: string | null = null;\n try {\n let infoQuery = repoInfoQuery;\n\n // GitHub Enterprise Server <3.3.0 doesn't support autoMergeAllowed and hasIssuesEnabled objects\n // TODO #22198\n if (\n platformConfig.isGhe &&\n // semver not null safe, accepts null and undefined\n semver.satisfies(platformConfig.gheVersion!, '<3.3.0')\n ) {\n infoQuery = infoQuery.replace(regEx(/\\n\\s*autoMergeAllowed\\s*\\n/), '\\n');\n infoQuery = infoQuery.replace(regEx(/\\n\\s*hasIssuesEnabled\\s*\\n/), '\\n');\n }\n\n // GitHub Enterprise Server <3.9.0 doesn't support hasVulnerabilityAlertsEnabled objects\n if (\n platformConfig.isGhe &&\n // semver not null safe, accepts null and undefined\n semver.satisfies(platformConfig.gheVersion!, '<3.9.0')\n ) {\n infoQuery = infoQuery.replace(\n regEx(/\\n\\s*hasVulnerabilityAlertsEnabled\\s*\\n/),\n '\\n',\n );\n }\n\n // GitHub Enterprise Server <3.12.0 doesn't support merge queues\n if (\n platformConfig.isGhe &&\n // semver not null safe, accepts null and undefined\n semver.satisfies(platformConfig.gheVersion!, '<3.12.0')\n ) {\n infoQuery = infoQuery.replace(\n regEx(/\\n\\s*mergeQueue\\s*\\{\\s*id\\s*\\}\\s*\\n/),\n '\\n',\n );\n }\n\n const res = await githubApi.requestGraphql<{\n repository: GhRepo;\n }>(infoQuery, {\n variables: {\n owner: config.repositoryOwner,\n name: config.repositoryName,\n ...(!config.ignorePrAuthor && { user: renovateUsername }),\n },\n readOnly: true,\n count: 1, // bypass graphql check\n });\n\n if (res?.errors) {\n if (res.errors.find((err) => err.type === 'RATE_LIMITED')) {\n logger.debug({ res }, 'GraphQL rate limit exceeded.');\n throw new Error(PLATFORM_RATE_LIMIT_EXCEEDED);\n }\n logger.debug({ res }, 'Unexpected GraphQL errors');\n throw new Error(PLATFORM_UNKNOWN_ERROR);\n }\n\n repo = res?.data?.repository;\n /* v8 ignore next -- defensive: GraphQL errors are handled above, a null repository is not mocked in specs */\n if (!repo) {\n logger.debug({ res }, 'No repository returned');\n throw new Error(REPOSITORY_NOT_FOUND);\n }\n /* v8 ignore next -- empty-repo detection via missing defaultBranchRef is not mocked in specs */\n if (!repo.defaultBranchRef?.name) {\n logger.debug(\n { res },\n 'No default branch returned - treating repo as empty',\n );\n throw new Error(REPOSITORY_EMPTY);\n }\n if (\n repo.nameWithOwner &&\n repo.nameWithOwner.toUpperCase() !== repository.toUpperCase()\n ) {\n logger.debug(\n { desiredRepo: repository, foundRepo: repo.nameWithOwner },\n 'Repository has been renamed',\n );\n throw new Error(REPOSITORY_RENAMED);\n }\n if (repo.isArchived) {\n logger.debug(\n 'Repository is archived - throwing error to abort renovation',\n );\n throw new Error(REPOSITORY_ARCHIVED);\n }\n // Use default branch as PR target unless later overridden.\n config.defaultBranch = repo.defaultBranchRef.name;\n // Base branch may be configured but defaultBranch is always fixed\n logger.debug(`${repository} default branch = ${config.defaultBranch}`);\n // GitHub allows administrators to block certain types of merge, so we need to check it\n if (repo.squashMergeAllowed) {\n config.mergeMethod = 'squash';\n } else if (repo.mergeCommitAllowed) {\n config.mergeMethod = 'merge';\n } else if (repo.rebaseMergeAllowed) {\n config.mergeMethod = 'rebase';\n } else {\n // This happens if we don't have Administrator read access, it is not a critical error\n logger.debug('Could not find allowed merge methods for repo');\n }\n config.autoMergeAllowed = repo.autoMergeAllowed;\n config.hasIssuesEnabled = repo.hasIssuesEnabled;\n config.hasVulnerabilityAlertsEnabled = repo.hasVulnerabilityAlertsEnabled;\n config.mergeQueueEnabled[config.defaultBranch] = isNonEmptyObject(\n repo.mergeQueue,\n );\n\n const recentIssues = Issue.array()\n .catch([])\n .parse(res?.data?.repository?.issues?.nodes);\n GithubIssueCache.addIssuesToReconcile(recentIssues);\n } catch (err) /* v8 ignore next -- initRepo error mapping needs failure shapes not mocked in specs */ {\n logger.debug({ err }, 'Caught initRepo error');\n if (\n err.message === REPOSITORY_ARCHIVED ||\n err.message === REPOSITORY_RENAMED ||\n err.message === REPOSITORY_NOT_FOUND\n ) {\n throw err;\n }\n if (err.statusCode === 403) {\n throw new Error(REPOSITORY_ACCESS_FORBIDDEN);\n }\n if (err.statusCode === 404) {\n throw new Error(REPOSITORY_NOT_FOUND);\n }\n if (err.message.startsWith('Repository access blocked')) {\n throw new Error(REPOSITORY_BLOCKED);\n }\n if (err.message === REPOSITORY_FORK_MODE_FORKED) {\n throw err;\n }\n if (err.message === REPOSITORY_FORKED) {\n throw err;\n }\n if (err.message === REPOSITORY_DISABLED) {\n throw err;\n }\n if (err.message === 'Response code 451 (Unavailable for Legal Reasons)') {\n throw new Error(REPOSITORY_ACCESS_FORBIDDEN);\n }\n logger.debug({ err }, 'Unknown GitHub initRepo error');\n throw err;\n }\n // This shouldn't be necessary, but occasional strange errors happened until it was added\n config.prList = null;\n\n if (forkToken) {\n logger.debug('Bot is in fork mode');\n if (repo.isFork) {\n logger.debug(\n `Forked repos cannot be processed when running with a forkToken, so this repo will be skipped`,\n );\n logger.debug(\n `Parent repo for this forked repo is ${repo.parent?.nameWithOwner}`,\n );\n throw new Error(REPOSITORY_FORKED);\n }\n config.forkOrg = forkOrg;\n config.forkToken = forkToken;\n // save parent name then delete\n config.parentRepo = config.repository;\n config.repository = null;\n let forkedRepo = await findFork(forkToken, repository, forkOrg);\n if (forkedRepo) {\n config.repository = forkedRepo.full_name;\n forkSshUrl = forkedRepo.ssh_url;\n const forkDefaultBranch = forkedRepo.default_branch;\n if (forkDefaultBranch !== config.defaultBranch) {\n const body = {\n ref: `refs/heads/${config.defaultBranch}`,\n sha: repo.defaultBranchRef.target.oid,\n };\n logger.debug(\n {\n defaultBranch: config.defaultBranch,\n forkDefaultBranch,\n body,\n },\n 'Fork has different default branch to parent, attempting to create branch',\n );\n try {\n await githubApi.postJson(`repos/${config.repository}/git/refs`, {\n body,\n token: forkToken,\n });\n logger.debug('Created new default branch in fork');\n } catch (err) /* v8 ignore next -- fork default-branch creation failures are not mocked in specs */ {\n if (err.response?.body?.message === 'Reference already exists') {\n logger.debug(\n `Branch ${config.defaultBranch} already exists in the fork`,\n );\n } else {\n logger.warn(\n { err, body: err.response?.body },\n 'Could not create parent defaultBranch in fork',\n );\n }\n }\n logger.debug(\n `Setting ${config.defaultBranch} as default branch for ${config.repository}`,\n );\n try {\n await githubApi.patchJson(`repos/${config.repository}`, {\n body: {\n name: config.repository.split('/')[1],\n default_branch: config.defaultBranch,\n },\n token: forkToken,\n });\n logger.debug('Successfully changed default branch for fork');\n } catch (err) /* v8 ignore next -- defensive: fork default-branch update failures are logged and swallowed, not simulated in specs */ {\n logger.warn({ err }, 'Could not set default branch');\n }\n }\n } else if (forkCreation) {\n logger.debug('Forked repo is not found - attempting to create it');\n forkedRepo = await createFork(forkToken, repository, forkOrg);\n config.repository = forkedRepo.full_name;\n forkSshUrl = forkedRepo.ssh_url;\n } else {\n logger.debug('Forked repo is not found and forkCreation is disabled');\n throw new Error(REPOSITORY_FORK_MISSING);\n }\n }\n\n let authToken: string | null;\n if (forkToken) {\n logger.debug('Using forkToken for git init');\n authToken = coerceToNull(config.forkToken);\n } /* v8 ignore next -- token-type detection depends on opts.token shapes not varied in specs */ else {\n const tokenType = opts.token?.startsWith('x-access-token:')\n ? 'app'\n : 'personal access';\n logger.debug(`Using ${tokenType} token for git init`);\n authToken = opts.token ?? null;\n }\n // endpoint is validated during initPlatform\n const parsedEndpoint = parseUrl(platformConfig.endpoint)!;\n const workingSshUrl = forkToken ? forkSshUrl : repo.sshUrl;\n const url = getRepoUrl(\n config.repository!,\n gitUrl,\n workingSshUrl,\n parsedEndpoint,\n authToken,\n );\n let upstreamUrl: string | undefined;\n if (forkCreation && config.parentRepo) {\n upstreamUrl = getRepoUrl(\n config.parentRepo,\n gitUrl,\n repo.sshUrl,\n parsedEndpoint,\n authToken,\n );\n }\n await git.initRepo({\n ...config,\n url,\n upstreamUrl,\n });\n const repoConfig: RepoResult = {\n defaultBranch: config.defaultBranch,\n isFork: repo.isFork === true,\n repoFingerprint: repoFingerprint(repo.id, platformConfig.endpoint),\n };\n return repoConfig;\n}\n\nasync function checkRulesetsForForceRebase(\n branchName: string,\n): Promise<boolean> {\n try {\n const rulesets = await getBranchRulesets(branchName);\n logger.trace(\n `Ruleset: Found ${rulesets.length} rulesets for branch ${branchName}`,\n );\n\n return rulesets.some((rule) => {\n if (\n rule.type === 'required_status_checks' &&\n rule.parameters?.strict_required_status_checks_policy === true\n ) {\n logger.debug(\n `Ruleset: strict required status checks found for ${branchName}`,\n );\n return true;\n }\n\n return false;\n });\n } catch (err) {\n handleBranchProtectionError('rulesets', err, branchName);\n return false;\n }\n}\n\nasync function checkBranchProtectionForForceRebase(\n branchName: string,\n): Promise<boolean> {\n try {\n const branchProtection = await getBranchProtection(branchName);\n logger.trace(`Found branch protection for branch ${branchName}`);\n\n const strictStatusChecks = branchProtection?.required_status_checks?.strict;\n if (strictStatusChecks) {\n logger.debug(\n `Branch protection: PRs must be up-to-date before merging for ${branchName}`,\n );\n return true;\n }\n return false;\n } catch (err) {\n handleBranchProtectionError('branch-protection', err, branchName);\n return false;\n }\n}\n\nexport async function getBranchForceRebase(\n branchName: string,\n): Promise<boolean> {\n config.branchForceRebase ??= {};\n\n const cachedResult = config.branchForceRebase[branchName];\n if (cachedResult !== undefined) {\n return cachedResult;\n }\n\n // Initialize to false before checking branch protection\n config.branchForceRebase[branchName] = false;\n\n // Check rulesets first (newer API)\n const hasRulesetForceRebase = await checkRulesetsForForceRebase(branchName);\n if (hasRulesetForceRebase) {\n config.branchForceRebase[branchName] = true;\n return true;\n }\n\n // Fall back to legacy branch protection\n const hasBranchProtectionForceRebase =\n await checkBranchProtectionForForceRebase(branchName);\n if (hasBranchProtectionForceRebase) {\n config.branchForceRebase[branchName] = true;\n }\n\n return config.branchForceRebase[branchName];\n}\n\nfunction handleBranchProtectionError(\n protection: 'branch-protection' | 'rulesets',\n err: any,\n branchName: string,\n): void {\n if (err.statusCode === 404) {\n logger.debug(`No ${protection} found for ${branchName}`);\n return;\n }\n\n const isUnauthorized =\n err.message === PLATFORM_INTEGRATION_UNAUTHORIZED || err.statusCode === 403;\n\n if (isUnauthorized) {\n logger.once.debug(\n `Branch protection: Do not have permissions to detect ${protection} for ${branchName}`,\n );\n return;\n }\n\n throw err;\n}\n\nfunction cachePr(pr?: GhPr | null): void {\n config.prList ??= [];\n // v8 ignore else -- TODO: add test #40625\n if (pr) {\n updatePrCache(pr);\n for (let idx = 0; idx < config.prList.length; idx += 1) {\n const cachedPr = config.prList[idx];\n if (cachedPr.number === pr.number) {\n config.prList[idx] = pr;\n return;\n }\n }\n config.prList.push(pr);\n }\n}\n\n// Fetch fresh Pull Request and cache it when possible\nasync function fetchPr(prNo: number): Promise<GhPr | null> {\n try {\n const { body: ghRestPr } = await githubApi.getJsonUnchecked<GhRestPr>(\n `repos/${config.parentRepo ?? config.repository}/pulls/${prNo}`,\n );\n const result = coerceRestPr(ghRestPr);\n cachePr(result);\n return result;\n } catch (err) {\n logger.warn({ err, prNo }, `GitHub fetchPr error`);\n return null;\n }\n}\n\n// Gets details for a PR\nexport async function getPr(prNo: number): Promise<GhPr | null> {\n if (!prNo) {\n return null;\n }\n const prList = await getPrList();\n let pr = prList.find(({ number }) => number === prNo) ?? null;\n if (pr) {\n logger.debug('Returning PR from cache');\n }\n pr ??= await fetchPr(prNo);\n return pr;\n}\n\nfunction matchesState(state: string, desiredState: string): boolean {\n if (desiredState === 'all') {\n return true;\n }\n if (desiredState.startsWith('!')) {\n return state !== desiredState.substring(1);\n }\n return state === desiredState;\n}\n\nexport async function getPrList(): Promise<GhPr[]> {\n if (!config.prList) {\n const repo = config.parentRepo ?? config.repository;\n\n let username = config.renovateUsername;\n if (config.forkToken || config.ignorePrAuthor) {\n username = undefined;\n }\n\n // TODO: check null `repo` (#22198)\n const prCache = await instrument('getPrCache', () =>\n getPrCache(githubApi, repo!, username),\n );\n config.prList = Object.values(prCache).sort(\n ({ number: a }, { number: b }) => b - a,\n );\n }\n\n return config.prList;\n}\n\nexport async function findPr({\n branchName,\n prTitle,\n state = 'all',\n includeOtherAuthors,\n}: FindPRConfig): Promise<GhPr | null> {\n logger.debug(`findPr(${branchName}, ${prTitle}, ${state})`);\n\n if (includeOtherAuthors) {\n const repo = config.parentRepo ?? config.repository;\n const org = repo?.split('/')[0];\n // PR might have been created by anyone, so don't use the cached Renovate PR list\n const { body: prList } = await githubApi.getJsonUnchecked<GhRestPr[]>(\n `repos/${repo}/pulls?head=${org}:${branchName}&state=open`,\n { cacheProvider: repoCacheProvider },\n );\n\n if (!prList.length) {\n logger.debug(`No PR found for branch ${branchName}`);\n return null;\n }\n\n return coerceRestPr(prList[0]);\n }\n\n const prList = await getPrList();\n const pr = prList.find((p) => {\n if (p.sourceBranch !== branchName) {\n return false;\n }\n\n if (prTitle && prTitle.toUpperCase() !== p.title.toUpperCase()) {\n return false;\n }\n\n if (!matchesState(p.state, state)) {\n return false;\n }\n\n if (!config.forkToken && !looseEquals(config.repository, p.sourceRepo)) {\n return false;\n }\n\n return true;\n });\n if (pr) {\n logger.debug(`Found PR #${pr.number}`);\n }\n return pr ?? null;\n}\n\nasync function ensureBranchSha(\n branchName: string,\n sha: LongCommitSha,\n): Promise<void> {\n const repository = config.repository!;\n try {\n const commitUrl = `/repos/${repository}/git/commits/${sha}`;\n await githubApi.head(commitUrl, { memCache: false });\n } catch (err) {\n logger.error({ err, sha, branchName }, 'Commit not found');\n throw err;\n }\n\n const refUrl = `/repos/${config.repository}/git/refs/heads/${branchName}`;\n const branchExists = await remoteBranchExists(repository, branchName);\n\n if (branchExists) {\n try {\n await githubApi.patchJson(refUrl, { body: { sha, force: true } });\n return;\n } catch (err) {\n if (err.err?.response?.statusCode === 422) {\n logger.debug(\n { err },\n 'Branch update failed due to reference not existing - will try to create',\n );\n } else {\n logger.warn({ refUrl, err }, 'Error updating branch');\n throw err;\n }\n }\n }\n\n await githubApi.postJson(`/repos/${repository}/git/refs`, {\n body: { sha, ref: `refs/heads/${branchName}` },\n });\n}\n\n// Returns the Pull Request for a branch. Null if not exists.\nexport async function getBranchPr(branchName: string): Promise<GhPr | null> {\n logger.debug(`getBranchPr(${branchName})`);\n\n const openPr = await findPr({\n branchName,\n state: 'open',\n });\n\n if (openPr) {\n return openPr;\n }\n\n return null;\n}\n\nexport async function tryReuseAutoclosedPr(\n autoclosedPr: Pr,\n newTitle: string,\n): Promise<Pr | null> {\n const { sha, number, sourceBranch: branchName } = autoclosedPr;\n try {\n await ensureBranchSha(branchName, sha!);\n logger.debug(`Recreated autoclosed branch ${branchName} with sha ${sha}`);\n } catch (err) {\n logger.debug(\n { err, branchName, sha, autoclosedPr },\n 'Could not recreate autoclosed branch - skipping reopen',\n );\n return null;\n }\n\n try {\n const { body: ghPr } = await githubApi.patchJson<GhRestPr>(\n `repos/${config.repository}/pulls/${number}`,\n {\n body: {\n state: 'open',\n title: newTitle,\n },\n },\n );\n logger.info(\n { branchName, oldTitle: autoclosedPr.title, newTitle, number },\n 'Successfully reopened autoclosed PR',\n );\n\n const result = coerceRestPr(ghPr);\n\n const localSha = git.getBranchCommit(branchName);\n // v8 ignore else -- TODO: add test #40625\n if (localSha && localSha !== sha) {\n await git.forcePushToRemote(branchName, 'origin');\n result.sha = localSha;\n }\n\n cachePr(result);\n return result;\n } catch {\n logger.debug('Could not reopen autoclosed PR');\n return null;\n }\n}\n\nasync function getStatus(\n branchName: string,\n useCache = true,\n): Promise<CombinedBranchStatus> {\n const branch = escapeHash(branchName);\n const url = `repos/${config.repository}/commits/${branch}/status`;\n\n const { body: status } =\n await githubApi.getJsonUnchecked<CombinedBranchStatus>(url, {\n memCache: useCache,\n cacheProvider: repoCacheProvider,\n });\n\n return status;\n}\n\n// Returns the combined status for a branch.\nexport async function getBranchStatus(\n branchName: string,\n internalChecksAsSuccess: boolean,\n): Promise<BranchStatus> {\n logger.debug(`getBranchStatus(${branchName})`);\n let commitStatus: CombinedBranchStatus;\n try {\n commitStatus = await getStatus(branchName);\n } catch (err) /* v8 ignore next -- 404-to-REPOSITORY_CHANGED mapping for deleted branches is not mocked in specs */ {\n if (err.statusCode === 404) {\n logger.debug(\n 'Received 404 when checking branch status, assuming that branch has been deleted',\n );\n throw new Error(REPOSITORY_CHANGED);\n }\n logger.debug('Unknown error when checking branch status');\n throw err;\n }\n logger.debug(\n { state: commitStatus.state, statuses: commitStatus.statuses },\n 'branch status check result',\n );\n if (commitStatus.statuses && !internalChecksAsSuccess) {\n commitStatus.statuses = commitStatus.statuses.filter(\n (status) =>\n status.state !== 'success' || !status.context?.startsWith('renovate/'),\n );\n // v8 ignore else -- TODO: add test #40625\n if (!commitStatus.statuses.length) {\n logger.debug(\n 'Successful checks are all internal renovate/ checks, so returning \"pending\" branch status',\n );\n commitStatus.state = 'pending';\n }\n }\n let checkRuns: { name: string; status: string; conclusion: string }[] = [];\n // API is supported in oldest available GHE version 2.19\n try {\n const checkRunsUrl = `repos/${config.repository}/commits/${escapeHash(\n branchName,\n )}/check-runs?per_page=100`;\n const opts = {\n headers: {\n accept: 'application/vnd.github.antiope-preview+json',\n },\n paginate: true,\n paginationField: 'check_runs',\n cacheProvider: memCacheProvider,\n };\n const checkRunsRaw = (\n await githubApi.getJsonUnchecked<{\n check_runs: { name: string; status: string; conclusion: string }[];\n }>(checkRunsUrl, opts)\n ).body;\n if (checkRunsRaw.check_runs?.length) {\n checkRuns = checkRunsRaw.check_runs.map((run) => ({\n name: run.name,\n status: run.status,\n conclusion: run.conclusion,\n }));\n logger.debug({ checkRuns }, 'check runs result');\n } /* v8 ignore next -- specs always mock a non-empty check_runs response */ else {\n logger.debug({ result: checkRunsRaw }, 'No check runs found');\n }\n } catch (err) /* v8 ignore next -- check-run permission errors (403) are mapped to empty results, not mocked in specs */ {\n if (err instanceof ExternalHostError) {\n throw err;\n }\n if (\n err.statusCode === 403 ||\n err.message === PLATFORM_INTEGRATION_UNAUTHORIZED\n ) {\n logger.debug('No permission to view check runs');\n } else {\n logger.warn({ err }, 'Error retrieving check runs');\n }\n }\n if (checkRuns.length === 0) {\n if (commitStatus.state === 'success') {\n return 'green';\n }\n if (commitStatus.state === 'failure') {\n return 'red';\n }\n return 'yellow';\n }\n if (\n commitStatus.state === 'failure' ||\n checkRuns.some((run) => run.conclusion === 'failure')\n ) {\n return 'red';\n }\n if (\n (commitStatus.state === 'success' || commitStatus.statuses.length === 0) &&\n checkRuns.every((run) =>\n ['skipped', 'neutral', 'success'].includes(run.conclusion),\n )\n ) {\n return 'green';\n }\n return 'yellow';\n}\n\nasync function getStatusCheck(\n branchName: string,\n useCache = true,\n): Promise<GhBranchStatus[]> {\n const branchCommit = git.getBranchCommit(branchName);\n\n const url = `repos/${config.repository}/commits/${branchCommit}/statuses`;\n\n const opts: GithubHttpOptions = useCache\n ? { cacheProvider: memCacheProvider }\n : { memCache: false };\n\n return (await githubApi.getJsonUnchecked<GhBranchStatus[]>(url, opts)).body;\n}\n\ntype GithubToRenovateStatusMapping = Record<string, BranchStatus>;\nconst githubToRenovateStatusMapping: GithubToRenovateStatusMapping = {\n success: 'green',\n error: 'red',\n failure: 'red',\n pending: 'yellow',\n};\n\nexport async function getBranchStatusCheck(\n branchName: string,\n context: string,\n): Promise<BranchStatus | null> {\n try {\n const res = await getStatusCheck(branchName);\n for (const check of res) {\n if (check.context === context) {\n return githubToRenovateStatusMapping[check.state] || 'yellow';\n }\n }\n return null;\n } catch (err) /* v8 ignore next -- 404-to-REPOSITORY_CHANGED mapping for missing commits is not mocked in specs */ {\n if (err.statusCode === 404) {\n logger.debug('Commit not found when checking statuses');\n throw new Error(REPOSITORY_CHANGED);\n }\n throw err;\n }\n}\n\nexport async function setBranchStatus({\n branchName,\n context,\n description,\n state,\n url: targetUrl,\n}: BranchStatusConfig): Promise<void> {\n /* v8 ignore next -- specs do not run setBranchStatus in forking mode */\n if (config.parentRepo) {\n logger.debug('Cannot set branch status when in forking mode');\n return;\n }\n const existingStatus = await getBranchStatusCheck(branchName, context);\n if (existingStatus === state) {\n return;\n }\n logger.debug({ branch: branchName, context, state }, 'Setting branch status');\n let url: string | undefined;\n try {\n const branchCommit = git.getBranchCommit(branchName);\n url = `repos/${config.repository}/statuses/${branchCommit}`;\n const renovateToGitHubStateMapping = {\n green: 'success',\n yellow: 'pending',\n red: 'failure',\n };\n const options: any = {\n state: renovateToGitHubStateMapping[state],\n description,\n context,\n };\n // v8 ignore else -- TODO: add test #40625\n if (targetUrl) {\n options.target_url = targetUrl;\n }\n await githubApi.postJson(url, { body: options });\n\n // update status cache\n await getStatus(branchName, false);\n await getStatusCheck(branchName, false);\n } catch (err) /* v8 ignore next -- defensive: status POST failures abort with REPOSITORY_CHANGED, not simulated in specs */ {\n logger.debug({ err, url }, 'Caught error setting branch status - aborting');\n throw new Error(REPOSITORY_CHANGED);\n }\n}\n\n// Issue\n\nasync function getIssues(): Promise<Issue[]> {\n const result = await githubApi.queryRepoField<unknown>(\n getIssuesQuery,\n 'issues',\n {\n variables: {\n owner: config.repositoryOwner,\n name: config.repositoryName,\n ...(!config.ignorePrAuthor && { user: config.renovateUsername }),\n },\n readOnly: true,\n },\n );\n\n logger.debug(`Retrieved ${result.length} issues`);\n return Issue.array().parse(result);\n}\n\nexport async function getIssueList(): Promise<Issue[]> {\n /* v8 ignore next -- specs initialize repos with issues enabled */\n if (config.hasIssuesEnabled === false) {\n return [];\n }\n let issueList = GithubIssueCache.getIssues();\n // v8 ignore else -- TODO: add test #40625\n if (!issueList) {\n logger.debug('Retrieving issueList');\n issueList = await getIssues();\n GithubIssueCache.setIssues(issueList);\n }\n return issueList;\n}\n\nexport async function getIssue(number: number): Promise<Issue | null> {\n if (config.hasIssuesEnabled === false) {\n return null;\n }\n try {\n const repo = config.parentRepo ?? config.repository;\n const { body: issue } = await githubApi.getJson(\n `repos/${repo}/issues/${number}`,\n {\n cacheProvider: repoCacheProvider,\n },\n Issue,\n );\n GithubIssueCache.updateIssue(issue);\n return issue;\n } catch (err) {\n logger.debug({ err, number }, 'Error getting issue');\n if (err.response?.statusCode === 410) {\n logger.debug(`Issue #${number} has been deleted`);\n GithubIssueCache.deleteIssue(number);\n }\n return null;\n }\n}\n\nexport async function findIssue(title: string): Promise<Issue | null> {\n logger.debug(`findIssue(${title})`);\n const [issue] = (await getIssueList()).filter(\n (i) => i.state === 'open' && i.title === title,\n );\n if (!issue) {\n return null;\n }\n logger.debug(`Found issue ${issue.number}`);\n return getIssue(issue.number);\n}\n\nasync function closeIssue(issueNumber: number): Promise<void> {\n logger.debug(`closeIssue(${issueNumber})`);\n const repo = config.parentRepo ?? config.repository;\n try {\n const { body: closedIssue } = await githubApi.patchJson(\n `repos/${repo}/issues/${issueNumber}`,\n { body: { state: 'closed' } },\n Issue,\n );\n GithubIssueCache.updateIssue(closedIssue);\n } catch (err) {\n const statusCode = err.response?.statusCode;\n if (statusCode === 404 || statusCode === 410) {\n logger.debug(\n `Issue #${issueNumber} no longer exists on the platform, removing from cache`,\n );\n GithubIssueCache.deleteIssue(issueNumber);\n return;\n }\n throw err;\n }\n}\n\nexport async function ensureIssue({\n title,\n reuseTitle,\n body: rawBody,\n labels,\n once = false,\n shouldReOpen = true,\n}: EnsureIssueConfig): Promise<EnsureIssueResult | null> {\n logger.debug(`ensureIssue(${title})`);\n /* v8 ignore next -- specs initialize repos with issues enabled */\n if (config.hasIssuesEnabled === false) {\n logger.info(\n 'Cannot ensure issue because issues are disabled in this repository',\n );\n return null;\n }\n const body = sanitize(rawBody);\n try {\n const issueList = await getIssueList();\n let issues = issueList.filter((i) => i.title === title);\n if (!issues.length) {\n issues = issueList.filter((i) => i.title === reuseTitle);\n if (issues.length) {\n logger.debug(`Reusing issue title: \"${reuseTitle}\"`);\n }\n }\n if (issues.length) {\n let issue = issues.find((i) => i.state === 'open');\n if (!issue) {\n if (once) {\n logger.debug('Issue already closed - skipping recreation');\n return null;\n }\n if (shouldReOpen) {\n logger.debug('Reopening previously closed issue');\n }\n issue = issues.at(-1)!;\n }\n for (const i of issues) {\n if (i.state === 'open' && i.number !== issue.number) {\n logger.warn({ issueNo: i.number }, 'Closing duplicate issue');\n await closeIssue(i.number);\n }\n }\n\n const repo = config.parentRepo ?? config.repository;\n const { body: serverIssue } = await githubApi.getJson(\n `repos/${repo}/issues/${issue.number}`,\n { cacheProvider: repoCacheProvider },\n Issue,\n );\n GithubIssueCache.updateIssue(serverIssue);\n\n if (\n issue.title === title &&\n serverIssue.body === body &&\n issue.state === 'open'\n ) {\n logger.debug('Issue is open and up to date - nothing to do');\n return null;\n }\n if (shouldReOpen || issue.state === 'open') {\n logger.debug('Patching issue');\n const data: Record<string, unknown> = { body, state: 'open', title };\n if (labels) {\n data.labels = labels;\n }\n const repo = config.parentRepo ?? config.repository;\n const { body: updatedIssue } = await githubApi.patchJson(\n `repos/${repo}/issues/${issue.number}`,\n { body: data },\n Issue,\n );\n GithubIssueCache.updateIssue(updatedIssue);\n logger.debug('Issue updated');\n return 'updated';\n }\n }\n const { body: createdIssue } = await githubApi.postJson(\n `repos/${config.parentRepo ?? config.repository}/issues`,\n {\n body: {\n title,\n body,\n labels: labels ?? [],\n },\n },\n Issue,\n );\n logger.info('Issue created');\n // reset issueList so that it will be fetched again as-needed\n GithubIssueCache.updateIssue(createdIssue);\n return 'created';\n } catch (err) /* v8 ignore next -- issue creation failure handling is not mocked in specs */ {\n if (err.body?.message?.startsWith('Issues are disabled for this repo')) {\n logger.debug(`Issues are disabled, so could not create issue: ${title}`);\n } else {\n logger.warn({ err }, 'Could not ensure issue');\n }\n }\n return null;\n}\n\nexport async function ensureIssueClosing(title: string): Promise<void> {\n logger.trace(`ensureIssueClosing(${title})`);\n /* v8 ignore next -- specs initialize repos with issues enabled */\n if (config.hasIssuesEnabled === false) {\n return;\n }\n const issueList = await getIssueList();\n for (const issue of issueList) {\n if (issue.state === 'open' && issue.title === title) {\n await closeIssue(issue.number);\n logger.debug(`Issue closed, issueNo: ${issue.number}`);\n }\n }\n}\n\nasync function tryAddMilestone(\n issueNo: number,\n milestoneNo: number | undefined,\n): Promise<void> {\n if (!milestoneNo) {\n return;\n }\n\n logger.debug(\n {\n milestone: milestoneNo,\n pr: issueNo,\n },\n 'Adding milestone to PR',\n );\n try {\n const repo = config.parentRepo ?? config.repository;\n const { body: updatedIssue } = await githubApi.patchJson(\n `repos/${repo}/issues/${issueNo}`,\n { body: { milestone: milestoneNo } },\n Issue,\n );\n GithubIssueCache.updateIssue(updatedIssue);\n } catch (err) {\n /* v8 ignore next -- defensive: the raw-error fallback is for non-HTTP failures not seen in specs */\n const actualError = err.response?.body ?? err;\n logger.warn(\n {\n milestone: milestoneNo,\n pr: issueNo,\n err: actualError,\n },\n 'Unable to add milestone to PR',\n );\n }\n}\n\nexport async function addAssignees(\n issueNo: number,\n assignees: string[],\n): Promise<void> {\n logger.debug(`Adding assignees '${assignees.join(', ')}' to #${issueNo}`);\n const repository = config.parentRepo ?? config.repository;\n const url = `repos/${repository}/issues/${issueNo}/assignees`;\n let lastErr: Error | undefined;\n for (let attempt = 0; attempt < 3; attempt += 1) {\n try {\n const { body: updatedIssue } = await githubApi.postJson(\n url,\n { body: { assignees } },\n Issue,\n );\n GithubIssueCache.updateIssue(updatedIssue);\n return;\n } catch (err) {\n if (err.statusCode !== 404) {\n throw err;\n }\n lastErr = err;\n logger.debug(\n { attempt: attempt + 1 },\n `Retrying addAssignees for #${issueNo} after 404`,\n );\n await setTimeout(1000);\n }\n }\n throw lastErr!;\n}\n\nexport async function addReviewers(\n prNo: number,\n reviewers: string[],\n): Promise<void> {\n logger.debug(`Adding reviewers '${reviewers.join(', ')}' to #${prNo}`);\n\n const userReviewers = reviewers.filter((e) => !e.startsWith('team:'));\n const teamReviewers = reviewers\n .filter((e) => e.startsWith('team:'))\n .map((e) => e.replace(regEx(/^team:/), ''));\n try {\n await githubApi.postJson(\n `repos/${\n config.parentRepo ?? config.repository\n }/pulls/${prNo}/requested_reviewers`,\n {\n body: {\n reviewers: userReviewers,\n team_reviewers: teamReviewers,\n },\n },\n );\n } catch (err) /* v8 ignore next -- defensive: reviewer assignment failures are logged and swallowed, not simulated in specs */ {\n logger.warn({ err }, 'Failed to assign reviewer');\n }\n}\n\nexport async function addLabels(\n issueNo: number,\n labels: string[] | null | undefined,\n): Promise<void> {\n logger.debug(`Adding labels '${labels?.join(', ')}' to #${issueNo}`);\n try {\n const repository = config.parentRepo ?? config.repository;\n if (isArray(labels) && labels.length) {\n await githubApi.postJson(`repos/${repository}/issues/${issueNo}/labels`, {\n body: labels,\n });\n }\n } catch (err) /* v8 ignore next -- defensive: label-adding failures are logged and swallowed, not simulated in specs */ {\n logger.warn(\n { err, issueNo, labels },\n 'Error while adding labels. Skipping',\n );\n }\n}\n\nexport async function deleteLabel(\n issueNo: number,\n label: string,\n): Promise<void> {\n logger.debug(`Deleting label ${label} from #${issueNo}`);\n const repository = config.parentRepo ?? config.repository;\n try {\n await githubApi.deleteJson(\n `repos/${repository}/issues/${issueNo}/labels/${label}`,\n );\n } catch (err) /* v8 ignore next -- defensive: label deletion failures are logged and swallowed, not simulated in specs */ {\n logger.warn({ err, issueNo, label }, 'Failed to delete label');\n }\n}\n\nasync function addComment(issueNo: number, body: string): Promise<void> {\n // POST /repos/:owner/:repo/issues/:number/comments\n await githubApi.postJson(\n `repos/${\n config.parentRepo ?? config.repository\n }/issues/${issueNo}/comments`,\n {\n body: { body },\n },\n );\n}\n\nasync function editComment(commentId: number, body: string): Promise<void> {\n // PATCH /repos/:owner/:repo/issues/comments/:id\n await githubApi.patchJson(\n `repos/${\n config.parentRepo ?? config.repository\n }/issues/comments/${commentId}`,\n {\n body: { body },\n },\n );\n}\n\nasync function deleteComment(commentId: number): Promise<void> {\n // DELETE /repos/:owner/:repo/issues/comments/:id\n await githubApi.deleteJson(\n `repos/${\n config.parentRepo ?? config.repository\n }/issues/comments/${commentId}`,\n );\n}\n\nasync function getComments(issueNo: number): Promise<Comment[]> {\n // GET /repos/:owner/:repo/issues/:number/comments\n logger.debug(`Getting comments for #${issueNo}`);\n const repo = config.parentRepo ?? config.repository;\n const url = `repos/${repo}/issues/${issueNo}/comments?per_page=100`;\n try {\n const { body: comments } = await githubApi.getJsonUnchecked<Comment[]>(\n url,\n {\n paginate: true,\n cacheProvider: repoCacheProvider,\n },\n );\n logger.debug(`Found ${comments.length} comments`);\n return comments;\n } catch (err) /* v8 ignore next -- comment-fetch 404s are wrapped as ExternalHostError, not mocked in specs */ {\n if (err.statusCode === 404) {\n logger.debug('404 response when retrieving comments');\n throw new ExternalHostError(err, 'github');\n }\n throw err;\n }\n}\n\nexport async function ensureComment({\n number,\n topic,\n content,\n}: EnsureCommentConfig): Promise<boolean> {\n const sanitizedContent = sanitize(content);\n try {\n const comments = await getComments(number);\n let body: string;\n let commentId: number | null = null;\n let commentNeedsUpdating = false;\n if (topic) {\n logger.debug(`Ensuring comment \"${topic}\" in #${number}`);\n body = `### ${topic}\\n\\n${sanitizedContent}`;\n comments.forEach((comment) => {\n if (comment.body.startsWith(`### ${topic}\\n\\n`)) {\n commentId = comment.id;\n commentNeedsUpdating = comment.body !== body;\n }\n });\n } else {\n logger.debug(`Ensuring content-only comment in #${number}`);\n body = `${sanitizedContent}`;\n comments.forEach((comment) => {\n // v8 ignore else -- TODO: add test #40625\n if (comment.body === body) {\n commentId = comment.id;\n commentNeedsUpdating = false;\n }\n });\n }\n if (!commentId) {\n await addComment(number, body);\n logger.info(\n { repository: config.repository, issueNo: number, topic },\n 'Comment added',\n );\n } else if (commentNeedsUpdating) {\n await editComment(commentId, body);\n logger.debug(\n { repository: config.repository, issueNo: number },\n 'Comment updated',\n );\n } else {\n logger.debug('Comment is already up-to-date');\n }\n return true;\n } catch (err) /* v8 ignore next -- comment API failure handling (locked issues) is not mocked in specs */ {\n if (err instanceof ExternalHostError) {\n throw err;\n }\n if (err.body?.message?.includes('is locked')) {\n logger.debug('Issue is locked - cannot add comment');\n } else {\n logger.warn({ err }, 'Error ensuring comment');\n }\n return false;\n }\n}\n\nfunction byTopic(comment: Comment, topic: string): boolean {\n return comment.body.startsWith(`### ${topic}\\n\\n`);\n}\n\nfunction byContent(comment: Comment, content: string): boolean {\n return comment.body.trim() === content;\n}\n\nexport async function ensureCommentRemoval(\n deleteConfig: EnsureCommentRemovalConfig,\n): Promise<void> {\n const { number: issueNo } = deleteConfig;\n const key =\n deleteConfig.type === 'by-topic'\n ? deleteConfig.topic\n : deleteConfig.content;\n logger.trace(`Ensuring comment \"${key}\" in #${issueNo} is removed`);\n const comments = await getComments(issueNo);\n let commentId: number | null | undefined = null;\n\n // v8 ignore else -- TODO: add test #40625\n if (deleteConfig.type === 'by-topic') {\n const topic = deleteConfig.topic;\n commentId = comments.find((comment) => byTopic(comment, topic))?.id;\n } else if (deleteConfig.type === 'by-content') {\n const content = deleteConfig.content;\n commentId = comments.find((comment) => byContent(comment, content))?.id;\n }\n\n try {\n // v8 ignore else -- TODO: add test #40625\n if (commentId) {\n logger.debug(`Removing comment from issueNo: ${issueNo}`);\n await deleteComment(commentId);\n }\n } catch (err) /* v8 ignore next -- defensive: comment deletion failures are logged and swallowed, not simulated in specs */ {\n logger.warn({ err }, 'Error deleting comment');\n }\n}\n\n// Pull Request\n\nasync function tryPrAutomerge(\n prNumber: number,\n prNodeId: string,\n platformPrOptions: PlatformPrOptions | undefined,\n): Promise<void> {\n if (!platformPrOptions?.usePlatformAutomerge) {\n return;\n }\n\n // If GitHub Enterprise Server <3.3.0 it doesn't support automerge\n // TODO #22198\n // semver not null safe, accepts null and undefined\n if (\n platformConfig.isGhe &&\n semver.satisfies(platformConfig.gheVersion!, '<3.3.0')\n ) {\n logger.debug(\n { prNumber },\n 'GitHub-native automerge: not supported on this version of GHE. Use 3.3.0 or newer.',\n );\n return;\n }\n\n if (!config.autoMergeAllowed) {\n logger.debug(\n { prNumber },\n 'GitHub-native automerge: not enabled in repo settings',\n );\n return;\n }\n\n try {\n const mergeMethod =\n (\n mapMergeStartegy(platformPrOptions.automergeStrategy) ??\n config.mergeMethod\n )?.toUpperCase() || 'MERGE';\n\n let commitHeadline: string | undefined;\n let commitBody: string | undefined;\n // For SQUASH and MERGE methods, pass the commit message explicitly to avoid\n // GitHub using the PR description as the commit body when \"Use PR title and\n // body as commit message\" is enabled in repository settings.\n const automergeCommitMessage = platformPrOptions?.automergeCommitMessage;\n if (mergeMethod !== 'REBASE' && automergeCommitMessage) {\n const newlineIndex = automergeCommitMessage.indexOf('\\n');\n if (newlineIndex === -1) {\n commitHeadline = automergeCommitMessage;\n } else {\n commitHeadline = automergeCommitMessage.slice(0, newlineIndex);\n commitBody = automergeCommitMessage.slice(newlineIndex + 1).trim();\n }\n\n // Add PR number to the commit headline to match the default GitHub behavior\n commitHeadline = `${commitHeadline} (#${prNumber})`;\n }\n\n const variables = {\n pullRequestId: prNodeId,\n mergeMethod,\n commitHeadline,\n commitBody,\n };\n // set count to one bypass graphql check\n const queryOptions = { variables, count: 1 };\n\n const res = await githubApi.requestGraphql<GhAutomergeResponse>(\n enableAutoMergeMutation,\n queryOptions,\n );\n\n if (res?.errors) {\n logger.debug(\n { prNumber, errors: res.errors },\n 'GitHub-native automerge: fail',\n );\n return;\n }\n\n logger.debug(`GitHub-native automerge: success...PrNo: ${prNumber}`);\n } catch (err) /* v8 ignore next: missing test #22198 */ {\n logger.warn({ prNumber, err }, 'GitHub-native automerge: REST API error');\n }\n}\n\n// Creates PR and returns PR number\nexport async function createPr({\n sourceBranch,\n targetBranch,\n prTitle: title,\n prBody: rawBody,\n labels,\n draftPR = false,\n platformPrOptions,\n milestone,\n}: CreatePRConfig): Promise<GhPr | null> {\n const body = sanitize(rawBody);\n const base = targetBranch;\n // Include the repository owner to handle forkToken and regular mode\n // TODO: can `repository` be null? (#22198)\n\n const head = `${config.repository!.split('/')[0]}:${sourceBranch}`;\n const options: any = {\n body: {\n title,\n head,\n base,\n body,\n draft: draftPR,\n },\n };\n /* v8 ignore next -- fork mode is not exercised in createPr specs */\n if (config.forkToken) {\n options.token = config.forkToken;\n options.body.maintainer_can_modify =\n !config.forkOrg &&\n platformPrOptions?.forkModeDisallowMaintainerEdits !== true;\n }\n logger.debug({ title, head, base, draft: draftPR }, 'Creating PR');\n const ghPr = (\n await githubApi.postJson<GhRestPr>(\n `repos/${config.parentRepo ?? config.repository}/pulls`,\n options,\n )\n ).body;\n logger.debug(\n { branch: sourceBranch, pr: ghPr.number, draft: draftPR },\n 'PR created',\n );\n\n const result = coerceRestPr(ghPr);\n const { number, node_id } = result;\n\n await addLabels(number, labels);\n await tryAddMilestone(number, milestone);\n await tryPrAutomerge(number, node_id, platformPrOptions);\n\n cachePr(result);\n return result;\n}\n\nasync function isMergeQueueEnabled(baseBranch: string): Promise<boolean> {\n const cachedResult = config.mergeQueueEnabled[baseBranch];\n if (cachedResult !== undefined) {\n return cachedResult;\n }\n\n // TODO #22198\n // semver not null safe, accepts null and undefined\n if (\n platformConfig.isGhe &&\n semver.satisfies(platformConfig.gheVersion!, '<3.12.0')\n ) {\n // Merge queues are only supported on GHES >=3.12.0\n config.mergeQueueEnabled[baseBranch] = false;\n return false;\n }\n\n // Assume enabled unless proven otherwise, so the merge queue check is not\n // skipped by mistake\n let result = true;\n try {\n const res = await githubApi.requestGraphql<{\n repository: { mergeQueue: { id: string } | null };\n }>(repoMergeQueueQuery, {\n variables: {\n owner: config.repositoryOwner,\n name: config.repositoryName,\n branch: baseBranch,\n },\n readOnly: true,\n count: 1, // bypass graphql check\n });\n if (res?.errors) {\n logger.debug(\n { baseBranch, errors: res.errors },\n 'Failed to fetch merge queue status - assuming merge queue is enabled',\n );\n } else {\n result = isNonEmptyObject(res?.data?.repository?.mergeQueue);\n }\n } catch (err) {\n logger.debug(\n { baseBranch, err },\n 'Error fetching merge queue status - assuming merge queue is enabled',\n );\n }\n\n config.mergeQueueEnabled[baseBranch] = result;\n return result;\n}\n\nexport async function assertPrNotInMergeQueue(\n branchName: string,\n baseBranch?: string,\n): Promise<void> {\n if (!(await isMergeQueueEnabled(baseBranch ?? config.defaultBranch))) {\n return;\n }\n\n const pr = await findPr({ branchName, state: 'open' });\n if (!pr) {\n return;\n }\n\n if (\n await isPrInMergeQueue(\n githubApi,\n config.repositoryOwner,\n config.repositoryName,\n pr.number,\n )\n ) {\n logger.debug(`PR #${pr.number} is in the merge queue - aborting push`);\n throw new Error(PR_ALREADY_IN_MERGE_QUEUE);\n }\n}\n\nexport async function updatePr({\n number: prNo,\n prTitle: title,\n prBody: rawBody,\n addLabels: labelsToAdd,\n removeLabels,\n state,\n targetBranch,\n}: UpdatePrConfig): Promise<void> {\n logger.debug(`updatePr(${prNo}, ${title}, body)`);\n const body = sanitize(rawBody);\n const patchBody: any = { title };\n // v8 ignore else -- TODO: add test #40625\n if (body) {\n patchBody.body = body;\n }\n if (targetBranch) {\n patchBody.base = targetBranch;\n }\n if (state) {\n patchBody.state = state;\n }\n const options: any = {\n body: patchBody,\n };\n /* v8 ignore next -- fork mode is not exercised in updatePr specs */\n if (config.forkToken) {\n options.token = config.forkToken;\n }\n\n // Update PR labels\n try {\n if (labelsToAdd) {\n await addLabels(prNo, labelsToAdd);\n }\n\n if (removeLabels) {\n for (const label of removeLabels) {\n await deleteLabel(prNo, label);\n }\n }\n\n const { body: ghPr } = await githubApi.patchJson<GhRestPr>(\n `repos/${config.parentRepo ?? config.repository}/pulls/${prNo}`,\n options,\n );\n const result = coerceRestPr(ghPr);\n cachePr(result);\n logger.debug(`PR updated...prNo: ${prNo}`);\n } catch (err) /* v8 ignore next -- non-host update failures are logged and swallowed, not mocked in specs */ {\n if (err instanceof ExternalHostError) {\n throw err;\n }\n logger.warn({ err }, 'Error updating PR');\n }\n}\n\nexport async function reattemptPlatformAutomerge({\n number,\n platformPrOptions,\n}: ReattemptPlatformAutomergeConfig): Promise<void> {\n try {\n const result = (await getPr(number))!;\n const { node_id } = result;\n\n await tryPrAutomerge(number, node_id, platformPrOptions);\n\n logger.debug(`PR platform automerge re-attempted...prNo: ${number}`);\n } catch (err) /* v8 ignore next -- defensive: automerge re-attempt failures are logged and swallowed, not simulated in specs */ {\n logger.warn({ err }, 'Error re-attempting PR platform automerge');\n }\n}\n\nexport async function mergePr({\n branchName,\n id: prNo,\n strategy,\n}: MergePRConfig): Promise<boolean> {\n logger.debug(`mergePr(${prNo}, ${branchName})`);\n const url = `repos/${\n config.parentRepo ?? config.repository\n }/pulls/${prNo}/merge`;\n const options: GithubHttpOptions = {\n body: {},\n };\n /* v8 ignore next -- fork mode is not exercised in mergePr specs */\n if (config.forkToken) {\n options.token = config.forkToken;\n }\n let automerged = false;\n let automergeResult: HttpResponse<unknown>;\n const mergeStrategy = mapMergeStartegy(strategy) ?? config.mergeMethod;\n\n // v8 ignore else -- TODO: add test #40625\n if (mergeStrategy) {\n // This path is taken if we have auto-detected the allowed merge types from the repo or\n // automergeStrategy is configured by user\n options.body.merge_method = mergeStrategy;\n try {\n logger.debug({ options, url }, `mergePr`);\n automergeResult = await githubApi.putJson(url, options);\n automerged = true;\n } catch (err) /* v8 ignore next -- merge rejection handling (404/405 status-check bodies) is not fully mocked in specs */ {\n if (err.statusCode === 404 || err.statusCode === 405) {\n const body = err.response?.body;\n if (\n isNonEmptyString(body?.message) &&\n regEx(/^Required status check \".+\" is expected\\.$/).test(body.message)\n ) {\n logger.debug(\n { response: body },\n `GitHub blocking PR merge -- Missing required status check(s)`,\n );\n return false;\n }\n if (\n isNonEmptyString(body?.message) &&\n (body.message.includes('approving review') ||\n body.message.includes('code owner review') ||\n body.message.includes(\n 'New changes require approval from someone other than the last pusher',\n ))\n ) {\n logger.debug(\n { response: body },\n `GitHub blocking PR merge -- Needs approving review(s)`,\n );\n return false;\n }\n logger.debug(\n { response: body },\n 'GitHub blocking PR merge -- will keep trying',\n );\n } else {\n logger.warn(\n { mergeMethod: config.mergeMethod, err },\n 'Failed to merge PR',\n );\n return false;\n }\n }\n }\n if (!automerged) {\n // We need to guess the merge method and try squash -> merge -> rebase\n options.body.merge_method = 'squash';\n try {\n logger.debug({ options, url }, `mergePr`);\n automergeResult = await githubApi.putJson(url, options);\n } catch (err1) {\n logger.debug({ err: err1 }, `Failed to squash merge PR`);\n try {\n options.body.merge_method = 'merge';\n logger.debug({ options, url }, `mergePr`);\n automergeResult = await githubApi.putJson(url, options);\n } catch (err2) {\n logger.debug({ err: err2 }, `Failed to merge commit PR`);\n try {\n options.body.merge_method = 'rebase';\n logger.debug({ options, url }, `mergePr`);\n automergeResult = await githubApi.putJson(url, options);\n } catch (err3) {\n logger.debug({ err: err3 }, `Failed to rebase merge PR`);\n logger.info({ pr: prNo }, 'All merge attempts failed');\n return false;\n }\n }\n }\n }\n logger.debug(\n { automergeResult: automergeResult!.body, pr: prNo },\n 'PR merged',\n );\n const cachedPr = config.prList?.find(({ number }) => number === prNo);\n if (cachedPr) {\n cachePr({ ...cachedPr, state: 'merged' });\n }\n return true;\n}\n\nexport function massageMarkdown(input: string): string {\n if (platformConfig.isGhe) {\n return smartTruncate(input, maxBodyLength());\n }\n const massagedInput = massageMarkdownLinks(input)\n // to be safe, replace all github.com links with redirect.github.com\n .replace(\n regEx(/href=\"https?:\\/\\/github.com\\//g),\n 'href=\"https://redirect.github.com/',\n )\n .replace(\n regEx(/]\\(https:\\/\\/github\\.com\\//g),\n '](https://redirect.github.com/',\n )\n .replace(\n regEx(/]: https:\\/\\/github\\.com\\//g),\n ']: https://redirect.github.com/',\n )\n .replaceAll('> ℹ **Note**\\n> \\n', '> [!NOTE]\\n')\n .replaceAll('> ℹ️ **Note**\\n> \\n', '> [!NOTE]\\n')\n .replaceAll('> ⚠ **Warning**\\n> \\n', '> [!WARNING]\\n')\n .replaceAll('> ⚠️ **Warning**\\n> \\n', '> [!WARNING]\\n')\n .replaceAll('> ❗ **Caution**\\n> \\n', '> [!CAUTION]\\n')\n .replaceAll('> ❗ **Important**\\n> \\n', '> [!IMPORTANT]\\n');\n return smartTruncate(massagedInput, maxBodyLength());\n}\n\nexport function maxBodyLength(): number {\n return GitHubMaxPrBodyLen;\n}\n\nexport async function getVulnerabilityAlerts(): Promise<GithubVulnerabilityAlerts> {\n /* v8 ignore next -- specs initialize repos with vulnerability alerts enabled */\n if (config.hasVulnerabilityAlertsEnabled === false) {\n logger.debug('No vulnerability alerts enabled for repo');\n return [];\n }\n let vulnerabilityAlerts: GithubVulnerabilityAlerts | undefined;\n try {\n vulnerabilityAlerts = (\n await githubApi.getJson(\n `/repos/${config.repositoryOwner}/${config.repositoryName}/dependabot/alerts?state=open&direction=asc&per_page=100`,\n {\n paginate: true,\n headers: { accept: 'application/vnd.github+json' },\n cacheProvider: repoCacheProvider,\n },\n GithubVulnerabilityAlerts,\n )\n ).body;\n } catch (err) /* v8 ignore next -- alert-permission failures are logged and swallowed, not mocked in specs */ {\n logger.debug({ err }, 'Error retrieving vulnerability alerts');\n logger.warn(\n {\n url: `${GlobalConfig.get('productLinks').documentation}configuration-options/#vulnerabilityalerts`,\n },\n 'Cannot access vulnerability alerts. Please ensure permissions have been granted.',\n );\n }\n try {\n if (vulnerabilityAlerts?.length) {\n const shortAlerts: AggregatedVulnerabilities = {};\n logger.trace(\n { alerts: vulnerabilityAlerts },\n 'GitHub vulnerability details',\n );\n for (const alert of vulnerabilityAlerts) {\n // v8 ignore if -- TODO: can never happen but makes typescript happy #40625\n if (alert.security_vulnerability === null) {\n // As described in the documentation, there are cases in which\n // GitHub API responds with `\"securityVulnerability\": null`.\n // But it's may be faulty, so skip processing it here.\n continue;\n }\n const {\n package: { name, ecosystem },\n vulnerable_version_range: vulnerableVersionRange,\n first_patched_version: firstPatchedVersion,\n } = alert.security_vulnerability;\n const patch = firstPatchedVersion?.identifier;\n\n const normalizedName =\n ecosystem === 'pip' ? normalizePythonDepName(name) : name;\n alert.security_vulnerability.package.name = normalizedName;\n const key = `${ecosystem.toLowerCase()}/${normalizedName}`;\n const range = vulnerableVersionRange;\n const elem = shortAlerts[key] || {};\n elem[range] = coerceToNull(patch);\n shortAlerts[key] = elem;\n }\n logger.debug({ alerts: shortAlerts }, 'GitHub vulnerability details');\n } else {\n logger.debug('No vulnerability alerts found');\n }\n } catch (err) /* v8 ignore next -- defensive: processing already-parsed alerts does not throw in specs */ {\n logger.error({ err }, 'Error processing vulnerabity alerts');\n }\n return vulnerabilityAlerts ?? [];\n}\n\nasync function pushFiles(\n { branchName, message, trailers }: CommitFilesConfig,\n { parentCommitSha, commitSha }: CommitResult,\n): Promise<LongCommitSha | null> {\n try {\n // Hybrid git/REST commit strategy (see #13824, #14271):\n // 1. The git push below uploads blobs to GitHub via a custom ref\n // (refs/renovate/branches/*) which does NOT trigger CI/Actions.\n // 2. We then recreate the tree+commit via REST API so that:\n // - The commit is signed by GitHub (\"committed via GitHub\" badge)\n // - Force-push and file mode bits are supported (GraphQL can't do this)\n // - We can use base_tree to send only changed files, avoiding org\n // ruleset file-path restrictions on unchanged files (#42554)\n // Reusing the pushed commit/tree SHAs directly does not work because\n // the branch ref must point to an API-created commit for signing.\n await pushCommitToRenovateRef(commitSha, branchName);\n const baseTreeSha = await getCommitTreeSha(parentCommitSha);\n const treeItems = await diffCommitTree(parentCommitSha, commitSha);\n\n if (treeItems.length === 0) {\n logger.debug(\n { branchName },\n 'Platform-native commit: no changed files between commits',\n );\n return null;\n }\n\n const treeRes = await githubApi.postJson<{ sha: string }>(\n `/repos/${config.repository}/git/trees`,\n { body: { base_tree: baseTreeSha, tree: treeItems } },\n );\n const treeSha = treeRes.body.sha;\n\n const commitMessage = formatCommitMessage(message, trailers);\n\n // Now we recreate the commit using the tree we recreated the step before\n const commitRes = await githubApi.postJson<{ sha: string }>(\n `/repos/${config.repository}/git/commits`,\n {\n body: {\n message: commitMessage,\n tree: treeSha,\n parents: [parentCommitSha],\n },\n },\n );\n incLimitedValue('Commits');\n const remoteCommitSha = toLongCommitSha(commitRes.body.sha);\n await ensureBranchSha(branchName, remoteCommitSha);\n return remoteCommitSha;\n } catch (err) {\n logger.debug({ branchName, err }, 'Platform-native commit: unknown error');\n return null;\n }\n}\n\nexport async function commitFiles(\n config: CommitFilesConfig,\n): Promise<LongCommitSha | null> {\n const commitResult = await git.prepareCommit(config); // Commit locally and don't push\n const { branchName, files } = config;\n if (!commitResult) {\n logger.debug(\n { branchName, files: files.map(({ path }) => path) },\n `Platform-native commit: unable to prepare for commit`,\n );\n return null;\n }\n // Perform the commits using REST API\n const pushResult = await pushFiles(config, commitResult);\n if (!pushResult) {\n return null;\n }\n // Replace locally created branch with the remotely created one\n // and return the remote commit SHA\n await git.resetToCommit(commitResult.parentCommitSha);\n const commitSha = await git.fetchBranch(branchName);\n return commitSha;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA8GA,MAAa,KAAK;AAElB,IAAI;AACJ,IAAI;AAGJ,MAAM,qBAAqB;AAE3B,SAAgB,eAAqB;CACnC,SAAS,CAAC;CACV,iBAAiB;EACf,UAAU;EACV,UAAU;CACZ;AACF;AAEA,aAAa;AAEb,SAAS,WAAW,OAAuB;CACzC,OAAO,OAAO,QAAQ,MAAM,IAAI,GAAG,KAAK;AAC1C;AAEA,SAAgB,UAAmB;CACjC,OAAO,CAAC,CAAC,eAAe;AAC1B;AAEA,eAAsB,UAAU,OAA8B;CAC5D,MAAM,iBAAiB,SAAS,eAAe,QAAQ;;CAEvD,IAAI,CAAC,gBACH,MAAM,IAAI,MAAM,4BAA4B,eAAe,UAAU;CAEvE,MAAM,OAAO,eAAe;CAC5B,eAAe,QAAQ,SAAS;CAChC,eAAe,aAAa,KAAK,SAAS,UAAU;CACpD,IAAI,eAAe,OAAO;EACxB,MAAM,eAAe;EACrB,MAAM,cAAc,MAAM,UAAU,SAAS,KAAK,EAAE,MAAM,CAAC;EAC3D,MAAM,aAAa,aAAa,aAAa,OAAO;EACpD,MAAM,GAAG,cACP,OAAO,QAAQ,UAAU,CAAC,CAAC,MACxB,CAAC,OAAO,EAAE,YAAY,MAAM,YAC/B,KAAK,CAAC;EACR,eAAe,aAAa,OAAO,MAAM,UAAoB,KAAK;EAClE,OAAO,MACL,+CAA+C,eAAe,YAChE;CACF;AACF;AAEA,eAAsB,aAAa,EACjC,UACA,OAAO,eACP,UACA,aAC0C;CAC1C,IAAI,QAAQ;CACZ,IAAI,CAAC,OACH,MAAM,IAAI,MAAM,yCAAyC;CAE3D,QAAQ,MAAM,QAAQ,MAAM,OAAO,GAAG,qBAAqB;CAC3D,eAAe,UAAU,MAAM,WAAW,iBAAiB;CAE3D,IAAI,UAAU;EACZ,IAAI,CAAC,UAAU,QAAQ,GACrB,MAAM,IAAI,MAAM,sCAAsC,UAAU;EAElE,eAAe,WAAW,oBAAoB,QAAQ;EACtD,WAAsB,eAAe,QAAQ;CAC/C,OACE,OAAO,MAAM,kCAAkC,eAAe,UAAU;CAG1E,MAAM,UAAU,KAAK;;;;;CAKrB,IACE,uCAAuC,KAAK,KAC5C,eAAe,UACd,CAAC,eAAe,cACf,OAAO,GAAG,eAAe,YAAY,QAAQ,IAE/C,MAAM,IAAI,MACR,uIACF;CAGF,IAAI;CACJ,IAAI,UACF,mBAAmB;MACd,IAAI,eAAe,SAAS;EACjC,eAAe,gBAAgB,MAAM,cAAc,KAAK;EACxD,mBAAmB,eAAe,YAAY;CAChD,OAAO;EACL,eAAe,gBAAgB,MAAM,eACnC,eAAe,UACf,KACF;EACA,mBAAmB,eAAe,YAAY;CAChD;CAEA,IAAI;;CAEJ,IAAI,eAAe,YACjB,aAAa;MACR,IAAI,eAAe,OAGxB,aADuB,SAAS,eAAe,QACrB,CAAC,CAAC;MAE5B,aAAa;CAGf,IAAI;CACJ,IAAI,CAAC,WAAW;EACd,IAAI,eAAe,SAAS;GAC1B,eAAe,gBAAgB,MAAM,cAAc,KAAK;GACxD,sBAAsB,GAAG,eAAe,YAAY,KAAK,IAAI,eAAe,YAAY,GAAG,GAAG,eAAe,YAAY,SAAS,iBAAiB,WAAW;EAChK,OAAO;GACL,eAAe,gBAAgB,MAAM,eACnC,eAAe,UACf,KACF;;GAEA,eAAe,YACb,eAAe,YAAY,SAC1B,MAAM,aAAa,eAAe,UAAU,KAAK;GACpD,IAAI,eAAe,WACjB,sBAAsB,GAAG,eAAe,YAAY,KAAK,IAAI,eAAe,UAAU;EAE1F;CACF;CAEA,0BAA8B,CAAC,WAAW,YAAY,CAAC;CAEvD,OAAO,MAAM;EAAE;EAAgB;CAAiB,GAAG,iBAAiB;CACpE,MAAM,iBAAiC;EACrC,UAAU,eAAe;EACzB,WAAW,aAAa;EACxB;EACA;CACF;CAEA,4BAA4B,eAAe,WAAW,eAAe,KAAK;CAE1E,IACE,OAAO,CAAC,CAAC,gCACT,eAAe,aAAa,2BAC5B;EACA,OAAO,MAAM,sCAAsC;EACnD,eAAe,YAAY,CACzB;GACE,WAAW;GACX,UAAU;GACV,UAAU;GACV,UAAU,MAAM,QAAQ,MAAM,kBAAkB,GAAG,EAAE;EACvD,CACF;EACA,OAAO,MAAM,uDAAuD;EACpE,eAAe,UAAU,KAAK;GAC5B,WAAW;GACX,UAAU;GACV,OAAO,MAAM,QAAQ,MAAM,kBAAkB,GAAG,EAAE;EACpD,CAAC;EAED,KAAK,MAAM,YAAY;GADY;GAAY;GAAS;EACT,GAAG;GAChD,OAAO,MACL,0BAA0B,SAAS,yBACrC;GACA,eAAe,UAAU,KAAK;IAC5B;IACA,WAAW,GAAG,SAAS;IACvB,UAAU;IACV,UAAU,MAAM,QAAQ,MAAM,kBAAkB,GAAG,EAAE;GACvD,CAAC;EACH;CACF;CACA,OAAO;AACT;AAEA,eAAe,oBAA2C;CACxD,IAAI;EACF,IAAI,QAAQ,GAOV,QAAO,MANW,UAAU,iBAEzB,0CAA0C;GAC3C,iBAAiB;GACjB,UAAU;EACZ,CAAC,EAAA,CACU,KAAK;EAMlB,QAAO,MAJW,UAAU,iBAC1B,2BACA,EAAE,UAAU,MAAM,CACpB,EAAA,CACW;CACb,SAAS,8GAA8G;EACrH,OAAO,MAAM,EAAE,IAAI,GAAG,uBAAuB;EAC7C,MAAM;CACR;AACF;AAGA,eAAsB,SAAS,QAAgD;CAC7E,OAAO,MAAM,qCAAqC;CAClD,MAAM,wBAAwB,MAAM,kBAAkB,EAAA,CAAG,OACvD,gBACF;CACA,MAAM,0BAA0B,qBAAqB,QAClD,SAAS,CAAC,KAAK,QAClB;CACA,IAAI,wBAAwB,SAAS,qBAAqB,QACxD,OAAO,MACL,gBACE,qBAAqB,SAAS,wBAAwB,OACvD,uBACH;CAEF,IAAI,CAAC,QAAQ,QACX,OAAO,wBAAwB,KAAK,SAAS,KAAK,SAAS;CAG7D,OAAO,MAAM,EAAE,QAAQ,OAAO,OAAO,GAAG,qBAAqB;CAC7D,MAAM,oBAAoB,wBAAwB,QAAQ,SACxD,KAAK,QAAQ,MAAM,UAAU,QAAQ,QAAQ,SAAS,KAAK,CAAC,CAC9D;;CAGA,IAAI,kBAAkB,SAAS,wBAAwB,QACrD,OAAO,MACL,gBACE,wBAAwB,SAAS,kBAAkB,OACpD,yCACH;CAEF,OAAO,kBAAkB,KAAK,SAAS,KAAK,SAAS;AACvD;AAEA,eAAe,oBACb,YACiC;CACjC,IAAI,OAAO,YACT,OAAO,CAAC;CAQV,QAAO,MALW,UAAU,QAC1B,SAAS,OAAO,WAAW,YAAY,WAAW,UAAU,EAAE,cAC9D,EAAE,eAAe,kBAAkB,GACnC,sBACF,EAAA,CACW;AACb;AAEA,eAAe,kBACb,YAC+B;CAC/B,IAAI,OAAO,YACT,OAAO,CAAC;CAGV,IAAI;EAMF,QAAO,MALW,UAAU,QAC1B,SAAS,OAAO,WAAW,kBAAkB,WAAW,UAAU,KAClE,EAAE,eAAe,kBAAkB,GACnC,oBACF,EAAA,CACW;CACb,SAAS,KAAK;EACZ,IAAI,IAAI,eAAe,KAAK;GAC1B,OAAO,MAAM,gCAAgC,YAAY;GACzD,OAAO,CAAC;EACV;EACA,MAAM;CACR;AACF;AAEA,eAAsB,WACpB,UACA,UACA,aACwB;CACxB,MAAM,OAAO,YAAY,OAAO;CAGhC,MAAM,cAAiC,CAAC;;CAGxC,IAFkB,MAAM,MAAM,GAAG,CAAC,GAAG,OAAO,OAAO,iBAGjD,YAAY,gBAAgB;CAG9B,IAAI,MAAM,SAAS,KAAK,YAAY;CACpC,IAAI,aACF,OAAO,QAAQ;CAMjB,MAAM,OAAM,MAJM,UAAU,iBAC1B,KACA,WACF,EAAA,CACgB,KAAK;CAErB,OADY,WAAW,GACd;AACX;AAEA,eAAsB,YACpB,UACA,UACA,aACc;CACd,MAAM,MAAM,MAAM,WAAW,UAAU,UAAU,WAAW;CAC5D,OAAO,UAAU,KAAK,QAAQ;AAChC;AAEA,eAAsB,UACpB,OACA,YACuB;CACvB,IAAI;EAEF,MAAM,MAAM,SAAS,WAAW;EAChC,MAAM,SACJ,MAAM,UAAU,iBAA+B,KAAK;GAClD;GACA,UAAU;GACV,WAAW;EACb,CAAC,EAAA,CACD;EACF,OAAO,MAAM,SAAS,MAAM,OAAO,gBAAgB;EACnD,OAAO;CACT,SAAS,KAAK;EACZ,IAAI,IAAI,eAAe,KACrB,OAAO,MAAM,+CAA+C;OAE5D,OAAO,MAAM,EAAE,IAAI,GAAG,wCAAwC;EAEhE,MAAM,IAAI,MAAM,sBAAsB;CACxC;AACF;AAEA,eAAsB,SACpB,OACA,YACA,SAC4B;CAC5B,MAAM,QAAQ,MAAM,UAAU,OAAO,UAAU;CAC/C,IAAI,SAAS;EACX,OAAO,MAAM,yCAAyC,QAAQ,EAAE;EAChE,MAAM,aAAa,MAAM,MAAM,SAAS,KAAK,MAAM,UAAU,OAAO;EACpE,IAAI,YAAY;GACd,OAAO,MAAM,0BAA0B,WAAW,WAAW;GAC7D,OAAO;EACT;EACA,OAAO,MAAM,0BAA0B;CACzC;CACA,OAAO,MAAM,2CAA2C;CACxD,IAAI;EACF,MAAM,EAAE,aAAa,MAAM,eAAe,eAAe,UAAU,KAAK;EACxE,MAAM,aAAa,MAAM,MAAM,SAAS,KAAK,MAAM,UAAU,QAAQ;EACrE,IAAI,YAAY;GACd,OAAO,MAAM,+BAA+B,WAAW,WAAW;GAClE,OAAO;EACT;CACF,QAAQ;EACN,MAAM,IAAI,MAAM,sBAAsB;CACxC;CACA,OAAO,MAAM,+BAA+B;CAC5C,OAAO;AACT;AAEA,eAAsB,WACpB,OACA,YACA,SACqB;CACrB,IAAI;CACJ,IAAI;EACF,cACE,MAAM,UAAU,SAAqB,SAAS,WAAW,SAAS;GAChE;GACA,MAAM;IACJ,cAAc,WAAW,KAAA;IACzB,MAAM,OAAO,WAAY,QAAQ,KAAK,KAAK;IAC3C,qBAAqB;GACvB;EACF,CAAC,EAAA,CACD;CACJ,SAAS,KAAK;EACZ,OAAO,MAAM,EAAE,IAAI,GAAG,qBAAqB;CAC7C;CACA,IAAI,CAAC,YACH,MAAM,IAAI,MAAM,sBAAsB;CAExC,OAAO,KAAK,EAAE,YAAY,WAAW,UAAU,GAAG,qBAAqB;CACvE,OAAO,MAAM,kCAAkC;CAC/C,MAAM,WAAW,GAAK;CACtB,OAAO;AACT;AAGA,eAAsB,SAAS,EAC7B,YACA,cACA,SACA,WACA,QACA,kBACA,iBACA,yBACkC;CAClC,OAAO,MAAM,aAAa,WAAW,GAAG;CAExC,SAAS;EACP;EACA;EACA;EACA,gBAAgB,aAAa,IAAI,gBAAgB;EACjD,mBAAmB,CAAC;CACtB;CACA,MAAM,OAAOA,KAAe;EAC1B,UAAU;EACV,KAAK,eAAe;EACpB,UAAU;CACZ,CAAC;CACD,OAAO,mBAAmB;CAC1B,CAAC,OAAO,iBAAiB,OAAO,kBAAkB,WAAW,MAAM,GAAG;CACtE,IAAI;CACJ,IAAI,aAA4B;CAChC,IAAI;EACF,IAAI,YAAY;EAIhB,IACE,eAAe,SAEf,OAAO,UAAU,eAAe,YAAa,QAAQ,GACrD;GACA,YAAY,UAAU,QAAQ,MAAM,4BAA4B,GAAG,IAAI;GACvE,YAAY,UAAU,QAAQ,MAAM,4BAA4B,GAAG,IAAI;EACzE;EAGA,IACE,eAAe,SAEf,OAAO,UAAU,eAAe,YAAa,QAAQ,GAErD,YAAY,UAAU,QACpB,MAAM,yCAAyC,GAC/C,IACF;EAIF,IACE,eAAe,SAEf,OAAO,UAAU,eAAe,YAAa,SAAS,GAEtD,YAAY,UAAU,QACpB,MAAM,qCAAqC,GAC3C,IACF;EAGF,MAAM,MAAM,MAAM,UAAU,eAEzB,WAAW;GACZ,WAAW;IACT,OAAO,OAAO;IACd,MAAM,OAAO;IACb,GAAI,CAAC,OAAO,kBAAkB,EAAE,MAAM,iBAAiB;GACzD;GACA,UAAU;GACV,OAAO;EACT,CAAC;EAED,IAAI,KAAK,QAAQ;GACf,IAAI,IAAI,OAAO,MAAM,QAAQ,IAAI,SAAS,cAAc,GAAG;IACzD,OAAO,MAAM,EAAE,IAAI,GAAG,8BAA8B;IACpD,MAAM,IAAI,MAAM,4BAA4B;GAC9C;GACA,OAAO,MAAM,EAAE,IAAI,GAAG,2BAA2B;GACjD,MAAM,IAAI,MAAM,sBAAsB;EACxC;EAEA,OAAO,KAAK,MAAM;;EAElB,IAAI,CAAC,MAAM;GACT,OAAO,MAAM,EAAE,IAAI,GAAG,wBAAwB;GAC9C,MAAM,IAAI,MAAM,oBAAoB;EACtC;;EAEA,IAAI,CAAC,KAAK,kBAAkB,MAAM;GAChC,OAAO,MACL,EAAE,IAAI,GACN,qDACF;GACA,MAAM,IAAI,MAAM,gBAAgB;EAClC;EACA,IACE,KAAK,iBACL,KAAK,cAAc,YAAY,MAAM,WAAW,YAAY,GAC5D;GACA,OAAO,MACL;IAAE,aAAa;IAAY,WAAW,KAAK;GAAc,GACzD,6BACF;GACA,MAAM,IAAI,MAAM,kBAAkB;EACpC;EACA,IAAI,KAAK,YAAY;GACnB,OAAO,MACL,6DACF;GACA,MAAM,IAAI,MAAM,mBAAmB;EACrC;EAEA,OAAO,gBAAgB,KAAK,iBAAiB;EAE7C,OAAO,MAAM,GAAG,WAAW,oBAAoB,OAAO,eAAe;EAErE,IAAI,KAAK,oBACP,OAAO,cAAc;OAChB,IAAI,KAAK,oBACd,OAAO,cAAc;OAChB,IAAI,KAAK,oBACd,OAAO,cAAc;OAGrB,OAAO,MAAM,+CAA+C;EAE9D,OAAO,mBAAmB,KAAK;EAC/B,OAAO,mBAAmB,KAAK;EAC/B,OAAO,gCAAgC,KAAK;EAC5C,OAAO,kBAAkB,OAAO,iBAAiB,iBAC/C,KAAK,UACP;EAEA,MAAM,eAAeC,YAAM,MAAM,CAAC,CAC/B,MAAM,CAAC,CAAC,CAAC,CACT,MAAM,KAAK,MAAM,YAAY,QAAQ,KAAK;EAC7C,iBAAiB,qBAAqB,YAAY;CACpD,SAAS,6FAA6F;EACpG,OAAO,MAAM,EAAE,IAAI,GAAG,uBAAuB;EAC7C,IACE,IAAI,YAAA,cACJ,IAAI,YAAA,aACJ,IAAI,YAAA,aAEJ,MAAM;EAER,IAAI,IAAI,eAAe,KACrB,MAAM,IAAI,MAAM,2BAA2B;EAE7C,IAAI,IAAI,eAAe,KACrB,MAAM,IAAI,MAAM,oBAAoB;EAEtC,IAAI,IAAI,QAAQ,WAAW,2BAA2B,GACpD,MAAM,IAAI,MAAM,kBAAkB;EAEpC,IAAI,IAAI,YAAA,oBACN,MAAM;EAER,IAAI,IAAI,YAAA,QACN,MAAM;EAER,IAAI,IAAI,YAAA,YACN,MAAM;EAER,IAAI,IAAI,YAAY,qDAClB,MAAM,IAAI,MAAM,2BAA2B;EAE7C,OAAO,MAAM,EAAE,IAAI,GAAG,+BAA+B;EACrD,MAAM;CACR;CAEA,OAAO,SAAS;CAEhB,IAAI,WAAW;EACb,OAAO,MAAM,qBAAqB;EAClC,IAAI,KAAK,QAAQ;GACf,OAAO,MACL,8FACF;GACA,OAAO,MACL,uCAAuC,KAAK,QAAQ,eACtD;GACA,MAAM,IAAI,MAAM,iBAAiB;EACnC;EACA,OAAO,UAAU;EACjB,OAAO,YAAY;EAEnB,OAAO,aAAa,OAAO;EAC3B,OAAO,aAAa;EACpB,IAAI,aAAa,MAAM,SAAS,WAAW,YAAY,OAAO;EAC9D,IAAI,YAAY;GACd,OAAO,aAAa,WAAW;GAC/B,aAAa,WAAW;GACxB,MAAM,oBAAoB,WAAW;GACrC,IAAI,sBAAsB,OAAO,eAAe;IAC9C,MAAM,OAAO;KACX,KAAK,cAAc,OAAO;KAC1B,KAAK,KAAK,iBAAiB,OAAO;IACpC;IACA,OAAO,MACL;KACE,eAAe,OAAO;KACtB;KACA;IACF,GACA,0EACF;IACA,IAAI;KACF,MAAM,UAAU,SAAS,SAAS,OAAO,WAAW,YAAY;MAC9D;MACA,OAAO;KACT,CAAC;KACD,OAAO,MAAM,oCAAoC;IACnD,SAAS,2FAA2F;KAClG,IAAI,IAAI,UAAU,MAAM,YAAY,4BAClC,OAAO,MACL,UAAU,OAAO,cAAc,4BACjC;UAEA,OAAO,KACL;MAAE;MAAK,MAAM,IAAI,UAAU;KAAK,GAChC,+CACF;IAEJ;IACA,OAAO,MACL,WAAW,OAAO,cAAc,yBAAyB,OAAO,YAClE;IACA,IAAI;KACF,MAAM,UAAU,UAAU,SAAS,OAAO,cAAc;MACtD,MAAM;OACJ,MAAM,OAAO,WAAW,MAAM,GAAG,CAAC,CAAC;OACnC,gBAAgB,OAAO;MACzB;MACA,OAAO;KACT,CAAC;KACD,OAAO,MAAM,8CAA8C;IAC7D,SAAS,6HAA6H;KACpI,OAAO,KAAK,EAAE,IAAI,GAAG,8BAA8B;IACrD;GACF;EACF,OAAO,IAAI,cAAc;GACvB,OAAO,MAAM,oDAAoD;GACjE,aAAa,MAAM,WAAW,WAAW,YAAY,OAAO;GAC5D,OAAO,aAAa,WAAW;GAC/B,aAAa,WAAW;EAC1B,OAAO;GACL,OAAO,MAAM,uDAAuD;GACpE,MAAM,IAAI,MAAM,uBAAuB;EACzC;CACF;CAEA,IAAI;CACJ,IAAI,WAAW;EACb,OAAO,MAAM,8BAA8B;EAC3C,YAAY,aAAa,OAAO,SAAS;CAC3C,OAAqG;EACnG,MAAM,YAAY,KAAK,OAAO,WAAW,iBAAiB,IACtD,QACA;EACJ,OAAO,MAAM,SAAS,UAAU,oBAAoB;EACpD,YAAY,KAAK,SAAS;CAC5B;CAEA,MAAM,iBAAiB,SAAS,eAAe,QAAQ;CACvD,MAAM,gBAAgB,YAAY,aAAa,KAAK;CACpD,MAAM,MAAM,WACV,OAAO,YACP,QACA,eACA,gBACA,SACF;CACA,IAAI;CACJ,IAAI,gBAAgB,OAAO,YACzB,cAAc,WACZ,OAAO,YACP,QACA,KAAK,QACL,gBACA,SACF;CAEF,MAAMC,WAAa;EACjB,GAAG;EACH;EACA;CACF,CAAC;CAMD,OAAO;EAJL,eAAe,OAAO;EACtB,QAAQ,KAAK,WAAW;EACxB,iBAAiB,gBAAgB,KAAK,IAAI,eAAe,QAAQ;CAEnD;AAClB;AAEA,eAAe,4BACb,YACkB;CAClB,IAAI;EACF,MAAM,WAAW,MAAM,kBAAkB,UAAU;EACnD,OAAO,MACL,kBAAkB,SAAS,OAAO,uBAAuB,YAC3D;EAEA,OAAO,SAAS,MAAM,SAAS;GAC7B,IACE,KAAK,SAAS,4BACd,KAAK,YAAY,yCAAyC,MAC1D;IACA,OAAO,MACL,oDAAoD,YACtD;IACA,OAAO;GACT;GAEA,OAAO;EACT,CAAC;CACH,SAAS,KAAK;EACZ,4BAA4B,YAAY,KAAK,UAAU;EACvD,OAAO;CACT;AACF;AAEA,eAAe,oCACb,YACkB;CAClB,IAAI;EACF,MAAM,mBAAmB,MAAM,oBAAoB,UAAU;EAC7D,OAAO,MAAM,sCAAsC,YAAY;EAG/D,IAD2B,kBAAkB,wBAAwB,QAC7C;GACtB,OAAO,MACL,gEAAgE,YAClE;GACA,OAAO;EACT;EACA,OAAO;CACT,SAAS,KAAK;EACZ,4BAA4B,qBAAqB,KAAK,UAAU;EAChE,OAAO;CACT;AACF;AAEA,eAAsB,qBACpB,YACkB;CAClB,OAAO,sBAAsB,CAAC;CAE9B,MAAM,eAAe,OAAO,kBAAkB;CAC9C,IAAI,iBAAiB,KAAA,GACnB,OAAO;CAIT,OAAO,kBAAkB,cAAc;CAIvC,IAAI,MADgC,4BAA4B,UAAU,GAC/C;EACzB,OAAO,kBAAkB,cAAc;EACvC,OAAO;CACT;CAKA,IAAI,MADI,oCAAoC,UAAU,GAEpD,OAAO,kBAAkB,cAAc;CAGzC,OAAO,OAAO,kBAAkB;AAClC;AAEA,SAAS,4BACP,YACA,KACA,YACM;CACN,IAAI,IAAI,eAAe,KAAK;EAC1B,OAAO,MAAM,MAAM,WAAW,aAAa,YAAY;EACvD;CACF;CAKA,IAFE,IAAI,YAAA,8BAAiD,IAAI,eAAe,KAEtD;EAClB,OAAO,KAAK,MACV,wDAAwD,WAAW,OAAO,YAC5E;EACA;CACF;CAEA,MAAM;AACR;AAEA,SAAS,QAAQ,IAAwB;CACvC,OAAO,WAAW,CAAC;;CAEnB,IAAI,IAAI;EACN,cAAc,EAAE;EAChB,KAAK,IAAI,MAAM,GAAG,MAAM,OAAO,OAAO,QAAQ,OAAO,GAEnD,IADiB,OAAO,OAAO,IACnB,CAAC,WAAW,GAAG,QAAQ;GACjC,OAAO,OAAO,OAAO;GACrB;EACF;EAEF,OAAO,OAAO,KAAK,EAAE;CACvB;AACF;AAGA,eAAe,QAAQ,MAAoC;CACzD,IAAI;EACF,MAAM,EAAE,MAAM,aAAa,MAAM,UAAU,iBACzC,SAAS,OAAO,cAAc,OAAO,WAAW,SAAS,MAC3D;EACA,MAAM,SAAS,aAAa,QAAQ;EACpC,QAAQ,MAAM;EACd,OAAO;CACT,SAAS,KAAK;EACZ,OAAO,KAAK;GAAE;GAAK;EAAK,GAAG,sBAAsB;EACjD,OAAO;CACT;AACF;AAGA,eAAsB,MAAM,MAAoC;CAC9D,IAAI,CAAC,MACH,OAAO;CAGT,IAAI,MAAK,MADY,UAAU,EAAA,CACf,MAAM,EAAE,aAAa,WAAW,IAAI,KAAK;CACzD,IAAI,IACF,OAAO,MAAM,yBAAyB;CAExC,OAAO,MAAM,QAAQ,IAAI;CACzB,OAAO;AACT;AAEA,SAAS,aAAa,OAAe,cAA+B;CAClE,IAAI,iBAAiB,OACnB,OAAO;CAET,IAAI,aAAa,WAAW,GAAG,GAC7B,OAAO,UAAU,aAAa,UAAU,CAAC;CAE3C,OAAO,UAAU;AACnB;AAEA,eAAsB,YAA6B;CACjD,IAAI,CAAC,OAAO,QAAQ;EAClB,MAAM,OAAO,OAAO,cAAc,OAAO;EAEzC,IAAI,WAAW,OAAO;EACtB,IAAI,OAAO,aAAa,OAAO,gBAC7B,WAAW,KAAA;EAIb,MAAM,UAAU,MAAM,WAAW,oBAC/B,WAAW,WAAW,MAAO,QAAQ,CACvC;EACA,OAAO,SAAS,OAAO,OAAO,OAAO,CAAC,CAAC,MACpC,EAAE,QAAQ,KAAK,EAAE,QAAQ,QAAQ,IAAI,CACxC;CACF;CAEA,OAAO,OAAO;AAChB;AAEA,eAAsB,OAAO,EAC3B,YACA,SACA,QAAQ,OACR,uBACqC;CACrC,OAAO,MAAM,UAAU,WAAW,IAAI,QAAQ,IAAI,MAAM,EAAE;CAE1D,IAAI,qBAAqB;EACvB,MAAM,OAAO,OAAO,cAAc,OAAO;EACzC,MAAM,MAAM,MAAM,MAAM,GAAG,CAAC,CAAC;EAE7B,MAAM,EAAE,MAAM,WAAW,MAAM,UAAU,iBACvC,SAAS,KAAK,cAAc,IAAI,GAAG,WAAW,cAC9C,EAAE,eAAe,kBAAkB,CACrC;EAEA,IAAI,CAAC,OAAO,QAAQ;GAClB,OAAO,MAAM,0BAA0B,YAAY;GACnD,OAAO;EACT;EAEA,OAAO,aAAa,OAAO,EAAE;CAC/B;CAGA,MAAM,MAAK,MADU,UAAU,EAAA,CACb,MAAM,MAAM;EAC5B,IAAI,EAAE,iBAAiB,YACrB,OAAO;EAGT,IAAI,WAAW,QAAQ,YAAY,MAAM,EAAE,MAAM,YAAY,GAC3D,OAAO;EAGT,IAAI,CAAC,aAAa,EAAE,OAAO,KAAK,GAC9B,OAAO;EAGT,IAAI,CAAC,OAAO,aAAa,CAAC,YAAY,OAAO,YAAY,EAAE,UAAU,GACnE,OAAO;EAGT,OAAO;CACT,CAAC;CACD,IAAI,IACF,OAAO,MAAM,aAAa,GAAG,QAAQ;CAEvC,OAAO,MAAM;AACf;AAEA,eAAe,gBACb,YACA,KACe;CACf,MAAM,aAAa,OAAO;CAC1B,IAAI;EACF,MAAM,YAAY,UAAU,WAAW,eAAe;EACtD,MAAM,UAAU,KAAK,WAAW,EAAE,UAAU,MAAM,CAAC;CACrD,SAAS,KAAK;EACZ,OAAO,MAAM;GAAE;GAAK;GAAK;EAAW,GAAG,kBAAkB;EACzD,MAAM;CACR;CAEA,MAAM,SAAS,UAAU,OAAO,WAAW,kBAAkB;CAG7D,IAAI,MAFuB,mBAAmB,YAAY,UAAU,GAGlE,IAAI;EACF,MAAM,UAAU,UAAU,QAAQ,EAAE,MAAM;GAAE;GAAK,OAAO;EAAK,EAAE,CAAC;EAChE;CACF,SAAS,KAAK;EACZ,IAAI,IAAI,KAAK,UAAU,eAAe,KACpC,OAAO,MACL,EAAE,IAAI,GACN,yEACF;OACK;GACL,OAAO,KAAK;IAAE;IAAQ;GAAI,GAAG,uBAAuB;GACpD,MAAM;EACR;CACF;CAGF,MAAM,UAAU,SAAS,UAAU,WAAW,YAAY,EACxD,MAAM;EAAE;EAAK,KAAK,cAAc;CAAa,EAC/C,CAAC;AACH;AAGA,eAAsB,YAAY,YAA0C;CAC1E,OAAO,MAAM,eAAe,WAAW,EAAE;CAEzC,MAAM,SAAS,MAAM,OAAO;EAC1B;EACA,OAAO;CACT,CAAC;CAED,IAAI,QACF,OAAO;CAGT,OAAO;AACT;AAEA,eAAsB,qBACpB,cACA,UACoB;CACpB,MAAM,EAAE,KAAK,QAAQ,cAAc,eAAe;CAClD,IAAI;EACF,MAAM,gBAAgB,YAAY,GAAI;EACtC,OAAO,MAAM,+BAA+B,WAAW,YAAY,KAAK;CAC1E,SAAS,KAAK;EACZ,OAAO,MACL;GAAE;GAAK;GAAY;GAAK;EAAa,GACrC,wDACF;EACA,OAAO;CACT;CAEA,IAAI;EACF,MAAM,EAAE,MAAM,SAAS,MAAM,UAAU,UACrC,SAAS,OAAO,WAAW,SAAS,UACpC,EACE,MAAM;GACJ,OAAO;GACP,OAAO;EACT,EACF,CACF;EACA,OAAO,KACL;GAAE;GAAY,UAAU,aAAa;GAAO;GAAU;EAAO,GAC7D,qCACF;EAEA,MAAM,SAAS,aAAa,IAAI;EAEhC,MAAM,WAAWC,gBAAoB,UAAU;;EAE/C,IAAI,YAAY,aAAa,KAAK;GAChC,MAAMC,kBAAsB,YAAY,QAAQ;GAChD,OAAO,MAAM;EACf;EAEA,QAAQ,MAAM;EACd,OAAO;CACT,QAAQ;EACN,OAAO,MAAM,gCAAgC;EAC7C,OAAO;CACT;AACF;AAEA,eAAe,UACb,YACA,WAAW,MACoB;CAC/B,MAAM,SAAS,WAAW,UAAU;CACpC,MAAM,MAAM,SAAS,OAAO,WAAW,WAAW,OAAO;CAEzD,MAAM,EAAE,MAAM,WACZ,MAAM,UAAU,iBAAuC,KAAK;EAC1D,UAAU;EACV,eAAe;CACjB,CAAC;CAEH,OAAO;AACT;AAGA,eAAsB,gBACpB,YACA,yBACuB;CACvB,OAAO,MAAM,mBAAmB,WAAW,EAAE;CAC7C,IAAI;CACJ,IAAI;EACF,eAAe,MAAM,UAAU,UAAU;CAC3C,SAAS,2GAA2G;EAClH,IAAI,IAAI,eAAe,KAAK;GAC1B,OAAO,MACL,iFACF;GACA,MAAM,IAAI,MAAM,kBAAkB;EACpC;EACA,OAAO,MAAM,2CAA2C;EACxD,MAAM;CACR;CACA,OAAO,MACL;EAAE,OAAO,aAAa;EAAO,UAAU,aAAa;CAAS,GAC7D,4BACF;CACA,IAAI,aAAa,YAAY,CAAC,yBAAyB;EACrD,aAAa,WAAW,aAAa,SAAS,QAC3C,WACC,OAAO,UAAU,aAAa,CAAC,OAAO,SAAS,WAAW,WAAW,CACzE;;EAEA,IAAI,CAAC,aAAa,SAAS,QAAQ;GACjC,OAAO,MACL,6FACF;GACA,aAAa,QAAQ;EACvB;CACF;CACA,IAAI,YAAoE,CAAC;CAEzE,IAAI;EACF,MAAM,eAAe,SAAS,OAAO,WAAW,WAAW,WACzD,UACF,EAAE;EACF,MAAM,OAAO;GACX,SAAS,EACP,QAAQ,8CACV;GACA,UAAU;GACV,iBAAiB;GACjB,eAAe;EACjB;EACA,MAAM,gBACJ,MAAM,UAAU,iBAEb,cAAc,IAAI,EAAA,CACrB;EACF,IAAI,aAAa,YAAY,QAAQ;GACnC,YAAY,aAAa,WAAW,KAAK,SAAS;IAChD,MAAM,IAAI;IACV,QAAQ,IAAI;IACZ,YAAY,IAAI;GAClB,EAAE;GACF,OAAO,MAAM,EAAE,UAAU,GAAG,mBAAmB;EACjD,OACE,OAAO,MAAM,EAAE,QAAQ,aAAa,GAAG,qBAAqB;CAEhE,SAAS,gHAAgH;EACvH,IAAI,eAAe,mBACjB,MAAM;EAER,IACE,IAAI,eAAe,OACnB,IAAI,YAAA,4BAEJ,OAAO,MAAM,kCAAkC;OAE/C,OAAO,KAAK,EAAE,IAAI,GAAG,6BAA6B;CAEtD;CACA,IAAI,UAAU,WAAW,GAAG;EAC1B,IAAI,aAAa,UAAU,WACzB,OAAO;EAET,IAAI,aAAa,UAAU,WACzB,OAAO;EAET,OAAO;CACT;CACA,IACE,aAAa,UAAU,aACvB,UAAU,MAAM,QAAQ,IAAI,eAAe,SAAS,GAEpD,OAAO;CAET,KACG,aAAa,UAAU,aAAa,aAAa,SAAS,WAAW,MACtE,UAAU,OAAO,QACf;EAAC;EAAW;EAAW;CAAS,CAAC,CAAC,SAAS,IAAI,UAAU,CAC3D,GAEA,OAAO;CAET,OAAO;AACT;AAEA,eAAe,eACb,YACA,WAAW,MACgB;CAC3B,MAAM,eAAeD,gBAAoB,UAAU;CAEnD,MAAM,MAAM,SAAS,OAAO,WAAW,WAAW,aAAa;CAE/D,MAAM,OAA0B,WAC5B,EAAE,eAAe,iBAAiB,IAClC,EAAE,UAAU,MAAM;CAEtB,QAAQ,MAAM,UAAU,iBAAmC,KAAK,IAAI,EAAA,CAAG;AACzE;AAGA,MAAM,gCAA+D;CACnE,SAAS;CACT,OAAO;CACP,SAAS;CACT,SAAS;AACX;AAEA,eAAsB,qBACpB,YACA,SAC8B;CAC9B,IAAI;EACF,MAAM,MAAM,MAAM,eAAe,UAAU;EAC3C,KAAK,MAAM,SAAS,KAClB,IAAI,MAAM,YAAY,SACpB,OAAO,8BAA8B,MAAM,UAAU;EAGzD,OAAO;CACT,SAAS,0GAA0G;EACjH,IAAI,IAAI,eAAe,KAAK;GAC1B,OAAO,MAAM,yCAAyC;GACtD,MAAM,IAAI,MAAM,kBAAkB;EACpC;EACA,MAAM;CACR;AACF;AAEA,eAAsB,gBAAgB,EACpC,YACA,SACA,aACA,OACA,KAAK,aAC+B;;CAEpC,IAAI,OAAO,YAAY;EACrB,OAAO,MAAM,+CAA+C;EAC5D;CACF;CAEA,IAAI,MADyB,qBAAqB,YAAY,OAAO,MAC9C,OACrB;CAEF,OAAO,MAAM;EAAE,QAAQ;EAAY;EAAS;CAAM,GAAG,uBAAuB;CAC5E,IAAI;CACJ,IAAI;EACF,MAAM,eAAeA,gBAAoB,UAAU;EACnD,MAAM,SAAS,OAAO,WAAW,YAAY;EAM7C,MAAM,UAAe;GACnB,OAAO;IALP,OAAO;IACP,QAAQ;IACR,KAAK;GAG6B,EAAE;GACpC;GACA;EACF;;EAEA,IAAI,WACF,QAAQ,aAAa;EAEvB,MAAM,UAAU,SAAS,KAAK,EAAE,MAAM,QAAQ,CAAC;EAG/C,MAAM,UAAU,YAAY,KAAK;EACjC,MAAM,eAAe,YAAY,KAAK;CACxC,SAAS,mHAAmH;EAC1H,OAAO,MAAM;GAAE;GAAK;EAAI,GAAG,+CAA+C;EAC1E,MAAM,IAAI,MAAM,kBAAkB;CACpC;AACF;AAIA,eAAe,YAA8B;CAC3C,MAAM,SAAS,MAAM,UAAU,eAC7B,gBACA,UACA;EACE,WAAW;GACT,OAAO,OAAO;GACd,MAAM,OAAO;GACb,GAAI,CAAC,OAAO,kBAAkB,EAAE,MAAM,OAAO,iBAAiB;EAChE;EACA,UAAU;CACZ,CACF;CAEA,OAAO,MAAM,aAAa,OAAO,OAAO,QAAQ;CAChD,OAAOF,YAAM,MAAM,CAAC,CAAC,MAAM,MAAM;AACnC;AAEA,eAAsB,eAAiC;;CAErD,IAAI,OAAO,qBAAqB,OAC9B,OAAO,CAAC;CAEV,IAAI,YAAY,iBAAiB,UAAU;;CAE3C,IAAI,CAAC,WAAW;EACd,OAAO,MAAM,sBAAsB;EACnC,YAAY,MAAM,UAAU;EAC5B,iBAAiB,UAAU,SAAS;CACtC;CACA,OAAO;AACT;AAEA,eAAsB,SAAS,QAAuC;CACpE,IAAI,OAAO,qBAAqB,OAC9B,OAAO;CAET,IAAI;EACF,MAAM,OAAO,OAAO,cAAc,OAAO;EACzC,MAAM,EAAE,MAAM,UAAU,MAAM,UAAU,QACtC,SAAS,KAAK,UAAU,UACxB,EACE,eAAe,kBACjB,GACAA,WACF;EACA,iBAAiB,YAAY,KAAK;EAClC,OAAO;CACT,SAAS,KAAK;EACZ,OAAO,MAAM;GAAE;GAAK;EAAO,GAAG,qBAAqB;EACnD,IAAI,IAAI,UAAU,eAAe,KAAK;GACpC,OAAO,MAAM,UAAU,OAAO,kBAAkB;GAChD,iBAAiB,YAAY,MAAM;EACrC;EACA,OAAO;CACT;AACF;AAEA,eAAsB,UAAU,OAAsC;CACpE,OAAO,MAAM,aAAa,MAAM,EAAE;CAClC,MAAM,CAAC,UAAU,MAAM,aAAa,EAAA,CAAG,QACpC,MAAM,EAAE,UAAU,UAAU,EAAE,UAAU,KAC3C;CACA,IAAI,CAAC,OACH,OAAO;CAET,OAAO,MAAM,eAAe,MAAM,QAAQ;CAC1C,OAAO,SAAS,MAAM,MAAM;AAC9B;AAEA,eAAe,WAAW,aAAoC;CAC5D,OAAO,MAAM,cAAc,YAAY,EAAE;CACzC,MAAM,OAAO,OAAO,cAAc,OAAO;CACzC,IAAI;EACF,MAAM,EAAE,MAAM,gBAAgB,MAAM,UAAU,UAC5C,SAAS,KAAK,UAAU,eACxB,EAAE,MAAM,EAAE,OAAO,SAAS,EAAE,GAC5BA,WACF;EACA,iBAAiB,YAAY,WAAW;CAC1C,SAAS,KAAK;EACZ,MAAM,aAAa,IAAI,UAAU;EACjC,IAAI,eAAe,OAAO,eAAe,KAAK;GAC5C,OAAO,MACL,UAAU,YAAY,uDACxB;GACA,iBAAiB,YAAY,WAAW;GACxC;EACF;EACA,MAAM;CACR;AACF;AAEA,eAAsB,YAAY,EAChC,OACA,YACA,MAAM,SACN,QACA,OAAO,OACP,eAAe,QACwC;CACvD,OAAO,MAAM,eAAe,MAAM,EAAE;;CAEpC,IAAI,OAAO,qBAAqB,OAAO;EACrC,OAAO,KACL,oEACF;EACA,OAAO;CACT;CACA,MAAM,OAAO,SAAS,OAAO;CAC7B,IAAI;EACF,MAAM,YAAY,MAAM,aAAa;EACrC,IAAI,SAAS,UAAU,QAAQ,MAAM,EAAE,UAAU,KAAK;EACtD,IAAI,CAAC,OAAO,QAAQ;GAClB,SAAS,UAAU,QAAQ,MAAM,EAAE,UAAU,UAAU;GACvD,IAAI,OAAO,QACT,OAAO,MAAM,yBAAyB,WAAW,EAAE;EAEvD;EACA,IAAI,OAAO,QAAQ;GACjB,IAAI,QAAQ,OAAO,MAAM,MAAM,EAAE,UAAU,MAAM;GACjD,IAAI,CAAC,OAAO;IACV,IAAI,MAAM;KACR,OAAO,MAAM,4CAA4C;KACzD,OAAO;IACT;IACA,IAAI,cACF,OAAO,MAAM,mCAAmC;IAElD,QAAQ,OAAO,GAAG,EAAE;GACtB;GACA,KAAK,MAAM,KAAK,QACd,IAAI,EAAE,UAAU,UAAU,EAAE,WAAW,MAAM,QAAQ;IACnD,OAAO,KAAK,EAAE,SAAS,EAAE,OAAO,GAAG,yBAAyB;IAC5D,MAAM,WAAW,EAAE,MAAM;GAC3B;GAGF,MAAM,OAAO,OAAO,cAAc,OAAO;GACzC,MAAM,EAAE,MAAM,gBAAgB,MAAM,UAAU,QAC5C,SAAS,KAAK,UAAU,MAAM,UAC9B,EAAE,eAAe,kBAAkB,GACnCA,WACF;GACA,iBAAiB,YAAY,WAAW;GAExC,IACE,MAAM,UAAU,SAChB,YAAY,SAAS,QACrB,MAAM,UAAU,QAChB;IACA,OAAO,MAAM,8CAA8C;IAC3D,OAAO;GACT;GACA,IAAI,gBAAgB,MAAM,UAAU,QAAQ;IAC1C,OAAO,MAAM,gBAAgB;IAC7B,MAAM,OAAgC;KAAE;KAAM,OAAO;KAAQ;IAAM;IACnE,IAAI,QACF,KAAK,SAAS;IAEhB,MAAM,OAAO,OAAO,cAAc,OAAO;IACzC,MAAM,EAAE,MAAM,iBAAiB,MAAM,UAAU,UAC7C,SAAS,KAAK,UAAU,MAAM,UAC9B,EAAE,MAAM,KAAK,GACbA,WACF;IACA,iBAAiB,YAAY,YAAY;IACzC,OAAO,MAAM,eAAe;IAC5B,OAAO;GACT;EACF;EACA,MAAM,EAAE,MAAM,iBAAiB,MAAM,UAAU,SAC7C,SAAS,OAAO,cAAc,OAAO,WAAW,UAChD,EACE,MAAM;GACJ;GACA;GACA,QAAQ,UAAU,CAAC;EACrB,EACF,GACAA,WACF;EACA,OAAO,KAAK,eAAe;EAE3B,iBAAiB,YAAY,YAAY;EACzC,OAAO;CACT,SAAS,oFAAoF;EAC3F,IAAI,IAAI,MAAM,SAAS,WAAW,mCAAmC,GACnE,OAAO,MAAM,mDAAmD,OAAO;OAEvE,OAAO,KAAK,EAAE,IAAI,GAAG,wBAAwB;CAEjD;CACA,OAAO;AACT;AAEA,eAAsB,mBAAmB,OAA8B;CACrE,OAAO,MAAM,sBAAsB,MAAM,EAAE;;CAE3C,IAAI,OAAO,qBAAqB,OAC9B;CAEF,MAAM,YAAY,MAAM,aAAa;CACrC,KAAK,MAAM,SAAS,WAClB,IAAI,MAAM,UAAU,UAAU,MAAM,UAAU,OAAO;EACnD,MAAM,WAAW,MAAM,MAAM;EAC7B,OAAO,MAAM,0BAA0B,MAAM,QAAQ;CACvD;AAEJ;AAEA,eAAe,gBACb,SACA,aACe;CACf,IAAI,CAAC,aACH;CAGF,OAAO,MACL;EACE,WAAW;EACX,IAAI;CACN,GACA,wBACF;CACA,IAAI;EACF,MAAM,OAAO,OAAO,cAAc,OAAO;EACzC,MAAM,EAAE,MAAM,iBAAiB,MAAM,UAAU,UAC7C,SAAS,KAAK,UAAU,WACxB,EAAE,MAAM,EAAE,WAAW,YAAY,EAAE,GACnCA,WACF;EACA,iBAAiB,YAAY,YAAY;CAC3C,SAAS,KAAK;;EAEZ,MAAM,cAAc,IAAI,UAAU,QAAQ;EAC1C,OAAO,KACL;GACE,WAAW;GACX,IAAI;GACJ,KAAK;EACP,GACA,+BACF;CACF;AACF;AAEA,eAAsB,aACpB,SACA,WACe;CACf,OAAO,MAAM,qBAAqB,UAAU,KAAK,IAAI,EAAE,QAAQ,SAAS;CAExE,MAAM,MAAM,SADO,OAAO,cAAc,OAAO,WACf,UAAU,QAAQ;CAClD,IAAI;CACJ,KAAK,IAAI,UAAU,GAAG,UAAU,GAAG,WAAW,GAC5C,IAAI;EACF,MAAM,EAAE,MAAM,iBAAiB,MAAM,UAAU,SAC7C,KACA,EAAE,MAAM,EAAE,UAAU,EAAE,GACtBA,WACF;EACA,iBAAiB,YAAY,YAAY;EACzC;CACF,SAAS,KAAK;EACZ,IAAI,IAAI,eAAe,KACrB,MAAM;EAER,UAAU;EACV,OAAO,MACL,EAAE,SAAS,UAAU,EAAE,GACvB,8BAA8B,QAAQ,WACxC;EACA,MAAM,WAAW,GAAI;CACvB;CAEF,MAAM;AACR;AAEA,eAAsB,aACpB,MACA,WACe;CACf,OAAO,MAAM,qBAAqB,UAAU,KAAK,IAAI,EAAE,QAAQ,MAAM;CAErE,MAAM,gBAAgB,UAAU,QAAQ,MAAM,CAAC,EAAE,WAAW,OAAO,CAAC;CACpE,MAAM,gBAAgB,UACnB,QAAQ,MAAM,EAAE,WAAW,OAAO,CAAC,CAAC,CACpC,KAAK,MAAM,EAAE,QAAQ,MAAM,QAAQ,GAAG,EAAE,CAAC;CAC5C,IAAI;EACF,MAAM,UAAU,SACd,SACE,OAAO,cAAc,OAAO,WAC7B,SAAS,KAAK,uBACf,EACE,MAAM;GACJ,WAAW;GACX,gBAAgB;EAClB,EACF,CACF;CACF,SAAS,sHAAsH;EAC7H,OAAO,KAAK,EAAE,IAAI,GAAG,2BAA2B;CAClD;AACF;AAEA,eAAsB,UACpB,SACA,QACe;CACf,OAAO,MAAM,kBAAkB,QAAQ,KAAK,IAAI,EAAE,QAAQ,SAAS;CACnE,IAAI;EACF,MAAM,aAAa,OAAO,cAAc,OAAO;EAC/C,IAAI,QAAQ,MAAM,KAAK,OAAO,QAC5B,MAAM,UAAU,SAAS,SAAS,WAAW,UAAU,QAAQ,UAAU,EACvE,MAAM,OACR,CAAC;CAEL,SAAS,+GAA+G;EACtH,OAAO,KACL;GAAE;GAAK;GAAS;EAAO,GACvB,qCACF;CACF;AACF;AAEA,eAAsB,YACpB,SACA,OACe;CACf,OAAO,MAAM,kBAAkB,MAAM,SAAS,SAAS;CACvD,MAAM,aAAa,OAAO,cAAc,OAAO;CAC/C,IAAI;EACF,MAAM,UAAU,WACd,SAAS,WAAW,UAAU,QAAQ,UAAU,OAClD;CACF,SAAS,iHAAiH;EACxH,OAAO,KAAK;GAAE;GAAK;GAAS;EAAM,GAAG,wBAAwB;CAC/D;AACF;AAEA,eAAe,WAAW,SAAiB,MAA6B;CAEtE,MAAM,UAAU,SACd,SACE,OAAO,cAAc,OAAO,WAC7B,UAAU,QAAQ,YACnB,EACE,MAAM,EAAE,KAAK,EACf,CACF;AACF;AAEA,eAAe,YAAY,WAAmB,MAA6B;CAEzE,MAAM,UAAU,UACd,SACE,OAAO,cAAc,OAAO,WAC7B,mBAAmB,aACpB,EACE,MAAM,EAAE,KAAK,EACf,CACF;AACF;AAEA,eAAe,cAAc,WAAkC;CAE7D,MAAM,UAAU,WACd,SACE,OAAO,cAAc,OAAO,WAC7B,mBAAmB,WACtB;AACF;AAEA,eAAe,YAAY,SAAqC;CAE9D,OAAO,MAAM,yBAAyB,SAAS;CAE/C,MAAM,MAAM,SADC,OAAO,cAAc,OAAO,WACf,UAAU,QAAQ;CAC5C,IAAI;EACF,MAAM,EAAE,MAAM,aAAa,MAAM,UAAU,iBACzC,KACA;GACE,UAAU;GACV,eAAe;EACjB,CACF;EACA,OAAO,MAAM,SAAS,SAAS,OAAO,UAAU;EAChD,OAAO;CACT,SAAS,sGAAsG;EAC7G,IAAI,IAAI,eAAe,KAAK;GAC1B,OAAO,MAAM,uCAAuC;GACpD,MAAM,IAAI,kBAAkB,KAAK,QAAQ;EAC3C;EACA,MAAM;CACR;AACF;AAEA,eAAsB,cAAc,EAClC,QACA,OACA,WACwC;CACxC,MAAM,mBAAmB,SAAS,OAAO;CACzC,IAAI;EACF,MAAM,WAAW,MAAM,YAAY,MAAM;EACzC,IAAI;EACJ,IAAI,YAA2B;EAC/B,IAAI,uBAAuB;EAC3B,IAAI,OAAO;GACT,OAAO,MAAM,qBAAqB,MAAM,QAAQ,QAAQ;GACxD,OAAO,OAAO,MAAM,MAAM;GAC1B,SAAS,SAAS,YAAY;IAC5B,IAAI,QAAQ,KAAK,WAAW,OAAO,MAAM,KAAK,GAAG;KAC/C,YAAY,QAAQ;KACpB,uBAAuB,QAAQ,SAAS;IAC1C;GACF,CAAC;EACH,OAAO;GACL,OAAO,MAAM,qCAAqC,QAAQ;GAC1D,OAAO,GAAG;GACV,SAAS,SAAS,YAAY;;IAE5B,IAAI,QAAQ,SAAS,MAAM;KACzB,YAAY,QAAQ;KACpB,uBAAuB;IACzB;GACF,CAAC;EACH;EACA,IAAI,CAAC,WAAW;GACd,MAAM,WAAW,QAAQ,IAAI;GAC7B,OAAO,KACL;IAAE,YAAY,OAAO;IAAY,SAAS;IAAQ;GAAM,GACxD,eACF;EACF,OAAO,IAAI,sBAAsB;GAC/B,MAAM,YAAY,WAAW,IAAI;GACjC,OAAO,MACL;IAAE,YAAY,OAAO;IAAY,SAAS;GAAO,GACjD,iBACF;EACF,OACE,OAAO,MAAM,+BAA+B;EAE9C,OAAO;CACT,SAAS,iGAAiG;EACxG,IAAI,eAAe,mBACjB,MAAM;EAER,IAAI,IAAI,MAAM,SAAS,SAAS,WAAW,GACzC,OAAO,MAAM,sCAAsC;OAEnD,OAAO,KAAK,EAAE,IAAI,GAAG,wBAAwB;EAE/C,OAAO;CACT;AACF;AAEA,SAAS,QAAQ,SAAkB,OAAwB;CACzD,OAAO,QAAQ,KAAK,WAAW,OAAO,MAAM,KAAK;AACnD;AAEA,SAAS,UAAU,SAAkB,SAA0B;CAC7D,OAAO,QAAQ,KAAK,KAAK,MAAM;AACjC;AAEA,eAAsB,qBACpB,cACe;CACf,MAAM,EAAE,QAAQ,YAAY;CAC5B,MAAM,MACJ,aAAa,SAAS,aAClB,aAAa,QACb,aAAa;CACnB,OAAO,MAAM,qBAAqB,IAAI,QAAQ,QAAQ,YAAY;CAClE,MAAM,WAAW,MAAM,YAAY,OAAO;CAC1C,IAAI,YAAuC;;CAG3C,IAAI,aAAa,SAAS,YAAY;EACpC,MAAM,QAAQ,aAAa;EAC3B,YAAY,SAAS,MAAM,YAAY,QAAQ,SAAS,KAAK,CAAC,CAAC,EAAE;CACnE,OAAO,IAAI,aAAa,SAAS,cAAc;EAC7C,MAAM,UAAU,aAAa;EAC7B,YAAY,SAAS,MAAM,YAAY,UAAU,SAAS,OAAO,CAAC,CAAC,EAAE;CACvE;CAEA,IAAI;;EAEF,IAAI,WAAW;GACb,OAAO,MAAM,kCAAkC,SAAS;GACxD,MAAM,cAAc,SAAS;EAC/B;CACF,SAAS,mHAAmH;EAC1H,OAAO,KAAK,EAAE,IAAI,GAAG,wBAAwB;CAC/C;AACF;AAIA,eAAe,eACb,UACA,UACA,mBACe;CACf,IAAI,CAAC,mBAAmB,sBACtB;CAMF,IACE,eAAe,SACf,OAAO,UAAU,eAAe,YAAa,QAAQ,GACrD;EACA,OAAO,MACL,EAAE,SAAS,GACX,oFACF;EACA;CACF;CAEA,IAAI,CAAC,OAAO,kBAAkB;EAC5B,OAAO,MACL,EAAE,SAAS,GACX,uDACF;EACA;CACF;CAEA,IAAI;EACF,MAAM,eAEF,iBAAiB,kBAAkB,iBAAiB,KACpD,OAAO,YAAA,EACN,YAAY,KAAK;EAEtB,IAAI;EACJ,IAAI;EAIJ,MAAM,yBAAyB,mBAAmB;EAClD,IAAI,gBAAgB,YAAY,wBAAwB;GACtD,MAAM,eAAe,uBAAuB,QAAQ,IAAI;GACxD,IAAI,iBAAiB,IACnB,iBAAiB;QACZ;IACL,iBAAiB,uBAAuB,MAAM,GAAG,YAAY;IAC7D,aAAa,uBAAuB,MAAM,eAAe,CAAC,CAAC,CAAC,KAAK;GACnE;GAGA,iBAAiB,GAAG,eAAe,KAAK,SAAS;EACnD;EASA,MAAM,eAAe;GAAE,WAAA;IANrB,eAAe;IACf;IACA;IACA;GAG6B;GAAG,OAAO;EAAE;EAE3C,MAAM,MAAM,MAAM,UAAU,eAC1B,yBACA,YACF;EAEA,IAAI,KAAK,QAAQ;GACf,OAAO,MACL;IAAE;IAAU,QAAQ,IAAI;GAAO,GAC/B,+BACF;GACA;EACF;EAEA,OAAO,MAAM,4CAA4C,UAAU;CACrE,SAAS,+CAA+C;EACtD,OAAO,KAAK;GAAE;GAAU;EAAI,GAAG,yCAAyC;CAC1E;AACF;AAGA,eAAsB,SAAS,EAC7B,cACA,cACA,SAAS,OACT,QAAQ,SACR,QACA,UAAU,OACV,mBACA,aACuC;CACvC,MAAM,OAAO,SAAS,OAAO;CAC7B,MAAM,OAAO;CAIb,MAAM,OAAO,GAAG,OAAO,WAAY,MAAM,GAAG,CAAC,CAAC,GAAG,GAAG;CACpD,MAAM,UAAe,EACnB,MAAM;EACJ;EACA;EACA;EACA;EACA,OAAO;CACT,EACF;;CAEA,IAAI,OAAO,WAAW;EACpB,QAAQ,QAAQ,OAAO;EACvB,QAAQ,KAAK,wBACX,CAAC,OAAO,WACR,mBAAmB,oCAAoC;CAC3D;CACA,OAAO,MAAM;EAAE;EAAO;EAAM;EAAM,OAAO;CAAQ,GAAG,aAAa;CACjE,MAAM,QACJ,MAAM,UAAU,SACd,SAAS,OAAO,cAAc,OAAO,WAAW,SAChD,OACF,EAAA,CACA;CACF,OAAO,MACL;EAAE,QAAQ;EAAc,IAAI,KAAK;EAAQ,OAAO;CAAQ,GACxD,YACF;CAEA,MAAM,SAAS,aAAa,IAAI;CAChC,MAAM,EAAE,QAAQ,YAAY;CAE5B,MAAM,UAAU,QAAQ,MAAM;CAC9B,MAAM,gBAAgB,QAAQ,SAAS;CACvC,MAAM,eAAe,QAAQ,SAAS,iBAAiB;CAEvD,QAAQ,MAAM;CACd,OAAO;AACT;AAEA,eAAe,oBAAoB,YAAsC;CACvE,MAAM,eAAe,OAAO,kBAAkB;CAC9C,IAAI,iBAAiB,KAAA,GACnB,OAAO;CAKT,IACE,eAAe,SACf,OAAO,UAAU,eAAe,YAAa,SAAS,GACtD;EAEA,OAAO,kBAAkB,cAAc;EACvC,OAAO;CACT;CAIA,IAAI,SAAS;CACb,IAAI;EACF,MAAM,MAAM,MAAM,UAAU,eAEzB,qBAAqB;GACtB,WAAW;IACT,OAAO,OAAO;IACd,MAAM,OAAO;IACb,QAAQ;GACV;GACA,UAAU;GACV,OAAO;EACT,CAAC;EACD,IAAI,KAAK,QACP,OAAO,MACL;GAAE;GAAY,QAAQ,IAAI;EAAO,GACjC,sEACF;OAEA,SAAS,iBAAiB,KAAK,MAAM,YAAY,UAAU;CAE/D,SAAS,KAAK;EACZ,OAAO,MACL;GAAE;GAAY;EAAI,GAClB,qEACF;CACF;CAEA,OAAO,kBAAkB,cAAc;CACvC,OAAO;AACT;AAEA,eAAsB,wBACpB,YACA,YACe;CACf,IAAI,CAAE,MAAM,oBAAoB,cAAc,OAAO,aAAa,GAChE;CAGF,MAAM,KAAK,MAAM,OAAO;EAAE;EAAY,OAAO;CAAO,CAAC;CACrD,IAAI,CAAC,IACH;CAGF,IACE,MAAM,iBACJ,WACA,OAAO,iBACP,OAAO,gBACP,GAAG,MACL,GACA;EACA,OAAO,MAAM,OAAO,GAAG,OAAO,uCAAuC;EACrE,MAAM,IAAI,MAAM,yBAAyB;CAC3C;AACF;AAEA,eAAsB,SAAS,EAC7B,QAAQ,MACR,SAAS,OACT,QAAQ,SACR,WAAW,aACX,cACA,OACA,gBACgC;CAChC,OAAO,MAAM,YAAY,KAAK,IAAI,MAAM,QAAQ;CAChD,MAAM,OAAO,SAAS,OAAO;CAC7B,MAAM,YAAiB,EAAE,MAAM;;CAE/B,IAAI,MACF,UAAU,OAAO;CAEnB,IAAI,cACF,UAAU,OAAO;CAEnB,IAAI,OACF,UAAU,QAAQ;CAEpB,MAAM,UAAe,EACnB,MAAM,UACR;;CAEA,IAAI,OAAO,WACT,QAAQ,QAAQ,OAAO;CAIzB,IAAI;EACF,IAAI,aACF,MAAM,UAAU,MAAM,WAAW;EAGnC,IAAI,cACF,KAAK,MAAM,SAAS,cAClB,MAAM,YAAY,MAAM,KAAK;EAIjC,MAAM,EAAE,MAAM,SAAS,MAAM,UAAU,UACrC,SAAS,OAAO,cAAc,OAAO,WAAW,SAAS,QACzD,OACF;EAEA,QADe,aAAa,IACf,CAAC;EACd,OAAO,MAAM,sBAAsB,MAAM;CAC3C,SAAS,oGAAoG;EAC3G,IAAI,eAAe,mBACjB,MAAM;EAER,OAAO,KAAK,EAAE,IAAI,GAAG,mBAAmB;CAC1C;AACF;AAEA,eAAsB,2BAA2B,EAC/C,QACA,qBACkD;CAClD,IAAI;EAEF,MAAM,EAAE,YAAY,MADE,MAAM,MAAM;EAGlC,MAAM,eAAe,QAAQ,SAAS,iBAAiB;EAEvD,OAAO,MAAM,8CAA8C,QAAQ;CACrE,SAAS,uHAAuH;EAC9H,OAAO,KAAK,EAAE,IAAI,GAAG,2CAA2C;CAClE;AACF;AAEA,eAAsB,QAAQ,EAC5B,YACA,IAAI,MACJ,YACkC;CAClC,OAAO,MAAM,WAAW,KAAK,IAAI,WAAW,EAAE;CAC9C,MAAM,MAAM,SACV,OAAO,cAAc,OAAO,WAC7B,SAAS,KAAK;CACf,MAAM,UAA6B,EACjC,MAAM,CAAC,EACT;;CAEA,IAAI,OAAO,WACT,QAAQ,QAAQ,OAAO;CAEzB,IAAI,aAAa;CACjB,IAAI;CACJ,MAAM,gBAAgB,iBAAiB,QAAQ,KAAK,OAAO;;CAG3D,IAAI,eAAe;EAGjB,QAAQ,KAAK,eAAe;EAC5B,IAAI;GACF,OAAO,MAAM;IAAE;IAAS;GAAI,GAAG,SAAS;GACxC,kBAAkB,MAAM,UAAU,QAAQ,KAAK,OAAO;GACtD,aAAa;EACf,SAAS,iHAAiH;GACxH,IAAI,IAAI,eAAe,OAAO,IAAI,eAAe,KAAK;IACpD,MAAM,OAAO,IAAI,UAAU;IAC3B,IACE,iBAAiB,MAAM,OAAO,KAC9B,MAAM,4CAA4C,CAAC,CAAC,KAAK,KAAK,OAAO,GACrE;KACA,OAAO,MACL,EAAE,UAAU,KAAK,GACjB,8DACF;KACA,OAAO;IACT;IACA,IACE,iBAAiB,MAAM,OAAO,MAC7B,KAAK,QAAQ,SAAS,kBAAkB,KACvC,KAAK,QAAQ,SAAS,mBAAmB,KACzC,KAAK,QAAQ,SACX,sEACF,IACF;KACA,OAAO,MACL,EAAE,UAAU,KAAK,GACjB,uDACF;KACA,OAAO;IACT;IACA,OAAO,MACL,EAAE,UAAU,KAAK,GACjB,8CACF;GACF,OAAO;IACL,OAAO,KACL;KAAE,aAAa,OAAO;KAAa;IAAI,GACvC,oBACF;IACA,OAAO;GACT;EACF;CACF;CACA,IAAI,CAAC,YAAY;EAEf,QAAQ,KAAK,eAAe;EAC5B,IAAI;GACF,OAAO,MAAM;IAAE;IAAS;GAAI,GAAG,SAAS;GACxC,kBAAkB,MAAM,UAAU,QAAQ,KAAK,OAAO;EACxD,SAAS,MAAM;GACb,OAAO,MAAM,EAAE,KAAK,KAAK,GAAG,2BAA2B;GACvD,IAAI;IACF,QAAQ,KAAK,eAAe;IAC5B,OAAO,MAAM;KAAE;KAAS;IAAI,GAAG,SAAS;IACxC,kBAAkB,MAAM,UAAU,QAAQ,KAAK,OAAO;GACxD,SAAS,MAAM;IACb,OAAO,MAAM,EAAE,KAAK,KAAK,GAAG,2BAA2B;IACvD,IAAI;KACF,QAAQ,KAAK,eAAe;KAC5B,OAAO,MAAM;MAAE;MAAS;KAAI,GAAG,SAAS;KACxC,kBAAkB,MAAM,UAAU,QAAQ,KAAK,OAAO;IACxD,SAAS,MAAM;KACb,OAAO,MAAM,EAAE,KAAK,KAAK,GAAG,2BAA2B;KACvD,OAAO,KAAK,EAAE,IAAI,KAAK,GAAG,2BAA2B;KACrD,OAAO;IACT;GACF;EACF;CACF;CACA,OAAO,MACL;EAAE,iBAAiB,gBAAiB;EAAM,IAAI;CAAK,GACnD,WACF;CACA,MAAM,WAAW,OAAO,QAAQ,MAAM,EAAE,aAAa,WAAW,IAAI;CACpE,IAAI,UACF,QAAQ;EAAE,GAAG;EAAU,OAAO;CAAS,CAAC;CAE1C,OAAO;AACT;AAEA,SAAgB,gBAAgB,OAAuB;CACrD,IAAI,eAAe,OACjB,OAAO,cAAc,OAAO,cAAc,CAAC;CAE7C,MAAM,gBAAgB,qBAAqB,KAAK,CAAC,CAE9C,QACC,MAAM,gCAAgC,GACtC,qCACF,CAAC,CACA,QACC,MAAM,6BAA6B,GACnC,gCACF,CAAC,CACA,QACC,MAAM,6BAA6B,GACnC,iCACF,CAAC,CACA,WAAW,sBAAsB,aAAa,CAAC,CAC/C,WAAW,uBAAuB,aAAa,CAAC,CAChD,WAAW,yBAAyB,gBAAgB,CAAC,CACrD,WAAW,0BAA0B,gBAAgB,CAAC,CACtD,WAAW,yBAAyB,gBAAgB,CAAC,CACrD,WAAW,2BAA2B,kBAAkB;CAC3D,OAAO,cAAc,eAAe,cAAc,CAAC;AACrD;AAEA,SAAgB,gBAAwB;CACtC,OAAO;AACT;AAEA,eAAsB,yBAA6D;;CAEjF,IAAI,OAAO,kCAAkC,OAAO;EAClD,OAAO,MAAM,0CAA0C;EACvD,OAAO,CAAC;CACV;CACA,IAAI;CACJ,IAAI;EACF,uBACE,MAAM,UAAU,QACd,UAAU,OAAO,gBAAgB,GAAG,OAAO,eAAe,2DAC1D;GACE,UAAU;GACV,SAAS,EAAE,QAAQ,8BAA8B;GACjD,eAAe;EACjB,GACA,yBACF,EAAA,CACA;CACJ,SAAS,qGAAqG;EAC5G,OAAO,MAAM,EAAE,IAAI,GAAG,uCAAuC;EAC7D,OAAO,KACL,EACE,KAAK,GAAG,aAAa,IAAI,cAAc,CAAC,CAAC,cAAc,4CACzD,GACA,kFACF;CACF;CACA,IAAI;EACF,IAAI,qBAAqB,QAAQ;GAC/B,MAAM,cAAyC,CAAC;GAChD,OAAO,MACL,EAAE,QAAQ,oBAAoB,GAC9B,8BACF;GACA,KAAK,MAAM,SAAS,qBAAqB;;IAEvC,IAAI,MAAM,2BAA2B,MAInC;IAEF,MAAM,EACJ,SAAS,EAAE,MAAM,aACjB,0BAA0B,wBAC1B,uBAAuB,wBACrB,MAAM;IACV,MAAM,QAAQ,qBAAqB;IAEnC,MAAM,iBACJ,cAAc,QAAQ,uBAAuB,IAAI,IAAI;IACvD,MAAM,uBAAuB,QAAQ,OAAO;IAC5C,MAAM,MAAM,GAAG,UAAU,YAAY,EAAE,GAAG;IAC1C,MAAM,QAAQ;IACd,MAAM,OAAO,YAAY,QAAQ,CAAC;IAClC,KAAK,SAAS,aAAa,KAAK;IAChC,YAAY,OAAO;GACrB;GACA,OAAO,MAAM,EAAE,QAAQ,YAAY,GAAG,8BAA8B;EACtE,OACE,OAAO,MAAM,+BAA+B;CAEhD,SAAS,iGAAiG;EACxG,OAAO,MAAM,EAAE,IAAI,GAAG,qCAAqC;CAC7D;CACA,OAAO,uBAAuB,CAAC;AACjC;AAEA,eAAe,UACb,EAAE,YAAY,SAAS,YACvB,EAAE,iBAAiB,aACY;CAC/B,IAAI;EAWF,MAAM,wBAAwB,WAAW,UAAU;EACnD,MAAM,cAAc,MAAM,iBAAiB,eAAe;EAC1D,MAAM,YAAY,MAAM,eAAe,iBAAiB,SAAS;EAEjE,IAAI,UAAU,WAAW,GAAG;GAC1B,OAAO,MACL,EAAE,WAAW,GACb,0DACF;GACA,OAAO;EACT;EAMA,MAAM,WAAU,MAJM,UAAU,SAC9B,UAAU,OAAO,WAAW,aAC5B,EAAE,MAAM;GAAE,WAAW;GAAa,MAAM;EAAU,EAAE,CACtD,EAAA,CACwB,KAAK;EAE7B,MAAM,gBAAgB,oBAAoB,SAAS,QAAQ;EAG3D,MAAM,YAAY,MAAM,UAAU,SAChC,UAAU,OAAO,WAAW,eAC5B,EACE,MAAM;GACJ,SAAS;GACT,MAAM;GACN,SAAS,CAAC,eAAe;EAC3B,EACF,CACF;EACA,gBAAgB,SAAS;EACzB,MAAM,kBAAkB,gBAAgB,UAAU,KAAK,GAAG;EAC1D,MAAM,gBAAgB,YAAY,eAAe;EACjD,OAAO;CACT,SAAS,KAAK;EACZ,OAAO,MAAM;GAAE;GAAY;EAAI,GAAG,uCAAuC;EACzE,OAAO;CACT;AACF;AAEA,eAAsB,YACpB,QAC+B;CAC/B,MAAM,eAAe,MAAMI,cAAkB,MAAM;CACnD,MAAM,EAAE,YAAY,UAAU;CAC9B,IAAI,CAAC,cAAc;EACjB,OAAO,MACL;GAAE;GAAY,OAAO,MAAM,KAAK,EAAE,WAAW,IAAI;EAAE,GACnD,sDACF;EACA,OAAO;CACT;CAGA,IAAI,CAAC,MADoB,UAAU,QAAQ,YAAY,GAErD,OAAO;CAIT,MAAMC,cAAkB,aAAa,eAAe;CAEpD,OAAO,MADiBC,YAAgB,UAAU;AAEpD"}
|
|
@@ -11,7 +11,7 @@ function getMajor(version) {
|
|
|
11
11
|
const options = getOptions(version);
|
|
12
12
|
options.includePrerelease = true;
|
|
13
13
|
const cleanerVersion = makeVersion(cleanedVersion, options);
|
|
14
|
-
if (isString(cleanerVersion)) return
|
|
14
|
+
if (isString(cleanerVersion)) return parseInt(cleanerVersion.split(".")[0], 10);
|
|
15
15
|
return null;
|
|
16
16
|
}
|
|
17
17
|
function getMinor(version) {
|
|
@@ -19,7 +19,7 @@ function getMinor(version) {
|
|
|
19
19
|
const options = getOptions(version);
|
|
20
20
|
options.includePrerelease = true;
|
|
21
21
|
const cleanerVersion = makeVersion(cleanedVersion, options);
|
|
22
|
-
if (isString(cleanerVersion)) return
|
|
22
|
+
if (isString(cleanerVersion)) return parseInt(cleanerVersion.split(".")[1], 10);
|
|
23
23
|
return null;
|
|
24
24
|
}
|
|
25
25
|
function getPatch(version) {
|
|
@@ -29,7 +29,8 @@ function getPatch(version) {
|
|
|
29
29
|
const cleanerVersion = makeVersion(cleanedVersion, options);
|
|
30
30
|
if (isString(cleanerVersion)) {
|
|
31
31
|
const newVersion = semver$1.valid(semver$1.coerce(cleanedVersion, { loose: false }), options);
|
|
32
|
-
|
|
32
|
+
/* v8 ignore next -- newVersion always has a patch segment once cleanerVersion is a valid, coercible semver string */
|
|
33
|
+
return parseInt(coerceString(newVersion).split(".")[2] ?? "", 10);
|
|
33
34
|
}
|
|
34
35
|
return null;
|
|
35
36
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"range.js","names":["semver"],"sources":["../../../../lib/modules/versioning/conan/range.ts"],"sourcesContent":["import { isString } from '@sindresorhus/is';\nimport * as semver from 'semver';\nimport type { SemVer } from 'semver-utils';\nimport { parseRange } from 'semver-utils';\nimport { logger } from '../../../logger/index.ts';\nimport { regEx } from '../../../util/regex.ts';\nimport { coerceString } from '../../../util/string.ts';\nimport type { NewValueConfig } from '../types.ts';\nimport {\n cleanVersion,\n containsOperators,\n getOptions,\n makeVersion,\n matchesWithOptions,\n} from './common.ts';\n\n// always include prereleases\nexport function getMajor(version: string): null | number {\n const cleanedVersion = cleanVersion(version);\n const options = getOptions(version);\n options.includePrerelease = true;\n const cleanerVersion = makeVersion(cleanedVersion, options);\n if (isString(cleanerVersion)) {\n return Number(cleanerVersion.split('.')[0]);\n }\n return null;\n}\n\n// always include prereleases\nexport function getMinor(version: string): null | number {\n const cleanedVersion = cleanVersion(version);\n const options = getOptions(version);\n options.includePrerelease = true;\n const cleanerVersion = makeVersion(cleanedVersion, options);\n if (isString(cleanerVersion)) {\n return Number(cleanerVersion.split('.')[1]);\n }\n return null;\n}\n\n// always include prereleases\nexport function getPatch(version: string): null | number {\n const cleanedVersion = cleanVersion(version);\n const options = getOptions(version);\n options.includePrerelease = true;\n const cleanerVersion = makeVersion(cleanedVersion, options);\n\n if (isString(cleanerVersion)) {\n const newVersion = semver.valid(\n semver.coerce(cleanedVersion, {\n loose: false,\n }),\n options,\n );\n return Number(newVersion?.split('.')[2]);\n }\n return null;\n}\n\nexport function fixParsedRange(range: string): any {\n const ordValues = [];\n\n // don't bump or'd single version values\n const originalSplit = range.split(' ');\n for (let i = 0; i < originalSplit.length; i += 1) {\n if (\n !containsOperators(originalSplit[i]) &&\n !originalSplit[i].includes('||')\n ) {\n if (i !== 0 && originalSplit[i - 1].includes('||')) {\n ordValues.push(`|| ${originalSplit[i]}`);\n } else if (i !== originalSplit.length && originalSplit[i + 1] === '||') {\n ordValues.push(`${originalSplit[i]} ||`);\n }\n } else {\n ordValues.push(originalSplit[i]);\n }\n }\n\n const parsedRange = parseRange(range);\n const cleanRange = range.replace(regEx(/([<=>^~])( )?/g), '');\n const splitRange = cleanRange.split(' ');\n const semverRange: SemVer[] = [];\n\n for (let i = 0; i < splitRange.length; i += 1) {\n if (!splitRange[i].includes('||')) {\n const splitVersion = splitRange[i].split('.');\n const major = splitVersion[0];\n const minor = splitVersion[1];\n const patch = splitVersion[2];\n const operator = ordValues[i].includes('||')\n ? '||'\n : parsedRange[i].operator;\n const NewSemVer: SemVer = {\n major,\n };\n\n let full = `${coerceString(operator)}${major}`;\n if (minor) {\n NewSemVer.minor = minor;\n full = `${full}.${minor}`;\n if (patch) {\n NewSemVer.patch = patch;\n full = `${full}.${patch}`;\n }\n }\n /* v8 ignore next -- a segment with no operator is only reachable when adjacent to `||`, which always makes `operator` truthy (`'||'`) above; any other bare segment throws earlier at ordValues[i] */\n if (operator) {\n NewSemVer.operator = operator;\n full = range.includes(`${operator} `)\n ? `${operator} ${full.replace(operator, '')}`\n : `${operator}${full.replace(operator, '')}`;\n }\n\n full = ordValues[i].includes('||') ? ordValues[i] : full;\n\n NewSemVer.semver = full;\n\n semverRange.push(NewSemVer);\n }\n }\n return semverRange;\n}\n\nexport function replaceRange({\n currentValue,\n newVersion,\n}: NewValueConfig): string {\n const parsedRange = parseRange(currentValue);\n const element = parsedRange.at(-1)!;\n const toVersionMajor = getMajor(newVersion);\n const toVersionMinor = getMinor(newVersion);\n const toVersionPatch = getPatch(newVersion);\n const suffix = semver.prerelease(newVersion)\n ? `-${String(semver.prerelease(newVersion)?.[0])}`\n : '';\n\n if (element.operator === '~>') {\n return `~> ${toVersionMajor}.${toVersionMinor}.0`;\n }\n if (element.operator === '=') {\n return `=${newVersion}`;\n }\n if (element.operator === '~') {\n if (suffix.length) {\n return `~${toVersionMajor}.${toVersionMinor}.${toVersionPatch}${suffix}`;\n }\n return `~${toVersionMajor}.${toVersionMinor}.0`;\n }\n if (element.operator === '<=') {\n let res;\n if (!!element.patch || suffix.length) {\n res = `<=${newVersion}`;\n } else if (element.minor) {\n res = `<=${toVersionMajor}.${toVersionMinor}`;\n } else {\n res = `<=${toVersionMajor}`;\n }\n if (currentValue.includes('<= ')) {\n res = res.replace('<=', '<= ');\n }\n return res;\n }\n if (element.operator === '<' && toVersionMajor) {\n let res;\n if (currentValue.endsWith('.0.0')) {\n const newMajor = toVersionMajor + 1;\n res = `<${newMajor}.0.0`;\n } else if (element.patch) {\n res = `<${semver.inc(newVersion, 'patch')}`;\n } else if (element.minor && toVersionMinor) {\n res = `<${toVersionMajor}.${toVersionMinor + 1}`;\n } else {\n res = `<${toVersionMajor + 1}`;\n }\n if (currentValue.includes('< ')) {\n res = res.replace(regEx(/</g), '< ');\n }\n return res;\n }\n if (element.operator === '>') {\n let res;\n if (currentValue.endsWith('.0.0') && toVersionMajor) {\n const newMajor = toVersionMajor + 1;\n res = `>${newMajor}.0.0`;\n } else if (element.patch) {\n res = `>${toVersionMajor}.${toVersionMinor}.${toVersionPatch}`;\n } else if (element.minor) {\n res = `>${toVersionMajor}.${toVersionMinor}`;\n } else {\n res = `>${toVersionMajor}`;\n }\n if (currentValue.includes('> ')) {\n res = res.replace(regEx(/</g), '> ');\n }\n return res;\n }\n if (!element.operator) {\n if (element.minor) {\n if (element.minor === 'x') {\n return `${toVersionMajor}.x`;\n }\n if (element.minor === '*') {\n return `${toVersionMajor}.*`;\n }\n if (element.patch === 'x') {\n return `${toVersionMajor}.${toVersionMinor}.x`;\n }\n if (element.patch === '*') {\n return `${toVersionMajor}.${toVersionMinor}.*`;\n }\n return `${newVersion}`;\n }\n return `${toVersionMajor}`;\n }\n return newVersion;\n}\n\nexport function widenRange(\n { currentValue, currentVersion, newVersion }: NewValueConfig,\n options: semver.Options,\n): string | null {\n const parsedRange = parseRange(currentValue);\n const element = parsedRange.at(-1)!;\n\n if (matchesWithOptions(newVersion, currentValue, options)) {\n return currentValue;\n }\n const newValue = replaceRange({\n currentValue,\n rangeStrategy: 'replace',\n currentVersion,\n newVersion,\n });\n if (element.operator?.startsWith('<')) {\n const splitCurrent = currentValue.split(element.operator);\n splitCurrent.pop();\n return splitCurrent.join(element.operator) + newValue;\n }\n if (parsedRange.length > 1) {\n const previousElement = parsedRange.at(-2)!;\n if (previousElement.operator === '-') {\n const splitCurrent = currentValue.split('-');\n splitCurrent.pop();\n return `${splitCurrent.join('-')}- ${newValue}`;\n }\n if (element.operator?.startsWith('>')) {\n logger.warn(`Complex ranges ending in greater than are not supported`);\n return null;\n }\n }\n return `${currentValue} || ${newValue}`;\n}\n\nexport function bumpRange(\n { currentValue, currentVersion, newVersion }: NewValueConfig,\n options: semver.Options,\n): string | null {\n if (!containsOperators(currentValue) && currentValue.includes('||')) {\n return widenRange(\n {\n currentValue,\n rangeStrategy: 'widen',\n currentVersion,\n newVersion,\n },\n options,\n );\n }\n const parsedRange = parseRange(currentValue);\n const element = parsedRange.at(-1)!;\n\n const toVersionMajor = getMajor(newVersion);\n const toVersionMinor = getMinor(newVersion);\n const suffix = semver.prerelease(newVersion)\n ? `-${String(semver.prerelease(newVersion)?.[0])}`\n : '';\n\n if (parsedRange.length === 1) {\n if (!element.operator) {\n return replaceRange({\n currentValue,\n rangeStrategy: 'replace',\n currentVersion,\n newVersion,\n });\n }\n if (element.operator.startsWith('~')) {\n const split = currentValue.split('.');\n if (suffix.length) {\n return `${element.operator}${newVersion}`;\n }\n if (split.length === 1) {\n // ~4\n return `${element.operator}${toVersionMajor}`;\n }\n if (split.length === 2) {\n // ~4.1\n return `${element.operator}${toVersionMajor}.${toVersionMinor}`;\n }\n return `${element.operator}${newVersion}`;\n }\n if (element.operator === '=') {\n return `=${newVersion}`;\n }\n if (element.operator === '>=') {\n return currentValue.includes('>= ')\n ? `>= ${newVersion}`\n : `>=${newVersion}`;\n }\n if (element.operator.startsWith('<')) {\n return currentValue;\n }\n } else {\n const newRange = fixParsedRange(currentValue);\n const versions = newRange.map((x: any) => {\n // don't bump or'd single version values\n if (x.operator === '||') {\n return x.semver;\n }\n /* v8 ignore next -- fixParsedRange only ever produces elements with `operator === '||'` (handled above) or a real comparator operator; a falsy, non-`||` operator would have already thrown inside fixParsedRange */\n if (x.operator) {\n const bumpedSubRange = bumpRange(\n {\n currentValue: x.semver,\n rangeStrategy: 'bump',\n currentVersion,\n newVersion,\n },\n options,\n );\n if (\n bumpedSubRange &&\n matchesWithOptions(newVersion, bumpedSubRange, options)\n ) {\n return bumpedSubRange;\n }\n }\n\n return replaceRange({\n currentValue: x.semver,\n rangeStrategy: 'replace',\n currentVersion,\n newVersion,\n });\n });\n return versions.filter((x: any) => x !== null && x !== '').join(' ');\n }\n logger.debug(\n `Unsupported range type for rangeStrategy=bump: ${currentValue}`,\n );\n return null;\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"range.js","names":["semver"],"sources":["../../../../lib/modules/versioning/conan/range.ts"],"sourcesContent":["import { isString } from '@sindresorhus/is';\nimport * as semver from 'semver';\nimport type { SemVer } from 'semver-utils';\nimport { parseRange } from 'semver-utils';\nimport { logger } from '../../../logger/index.ts';\nimport { regEx } from '../../../util/regex.ts';\nimport { coerceString } from '../../../util/string.ts';\nimport type { NewValueConfig } from '../types.ts';\nimport {\n cleanVersion,\n containsOperators,\n getOptions,\n makeVersion,\n matchesWithOptions,\n} from './common.ts';\n\n// always include prereleases\nexport function getMajor(version: string): null | number {\n const cleanedVersion = cleanVersion(version);\n const options = getOptions(version);\n options.includePrerelease = true;\n const cleanerVersion = makeVersion(cleanedVersion, options);\n if (isString(cleanerVersion)) {\n return parseInt(cleanerVersion.split('.')[0], 10);\n }\n return null;\n}\n\n// always include prereleases\nexport function getMinor(version: string): null | number {\n const cleanedVersion = cleanVersion(version);\n const options = getOptions(version);\n options.includePrerelease = true;\n const cleanerVersion = makeVersion(cleanedVersion, options);\n if (isString(cleanerVersion)) {\n return parseInt(cleanerVersion.split('.')[1], 10);\n }\n return null;\n}\n\n// always include prereleases\nexport function getPatch(version: string): null | number {\n const cleanedVersion = cleanVersion(version);\n const options = getOptions(version);\n options.includePrerelease = true;\n const cleanerVersion = makeVersion(cleanedVersion, options);\n\n if (isString(cleanerVersion)) {\n const newVersion = semver.valid(\n semver.coerce(cleanedVersion, {\n loose: false,\n }),\n options,\n );\n /* v8 ignore next -- newVersion always has a patch segment once cleanerVersion is a valid, coercible semver string */\n return parseInt(coerceString(newVersion).split('.')[2] ?? '', 10);\n }\n return null;\n}\n\nexport function fixParsedRange(range: string): any {\n const ordValues = [];\n\n // don't bump or'd single version values\n const originalSplit = range.split(' ');\n for (let i = 0; i < originalSplit.length; i += 1) {\n if (\n !containsOperators(originalSplit[i]) &&\n !originalSplit[i].includes('||')\n ) {\n if (i !== 0 && originalSplit[i - 1].includes('||')) {\n ordValues.push(`|| ${originalSplit[i]}`);\n } else if (i !== originalSplit.length && originalSplit[i + 1] === '||') {\n ordValues.push(`${originalSplit[i]} ||`);\n }\n } else {\n ordValues.push(originalSplit[i]);\n }\n }\n\n const parsedRange = parseRange(range);\n const cleanRange = range.replace(regEx(/([<=>^~])( )?/g), '');\n const splitRange = cleanRange.split(' ');\n const semverRange: SemVer[] = [];\n\n for (let i = 0; i < splitRange.length; i += 1) {\n if (!splitRange[i].includes('||')) {\n const splitVersion = splitRange[i].split('.');\n const major = splitVersion[0];\n const minor = splitVersion[1];\n const patch = splitVersion[2];\n const operator = ordValues[i].includes('||')\n ? '||'\n : parsedRange[i].operator;\n const NewSemVer: SemVer = {\n major,\n };\n\n let full = `${coerceString(operator)}${major}`;\n if (minor) {\n NewSemVer.minor = minor;\n full = `${full}.${minor}`;\n if (patch) {\n NewSemVer.patch = patch;\n full = `${full}.${patch}`;\n }\n }\n /* v8 ignore next -- a segment with no operator is only reachable when adjacent to `||`, which always makes `operator` truthy (`'||'`) above; any other bare segment throws earlier at ordValues[i] */\n if (operator) {\n NewSemVer.operator = operator;\n full = range.includes(`${operator} `)\n ? `${operator} ${full.replace(operator, '')}`\n : `${operator}${full.replace(operator, '')}`;\n }\n\n full = ordValues[i].includes('||') ? ordValues[i] : full;\n\n NewSemVer.semver = full;\n\n semverRange.push(NewSemVer);\n }\n }\n return semverRange;\n}\n\nexport function replaceRange({\n currentValue,\n newVersion,\n}: NewValueConfig): string {\n const parsedRange = parseRange(currentValue);\n const element = parsedRange.at(-1)!;\n const toVersionMajor = getMajor(newVersion);\n const toVersionMinor = getMinor(newVersion);\n const toVersionPatch = getPatch(newVersion);\n const suffix = semver.prerelease(newVersion)\n ? `-${String(semver.prerelease(newVersion)?.[0])}`\n : '';\n\n if (element.operator === '~>') {\n return `~> ${toVersionMajor}.${toVersionMinor}.0`;\n }\n if (element.operator === '=') {\n return `=${newVersion}`;\n }\n if (element.operator === '~') {\n if (suffix.length) {\n return `~${toVersionMajor}.${toVersionMinor}.${toVersionPatch}${suffix}`;\n }\n return `~${toVersionMajor}.${toVersionMinor}.0`;\n }\n if (element.operator === '<=') {\n let res;\n if (!!element.patch || suffix.length) {\n res = `<=${newVersion}`;\n } else if (element.minor) {\n res = `<=${toVersionMajor}.${toVersionMinor}`;\n } else {\n res = `<=${toVersionMajor}`;\n }\n if (currentValue.includes('<= ')) {\n res = res.replace('<=', '<= ');\n }\n return res;\n }\n if (element.operator === '<' && toVersionMajor) {\n let res;\n if (currentValue.endsWith('.0.0')) {\n const newMajor = toVersionMajor + 1;\n res = `<${newMajor}.0.0`;\n } else if (element.patch) {\n res = `<${semver.inc(newVersion, 'patch')}`;\n } else if (element.minor && toVersionMinor) {\n res = `<${toVersionMajor}.${toVersionMinor + 1}`;\n } else {\n res = `<${toVersionMajor + 1}`;\n }\n if (currentValue.includes('< ')) {\n res = res.replace(regEx(/</g), '< ');\n }\n return res;\n }\n if (element.operator === '>') {\n let res;\n if (currentValue.endsWith('.0.0') && toVersionMajor) {\n const newMajor = toVersionMajor + 1;\n res = `>${newMajor}.0.0`;\n } else if (element.patch) {\n res = `>${toVersionMajor}.${toVersionMinor}.${toVersionPatch}`;\n } else if (element.minor) {\n res = `>${toVersionMajor}.${toVersionMinor}`;\n } else {\n res = `>${toVersionMajor}`;\n }\n if (currentValue.includes('> ')) {\n res = res.replace(regEx(/</g), '> ');\n }\n return res;\n }\n if (!element.operator) {\n if (element.minor) {\n if (element.minor === 'x') {\n return `${toVersionMajor}.x`;\n }\n if (element.minor === '*') {\n return `${toVersionMajor}.*`;\n }\n if (element.patch === 'x') {\n return `${toVersionMajor}.${toVersionMinor}.x`;\n }\n if (element.patch === '*') {\n return `${toVersionMajor}.${toVersionMinor}.*`;\n }\n return `${newVersion}`;\n }\n return `${toVersionMajor}`;\n }\n return newVersion;\n}\n\nexport function widenRange(\n { currentValue, currentVersion, newVersion }: NewValueConfig,\n options: semver.Options,\n): string | null {\n const parsedRange = parseRange(currentValue);\n const element = parsedRange.at(-1)!;\n\n if (matchesWithOptions(newVersion, currentValue, options)) {\n return currentValue;\n }\n const newValue = replaceRange({\n currentValue,\n rangeStrategy: 'replace',\n currentVersion,\n newVersion,\n });\n if (element.operator?.startsWith('<')) {\n const splitCurrent = currentValue.split(element.operator);\n splitCurrent.pop();\n return splitCurrent.join(element.operator) + newValue;\n }\n if (parsedRange.length > 1) {\n const previousElement = parsedRange.at(-2)!;\n if (previousElement.operator === '-') {\n const splitCurrent = currentValue.split('-');\n splitCurrent.pop();\n return `${splitCurrent.join('-')}- ${newValue}`;\n }\n if (element.operator?.startsWith('>')) {\n logger.warn(`Complex ranges ending in greater than are not supported`);\n return null;\n }\n }\n return `${currentValue} || ${newValue}`;\n}\n\nexport function bumpRange(\n { currentValue, currentVersion, newVersion }: NewValueConfig,\n options: semver.Options,\n): string | null {\n if (!containsOperators(currentValue) && currentValue.includes('||')) {\n return widenRange(\n {\n currentValue,\n rangeStrategy: 'widen',\n currentVersion,\n newVersion,\n },\n options,\n );\n }\n const parsedRange = parseRange(currentValue);\n const element = parsedRange.at(-1)!;\n\n const toVersionMajor = getMajor(newVersion);\n const toVersionMinor = getMinor(newVersion);\n const suffix = semver.prerelease(newVersion)\n ? `-${String(semver.prerelease(newVersion)?.[0])}`\n : '';\n\n if (parsedRange.length === 1) {\n if (!element.operator) {\n return replaceRange({\n currentValue,\n rangeStrategy: 'replace',\n currentVersion,\n newVersion,\n });\n }\n if (element.operator.startsWith('~')) {\n const split = currentValue.split('.');\n if (suffix.length) {\n return `${element.operator}${newVersion}`;\n }\n if (split.length === 1) {\n // ~4\n return `${element.operator}${toVersionMajor}`;\n }\n if (split.length === 2) {\n // ~4.1\n return `${element.operator}${toVersionMajor}.${toVersionMinor}`;\n }\n return `${element.operator}${newVersion}`;\n }\n if (element.operator === '=') {\n return `=${newVersion}`;\n }\n if (element.operator === '>=') {\n return currentValue.includes('>= ')\n ? `>= ${newVersion}`\n : `>=${newVersion}`;\n }\n if (element.operator.startsWith('<')) {\n return currentValue;\n }\n } else {\n const newRange = fixParsedRange(currentValue);\n const versions = newRange.map((x: any) => {\n // don't bump or'd single version values\n if (x.operator === '||') {\n return x.semver;\n }\n /* v8 ignore next -- fixParsedRange only ever produces elements with `operator === '||'` (handled above) or a real comparator operator; a falsy, non-`||` operator would have already thrown inside fixParsedRange */\n if (x.operator) {\n const bumpedSubRange = bumpRange(\n {\n currentValue: x.semver,\n rangeStrategy: 'bump',\n currentVersion,\n newVersion,\n },\n options,\n );\n if (\n bumpedSubRange &&\n matchesWithOptions(newVersion, bumpedSubRange, options)\n ) {\n return bumpedSubRange;\n }\n }\n\n return replaceRange({\n currentValue: x.semver,\n rangeStrategy: 'replace',\n currentVersion,\n newVersion,\n });\n });\n return versions.filter((x: any) => x !== null && x !== '').join(' ');\n }\n logger.debug(\n `Unsupported range type for rangeStrategy=bump: ${currentValue}`,\n );\n return null;\n}\n"],"mappings":"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"}
|
|
@@ -13,17 +13,17 @@ function isGreaterThan(version, other) {
|
|
|
13
13
|
function getMajor(version) {
|
|
14
14
|
const parts = getParts(version);
|
|
15
15
|
if (parts === null) return null;
|
|
16
|
-
return
|
|
16
|
+
return parseFloat(parts.major.join("."));
|
|
17
17
|
}
|
|
18
18
|
function getMinor(version) {
|
|
19
19
|
const parts = getParts(version);
|
|
20
20
|
if (parts === null || parts.minor.length === 0) return null;
|
|
21
|
-
return
|
|
21
|
+
return parseFloat(parts.minor.join("."));
|
|
22
22
|
}
|
|
23
23
|
function getPatch(version) {
|
|
24
24
|
const parts = getParts(version);
|
|
25
25
|
if (parts === null || parts.patch.length === 0) return null;
|
|
26
|
-
return
|
|
26
|
+
return parseFloat(`${parts.patch[0]}.${parts.patch.slice(1).join("")}`);
|
|
27
27
|
}
|
|
28
28
|
function matches(version, range) {
|
|
29
29
|
const parsed = parseRange(range);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../../../../lib/modules/versioning/pvp/index.ts"],"sourcesContent":["import { isString } from '@sindresorhus/is';\nimport { logger } from '../../../logger/index.ts';\nimport type { RangeStrategy } from '../../../types/versioning.ts';\nimport { regEx } from '../../../util/regex.ts';\nimport type { NewValueConfig, VersioningApi } from '../types.ts';\nimport { parseRange } from './range.ts';\nimport { compareIntArray, extractAllParts, getParts, plusOne } from './util.ts';\n\nexport const id = 'pvp';\nexport const displayName = 'Package Versioning Policy (Haskell)';\nexport const urls = [\n '[Haskell Package Versioning Policy](https://pvp.haskell.org)',\n];\nexport const supportsRanges = true;\nexport const supportedRangeStrategies: RangeStrategy[] = ['widen'];\n\nconst digitsAndDots = regEx(/^[\\d.]+$/);\n\nfunction isGreaterThan(version: string, other: string): boolean {\n const versionIntMajor = extractAllParts(version);\n const otherIntMajor = extractAllParts(other);\n if (versionIntMajor === null || otherIntMajor === null) {\n return false;\n }\n return compareIntArray(versionIntMajor, otherIntMajor) === 'gt';\n}\n\nfunction getMajor(version: string): number | null {\n // This basically can't be implemented correctly, since\n // 1.1 and 1.10 become equal when converted to float.\n // Consumers should use isSame instead.\n const parts = getParts(version);\n if (parts === null) {\n return null;\n }\n return Number(parts.major.join('.'));\n}\n\nfunction getMinor(version: string): number | null {\n const parts = getParts(version);\n if (parts === null || parts.minor.length === 0) {\n return null;\n }\n return Number(parts.minor.join('.'));\n}\n\nfunction getPatch(version: string): number | null {\n const parts = getParts(version);\n if (parts === null || parts.patch.length === 0) {\n return null;\n }\n return Number(`${parts.patch[0]}.${parts.patch.slice(1).join('')}`);\n}\n\nfunction matches(version: string, range: string): boolean {\n const parsed = parseRange(range);\n if (parsed === null) {\n return false;\n }\n const ver = extractAllParts(version);\n const lower = extractAllParts(parsed.lower);\n const upper = extractAllParts(parsed.upper);\n if (ver === null || lower === null || upper === null) {\n return false;\n }\n return (\n 'gt' === compareIntArray(upper, ver) &&\n ['eq', 'lt'].includes(compareIntArray(lower, ver))\n );\n}\n\nfunction satisfyingVersion(\n versions: string[],\n range: string,\n reverse: boolean,\n): string | null {\n const copy = versions.slice(0);\n copy.sort((a, b) => {\n const multiplier = reverse ? 1 : -1;\n return sortVersions(a, b) * multiplier;\n });\n const result = copy.find((v) => matches(v, range));\n return result ?? null;\n}\n\nfunction getSatisfyingVersion(\n versions: string[],\n range: string,\n): string | null {\n return satisfyingVersion(versions, range, false);\n}\n\nfunction minSatisfyingVersion(\n versions: string[],\n range: string,\n): string | null {\n return satisfyingVersion(versions, range, true);\n}\n\nfunction isLessThanRange(version: string, range: string): boolean {\n const parsed = parseRange(range);\n if (parsed === null) {\n return false;\n }\n const compos = extractAllParts(version);\n const lower = extractAllParts(parsed.lower);\n if (compos === null || lower === null) {\n return false;\n }\n return 'lt' === compareIntArray(compos, lower);\n}\n\nfunction getNewValue({\n currentValue,\n newVersion,\n rangeStrategy,\n}: NewValueConfig): string | null {\n if (rangeStrategy !== 'widen') {\n logger.info(\n { rangeStrategy, currentValue, newVersion },\n `PVP can't handle this range strategy.`,\n );\n return null;\n }\n const parsed = parseRange(currentValue);\n if (parsed === null) {\n logger.info(\n { currentValue, newVersion },\n 'could not parse PVP version range',\n );\n return null;\n }\n if (isLessThanRange(newVersion, currentValue)) {\n // ignore new releases in old release series\n return null;\n }\n if (matches(newVersion, currentValue)) {\n // the upper bound is already high enough\n return null;\n }\n const compos = getParts(newVersion);\n if (compos === null) {\n return null;\n }\n const majorPlusOne = plusOne(compos.major);\n // istanbul ignore next: since all versions that can be parsed, can also be bumped, this can never happen\n if (!matches(newVersion, `>=${parsed.lower} && <${majorPlusOne}`)) {\n logger.warn(\n { newVersion },\n \"Even though the major bound was bumped, the newVersion still isn't accepted.\",\n );\n return null;\n }\n return `>=${parsed.lower} && <${majorPlusOne}`;\n}\n\nfunction isSame(\n type: 'major' | 'minor' | 'patch',\n a: string,\n b: string,\n): boolean {\n const aParts = getParts(a);\n const bParts = getParts(b);\n if (aParts === null || bParts === null) {\n return false;\n }\n if (type === 'major') {\n return 'eq' === compareIntArray(aParts.major, bParts.major);\n }\n if (type === 'minor') {\n return 'eq' === compareIntArray(aParts.minor, bParts.minor);\n }\n return 'eq' === compareIntArray(aParts.patch, bParts.patch);\n}\n\nfunction subset(subRange: string, superRange: string): boolean | undefined {\n const sub = parseRange(subRange);\n const sup = parseRange(superRange);\n if (sub === null || sup === null) {\n return undefined;\n }\n const subLower = extractAllParts(sub.lower);\n const subUpper = extractAllParts(sub.upper);\n const supLower = extractAllParts(sup.lower);\n const supUpper = extractAllParts(sup.upper);\n if (\n subLower === null ||\n subUpper === null ||\n supLower === null ||\n supUpper === null\n ) {\n return undefined;\n }\n if ('lt' === compareIntArray(subLower, supLower)) {\n return false;\n }\n if ('gt' === compareIntArray(subUpper, supUpper)) {\n return false;\n }\n return true;\n}\n\nfunction isVersion(maybeRange: string | undefined | null): boolean {\n return isString(maybeRange) && parseRange(maybeRange) === null;\n}\n\nfunction isValid(ver: string): boolean {\n return extractAllParts(ver) !== null || parseRange(ver) !== null;\n}\n\nfunction isSingleVersion(range: string): boolean {\n const noSpaces = range.trim();\n return noSpaces.startsWith('==') && digitsAndDots.test(noSpaces.slice(2));\n}\n\nfunction equals(a: string, b: string): boolean {\n const aParts = extractAllParts(a);\n const bParts = extractAllParts(b);\n if (aParts === null || bParts === null) {\n return false;\n }\n return 'eq' === compareIntArray(aParts, bParts);\n}\n\nfunction sortVersions(a: string, b: string): number {\n if (equals(a, b)) {\n return 0;\n }\n return isGreaterThan(a, b) ? 1 : -1;\n}\n\nfunction isStable(_version: string): boolean {\n return true;\n}\n\nfunction isCompatible(_version: string): boolean {\n return true;\n}\n\nexport const api: VersioningApi = {\n isValid,\n isVersion,\n isStable,\n isCompatible,\n getMajor,\n getMinor,\n getPatch,\n isSingleVersion,\n sortVersions,\n equals,\n matches,\n getSatisfyingVersion,\n minSatisfyingVersion,\n isLessThanRange,\n isGreaterThan,\n getNewValue,\n isSame,\n subset,\n};\nexport default api;\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../../../../lib/modules/versioning/pvp/index.ts"],"sourcesContent":["import { isString } from '@sindresorhus/is';\nimport { logger } from '../../../logger/index.ts';\nimport type { RangeStrategy } from '../../../types/versioning.ts';\nimport { regEx } from '../../../util/regex.ts';\nimport type { NewValueConfig, VersioningApi } from '../types.ts';\nimport { parseRange } from './range.ts';\nimport { compareIntArray, extractAllParts, getParts, plusOne } from './util.ts';\n\nexport const id = 'pvp';\nexport const displayName = 'Package Versioning Policy (Haskell)';\nexport const urls = [\n '[Haskell Package Versioning Policy](https://pvp.haskell.org)',\n];\nexport const supportsRanges = true;\nexport const supportedRangeStrategies: RangeStrategy[] = ['widen'];\n\nconst digitsAndDots = regEx(/^[\\d.]+$/);\n\nfunction isGreaterThan(version: string, other: string): boolean {\n const versionIntMajor = extractAllParts(version);\n const otherIntMajor = extractAllParts(other);\n if (versionIntMajor === null || otherIntMajor === null) {\n return false;\n }\n return compareIntArray(versionIntMajor, otherIntMajor) === 'gt';\n}\n\nfunction getMajor(version: string): number | null {\n // This basically can't be implemented correctly, since\n // 1.1 and 1.10 become equal when converted to float.\n // Consumers should use isSame instead.\n const parts = getParts(version);\n if (parts === null) {\n return null;\n }\n return parseFloat(parts.major.join('.'));\n}\n\nfunction getMinor(version: string): number | null {\n const parts = getParts(version);\n if (parts === null || parts.minor.length === 0) {\n return null;\n }\n return parseFloat(parts.minor.join('.'));\n}\n\nfunction getPatch(version: string): number | null {\n const parts = getParts(version);\n if (parts === null || parts.patch.length === 0) {\n return null;\n }\n return parseFloat(`${parts.patch[0]}.${parts.patch.slice(1).join('')}`);\n}\n\nfunction matches(version: string, range: string): boolean {\n const parsed = parseRange(range);\n if (parsed === null) {\n return false;\n }\n const ver = extractAllParts(version);\n const lower = extractAllParts(parsed.lower);\n const upper = extractAllParts(parsed.upper);\n if (ver === null || lower === null || upper === null) {\n return false;\n }\n return (\n 'gt' === compareIntArray(upper, ver) &&\n ['eq', 'lt'].includes(compareIntArray(lower, ver))\n );\n}\n\nfunction satisfyingVersion(\n versions: string[],\n range: string,\n reverse: boolean,\n): string | null {\n const copy = versions.slice(0);\n copy.sort((a, b) => {\n const multiplier = reverse ? 1 : -1;\n return sortVersions(a, b) * multiplier;\n });\n const result = copy.find((v) => matches(v, range));\n return result ?? null;\n}\n\nfunction getSatisfyingVersion(\n versions: string[],\n range: string,\n): string | null {\n return satisfyingVersion(versions, range, false);\n}\n\nfunction minSatisfyingVersion(\n versions: string[],\n range: string,\n): string | null {\n return satisfyingVersion(versions, range, true);\n}\n\nfunction isLessThanRange(version: string, range: string): boolean {\n const parsed = parseRange(range);\n if (parsed === null) {\n return false;\n }\n const compos = extractAllParts(version);\n const lower = extractAllParts(parsed.lower);\n if (compos === null || lower === null) {\n return false;\n }\n return 'lt' === compareIntArray(compos, lower);\n}\n\nfunction getNewValue({\n currentValue,\n newVersion,\n rangeStrategy,\n}: NewValueConfig): string | null {\n if (rangeStrategy !== 'widen') {\n logger.info(\n { rangeStrategy, currentValue, newVersion },\n `PVP can't handle this range strategy.`,\n );\n return null;\n }\n const parsed = parseRange(currentValue);\n if (parsed === null) {\n logger.info(\n { currentValue, newVersion },\n 'could not parse PVP version range',\n );\n return null;\n }\n if (isLessThanRange(newVersion, currentValue)) {\n // ignore new releases in old release series\n return null;\n }\n if (matches(newVersion, currentValue)) {\n // the upper bound is already high enough\n return null;\n }\n const compos = getParts(newVersion);\n if (compos === null) {\n return null;\n }\n const majorPlusOne = plusOne(compos.major);\n // istanbul ignore next: since all versions that can be parsed, can also be bumped, this can never happen\n if (!matches(newVersion, `>=${parsed.lower} && <${majorPlusOne}`)) {\n logger.warn(\n { newVersion },\n \"Even though the major bound was bumped, the newVersion still isn't accepted.\",\n );\n return null;\n }\n return `>=${parsed.lower} && <${majorPlusOne}`;\n}\n\nfunction isSame(\n type: 'major' | 'minor' | 'patch',\n a: string,\n b: string,\n): boolean {\n const aParts = getParts(a);\n const bParts = getParts(b);\n if (aParts === null || bParts === null) {\n return false;\n }\n if (type === 'major') {\n return 'eq' === compareIntArray(aParts.major, bParts.major);\n }\n if (type === 'minor') {\n return 'eq' === compareIntArray(aParts.minor, bParts.minor);\n }\n return 'eq' === compareIntArray(aParts.patch, bParts.patch);\n}\n\nfunction subset(subRange: string, superRange: string): boolean | undefined {\n const sub = parseRange(subRange);\n const sup = parseRange(superRange);\n if (sub === null || sup === null) {\n return undefined;\n }\n const subLower = extractAllParts(sub.lower);\n const subUpper = extractAllParts(sub.upper);\n const supLower = extractAllParts(sup.lower);\n const supUpper = extractAllParts(sup.upper);\n if (\n subLower === null ||\n subUpper === null ||\n supLower === null ||\n supUpper === null\n ) {\n return undefined;\n }\n if ('lt' === compareIntArray(subLower, supLower)) {\n return false;\n }\n if ('gt' === compareIntArray(subUpper, supUpper)) {\n return false;\n }\n return true;\n}\n\nfunction isVersion(maybeRange: string | undefined | null): boolean {\n return isString(maybeRange) && parseRange(maybeRange) === null;\n}\n\nfunction isValid(ver: string): boolean {\n return extractAllParts(ver) !== null || parseRange(ver) !== null;\n}\n\nfunction isSingleVersion(range: string): boolean {\n const noSpaces = range.trim();\n return noSpaces.startsWith('==') && digitsAndDots.test(noSpaces.slice(2));\n}\n\nfunction equals(a: string, b: string): boolean {\n const aParts = extractAllParts(a);\n const bParts = extractAllParts(b);\n if (aParts === null || bParts === null) {\n return false;\n }\n return 'eq' === compareIntArray(aParts, bParts);\n}\n\nfunction sortVersions(a: string, b: string): number {\n if (equals(a, b)) {\n return 0;\n }\n return isGreaterThan(a, b) ? 1 : -1;\n}\n\nfunction isStable(_version: string): boolean {\n return true;\n}\n\nfunction isCompatible(_version: string): boolean {\n return true;\n}\n\nexport const api: VersioningApi = {\n isValid,\n isVersion,\n isStable,\n isCompatible,\n getMajor,\n getMinor,\n getPatch,\n isSingleVersion,\n sortVersions,\n equals,\n matches,\n getSatisfyingVersion,\n minSatisfyingVersion,\n isLessThanRange,\n isGreaterThan,\n getNewValue,\n isSame,\n subset,\n};\nexport default api;\n"],"mappings":"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"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { GlobalConfig } from "../../config/global.js";
|
|
2
2
|
import { logger } from "../../logger/index.js";
|
|
3
|
+
import { isNumber } from "@sindresorhus/is";
|
|
3
4
|
import upath from "upath";
|
|
4
5
|
import { parse } from "editorconfig";
|
|
5
6
|
//#region lib/util/json-writer/editor-config.ts
|
|
@@ -24,8 +25,8 @@ var EditorConfig = class EditorConfig {
|
|
|
24
25
|
if (indentStyle === "space") return "space";
|
|
25
26
|
}
|
|
26
27
|
static getIndentationSize(knownProps) {
|
|
27
|
-
const indentSize =
|
|
28
|
-
if (
|
|
28
|
+
const { indent_size: indentSize } = knownProps;
|
|
29
|
+
if (isNumber(indentSize) && Number.isInteger(indentSize)) return indentSize;
|
|
29
30
|
}
|
|
30
31
|
};
|
|
31
32
|
//#endregion
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"editor-config.js","names":[],"sources":["../../../lib/util/json-writer/editor-config.ts"],"sourcesContent":["import type { Props } from 'editorconfig';\nimport { parse } from 'editorconfig';\nimport upath from 'upath';\nimport { GlobalConfig } from '../../config/global.ts';\nimport { logger } from '../../logger/index.ts';\nimport type { CodeFormat } from './code-format.ts';\nimport type { IndentationType } from './indentation-type.ts';\n\nexport class EditorConfig {\n public static async getCodeFormat(fileName: string): Promise<CodeFormat> {\n const localDir = GlobalConfig.get('localDir');\n try {\n const knownProps = await parse(upath.join(localDir, fileName));\n return {\n indentationSize: EditorConfig.getIndentationSize(knownProps),\n indentationType: EditorConfig.getIndentationType(knownProps),\n maxLineLength: knownProps.max_line_length as number | 'off' | undefined,\n };\n } catch (err) {\n logger.warn({ err }, 'Failed to parse editor config');\n return {};\n }\n }\n\n private static getIndentationType(\n knownProps: Props,\n ): IndentationType | undefined {\n const { indent_style: indentStyle } = knownProps;\n\n if (indentStyle === 'tab') {\n return 'tab';\n }\n\n if (indentStyle === 'space') {\n return 'space';\n }\n\n return undefined;\n }\n\n private static getIndentationSize(knownProps: Props): number | undefined {\n const indentSize =
|
|
1
|
+
{"version":3,"file":"editor-config.js","names":[],"sources":["../../../lib/util/json-writer/editor-config.ts"],"sourcesContent":["import { isNumber } from '@sindresorhus/is';\nimport type { Props } from 'editorconfig';\nimport { parse } from 'editorconfig';\nimport upath from 'upath';\nimport { GlobalConfig } from '../../config/global.ts';\nimport { logger } from '../../logger/index.ts';\nimport type { CodeFormat } from './code-format.ts';\nimport type { IndentationType } from './indentation-type.ts';\n\nexport class EditorConfig {\n public static async getCodeFormat(fileName: string): Promise<CodeFormat> {\n const localDir = GlobalConfig.get('localDir');\n try {\n const knownProps = await parse(upath.join(localDir, fileName));\n return {\n indentationSize: EditorConfig.getIndentationSize(knownProps),\n indentationType: EditorConfig.getIndentationType(knownProps),\n maxLineLength: knownProps.max_line_length as number | 'off' | undefined,\n };\n } catch (err) {\n logger.warn({ err }, 'Failed to parse editor config');\n return {};\n }\n }\n\n private static getIndentationType(\n knownProps: Props,\n ): IndentationType | undefined {\n const { indent_style: indentStyle } = knownProps;\n\n if (indentStyle === 'tab') {\n return 'tab';\n }\n\n if (indentStyle === 'space') {\n return 'space';\n }\n\n return undefined;\n }\n\n private static getIndentationSize(knownProps: Props): number | undefined {\n const { indent_size: indentSize } = knownProps;\n\n if (isNumber(indentSize) && Number.isInteger(indentSize)) {\n return indentSize;\n }\n\n return undefined;\n }\n}\n"],"mappings":";;;;;;AASA,IAAa,eAAb,MAAa,aAAa;CACxB,aAAoB,cAAc,UAAuC;EACvE,MAAM,WAAW,aAAa,IAAI,UAAU;EAC5C,IAAI;GACF,MAAM,aAAa,MAAM,MAAM,MAAM,KAAK,UAAU,QAAQ,CAAC;GAC7D,OAAO;IACL,iBAAiB,aAAa,mBAAmB,UAAU;IAC3D,iBAAiB,aAAa,mBAAmB,UAAU;IAC3D,eAAe,WAAW;GAC5B;EACF,SAAS,KAAK;GACZ,OAAO,KAAK,EAAE,IAAI,GAAG,+BAA+B;GACpD,OAAO,CAAC;EACV;CACF;CAEA,OAAe,mBACb,YAC6B;EAC7B,MAAM,EAAE,cAAc,gBAAgB;EAEtC,IAAI,gBAAgB,OAClB,OAAO;EAGT,IAAI,gBAAgB,SAClB,OAAO;CAIX;CAEA,OAAe,mBAAmB,YAAuC;EACvE,MAAM,EAAE,aAAa,eAAe;EAEpC,IAAI,SAAS,UAAU,KAAK,OAAO,UAAU,UAAU,GACrD,OAAO;CAIX;AACF"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "renovate",
|
|
3
3
|
"description": "Automated dependency updates. Flexible so you don't need to be.",
|
|
4
|
-
"version": "44.46.
|
|
4
|
+
"version": "44.46.5",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
7
7
|
"renovate": "dist/renovate.js",
|
|
@@ -287,7 +287,7 @@
|
|
|
287
287
|
"type-fest": "5.8.0",
|
|
288
288
|
"typescript": "7.0.2",
|
|
289
289
|
"unified": "11.0.5",
|
|
290
|
-
"vite": "8.2.
|
|
290
|
+
"vite": "8.2.2",
|
|
291
291
|
"vitest": "4.1.11",
|
|
292
292
|
"vitest-mock-extended": "5.1.1",
|
|
293
293
|
"yazl": "3.3.1"
|
package/renovate-schema.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$id": "https://docs.renovatebot.com/renovate-schema.json",
|
|
3
|
-
"title": "JSON schema for Renovate 44.46.
|
|
3
|
+
"title": "JSON schema for Renovate 44.46.5 config files (https://renovatebot.com/)",
|
|
4
4
|
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
5
|
-
"x-renovate-version": "44.46.
|
|
5
|
+
"x-renovate-version": "44.46.5",
|
|
6
6
|
"allowComments": true,
|
|
7
7
|
"type": "object",
|
|
8
8
|
"definitions": {
|