renovate 43.224.0 → 43.225.0

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.
@@ -19,6 +19,7 @@ interface BranchUpgradeCache {
19
19
  depName?: string;
20
20
  depType?: string;
21
21
  displayPending?: unknown;
22
+ manager?: string;
22
23
  fixedVersion?: string;
23
24
  currentVersion?: string;
24
25
  packageName?: string;
@@ -29,6 +30,7 @@ interface BranchUpgradeCache {
29
30
  packageFile?: string;
30
31
  remediationNotPossible?: unknown;
31
32
  updateType?: UpdateType;
33
+ isVulnerabilityAlert?: boolean;
32
34
  }
33
35
  interface OnboardingBranchCache {
34
36
  defaultBranchSha: string;
@@ -10,12 +10,13 @@ import { getCachedPristineResult } from "../../util/git/pristine.js";
10
10
  import { getPrCache } from "./update/pr/pr-cache.js";
11
11
  //#region lib/workers/repository/cache.ts
12
12
  function generateBranchUpgradeCache(upgrade) {
13
- const { datasource, depName, depType, displayPending, packageName, fixedVersion, currentVersion, newVersion, currentValue, newValue, currentDigest, newDigest, packageFile, sourceUrl, remediationNotPossible, updateType } = upgrade;
13
+ const { datasource, depName, depType, displayPending, manager, packageName, fixedVersion, currentVersion, newVersion, currentValue, newValue, currentDigest, newDigest, packageFile, sourceUrl, remediationNotPossible, updateType, isVulnerabilityAlert } = upgrade;
14
14
  const result = {
15
15
  datasource,
16
16
  depName,
17
17
  depType,
18
18
  displayPending,
19
+ manager,
19
20
  fixedVersion,
20
21
  currentVersion,
21
22
  currentValue,
@@ -26,7 +27,8 @@ function generateBranchUpgradeCache(upgrade) {
26
27
  packageFile,
27
28
  sourceUrl,
28
29
  remediationNotPossible,
29
- updateType
30
+ updateType,
31
+ isVulnerabilityAlert
30
32
  };
31
33
  if (packageName) result.packageName = packageName;
32
34
  return result;
@@ -1 +1 @@
1
- {"version":3,"file":"cache.js","names":[],"sources":["../../../lib/workers/repository/cache.ts"],"sourcesContent":["import { REPOSITORY_CHANGED } from '../../constants/error-messages.ts';\nimport { logger } from '../../logger/index.ts';\nimport { platform } from '../../modules/platform/index.ts';\nimport { scm } from '../../modules/platform/scm.ts';\nimport { getCache } from '../../util/cache/repository/index.ts';\nimport type {\n BranchCache,\n BranchUpgradeCache,\n} from '../../util/cache/repository/types.ts';\nimport { getCachedBehindBaseResult } from '../../util/git/behind-base-branch-cache.ts';\nimport { getCachedConflictResult } from '../../util/git/conflicts-cache.ts';\nimport { getCachedModifiedResult } from '../../util/git/modified-cache.ts';\nimport { getCachedPristineResult } from '../../util/git/pristine.ts';\nimport type { BranchConfig, BranchUpgradeConfig } from '../types.ts';\nimport { getPrCache } from './update/pr/pr-cache.ts';\n\nfunction generateBranchUpgradeCache(\n upgrade: BranchUpgradeConfig,\n): BranchUpgradeCache {\n const {\n datasource,\n depName,\n depType,\n displayPending,\n packageName,\n fixedVersion,\n currentVersion,\n newVersion,\n currentValue,\n newValue,\n currentDigest,\n newDigest,\n packageFile,\n sourceUrl,\n remediationNotPossible,\n updateType,\n } = upgrade;\n const result: BranchUpgradeCache = {\n datasource,\n depName,\n depType,\n displayPending,\n fixedVersion,\n currentVersion,\n currentValue,\n newValue,\n newVersion,\n currentDigest,\n newDigest,\n packageFile,\n sourceUrl,\n remediationNotPossible,\n updateType,\n };\n if (packageName) {\n result.packageName = packageName;\n }\n return result;\n}\n\nasync function generateBranchCache(\n branch: BranchConfig,\n): Promise<BranchCache | null> {\n const { baseBranch, branchName, prBlockedBy, prTitle, result } = branch;\n try {\n const branchSha = await scm.getBranchCommit(branchName);\n const baseBranchSha = await scm.getBranchCommit(baseBranch);\n const pristine = getCachedPristineResult(branchName);\n let prNo = null;\n let isModified: boolean | undefined;\n let isBehindBase: boolean | undefined;\n let isConflicted: boolean | undefined;\n let commitTimestamp: string | undefined;\n if (baseBranchSha && branchSha) {\n const branchPr = await platform.getBranchPr(branchName, baseBranch);\n if (branchPr) {\n prNo = branchPr.number;\n }\n isModified = getCachedModifiedResult(branchName, branchSha) ?? undefined;\n isBehindBase =\n getCachedBehindBaseResult(\n branchName,\n branchSha,\n baseBranch,\n baseBranchSha,\n ) ?? undefined;\n isConflicted =\n getCachedConflictResult(\n branchName,\n branchSha,\n baseBranch,\n baseBranchSha,\n ) ?? undefined;\n // Get commit timestamp for hourly limit tracking\n const commitDate = await scm.getBranchUpdateDate(branchName);\n if (commitDate) {\n commitTimestamp = commitDate.toISO()!;\n }\n } else if (baseBranchSha && !branchSha && branch.prNo) {\n // if branch was deleted/ PR exists and ignored\n prNo = branch.prNo;\n }\n\n const automerge = !!branch.automerge;\n const upgrades: BranchUpgradeCache[] = branch.upgrades\n ? branch.upgrades.map(generateBranchUpgradeCache)\n : [];\n const commitFingerprint = branch.commitFingerprint;\n const prCache = getPrCache(branchName);\n\n return {\n automerge,\n baseBranchSha,\n baseBranch,\n commitFingerprint,\n commitTimestamp,\n branchName,\n isBehindBase,\n isConflicted,\n isModified,\n prBlockedBy,\n pristine,\n prCache,\n prNo,\n prTitle,\n result,\n sha: branchSha,\n upgrades,\n };\n } catch (error) {\n const err = error.err ?? error; // external host error nests err\n const errCodes = [401, 404];\n // istanbul ignore if\n if (errCodes.includes(err.response?.statusCode)) {\n logger.warn({ err, branchName }, 'HTTP error generating branch cache');\n return null;\n }\n if (err.message === REPOSITORY_CHANGED) {\n throw err;\n }\n logger.error({ err, branchName }, 'Error generating branch cache');\n return null;\n }\n}\n\nexport async function setBranchCache(branches: BranchConfig[]): Promise<void> {\n const branchCaches: BranchCache[] = [];\n for (const branch of branches) {\n const branchCache = await generateBranchCache(branch);\n if (branchCache) {\n branchCaches.push(branchCache);\n }\n }\n getCache().branches = branchCaches;\n}\n"],"mappings":";;;;;;;;;;;AAgBA,SAAS,2BACP,SACoB;CACpB,MAAM,EACJ,YACA,SACA,SACA,gBACA,aACA,cACA,gBACA,YACA,cACA,UACA,eACA,WACA,aACA,WACA,wBACA,eACE;CACJ,MAAM,SAA6B;EACjC;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;CACF;CACA,IAAI,aACF,OAAO,cAAc;CAEvB,OAAO;AACT;AAEA,eAAe,oBACb,QAC6B;CAC7B,MAAM,EAAE,YAAY,YAAY,aAAa,SAAS,WAAW;CACjE,IAAI;EACF,MAAM,YAAY,MAAM,IAAI,gBAAgB,UAAU;EACtD,MAAM,gBAAgB,MAAM,IAAI,gBAAgB,UAAU;EAC1D,MAAM,WAAW,wBAAwB,UAAU;EACnD,IAAI,OAAO;EACX,IAAI;EACJ,IAAI;EACJ,IAAI;EACJ,IAAI;EACJ,IAAI,iBAAiB,WAAW;GAC9B,MAAM,WAAW,MAAM,SAAS,YAAY,YAAY,UAAU;GAClE,IAAI,UACF,OAAO,SAAS;GAElB,aAAa,wBAAwB,YAAY,SAAS,KAAK,KAAA;GAC/D,eACE,0BACE,YACA,WACA,YACA,aACF,KAAK,KAAA;GACP,eACE,wBACE,YACA,WACA,YACA,aACF,KAAK,KAAA;GAEP,MAAM,aAAa,MAAM,IAAI,oBAAoB,UAAU;GAC3D,IAAI,YACF,kBAAkB,WAAW,MAAM;EAEvC,OAAO,IAAI,iBAAiB,CAAC,aAAa,OAAO,MAE/C,OAAO,OAAO;EAGhB,MAAM,YAAY,CAAC,CAAC,OAAO;EAC3B,MAAM,WAAiC,OAAO,WAC1C,OAAO,SAAS,IAAI,0BAA0B,IAC9C,CAAC;EACL,MAAM,oBAAoB,OAAO;EACjC,MAAM,UAAU,WAAW,UAAU;EAErC,OAAO;GACL;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA,KAAK;GACL;EACF;CACF,SAAS,OAAO;EACd,MAAM,MAAM,MAAM,OAAO;;EAGzB,IAAI,CAFc,KAAK,GAEZ,CAAC,CAAC,SAAS,IAAI,UAAU,UAAU,GAAG;GAC/C,OAAO,KAAK;IAAE;IAAK;GAAW,GAAG,oCAAoC;GACrE,OAAO;EACT;EACA,IAAI,IAAI,YAAA,sBACN,MAAM;EAER,OAAO,MAAM;GAAE;GAAK;EAAW,GAAG,+BAA+B;EACjE,OAAO;CACT;AACF;AAEA,eAAsB,eAAe,UAAyC;CAC5E,MAAM,eAA8B,CAAC;CACrC,KAAK,MAAM,UAAU,UAAU;EAC7B,MAAM,cAAc,MAAM,oBAAoB,MAAM;EACpD,IAAI,aACF,aAAa,KAAK,WAAW;CAEjC;CACA,SAAS,CAAC,CAAC,WAAW;AACxB"}
1
+ {"version":3,"file":"cache.js","names":[],"sources":["../../../lib/workers/repository/cache.ts"],"sourcesContent":["import { REPOSITORY_CHANGED } from '../../constants/error-messages.ts';\nimport { logger } from '../../logger/index.ts';\nimport { platform } from '../../modules/platform/index.ts';\nimport { scm } from '../../modules/platform/scm.ts';\nimport { getCache } from '../../util/cache/repository/index.ts';\nimport type {\n BranchCache,\n BranchUpgradeCache,\n} from '../../util/cache/repository/types.ts';\nimport { getCachedBehindBaseResult } from '../../util/git/behind-base-branch-cache.ts';\nimport { getCachedConflictResult } from '../../util/git/conflicts-cache.ts';\nimport { getCachedModifiedResult } from '../../util/git/modified-cache.ts';\nimport { getCachedPristineResult } from '../../util/git/pristine.ts';\nimport type { BranchConfig, BranchUpgradeConfig } from '../types.ts';\nimport { getPrCache } from './update/pr/pr-cache.ts';\n\nfunction generateBranchUpgradeCache(\n upgrade: BranchUpgradeConfig,\n): BranchUpgradeCache {\n const {\n datasource,\n depName,\n depType,\n displayPending,\n manager,\n packageName,\n fixedVersion,\n currentVersion,\n newVersion,\n currentValue,\n newValue,\n currentDigest,\n newDigest,\n packageFile,\n sourceUrl,\n remediationNotPossible,\n updateType,\n isVulnerabilityAlert,\n } = upgrade;\n const result: BranchUpgradeCache = {\n datasource,\n depName,\n depType,\n displayPending,\n manager,\n fixedVersion,\n currentVersion,\n currentValue,\n newValue,\n newVersion,\n currentDigest,\n newDigest,\n packageFile,\n sourceUrl,\n remediationNotPossible,\n updateType,\n isVulnerabilityAlert,\n };\n if (packageName) {\n result.packageName = packageName;\n }\n return result;\n}\n\nasync function generateBranchCache(\n branch: BranchConfig,\n): Promise<BranchCache | null> {\n const { baseBranch, branchName, prBlockedBy, prTitle, result } = branch;\n try {\n const branchSha = await scm.getBranchCommit(branchName);\n const baseBranchSha = await scm.getBranchCommit(baseBranch);\n const pristine = getCachedPristineResult(branchName);\n let prNo = null;\n let isModified: boolean | undefined;\n let isBehindBase: boolean | undefined;\n let isConflicted: boolean | undefined;\n let commitTimestamp: string | undefined;\n if (baseBranchSha && branchSha) {\n const branchPr = await platform.getBranchPr(branchName, baseBranch);\n if (branchPr) {\n prNo = branchPr.number;\n }\n isModified = getCachedModifiedResult(branchName, branchSha) ?? undefined;\n isBehindBase =\n getCachedBehindBaseResult(\n branchName,\n branchSha,\n baseBranch,\n baseBranchSha,\n ) ?? undefined;\n isConflicted =\n getCachedConflictResult(\n branchName,\n branchSha,\n baseBranch,\n baseBranchSha,\n ) ?? undefined;\n // Get commit timestamp for hourly limit tracking\n const commitDate = await scm.getBranchUpdateDate(branchName);\n if (commitDate) {\n commitTimestamp = commitDate.toISO()!;\n }\n } else if (baseBranchSha && !branchSha && branch.prNo) {\n // if branch was deleted/ PR exists and ignored\n prNo = branch.prNo;\n }\n\n const automerge = !!branch.automerge;\n const upgrades: BranchUpgradeCache[] = branch.upgrades\n ? branch.upgrades.map(generateBranchUpgradeCache)\n : [];\n const commitFingerprint = branch.commitFingerprint;\n const prCache = getPrCache(branchName);\n\n return {\n automerge,\n baseBranchSha,\n baseBranch,\n commitFingerprint,\n commitTimestamp,\n branchName,\n isBehindBase,\n isConflicted,\n isModified,\n prBlockedBy,\n pristine,\n prCache,\n prNo,\n prTitle,\n result,\n sha: branchSha,\n upgrades,\n };\n } catch (error) {\n const err = error.err ?? error; // external host error nests err\n const errCodes = [401, 404];\n // istanbul ignore if\n if (errCodes.includes(err.response?.statusCode)) {\n logger.warn({ err, branchName }, 'HTTP error generating branch cache');\n return null;\n }\n if (err.message === REPOSITORY_CHANGED) {\n throw err;\n }\n logger.error({ err, branchName }, 'Error generating branch cache');\n return null;\n }\n}\n\nexport async function setBranchCache(branches: BranchConfig[]): Promise<void> {\n const branchCaches: BranchCache[] = [];\n for (const branch of branches) {\n const branchCache = await generateBranchCache(branch);\n if (branchCache) {\n branchCaches.push(branchCache);\n }\n }\n getCache().branches = branchCaches;\n}\n"],"mappings":";;;;;;;;;;;AAgBA,SAAS,2BACP,SACoB;CACpB,MAAM,EACJ,YACA,SACA,SACA,gBACA,SACA,aACA,cACA,gBACA,YACA,cACA,UACA,eACA,WACA,aACA,WACA,wBACA,YACA,yBACE;CACJ,MAAM,SAA6B;EACjC;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;CACF;CACA,IAAI,aACF,OAAO,cAAc;CAEvB,OAAO;AACT;AAEA,eAAe,oBACb,QAC6B;CAC7B,MAAM,EAAE,YAAY,YAAY,aAAa,SAAS,WAAW;CACjE,IAAI;EACF,MAAM,YAAY,MAAM,IAAI,gBAAgB,UAAU;EACtD,MAAM,gBAAgB,MAAM,IAAI,gBAAgB,UAAU;EAC1D,MAAM,WAAW,wBAAwB,UAAU;EACnD,IAAI,OAAO;EACX,IAAI;EACJ,IAAI;EACJ,IAAI;EACJ,IAAI;EACJ,IAAI,iBAAiB,WAAW;GAC9B,MAAM,WAAW,MAAM,SAAS,YAAY,YAAY,UAAU;GAClE,IAAI,UACF,OAAO,SAAS;GAElB,aAAa,wBAAwB,YAAY,SAAS,KAAK,KAAA;GAC/D,eACE,0BACE,YACA,WACA,YACA,aACF,KAAK,KAAA;GACP,eACE,wBACE,YACA,WACA,YACA,aACF,KAAK,KAAA;GAEP,MAAM,aAAa,MAAM,IAAI,oBAAoB,UAAU;GAC3D,IAAI,YACF,kBAAkB,WAAW,MAAM;EAEvC,OAAO,IAAI,iBAAiB,CAAC,aAAa,OAAO,MAE/C,OAAO,OAAO;EAGhB,MAAM,YAAY,CAAC,CAAC,OAAO;EAC3B,MAAM,WAAiC,OAAO,WAC1C,OAAO,SAAS,IAAI,0BAA0B,IAC9C,CAAC;EACL,MAAM,oBAAoB,OAAO;EACjC,MAAM,UAAU,WAAW,UAAU;EAErC,OAAO;GACL;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA,KAAK;GACL;EACF;CACF,SAAS,OAAO;EACd,MAAM,MAAM,MAAM,OAAO;;EAGzB,IAAI,CAFc,KAAK,GAEZ,CAAC,CAAC,SAAS,IAAI,UAAU,UAAU,GAAG;GAC/C,OAAO,KAAK;IAAE;IAAK;GAAW,GAAG,oCAAoC;GACrE,OAAO;EACT;EACA,IAAI,IAAI,YAAA,sBACN,MAAM;EAER,OAAO,MAAM;GAAE;GAAK;EAAW,GAAG,+BAA+B;EACjE,OAAO;CACT;AACF;AAEA,eAAsB,eAAe,UAAyC;CAC5E,MAAM,eAA8B,CAAC;CACrC,KAAK,MAAM,UAAU,UAAU;EAC7B,MAAM,cAAc,MAAM,oBAAoB,MAAM;EACpD,IAAI,aACF,aAAa,KAAK,WAAW;CAEjC;CACA,SAAS,CAAC,CAAC,WAAW;AACxB"}
@@ -99,8 +99,49 @@ function runBranchSummary(config) {
99
99
  const branchesInformation = filterDependencyDashboardData(branches);
100
100
  addBranchStats(config, branchesInformation);
101
101
  logger.debug({ branchesInformation }, "branches info extended");
102
+ const updateSummary = getUpdateSummary(branches);
103
+ logger.debug({ updateSummary }, "Updates summary");
102
104
  }
103
105
  }
106
+ function getUpdateSummary(branches) {
107
+ const summaryByBase = /* @__PURE__ */ new Map();
108
+ for (const branch of branches) {
109
+ const baseBranch = branch.baseBranch ?? "";
110
+ let entry = summaryByBase.get(baseBranch);
111
+ if (!entry) {
112
+ entry = {
113
+ baseBranch,
114
+ total: 0,
115
+ vulnerabilityAlert: 0,
116
+ updates: {},
117
+ managers: {}
118
+ };
119
+ summaryByBase.set(baseBranch, entry);
120
+ }
121
+ for (const upgrade of branch.upgrades ?? []) {
122
+ const { updateType } = upgrade;
123
+ if (updateType) {
124
+ entry.total += 1;
125
+ if (upgrade.isVulnerabilityAlert) entry.vulnerabilityAlert += 1;
126
+ entry.updates[updateType] = (entry.updates[updateType] ?? 0) + 1;
127
+ const manager = upgrade.manager ?? "";
128
+ let managerEntry = entry.managers[manager];
129
+ if (!managerEntry) {
130
+ managerEntry = {
131
+ total: 0,
132
+ vulnerabilityAlert: 0,
133
+ updates: {}
134
+ };
135
+ entry.managers[manager] = managerEntry;
136
+ }
137
+ managerEntry.total += 1;
138
+ if (upgrade.isVulnerabilityAlert) managerEntry.vulnerabilityAlert += 1;
139
+ managerEntry.updates[updateType] = (managerEntry.updates[updateType] ?? 0) + 1;
140
+ } else logger.debug({ upgrade }, "Found an upgrade without an updateType, which should not be possible");
141
+ }
142
+ }
143
+ return Array.from(summaryByBase.values());
144
+ }
104
145
  //#endregion
105
146
  export { runBranchSummary, runRenovateRepoStats };
106
147
 
@@ -1 +1 @@
1
- {"version":3,"file":"repository-statistics.js","names":[],"sources":["../../../../lib/workers/repository/finalize/repository-statistics.ts"],"sourcesContent":["import type { RenovateConfig } from '../../../config/types.ts';\nimport { addBranchStats } from '../../../instrumentation/reporting.ts';\nimport { logger } from '../../../logger/index.ts';\nimport type { Pr } from '../../../modules/platform/index.ts';\nimport {\n getCache,\n isCacheModified,\n} from '../../../util/cache/repository/index.ts';\nimport type {\n BranchCache,\n BranchUpgradeCache,\n} from '../../../util/cache/repository/types.ts';\nimport { getInheritedOrGlobal } from '../../../util/common.ts';\nimport type {\n BaseBranchMetadata,\n BranchMetadata,\n BranchSummary,\n} from '../../types.ts';\n\nexport function runRenovateRepoStats(\n config: RenovateConfig,\n prList: Pr[],\n): void {\n const prStats = { total: 0, open: 0, closed: 0, merged: 0 };\n\n for (const pr of prList) {\n if (\n pr.title === 'Configure Renovate' ||\n pr.title === getInheritedOrGlobal('onboardingPrTitle')\n ) {\n continue;\n }\n prStats.total += 1;\n switch (pr.state) {\n case 'merged':\n prStats.merged += 1;\n break;\n case 'closed':\n prStats.closed += 1;\n break;\n case 'open':\n prStats.open += 1;\n break;\n default:\n break;\n }\n }\n logger.debug({ stats: prStats }, `Renovate repository PR statistics`);\n}\n\nfunction branchCacheToMetadata({\n automerge,\n baseBranch,\n baseBranchSha,\n branchName,\n isModified,\n pristine: isPristine,\n sha: branchSha,\n}: BranchCache): BranchMetadata {\n return {\n automerge,\n baseBranch,\n baseBranchSha,\n branchName,\n branchSha,\n isModified,\n isPristine,\n };\n}\n\nfunction filterDependencyDashboardData(\n branches: BranchCache[],\n): Partial<BranchCache>[] {\n const branchesFiltered: Partial<BranchCache>[] = [];\n for (const branch of branches) {\n const upgradesFiltered: Partial<BranchUpgradeCache>[] = [];\n const { branchName, prNo, prTitle, result, upgrades, prBlockedBy } = branch;\n\n for (const upgrade of upgrades ?? []) {\n const {\n datasource,\n depName,\n displayPending,\n fixedVersion,\n currentVersion,\n currentValue,\n currentDigest,\n newValue,\n newVersion,\n newDigest,\n packageFile,\n updateType,\n packageName,\n } = upgrade;\n\n const filteredUpgrade: Partial<BranchUpgradeCache> = {\n datasource,\n depName,\n displayPending,\n fixedVersion,\n currentVersion,\n currentValue,\n currentDigest,\n newValue,\n newVersion,\n newDigest,\n packageFile,\n updateType,\n packageName,\n };\n upgradesFiltered.push(filteredUpgrade);\n }\n\n const filteredBranch: Partial<BranchCache> = {\n branchName,\n prNo,\n prTitle,\n result,\n prBlockedBy,\n upgrades: upgradesFiltered,\n };\n branchesFiltered.push(filteredBranch);\n }\n\n return branchesFiltered;\n}\n\nexport function runBranchSummary(config: RenovateConfig): void {\n const defaultBranch = config.defaultBranch;\n const { scan, branches } = getCache();\n\n const baseMetadata: BaseBranchMetadata[] = [];\n for (const [branchName, cached] of Object.entries(scan ?? {})) {\n baseMetadata.push({ branchName, sha: cached.sha });\n }\n\n const branchMetadata: BranchMetadata[] = [];\n const inactiveBranches: string[] = [];\n\n for (const branch of branches ?? []) {\n if (branch.sha) {\n branchMetadata.push(branchCacheToMetadata(branch));\n } else {\n inactiveBranches.push(branch.branchName);\n }\n }\n\n const res: BranchSummary = {\n cacheModified: isCacheModified(),\n baseBranches: baseMetadata,\n branches: branchMetadata,\n defaultBranch,\n inactiveBranches,\n };\n\n logger.debug(res, 'Branch summary');\n\n if (branches?.length) {\n const branchesInformation = filterDependencyDashboardData(branches);\n addBranchStats(config, branchesInformation);\n logger.debug({ branchesInformation }, 'branches info extended');\n }\n}\n"],"mappings":";;;;;AAmBA,SAAgB,qBACd,QACA,QACM;CACN,MAAM,UAAU;EAAE,OAAO;EAAG,MAAM;EAAG,QAAQ;EAAG,QAAQ;CAAE;CAE1D,KAAK,MAAM,MAAM,QAAQ;EACvB,IACE,GAAG,UAAU,wBACb,GAAG,UAAU,qBAAqB,mBAAmB,GAErD;EAEF,QAAQ,SAAS;EACjB,QAAQ,GAAG,OAAX;GACE,KAAK;IACH,QAAQ,UAAU;IAClB;GACF,KAAK;IACH,QAAQ,UAAU;IAClB;GACF,KAAK;IACH,QAAQ,QAAQ;IAChB;GACF,SACE;EACJ;CACF;CACA,OAAO,MAAM,EAAE,OAAO,QAAQ,GAAG,mCAAmC;AACtE;AAEA,SAAS,sBAAsB,EAC7B,WACA,YACA,eACA,YACA,YACA,UAAU,YACV,KAAK,aACyB;CAC9B,OAAO;EACL;EACA;EACA;EACA;EACA;EACA;EACA;CACF;AACF;AAEA,SAAS,8BACP,UACwB;CACxB,MAAM,mBAA2C,CAAC;CAClD,KAAK,MAAM,UAAU,UAAU;EAC7B,MAAM,mBAAkD,CAAC;EACzD,MAAM,EAAE,YAAY,MAAM,SAAS,QAAQ,UAAU,gBAAgB;EAErE,KAAK,MAAM,WAAW,YAAY,CAAC,GAAG;GACpC,MAAM,EACJ,YACA,SACA,gBACA,cACA,gBACA,cACA,eACA,UACA,YACA,WACA,aACA,YACA,gBACE;GAEJ,MAAM,kBAA+C;IACnD;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;GACF;GACA,iBAAiB,KAAK,eAAe;EACvC;EAEA,MAAM,iBAAuC;GAC3C;GACA;GACA;GACA;GACA;GACA,UAAU;EACZ;EACA,iBAAiB,KAAK,cAAc;CACtC;CAEA,OAAO;AACT;AAEA,SAAgB,iBAAiB,QAA8B;CAC7D,MAAM,gBAAgB,OAAO;CAC7B,MAAM,EAAE,MAAM,aAAa,SAAS;CAEpC,MAAM,eAAqC,CAAC;CAC5C,KAAK,MAAM,CAAC,YAAY,WAAW,OAAO,QAAQ,QAAQ,CAAC,CAAC,GAC1D,aAAa,KAAK;EAAE;EAAY,KAAK,OAAO;CAAI,CAAC;CAGnD,MAAM,iBAAmC,CAAC;CAC1C,MAAM,mBAA6B,CAAC;CAEpC,KAAK,MAAM,UAAU,YAAY,CAAC,GAChC,IAAI,OAAO,KACT,eAAe,KAAK,sBAAsB,MAAM,CAAC;MAEjD,iBAAiB,KAAK,OAAO,UAAU;CAI3C,MAAM,MAAqB;EACzB,eAAe,gBAAgB;EAC/B,cAAc;EACd,UAAU;EACV;EACA;CACF;CAEA,OAAO,MAAM,KAAK,gBAAgB;CAElC,IAAI,UAAU,QAAQ;EACpB,MAAM,sBAAsB,8BAA8B,QAAQ;EAClE,eAAe,QAAQ,mBAAmB;EAC1C,OAAO,MAAM,EAAE,oBAAoB,GAAG,wBAAwB;CAChE;AACF"}
1
+ {"version":3,"file":"repository-statistics.js","names":[],"sources":["../../../../lib/workers/repository/finalize/repository-statistics.ts"],"sourcesContent":["import type { RenovateConfig } from '../../../config/types.ts';\nimport { addBranchStats } from '../../../instrumentation/reporting.ts';\nimport { logger } from '../../../logger/index.ts';\nimport type { Pr } from '../../../modules/platform/index.ts';\nimport {\n getCache,\n isCacheModified,\n} from '../../../util/cache/repository/index.ts';\nimport type {\n BranchCache,\n BranchUpgradeCache,\n} from '../../../util/cache/repository/types.ts';\nimport { getInheritedOrGlobal } from '../../../util/common.ts';\nimport type {\n BaseBranchMetadata,\n BaseBranchUpdateSummary,\n BranchMetadata,\n BranchSummary,\n ManagerUpdateSummary,\n UpdateSummary,\n} from '../../types.ts';\n\nexport function runRenovateRepoStats(\n config: RenovateConfig,\n prList: Pr[],\n): void {\n const prStats = { total: 0, open: 0, closed: 0, merged: 0 };\n\n for (const pr of prList) {\n if (\n pr.title === 'Configure Renovate' ||\n pr.title === getInheritedOrGlobal('onboardingPrTitle')\n ) {\n continue;\n }\n prStats.total += 1;\n switch (pr.state) {\n case 'merged':\n prStats.merged += 1;\n break;\n case 'closed':\n prStats.closed += 1;\n break;\n case 'open':\n prStats.open += 1;\n break;\n default:\n break;\n }\n }\n logger.debug({ stats: prStats }, `Renovate repository PR statistics`);\n}\n\nfunction branchCacheToMetadata({\n automerge,\n baseBranch,\n baseBranchSha,\n branchName,\n isModified,\n pristine: isPristine,\n sha: branchSha,\n}: BranchCache): BranchMetadata {\n return {\n automerge,\n baseBranch,\n baseBranchSha,\n branchName,\n branchSha,\n isModified,\n isPristine,\n };\n}\n\nfunction filterDependencyDashboardData(\n branches: BranchCache[],\n): Partial<BranchCache>[] {\n const branchesFiltered: Partial<BranchCache>[] = [];\n for (const branch of branches) {\n const upgradesFiltered: Partial<BranchUpgradeCache>[] = [];\n const { branchName, prNo, prTitle, result, upgrades, prBlockedBy } = branch;\n\n for (const upgrade of upgrades ?? []) {\n const {\n datasource,\n depName,\n displayPending,\n fixedVersion,\n currentVersion,\n currentValue,\n currentDigest,\n newValue,\n newVersion,\n newDigest,\n packageFile,\n updateType,\n packageName,\n } = upgrade;\n\n const filteredUpgrade: Partial<BranchUpgradeCache> = {\n datasource,\n depName,\n displayPending,\n fixedVersion,\n currentVersion,\n currentValue,\n currentDigest,\n newValue,\n newVersion,\n newDigest,\n packageFile,\n updateType,\n packageName,\n };\n upgradesFiltered.push(filteredUpgrade);\n }\n\n const filteredBranch: Partial<BranchCache> = {\n branchName,\n prNo,\n prTitle,\n result,\n prBlockedBy,\n upgrades: upgradesFiltered,\n };\n branchesFiltered.push(filteredBranch);\n }\n\n return branchesFiltered;\n}\n\nexport function runBranchSummary(config: RenovateConfig): void {\n const defaultBranch = config.defaultBranch;\n const { scan, branches } = getCache();\n\n const baseMetadata: BaseBranchMetadata[] = [];\n for (const [branchName, cached] of Object.entries(scan ?? {})) {\n baseMetadata.push({ branchName, sha: cached.sha });\n }\n\n const branchMetadata: BranchMetadata[] = [];\n const inactiveBranches: string[] = [];\n\n for (const branch of branches ?? []) {\n if (branch.sha) {\n branchMetadata.push(branchCacheToMetadata(branch));\n } else {\n inactiveBranches.push(branch.branchName);\n }\n }\n\n const res: BranchSummary = {\n cacheModified: isCacheModified(),\n baseBranches: baseMetadata,\n branches: branchMetadata,\n defaultBranch,\n inactiveBranches,\n };\n\n logger.debug(res, 'Branch summary');\n\n if (branches?.length) {\n const branchesInformation = filterDependencyDashboardData(branches);\n addBranchStats(config, branchesInformation);\n logger.debug({ branchesInformation }, 'branches info extended');\n\n const updateSummary = getUpdateSummary(branches);\n logger.debug({ updateSummary }, 'Updates summary');\n }\n}\n\nexport function getUpdateSummary(branches: BranchCache[]): UpdateSummary {\n const summaryByBase = new Map<string, BaseBranchUpdateSummary>();\n\n for (const branch of branches) {\n const baseBranch = branch.baseBranch ?? '';\n let entry = summaryByBase.get(baseBranch);\n if (!entry) {\n entry = {\n baseBranch,\n total: 0,\n vulnerabilityAlert: 0,\n updates: {},\n managers: {},\n };\n summaryByBase.set(baseBranch, entry);\n }\n for (const upgrade of branch.upgrades ?? []) {\n const { updateType } = upgrade;\n if (updateType) {\n entry.total += 1;\n if (upgrade.isVulnerabilityAlert) {\n entry.vulnerabilityAlert += 1;\n }\n\n entry.updates[updateType] = (entry.updates[updateType] ?? 0) + 1;\n\n const manager = upgrade.manager ?? '';\n let managerEntry: ManagerUpdateSummary | undefined =\n entry.managers[manager];\n if (!managerEntry) {\n managerEntry = { total: 0, vulnerabilityAlert: 0, updates: {} };\n entry.managers[manager] = managerEntry;\n }\n managerEntry.total += 1;\n if (upgrade.isVulnerabilityAlert) {\n managerEntry.vulnerabilityAlert += 1;\n }\n managerEntry.updates[updateType] =\n (managerEntry.updates[updateType] ?? 0) + 1;\n } else {\n logger.debug(\n { upgrade },\n 'Found an upgrade without an updateType, which should not be possible',\n );\n }\n }\n }\n\n return Array.from(summaryByBase.values());\n}\n"],"mappings":"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"}
@@ -279,7 +279,8 @@ async function addReleaseNotes(input, config) {
279
279
  const cacheKeyPrefix = sourceDirectory ? `${repository}:${sourceDirectory}` : `${repository}`;
280
280
  for (const v of input.versions) {
281
281
  let releaseNotes;
282
- const cacheKey = `${cacheKeyPrefix}:${v.version}`;
282
+ const gitRefCachePart = v.gitRef ? `:${v.gitRef}` : "";
283
+ const cacheKey = `${cacheKeyPrefix}:${v.version}${gitRefCachePart}`;
283
284
  releaseNotes = await get$1(cacheNamespace, cacheKey);
284
285
  releaseNotes ??= await getReleaseNotesMd(input.project, v);
285
286
  releaseNotes ??= await getReleaseNotes(input.project, v, config);
@@ -1 +1 @@
1
- {"version":3,"file":"release-notes.js","names":["bitbucket.getReleaseList","forgejo.getReleaseList","gitea.getReleaseList","github.getReleaseList","gitlab.getReleaseList","memCache.get","bitbucket.getReleaseNotesMd","bitbucketServer.getReleaseNotesMd","forgejo.getReleaseNotesMd","gitea.getReleaseNotesMd","github.getReleaseNotesMd","gitlab.getReleaseNotesMd","packageCache.get","packageCache.set"],"sources":["../../../../../../lib/workers/repository/update/pr/changelog/release-notes.ts"],"sourcesContent":["import { isDate, isUndefined } from '@sindresorhus/is';\nimport { DateTime } from 'luxon';\nimport MarkdownIt from 'markdown-it';\nimport { logger } from '../../../../../logger/index.ts';\nimport * as memCache from '../../../../../util/cache/memory/index.ts';\nimport * as packageCache from '../../../../../util/cache/package/index.ts';\nimport type { PackageCacheNamespace } from '../../../../../util/cache/package/types.ts';\nimport { detectPlatform } from '../../../../../util/common.ts';\nimport { linkify } from '../../../../../util/markdown.ts';\nimport { newlineRegex, regEx } from '../../../../../util/regex.ts';\nimport { coerceString } from '../../../../../util/string.ts';\nimport { isHttpUrl, joinUrlParts } from '../../../../../util/url.ts';\nimport type { BranchUpgradeConfig } from '../../../../types.ts';\nimport * as bitbucket from './bitbucket/index.ts';\nimport * as bitbucketServer from './bitbucket-server/index.ts';\nimport * as forgejo from './forgejo/index.ts';\nimport * as gitea from './gitea/index.ts';\nimport * as github from './github/index.ts';\nimport * as gitlab from './gitlab/index.ts';\nimport type {\n ChangeLogFile,\n ChangeLogNotes,\n ChangeLogProject,\n ChangeLogRelease,\n ChangeLogResult,\n} from './types.ts';\n\nconst markdown = new MarkdownIt('zero');\nmarkdown.enable(['heading', 'lheading', 'fence']);\n\nconst repositoriesToSkipMdFetching = ['facebook/react-native'];\n\nexport async function getReleaseList(\n project: ChangeLogProject,\n release: ChangeLogRelease,\n): Promise<ChangeLogNotes[]> {\n logger.trace('getReleaseList()');\n const { apiBaseUrl, repository, type } = project;\n try {\n switch (type) {\n case 'bitbucket':\n return bitbucket.getReleaseList(project, release);\n case 'bitbucket-server':\n logger.trace(\n 'Unsupported Bitbucket Server feature. Skipping release fetching.',\n );\n return [];\n case 'forgejo':\n return await forgejo.getReleaseList(project, release);\n case 'gitea':\n return await gitea.getReleaseList(project, release);\n case 'github':\n return await github.getReleaseList(project, release);\n case 'gitlab':\n return await gitlab.getReleaseList(project, release);\n default:\n logger.warn({ apiBaseUrl, repository, type }, 'Invalid project type');\n return [];\n }\n } catch (err) /* istanbul ignore next */ {\n if (err.statusCode === 404) {\n logger.debug({ repository, type, apiBaseUrl }, 'getReleaseList 404');\n } else {\n logger.debug(\n { repository, type, apiBaseUrl, err },\n 'getReleaseList error',\n );\n }\n }\n return [];\n}\n\nexport function getCachedReleaseList(\n project: ChangeLogProject,\n release: ChangeLogRelease,\n): Promise<ChangeLogNotes[]> {\n const { repository, apiBaseUrl } = project;\n // TODO: types (#22198)\n const cacheKey = `getReleaseList-${apiBaseUrl}-${repository}`;\n const cachedResult = memCache.get<Promise<ChangeLogNotes[]>>(cacheKey);\n // istanbul ignore if\n if (cachedResult !== undefined) {\n return cachedResult;\n }\n const promisedRes = getReleaseList(project, release);\n memCache.set(cacheKey, promisedRes);\n return promisedRes;\n}\n\nexport function massageBody(\n input: string | undefined | null,\n baseUrl: string,\n): string {\n let body = coerceString(input);\n // Convert line returns\n body = body.replace(regEx(/\\r\\n/g), '\\n');\n // semantic-release cleanup\n body = body.replace(regEx(/^<a name=\"[^\"]*\"><\\/a>\\n/), '');\n body = body.replace(\n regEx(\n `^##? \\\\[[^\\\\]]*\\\\]\\\\(${baseUrl}[^/]*/[^/]*/compare/.*?\\\\n`,\n undefined,\n false,\n ),\n '',\n );\n // Clean-up unnecessary commits link\n body = `\\n${body}\\n`.replace(\n regEx(`\\\\n${baseUrl}[^/]+/[^/]+/compare/[^\\\\n]+(\\\\n|$)`),\n '\\n',\n );\n // Reduce headings size\n body = body\n .split(regEx(/(```[\\s\\S]*?```)/g))\n .map((part) =>\n part.startsWith('```') // do not modify # inside of codeblocks\n ? part\n : part\n .replace(regEx(/\\n\\s*####? /g), '\\n##### ')\n .replace(regEx(/\\n\\s*## /g), '\\n#### ')\n .replace(regEx(/\\n\\s*# /g), '\\n### '),\n )\n .join('');\n // Trim whitespace\n return body.trim();\n}\n\nexport function massageName(\n input: string | undefined | null,\n version: string | undefined,\n): string | undefined {\n let name = input ?? '';\n\n if (version) {\n name = name.replace(RegExp(`^(Release )?v?${version}`, 'i'), '').trim();\n }\n\n name = name.trim();\n if (!name.length) {\n return undefined;\n }\n\n return name;\n}\n\nexport async function getReleaseNotes(\n project: ChangeLogProject,\n release: ChangeLogRelease,\n config: BranchUpgradeConfig,\n): Promise<ChangeLogNotes | null> {\n const { packageName, depName, repository } = project;\n const { version, gitRef } = release;\n // TODO: types (#22198)\n logger.trace(\n `getReleaseNotes(${repository}, ${version}, ${packageName!}, ${depName!})`,\n );\n const releases = await getCachedReleaseList(project, release);\n logger.trace({ releases }, 'Release list from getReleaseList');\n let releaseNotes: ChangeLogNotes | null = null;\n\n let matchedRelease = getExactReleaseMatch(\n packageName!,\n depName!,\n version,\n releases,\n );\n if (isUndefined(matchedRelease)) {\n // no exact match of a release then check other cases\n matchedRelease = releases.find(\n (r) =>\n r.tag === version ||\n r.tag === `v${version}` ||\n r.tag === gitRef ||\n r.tag === `v${gitRef}`,\n );\n }\n if (isUndefined(matchedRelease) && config.extractVersion) {\n const extractVersionRegEx = regEx(config.extractVersion);\n matchedRelease = releases.find((r) => {\n const extractedVersion = extractVersionRegEx.exec(r.tag!)?.groups\n ?.version;\n return version === extractedVersion;\n });\n }\n releaseNotes = await releaseNotesResult(matchedRelease, project);\n logger.trace({ releaseNotes });\n return releaseNotes;\n}\n\nfunction getExactReleaseMatch(\n packageName: string,\n depName: string,\n version: string,\n releases: ChangeLogNotes[],\n): ChangeLogNotes | undefined {\n const exactReleaseReg = regEx(\n `(?:^|/)(?:${packageName}|${depName})[@_/-]v?${version}`,\n );\n const candidateReleases = releases.filter((r) => r.tag?.endsWith(version));\n const matchedRelease = candidateReleases.find((r) =>\n exactReleaseReg.test(r.tag!),\n );\n return matchedRelease;\n}\n\nasync function releaseNotesResult(\n releaseMatch: ChangeLogNotes | undefined,\n project: ChangeLogProject,\n): Promise<ChangeLogNotes | null> {\n if (!releaseMatch) {\n return null;\n }\n const { baseUrl, repository } = project;\n const releaseNotes: ChangeLogNotes = releaseMatch;\n if (detectPlatform(baseUrl) === 'gitlab') {\n releaseNotes.url = `${baseUrl}${repository}/tags/${releaseMatch.tag!}`;\n } else {\n releaseNotes.url = releaseMatch.url\n ? releaseMatch.url\n : /* istanbul ignore next */\n `${baseUrl}${repository}/releases/${releaseMatch.tag!}`;\n }\n // set body for release notes\n releaseNotes.body = massageBody(releaseNotes.body, baseUrl);\n releaseNotes.name = massageName(releaseNotes.name, releaseNotes.tag);\n if (releaseNotes.body.length || releaseNotes.name?.length) {\n try {\n if (baseUrl !== 'https://gitlab.com/') {\n releaseNotes.body = await linkify(releaseNotes.body, {\n repository: `${baseUrl}${repository}`,\n });\n }\n } catch (err) /* istanbul ignore next */ {\n logger.warn({ err, baseUrl, repository }, 'Error linkifying');\n }\n } else {\n return null;\n }\n\n return releaseNotes;\n}\n\nfunction sectionize(text: string, level: number): string[] {\n const sections: [number, number][] = [];\n const lines = text.split(newlineRegex);\n const tokens = markdown.parse(text, undefined);\n tokens.forEach((token) => {\n if (token.type === 'heading_open') {\n const lev = +token.tag.substring(1);\n if (lev <= level) {\n sections.push([lev, token.map![0]]);\n }\n }\n });\n sections.push([-1, lines.length]);\n const result: string[] = [];\n for (let i = 1; i < sections.length; i += 1) {\n const [lev, start] = sections[i - 1];\n const [, end] = sections[i];\n if (lev === level) {\n result.push(lines.slice(start, end).join('\\n'));\n }\n }\n return result;\n}\n\nexport async function getReleaseNotesMdFileInner(\n project: ChangeLogProject,\n): Promise<ChangeLogFile | null> {\n const { repository, type } = project;\n const apiBaseUrl = project.apiBaseUrl;\n const sourceDirectory = project.sourceDirectory!;\n try {\n switch (type) {\n case 'bitbucket':\n return await bitbucket.getReleaseNotesMd(\n repository,\n apiBaseUrl,\n sourceDirectory,\n );\n case 'bitbucket-server':\n return await bitbucketServer.getReleaseNotesMd(\n repository,\n apiBaseUrl,\n sourceDirectory,\n );\n case 'forgejo':\n return await forgejo.getReleaseNotesMd(\n repository,\n apiBaseUrl,\n sourceDirectory,\n );\n case 'gitea':\n return await gitea.getReleaseNotesMd(\n repository,\n apiBaseUrl,\n sourceDirectory,\n );\n case 'github':\n return await github.getReleaseNotesMd(\n repository,\n apiBaseUrl,\n sourceDirectory,\n );\n case 'gitlab':\n return await gitlab.getReleaseNotesMd(\n repository,\n apiBaseUrl,\n sourceDirectory,\n );\n default:\n logger.warn({ apiBaseUrl, repository, type }, 'Invalid project type');\n return null;\n }\n } catch (err) /* istanbul ignore next */ {\n if (err.statusCode === 404) {\n logger.debug(\n { repository, type, apiBaseUrl },\n 'Error 404 getting changelog md',\n );\n } else {\n logger.debug(\n { err, repository, type, apiBaseUrl },\n 'Error getting changelog md',\n );\n }\n }\n return null;\n}\n\nexport function getReleaseNotesMdFile(\n project: ChangeLogProject,\n): Promise<ChangeLogFile | null> {\n const { sourceDirectory, repository, apiBaseUrl } = project;\n // TODO: types (#22198)\n const cacheKey = sourceDirectory\n ? `getReleaseNotesMdFile@v2-${repository}-${sourceDirectory}-${apiBaseUrl}`\n : `getReleaseNotesMdFile@v2-${repository}-${apiBaseUrl}`;\n const cachedResult = memCache.get<Promise<ChangeLogFile | null>>(cacheKey);\n // istanbul ignore if\n if (cachedResult !== undefined) {\n return cachedResult;\n }\n const promisedRes = getReleaseNotesMdFileInner(project);\n memCache.set(cacheKey, promisedRes);\n return promisedRes;\n}\n\nexport async function getReleaseNotesMd(\n project: ChangeLogProject,\n release: ChangeLogRelease,\n): Promise<ChangeLogNotes | null> {\n const { baseUrl, repository, packageName } = project;\n const version = release.version;\n logger.trace(`getReleaseNotesMd(${repository}, ${version})`);\n\n if (shouldSkipChangelogMd(repository)) {\n return null;\n }\n\n const changelog = await getReleaseNotesMdFile(project);\n if (!changelog) {\n return null;\n }\n const { changelogFile } = changelog;\n const changelogMd = changelog.changelogMd.replace(\n regEx(/\\n\\s*<a name=\"[^\"]*\">.*?<\\/a>\\n/g),\n '\\n',\n );\n for (const level of [1, 2, 3, 4, 5, 6, 7]) {\n const changelogParsed = sectionize(changelogMd, level);\n if (changelogParsed.length >= 2) {\n for (const section of changelogParsed) {\n try {\n // replace brackets and parenthesis with space\n const deParenthesizedSection = section.replace(\n regEx(/[[\\]()]/g),\n ' ',\n );\n const [heading] = deParenthesizedSection.split(newlineRegex);\n const title = heading\n .replace(regEx(/^\\s*#*\\s*/), '')\n .split(' ')\n .filter(Boolean);\n const body = section.replace(regEx(/.*?\\n(-{3,}\\n)?/), '').trim();\n const notesSourceUrl = getNotesSourceUrl(\n baseUrl,\n repository,\n project,\n changelogFile,\n );\n const mdHeadingLink = title\n .filter((word) => !isHttpUrl(word))\n .join('-')\n .replace(regEx(/[^A-Za-z0-9-]/g), '');\n const url = `${notesSourceUrl}#${mdHeadingLink}`;\n // Look for version in title\n for (const word of title) {\n if (word.includes(version) && !isHttpUrl(word)) {\n logger.trace({ body }, `Found release notes for v${version}`);\n return {\n body: await linkifyBody(project, body),\n url,\n notesSourceUrl,\n };\n }\n }\n // Look for version in body - useful for monorepos. First check for heading with \"(yyyy-mm-dd)\"\n const releasesRegex = regEx(/([0-9]{4}-[0-9]{2}-[0-9]{2})/);\n if (packageName && heading.search(releasesRegex) !== -1) {\n // Now check if any line contains both the package name and the version\n // Skip Markdown link reference definitions (e.g. `[1.2.3]: https://…/compare/...`)\n // which Keep-a-Changelog files list at the bottom and would otherwise match every version.\n const linkRefDefRegex = regEx(/^\\s*\\[[^\\]]+\\]:\\s*\\S+/);\n const bodyLines = body.split('\\n');\n if (\n bodyLines.some(\n (line) =>\n line.includes(packageName) &&\n line.includes(version) &&\n !isHttpUrl(line) &&\n !linkRefDefRegex.test(line),\n )\n ) {\n logger.trace({ body }, `Found release notes for v${version}`);\n return {\n body: await linkifyBody(project, body),\n url,\n notesSourceUrl,\n };\n }\n }\n } catch (err) /* istanbul ignore next */ {\n logger.warn(\n { file: changelogFile, err },\n `Error parsing changelog file`,\n );\n }\n }\n }\n logger.trace({ repository }, `No level ${level} changelogs headings found`);\n }\n logger.trace({ repository, version }, `No entry found in ${changelogFile}`);\n return null;\n}\n\n/**\n * Determine how long to cache release notes based on when the version was released.\n *\n * It's not uncommon for release notes to be updated shortly after the release itself,\n * so only cache for about an hour when the release is less than a week old. Otherwise,\n * cache for days.\n */\nexport function releaseNotesCacheMinutes(releaseDate?: string | Date): number {\n const dt = isDate(releaseDate)\n ? DateTime.fromJSDate(releaseDate)\n : DateTime.fromISO(releaseDate!);\n\n const now = DateTime.local();\n\n if (!dt.isValid || now.diff(dt, 'days').days < 7) {\n return 55;\n }\n\n if (now.diff(dt, 'months').months < 6) {\n return 1435; // 5 minutes shy of one day\n }\n\n return 14495; // 5 minutes shy of 10 days\n}\n\nexport async function addReleaseNotes(\n input: ChangeLogResult | null | undefined,\n config: BranchUpgradeConfig,\n): Promise<ChangeLogResult | null> {\n if (!input?.versions || !input.project?.type) {\n logger.debug('Missing project or versions');\n return input ?? null;\n }\n const output: ChangeLogResult = {\n ...input,\n versions: [],\n hasReleaseNotes: false,\n };\n\n const { repository, sourceDirectory, type: projectType } = input.project;\n const cacheNamespace: PackageCacheNamespace = `changelog-${projectType}-notes@v2`;\n const cacheKeyPrefix = sourceDirectory\n ? `${repository}:${sourceDirectory}`\n : `${repository}`;\n\n for (const v of input.versions) {\n let releaseNotes: ChangeLogNotes | null | undefined;\n const cacheKey = `${cacheKeyPrefix}:${v.version}`;\n releaseNotes = await packageCache.get(cacheNamespace, cacheKey);\n releaseNotes ??= await getReleaseNotesMd(input.project, v);\n releaseNotes ??= await getReleaseNotes(input.project, v, config);\n\n // If there is no release notes, at least try to show the compare URL\n if (!releaseNotes && v.compare.url) {\n releaseNotes = { url: v.compare.url, notesSourceUrl: '' };\n }\n\n const cacheMinutes = releaseNotesCacheMinutes(v.date);\n await packageCache.set(\n cacheNamespace,\n cacheKey,\n releaseNotes,\n cacheMinutes,\n );\n output.versions!.push({\n ...v,\n releaseNotes: releaseNotes!,\n });\n\n if (releaseNotes) {\n output.hasReleaseNotes = true;\n }\n }\n return output;\n}\n\n/**\n * Skip fetching changelog/release-notes markdown files.\n * Will force a fallback to using GitHub release notes\n */\nexport function shouldSkipChangelogMd(repository: string): boolean {\n return repositoriesToSkipMdFetching.includes(repository);\n}\n\nfunction getNotesSourceUrl(\n baseUrl: string,\n repository: string,\n project: ChangeLogProject,\n changelogFile: string,\n): string {\n if (project.type === 'bitbucket-server') {\n const [projectKey, repositorySlug] = repository.split('/');\n return joinUrlParts(\n baseUrl,\n 'projects',\n projectKey,\n 'repos',\n repositorySlug,\n 'browse',\n changelogFile,\n '?at=HEAD',\n );\n }\n\n return joinUrlParts(\n baseUrl,\n repository,\n project.type === 'bitbucket' ? 'src' : 'blob',\n 'HEAD',\n changelogFile,\n );\n}\n\nasync function linkifyBody(\n { baseUrl, repository }: ChangeLogProject,\n bodyStr: string,\n): Promise<string> {\n const body = massageBody(bodyStr, baseUrl);\n if (body?.length) {\n try {\n return await linkify(body, {\n repository: `${baseUrl}${repository}`,\n });\n } catch (err) /* istanbul ignore next */ {\n logger.warn({ body, err }, 'linkify error');\n }\n }\n return body;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"release-notes.js","names":["bitbucket.getReleaseList","forgejo.getReleaseList","gitea.getReleaseList","github.getReleaseList","gitlab.getReleaseList","memCache.get","bitbucket.getReleaseNotesMd","bitbucketServer.getReleaseNotesMd","forgejo.getReleaseNotesMd","gitea.getReleaseNotesMd","github.getReleaseNotesMd","gitlab.getReleaseNotesMd","packageCache.get","packageCache.set"],"sources":["../../../../../../lib/workers/repository/update/pr/changelog/release-notes.ts"],"sourcesContent":["import { isDate, isUndefined } from '@sindresorhus/is';\nimport { DateTime } from 'luxon';\nimport MarkdownIt from 'markdown-it';\nimport { logger } from '../../../../../logger/index.ts';\nimport * as memCache from '../../../../../util/cache/memory/index.ts';\nimport * as packageCache from '../../../../../util/cache/package/index.ts';\nimport type { PackageCacheNamespace } from '../../../../../util/cache/package/types.ts';\nimport { detectPlatform } from '../../../../../util/common.ts';\nimport { linkify } from '../../../../../util/markdown.ts';\nimport { newlineRegex, regEx } from '../../../../../util/regex.ts';\nimport { coerceString } from '../../../../../util/string.ts';\nimport { isHttpUrl, joinUrlParts } from '../../../../../util/url.ts';\nimport type { BranchUpgradeConfig } from '../../../../types.ts';\nimport * as bitbucket from './bitbucket/index.ts';\nimport * as bitbucketServer from './bitbucket-server/index.ts';\nimport * as forgejo from './forgejo/index.ts';\nimport * as gitea from './gitea/index.ts';\nimport * as github from './github/index.ts';\nimport * as gitlab from './gitlab/index.ts';\nimport type {\n ChangeLogFile,\n ChangeLogNotes,\n ChangeLogProject,\n ChangeLogRelease,\n ChangeLogResult,\n} from './types.ts';\n\nconst markdown = new MarkdownIt('zero');\nmarkdown.enable(['heading', 'lheading', 'fence']);\n\nconst repositoriesToSkipMdFetching = ['facebook/react-native'];\n\nexport async function getReleaseList(\n project: ChangeLogProject,\n release: ChangeLogRelease,\n): Promise<ChangeLogNotes[]> {\n logger.trace('getReleaseList()');\n const { apiBaseUrl, repository, type } = project;\n try {\n switch (type) {\n case 'bitbucket':\n return bitbucket.getReleaseList(project, release);\n case 'bitbucket-server':\n logger.trace(\n 'Unsupported Bitbucket Server feature. Skipping release fetching.',\n );\n return [];\n case 'forgejo':\n return await forgejo.getReleaseList(project, release);\n case 'gitea':\n return await gitea.getReleaseList(project, release);\n case 'github':\n return await github.getReleaseList(project, release);\n case 'gitlab':\n return await gitlab.getReleaseList(project, release);\n default:\n logger.warn({ apiBaseUrl, repository, type }, 'Invalid project type');\n return [];\n }\n } catch (err) /* istanbul ignore next */ {\n if (err.statusCode === 404) {\n logger.debug({ repository, type, apiBaseUrl }, 'getReleaseList 404');\n } else {\n logger.debug(\n { repository, type, apiBaseUrl, err },\n 'getReleaseList error',\n );\n }\n }\n return [];\n}\n\nexport function getCachedReleaseList(\n project: ChangeLogProject,\n release: ChangeLogRelease,\n): Promise<ChangeLogNotes[]> {\n const { repository, apiBaseUrl } = project;\n // TODO: types (#22198)\n const cacheKey = `getReleaseList-${apiBaseUrl}-${repository}`;\n const cachedResult = memCache.get<Promise<ChangeLogNotes[]>>(cacheKey);\n // istanbul ignore if\n if (cachedResult !== undefined) {\n return cachedResult;\n }\n const promisedRes = getReleaseList(project, release);\n memCache.set(cacheKey, promisedRes);\n return promisedRes;\n}\n\nexport function massageBody(\n input: string | undefined | null,\n baseUrl: string,\n): string {\n let body = coerceString(input);\n // Convert line returns\n body = body.replace(regEx(/\\r\\n/g), '\\n');\n // semantic-release cleanup\n body = body.replace(regEx(/^<a name=\"[^\"]*\"><\\/a>\\n/), '');\n body = body.replace(\n regEx(\n `^##? \\\\[[^\\\\]]*\\\\]\\\\(${baseUrl}[^/]*/[^/]*/compare/.*?\\\\n`,\n undefined,\n false,\n ),\n '',\n );\n // Clean-up unnecessary commits link\n body = `\\n${body}\\n`.replace(\n regEx(`\\\\n${baseUrl}[^/]+/[^/]+/compare/[^\\\\n]+(\\\\n|$)`),\n '\\n',\n );\n // Reduce headings size\n body = body\n .split(regEx(/(```[\\s\\S]*?```)/g))\n .map((part) =>\n part.startsWith('```') // do not modify # inside of codeblocks\n ? part\n : part\n .replace(regEx(/\\n\\s*####? /g), '\\n##### ')\n .replace(regEx(/\\n\\s*## /g), '\\n#### ')\n .replace(regEx(/\\n\\s*# /g), '\\n### '),\n )\n .join('');\n // Trim whitespace\n return body.trim();\n}\n\nexport function massageName(\n input: string | undefined | null,\n version: string | undefined,\n): string | undefined {\n let name = input ?? '';\n\n if (version) {\n name = name.replace(RegExp(`^(Release )?v?${version}`, 'i'), '').trim();\n }\n\n name = name.trim();\n if (!name.length) {\n return undefined;\n }\n\n return name;\n}\n\nexport async function getReleaseNotes(\n project: ChangeLogProject,\n release: ChangeLogRelease,\n config: BranchUpgradeConfig,\n): Promise<ChangeLogNotes | null> {\n const { packageName, depName, repository } = project;\n const { version, gitRef } = release;\n // TODO: types (#22198)\n logger.trace(\n `getReleaseNotes(${repository}, ${version}, ${packageName!}, ${depName!})`,\n );\n const releases = await getCachedReleaseList(project, release);\n logger.trace({ releases }, 'Release list from getReleaseList');\n let releaseNotes: ChangeLogNotes | null = null;\n\n let matchedRelease = getExactReleaseMatch(\n packageName!,\n depName!,\n version,\n releases,\n );\n if (isUndefined(matchedRelease)) {\n // no exact match of a release then check other cases\n matchedRelease = releases.find(\n (r) =>\n r.tag === version ||\n r.tag === `v${version}` ||\n r.tag === gitRef ||\n r.tag === `v${gitRef}`,\n );\n }\n if (isUndefined(matchedRelease) && config.extractVersion) {\n const extractVersionRegEx = regEx(config.extractVersion);\n matchedRelease = releases.find((r) => {\n const extractedVersion = extractVersionRegEx.exec(r.tag!)?.groups\n ?.version;\n return version === extractedVersion;\n });\n }\n releaseNotes = await releaseNotesResult(matchedRelease, project);\n logger.trace({ releaseNotes });\n return releaseNotes;\n}\n\nfunction getExactReleaseMatch(\n packageName: string,\n depName: string,\n version: string,\n releases: ChangeLogNotes[],\n): ChangeLogNotes | undefined {\n const exactReleaseReg = regEx(\n `(?:^|/)(?:${packageName}|${depName})[@_/-]v?${version}`,\n );\n const candidateReleases = releases.filter((r) => r.tag?.endsWith(version));\n const matchedRelease = candidateReleases.find((r) =>\n exactReleaseReg.test(r.tag!),\n );\n return matchedRelease;\n}\n\nasync function releaseNotesResult(\n releaseMatch: ChangeLogNotes | undefined,\n project: ChangeLogProject,\n): Promise<ChangeLogNotes | null> {\n if (!releaseMatch) {\n return null;\n }\n const { baseUrl, repository } = project;\n const releaseNotes: ChangeLogNotes = releaseMatch;\n if (detectPlatform(baseUrl) === 'gitlab') {\n releaseNotes.url = `${baseUrl}${repository}/tags/${releaseMatch.tag!}`;\n } else {\n releaseNotes.url = releaseMatch.url\n ? releaseMatch.url\n : /* istanbul ignore next */\n `${baseUrl}${repository}/releases/${releaseMatch.tag!}`;\n }\n // set body for release notes\n releaseNotes.body = massageBody(releaseNotes.body, baseUrl);\n releaseNotes.name = massageName(releaseNotes.name, releaseNotes.tag);\n if (releaseNotes.body.length || releaseNotes.name?.length) {\n try {\n if (baseUrl !== 'https://gitlab.com/') {\n releaseNotes.body = await linkify(releaseNotes.body, {\n repository: `${baseUrl}${repository}`,\n });\n }\n } catch (err) /* istanbul ignore next */ {\n logger.warn({ err, baseUrl, repository }, 'Error linkifying');\n }\n } else {\n return null;\n }\n\n return releaseNotes;\n}\n\nfunction sectionize(text: string, level: number): string[] {\n const sections: [number, number][] = [];\n const lines = text.split(newlineRegex);\n const tokens = markdown.parse(text, undefined);\n tokens.forEach((token) => {\n if (token.type === 'heading_open') {\n const lev = +token.tag.substring(1);\n if (lev <= level) {\n sections.push([lev, token.map![0]]);\n }\n }\n });\n sections.push([-1, lines.length]);\n const result: string[] = [];\n for (let i = 1; i < sections.length; i += 1) {\n const [lev, start] = sections[i - 1];\n const [, end] = sections[i];\n if (lev === level) {\n result.push(lines.slice(start, end).join('\\n'));\n }\n }\n return result;\n}\n\nexport async function getReleaseNotesMdFileInner(\n project: ChangeLogProject,\n): Promise<ChangeLogFile | null> {\n const { repository, type } = project;\n const apiBaseUrl = project.apiBaseUrl;\n const sourceDirectory = project.sourceDirectory!;\n try {\n switch (type) {\n case 'bitbucket':\n return await bitbucket.getReleaseNotesMd(\n repository,\n apiBaseUrl,\n sourceDirectory,\n );\n case 'bitbucket-server':\n return await bitbucketServer.getReleaseNotesMd(\n repository,\n apiBaseUrl,\n sourceDirectory,\n );\n case 'forgejo':\n return await forgejo.getReleaseNotesMd(\n repository,\n apiBaseUrl,\n sourceDirectory,\n );\n case 'gitea':\n return await gitea.getReleaseNotesMd(\n repository,\n apiBaseUrl,\n sourceDirectory,\n );\n case 'github':\n return await github.getReleaseNotesMd(\n repository,\n apiBaseUrl,\n sourceDirectory,\n );\n case 'gitlab':\n return await gitlab.getReleaseNotesMd(\n repository,\n apiBaseUrl,\n sourceDirectory,\n );\n default:\n logger.warn({ apiBaseUrl, repository, type }, 'Invalid project type');\n return null;\n }\n } catch (err) /* istanbul ignore next */ {\n if (err.statusCode === 404) {\n logger.debug(\n { repository, type, apiBaseUrl },\n 'Error 404 getting changelog md',\n );\n } else {\n logger.debug(\n { err, repository, type, apiBaseUrl },\n 'Error getting changelog md',\n );\n }\n }\n return null;\n}\n\nexport function getReleaseNotesMdFile(\n project: ChangeLogProject,\n): Promise<ChangeLogFile | null> {\n const { sourceDirectory, repository, apiBaseUrl } = project;\n // TODO: types (#22198)\n const cacheKey = sourceDirectory\n ? `getReleaseNotesMdFile@v2-${repository}-${sourceDirectory}-${apiBaseUrl}`\n : `getReleaseNotesMdFile@v2-${repository}-${apiBaseUrl}`;\n const cachedResult = memCache.get<Promise<ChangeLogFile | null>>(cacheKey);\n // istanbul ignore if\n if (cachedResult !== undefined) {\n return cachedResult;\n }\n const promisedRes = getReleaseNotesMdFileInner(project);\n memCache.set(cacheKey, promisedRes);\n return promisedRes;\n}\n\nexport async function getReleaseNotesMd(\n project: ChangeLogProject,\n release: ChangeLogRelease,\n): Promise<ChangeLogNotes | null> {\n const { baseUrl, repository, packageName } = project;\n const version = release.version;\n logger.trace(`getReleaseNotesMd(${repository}, ${version})`);\n\n if (shouldSkipChangelogMd(repository)) {\n return null;\n }\n\n const changelog = await getReleaseNotesMdFile(project);\n if (!changelog) {\n return null;\n }\n const { changelogFile } = changelog;\n const changelogMd = changelog.changelogMd.replace(\n regEx(/\\n\\s*<a name=\"[^\"]*\">.*?<\\/a>\\n/g),\n '\\n',\n );\n for (const level of [1, 2, 3, 4, 5, 6, 7]) {\n const changelogParsed = sectionize(changelogMd, level);\n if (changelogParsed.length >= 2) {\n for (const section of changelogParsed) {\n try {\n // replace brackets and parenthesis with space\n const deParenthesizedSection = section.replace(\n regEx(/[[\\]()]/g),\n ' ',\n );\n const [heading] = deParenthesizedSection.split(newlineRegex);\n const title = heading\n .replace(regEx(/^\\s*#*\\s*/), '')\n .split(' ')\n .filter(Boolean);\n const body = section.replace(regEx(/.*?\\n(-{3,}\\n)?/), '').trim();\n const notesSourceUrl = getNotesSourceUrl(\n baseUrl,\n repository,\n project,\n changelogFile,\n );\n const mdHeadingLink = title\n .filter((word) => !isHttpUrl(word))\n .join('-')\n .replace(regEx(/[^A-Za-z0-9-]/g), '');\n const url = `${notesSourceUrl}#${mdHeadingLink}`;\n // Look for version in title\n for (const word of title) {\n if (word.includes(version) && !isHttpUrl(word)) {\n logger.trace({ body }, `Found release notes for v${version}`);\n return {\n body: await linkifyBody(project, body),\n url,\n notesSourceUrl,\n };\n }\n }\n // Look for version in body - useful for monorepos. First check for heading with \"(yyyy-mm-dd)\"\n const releasesRegex = regEx(/([0-9]{4}-[0-9]{2}-[0-9]{2})/);\n if (packageName && heading.search(releasesRegex) !== -1) {\n // Now check if any line contains both the package name and the version\n // Skip Markdown link reference definitions (e.g. `[1.2.3]: https://…/compare/...`)\n // which Keep-a-Changelog files list at the bottom and would otherwise match every version.\n const linkRefDefRegex = regEx(/^\\s*\\[[^\\]]+\\]:\\s*\\S+/);\n const bodyLines = body.split('\\n');\n if (\n bodyLines.some(\n (line) =>\n line.includes(packageName) &&\n line.includes(version) &&\n !isHttpUrl(line) &&\n !linkRefDefRegex.test(line),\n )\n ) {\n logger.trace({ body }, `Found release notes for v${version}`);\n return {\n body: await linkifyBody(project, body),\n url,\n notesSourceUrl,\n };\n }\n }\n } catch (err) /* istanbul ignore next */ {\n logger.warn(\n { file: changelogFile, err },\n `Error parsing changelog file`,\n );\n }\n }\n }\n logger.trace({ repository }, `No level ${level} changelogs headings found`);\n }\n logger.trace({ repository, version }, `No entry found in ${changelogFile}`);\n return null;\n}\n\n/**\n * Determine how long to cache release notes based on when the version was released.\n *\n * It's not uncommon for release notes to be updated shortly after the release itself,\n * so only cache for about an hour when the release is less than a week old. Otherwise,\n * cache for days.\n */\nexport function releaseNotesCacheMinutes(releaseDate?: string | Date): number {\n const dt = isDate(releaseDate)\n ? DateTime.fromJSDate(releaseDate)\n : DateTime.fromISO(releaseDate!);\n\n const now = DateTime.local();\n\n if (!dt.isValid || now.diff(dt, 'days').days < 7) {\n return 55;\n }\n\n if (now.diff(dt, 'months').months < 6) {\n return 1435; // 5 minutes shy of one day\n }\n\n return 14495; // 5 minutes shy of 10 days\n}\n\nexport async function addReleaseNotes(\n input: ChangeLogResult | null | undefined,\n config: BranchUpgradeConfig,\n): Promise<ChangeLogResult | null> {\n if (!input?.versions || !input.project?.type) {\n logger.debug('Missing project or versions');\n return input ?? null;\n }\n const output: ChangeLogResult = {\n ...input,\n versions: [],\n hasReleaseNotes: false,\n };\n\n const { repository, sourceDirectory, type: projectType } = input.project;\n const cacheNamespace: PackageCacheNamespace = `changelog-${projectType}-notes@v2`;\n const cacheKeyPrefix = sourceDirectory\n ? `${repository}:${sourceDirectory}`\n : `${repository}`;\n\n for (const v of input.versions) {\n let releaseNotes: ChangeLogNotes | null | undefined;\n const gitRefCachePart = v.gitRef ? `:${v.gitRef}` : '';\n const cacheKey = `${cacheKeyPrefix}:${v.version}${gitRefCachePart}`;\n releaseNotes = await packageCache.get(cacheNamespace, cacheKey);\n releaseNotes ??= await getReleaseNotesMd(input.project, v);\n releaseNotes ??= await getReleaseNotes(input.project, v, config);\n\n // If there is no release notes, at least try to show the compare URL\n if (!releaseNotes && v.compare.url) {\n releaseNotes = { url: v.compare.url, notesSourceUrl: '' };\n }\n\n const cacheMinutes = releaseNotesCacheMinutes(v.date);\n await packageCache.set(\n cacheNamespace,\n cacheKey,\n releaseNotes,\n cacheMinutes,\n );\n output.versions!.push({\n ...v,\n releaseNotes: releaseNotes!,\n });\n\n if (releaseNotes) {\n output.hasReleaseNotes = true;\n }\n }\n return output;\n}\n\n/**\n * Skip fetching changelog/release-notes markdown files.\n * Will force a fallback to using GitHub release notes\n */\nexport function shouldSkipChangelogMd(repository: string): boolean {\n return repositoriesToSkipMdFetching.includes(repository);\n}\n\nfunction getNotesSourceUrl(\n baseUrl: string,\n repository: string,\n project: ChangeLogProject,\n changelogFile: string,\n): string {\n if (project.type === 'bitbucket-server') {\n const [projectKey, repositorySlug] = repository.split('/');\n return joinUrlParts(\n baseUrl,\n 'projects',\n projectKey,\n 'repos',\n repositorySlug,\n 'browse',\n changelogFile,\n '?at=HEAD',\n );\n }\n\n return joinUrlParts(\n baseUrl,\n repository,\n project.type === 'bitbucket' ? 'src' : 'blob',\n 'HEAD',\n changelogFile,\n );\n}\n\nasync function linkifyBody(\n { baseUrl, repository }: ChangeLogProject,\n bodyStr: string,\n): Promise<string> {\n const body = massageBody(bodyStr, baseUrl);\n if (body?.length) {\n try {\n return await linkify(body, {\n repository: `${baseUrl}${repository}`,\n });\n } catch (err) /* istanbul ignore next */ {\n logger.warn({ body, err }, 'linkify error');\n }\n }\n return body;\n}\n"],"mappings":"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"}
@@ -7,7 +7,7 @@ import { MergeConfidence } from "../util/merge-confidence/types.js";
7
7
  import { ChangeLogRelease, ChangeLogResult } from "./repository/update/pr/changelog/types.js";
8
8
  import { BranchStatus } from "../types/branch-status.js";
9
9
  import { ArtifactError, ArtifactNotice, ExtractConfig, LookupUpdate, PackageDependency, PackageFile } from "../modules/manager/types.js";
10
- import { GroupConfig, LegacyAdminConfig, RenovateConfig, RenovateSharedConfig, ValidationMessage } from "../config/types.js";
10
+ import { GroupConfig, LegacyAdminConfig, RenovateConfig, RenovateSharedConfig, UpdateType, ValidationMessage } from "../config/types.js";
11
11
  import { Merge } from "type-fest";
12
12
 
13
13
  //#region lib/workers/types.d.ts
@@ -148,6 +148,34 @@ interface BranchSummary {
148
148
  defaultBranch?: string;
149
149
  inactiveBranches: string[];
150
150
  }
151
+ interface ManagerUpdateSummary {
152
+ /** Total number of upgrades processed for this manager. */
153
+ total: number;
154
+ /**
155
+ * Number of upgrades flagged as a fix for a vulnerability alert.
156
+ *
157
+ * Counted separately to regular updates, as a `minor` version could include a security update.
158
+ */
159
+ vulnerabilityAlert: number;
160
+ /** The number of updates a given `updateType` has for this manager */
161
+ updates: Partial<Record<UpdateType, number>>;
162
+ }
163
+ interface BaseBranchUpdateSummary {
164
+ baseBranch: string;
165
+ /** Total number of upgrades processed for this base branch. */
166
+ total: number;
167
+ /**
168
+ * Number of upgrades flagged as a fix for a vulnerability alert.
169
+ *
170
+ * Counted separately to regular updates, as a `minor` version could include a security update.
171
+ */
172
+ vulnerabilityAlert: number;
173
+ /** The number of updates a given `updateType` has on this branch, across all package files and managers */
174
+ updates: Partial<Record<UpdateType, number>>;
175
+ /** Per-manager breakdown of updates on this base branch */
176
+ managers: Record<string, ManagerUpdateSummary>;
177
+ }
178
+ type UpdateSummary = BaseBranchUpdateSummary[];
151
179
  interface WorkerExtractConfig extends ExtractConfig {
152
180
  manager: string;
153
181
  fileList: string[];
@@ -188,5 +216,5 @@ interface ExtractResult {
188
216
  packageFiles: Record<string, PackageFile[]>;
189
217
  }
190
218
  //#endregion
191
- export { BaseBranchMetadata, BranchConfig, BranchMetadata, BranchResult, BranchSummary, BranchUpgradeConfig, CacheFingerprintMatchResult, DepWarnings, ExtractResult, PrBlockedBy, ReleaseWithNotes, SelectAllConfig, UpgradeFingerprintConfig, WorkerExtractConfig };
219
+ export { BaseBranchMetadata, BaseBranchUpdateSummary, BranchConfig, BranchMetadata, BranchResult, BranchSummary, BranchUpgradeConfig, CacheFingerprintMatchResult, DepWarnings, ExtractResult, ManagerUpdateSummary, PrBlockedBy, ReleaseWithNotes, SelectAllConfig, UpdateSummary, UpgradeFingerprintConfig, WorkerExtractConfig };
192
220
  //# sourceMappingURL=types.d.ts.map
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": "43.224.0",
4
+ "version": "43.225.0",
5
5
  "type": "module",
6
6
  "bin": {
7
7
  "renovate": "dist/renovate.js",
@@ -188,7 +188,7 @@
188
188
  "remark-github": "12.0.0",
189
189
  "safe-stable-stringify": "2.5.0",
190
190
  "sax": "1.6.0",
191
- "semver": "7.8.2",
191
+ "semver": "7.8.3",
192
192
  "semver-stable": "3.0.0",
193
193
  "semver-utils": "1.1.4",
194
194
  "shlex": "3.0.0",
@@ -273,7 +273,7 @@
273
273
  "nock": "14.0.15",
274
274
  "npm-run-all2": "8.0.4",
275
275
  "nyc": "18.0.0",
276
- "oxlint": "1.68.0",
276
+ "oxlint": "1.69.0",
277
277
  "oxlint-tsgolint": "0.23.0",
278
278
  "rimraf": "6.1.3",
279
279
  "semantic-release": "25.0.3",
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "$id": "https://docs.renovatebot.com/renovate-schema.json",
3
- "title": "JSON schema for Renovate 43.224.0 config files (https://renovatebot.com/)",
3
+ "title": "JSON schema for Renovate 43.225.0 config files (https://renovatebot.com/)",
4
4
  "$schema": "http://json-schema.org/draft-07/schema#",
5
- "x-renovate-version": "43.224.0",
5
+ "x-renovate-version": "43.225.0",
6
6
  "allowComments": true,
7
7
  "type": "object",
8
8
  "definitions": {