Skip to content

Commit

Permalink
feat(bitbucket-server)!: autodetect gitAuthor if possible (#29525)
Browse files Browse the repository at this point in the history
Co-authored-by: Rhys Arkins <rhys@arkins.net>
  • Loading branch information
amezin and rarkins committed Jul 25, 2024
1 parent b973219 commit 84ad846
Show file tree
Hide file tree
Showing 4 changed files with 149 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,7 @@ exports[`modules/platform/bitbucket-server/index endpoint with no path getPrList
exports[`modules/platform/bitbucket-server/index endpoint with no path initPlatform() should init 1`] = `
{
"endpoint": "https://stash.renovatebot.com/",
"gitAuthor": "Abc Def <abc@def.com>",
}
`;

Expand Down Expand Up @@ -355,6 +356,7 @@ exports[`modules/platform/bitbucket-server/index endpoint with path getPrList()
exports[`modules/platform/bitbucket-server/index endpoint with path initPlatform() should init 1`] = `
{
"endpoint": "https://stash.renovatebot.com/",
"gitAuthor": "Abc Def <abc@def.com>",
}
`;

Expand Down
105 changes: 105 additions & 0 deletions lib/modules/platform/bitbucket-server/index.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import {
import type { logger as _logger } from '../../../logger';
import type * as _git from '../../../util/git';
import type { LongCommitSha } from '../../../util/git/types';
import { ensureTrailingSlash } from '../../../util/url';
import type { Platform } from '../types';

jest.mock('timers/promises');
Expand Down Expand Up @@ -190,6 +191,11 @@ describe('modules/platform/bitbucket-server/index', () => {
let logger: jest.Mocked<typeof _logger>;
const username = 'abc';
const password = '123';
const userInfo = {
name: username,
emailAddress: 'abc@def.com',
displayName: 'Abc Def',
};

async function initRepo(config = {}): Promise<httpMock.Scope> {
const scope = httpMock
Expand Down Expand Up @@ -234,6 +240,10 @@ describe('modules/platform/bitbucket-server/index', () => {
.scope(urlHost)
.get(`${urlPath}/rest/api/1.0/application-properties`)
.reply(200, { version: '8.0.0' });
httpMock
.scope(urlHost)
.get(`${urlPath}/rest/api/1.0/users/${username}`)
.reply(200, userInfo);
await bitbucket.initPlatform({
endpoint,
username,
Expand Down Expand Up @@ -292,6 +302,10 @@ describe('modules/platform/bitbucket-server/index', () => {
.scope('https://stash.renovatebot.com')
.get('/rest/api/1.0/application-properties')
.reply(403);
httpMock
.scope('https://stash.renovatebot.com')
.get(`/rest/api/1.0/users/${username}`)
.reply(200, userInfo);

await bitbucket.initPlatform({
endpoint: 'https://stash.renovatebot.com',
Expand All @@ -304,8 +318,38 @@ describe('modules/platform/bitbucket-server/index', () => {
);
});

it('should not throw if user info fetch fails', async () => {
httpMock
.scope(urlHost)
.get(`${urlPath}/rest/api/1.0/application-properties`)
.reply(200, { version: '8.0.0' });
httpMock
.scope(urlHost)
.get(`${urlPath}/rest/api/1.0/users/${username}`)
.reply(404);

expect(
await bitbucket.initPlatform({
endpoint: url.href,
username,
password,
}),
).toEqual({
endpoint: ensureTrailingSlash(url.href),
});
expect(logger.debug).toHaveBeenCalledWith(
expect.any(Object),
'Failed to get user info, fallback gitAuthor will be used',
);
});

it('should skip api call to fetch version when platform version is set in environment', async () => {
process.env.RENOVATE_X_PLATFORM_VERSION = '8.0.0';
httpMock
.scope('https://stash.renovatebot.com')
.get(`/rest/api/1.0/users/${username}`)
.reply(200, userInfo);

await expect(
bitbucket.initPlatform({
endpoint: 'https://stash.renovatebot.com',
Expand All @@ -316,11 +360,72 @@ describe('modules/platform/bitbucket-server/index', () => {
delete process.env.RENOVATE_X_PLATFORM_VERSION;
});

it('should skip users api call when gitAuthor is configured', async () => {
httpMock
.scope(urlHost)
.get(`${urlPath}/rest/api/1.0/application-properties`)
.reply(200, { version: '8.0.0' });

expect(
await bitbucket.initPlatform({
endpoint: url.href,
username: 'def',
password: '123',
gitAuthor: `Def Abc <def@abc.com>`,
}),
).toEqual({
endpoint: ensureTrailingSlash(url.href),
});
});

it('should skip users api call when no username', async () => {
httpMock
.scope(urlHost)
.get(`${urlPath}/rest/api/1.0/application-properties`)
.reply(200, { version: '8.0.0' });

expect(
await bitbucket.initPlatform({
endpoint: url.href,
token: '123',
}),
).toEqual({
endpoint: ensureTrailingSlash(url.href),
});
});

it('should fetch user info if token with username', async () => {
httpMock
.scope(urlHost)
.get(`${urlPath}/rest/api/1.0/application-properties`)
.reply(200, { version: '8.0.0' });
httpMock
.scope(urlHost)
.get(`${urlPath}/rest/api/1.0/users/${username}`)
.reply(200, userInfo);

expect(
await bitbucket.initPlatform({
endpoint: url.href,
token: '123',
username,
}),
).toEqual({
endpoint: ensureTrailingSlash(url.href),
gitAuthor: `${userInfo.displayName} <${userInfo.emailAddress}>`,
});
});

it('should init', async () => {
httpMock
.scope('https://stash.renovatebot.com')
.get('/rest/api/1.0/application-properties')
.reply(200, { version: '8.0.0' });
httpMock
.scope('https://stash.renovatebot.com')
.get(`/rest/api/1.0/users/${username}`)
.reply(200, userInfo);

expect(
await bitbucket.initPlatform({
endpoint: 'https://stash.renovatebot.com',
Expand Down
37 changes: 36 additions & 1 deletion lib/modules/platform/bitbucket-server/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import {
BitbucketServerHttp,
setBaseUrl,
} from '../../../util/http/bitbucket-server';
import type { HttpResponse } from '../../../util/http/types';
import type { HttpOptions, HttpResponse } from '../../../util/http/types';
import { newlineRegex, regEx } from '../../../util/regex';
import { sanitize } from '../../../util/sanitize';
import { ensureTrailingSlash, getQueryString } from '../../../util/url';
Expand All @@ -40,6 +40,7 @@ import type {
} from '../types';
import { getNewBranchName, repoFingerprint } from '../util';
import { smartTruncate } from '../utils/pr-body';
import { UserSchema } from './schema';
import type {
BbsConfig,
BbsPr,
Expand Down Expand Up @@ -88,6 +89,7 @@ export async function initPlatform({
token,
username,
password,
gitAuthor,
}: PlatformParams): Promise<PlatformResult> {
if (!endpoint) {
throw new Error('Init: You must configure a Bitbucket Server endpoint');
Expand Down Expand Up @@ -132,6 +134,39 @@ export async function initPlatform({
);
}

if (!gitAuthor && username) {
logger.debug(`Attempting to confirm gitAuthor from username`);
const options: HttpOptions = {
memCache: false,
};

if (token) {
options.token = token;
} else {
options.username = username;
options.password = password;
}

try {
const { displayName, emailAddress } = (
await bitbucketServerHttp.getJson(
`./rest/api/1.0/users/${username}`,
options,
UserSchema,
)
).body;

platformConfig.gitAuthor = `${displayName} <${emailAddress}>`;

logger.debug(`Detected gitAuthor: ${platformConfig.gitAuthor}`);
} catch (err) {
logger.debug(
{ err },
'Failed to get user info, fallback gitAuthor will be used',
);
}
}

return platformConfig;
}

Expand Down
6 changes: 6 additions & 0 deletions lib/modules/platform/bitbucket-server/schema.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { z } from 'zod';

export const UserSchema = z.object({
displayName: z.string(),
emailAddress: z.string(),
});

0 comments on commit 84ad846

Please sign in to comment.