diff --git a/lib/config/presets/internal/workarounds.ts b/lib/config/presets/internal/workarounds.ts index 62e01f9426fbfa13da000f1c3ea7bfe035337335..0e9c2028d5fb17f8679f055e28a96d709cfa8e94 100644 --- a/lib/config/presets/internal/workarounds.ts +++ b/lib/config/presets/internal/workarounds.ts @@ -13,6 +13,7 @@ export const presets: Record<string, Preset> = { 'workarounds:typesNodeVersioning', 'workarounds:reduceRepologyServerLoad', 'workarounds:doNotUpgradeFromAlpineStableToEdge', + 'workarounds:supportRedHatImageVersion', ], ignoreDeps: [], }, @@ -89,4 +90,32 @@ export const presets: Record<string, Preset> = { }, ], }, + supportRedHatImageVersion: { + description: + 'Use specific versioning for Red Hat-maintained container images', + packageRules: [ + { + matchDatasources: ['docker'], + matchPackagePrefixes: [ + 'registry.access.redhat.com/rhceph/', + 'registry.access.redhat.com/rhgs3/', + 'registry.access.redhat.com/rhel7', + 'registry.access.redhat.com/rhel8/', + 'registry.access.redhat.com/rhel9/', + 'registry.access.redhat.com/rhscl/', + 'registry.access.redhat.com/ubi7', + 'registry.access.redhat.com/ubi8', + 'registry.access.redhat.com/ubi9', + 'redhat/', + ], + matchPackageNames: [ + 'registry.access.redhat.com/rhel', + 'registry.access.redhat.com/rhel-atomic', + 'registry.access.redhat.com/rhel-init', + 'registry.access.redhat.com/rhel-minimal', + ], + versioning: 'redhat', + }, + ], + }, }; diff --git a/lib/modules/versioning/api.ts b/lib/modules/versioning/api.ts index 5edcdcccc857111d38d3465fb6097466e35296f3..93ceef3a516553dcae9690319d1abd5e673d2bcf 100644 --- a/lib/modules/versioning/api.ts +++ b/lib/modules/versioning/api.ts @@ -17,6 +17,7 @@ import * as npm from './npm'; import * as nuget from './nuget'; import * as pep440 from './pep440'; import * as poetry from './poetry'; +import redhat from './redhat'; import * as regex from './regex'; import * as rez from './rez'; import * as ruby from './ruby'; @@ -48,6 +49,7 @@ api.set('npm', npm.api); api.set('nuget', nuget.api); api.set('pep440', pep440.api); api.set('poetry', poetry.api); +api.set('redhat', redhat); api.set('regex', regex.api); api.set('rez', rez.api); api.set('ruby', ruby.api); diff --git a/lib/modules/versioning/redhat/index.spec.ts b/lib/modules/versioning/redhat/index.spec.ts new file mode 100644 index 0000000000000000000000000000000000000000..83f60f9b36058da9b79e68ff9b6257f8744d74bb --- /dev/null +++ b/lib/modules/versioning/redhat/index.spec.ts @@ -0,0 +1,57 @@ +import redhat from '.'; + +describe('modules/versioning/redhat/index', () => { + test.each` + input | expected + ${'1'} | ${true} + ${'17.04'} | ${true} + ${'9.0.0'} | ${true} + ${'1-632'} | ${true} + ${'1.2-62'} | ${true} + ${'1.2.3-62'} | ${true} + ${'8.5-239.1651231664'} | ${true} + ${'8.5.0-239.1651231664'} | ${true} + ${'9.0.0-62'} | ${true} + ${'1.2.3.4-62'} | ${false} + ${'1.2.3 -62'} | ${false} + ${'8.5-'} | ${false} + ${'3.0.0-beta'} | ${false} + ${'2.0.2-pre2019100318'} | ${false} + ${'1.0.0+c30d7625'} | ${false} + ${'2.3.4-beta+1990ef74'} | ${false} + ${'5.1.2-+'} | ${false} + ${'5.1.2+1'} | ${false} + `('isValid("$input") === $expected', ({ input, expected }) => { + expect(redhat.isValid(input)).toBe(expected); + }); + + test.each` + a | b | expected + ${'3-57'} | ${'3-2'} | ${true} + ${'8.6'} | ${'8.4'} | ${true} + ${'3.2.32-12'} | ${'2.3.7-15'} | ${true} + ${'7.9-49'} | ${'7.9-46'} | ${true} + ${'1-121'} | ${'1-81.1618436879'} | ${true} + ${'7.7-18.1575996389'} | ${'7.7-18'} | ${true} + ${'7.9-698.1655292976'} | ${'7.9-628'} | ${true} + ${'7.9-698.1655292976'} | ${'7.9-628.1645808164'} | ${true} + ${'7.9-698.1655292976'} | ${'7.9-698.1645808164'} | ${true} + ${'8.6-754.1655117782'} | ${'8.5-239.1651231664'} | ${true} + ${'8.6-754.1655117782'} | ${'8.5-754.1651231664'} | ${true} + ${'8.6-754.1652117782'} | ${'8.5-754.1651231664'} | ${true} + ${'8.45-754.1652117782'} | ${'8.5-754.1651231664'} | ${true} + ${'8.6-754.1655117782'} | ${'8.6-754'} | ${true} + ${'9.0.0-1471'} | ${'9.0.0'} | ${true} + ${'9.0.0-1471.1655190711'} | ${'9.0.0-1471'} | ${true} + ${undefined} | ${'1.2.0'} | ${true} + ${'1.2.0'} | ${'1.2.0-2'} | ${false} + ${'1.9'} | ${'2'} | ${false} + ${'1.9'} | ${'1.9.1'} | ${false} + ${'2.4.0-50'} | ${'2.4.0-51'} | ${false} + ${'2.4.0-51'} | ${'2.4.0-51'} | ${false} + ${'1-19'} | ${'1-19.1655193074'} | ${false} + ${'8.5-754.1651117782'} | ${'8.5-754.1652231664'} | ${false} + `('isGreaterThan($a, $b) === $expected', ({ a, b, expected }) => { + expect(redhat.isGreaterThan(a, b)).toBe(expected); + }); +}); diff --git a/lib/modules/versioning/redhat/index.ts b/lib/modules/versioning/redhat/index.ts new file mode 100644 index 0000000000000000000000000000000000000000..21e468c907c5c69a9bbea760f1990510a7a4d1ab --- /dev/null +++ b/lib/modules/versioning/redhat/index.ts @@ -0,0 +1,40 @@ +import { regEx } from '../../../util/regex'; +import { GenericVersion, GenericVersioningApi } from '../generic'; +import type { VersioningApi } from '../types'; + +export const id = 'redhat'; +export const displayName = 'Red Hat'; +export const urls = []; +export const supportsRanges = false; + +const pattern = regEx( + /^(?<major>\d+)(?:\.(?<minor>\d+))?(?:\.(?<patch>\d+))?(?:-(?<releaseMajor>\d+)(?:\.(?<releaseMinor>\d+))?)?$/ +); + +class RedhatVersioningApi extends GenericVersioningApi { + protected _parse(version: string): GenericVersion | null { + const matches = pattern.exec(version)?.groups; + if (!matches) { + return null; + } + + const { major, minor, patch, releaseMajor, releaseMinor } = matches; + const release = [ + typeof major === 'undefined' ? 0 : Number.parseInt(major, 10), + typeof minor === 'undefined' ? 0 : Number.parseInt(minor, 10), + typeof patch === 'undefined' ? 0 : Number.parseInt(patch, 10), + typeof releaseMajor === 'undefined' + ? 0 + : Number.parseInt(releaseMajor, 10), + typeof releaseMinor === 'undefined' + ? 0 + : Number.parseInt(releaseMinor, 10), + ]; + + return { release, prerelease: '' }; + } +} + +export const api: VersioningApi = new RedhatVersioningApi(); + +export default api; diff --git a/lib/modules/versioning/redhat/readme.md b/lib/modules/versioning/redhat/readme.md new file mode 100644 index 0000000000000000000000000000000000000000..feb19d36bc2e4c331e7b9d576895b2a35278f334 --- /dev/null +++ b/lib/modules/versioning/redhat/readme.md @@ -0,0 +1,16 @@ +Red Hat versioning is used with container images that are maintained by Red Hat. + +Red Hat version definitions follow this pattern: + +- the version of the main component, where major is required, but minor and patch are optional +- optionally a hyphen followed by release information +- the version of Red Hat's release as an integer, optionally followed by a timestamp like: `1645808164` + +Examples of valid Red Hat versions: + +- `1` +- `8.5` +- `7.9-628` +- `9.0.0-19.1655192132` + +Ranges are not supported by this versioning.