diff --git a/lib/workers/repository/model/commit-message.spec.ts b/lib/workers/repository/model/commit-message.spec.ts new file mode 100644 index 0000000000000000000000000000000000000000..9290af0bbabf45a6f949770e235e4b9b44aedddd --- /dev/null +++ b/lib/workers/repository/model/commit-message.spec.ts @@ -0,0 +1,58 @@ +import { getName } from '../../../../test/util'; +import { CommitMessage } from './commit-message'; + +describe(getName(), () => { + describe('CommitMessage', () => { + const TEST_CASES: ReadonlyArray< + [message: string, prefix: string | undefined, result: string] + > = [ + ['test', undefined, 'Test'], + ['test', '', 'Test'], + [' test ', ' ', 'Test'], + ['test', 'fix', 'fix: test'], + ['test', 'fix:', 'fix: test'], + ]; + + it('has colon character separator', () => { + expect(CommitMessage.SEPARATOR).toBe(':'); + }); + + it.each(TEST_CASES)( + 'given %p and %p as arguments, returns %p', + (message, prefix, result) => { + const commitMessage = new CommitMessage(message); + commitMessage.setCustomPrefix(prefix); + + expect(commitMessage.toString()).toEqual(result); + } + ); + + it('should handle not defined semantic prefix', () => { + const message = new CommitMessage('test'); + message.setSemanticPrefix(); + + expect(message.toString()).toBe('Test'); + }); + + it('should handle empty semantic prefix', () => { + const message = new CommitMessage('test'); + message.setSemanticPrefix(' ', ' '); + + expect(message.toString()).toBe('Test'); + }); + + it('should format sematic prefix', () => { + const message = new CommitMessage('test'); + message.setSemanticPrefix(' fix '); + + expect(message.toString()).toBe('fix: test'); + }); + + it('should format sematic prefix with scope', () => { + const message = new CommitMessage('test'); + message.setSemanticPrefix(' fix ', ' scope '); + + expect(message.toString()).toBe('fix(scope): test'); + }); + }); +}); diff --git a/lib/workers/repository/model/commit-message.ts b/lib/workers/repository/model/commit-message.ts new file mode 100644 index 0000000000000000000000000000000000000000..f567b5615e94a7d9164a1200c3debb6acb03aa39 --- /dev/null +++ b/lib/workers/repository/model/commit-message.ts @@ -0,0 +1,54 @@ +export class CommitMessage { + public static readonly SEPARATOR: string = ':'; + + private message: string; + + private prefix: string; + + constructor(message = '') { + this.setMessage(message); + } + + public static formatPrefix(prefix: string): string { + if (!prefix) { + return ''; + } + + if (prefix.endsWith(CommitMessage.SEPARATOR)) { + return prefix; + } + + return `${prefix}${CommitMessage.SEPARATOR}`; + } + + public setMessage(message: string): void { + this.message = message.trim(); + } + + public setCustomPrefix(prefix = ''): void { + this.prefix = prefix.trim(); + } + + public setSemanticPrefix(type = '', scope = ''): void { + this.prefix = type.trim(); + + if (scope.trim()) { + this.prefix += `(${scope.trim()})`; + } + } + + public toString(): string { + const prefix = CommitMessage.formatPrefix(this.prefix); + const message = this.formatMessage(); + + return [prefix, message].join(' ').trim(); + } + + private formatMessage(): string { + if (this.prefix) { + return this.message; + } + + return this.message.charAt(0).toUpperCase() + this.message.slice(1); + } +} diff --git a/lib/workers/repository/onboarding/branch/commit-message.ts b/lib/workers/repository/onboarding/branch/commit-message.ts new file mode 100644 index 0000000000000000000000000000000000000000..88c36c3b556058b73eb701b0e4259db729b4fee0 --- /dev/null +++ b/lib/workers/repository/onboarding/branch/commit-message.ts @@ -0,0 +1,41 @@ +import { RenovateConfig } from '../../../../config/types'; +import { CommitMessage } from '../../model/commit-message'; + +export class OnboardingCommitMessageFactory { + private readonly config: RenovateConfig; + + private readonly configFile: string; + + constructor(config: RenovateConfig, configFile: string) { + this.config = config; + this.configFile = configFile; + } + + create(): CommitMessage { + const { + commitMessagePrefix, + onboardingCommitMessage, + semanticCommitScope, + semanticCommitType, + } = this.config; + const commitMessage = new CommitMessage(); + + if (commitMessagePrefix) { + commitMessage.setCustomPrefix(commitMessagePrefix); + } else if (this.areSemanticCommitsEnabled()) { + commitMessage.setSemanticPrefix(semanticCommitType, semanticCommitScope); + } + + if (onboardingCommitMessage) { + commitMessage.setMessage(onboardingCommitMessage); + } else { + commitMessage.setMessage(`add ${this.configFile}`); + } + + return commitMessage; + } + + private areSemanticCommitsEnabled(): boolean { + return this.config.semanticCommits === 'enabled'; + } +} diff --git a/lib/workers/repository/onboarding/branch/create.spec.ts b/lib/workers/repository/onboarding/branch/create.spec.ts index decbee29aec66891cfd9cd872fdf5a1d10c8781a..3ea76b528a2f658e740a29a372c35e74c47fa0ad 100644 --- a/lib/workers/repository/onboarding/branch/create.spec.ts +++ b/lib/workers/repository/onboarding/branch/create.spec.ts @@ -1,6 +1,6 @@ import { RenovateConfig, getConfig, getName } from '../../../../../test/util'; import { commitFiles } from '../../../../util/git'; -import { COMMIT_MESSAGE_PREFIX_SEPARATOR } from '../../util/commit-message'; +import { CommitMessage } from '../../model/commit-message'; import { createOnboardingBranch } from './create'; jest.mock('../../../../util/git'); @@ -54,7 +54,7 @@ describe(getName(), () => { await createOnboardingBranch(config); expect(commitFiles).toHaveBeenCalledWith( buildExpectedCommitFilesArgument( - `${prefix}${COMMIT_MESSAGE_PREFIX_SEPARATOR} add renovate.json` + `${prefix}${CommitMessage.SEPARATOR} add renovate.json` ) ); }); @@ -67,7 +67,7 @@ describe(getName(), () => { await createOnboardingBranch(config); expect(commitFiles).toHaveBeenCalledWith( buildExpectedCommitFilesArgument( - `${prefix}${COMMIT_MESSAGE_PREFIX_SEPARATOR} ${message}` + `${prefix}${CommitMessage.SEPARATOR} ${message}` ) ); }); @@ -79,7 +79,7 @@ describe(getName(), () => { await createOnboardingBranch(config); expect(commitFiles).toHaveBeenCalledWith( buildExpectedCommitFilesArgument( - `${prefix}${COMMIT_MESSAGE_PREFIX_SEPARATOR} add renovate.json` + `${prefix}${CommitMessage.SEPARATOR} add renovate.json` ) ); }); @@ -92,7 +92,7 @@ describe(getName(), () => { await createOnboardingBranch(config); expect(commitFiles).toHaveBeenCalledWith( buildExpectedCommitFilesArgument( - `${prefix}${COMMIT_MESSAGE_PREFIX_SEPARATOR} ${message}` + `${prefix}${CommitMessage.SEPARATOR} ${message}` ) ); }); @@ -105,7 +105,7 @@ describe(getName(), () => { await createOnboardingBranch(config); expect(commitFiles).toHaveBeenCalledWith( buildExpectedCommitFilesArgument( - `${prefix}${COMMIT_MESSAGE_PREFIX_SEPARATOR} add renovate.json` + `${prefix}${CommitMessage.SEPARATOR} add renovate.json` ) ); }); @@ -116,7 +116,7 @@ describe(getName(), () => { await createOnboardingBranch(config); expect(commitFiles).toHaveBeenCalledWith( buildExpectedCommitFilesArgument( - `${prefix}${COMMIT_MESSAGE_PREFIX_SEPARATOR} add renovate.json` + `${prefix}${CommitMessage.SEPARATOR} add renovate.json` ) ); }); @@ -127,7 +127,7 @@ describe(getName(), () => { await createOnboardingBranch(config); expect(commitFiles).toHaveBeenCalledWith( buildExpectedCommitFilesArgument( - `${prefix}${COMMIT_MESSAGE_PREFIX_SEPARATOR} add ${config.onboardingConfigFileName}`, + `${prefix}${CommitMessage.SEPARATOR} add ${config.onboardingConfigFileName}`, config.onboardingConfigFileName ) ); @@ -139,7 +139,7 @@ describe(getName(), () => { await createOnboardingBranch(config); expect(commitFiles).toHaveBeenCalledWith( buildExpectedCommitFilesArgument( - `${prefix}${COMMIT_MESSAGE_PREFIX_SEPARATOR} add ${config.onboardingConfigFileName}`, + `${prefix}${CommitMessage.SEPARATOR} add ${config.onboardingConfigFileName}`, config.onboardingConfigFileName ) ); diff --git a/lib/workers/repository/onboarding/branch/create.ts b/lib/workers/repository/onboarding/branch/create.ts index e670134c6871484ae0a831cee38174c06bb9fa1a..c819f09bec2a847f798b00846f26d3897064f9b7 100644 --- a/lib/workers/repository/onboarding/branch/create.ts +++ b/lib/workers/repository/onboarding/branch/create.ts @@ -3,7 +3,7 @@ import { configFileNames } from '../../../../config/app-strings'; import type { RenovateConfig } from '../../../../config/types'; import { logger } from '../../../../logger'; import { commitFiles } from '../../../../util/git'; -import { formatCommitMessagePrefix } from '../../util/commit-message'; +import { OnboardingCommitMessageFactory } from './commit-message'; import { getOnboardingConfigContents } from './config'; const defaultConfigFile = configFileNames[0]; @@ -19,30 +19,11 @@ export async function createOnboardingBranch( ? config.onboardingConfigFileName : defaultConfigFile; - let commitMessagePrefix = ''; - if (config.commitMessagePrefix) { - commitMessagePrefix = config.commitMessagePrefix; - } else if (config.semanticCommits === 'enabled') { - commitMessagePrefix = config.semanticCommitType; - if (config.semanticCommitScope) { - commitMessagePrefix += `(${config.semanticCommitScope})`; - } - } - if (commitMessagePrefix) { - commitMessagePrefix = formatCommitMessagePrefix(commitMessagePrefix); - } - - let onboardingCommitMessage: string; - if (config.onboardingCommitMessage) { - onboardingCommitMessage = config.onboardingCommitMessage; - } else { - onboardingCommitMessage = `${ - commitMessagePrefix ? 'add' : 'Add' - } ${configFile}`; - } - - const commitMessage = - `${commitMessagePrefix} ${onboardingCommitMessage}`.trim(); + const commitMessageFactory = new OnboardingCommitMessageFactory( + config, + configFile + ); + const commitMessage = commitMessageFactory.create(); // istanbul ignore if if (getAdminConfig().dryRun) { @@ -57,6 +38,6 @@ export async function createOnboardingBranch( contents, }, ], - message: commitMessage, + message: commitMessage.toString(), }); } diff --git a/lib/workers/repository/onboarding/branch/rebase.ts b/lib/workers/repository/onboarding/branch/rebase.ts index 5080736251d3e8a4bce64b90fafdea811d76a066..82cd7d93fd7ca06e6a51f4f1877792118fd916ff 100644 --- a/lib/workers/repository/onboarding/branch/rebase.ts +++ b/lib/workers/repository/onboarding/branch/rebase.ts @@ -8,6 +8,7 @@ import { isBranchModified, isBranchStale, } from '../../../../util/git'; +import { OnboardingCommitMessageFactory } from './commit-message'; import { getOnboardingConfigContents } from './config'; const defaultConfigFile = (config: RenovateConfig): string => @@ -15,23 +16,6 @@ const defaultConfigFile = (config: RenovateConfig): string => ? config.onboardingConfigFileName : configFileNames[0]; -function getCommitMessage(config: RenovateConfig): string { - const configFile = defaultConfigFile(config); - let commitMessage: string; - // istanbul ignore if - if (config.semanticCommits === 'enabled') { - commitMessage = config.semanticCommitType; - if (config.semanticCommitScope) { - commitMessage += `(${config.semanticCommitScope})`; - } - commitMessage += ': '; - commitMessage += 'add ' + configFile; - } else { - commitMessage = 'Add ' + configFile; - } - return commitMessage; -} - export async function rebaseOnboardingBranch( config: RenovateConfig ): Promise<string | null> { @@ -52,7 +36,11 @@ export async function rebaseOnboardingBranch( } logger.debug('Rebasing onboarding branch'); // istanbul ignore next - const commitMessage = getCommitMessage(config); + const commitMessageFactory = new OnboardingCommitMessageFactory( + config, + configFile + ); + const commitMessage = commitMessageFactory.create(); // istanbul ignore if if (getAdminConfig().dryRun) { @@ -67,6 +55,6 @@ export async function rebaseOnboardingBranch( contents, }, ], - message: commitMessage, + message: commitMessage.toString(), }); } diff --git a/lib/workers/repository/updates/generate.ts b/lib/workers/repository/updates/generate.ts index e7e9d2b3adf14de782938b39612920195a5ca9e6..05ea64a7e548dbc396ee8fb2856779b00c05d258 100644 --- a/lib/workers/repository/updates/generate.ts +++ b/lib/workers/repository/updates/generate.ts @@ -7,7 +7,7 @@ import { logger } from '../../../logger'; import { sanitize } from '../../../util/sanitize'; import * as template from '../../../util/template'; import type { BranchConfig, BranchUpgradeConfig } from '../../types'; -import { formatCommitMessagePrefix } from '../util/commit-message'; +import { CommitMessage } from '../model/commit-message'; function isTypesGroup(branchUpgrades: BranchUpgradeConfig[]): boolean { return ( @@ -158,7 +158,7 @@ export function generateBranchConfig( upgrade )})`; } - upgrade.commitMessagePrefix = formatCommitMessagePrefix(semanticPrefix); + upgrade.commitMessagePrefix = CommitMessage.formatPrefix(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 deleted file mode 100644 index 6a263b014bb07f310455f0344bb8e35ca77767a4..0000000000000000000000000000000000000000 --- a/lib/workers/repository/util/commit-message.spec.ts +++ /dev/null @@ -1,41 +0,0 @@ -import { getName } from '../../../../test/util'; -import { - COMMIT_MESSAGE_PREFIX_SEPARATOR, - formatCommitMessagePrefix, -} from './commit-message'; - -describe(getName(), () => { - 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 deleted file mode 100644 index d84752f81a63b27c30063423470a29330ddebac2..0000000000000000000000000000000000000000 --- a/lib/workers/repository/util/commit-message.ts +++ /dev/null @@ -1,10 +0,0 @@ -export const COMMIT_MESSAGE_PREFIX_SEPARATOR = ':'; - -export const formatCommitMessagePrefix = ( - commitMessagePrefix: string -): string => - `${commitMessagePrefix}${ - commitMessagePrefix.endsWith(COMMIT_MESSAGE_PREFIX_SEPARATOR) - ? '' - : COMMIT_MESSAGE_PREFIX_SEPARATOR - }`;