From 55563551dae4d8397dd1b0769655d6f894c766be Mon Sep 17 00:00:00 2001 From: Rhys Arkins Date: Sat, 4 May 2024 16:40:42 +0200 Subject: [PATCH 1/8] refactor: customManager mandatory fields check --- lib/config/validation.ts | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/lib/config/validation.ts b/lib/config/validation.ts index e12b7fb67bf816..bf274ba31f87d6 100644 --- a/lib/config/validation.ts +++ b/lib/config/validation.ts @@ -833,15 +833,22 @@ function validateRegexManagerFields( }); } - const mandatoryFields = ['depName', 'currentValue', 'datasource']; - for (const field of mandatoryFields) { + function hasField( + customManager: Partial, + field: string, + ): boolean { const templateField = `${field}Template` as keyof RegexManagerTemplates; - if ( - !customManager[templateField] && - !customManager.matchStrings?.some((matchString) => + return !!( + customManager[templateField] || + customManager.matchStrings?.some((matchString) => matchString.includes(`(?<${field}>`), ) - ) { + ); + } + + const mandatoryFields = ['depName', 'currentValue', 'datasource']; + for (const field of mandatoryFields) { + if (!hasField(customManager, field)) { errors.push({ topic: 'Configuration Error', message: `Regex Managers must contain ${field}Template configuration or regex group named ${field}`, From 3a1484d755cf78996fe24754fc5b701eaa2615b7 Mon Sep 17 00:00:00 2001 From: Rhys Arkins Date: Sat, 4 May 2024 16:44:28 +0200 Subject: [PATCH 2/8] module scope --- lib/config/validation.ts | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/lib/config/validation.ts b/lib/config/validation.ts index bf274ba31f87d6..46a1e78d371829 100644 --- a/lib/config/validation.ts +++ b/lib/config/validation.ts @@ -806,6 +806,19 @@ export async function validateConfig( return { errors, warnings }; } +function hasField( + customManager: Partial, + field: string, +): boolean { + const templateField = `${field}Template` as keyof RegexManagerTemplates; + return !!( + customManager[templateField] || + customManager.matchStrings?.some((matchString) => + matchString.includes(`(?<${field}>`), + ) + ); +} + function validateRegexManagerFields( customManager: Partial, currentPath: string, @@ -833,19 +846,6 @@ function validateRegexManagerFields( }); } - function hasField( - customManager: Partial, - field: string, - ): boolean { - const templateField = `${field}Template` as keyof RegexManagerTemplates; - return !!( - customManager[templateField] || - customManager.matchStrings?.some((matchString) => - matchString.includes(`(?<${field}>`), - ) - ); - } - const mandatoryFields = ['depName', 'currentValue', 'datasource']; for (const field of mandatoryFields) { if (!hasField(customManager, field)) { From 5f574533b59d78874ac9756332c17a6d410d1f74 Mon Sep 17 00:00:00 2001 From: Rhys Arkins Date: Sat, 4 May 2024 17:07:31 +0200 Subject: [PATCH 3/8] chore: fix gerrit eslint --- lib/modules/platform/gerrit/scm.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/modules/platform/gerrit/scm.ts b/lib/modules/platform/gerrit/scm.ts index 40fc56c88aab2e..e490a0448ccb7c 100644 --- a/lib/modules/platform/gerrit/scm.ts +++ b/lib/modules/platform/gerrit/scm.ts @@ -34,7 +34,7 @@ export class GerritScm extends DefaultGitScm { .findChanges(repository, searchConfig, true) .then((res) => res.pop()); if (change) { - return change.current_revision! as LongCommitSha; + return change.current_revision as LongCommitSha; } return git.getBranchCommit(branchName); } @@ -52,7 +52,7 @@ export class GerritScm extends DefaultGitScm { .findChanges(repository, searchConfig, true) .then((res) => res.pop()); if (change) { - const currentGerritPatchset = change.revisions![change.current_revision!]; + const currentGerritPatchset = change.revisions[change.current_revision]; return currentGerritPatchset.actions?.['rebase'].enabled === true; } return true; @@ -85,7 +85,7 @@ export class GerritScm extends DefaultGitScm { .findChanges(repository, searchConfig, true) .then((res) => res.pop()); if (change) { - const currentGerritPatchset = change.revisions![change.current_revision!]; + const currentGerritPatchset = change.revisions[change.current_revision]; return currentGerritPatchset.uploader.username !== username; } return false; @@ -154,7 +154,7 @@ export class GerritScm extends DefaultGitScm { .then((res) => res.pop()); if (change) { return super.mergeToLocal( - change.revisions![change.current_revision!].ref, + change.revisions[change.current_revision].ref, ); } return super.mergeToLocal(branchName); From 6da99c86540c17ef7838f31a50486cd411fe1ce3 Mon Sep 17 00:00:00 2001 From: Rhys Arkins Date: Sat, 4 May 2024 17:10:48 +0200 Subject: [PATCH 4/8] prettier fix --- lib/modules/platform/gerrit/scm.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/lib/modules/platform/gerrit/scm.ts b/lib/modules/platform/gerrit/scm.ts index e490a0448ccb7c..f4369fa39e2877 100644 --- a/lib/modules/platform/gerrit/scm.ts +++ b/lib/modules/platform/gerrit/scm.ts @@ -153,9 +153,7 @@ export class GerritScm extends DefaultGitScm { .findChanges(repository, searchConfig, true) .then((res) => res.pop()); if (change) { - return super.mergeToLocal( - change.revisions[change.current_revision].ref, - ); + return super.mergeToLocal(change.revisions[change.current_revision].ref); } return super.mergeToLocal(branchName); } From 3c4a9af125fe54e50eccb44b08d974721dbf4730 Mon Sep 17 00:00:00 2001 From: Rhys Arkins Date: Sat, 4 May 2024 17:21:18 +0200 Subject: [PATCH 5/8] feat(manager/custom): allow packageName-only for regex manager --- docs/usage/configuration-options.md | 2 +- lib/config/validation.spec.ts | 10 +++++++ lib/config/validation.ts | 10 ++++++- .../regex/__snapshots__/index.spec.ts.snap | 4 +-- .../manager/custom/regex/index.spec.ts | 6 ++-- lib/modules/manager/custom/regex/readme.md | 29 +++++++------------ lib/modules/manager/custom/regex/utils.ts | 4 ++- 7 files changed, 38 insertions(+), 27 deletions(-) diff --git a/docs/usage/configuration-options.md b/docs/usage/configuration-options.md index 4bcf63816598ba..c196cc086402e7 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` or `packageName` (either or both is OK) - `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 d1ca81e1a876d4..66b62f2853e9f3 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 c1be3de87510e3..a12651a241a83b 100644 --- a/lib/config/validation.ts +++ b/lib/config/validation.ts @@ -846,7 +846,7 @@ function validateRegexManagerFields( }); } - const mandatoryFields = ['depName', 'currentValue', 'datasource']; + const mandatoryFields = ['currentValue', 'datasource']; for (const field of mandatoryFields) { if (!hasField(customManager, field)) { errors.push({ @@ -855,6 +855,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..1cd41db7c44143 100644 --- a/lib/modules/manager/custom/regex/readme.md +++ b/lib/modules/manager/custom/regex/readme.md @@ -29,7 +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 must have either a `depName` capture group or a `depNameTemplate` config field, or `packageName` or `packageNameTemplate` - You can optionally have a `packageName` capture group or a `packageNameTemplate` if it differs from `depName` - 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 @@ -88,15 +88,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 +107,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)) ); From 8582d3ba56888653e136804775b9f46173b14786 Mon Sep 17 00:00:00 2001 From: Rhys Arkins Date: Sun, 5 May 2024 12:17:45 +0200 Subject: [PATCH 6/8] Update lib/modules/manager/custom/regex/readme.md --- lib/modules/manager/custom/regex/readme.md | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/modules/manager/custom/regex/readme.md b/lib/modules/manager/custom/regex/readme.md index 1cd41db7c44143..f4f00d2cd95884 100644 --- a/lib/modules/manager/custom/regex/readme.md +++ b/lib/modules/manager/custom/regex/readme.md @@ -30,7 +30,6 @@ 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, or `packageName` or `packageNameTemplate` -- You can optionally have a `packageName` capture group or a `packageNameTemplate` if it differs from `depName` - 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 From 933b971942be7a8aad39ae604b4e06d7cd7f7d9d Mon Sep 17 00:00:00 2001 From: Rhys Arkins Date: Sun, 5 May 2024 13:30:28 +0200 Subject: [PATCH 7/8] Apply suggestions from code review Co-authored-by: Sebastian Poxhofer --- docs/usage/configuration-options.md | 2 +- lib/modules/manager/custom/regex/readme.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/usage/configuration-options.md b/docs/usage/configuration-options.md index c196cc086402e7..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` or `packageName` (either or both is OK) +- `depName` and / or `packageName` - `currentValue` Use named capture group matching _or_ set a corresponding template. diff --git a/lib/modules/manager/custom/regex/readme.md b/lib/modules/manager/custom/regex/readme.md index f4f00d2cd95884..c355c903ef0158 100644 --- a/lib/modules/manager/custom/regex/readme.md +++ b/lib/modules/manager/custom/regex/readme.md @@ -29,7 +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, or `packageName` or `packageNameTemplate` +- 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 From 42e2a80eb6b7920f54cfac49560ab7a4e194e472 Mon Sep 17 00:00:00 2001 From: Rhys Arkins Date: Sun, 5 May 2024 13:45:29 +0200 Subject: [PATCH 8/8] prettier fix --- lib/modules/manager/custom/regex/readme.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/modules/manager/custom/regex/readme.md b/lib/modules/manager/custom/regex/readme.md index c355c903ef0158..add7b7d1142aff 100644 --- a/lib/modules/manager/custom/regex/readme.md +++ b/lib/modules/manager/custom/regex/readme.md @@ -29,7 +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` or `packageName` capture group, or use on of the respective template fields ( `depNameTemplate` and `packageNameTemplate` ) +- 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