mirror of
https://github.com/renovatebot/renovate.git
synced 2026-10-24 22:48:06 +00:00
97327c3d28
* refactor(linters): add prefer-coerce-array rule Refs #45217 `x ?? []` and `coerceArray(x)` say the same thing, but only the second one is searchable and consistent. The rule flags a `??` whose default is a bare `[]` literal; a non-empty default or an asserted `([] as Foo[])` still passes. Applying it across `lib/` surfaced three spots the helper cannot cover, which keep `?? []` with a disable comment or a narrower fix: - `package-files.ts` destructures a tuple, which `coerceArray()` widens - `generate.spec.ts` defaults `matchAll()`, an iterator rather than an array - `mise/upgradeable-tooling.ts` declares a `Record` return, so its `?? []` fallback was wrong to begin with and becomes `coerceObject()` * refactor(platform/github): hoist the GHE version header lookup `Object.entries(...).find()` returns a tuple, and defaulting it with `?? []` only to destructure the second element reads as an array default when it is not one. Name the found entry instead, which drops the `?? []` rather than routing a tuple through `coerceArray()`.
144 lines
4.7 KiB
TypeScript
144 lines
4.7 KiB
TypeScript
import { DateTime } from 'luxon';
|
|
import type { RenovateConfig } from '../../../config/types.ts';
|
|
import { instrument } from '../../../instrumentation/index.ts';
|
|
import { logger } from '../../../logger/index.ts';
|
|
import { platform } from '../../../modules/platform/index.ts';
|
|
import { scm } from '../../../modules/platform/scm.ts';
|
|
import { ExternalHostError } from '../../../types/errors/external-host-error.ts';
|
|
import { coerceArray } from '../../../util/array.ts';
|
|
import { getCache } from '../../../util/cache/repository/index.ts';
|
|
import { getInheritedOrGlobal } from '../../../util/common.ts';
|
|
import type { BranchConfig } from '../../types.ts';
|
|
|
|
export async function getPrHourlyCount(
|
|
config: RenovateConfig,
|
|
): Promise<number> {
|
|
return await instrument('getPrHourlyCount', async () => {
|
|
try {
|
|
const prList = await platform.getPrList();
|
|
const currentHourStart = DateTime.utc().startOf('hour');
|
|
logger.debug(
|
|
`Calculating PRs created so far in this hour currentHourStart=${String(currentHourStart)}`,
|
|
);
|
|
const soFarThisHour = prList.filter(
|
|
(pr) =>
|
|
pr.sourceBranch !== getInheritedOrGlobal('onboardingBranch') &&
|
|
pr.sourceBranch.startsWith(config.branchPrefix!) &&
|
|
DateTime.fromISO(pr.createdAt!).toUTC() > currentHourStart,
|
|
);
|
|
logger.debug(
|
|
`${soFarThisHour.length} PRs have been created so far in this hour.`,
|
|
);
|
|
return soFarThisHour.length;
|
|
} catch (err) {
|
|
// istanbul ignore if
|
|
if (err instanceof ExternalHostError) {
|
|
throw err;
|
|
}
|
|
logger.error({ err }, 'Error checking PRs created per hour');
|
|
return 0;
|
|
}
|
|
});
|
|
}
|
|
|
|
export async function getConcurrentPrsCount(
|
|
config: RenovateConfig,
|
|
branches: BranchConfig[],
|
|
): Promise<number> {
|
|
return await instrument('getConcurrentPrsCount', async () => {
|
|
let openPrCount = 0;
|
|
for (const { branchName } of branches) {
|
|
try {
|
|
const pr = await platform.getBranchPr(branchName, config.baseBranch);
|
|
if (
|
|
pr &&
|
|
pr.sourceBranch !== getInheritedOrGlobal('onboardingBranch') &&
|
|
pr.state === 'open'
|
|
) {
|
|
openPrCount++;
|
|
}
|
|
} catch (err) {
|
|
// istanbul ignore if
|
|
if (err instanceof ExternalHostError) {
|
|
throw err;
|
|
} else {
|
|
// no-op
|
|
}
|
|
}
|
|
}
|
|
|
|
logger.debug(`${openPrCount} PRs are currently open`);
|
|
return openPrCount;
|
|
});
|
|
}
|
|
|
|
export async function getCommitsHourlyCount(
|
|
branches: BranchConfig[],
|
|
): Promise<number> {
|
|
return await instrument('getCommitsHourlyCount', async () => {
|
|
try {
|
|
const currentHourStart = DateTime.utc().startOf('hour');
|
|
logger.debug(
|
|
`Calculating commits so far in this hour currentHourStart=${String(currentHourStart)}, for ${branches.length} branches`,
|
|
);
|
|
|
|
const cache = getCache();
|
|
const cachedBranches = coerceArray(cache.branches);
|
|
|
|
// if we don't have all of our branches in our cache (for instance, if we're not using the Repository Cache, or this is the first run against a repo), we need to fall back to the SCM
|
|
const needsScmFallback = branches.some(
|
|
(branch) =>
|
|
!cachedBranches.find((b) => b.branchName === branch.branchName)
|
|
?.commitTimestamp,
|
|
);
|
|
const fallbackUpdateDates = needsScmFallback
|
|
? await scm.getAllBranchUpdateDates()
|
|
: {};
|
|
|
|
let soFarThisHour = 0;
|
|
for (const branch of branches) {
|
|
// First try to get from cache
|
|
const branchCache = cachedBranches.find(
|
|
(b) => b.branchName === branch.branchName,
|
|
);
|
|
|
|
if (branchCache?.commitTimestamp) {
|
|
const commitTime = DateTime.fromISO(
|
|
branchCache.commitTimestamp,
|
|
).toUTC();
|
|
if (commitTime > currentHourStart) {
|
|
soFarThisHour++;
|
|
}
|
|
} else {
|
|
// Fallback to SCM if not in cache
|
|
const updateDate = fallbackUpdateDates[branch.branchName];
|
|
if (updateDate && updateDate > currentHourStart) {
|
|
soFarThisHour++;
|
|
}
|
|
}
|
|
}
|
|
logger.debug(`${soFarThisHour} commits so far in this hour.`);
|
|
return soFarThisHour;
|
|
} catch (err) {
|
|
logger.error({ err }, 'Error checking commits per hour');
|
|
return 0;
|
|
}
|
|
});
|
|
}
|
|
|
|
export async function getConcurrentBranchesCount(
|
|
branches: BranchConfig[],
|
|
): Promise<number> {
|
|
return await instrument('getConcurrentBranchesCount', async () => {
|
|
let existingBranchCount = 0;
|
|
for (const branch of branches) {
|
|
if (await scm.branchExists(branch.branchName)) {
|
|
existingBranchCount++;
|
|
}
|
|
}
|
|
|
|
logger.debug(`${existingBranchCount} already existing branches found.`);
|
|
return existingBranchCount;
|
|
});
|
|
}
|