mirror of
https://github.com/renovatebot/renovate.git
synced 2026-11-01 10:09:50 +00:00
40fce9aba7
* fix(gerrit): resolve relative submodule URLs for nested project paths * Fix tests after rebase --------- Co-authored-by: Felipe Santos <felipe.santos@ericsson.com>
482 lines
14 KiB
TypeScript
482 lines
14 KiB
TypeScript
import { hostRules } from '~test/host-rules.ts';
|
|
import { partial } from '~test/util.ts';
|
|
import { CONFIG_GIT_URL_UNAVAILABLE } from '../../../constants/error-messages.ts';
|
|
import type { BranchStatus } from '../../../types/index.ts';
|
|
import { setBaseUrl } from '../../../util/http/gerrit.ts';
|
|
import { hashBody } from '../pr-body.ts';
|
|
import type {
|
|
GerritAccountInfo,
|
|
GerritChange,
|
|
GerritChangeMessageInfo,
|
|
GerritLabelTypeInfo,
|
|
GerritRevisionInfo,
|
|
} from './schema.ts';
|
|
import type { GerritChangeStatus } from './types.ts';
|
|
import * as utils from './utils.ts';
|
|
import { mapBranchStatusToLabel } from './utils.ts';
|
|
|
|
const baseUrl = 'https://gerrit.example.com';
|
|
|
|
describe('modules/platform/gerrit/utils', () => {
|
|
const currentRevision = '0123456789abcdef0123456789abcdef01234567';
|
|
|
|
beforeEach(() => {
|
|
setBaseUrl(baseUrl);
|
|
});
|
|
|
|
describe('getGerritRepoUrl()', () => {
|
|
describe('no gitUrl provided', () => {
|
|
it('create a git url with username/password', () => {
|
|
hostRules.add({
|
|
username: 'abc',
|
|
password: '123',
|
|
});
|
|
const repoUrl = utils.getGerritRepoUrl(
|
|
'web/apps',
|
|
baseUrl,
|
|
undefined,
|
|
'abc',
|
|
);
|
|
expect(repoUrl).toBe('https://abc:123@gerrit.example.com/a/web/apps');
|
|
});
|
|
|
|
it('preserves slashes for deeply nested repository paths', () => {
|
|
hostRules.add({
|
|
username: 'abc',
|
|
password: '123',
|
|
});
|
|
const repoUrl = utils.getGerritRepoUrl(
|
|
'group/subgroup/my-repo',
|
|
baseUrl,
|
|
undefined,
|
|
'abc',
|
|
);
|
|
expect(repoUrl).toBe(
|
|
'https://abc:123@gerrit.example.com/a/group/subgroup/my-repo',
|
|
);
|
|
});
|
|
|
|
it('create a git url without username/password', () => {
|
|
expect(() =>
|
|
utils.getGerritRepoUrl('web/apps', baseUrl, undefined, 'abc'),
|
|
).toThrow('Init: You must configure a Gerrit Server username/password');
|
|
});
|
|
|
|
it('throws on invalid endpoint', () => {
|
|
expect(() =>
|
|
utils.getGerritRepoUrl('web/apps', '...', undefined, 'abc'),
|
|
).toThrow(Error(CONFIG_GIT_URL_UNAVAILABLE));
|
|
});
|
|
});
|
|
describe('default gitUrl', () => {
|
|
it('create a git url with username/password', () => {
|
|
hostRules.add({
|
|
username: 'abc',
|
|
password: '123',
|
|
});
|
|
const repoUrl = utils.getGerritRepoUrl(
|
|
'web/apps',
|
|
baseUrl,
|
|
'default',
|
|
'abc',
|
|
);
|
|
expect(repoUrl).toBe('https://abc:123@gerrit.example.com/a/web/apps');
|
|
});
|
|
});
|
|
describe('endpoint gitUrl', () => {
|
|
it('create a git url with username/password', () => {
|
|
hostRules.add({
|
|
username: 'abc',
|
|
password: '123',
|
|
});
|
|
const repoUrl = utils.getGerritRepoUrl(
|
|
'web/apps',
|
|
baseUrl,
|
|
'endpoint',
|
|
'abc',
|
|
);
|
|
expect(repoUrl).toBe('https://abc:123@gerrit.example.com/a/web/apps');
|
|
});
|
|
});
|
|
describe('ssh gitUrl', () => {
|
|
it('create a simple url', () => {
|
|
hostRules.add({
|
|
username: 'abc',
|
|
password: '123',
|
|
});
|
|
const repoUrl = utils.getGerritRepoUrl(
|
|
'web/apps',
|
|
baseUrl,
|
|
'ssh',
|
|
'abc',
|
|
);
|
|
expect(repoUrl).toBe('ssh://abc@gerrit.example.com:29418/web/apps');
|
|
});
|
|
|
|
it('create a url with trailing slash', () => {
|
|
hostRules.add({
|
|
username: 'abc',
|
|
password: '123',
|
|
});
|
|
const repoUrl = utils.getGerritRepoUrl(
|
|
'web/apps',
|
|
'https://gerrit.example.com/',
|
|
'ssh',
|
|
'abc',
|
|
);
|
|
expect(repoUrl).toBe('ssh://abc@gerrit.example.com:29418/web/apps');
|
|
});
|
|
|
|
it('create a url when base has context', () => {
|
|
hostRules.add({
|
|
username: 'abc',
|
|
password: '123',
|
|
});
|
|
const repoUrl = utils.getGerritRepoUrl(
|
|
'web/apps',
|
|
'https://gerrit.example.com/context',
|
|
'ssh',
|
|
'abc',
|
|
);
|
|
expect(repoUrl).toBe('ssh://abc@gerrit.example.com:29418/web/apps');
|
|
});
|
|
|
|
it('ignores non-default HTTP port from the endpoint', () => {
|
|
vi.spyOn(hostRules, 'find').mockReturnValue({
|
|
username: 'abc',
|
|
password: '123',
|
|
});
|
|
const repoUrl = utils.getGerritRepoUrl(
|
|
'web/apps',
|
|
'http://gerrit.example.com:8080/',
|
|
'ssh',
|
|
'abc',
|
|
);
|
|
expect(repoUrl).toBe('ssh://abc@gerrit.example.com:29418/web/apps');
|
|
});
|
|
});
|
|
});
|
|
|
|
describe('mapPrStateToGerritFilter()', () => {
|
|
it.each([
|
|
['closed', 'status:abandoned'],
|
|
['merged', 'status:merged'],
|
|
['!open', '-status:open'],
|
|
['open', 'status:open'],
|
|
['all', null],
|
|
[undefined, null],
|
|
])(
|
|
'maps pr state %p to gerrit filter %p',
|
|
(prState: any, filter: string | null) => {
|
|
expect(utils.mapPrStateToGerritFilter(prState)).toEqual(filter);
|
|
},
|
|
);
|
|
});
|
|
|
|
describe('mapGerritChangeStateToPrState()', () => {
|
|
it.each([
|
|
['NEW', 'open'],
|
|
['MERGED', 'merged'],
|
|
['ABANDONED', 'closed'],
|
|
['unknown', undefined],
|
|
])('maps gerrit change state %p to PrState %p', (state, prState) => {
|
|
expect(
|
|
utils.mapGerritChangeStateToPrState(state as GerritChangeStatus),
|
|
).toEqual(prState);
|
|
});
|
|
});
|
|
|
|
describe('mapGerritChangeToPr()', () => {
|
|
it('map a gerrit change to to Pr', () => {
|
|
const change = partial<GerritChange>({
|
|
_number: 123456,
|
|
status: 'NEW',
|
|
branch: 'main',
|
|
subject: 'Fix for',
|
|
created: '2025-04-14 16:33:37.000000000',
|
|
hashtags: ['hashtag1', 'hashtag2'],
|
|
reviewers: {
|
|
REVIEWER: [partial<GerritAccountInfo>({ username: 'username' })],
|
|
},
|
|
current_revision: currentRevision,
|
|
revisions: {
|
|
[currentRevision]: partial<GerritRevisionInfo>({
|
|
commit_with_footers:
|
|
'Some change\n\nRenovate-Branch: renovate/dependency-1.x\nChange-Id: ...',
|
|
}),
|
|
},
|
|
messages: [
|
|
partial<GerritChangeMessageInfo>({
|
|
id: '9d78ac236714cee8c2d86e95d638358925cf6853',
|
|
tag: 'pull-request',
|
|
message: 'Patch Set 1:\n\nOld PR-Body',
|
|
}),
|
|
partial<GerritChangeMessageInfo>({
|
|
id: '1d17c930381e88e177bbc59595c3ec941bd21028',
|
|
tag: 'pull-request',
|
|
message: 'Patch Set 12:\n\nLast PR-Body',
|
|
}),
|
|
partial<GerritChangeMessageInfo>({
|
|
id: '9d78ac236714cee8c2d86e95d638358925cf6853',
|
|
message: 'other message...',
|
|
}),
|
|
],
|
|
});
|
|
|
|
expect(utils.mapGerritChangeToPr(change)).toEqual({
|
|
number: 123456,
|
|
state: 'open',
|
|
title: 'Fix for',
|
|
createdAt: '2025-04-14T16:33:37.000000000',
|
|
sourceBranch: 'renovate/dependency-1.x',
|
|
targetBranch: 'main',
|
|
labels: ['hashtag1', 'hashtag2'],
|
|
reviewers: ['username'],
|
|
bodyStruct: {
|
|
hash: hashBody('Last PR-Body'),
|
|
},
|
|
sha: currentRevision,
|
|
});
|
|
});
|
|
|
|
it('map a gerrit change without reviewers to Pr', () => {
|
|
const change = partial<GerritChange>({
|
|
_number: 123456,
|
|
status: 'NEW',
|
|
branch: 'main',
|
|
subject: 'Fix for',
|
|
reviewers: {},
|
|
current_revision: currentRevision,
|
|
revisions: {
|
|
[currentRevision]: partial<GerritRevisionInfo>({
|
|
commit_with_footers:
|
|
'Some change\n\nRenovate-Branch: renovate/dependency-1.x\nChange-Id: ...',
|
|
}),
|
|
},
|
|
created: '2025-04-14 16:33:37.000000000',
|
|
});
|
|
expect(utils.mapGerritChangeToPr(change)).toEqual({
|
|
number: 123456,
|
|
state: 'open',
|
|
title: 'Fix for',
|
|
sourceBranch: 'renovate/dependency-1.x',
|
|
targetBranch: 'main',
|
|
reviewers: [],
|
|
sha: currentRevision,
|
|
bodyStruct: {
|
|
hash: hashBody(''),
|
|
},
|
|
createdAt: '2025-04-14T16:33:37.000000000',
|
|
});
|
|
});
|
|
|
|
it('does not map a gerrit change without source branch to Pr', () => {
|
|
const change = partial<GerritChange>({
|
|
_number: 123456,
|
|
status: 'NEW',
|
|
branch: 'main',
|
|
subject: 'Fix for',
|
|
current_revision: currentRevision,
|
|
revisions: {
|
|
[currentRevision]: partial<GerritRevisionInfo>({
|
|
commit_with_footers:
|
|
'Some change\n\nRenovate-Broke: renovate/dependency-1.x\nChange-Id: ...',
|
|
}),
|
|
},
|
|
created: '2025-04-14 16:33:37.000000000',
|
|
});
|
|
expect(utils.mapGerritChangeToPr(change)).toBeNull();
|
|
});
|
|
|
|
it('does not reject a broken commit message if knownProperties.sourceBranch is passed', () => {
|
|
const change = partial<GerritChange>({
|
|
_number: 123456,
|
|
status: 'NEW',
|
|
branch: 'main',
|
|
subject: 'Fix for',
|
|
current_revision: currentRevision,
|
|
revisions: {
|
|
[currentRevision]: partial<GerritRevisionInfo>({
|
|
commit_with_footers:
|
|
'Some change\n\nRenovate-Broke: renovate/dependency-1.x\nChange-Id: ...',
|
|
}),
|
|
},
|
|
created: '2025-04-14 16:33:37.000000000',
|
|
});
|
|
expect(
|
|
utils.mapGerritChangeToPr(change, {
|
|
sourceBranch: 'renovate/dependency-1.x',
|
|
}),
|
|
).toEqual({
|
|
number: 123456,
|
|
state: 'open',
|
|
title: 'Fix for',
|
|
sourceBranch: 'renovate/dependency-1.x',
|
|
targetBranch: 'main',
|
|
reviewers: [],
|
|
sha: currentRevision,
|
|
bodyStruct: {
|
|
hash: hashBody(''),
|
|
},
|
|
createdAt: '2025-04-14T16:33:37.000000000',
|
|
});
|
|
});
|
|
|
|
it('avoids iterating through change messages knownProperties.prBody is passed', () => {
|
|
const change = partial<GerritChange>({
|
|
_number: 123456,
|
|
status: 'NEW',
|
|
branch: 'main',
|
|
subject: 'Fix for',
|
|
current_revision: currentRevision,
|
|
revisions: {
|
|
[currentRevision]: partial<GerritRevisionInfo>({
|
|
commit_with_footers:
|
|
'Some change\n\nRenovate-Branch: renovate/dependency-1.x\nChange-Id: ...',
|
|
}),
|
|
},
|
|
created: '2025-04-14 16:33:37.000000000',
|
|
});
|
|
expect(
|
|
utils.mapGerritChangeToPr(change, {
|
|
prBody: 'PR Body',
|
|
}),
|
|
).toEqual({
|
|
number: 123456,
|
|
state: 'open',
|
|
title: 'Fix for',
|
|
sourceBranch: 'renovate/dependency-1.x',
|
|
targetBranch: 'main',
|
|
reviewers: [],
|
|
sha: currentRevision,
|
|
bodyStruct: {
|
|
hash: hashBody('PR Body'),
|
|
},
|
|
createdAt: '2025-04-14T16:33:37.000000000',
|
|
});
|
|
});
|
|
});
|
|
|
|
describe('extractSourceBranch()', () => {
|
|
it('no commit message', () => {
|
|
const change = partial<GerritChange>();
|
|
expect(utils.extractSourceBranch(change)).toBeUndefined();
|
|
});
|
|
|
|
it('commit message with no footer', () => {
|
|
const change = partial<GerritChange>({
|
|
current_revision: currentRevision,
|
|
revisions: {
|
|
[currentRevision]: partial<GerritRevisionInfo>({
|
|
commit_with_footers: 'some message...',
|
|
}),
|
|
},
|
|
});
|
|
expect(utils.extractSourceBranch(change)).toBeUndefined();
|
|
});
|
|
|
|
it('commit message with footer', () => {
|
|
const change = partial<GerritChange>({
|
|
current_revision: currentRevision,
|
|
revisions: {
|
|
[currentRevision]: partial<GerritRevisionInfo>({
|
|
commit_with_footers:
|
|
'Some change\n\nRenovate-Branch: renovate/dependency-1.x\nChange-Id: ...',
|
|
}),
|
|
},
|
|
});
|
|
expect(utils.extractSourceBranch(change)).toBe('renovate/dependency-1.x');
|
|
});
|
|
});
|
|
|
|
describe('findPullRequestBody()', () => {
|
|
it('find pull-request-body', () => {
|
|
const change = partial<GerritChange>({
|
|
messages: [
|
|
partial<GerritChangeMessageInfo>({
|
|
id: '9d78ac236714cee8c2d86e95d638358925cf6853',
|
|
tag: 'pull-request',
|
|
message: 'Patch Set 1:\n\nOld PR-Body',
|
|
}),
|
|
partial<GerritChangeMessageInfo>({
|
|
id: '1d17c930381e88e177bbc59595c3ec941bd21028',
|
|
tag: 'pull-request',
|
|
message: 'Patch Set 12:\n\nLast PR-Body',
|
|
}),
|
|
partial<GerritChangeMessageInfo>({
|
|
id: '9d78ac236714cee8c2d86e95d638358925cf6853',
|
|
message: 'other message...',
|
|
}),
|
|
],
|
|
});
|
|
expect(utils.findPullRequestBody(change)).toBe('Last PR-Body');
|
|
});
|
|
|
|
it('no pull-request-body message found', () => {
|
|
const change = partial<GerritChange>({});
|
|
expect(utils.findPullRequestBody(change)).toBeUndefined();
|
|
change.messages = [];
|
|
expect(utils.findPullRequestBody(change)).toBeUndefined();
|
|
change.messages = [
|
|
partial<GerritChangeMessageInfo>({
|
|
tag: 'other-tag',
|
|
message: 'message',
|
|
}),
|
|
];
|
|
expect(utils.findPullRequestBody(change)).toBeUndefined();
|
|
});
|
|
});
|
|
|
|
describe('mapBranchStatusToLabel()', () => {
|
|
const labelWithOne: GerritLabelTypeInfo = {
|
|
values: { '-1': 'rejected', '0': 'default', '1': 'accepted' },
|
|
default_value: 0,
|
|
};
|
|
|
|
it.each([
|
|
['red', -1],
|
|
['yellow', -1],
|
|
['green', 1],
|
|
])(
|
|
'Label with +1/-1 map branchState=%p to %p',
|
|
(branchState, expectedValue) => {
|
|
expect(
|
|
mapBranchStatusToLabel(branchState as BranchStatus, labelWithOne),
|
|
).toEqual(expectedValue);
|
|
},
|
|
);
|
|
|
|
const labelWithTwo: GerritLabelTypeInfo = {
|
|
values: {
|
|
'-2': 'rejected',
|
|
'-1': 'disliked',
|
|
'0': 'default',
|
|
'1': 'looksOkay',
|
|
'2': 'approved',
|
|
},
|
|
default_value: 0,
|
|
};
|
|
|
|
it.each([
|
|
['red', -2],
|
|
['yellow', -2],
|
|
['green', 2],
|
|
])(
|
|
'Label with +2/-2, map branchState=%p to %p',
|
|
(branchState, expectedValue) => {
|
|
expect(
|
|
mapBranchStatusToLabel(branchState as BranchStatus, labelWithTwo),
|
|
).toEqual(expectedValue);
|
|
},
|
|
);
|
|
});
|
|
|
|
describe('convertGerritDateToISO()', () => {
|
|
it('converts Gerrit date format to ISO format', () => {
|
|
expect(
|
|
utils.convertGerritDateToISO('2023-05-20 14:25:30.123456789'),
|
|
).toBe('2023-05-20T14:25:30.123456789');
|
|
});
|
|
});
|
|
});
|