Skip to content

Commit 777b884

Browse files
authored
feat(gerrit): Add gitUrl support (#42672)
* feat: Gerrit supports gitUrl This change adds support for the gitUrl parameter to the gerrit platform. It queries the gerrit server to check what download options are available. If ssh is selected but not available, it will throw an error. * feat: Gerrit supports gitUrl This removes support for querying the supported download schemes and instead hard-codes the default ssh port. * fix: Review feedback Addresses feedback left in review: - constants for ports - better SSH url creation - more consistent util method usage * fix: Review feedback Addresses feedback left in review: - Reverts SSH URL creation to ensure coverage target * fix: Review feedback Addresses feedback left in review: - Convert switch statement to if/else - Move endpointURL check into getGerritResponse This makes the parse/clone calls unnecessary. * fix: Review feedback Addresses feedback left in review: - Simplify ssh url creation
1 parent 05d36b7 commit 777b884

4 files changed

Lines changed: 104 additions & 27 deletions

File tree

lib/config/options/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3247,6 +3247,7 @@ const options: Readonly<RenovateOptions>[] = [
32473247
supportedPlatforms: [
32483248
'bitbucket-server',
32493249
'forgejo',
3250+
'gerrit',
32503251
'gitea',
32513252
'gitlab',
32523253
'scm-manager',

lib/modules/platform/gerrit/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,7 @@ export async function initRepo({
147147
labels: projectInfo.labels ?? {},
148148
};
149149
const baseUrl = defaults.endpoint!;
150-
const url = getGerritRepoUrl(repository, baseUrl);
150+
const url = getGerritRepoUrl(repository, baseUrl, gitUrl);
151151
configureScm(repository, config.gerritUsername!);
152152
await git.initRepo({ url, cloneSubmodules, cloneSubmodulesFilter });
153153

lib/modules/platform/gerrit/utils.spec.ts

Lines changed: 74 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -24,26 +24,84 @@ describe('modules/platform/gerrit/utils', () => {
2424
});
2525

2626
describe('getGerritRepoUrl()', () => {
27-
it('create a git url with username/password', () => {
28-
hostRules.find.mockReturnValue({
29-
username: 'abc',
30-
password: '123',
27+
describe('no gitUrl provided', () => {
28+
it('create a git url with username/password', () => {
29+
hostRules.find.mockReturnValue({
30+
username: 'abc',
31+
password: '123',
32+
});
33+
const repoUrl = utils.getGerritRepoUrl('web/apps', baseUrl, undefined);
34+
expect(repoUrl).toBe('https://abc:123@gerrit.example.com/a/web%2Fapps');
35+
});
36+
37+
it('create a git url without username/password', () => {
38+
hostRules.find.mockReturnValue({});
39+
expect(() =>
40+
utils.getGerritRepoUrl('web/apps', baseUrl, undefined),
41+
).toThrow('Init: You must configure a Gerrit Server username/password');
3142
});
32-
const repoUrl = utils.getGerritRepoUrl('web/apps', baseUrl);
33-
expect(repoUrl).toBe('https://abc:123@gerrit.example.com/a/web%2Fapps');
34-
});
3543

36-
it('create a git url without username/password', () => {
37-
hostRules.find.mockReturnValue({});
38-
expect(() => utils.getGerritRepoUrl('web/apps', baseUrl)).toThrow(
39-
'Init: You must configure a Gerrit Server username/password',
40-
);
44+
it('throws on invalid endpoint', () => {
45+
expect(() =>
46+
utils.getGerritRepoUrl('web/apps', '...', undefined),
47+
).toThrow(Error(CONFIG_GIT_URL_UNAVAILABLE));
48+
});
49+
});
50+
describe('default gitUrl', () => {
51+
it('create a git url with username/password', () => {
52+
hostRules.find.mockReturnValue({
53+
username: 'abc',
54+
password: '123',
55+
});
56+
const repoUrl = utils.getGerritRepoUrl('web/apps', baseUrl, 'default');
57+
expect(repoUrl).toBe('https://abc:123@gerrit.example.com/a/web%2Fapps');
58+
});
59+
});
60+
describe('endpoint gitUrl', () => {
61+
it('create a git url with username/password', () => {
62+
hostRules.find.mockReturnValue({
63+
username: 'abc',
64+
password: '123',
65+
});
66+
const repoUrl = utils.getGerritRepoUrl('web/apps', baseUrl, 'endpoint');
67+
expect(repoUrl).toBe('https://abc:123@gerrit.example.com/a/web%2Fapps');
68+
});
4169
});
70+
describe('ssh gitUrl', () => {
71+
it('create a simple url', () => {
72+
hostRules.find.mockReturnValue({
73+
username: 'abc',
74+
password: '123',
75+
});
76+
const repoUrl = utils.getGerritRepoUrl('web/apps', baseUrl, 'ssh');
77+
expect(repoUrl).toBe('ssh://gerrit.example.com:29418/web/apps');
78+
});
4279

43-
it('throws on invalid endpoint', () => {
44-
expect(() => utils.getGerritRepoUrl('web/apps', '...')).toThrow(
45-
Error(CONFIG_GIT_URL_UNAVAILABLE),
46-
);
80+
it('create a url with trailing slash', () => {
81+
hostRules.find.mockReturnValue({
82+
username: 'abc',
83+
password: '123',
84+
});
85+
const repoUrl = utils.getGerritRepoUrl(
86+
'web/apps',
87+
'https://gerrit.example.com/',
88+
'ssh',
89+
);
90+
expect(repoUrl).toBe('ssh://gerrit.example.com:29418/web/apps');
91+
});
92+
93+
it('create a url when base has context', () => {
94+
hostRules.find.mockReturnValue({
95+
username: 'abc',
96+
password: '123',
97+
});
98+
const repoUrl = utils.getGerritRepoUrl(
99+
'web/apps',
100+
'https://gerrit.example.com/context',
101+
'ssh',
102+
);
103+
expect(repoUrl).toBe('ssh://gerrit.example.com:29418/web/apps');
104+
});
47105
});
48106
});
49107

lib/modules/platform/gerrit/utils.ts

Lines changed: 28 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import * as hostRules from '../../../util/host-rules.ts';
66
import { regEx } from '../../../util/regex.ts';
77
import { joinUrlParts, parseUrl } from '../../../util/url.ts';
88
import { hashBody } from '../pr-body.ts';
9-
import type { Pr } from '../types.ts';
9+
import type { GitUrlOption, Pr } from '../types.ts';
1010
import type {
1111
GerritChange,
1212
GerritChangeStatus,
@@ -18,6 +18,8 @@ export const MIN_GERRIT_VERSION = '3.0.0';
1818

1919
export const TAG_PULL_REQUEST_BODY = 'pull-request';
2020

21+
const DEFAULT_SSH_PORT = `29418`;
22+
2123
/**
2224
* Max comment size in Gerrit (16kiB by default)
2325
* https://gerrit-review.googlesource.com/Documentation/config-gerrit.html#change:~:text=change.commentSizeLimit
@@ -32,33 +34,49 @@ export const REQUEST_DETAILS_FOR_PRS: GerritRequestDetail[] = [
3234
'COMMIT_FOOTERS', // to get the commit message
3335
] as const;
3436

35-
export function getGerritRepoUrl(repository: string, endpoint: string): string {
37+
export function getGerritRepoUrl(
38+
repository: string,
39+
endpoint: string,
40+
gitUrl: GitUrlOption | undefined,
41+
): string {
42+
const endpointUrl = parseUrl(endpoint);
43+
if (!endpointUrl) {
44+
throw new Error(CONFIG_GIT_URL_UNAVAILABLE);
45+
}
46+
47+
const url =
48+
gitUrl === 'ssh'
49+
? createSshUrl(endpointUrl, repository)
50+
: createHttpUrl(endpointUrl, endpoint, repository);
51+
logger.trace({ url }, 'using URL based on configured endpoint');
52+
53+
return url;
54+
}
55+
56+
function createSshUrl(url: URL, repository: string): string {
57+
return `ssh://${url.host}:${DEFAULT_SSH_PORT}/${repository}`;
58+
}
59+
60+
function createHttpUrl(url: URL, endpoint: string, repository: string): string {
3661
// Find options for current host and determine Git endpoint
3762
const opts = hostRules.find({
3863
hostType: 'gerrit',
3964
url: endpoint,
4065
});
4166

42-
const url = parseUrl(endpoint);
43-
if (!url) {
44-
throw new Error(CONFIG_GIT_URL_UNAVAILABLE);
45-
}
4667
if (!(opts.username && opts.password)) {
4768
throw new Error(
4869
'Init: You must configure a Gerrit Server username/password',
4970
);
5071
}
72+
5173
url.username = opts.username;
5274
url.password = opts.password;
5375
url.pathname = joinUrlParts(
5476
url.pathname,
5577
'a',
5678
encodeURIComponent(repository),
5779
);
58-
logger.trace(
59-
{ url: url.toString() },
60-
'using URL based on configured endpoint',
61-
);
6280
return url.toString();
6381
}
6482

0 commit comments

Comments
 (0)