From 62bc64970af9ef2ca8cc18da39c262c444d4cb8e Mon Sep 17 00:00:00 2001 From: Rhys Arkins <rhys@arkins.net> Date: Thu, 17 Sep 2020 10:06:06 +0200 Subject: [PATCH] feat: extractVersion (#7307) Adds a new option extractVersion which allows for extracting a substring of raw versions from datasources, to be used as the actual version. Closes #7297, Closes #6793 --- docs/usage/configuration-options.md | 45 +++++++++++++++++++++++++++++ lib/config/definitions.ts | 9 ++++++ lib/datasource/common.ts | 1 + lib/datasource/index.spec.ts | 17 +++++++++++ lib/datasource/index.ts | 21 ++++++++++++++ 5 files changed, 93 insertions(+) diff --git a/docs/usage/configuration-options.md b/docs/usage/configuration-options.md index 26760b9f8f..fb7cf289bb 100644 --- a/docs/usage/configuration-options.md +++ b/docs/usage/configuration-options.md @@ -387,6 +387,51 @@ The above would mean Renovate would not include files matching the above glob pa See [shareable config presets](https://docs.renovatebot.com/config-presets) for details. +## extractVersion + +Use this only when the raw version strings from the datasource do not match the expected format that you need in your package file. You must defined a "named capture group" called `version` as shown in the below examples. + +For example, to extract only the major.minor precision from a GitHub release, the following would work: + +```json +{ + "packageRules": [ + { + "packageNames": ["foo"], + "extractVersion": "^(?<version>v\\d+\\.\\d+)" + } + ] +} +``` + +The above will change a raw version of `v1.31.5` to `v1.31`, for example. + +Alternatively, to strip a `release-` prefix: + +```json +{ + "packageRules": [ + { + "packageNames": ["bar"], + "extractVersion": "^release-(?<version>.*)$" + } + ] +} +``` + +The above will change a raw version of `release-2.0.0` to `2.0.0`, for example. A similar one could strip leading `v` prefixes: + +```json +{ + "packageRules": [ + { + "packageNames": ["baz"], + "extractVersion": "^v(?<version>.*)$" + } + ] +} +``` + ## fileMatch `fileMatch` is used by Renovate to know which files in a repository to parse and extract, and it is possible to override defaults values to customize for your project's needs. diff --git a/lib/config/definitions.ts b/lib/config/definitions.ts index ed3cfe4617..257d5657fb 100644 --- a/lib/config/definitions.ts +++ b/lib/config/definitions.ts @@ -704,6 +704,15 @@ const options: RenovateOptions[] = [ cli: false, env: false, }, + { + name: 'extractVersion', + description: + "A regex (re2) to extract a version from a datasource's raw version string", + type: 'string', + format: 'regex', + cli: false, + env: false, + }, { name: 'versioning', description: 'versioning to use for filtering and comparisons', diff --git a/lib/datasource/common.ts b/lib/datasource/common.ts index c9355b9cbb..1ea807a037 100644 --- a/lib/datasource/common.ts +++ b/lib/datasource/common.ts @@ -25,6 +25,7 @@ export interface GetPkgReleasesConfig extends ReleasesConfigBase { depName: string; lookupName?: string; versioning?: string; + extractVersion?: string; } export function isGetPkgReleasesConfig( diff --git a/lib/datasource/index.spec.ts b/lib/datasource/index.spec.ts index 70e3b17251..ee1ec40b11 100644 --- a/lib/datasource/index.spec.ts +++ b/lib/datasource/index.spec.ts @@ -102,6 +102,23 @@ describe('datasource/index', () => { expect(res.changelogUrl).toBeDefined(); expect(res.sourceUrl).toBeDefined(); }); + it('applies extractVersion', async () => { + npmDatasource.getReleases.mockResolvedValue({ + releases: [ + { version: 'v1.0.0' }, + { version: 'v1.0.1' }, + { version: 'v2' }, + ], + }); + const res = await datasource.getPkgReleases({ + datasource: datasourceNpm.id, + depName: 'react-native', + extractVersion: '^(?<version>v\\d+\\.\\d+)', + versioning: 'loose', + }); + expect(res.releases).toHaveLength(1); + expect(res.releases[0].version).toEqual('v1.0'); + }); it('adds sourceUrl', async () => { npmDatasource.getReleases.mockResolvedValue({ releases: [{ version: '1.0.0' }], diff --git a/lib/datasource/index.ts b/lib/datasource/index.ts index 24fbc2d4d7..1ef1c2c7b9 100644 --- a/lib/datasource/index.ts +++ b/lib/datasource/index.ts @@ -5,6 +5,7 @@ import { logger } from '../logger'; import { ExternalHostError } from '../types/errors/external-host-error'; import * as memCache from '../util/cache/memory'; import { clone } from '../util/clone'; +import { regEx } from '../util/regex'; import * as allVersioning from '../versioning'; import datasources from './api.generated'; import { @@ -259,6 +260,19 @@ export async function getPkgReleases( if (!res) { return res; } + if (config.extractVersion) { + const extractVersionRegEx = regEx(config.extractVersion); + res.releases = res.releases + .map((release) => { + const version = extractVersionRegEx.exec(release.version)?.groups + ?.version; + if (version) { + return { ...release, version }; // overwrite version + } + return null; // filter out any we can't extract + }) + .filter(Boolean); + } // Filter by versioning const version = allVersioning.get(config.versioning); // Return a sorted list of valid Versions @@ -270,6 +284,13 @@ export async function getPkgReleases( .filter((release) => version.isVersion(release.version)) .sort(sortReleases); } + // Filter versions for uniqueness + res.releases = res.releases.filter( + (filterRelease, filterIndex) => + res.releases.findIndex( + (findRelease) => findRelease.version === filterRelease.version + ) === filterIndex + ); return res; } -- GitLab