From a54cc479500642a23bf877865d6b973b49dd2ffc Mon Sep 17 00:00:00 2001 From: Gabriel-Ladzaretti <97394622+Gabriel-Ladzaretti@users.noreply.github.com> Date: Mon, 22 Aug 2022 23:16:00 +0300 Subject: [PATCH] feat(repo/changelogs): allow user configuration of source url (#16873) --- docs/usage/configuration-options.md | 24 ++++++++ lib/config/options/index.ts | 10 ++++ lib/config/types.ts | 1 + .../update/pr/changelog/common.spec.ts | 14 +++++ .../repository/update/pr/changelog/common.ts | 7 +++ .../update/pr/changelog/github.spec.ts | 59 +++++++++++++++++++ .../update/pr/changelog/gitlab.spec.ts | 33 +++++++++++ .../repository/update/pr/changelog/index.ts | 6 +- .../update/pr/changelog/source-github.ts | 4 +- .../update/pr/changelog/source-gitlab.ts | 4 +- 10 files changed, 157 insertions(+), 5 deletions(-) create mode 100644 lib/workers/repository/update/pr/changelog/common.spec.ts create mode 100644 lib/workers/repository/update/pr/changelog/common.ts diff --git a/docs/usage/configuration-options.md b/docs/usage/configuration-options.md index 1fdb5949fd..78a95f31b0 100644 --- a/docs/usage/configuration-options.md +++ b/docs/usage/configuration-options.md @@ -1876,6 +1876,30 @@ For example to apply a special label for Major updates: } ``` +### customChangelogUrl + +Use this field to set the source URL for a package, including overriding an existing one. +Source URLs are necessary in order to look up release notes. + +Using this field we can specify the exact url to fetch release notes from. + +Example setting source URL for package "dummy": + +```json +{ + "packageRules": [ + { + "matchPackageNames": ["dummy"], + "customChangelogUrl": "https://github.com/org/dummy" + } + ] +} +``` + +<!-- prettier-ignore --> +!!! note +Renovate can fetch changelogs from GitHub and GitLab platforms only, and setting the URL to an unsupported host/platform type won't change that. + ### replacementName This config option only works with the `npm` manager. diff --git a/lib/config/options/index.ts b/lib/config/options/index.ts index a8736faccc..a744bc9dde 100644 --- a/lib/config/options/index.ts +++ b/lib/config/options/index.ts @@ -1185,6 +1185,16 @@ const options: RenovateOptions[] = [ cli: false, env: false, }, + { + name: 'customChangelogUrl', + description: + 'If set, Renovate will use this url to fetch changelogs for a matched dependency. Valid only within a `packageRules` object.', + type: 'string', + stage: 'pr', + parent: 'packageRules', + cli: false, + env: false, + }, { name: 'pinDigests', description: 'Whether to add digests to Dockerfile source images.', diff --git a/lib/config/types.ts b/lib/config/types.ts index 65ccc58323..a955ec2ee7 100644 --- a/lib/config/types.ts +++ b/lib/config/types.ts @@ -34,6 +34,7 @@ export interface RenovateSharedConfig { commitMessage?: string; commitMessagePrefix?: string; confidential?: boolean; + customChangelogUrl?: string; draftPR?: boolean; enabled?: boolean; enabledManagers?: string[]; diff --git a/lib/workers/repository/update/pr/changelog/common.spec.ts b/lib/workers/repository/update/pr/changelog/common.spec.ts new file mode 100644 index 0000000000..ca4613d24c --- /dev/null +++ b/lib/workers/repository/update/pr/changelog/common.spec.ts @@ -0,0 +1,14 @@ +import { slugifyUrl } from './common'; + +describe('workers/repository/update/pr/changelog/common', () => { + it.each` + url | expected + ${'https://github-enterprise.example.com/çhãlk/chálk'} | ${'https-github-enterprise-example-com-chalk-chalk'} + ${'https://github.com/chalk/chalk'} | ${'https-github-com-chalk-chalk'} + ${'https://github-enterprise.example.com/'} | ${'https-github-enterprise-example-com'} + ${'https://github.com/sindresorhus/delay'} | ${'https-github-com-sindresorhus-delay'} + ${'https://github.com/🔥/∂u/∂t/equals/α∇^2u'} | ${'https-github-com-du-dt-equals-a2u'} + `('isSingleVersion("$url") === $expected', ({ url, expected }) => { + expect(slugifyUrl(url)).toBe(expected); + }); +}); diff --git a/lib/workers/repository/update/pr/changelog/common.ts b/lib/workers/repository/update/pr/changelog/common.ts new file mode 100644 index 0000000000..cd2f8f4d3f --- /dev/null +++ b/lib/workers/repository/update/pr/changelog/common.ts @@ -0,0 +1,7 @@ +import slugify from 'slugify'; +import { regEx } from '../../../../../util/regex'; + +export function slugifyUrl(url: string): string { + const r = regEx(/(:?[:/.])+/g); + return slugify(url.replace(r, ' ')); +} diff --git a/lib/workers/repository/update/pr/changelog/github.spec.ts b/lib/workers/repository/update/pr/changelog/github.spec.ts index cb5ab72dc5..7d0c6d6f2c 100644 --- a/lib/workers/repository/update/pr/changelog/github.spec.ts +++ b/lib/workers/repository/update/pr/changelog/github.spec.ts @@ -265,6 +265,34 @@ describe('workers/repository/update/pr/changelog/github', () => { }); }); + it('supports overwriting sourceUrl for supports github enterprise and github.com changelog', async () => { + const sourceUrl = upgrade.sourceUrl; + const replacementSourceUrl = 'https://github.com/sindresorhus/got'; + const config = { + ...upgrade, + endpoint: 'https://github-enterprise.example.com/', + customChangelogUrl: replacementSourceUrl, + }; + hostRules.add({ + hostType: PlatformId.Github, + token: 'super_secret', + matchHost: 'https://github-enterprise.example.com/', + }); + expect(await getChangeLogJSON(config)).toMatchObject({ + hasReleaseNotes: true, + project: { + apiBaseUrl: 'https://api.github.com/', + baseUrl: 'https://github.com/', + depName: 'renovate', + repository: 'sindresorhus/got', + sourceDirectory: undefined, + sourceUrl: 'https://github.com/sindresorhus/got', + type: 'github', + }, + }); + expect(upgrade.sourceUrl).toBe(sourceUrl); // ensure unmodified function argument + }); + it('supports github enterprise and github enterprise changelog', async () => { hostRules.add({ hostType: PlatformId.Github, @@ -298,6 +326,37 @@ describe('workers/repository/update/pr/changelog/github', () => { }); }); + it('supports overwriting sourceUrl for github enterprise and github enterprise changelog', async () => { + const sourceUrl = 'https://github-enterprise.example.com/chalk/chalk'; + const replacementSourceUrl = + 'https://github-enterprise.example.com/sindresorhus/got'; + const config = { + ...upgrade, + sourceUrl, + endpoint: 'https://github-enterprise.example.com/', + customChangelogUrl: replacementSourceUrl, + }; + hostRules.add({ + hostType: PlatformId.Github, + matchHost: 'https://github-enterprise.example.com/', + token: 'abc', + }); + process.env.GITHUB_ENDPOINT = ''; + expect(await getChangeLogJSON(config)).toMatchObject({ + hasReleaseNotes: true, + project: { + apiBaseUrl: 'https://github-enterprise.example.com/api/v3/', + baseUrl: 'https://github-enterprise.example.com/', + depName: 'renovate', + repository: 'sindresorhus/got', + sourceDirectory: undefined, + sourceUrl: 'https://github-enterprise.example.com/sindresorhus/got', + type: 'github', + }, + }); + expect(config.sourceUrl).toBe(sourceUrl); // ensure unmodified function argument + }); + it('works with same version releases but different prefix', async () => { const githubTagsMock = jest.spyOn( CacheableGithubTags.prototype, diff --git a/lib/workers/repository/update/pr/changelog/gitlab.spec.ts b/lib/workers/repository/update/pr/changelog/gitlab.spec.ts index 0e27e9f651..c9196a53e6 100644 --- a/lib/workers/repository/update/pr/changelog/gitlab.spec.ts +++ b/lib/workers/repository/update/pr/changelog/gitlab.spec.ts @@ -315,5 +315,38 @@ describe('workers/repository/update/pr/changelog/gitlab', () => { ], }); }); + + it('supports overwriting sourceUrl for self-hosted gitlab changelog', async () => { + httpMock.scope('https://git.test.com').persist().get(/.*/).reply(200, []); + const sourceUrl = 'https://git.test.com/meno/dropzone/'; + const replacementSourceUrl = + 'https://git.test.com/replacement/sourceurl/'; + const config = { + ...upgrade, + platform: PlatformId.Gitlab, + endpoint: 'https://git.test.com/api/v4/', + sourceUrl, + customChangelogUrl: replacementSourceUrl, + }; + hostRules.add({ + hostType: PlatformId.Gitlab, + matchHost: 'https://git.test.com/', + token: 'abc', + }); + process.env.GITHUB_ENDPOINT = ''; + expect(await getChangeLogJSON(config)).toMatchObject({ + hasReleaseNotes: false, + project: { + apiBaseUrl: 'https://git.test.com/api/v4/', + baseUrl: 'https://git.test.com/', + depName: 'renovate', + repository: 'replacement/sourceurl', + sourceDirectory: undefined, + sourceUrl: 'https://git.test.com/replacement/sourceurl/', + type: 'gitlab', + }, + }); + expect(config.sourceUrl).toBe(sourceUrl); // ensure unmodified function argument + }); }); }); diff --git a/lib/workers/repository/update/pr/changelog/index.ts b/lib/workers/repository/update/pr/changelog/index.ts index fcca0fc7f5..a0e07f0c22 100644 --- a/lib/workers/repository/update/pr/changelog/index.ts +++ b/lib/workers/repository/update/pr/changelog/index.ts @@ -9,9 +9,11 @@ import type { ChangeLogResult } from './types'; export * from './types'; export async function getChangeLogJSON( - config: BranchUpgradeConfig + _config: BranchUpgradeConfig ): Promise<ChangeLogResult | null> { - const { sourceUrl, versioning, currentVersion, newVersion } = config; + const sourceUrl = _config.customChangelogUrl ?? _config.sourceUrl!; + const config: BranchUpgradeConfig = { ..._config, sourceUrl }; + const { versioning, currentVersion, newVersion } = config; try { if (!(sourceUrl && currentVersion && newVersion)) { return null; diff --git a/lib/workers/repository/update/pr/changelog/source-github.ts b/lib/workers/repository/update/pr/changelog/source-github.ts index 7631f6cd2e..d8dabe224e 100644 --- a/lib/workers/repository/update/pr/changelog/source-github.ts +++ b/lib/workers/repository/update/pr/changelog/source-github.ts @@ -10,6 +10,7 @@ import * as packageCache from '../../../../../util/cache/package'; import * as hostRules from '../../../../../util/host-rules'; import { regEx } from '../../../../../util/regex'; import type { BranchUpgradeConfig } from '../../../../types'; +import { slugifyUrl } from './common'; import { getTags } from './github'; import { addReleaseNotes } from './release-notes'; import { getInRangeReleases } from './releases'; @@ -120,8 +121,9 @@ export async function getChangeLogJSON( } const cacheNamespace = 'changelog-github-release'; + function getCacheKey(prev: string, next: string): string { - return `${manager}:${depName}:${prev}:${next}`; + return `${slugifyUrl(sourceUrl)}:${depName}:${prev}:${next}`; } const changelogReleases: ChangeLogRelease[] = []; diff --git a/lib/workers/repository/update/pr/changelog/source-gitlab.ts b/lib/workers/repository/update/pr/changelog/source-gitlab.ts index 2cd1b38c27..e55b681849 100644 --- a/lib/workers/repository/update/pr/changelog/source-gitlab.ts +++ b/lib/workers/repository/update/pr/changelog/source-gitlab.ts @@ -7,6 +7,7 @@ import * as memCache from '../../../../../util/cache/memory'; import * as packageCache from '../../../../../util/cache/package'; import { regEx } from '../../../../../util/regex'; import type { BranchUpgradeConfig } from '../../../../types'; +import { slugifyUrl } from './common'; import { getTags } from './gitlab'; import { addReleaseNotes } from './release-notes'; import { getInRangeReleases } from './releases'; @@ -38,7 +39,6 @@ export async function getChangeLogJSON( const newVersion = config.newVersion!; const sourceUrl = config.sourceUrl!; const depName = config.depName!; - const manager = config.manager; const sourceDirectory = config.sourceDirectory!; logger.trace('getChangeLogJSON for gitlab'); @@ -95,7 +95,7 @@ export async function getChangeLogJSON( } function getCacheKey(prev: string, next: string): string { - return `${manager}:${depName}:${prev}:${next}`; + return `${slugifyUrl(sourceUrl)}:${depName}:${prev}:${next}`; } const changelogReleases: ChangeLogRelease[] = []; -- GitLab