Files
renovate/lib/util/cache/package/ttl.ts
Jamie Tanna ff6761ed23 fix(config/global): return default values for GlobalConfig.get (#42113)
* fix(config/global): return default values for `GlobalConfig.get`

As noted in #39949, it can be awkward working with in `GlobalConfig.get`, where
we would previously need to specify the default value when calling `.get`,
which could lead to drift with the defaults for a given config option.

To reduce this risk, we can rely on a given `default` for a configuration
option, providing that as a default.

Because this now definitely returns a value that matches the config option, it
now allows us to remove `!` assertions.

* fixup! fix(config/global): return default values for `GlobalConfig.get`

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>

* fixup! fix(config/global): return default values for `GlobalConfig.get`

* test(presets): remove impossible test

As it's now not possible to set a value as `undefined` (as
`GlobalConfig` will then use the default), this test no longer validates
anything.

* test(workers/repository): add mock

Now `platform` defaults to `github`, we need to mock out the call to
fetch config.

Co-authored-by: Claude Sonnet 4.6 <jamie.tanna+claude-code@mend.io>

* test: coverage

* test: coverage

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: Claude Sonnet 4.6 <jamie.tanna+claude-code@mend.io>
2026-05-15 17:10:38 +00:00

66 lines
1.6 KiB
TypeScript

import { isNumber } from '@sindresorhus/is';
import { GlobalConfig } from '../../../config/global.ts';
import { matchRegexOrGlob } from '../../string-match.ts';
import type { PackageCacheNamespace } from './types.ts';
/**
* This MUST NOT be used outside of cache implementation
*
* @param namespace
*/
export function getTtlOverride(
namespace: PackageCacheNamespace,
): number | undefined {
const overrides = GlobalConfig.get('cacheTtlOverride');
let ttl: number | undefined = overrides[namespace];
if (isNumber(ttl)) {
return ttl;
}
let maxLen = 0;
for (const [key, value] of Object.entries(overrides)) {
if (!isNumber(value)) {
continue;
}
const keyLen = key.length;
if (keyLen > maxLen && matchRegexOrGlob(namespace, key)) {
maxLen = keyLen;
ttl = value;
}
}
if (isNumber(ttl)) {
return ttl;
}
return undefined;
}
export interface TTLValues {
/** TTL for serving cached value without hitting the server */
softTtlMinutes: number;
/** TTL for serving stale cache when upstream responds with errors */
hardTtlMinutes: number;
}
/**
* Apply user-configured overrides and return the final values for soft/hard TTL.
*
* @param namespace Cache namespace
* @param ttlMinutes TTL value configured in Renovate codebase
* @returns
*/
export function resolveTtlValues(
namespace: PackageCacheNamespace,
ttlMinutes: number,
): TTLValues {
const softTtlMinutes = getTtlOverride(namespace) ?? ttlMinutes;
const cacheHardTtlMinutes = GlobalConfig.get('cacheHardTtlMinutes');
const hardTtlMinutes = Math.max(softTtlMinutes, cacheHardTtlMinutes);
return { softTtlMinutes, hardTtlMinutes };
}