Compare commits

...

9 commits

Author SHA1 Message Date
HonkingGoose
bb6b7ead41
Merge ae54b7069f into ef1cf5906c 2025-01-16 10:14:42 +01:00
Jonas Rutishauser
ef1cf5906c
feat(datasource/maven): Use relocation information (#32636)
Co-authored-by: Rhys Arkins <rhys@arkins.net>
2025-01-16 08:52:17 +00:00
Ivan Ka
2b2d306fb0
fix(versioning/ubuntu): support suffixed codename versions (#33308)
Signed-off-by: ivan katliarchuk <ivan.katliarchuk@gmail.com>
Co-authored-by: Rhys Arkins <rhys@arkins.net>
2025-01-16 08:43:46 +00:00
HonkingGoose
ae54b7069f
Update switching-bot-identity.md
Co-authored-by: Sebastian Poxhofer <secustor@users.noreply.github.com>
2024-08-26 12:30:10 +02:00
HonkingGoose
8708557f44
Merge branch 'main' into docs/30385-new-page-switching-bot-id 2024-08-26 10:04:38 +02:00
HonkingGoose
0edddf4a28
Put new page in the Configuration sidebar 2024-07-29 11:20:36 +02:00
HonkingGoose
2411a6f713
Update switching-bot-identity.md 2024-07-29 11:18:29 +02:00
HonkingGoose
d2b04461aa
Update switching-bot-identity.md 2024-07-29 11:15:41 +02:00
HonkingGoose
3f65694a00
docs: new page about switching bot identity 2024-07-29 10:32:09 +02:00
8 changed files with 304 additions and 122 deletions

View file

@ -9,6 +9,7 @@ nav:
- 'Self-hosted': 'self-hosted-configuration.md'
- 'Presets': 'config-presets.md'
- 'Validation': 'config-validation.md'
- 'Switching bot identity': 'switching-bot-identity.md'
- ... | mend-hosted
- ... | key-concepts
- ... | modules

View file

@ -0,0 +1,52 @@
# Switching bot identity
Renovate uses its bot identity to know:
- if a PR is authored by Renovate bot
- if you, or some other bot, pushed commits into the PR branch
- Editor note: list other things Renovate uses the bot id for here
## Reasons to switch bot identity
Common reasons to switch bot identity are:
- Migrating between Mend-hosted and self-hosted
- Renaming the bot (self-hosted)
- Editor note: Maybe there are other reasons too, please comment
### Migrating from Mend-hosted to self-hosted
Most users start with the Mend-hosted bot, and are happy with this.
After a while, some users want to switch to self-hosting, for more control.
When you migrate you must tell your new self-hosted Renovate bot to take over from the old Mend-hosted bot.
### Renaming the bot (self-hosted)
Maybe you started self-hosting Renovate, and called your bot `@old-bot-name`.
But the name no longer fits, so you want to use `@new-bot-name`.
Follow these steps:
1. Start of ordered list with steps
1. Second step
1. Third step, and so on
### Other situations
Editor note: Please comment about other cases where you need to switch bot identity.
## How to switch bot identity
Looks like the steps are:
1. Put old bot name in the `gitIgnoredAuthors` config option
1. Set `ignorePrAuthor` to `true`
1. Let the "new" bot take over from the "old bot"
## Questions from the editor
- Is the `gitAuthor` field the bot identity?
- What's `gitIgnoredAuthors` for? It looks like you can ignore commits from the old bot with it?
- We also have `ignorePrAuthor` which if set to `true` fetches the _whole_ list of PRs, instead of just fetching Renovate PRs. The docs say this is the one to use to ignore old bot names. But the description of `ignorePrAuthor` only mentions the full list fetching, nothing about the name/id of the bot.
- It's easy to confuse `gitIgnoredAuthors` and `ignorePrAuthor` they have similar names, but do different things.

View file

@ -1,5 +1,6 @@
import { HeadObjectCommand, S3Client } from '@aws-sdk/client-s3';
import { mockClient } from 'aws-sdk-client-mock';
import { codeBlock } from 'common-tags';
import { GoogleAuth as _googleAuth } from 'google-auth-library';
import { DateTime } from 'luxon';
import type { Release, ReleaseResult } from '..';
@ -315,6 +316,72 @@ describe('modules/datasource/maven/index', () => {
expect(res?.sourceUrl).toBe('https://github.com/example/test');
});
describe('supports relocation', () => {
it('with only groupId present', async () => {
const pom = codeBlock`
<project>
<distributionManagement>
<relocation>
<groupId>io.example</groupId>
</relocation>
</distributionManagement>
</project>
`;
mockGenericPackage({ pom });
const res = await get();
expect(res).toMatchObject({
replacementName: 'io.example:package',
replacementVersion: '2.0.0',
});
});
it('with only artifactId present', async () => {
const pom = codeBlock`
<project>
<distributionManagement>
<relocation>
<artifactId>foo</artifactId>
</relocation>
</distributionManagement>
</project>
`;
mockGenericPackage({ pom });
const res = await get();
expect(res).toMatchObject({
replacementName: 'org.example:foo',
replacementVersion: '2.0.0',
});
});
it('with all elments present', async () => {
const pom = codeBlock`
<project>
<distributionManagement>
<relocation>
<groupId>io.example</groupId>
<artifactId>foo</artifactId>
<version>1.2.3</version>
<message>test relocation</message>
</relocation>
</distributionManagement>
</project>
`;
mockGenericPackage({ pom });
const res = await get();
expect(res).toMatchObject({
replacementName: 'io.example:foo',
replacementVersion: '1.2.3',
deprecationMessage: 'test relocation',
});
});
});
it('removes authentication header after redirect', async () => {
const frontendHost = 'frontend_for_private_s3_repository';
const frontendUrl = `https://${frontendHost}/maven2`;

View file

@ -18,7 +18,12 @@ export type HttpResourceCheckResult = 'found' | 'not-found' | 'error' | Date;
export type DependencyInfo = Pick<
ReleaseResult,
'homepage' | 'sourceUrl' | 'packageScope'
| 'homepage'
| 'sourceUrl'
| 'packageScope'
| 'replacementName'
| 'replacementVersion'
| 'deprecationMessage'
>;
export interface MavenFetchSuccess<T = string> {

View file

@ -543,6 +543,23 @@ export async function getDependencyInfo(
}
}
const relocation = pomContent.descendantWithPath(
'distributionManagement.relocation',
);
if (relocation) {
const relocationGroup =
relocation.valueWithPath('groupId') ?? dependency.group;
const relocationName =
relocation.valueWithPath('artifactId') ?? dependency.name;
result.replacementName = `${relocationGroup}:${relocationName}`;
const relocationVersion = relocation.valueWithPath('version');
result.replacementVersion = relocationVersion ?? version;
const relocationMessage = relocation.valueWithPath('message');
if (relocationMessage) {
result.deprecationMessage = relocationMessage;
}
}
const groupId = pomContent.valueWithPath('groupId');
if (groupId) {
result.packageScope = groupId;

View file

@ -1,11 +1,13 @@
import { regEx } from '../../../util/regex';
const regex = regEx(/^(?<codename>\w+)-(?<date>\d{8})(?<suffix>\.\d{1,2})?$/);
function isDatedCodeName(input: string): boolean {
return regEx(/^(?<codename>\w+)-(?<date>\d{8})$/).test(input);
return regex.test(input);
}
function getDatedContainerImageCodename(version: string): null | string {
const groups = regEx(/^(?<codename>\w+)-(?<date>\d{8})$/).exec(version);
const groups = regex.exec(version);
if (!groups?.groups) {
return null;
}
@ -13,7 +15,7 @@ function getDatedContainerImageCodename(version: string): null | string {
}
function getDatedContainerImageVersion(version: string): null | number {
const groups = regEx(/^(?<codename>\w+)-(?<date>\d{8})$/).exec(version);
const groups = regex.exec(version);
if (!groups?.groups) {
return null;
}
@ -21,8 +23,18 @@ function getDatedContainerImageVersion(version: string): null | number {
return parseInt(groups.groups.date, 10);
}
function getDatedContainerImageSuffix(version: string): null | string {
const groups = regex.exec(version);
if (!groups?.groups?.suffix) {
return null;
}
return groups.groups.suffix;
}
export {
isDatedCodeName,
getDatedContainerImageCodename,
getDatedContainerImageVersion,
getDatedContainerImageSuffix,
};

View file

@ -5,84 +5,88 @@ describe('modules/versioning/ubuntu/index', () => {
const dt = DateTime.fromISO('2022-04-20');
it.each`
version | expected
${undefined} | ${false}
${null} | ${false}
${''} | ${false}
${'xenial'} | ${true}
${'04.10'} | ${true}
${'05.04'} | ${true}
${'05.10'} | ${true}
${'6.06'} | ${true}
${'6.10'} | ${true}
${'7.04'} | ${true}
${'7.10'} | ${true}
${'8.04'} | ${true}
${'8.10'} | ${true}
${'9.04'} | ${true}
${'9.10'} | ${true}
${'10.04.4'} | ${true}
${'10.10'} | ${true}
${'11.04'} | ${true}
${'11.10'} | ${true}
${'12.04.5'} | ${true}
${'12.10'} | ${true}
${'13.04'} | ${true}
${'13.10'} | ${true}
${'14.04.6'} | ${true}
${'14.10'} | ${true}
${'15.04'} | ${true}
${'15.10'} | ${true}
${'16.04.7'} | ${true}
${'16.10'} | ${true}
${'17.04'} | ${true}
${'17.10'} | ${true}
${'18.04.5'} | ${true}
${'18.10'} | ${true}
${'19.04'} | ${true}
${'19.10'} | ${true}
${'20.04'} | ${true}
${'20.10'} | ${true}
${'2020.04'} | ${false}
${'xenial'} | ${true}
${'warty'} | ${true}
${'hoary'} | ${true}
${'breezy'} | ${true}
${'dapper'} | ${true}
${'edgy'} | ${true}
${'feisty'} | ${true}
${'gutsy'} | ${true}
${'hardy'} | ${true}
${'intrepid'} | ${true}
${'jaunty'} | ${true}
${'karmic'} | ${true}
${'lucid.4'} | ${false}
${'maverick'} | ${true}
${'natty'} | ${true}
${'oneiric'} | ${true}
${'precise.5'} | ${false}
${'quantal'} | ${true}
${'raring'} | ${true}
${'saucy'} | ${true}
${'trusty.6'} | ${false}
${'utopic'} | ${true}
${'vivid'} | ${true}
${'wily'} | ${true}
${'xenial.7'} | ${false}
${'yakkety'} | ${true}
${'zesty'} | ${true}
${'artful'} | ${true}
${'bionic.5'} | ${false}
${'cosmic'} | ${true}
${'disco'} | ${true}
${'eoan'} | ${true}
${'focal'} | ${true}
${'groovy'} | ${true}
${'hirsute'} | ${true}
${'impish'} | ${true}
${'jammy'} | ${true}
${'jammy-20230816'} | ${true}
${'jammy-2023086'} | ${false}
version | expected
${undefined} | ${false}
${null} | ${false}
${''} | ${false}
${'xenial'} | ${true}
${'04.10'} | ${true}
${'05.04'} | ${true}
${'05.10'} | ${true}
${'6.06'} | ${true}
${'6.10'} | ${true}
${'7.04'} | ${true}
${'7.10'} | ${true}
${'8.04'} | ${true}
${'8.10'} | ${true}
${'9.04'} | ${true}
${'9.10'} | ${true}
${'10.04.4'} | ${true}
${'10.10'} | ${true}
${'11.04'} | ${true}
${'11.10'} | ${true}
${'12.04.5'} | ${true}
${'12.10'} | ${true}
${'13.04'} | ${true}
${'13.10'} | ${true}
${'14.04.6'} | ${true}
${'14.10'} | ${true}
${'15.04'} | ${true}
${'15.10'} | ${true}
${'16.04.7'} | ${true}
${'16.10'} | ${true}
${'17.04'} | ${true}
${'17.10'} | ${true}
${'18.04.5'} | ${true}
${'18.10'} | ${true}
${'19.04'} | ${true}
${'19.10'} | ${true}
${'20.04'} | ${true}
${'20.10'} | ${true}
${'2020.04'} | ${false}
${'xenial'} | ${true}
${'warty'} | ${true}
${'hoary'} | ${true}
${'breezy'} | ${true}
${'dapper'} | ${true}
${'edgy'} | ${true}
${'feisty'} | ${true}
${'gutsy'} | ${true}
${'hardy'} | ${true}
${'intrepid'} | ${true}
${'jaunty'} | ${true}
${'karmic'} | ${true}
${'lucid.4'} | ${false}
${'maverick'} | ${true}
${'natty'} | ${true}
${'oneiric'} | ${true}
${'precise.5'} | ${false}
${'quantal'} | ${true}
${'raring'} | ${true}
${'saucy'} | ${true}
${'trusty.6'} | ${false}
${'utopic'} | ${true}
${'vivid'} | ${true}
${'wily'} | ${true}
${'xenial.7'} | ${false}
${'yakkety'} | ${true}
${'zesty'} | ${true}
${'artful'} | ${true}
${'bionic.5'} | ${false}
${'cosmic'} | ${true}
${'disco'} | ${true}
${'eoan'} | ${true}
${'focal'} | ${true}
${'groovy'} | ${true}
${'hirsute'} | ${true}
${'impish'} | ${true}
${'jammy'} | ${true}
${'jammy-20230816'} | ${true}
${'jammy-20230816'} | ${true}
${'yakkety-20160806.1'} | ${true}
${'utopic-20150228.11'} | ${true}
${'utopic-20150228.11.1'} | ${false}
${'oracular-20240811.'} | ${false}
`('isValid("$version") === $expected', ({ version, expected }) => {
expect(ubuntu.isValid(version)).toBe(expected);
});
@ -272,51 +276,59 @@ describe('modules/versioning/ubuntu/index', () => {
);
it.each`
a | b | expected
${'20.04'} | ${'2020.04'} | ${false}
${'17.10'} | ${'artful'} | ${true}
${'xenial'} | ${'artful'} | ${false}
${'17.04'} | ${'artful'} | ${false}
${'artful'} | ${'17.10'} | ${true}
${'16.04'} | ${'xenial'} | ${true}
${'focal'} | ${'20.04'} | ${true}
${'20.04'} | ${'focal'} | ${true}
${'19.10'} | ${'19.10'} | ${true}
${'jammy'} | ${'jammy-20230816'} | ${false}
${'jammy-20230816'} | ${'jammy-20230816'} | ${true}
${'jammy-20230716'} | ${'jammy-20230816'} | ${false}
a | b | expected
${'20.04'} | ${'2020.04'} | ${false}
${'17.10'} | ${'artful'} | ${true}
${'xenial'} | ${'artful'} | ${false}
${'17.04'} | ${'artful'} | ${false}
${'artful'} | ${'17.10'} | ${true}
${'16.04'} | ${'xenial'} | ${true}
${'focal'} | ${'20.04'} | ${true}
${'20.04'} | ${'focal'} | ${true}
${'19.10'} | ${'19.10'} | ${true}
${'jammy'} | ${'jammy-20230816'} | ${false}
${'jammy-20230816'} | ${'jammy-20230816'} | ${true}
${'jammy-20230716'} | ${'jammy-20230816'} | ${false}
${'jammy-20230716.1'} | ${'jammy-20230716.1'} | ${true}
${'jammy-20230716.1'} | ${'jammy-20230716.2'} | ${false}
${'jammy-20230716.1'} | ${'jammy-20230816.11'} | ${false}
`('equals($a, $b) === $expected', ({ a, b, expected }) => {
expect(ubuntu.equals(a, b)).toBe(expected);
});
it.each`
a | b | expected
${'20.04'} | ${'20.10'} | ${false}
${'20.10'} | ${'20.04'} | ${true}
${'19.10'} | ${'20.04'} | ${false}
${'20.04'} | ${'19.10'} | ${true}
${'16.04'} | ${'16.04.7'} | ${false}
${'16.04.7'} | ${'16.04'} | ${true}
${'16.04.1'} | ${'16.04.7'} | ${false}
${'16.04.7'} | ${'16.04.1'} | ${true}
${'19.10.1'} | ${'20.04.1'} | ${false}
${'20.04.1'} | ${'19.10.1'} | ${true}
${'xxx'} | ${'yyy'} | ${false}
${'focal'} | ${'groovy'} | ${false}
${'groovy'} | ${'focal'} | ${true}
${'eoan'} | ${'focal'} | ${false}
${'focal'} | ${'eoan'} | ${true}
${'vivid'} | ${'saucy'} | ${true}
${'impish'} | ${'focal'} | ${true}
${'eoan'} | ${'quantal'} | ${true}
${'focal'} | ${'lucid'} | ${true}
${'eoan'} | ${'focal'} | ${false}
${'focal'} | ${'eoan'} | ${true}
${'jammy'} | ${'focal'} | ${true}
${'jammy-20230816'} | ${'focal'} | ${true}
${'jammy-20230816'} | ${'jammy-20230716'} | ${true}
${'jammy-20230716'} | ${'jammy-20230816'} | ${false}
${'focal-20230816'} | ${'jammy-20230716'} | ${false}
a | b | expected
${'20.04'} | ${'20.10'} | ${false}
${'20.10'} | ${'20.04'} | ${true}
${'19.10'} | ${'20.04'} | ${false}
${'20.04'} | ${'19.10'} | ${true}
${'16.04'} | ${'16.04.7'} | ${false}
${'16.04.7'} | ${'16.04'} | ${true}
${'16.04.1'} | ${'16.04.7'} | ${false}
${'16.04.7'} | ${'16.04.1'} | ${true}
${'19.10.1'} | ${'20.04.1'} | ${false}
${'20.04.1'} | ${'19.10.1'} | ${true}
${'xxx'} | ${'yyy'} | ${false}
${'focal'} | ${'groovy'} | ${false}
${'groovy'} | ${'focal'} | ${true}
${'eoan'} | ${'focal'} | ${false}
${'focal'} | ${'eoan'} | ${true}
${'vivid'} | ${'saucy'} | ${true}
${'impish'} | ${'focal'} | ${true}
${'eoan'} | ${'quantal'} | ${true}
${'focal'} | ${'lucid'} | ${true}
${'eoan'} | ${'focal'} | ${false}
${'focal'} | ${'eoan'} | ${true}
${'jammy'} | ${'focal'} | ${true}
${'jammy-20230816'} | ${'focal'} | ${true}
${'jammy-20230816'} | ${'jammy-20230716'} | ${true}
${'jammy-20230716'} | ${'jammy-20230816'} | ${false}
${'focal-20230816'} | ${'jammy-20230716'} | ${false}
${'zesty-20170517.1'} | ${'jammy-20240627.1'} | ${false}
${'jammy-20240627.3'} | ${'jammy-20240627.1'} | ${true}
${'jammy-20240627.3'} | ${'jammy-20240627.4'} | ${false}
${'jammy-20240627.1'} | ${'precise-20150228.11'} | ${true}
${'jammy-20240627'} | ${'precise-20150228.11'} | ${true}
`('isGreaterThan("$a", "$b") === $expected', ({ a, b, expected }) => {
expect(ubuntu.isGreaterThan(a, b)).toBe(expected);
});

View file

@ -4,6 +4,7 @@ import { DistroInfo } from '../distro';
import type { NewValueConfig, VersioningApi } from '../types';
import {
getDatedContainerImageCodename,
getDatedContainerImageSuffix,
getDatedContainerImageVersion,
isDatedCodeName,
} from './common';
@ -105,6 +106,12 @@ function equals(version: string, other: string): boolean {
return false;
}
const verSuffix = getDatedContainerImageSuffix(version);
const otherSuffix = getDatedContainerImageSuffix(other);
if (verSuffix !== otherSuffix) {
return false;
}
const ver = getVersionByCodename(version);
const otherVer = getVersionByCodename(other);
return isVersion(ver) && isVersion(otherVer) && ver === otherVer;
@ -138,6 +145,15 @@ function isGreaterThan(version: string, other: string): boolean {
return false;
}
const xSuffixVersion = getDatedContainerImageSuffix(version) ?? 0;
const ySuffixVersion = getDatedContainerImageSuffix(other) ?? 0;
if (xSuffixVersion > ySuffixVersion) {
return true;
}
if (xSuffixVersion < ySuffixVersion) {
return false;
}
const xPatch = getPatch(version) ?? 0;
const yPatch = getPatch(other) ?? 0;
return xPatch > yPatch;