diff --git a/docs/usage/configuration-options.md b/docs/usage/configuration-options.md index 4bcf63816598ba..650433f09028e9 100644 --- a/docs/usage/configuration-options.md +++ b/docs/usage/configuration-options.md @@ -689,7 +689,7 @@ The `regex` manager which is based on using Regular Expression named capture gro You must have a named capture group matching (e.g. `(?.*)`) _or_ configure its corresponding template (e.g. `depNameTemplate`) for these fields: - `datasource` -- `depName` +- `depName` and / or `packageName` - `currentValue` Use named capture group matching _or_ set a corresponding template. diff --git a/lib/config/validation.spec.ts b/lib/config/validation.spec.ts index fb517bd0bb65bc..bdd5c1d2a6c16a 100644 --- a/lib/config/validation.spec.ts +++ b/lib/config/validation.spec.ts @@ -746,6 +746,16 @@ describe('config/validation', () => { extractVersionTemplate: '^(?v\\d+\\.\\d+)', depTypeTemplate: 'apple', }, + { + customType: 'regex', + fileMatch: ['Dockerfile'], + matchStrings: ['ENV (?.*?)\\s'], + packageNameTemplate: 'foo', + datasourceTemplate: 'bar', + registryUrlTemplate: 'foobar', + extractVersionTemplate: '^(?v\\d+\\.\\d+)', + depTypeTemplate: 'apple', + }, ], }; const { warnings, errors } = await configValidation.validateConfig( diff --git a/lib/config/validation.ts b/lib/config/validation.ts index d76b33b9e13426..80f007f20a224a 100644 --- a/lib/config/validation.ts +++ b/lib/config/validation.ts @@ -867,7 +867,7 @@ function validateRegexManagerFields( }); } - const mandatoryFields = ['depName', 'currentValue', 'datasource']; + const mandatoryFields = ['currentValue', 'datasource']; for (const field of mandatoryFields) { if (!hasField(customManager, field)) { errors.push({ @@ -876,6 +876,14 @@ function validateRegexManagerFields( }); } } + + const nameFields = ['depName', 'packageName']; + if (!nameFields.some((field) => hasField(customManager, field))) { + errors.push({ + topic: 'Configuration Error', + message: `Regex Managers must contain depName or packageName regex groups or templates`, + }); + } } /** diff --git a/lib/modules/manager/custom/regex/__snapshots__/index.spec.ts.snap b/lib/modules/manager/custom/regex/__snapshots__/index.spec.ts.snap index 5132942cd4da4f..25dd3663151b9f 100644 --- a/lib/modules/manager/custom/regex/__snapshots__/index.spec.ts.snap +++ b/lib/modules/manager/custom/regex/__snapshots__/index.spec.ts.snap @@ -198,7 +198,7 @@ exports[`modules/manager/custom/regex/index extracts registryUrl 1`] = ` { "currentValue": "8.12.13", "datasource": "helm", - "depName": "prometheus-operator", + "packageName": "prometheus-operator", "registryUrls": [ "https://charts.helm.sh/stable", ], @@ -212,7 +212,7 @@ exports[`modules/manager/custom/regex/index extracts registryUrl 1`] = ` "matchStrings": [ "chart: *repository: (?.*?) - *name: (?.*?) + *name: (?.*?) *version: (?.*) ", ], diff --git a/lib/modules/manager/custom/regex/index.spec.ts b/lib/modules/manager/custom/regex/index.spec.ts index f0a47dba3d3e79..671883e1c6d820 100644 --- a/lib/modules/manager/custom/regex/index.spec.ts +++ b/lib/modules/manager/custom/regex/index.spec.ts @@ -48,7 +48,7 @@ describe('modules/manager/custom/regex/index', () => { it('returns null if no dependencies found', async () => { const config = { matchStrings: [ - 'ENV .*?_VERSION=(?.*) # (?.*?)/(?[^&]*?)(\\&versioning=(?[^&]*?))?\\s', + 'ENV .*?_VERSION=(?.*) # (?.*?)/(?[^&]*?)(\\&versioning=(?[^&]*?))?\\s', ], versioningTemplate: '{{#if versioning}}{{versioning}}{{else}}semver{{/if}}', @@ -95,7 +95,7 @@ describe('modules/manager/custom/regex/index', () => { it('extracts registryUrl', async () => { const config = { matchStrings: [ - 'chart:\n *repository: (?.*?)\n *name: (?.*?)\n *version: (?.*)\n', + 'chart:\n *repository: (?.*?)\n *name: (?.*?)\n *version: (?.*)\n', ], datasourceTemplate: 'helm', }; @@ -121,7 +121,7 @@ describe('modules/manager/custom/regex/index', () => { { currentValue: '8.12.13', datasource: 'helm', - depName: 'prometheus-operator', + packageName: 'prometheus-operator', registryUrls: ['https://charts.helm.sh/stable'], }, ], diff --git a/lib/modules/manager/custom/regex/readme.md b/lib/modules/manager/custom/regex/readme.md index bc9c96dc64fc68..add7b7d1142aff 100644 --- a/lib/modules/manager/custom/regex/readme.md +++ b/lib/modules/manager/custom/regex/readme.md @@ -29,8 +29,7 @@ Before Renovate can look up a dependency and decide about updates, it needs this Configuration-wise, it works like this: - You must capture the `currentValue` of the dependency in a named capture group -- You must have either a `depName` capture group or a `depNameTemplate` config field -- You can optionally have a `packageName` capture group or a `packageNameTemplate` if it differs from `depName` +- You must have either a `depName` or `packageName` capture group, or use on of the respective template fields ( `depNameTemplate` and `packageNameTemplate` ) - You must have either a `datasource` capture group or a `datasourceTemplate` config field - You can optionally have a `depType` capture group or a `depTypeTemplate` config field - You can optionally have a `versioning` capture group or a `versioningTemplate` config field. If neither are present, Renovate will use `semver-coerced` as the default @@ -88,15 +87,13 @@ But you don't want to write a regex custom manager rule for _each_ variable. Instead you enhance your `Dockerfile` like this: ```Dockerfile -ARG IMAGE=node:12@sha256:6e5264cd4cfaefd7174b2bc10c7f9a1c2b99d98d127fc57a802d264da9fb43bd -FROM ${IMAGE} -# renovate: datasource=github-tags depName=nodejs/node versioning=node -ENV NODE_VERSION=10.19.0 -# renovate: datasource=github-releases depName=composer/composer +# renovate: datasource=github-tags depName=node packageName=nodejs/node versioning=node +ENV NODE_VERSION=20.10.0 +# renovate: datasource=github-releases depName=composer packageName=composer/composer ENV COMPOSER_VERSION=1.9.3 -# renovate: datasource=docker depName=docker versioning=docker +# renovate: datasource=docker packageName=docker versioning=docker ENV DOCKER_VERSION=19.03.1 -# renovate: datasource=npm depName=yarn +# renovate: datasource=npm packageName=yarn ENV YARN_VERSION=1.19.1 ``` @@ -109,18 +106,11 @@ You could configure Renovate to update the `Dockerfile` like this: "customManagers": [ { "customType": "regex", - "fileMatch": ["^Dockerfile$"], + "description": "Update _VERSION variables in Dockerfiles", + "fileMatch": ["(^|/|\\.)Dockerfile$", "(^|/)Dockerfile\\.[^/]*$"], "matchStrings": [ - "datasource=(?.*?) depName=(?.*?)( versioning=(?.*?))?\\sENV .*?_VERSION=(?.*)\\s" - ], - "versioningTemplate": "{{#if versioning}}{{{versioning}}}{{else}}semver{{/if}}" - }, - { - "fileMatch": ["^Dockerfile$"], - "matchStrings": [ - "ARG IMAGE=(?.*?):(?.*?)@(?sha256:[a-f0-9]+)\\s" - ], - "datasourceTemplate": "docker" + "# renovate: datasource=(?[a-z-]+?)(?: depName=(?.+?))? packageName=(?.+?)(?: versioning=(?[a-z-]+?))?\\s(?:ENV|ARG) .+?_VERSION=(?.+?)\\s" + ] } ] } diff --git a/lib/modules/manager/custom/regex/utils.ts b/lib/modules/manager/custom/regex/utils.ts index 48a0dbfe82a7c3..b1ddc709b89d01 100644 --- a/lib/modules/manager/custom/regex/utils.ts +++ b/lib/modules/manager/custom/regex/utils.ts @@ -124,10 +124,12 @@ export function isValidDependency({ depName, currentValue, currentDigest, + packageName, }: PackageDependency): boolean { // check if all the fields are set return ( - is.nonEmptyStringAndNotWhitespace(depName) && + (is.nonEmptyStringAndNotWhitespace(depName) || + is.nonEmptyStringAndNotWhitespace(packageName)) && (is.nonEmptyStringAndNotWhitespace(currentDigest) || is.nonEmptyStringAndNotWhitespace(currentValue)) );