diff --git a/lib/globals.d.ts b/lib/globals.d.ts index eef15fbf1826df8aed78f800a647a58527745637..8cd937df0d0887690eb5d26090dd9ec98e8af4bc 100644 --- a/lib/globals.d.ts +++ b/lib/globals.d.ts @@ -9,12 +9,6 @@ declare interface Error { validationMessage?: string; } -declare namespace NodeJS { - interface Global { - gitAuthor?: { name: string; email: string }; - } -} - // can't use `resolveJsonModule` because it will copy json files and change dist path declare module '*/package.json' { diff --git a/lib/platform/azure/index.ts b/lib/platform/azure/index.ts index 27efa594855b81a7da9944541e26518cd1e14513..d91f5aa485fe2dfea8d98d01149dd60ee3a427f6 100644 --- a/lib/platform/azure/index.ts +++ b/lib/platform/azure/index.ts @@ -180,8 +180,6 @@ export async function initRepo({ ...config, url, extraCloneOpts: getStorageExtraCloneOpts(opts), - gitAuthorName: global.gitAuthor?.name, - gitAuthorEmail: global.gitAuthor?.email, cloneSubmodules, }); const repoConfig: RepoResult = { diff --git a/lib/platform/bitbucket-server/index.spec.ts b/lib/platform/bitbucket-server/index.spec.ts index 1002b9aafa27195fd908a305b4a4908f9d334749..9ca7dba1e8353c2c3b3b5cc6e31dbd84697afb2e 100644 --- a/lib/platform/bitbucket-server/index.spec.ts +++ b/lib/platform/bitbucket-server/index.spec.ts @@ -1311,18 +1311,13 @@ describe('platform/bitbucket-server/index', () => { .twice() .reply(200, { conflicted: false }); - const author = global.gitAuthor; - try { - expect(await bitbucket.getPr(3)).toMatchSnapshot(); + expect(await bitbucket.getPr(3)).toMatchSnapshot(); - expect(await bitbucket.getPr(5)).toMatchSnapshot(); + expect(await bitbucket.getPr(5)).toMatchSnapshot(); - expect(await bitbucket.getPr(5)).toMatchSnapshot(); + expect(await bitbucket.getPr(5)).toMatchSnapshot(); - expect(httpMock.getTrace()).toMatchSnapshot(); - } finally { - global.gitAuthor = author; - } + expect(httpMock.getTrace()).toMatchSnapshot(); }); it('gets a closed PR', async () => { diff --git a/lib/platform/bitbucket-server/index.ts b/lib/platform/bitbucket-server/index.ts index 44bc93d61a6a4f32b52702c8de711391f6192e49..711be02aa8b476e973dff5cb1d3b0d1ace195668 100644 --- a/lib/platform/bitbucket-server/index.ts +++ b/lib/platform/bitbucket-server/index.ts @@ -214,8 +214,6 @@ export async function initRepo({ await git.initRepo({ ...config, url: gitUrl, - gitAuthorName: global.gitAuthor?.name, - gitAuthorEmail: global.gitAuthor?.email, cloneSubmodules, }); diff --git a/lib/platform/bitbucket/index.spec.ts b/lib/platform/bitbucket/index.spec.ts index 2711cf3cc7a9988321fb7f246a7d7ae938b11c21..2d8508446e5942c71096ad31c82b2aebf1b1faaf 100644 --- a/lib/platform/bitbucket/index.spec.ts +++ b/lib/platform/bitbucket/index.spec.ts @@ -726,7 +726,6 @@ describe('platform/bitbucket/index', () => { it('canRebase', async () => { expect.assertions(4); - const author = global.gitAuthor; const scope = await initRepoMock(); scope .get('/2.0/repositories/some/repo/pullrequests/3') @@ -747,22 +746,13 @@ describe('platform/bitbucket/index', () => { .get('/2.0/repositories/some/repo/pullrequests/5/diff') .twice() .reply(200, diff); - try { - expect(await bitbucket.getPr(3)).toMatchSnapshot(); - - global.gitAuthor = { - email: 'renovate@whitesourcesoftware.com', - name: 'bot', - }; - expect(await bitbucket.getPr(5)).toMatchSnapshot(); - - global.gitAuthor = { email: 'jane@example.com', name: 'jane' }; - expect(await bitbucket.getPr(5)).toMatchSnapshot(); - - expect(httpMock.getTrace()).toMatchSnapshot(); - } finally { - global.gitAuthor = author; - } + expect(await bitbucket.getPr(3)).toMatchSnapshot(); + + expect(await bitbucket.getPr(5)).toMatchSnapshot(); + + expect(await bitbucket.getPr(5)).toMatchSnapshot(); + + expect(httpMock.getTrace()).toMatchSnapshot(); }); }); diff --git a/lib/platform/bitbucket/index.ts b/lib/platform/bitbucket/index.ts index 98471047aa87f74c7206056e6f39e637ec070c1d..7f2cc28fc5f21920b3a1ec239c39b91bb11340c8 100644 --- a/lib/platform/bitbucket/index.ts +++ b/lib/platform/bitbucket/index.ts @@ -179,8 +179,6 @@ export async function initRepo({ await git.initRepo({ ...config, url, - gitAuthorName: global.gitAuthor?.name, - gitAuthorEmail: global.gitAuthor?.email, cloneSubmodules, }); const repoConfig: RepoResult = { diff --git a/lib/platform/gitea/index.spec.ts b/lib/platform/gitea/index.spec.ts index 2c41ac96a9cd02f9485ec376c406e2ecccefe7a8..1cd6325da00ce1be94a2d891dedd5f06749192f3 100644 --- a/lib/platform/gitea/index.spec.ts +++ b/lib/platform/gitea/index.spec.ts @@ -176,8 +176,6 @@ describe('platform/gitea/index', () => { gitvcs.isBranchStale.mockResolvedValue(false); gitvcs.getBranchCommit.mockReturnValue(mockCommitHash); - global.gitAuthor = { name: 'Renovate', email: 'renovate@example.com' }; - setBaseUrl('https://gitea.renovatebot.com/api/v1'); }); @@ -574,7 +572,9 @@ describe('platform/gitea/index', () => { partial<ght.Branch>({ commit: { id: mockCommitHash, - author: partial<ght.CommitUser>({ email: global.gitAuthor.email }), + author: partial<ght.CommitUser>({ + email: 'renovate@whitesourcesoftware.com', + }), }, }) ); diff --git a/lib/platform/gitea/index.ts b/lib/platform/gitea/index.ts index c7d831e6b007a71cf091153916c6c69d4b4def71..a72082431d3995bca9e6e8cfcb5fa8f7b238639c 100644 --- a/lib/platform/gitea/index.ts +++ b/lib/platform/gitea/index.ts @@ -297,8 +297,6 @@ const platform: Platform = { await git.initRepo({ ...config, url: URL.format(gitEndpoint), - gitAuthorName: global.gitAuthor?.name, - gitAuthorEmail: global.gitAuthor?.email, }); // Reset cached resources diff --git a/lib/platform/github/index.spec.ts b/lib/platform/github/index.spec.ts index 3d0c716cff4a53358d749b1c9352e9f89671a8b0..ff04c1f864f4d3a186085da9c42286cb99932584 100644 --- a/lib/platform/github/index.spec.ts +++ b/lib/platform/github/index.spec.ts @@ -30,7 +30,6 @@ describe('platform/github/index', () => { git.getBranchCommit.mockReturnValue( '0d9c7726c3d628b7e28af234595cfd20febdbf8e' ); - delete global.gitAuthor; hostRules.find.mockReturnValue({ token: 'abc123', }); @@ -1900,10 +1899,6 @@ describe('platform/github/index', () => { const scope = httpMock.scope(githubApiHost); initRepoMock(scope, 'some/repo'); scope.post('/graphql').reply(200, graphqlOpenPullRequests); - global.gitAuthor = { - name: 'Renovate Bot', - email: 'renovate@whitesourcesoftware.com', - }; await github.initRepo({ repository: 'some/repo', } as any); diff --git a/lib/platform/github/index.ts b/lib/platform/github/index.ts index 7b3af04531fc11a556fbe365e47b5b2a7ae6a8b1..f45144e82a77c8d878c1526d5939dc5bef3c9a0e 100644 --- a/lib/platform/github/index.ts +++ b/lib/platform/github/index.ts @@ -420,8 +420,6 @@ export async function initRepo({ await git.initRepo({ ...config, url, - gitAuthorName: global.gitAuthor?.name, - gitAuthorEmail: global.gitAuthor?.email, }); const repoConfig: RepoResult = { defaultBranch: config.defaultBranch, diff --git a/lib/platform/gitlab/__snapshots__/index.spec.ts.snap b/lib/platform/gitlab/__snapshots__/index.spec.ts.snap index 2a334d52630101e52a81976f643e31a1bfe0736f..9fffb450cdf82f890966c7d9db267cccc2f24b43 100644 --- a/lib/platform/gitlab/__snapshots__/index.spec.ts.snap +++ b/lib/platform/gitlab/__snapshots__/index.spec.ts.snap @@ -2653,63 +2653,12 @@ Array [ ] `; -exports[`platform/gitlab/index initRepo should use ssh_url_to_repo if gitUrl is set to ssh 1`] = ` -Array [ - Object { - "headers": Object { - "accept": "application/json", - "accept-encoding": "gzip, deflate, br", - "authorization": "Bearer abc123", - "host": "gitlab.com", - "user-agent": "RenovateBot/0.0.0-semantic-release (https://github.com/renovatebot/renovate)", - }, - "method": "GET", - "url": "https://gitlab.com/api/v4/projects/some%2Frepo%2Fproject", - }, -] -`; - -exports[`platform/gitlab/index initRepo should use ssh_url_to_repo if gitUrl is set to ssh 2`] = ` -Array [ - Array [ - Object { - "cloneSubmodules": undefined, - "defaultBranch": "master", - "gitAuthorEmail": undefined, - "gitAuthorName": undefined, - "ignorePrAuthor": undefined, - "mergeMethod": "merge", - "repository": "some%2Frepo%2Fproject", - "url": "ssh://git@gitlab.com/some%2Frepo%2Fproject.git", - }, - ], -] -`; - -exports[`platform/gitlab/index initRepo should throw if ssh_url_to_repo is not present but gitUrl is set to ssh 1`] = ` -Array [ - Object { - "headers": Object { - "accept": "application/json", - "accept-encoding": "gzip, deflate, br", - "authorization": "Bearer abc123", - "host": "gitlab.com", - "user-agent": "RenovateBot/0.0.0-semantic-release (https://github.com/renovatebot/renovate)", - }, - "method": "GET", - "url": "https://gitlab.com/api/v4/projects/some%2Frepo%2Fproject", - }, -] -`; - exports[`platform/gitlab/index initRepo should fall back respecting when GITLAB_IGNORE_REPO_URL is set 1`] = ` Array [ Array [ Object { "cloneSubmodules": undefined, "defaultBranch": "master", - "gitAuthorEmail": undefined, - "gitAuthorName": undefined, "ignorePrAuthor": undefined, "mergeMethod": "merge", "repository": "some%2Frepo%2Fproject", @@ -2869,6 +2818,53 @@ Array [ ] `; +exports[`platform/gitlab/index initRepo should throw if ssh_url_to_repo is not present but gitUrl is set to ssh 1`] = ` +Array [ + Object { + "headers": Object { + "accept": "application/json", + "accept-encoding": "gzip, deflate, br", + "authorization": "Bearer abc123", + "host": "gitlab.com", + "user-agent": "RenovateBot/0.0.0-semantic-release (https://github.com/renovatebot/renovate)", + }, + "method": "GET", + "url": "https://gitlab.com/api/v4/projects/some%2Frepo%2Fproject", + }, +] +`; + +exports[`platform/gitlab/index initRepo should use ssh_url_to_repo if gitUrl is set to ssh 1`] = ` +Array [ + Object { + "headers": Object { + "accept": "application/json", + "accept-encoding": "gzip, deflate, br", + "authorization": "Bearer abc123", + "host": "gitlab.com", + "user-agent": "RenovateBot/0.0.0-semantic-release (https://github.com/renovatebot/renovate)", + }, + "method": "GET", + "url": "https://gitlab.com/api/v4/projects/some%2Frepo%2Fproject", + }, +] +`; + +exports[`platform/gitlab/index initRepo should use ssh_url_to_repo if gitUrl is set to ssh 2`] = ` +Array [ + Array [ + Object { + "cloneSubmodules": undefined, + "defaultBranch": "master", + "ignorePrAuthor": undefined, + "mergeMethod": "merge", + "repository": "some%2Frepo%2Fproject", + "url": "ssh://git@gitlab.com/some%2Frepo%2Fproject.git", + }, + ], +] +`; + exports[`platform/gitlab/index massageMarkdown(input) returns updated pr body 1`] = ` "https://github.com/foo/bar/issues/5 plus also [a link](https://github.com/foo/bar/issues/5 diff --git a/lib/platform/gitlab/index.ts b/lib/platform/gitlab/index.ts index 688437f3cc6d36dc4cb1125c10f599e45c08f30d..6fdbccf431239427a6a47aa243a0a81ea165187f 100644 --- a/lib/platform/gitlab/index.ts +++ b/lib/platform/gitlab/index.ts @@ -286,8 +286,6 @@ export async function initRepo({ await git.initRepo({ ...config, url, - gitAuthorName: global.gitAuthor?.name, - gitAuthorEmail: global.gitAuthor?.email, }); } catch (err) /* istanbul ignore next */ { logger.debug({ err }, 'Caught initRepo error'); diff --git a/lib/platform/index.ts b/lib/platform/index.ts index 5436884fda69edf11442b9fe30a03009a599750e..df48461baedd083b86d6d57eacf92d695bc4dc59 100644 --- a/lib/platform/index.ts +++ b/lib/platform/index.ts @@ -3,8 +3,7 @@ import type { AllConfig } from '../config/types'; import { PLATFORM_NOT_FOUND } from '../constants/error-messages'; import { logger } from '../logger'; import type { HostRule } from '../types'; -import { setNoVerify, setPrivateKey } from '../util/git'; -import { parseGitAuthor } from '../util/git/author'; +import { setGitAuthor, setNoVerify, setPrivateKey } from '../util/git'; import * as hostRules from '../util/host-rules'; import platforms from './api'; import type { Platform } from './types'; @@ -46,30 +45,15 @@ export async function initPlatform(config: AllConfig): Promise<AllConfig> { // TODO: types const platformInfo = await platform.initPlatform(config); const returnConfig: any = { ...config, ...platformInfo }; - let gitAuthor: string; // istanbul ignore else if (config?.gitAuthor) { logger.debug(`Using configured gitAuthor (${config.gitAuthor})`); - gitAuthor = config.gitAuthor; + returnConfig.gitAuthor = config.gitAuthor; } else if (platformInfo?.gitAuthor) { logger.debug(`Using platform gitAuthor: ${String(platformInfo.gitAuthor)}`); - gitAuthor = platformInfo.gitAuthor; - } else { - logger.debug( - 'Using default gitAuthor: Renovate Bot <renovate@whitesourcesoftware.com>' - ); - gitAuthor = 'Renovate Bot <renovate@whitesourcesoftware.com>'; - } - const gitAuthorParsed = parseGitAuthor(gitAuthor); - // istanbul ignore if - if (!gitAuthorParsed) { - throw new Error('Init: gitAuthor is not parsed as valid RFC5322 format'); + returnConfig.gitAuthor = platformInfo.gitAuthor; } - global.gitAuthor = { - name: gitAuthorParsed.name, - email: gitAuthorParsed.address, - }; - + setGitAuthor(returnConfig.gitAuthor); const platformRule: HostRule = { hostType: returnConfig.platform, matchHost: URL.parse(returnConfig.endpoint).hostname, diff --git a/lib/util/git/index.spec.ts b/lib/util/git/index.spec.ts index c9232b60f58fa9feb97730bfaf61b41ac0ad7245..36a3136e7453b0ad48dd54a76f68ca17d0a73e4b 100644 --- a/lib/util/git/index.spec.ts +++ b/lib/util/git/index.spec.ts @@ -3,6 +3,7 @@ import Git from 'simple-git'; import SimpleGit from 'simple-git/src/git'; import tmp from 'tmp-promise'; import { setGlobalConfig } from '../../config/global'; +import { CONFIG_VALIDATION } from '../../constants/error-messages'; import * as git from '.'; import { GitNoVerifyOption, setNoVerify } from '.'; @@ -73,10 +74,9 @@ describe('util/git/index', () => { setGlobalConfig({ localDir: tmpDir.path }); await git.initRepo({ url: origin.path, - gitAuthorName: 'Jest', - gitAuthorEmail: 'Jest@example.com', }); await git.setUserRepoConfig({ branchPrefix: 'renovate/' }); + git.setGitAuthor('Jest <Jest@example.com>'); setNoVerify([]); await git.syncGit(); // override some local git settings for better testing @@ -548,4 +548,9 @@ describe('util/git/index', () => { expect(res).toBe('test-extra-config-value'); }); }); + describe('setGitAuthor()', () => { + it('throws for invalid', () => { + expect(() => git.setGitAuthor('invalid')).toThrow(CONFIG_VALIDATION); + }); + }); }); diff --git a/lib/util/git/index.ts b/lib/util/git/index.ts index 5194853076ac0a82c82720ecd57957c5a4836488..2bc8597d3cb089bb794e6af4fc0c816870bd9268 100644 --- a/lib/util/git/index.ts +++ b/lib/util/git/index.ts @@ -24,6 +24,7 @@ import { logger } from '../../logger'; import { ExternalHostError } from '../../types/errors/external-host-error'; import { GitOptions, GitProtocol } from '../../types/git'; import { Limit, incLimitedValue } from '../../workers/global/limits'; +import { parseGitAuthor } from './author'; import { GitNoVerifyOption, getNoVerify } from './config'; import { configSigningKey, writePrivateKey } from './private-key'; @@ -44,8 +45,6 @@ interface StorageConfig { currentBranch?: string; url: string; extraCloneOpts?: GitOptions; - gitAuthorName?: string; - gitAuthorEmail?: string; cloneSubmodules?: boolean; } @@ -57,6 +56,8 @@ interface LocalConfig extends StorageConfig { branchIsModified: Record<string, boolean>; branchPrefix: string; ignoredAuthors: string[]; + gitAuthorName?: string; + gitAuthorEmail?: string; } // istanbul ignore next @@ -234,6 +235,21 @@ async function setBranchPrefix(branchPrefix: string): Promise<void> { } } +export function setGitAuthor(gitAuthor: string): void { + const gitAuthorParsed = parseGitAuthor( + gitAuthor || 'Renovate Bot <renovate@whitesourcesoftware.com>' + ); + if (!gitAuthorParsed) { + const error = new Error(CONFIG_VALIDATION); + error.validationSource = 'None'; + error.validationError = 'Invalid gitAuthor'; + error.validationMessage = `gitAuthor is not parsed as valid RFC5322 format: ${gitAuthor}`; + throw error; + } + config.gitAuthorName = gitAuthorParsed.name; + config.gitAuthorEmail = gitAuthorParsed.address; +} + export async function writeGitAuthor(): Promise<void> { const { gitAuthorName, gitAuthorEmail } = config; try {