diff --git a/docs/usage/self-hosted-configuration.md b/docs/usage/self-hosted-configuration.md index 3a1f3ba379735ca5ae668d0d83576deb07470231..5d9d208e8ce076c8382437fea621121edd629437 100644 --- a/docs/usage/self-hosted-configuration.md +++ b/docs/usage/self-hosted-configuration.md @@ -110,6 +110,10 @@ Set this to `false` if (a) you configure Renovate entirely on the bot side (i.e. Note that this setting is independent of `branchPrefix`. For example, if you configure `branchPrefix` to be `renovate-` then you'd still have the onboarding PR created with branch `renovate/configure` until you configure `onboardingBranch=renovate-configure` or similar. If you have an existing Renovate installation and you change `onboardingBranch` then it's possible that you'll get onboarding PRs for repositories that had previously closed the onboarding PR unmerged. +## onboardingCommitMessage + +Note that if `commitMessagePrefix` or `semanticCommits` values are defined then they will be prepended to the commit message using the same logic that is used for adding them to non-onboarding commit messages. + ## onboardingConfig ## onboardingPrTitle diff --git a/lib/config/common.ts b/lib/config/common.ts index f09944becb39a2729bfb4f566389b52c31b619f9..8bce196e2b8bc18b3b03911bc657184fe1b26619 100644 --- a/lib/config/common.ts +++ b/lib/config/common.ts @@ -23,6 +23,7 @@ export interface RenovateSharedConfig { branchName?: string; manager?: string; commitMessage?: string; + commitMessagePrefix?: string; draftPR?: boolean; enabled?: boolean; enabledManagers?: string[]; @@ -86,6 +87,7 @@ export interface RenovateAdminConfig { onboarding?: boolean; onboardingBranch?: string; + onboardingCommitMessage?: string; onboardingPrTitle?: string; onboardingConfig?: RenovateSharedConfig; diff --git a/lib/config/definitions.ts b/lib/config/definitions.ts index 6a90038328671f5a85b34f69cb369e33d87fa252..c16b0d498c03b19aa11f9108f076c43f2550d5cc 100644 --- a/lib/config/definitions.ts +++ b/lib/config/definitions.ts @@ -140,6 +140,15 @@ const options: RenovateOptions[] = [ admin: true, cli: false, }, + { + name: 'onboardingCommitMessage', + description: + 'Change this value in order to override the default onboarding commit message.', + type: 'string', + default: null, + admin: true, + cli: false, + }, { name: 'onboardingPrTitle', description: diff --git a/lib/workers/repository/onboarding/branch/create.spec.ts b/lib/workers/repository/onboarding/branch/create.spec.ts new file mode 100644 index 0000000000000000000000000000000000000000..282a88965b1a0b9a1212159351d5307cd7c72820 --- /dev/null +++ b/lib/workers/repository/onboarding/branch/create.spec.ts @@ -0,0 +1,98 @@ +import { RenovateConfig, getConfig } from '../../../../../test/util'; +import { commitFiles } from '../../../../util/git'; +import { COMMIT_MESSAGE_PREFIX_SEPARATOR } from '../../util/commit-message'; +import { createOnboardingBranch } from './create'; + +jest.mock('../../../../util/git'); +jest.mock('./config', () => ({ + getOnboardingConfig: () => + JSON.stringify({ + foo: 'bar', + }), +})); + +const buildExpectedCommitFilesArgument = (message: string) => ({ + branchName: 'renovate/configure', + files: [ + { + name: 'renovate.json', + contents: '{"foo":"bar"}', + }, + ], + message, +}); + +describe('workers/repository/onboarding/branch', () => { + let config: RenovateConfig; + beforeEach(() => { + jest.clearAllMocks(); + config = getConfig(); + }); + describe('createOnboardingBranch', () => { + it('applies the default commit message', async () => { + await createOnboardingBranch(config); + expect(commitFiles).toHaveBeenCalledWith( + buildExpectedCommitFilesArgument('Add renovate.json') + ); + }); + it('applies supplied commit message', async () => { + const message = + 'We can Renovate if we want to, we can leave PRs in decline'; + config.onboardingCommitMessage = message; + await createOnboardingBranch(config); + expect(commitFiles).toHaveBeenCalledWith( + buildExpectedCommitFilesArgument(`${message}`) + ); + }); + describe('applies the commitMessagePrefix value', () => { + it('to the default commit message', async () => { + const prefix = 'RENOV-123'; + config.commitMessagePrefix = prefix; + await createOnboardingBranch(config); + expect(commitFiles).toHaveBeenCalledWith( + buildExpectedCommitFilesArgument( + `${prefix}${COMMIT_MESSAGE_PREFIX_SEPARATOR} add renovate.json` + ) + ); + }); + it('to the supplied commit message', async () => { + const prefix = 'RENOV-123'; + const message = + "Cause your deps need an update and if they dont update, well they're no deps of mine"; + config.commitMessagePrefix = prefix; + config.onboardingCommitMessage = message; + await createOnboardingBranch(config); + expect(commitFiles).toHaveBeenCalledWith( + buildExpectedCommitFilesArgument( + `${prefix}${COMMIT_MESSAGE_PREFIX_SEPARATOR} ${message}` + ) + ); + }); + }); + describe('applies semanticCommit prefix', () => { + it('to the default commit message', async () => { + const prefix = 'chore(deps)'; + config.semanticCommits = true; + await createOnboardingBranch(config); + expect(commitFiles).toHaveBeenCalledWith( + buildExpectedCommitFilesArgument( + `${prefix}${COMMIT_MESSAGE_PREFIX_SEPARATOR} add renovate.json` + ) + ); + }); + it('to the supplied commit message', async () => { + const prefix = 'chore(deps)'; + const message = + 'I say, we can update when we want to, a commit they will never mind'; + config.semanticCommits = true; + config.onboardingCommitMessage = message; + await createOnboardingBranch(config); + expect(commitFiles).toHaveBeenCalledWith( + buildExpectedCommitFilesArgument( + `${prefix}${COMMIT_MESSAGE_PREFIX_SEPARATOR} ${message}` + ) + ); + }); + }); + }); +}); diff --git a/lib/workers/repository/onboarding/branch/create.ts b/lib/workers/repository/onboarding/branch/create.ts index 615e332457ab41d072e50be8d9eb75c7c62712e0..1777fc57a1e4e251db3c9cd79281ef8176817e42 100644 --- a/lib/workers/repository/onboarding/branch/create.ts +++ b/lib/workers/repository/onboarding/branch/create.ts @@ -2,6 +2,7 @@ import { RenovateConfig } from '../../../../config'; import { configFileNames } from '../../../../config/app-strings'; import { logger } from '../../../../logger'; import { commitFiles } from '../../../../util/git'; +import { formatCommitMessagePrefix } from '../../util/commit-message'; import { getOnboardingConfig } from './config'; const defaultConfigFile = configFileNames[0]; @@ -12,18 +13,31 @@ export function createOnboardingBranch( logger.debug('createOnboardingBranch()'); const contents = getOnboardingConfig(config); logger.debug('Creating onboarding branch'); - let commitMessage; - // istanbul ignore if - if (config.semanticCommits) { - commitMessage = config.semanticCommitType; + + let commitMessagePrefix = ''; + if (config.commitMessagePrefix) { + commitMessagePrefix = config.commitMessagePrefix; + } else if (config.semanticCommits) { + commitMessagePrefix = config.semanticCommitType; if (config.semanticCommitScope) { - commitMessage += `(${config.semanticCommitScope})`; + commitMessagePrefix += `(${config.semanticCommitScope})`; } - commitMessage += ': '; - commitMessage += 'add ' + defaultConfigFile; + } + if (commitMessagePrefix) { + commitMessagePrefix = formatCommitMessagePrefix(commitMessagePrefix); + } + + let onboardingCommitMessage: string; + if (config.onboardingCommitMessage) { + onboardingCommitMessage = config.onboardingCommitMessage; } else { - commitMessage = 'Add ' + defaultConfigFile; + onboardingCommitMessage = `${ + commitMessagePrefix ? 'add' : 'Add' + } ${defaultConfigFile}`; } + + const commitMessage = `${commitMessagePrefix} ${onboardingCommitMessage}`.trim(); + // istanbul ignore if if (config.dryRun) { logger.info('DRY-RUN: Would commit files to onboarding branch'); diff --git a/lib/workers/repository/updates/generate.ts b/lib/workers/repository/updates/generate.ts index c3c652679387a7c93d2d896ddc2d2198b5526d76..e115b0a19469f18ffd53823356b932cb1b576b67 100644 --- a/lib/workers/repository/updates/generate.ts +++ b/lib/workers/repository/updates/generate.ts @@ -7,6 +7,7 @@ import { logger } from '../../../logger'; import { sanitize } from '../../../util/sanitize'; import * as template from '../../../util/template'; import { BranchConfig, BranchUpgradeConfig } from '../../common'; +import { formatCommitMessagePrefix } from '../util/commit-message'; function isTypesGroup(branchUpgrades: any[]): boolean { return ( @@ -181,8 +182,7 @@ export function generateBranchConfig( upgrade )})`; } - upgrade.commitMessagePrefix = semanticPrefix; - upgrade.commitMessagePrefix += semanticPrefix.endsWith(':') ? ' ' : ': '; + upgrade.commitMessagePrefix = formatCommitMessagePrefix(semanticPrefix); upgrade.toLowerCase = // eslint-disable-next-line @typescript-eslint/prefer-regexp-exec upgrade.semanticCommitType.match(/[A-Z]/) === null && diff --git a/lib/workers/repository/util/commit-message.spec.ts b/lib/workers/repository/util/commit-message.spec.ts new file mode 100644 index 0000000000000000000000000000000000000000..2e04be8f6ac0d086e1cd2d13cccf9ddba8d54077 --- /dev/null +++ b/lib/workers/repository/util/commit-message.spec.ts @@ -0,0 +1,40 @@ +import { + COMMIT_MESSAGE_PREFIX_SEPARATOR, + formatCommitMessagePrefix, +} from './commit-message'; + +describe('workers/repository/util/commit-message', () => { + describe('COMMIT_MESSAGE_PREFIX_END_CHARACTER', () => { + it('is a colon character', () => { + expect(COMMIT_MESSAGE_PREFIX_SEPARATOR).toBe(':'); + }); + }); + describe('formatCommitMessagePrefix', () => { + it.each([ + [ + 'adds a separator', + 'does not end', + 'RENOV-123', + `RENOV-123${COMMIT_MESSAGE_PREFIX_SEPARATOR}`, + ], + [ + 'does nothing', + 'ends', + `RENOV-123${COMMIT_MESSAGE_PREFIX_SEPARATOR}`, + `RENOV-123${COMMIT_MESSAGE_PREFIX_SEPARATOR}`, + ], + ])( + '%s when the prefix %s with a separator', + ( + expectedAction: string, + endingState: string, + commitMessagePrefix: string, + expectedPrefix: string + ) => { + expect(formatCommitMessagePrefix(commitMessagePrefix)).toBe( + expectedPrefix + ); + } + ); + }); +}); diff --git a/lib/workers/repository/util/commit-message.ts b/lib/workers/repository/util/commit-message.ts new file mode 100644 index 0000000000000000000000000000000000000000..014eadda43248c1b70e58ca8b41dfbfdd85961ac --- /dev/null +++ b/lib/workers/repository/util/commit-message.ts @@ -0,0 +1,11 @@ +export const COMMIT_MESSAGE_PREFIX_SEPARATOR = ':'; + +export const formatCommitMessagePrefix = ( + commitMessagePrefix: string +): string => { + return `${commitMessagePrefix}${ + commitMessagePrefix.endsWith(COMMIT_MESSAGE_PREFIX_SEPARATOR) + ? '' + : COMMIT_MESSAGE_PREFIX_SEPARATOR + }`; +};