diff --git a/docs/usage/configuration-options.md b/docs/usage/configuration-options.md index daf4c3c28270a0..8dfac52d901fc2 100644 --- a/docs/usage/configuration-options.md +++ b/docs/usage/configuration-options.md @@ -2163,6 +2163,44 @@ It will be compiled using Handlebars and the regex `groups` result. If the `registryUrls` for a dependency is not captured with a named group then it can be defined in config using this field. It will be compiled using Handlebars and the regex `groups` result. +### autoReplaceStringTemplate + +Allows overwriting how the matched string is replaced. +This allows for some migration strategies. +E.g. moving from one Docker image repository to another one. + +helm-values.yaml: + +```yaml +# The image of the service //: +image: my.old.registry/aRepository/andImage:1.18-alpine +``` + +regex definition: + +```json +{ + "regexManagers": [ + { + "fileMatch": ["values.yaml$"], + "matchStrings": [ + "image:\\s+(?my\\.old\\.registry\\/aRepository\\/andImage):(?[^\\s]+)" + ], + "depNameTemplate": "my.new.registry/aRepository/andImage", + "autoReplaceStringTemplate": "image: {{{depName}}}:{{{newValue}}}", + "datasourceTemplate": "docker" + } + ] +} +``` + +This will lead to following update where `1.21-alpine` is the newest version of `my.new.registry/aRepository/andImage`: + +```yaml +# The image of the service //: +image: my.new.registry/aRepository/andImage:1.21-alpine +``` + ## registryUrls Usually Renovate is able to either (a) use the default registries for a datasource, or (b) automatically detect during the manager extract phase which custom registries are in use. diff --git a/lib/config/options/index.ts b/lib/config/options/index.ts index 382a560472d5f4..dc557c23e756fc 100644 --- a/lib/config/options/index.ts +++ b/lib/config/options/index.ts @@ -2016,6 +2016,15 @@ const options: RenovateOptions[] = [ cli: false, env: false, }, + { + name: 'autoReplaceStringTemplate', + description: + 'Optional extractVersion for extracted dependencies. Valid only within a `regexManagers` object.', + type: 'string', + parent: 'regexManagers', + cli: false, + env: false, + }, { name: 'fetchReleaseNotes', description: 'Allow to disable release notes fetching.', diff --git a/lib/config/types.ts b/lib/config/types.ts index a773d15247b841..c13b6fc752710b 100644 --- a/lib/config/types.ts +++ b/lib/config/types.ts @@ -150,6 +150,7 @@ export interface CustomManager { datasourceTemplate?: string; lookupNameTemplate?: string; versioningTemplate?: string; + autoReplaceStringTemplate?: string; } // TODO: Proper typings diff --git a/lib/config/validation.ts b/lib/config/validation.ts index 0684c3445691fd..905b22a1658192 100644 --- a/lib/config/validation.ts +++ b/lib/config/validation.ts @@ -388,6 +388,7 @@ export async function validateConfig( 'registryUrlTemplate', 'currentValueTemplate', 'extractVersionTemplate', + 'autoReplaceStringTemplate', ]; // TODO: fix types for (const regexManager of val as any[]) { diff --git a/lib/manager/regex/__snapshots__/index.spec.ts.snap b/lib/manager/regex/__snapshots__/index.spec.ts.snap index 94aa2090dce108..6071a39e352525 100644 --- a/lib/manager/regex/__snapshots__/index.spec.ts.snap +++ b/lib/manager/regex/__snapshots__/index.spec.ts.snap @@ -41,6 +41,25 @@ Object { } `; +exports[`manager/regex/index extracts dependency with autoReplaceStringTemplate 1`] = ` +Object { + "autoReplaceStringTemplate": "image: {{{depName}}}:{{{newValue}}}", + "datasourceTemplate": "docker", + "depNameTemplate": "my.new.registry/aRepository/andImage", + "deps": Array [ + Object { + "currentValue": "1.18-alpine", + "datasource": "docker", + "depName": "my.new.registry/aRepository/andImage", + "replaceString": "image: my.old.registry/aRepository/andImage:1.18-alpine", + }, + ], + "matchStrings": Array [ + "image:\\\\s+(?my\\\\.old\\\\.registry\\\\/aRepository\\\\/andImage):(?[^\\\\s]+)", + ], +} +`; + exports[`manager/regex/index extracts extractVersion 1`] = ` Object { "deps": Array [ diff --git a/lib/manager/regex/index.spec.ts b/lib/manager/regex/index.spec.ts index 035c2854cc1886..7f3d9bdfc68026 100644 --- a/lib/manager/regex/index.spec.ts +++ b/lib/manager/regex/index.spec.ts @@ -168,6 +168,25 @@ describe('manager/regex/index', () => { 'maven' ); }); + + it('extracts dependency with autoReplaceStringTemplate', async () => { + const config = { + matchStrings: [ + 'image:\\s+(?my\\.old\\.registry\\/aRepository\\/andImage):(?[^\\s]+)', + ], + depNameTemplate: 'my.new.registry/aRepository/andImage', + autoReplaceStringTemplate: 'image: {{{depName}}}:{{{newValue}}}', + datasourceTemplate: 'docker', + }; + const res = await extractPackageFile( + 'image: my.old.registry/aRepository/andImage:1.18-alpine', + 'values.yaml', + config + ); + expect(res).toMatchSnapshot(); + expect(res.deps).toHaveLength(1); + }); + it('extracts with combination strategy', async () => { const config: CustomExtractConfig = { matchStrings: [ diff --git a/lib/manager/regex/index.ts b/lib/manager/regex/index.ts index 9c38450312e9a6..70f9c181ef11f5 100644 --- a/lib/manager/regex/index.ts +++ b/lib/manager/regex/index.ts @@ -221,6 +221,9 @@ export function extractPackageFile( res[field] = config[field]; } } + if (config.autoReplaceStringTemplate) { + res.autoReplaceStringTemplate = config.autoReplaceStringTemplate; + } return res; } diff --git a/lib/manager/types.ts b/lib/manager/types.ts index bb512be8b2546a..c84b69c132a69f 100644 --- a/lib/manager/types.ts +++ b/lib/manager/types.ts @@ -27,6 +27,7 @@ export interface ExtractConfig { } export interface CustomExtractConfig extends ExtractConfig { + autoReplaceStringTemplate?: string; matchStrings: string[]; matchStringsStrategy?: MatchStringsStrategy; depNameTemplate?: string; @@ -69,6 +70,7 @@ export interface NpmLockFiles { export interface PackageFile> extends NpmLockFiles, ManagerData { + autoReplaceStringTemplate?: string; hasYarnWorkspaces?: boolean; constraints?: Record; datasource?: string;