diff --git a/lib/workers/repository/model/commit-message.ts b/lib/workers/repository/model/commit-message.ts index 0344e5b6471fc0ee8eb2f321ec58d84ae11edfb6..b909f5bc1d837da52d340f71af9147d1b35549ca 100644 --- a/lib/workers/repository/model/commit-message.ts +++ b/lib/workers/repository/model/commit-message.ts @@ -60,6 +60,10 @@ export abstract class CommitMessage { this._footer = this.normalizeInput(value); } + get subject(): string { + return this._subject; + } + set subject(value: string) { this._subject = this.normalizeInput(value); this._subject = this._subject?.replace( diff --git a/lib/workers/repository/model/semantic-commit-message.spec.ts b/lib/workers/repository/model/semantic-commit-message.spec.ts index db76829ba5b9571cfc7e7026a2e18e521462ba8b..57e74b1bfc56e8a73467a1c8f8f96fa21b3350d8 100644 --- a/lib/workers/repository/model/semantic-commit-message.spec.ts +++ b/lib/workers/repository/model/semantic-commit-message.spec.ts @@ -25,6 +25,15 @@ describe('workers/repository/model/semantic-commit-message', () => { expect(message.toString()).toBe('fix(scope): test'); }); + it('should transform to lowercase only first letter', () => { + const message = new SemanticCommitMessage(); + message.subject = 'Update My Org dependencies'; + message.type = 'fix'; + message.scope = 'deps '; + + expect(message.toString()).toBe('fix(deps): update My Org dependencies'); + }); + it('should create instance from string without scope', () => { const instance = SemanticCommitMessage.fromString('feat: ticket 123'); diff --git a/lib/workers/repository/updates/generate.spec.ts b/lib/workers/repository/updates/generate.spec.ts index 25ded125464fbf6aa4b92d7695446901abab7a88..a27b4015a589e6b29aa0ae585a702e14a8cbe85b 100644 --- a/lib/workers/repository/updates/generate.spec.ts +++ b/lib/workers/repository/updates/generate.spec.ts @@ -504,7 +504,7 @@ describe('workers/repository/updates/generate', () => { }), ]; const res = generateBranchConfig(branch); - expect(res.prTitle).toBe('chore(): update dependency some-dep to v1.2.0'); + expect(res.prTitle).toBe('chore: update dependency some-dep to v1.2.0'); }); it('scopes monorepo commits with nested package files using parent directory', () => { @@ -908,5 +908,17 @@ describe('workers/repository/updates/generate', () => { '`1.1.1` (+1)', ]); }); + + it('fixes commit message with body', () => { + const branch = [ + partial<BranchUpgradeConfig>({ + ...defaultConfig, + commitMessage: 'update to vv1.2.0', + commitBody: 'some body', + }), + ]; + const res = generateBranchConfig(branch); + expect(res.commitMessage).toBe('Update to v1.2.0\n\nsome body'); + }); }); }); diff --git a/lib/workers/repository/updates/generate.ts b/lib/workers/repository/updates/generate.ts index f3df4f73124313e503d41289d04ef7ce885deff3..777b77763ff0034542e420af5285adab767a85e8 100644 --- a/lib/workers/repository/updates/generate.ts +++ b/lib/workers/repository/updates/generate.ts @@ -5,11 +5,12 @@ import semver from 'semver'; import { mergeChildConfig } from '../../../config'; import { CONFIG_SECRETS_EXPOSED } from '../../../constants/error-messages'; import { logger } from '../../../logger'; -import { newlineRegex, regEx } from '../../../util/regex'; +import { regEx } from '../../../util/regex'; import { sanitize } from '../../../util/sanitize'; import * as template from '../../../util/template'; import type { BranchConfig, BranchUpgradeConfig } from '../../types'; -import { CommitMessage } from '../model/commit-message'; +import { CommitMessageFactory } from '../model/commit-message-factory'; +import { SemanticCommitMessage } from '../model/semantic-commit-message'; function isTypesGroup(branchUpgrades: BranchUpgradeConfig[]): boolean { return ( @@ -166,28 +167,24 @@ export function generateBranchConfig( } else if (semver.valid(toVersions[0])) { upgrade.isRange = false; } + const commitMessageFactory = new CommitMessageFactory(upgrade); + const commitMessage = commitMessageFactory.create(); // Use templates to generate strings - if (upgrade.semanticCommits === 'enabled' && !upgrade.commitMessagePrefix) { + if (SemanticCommitMessage.is(commitMessage)) { logger.trace('Upgrade has semantic commits enabled'); - let semanticPrefix = upgrade.semanticCommitType; - if (upgrade.semanticCommitScope) { - semanticPrefix += `(${template.compile( - upgrade.semanticCommitScope, - upgrade - )})`; - } - upgrade.commitMessagePrefix = CommitMessage.formatPrefix(semanticPrefix); - upgrade.toLowerCase = - regEx(/[A-Z]/).exec(upgrade.semanticCommitType) === null && - !upgrade.semanticCommitType.startsWith(':'); + commitMessage.scope = template.compile( + upgrade.semanticCommitScope, + upgrade + ); } // Compile a few times in case there are nested templates - upgrade.commitMessage = template.compile( + commitMessage.subject = template.compile( upgrade.commitMessage || '', upgrade ); - upgrade.commitMessage = template.compile(upgrade.commitMessage, upgrade); - upgrade.commitMessage = template.compile(upgrade.commitMessage, upgrade); + commitMessage.subject = template.compile(commitMessage.subject, upgrade); + commitMessage.subject = template.compile(commitMessage.subject, upgrade); + upgrade.commitMessage = commitMessage.formatSubject(); // istanbul ignore if if (upgrade.commitMessage !== sanitize(upgrade.commitMessage)) { logger.debug( @@ -196,23 +193,14 @@ export function generateBranchConfig( ); throw new Error(CONFIG_SECRETS_EXPOSED); } - upgrade.commitMessage = upgrade.commitMessage.trim(); // Trim exterior whitespace - upgrade.commitMessage = upgrade.commitMessage.replace(regEx(/\s+/g), ' '); // Trim extra whitespace inside string - upgrade.commitMessage = upgrade.commitMessage.replace( + commitMessage.subject = commitMessage.subject.replace( regEx(/to vv(\d)/), 'to v$1' ); - if (upgrade.toLowerCase) { - // We only need to lowercase the first line - const splitMessage = upgrade.commitMessage.split(newlineRegex); - splitMessage[0] = splitMessage[0].toLowerCase(); - upgrade.commitMessage = splitMessage.join('\n'); - } + upgrade.commitMessage = commitMessage.formatSubject(); if (upgrade.commitBody) { - upgrade.commitMessage = `${upgrade.commitMessage}\n\n${template.compile( - upgrade.commitBody, - upgrade - )}`; + commitMessage.body = template.compile(upgrade.commitBody, upgrade); + upgrade.commitMessage = commitMessage.toString(); } logger.trace(`commitMessage: ` + JSON.stringify(upgrade.commitMessage)); if (upgrade.prTitle) { @@ -234,7 +222,7 @@ export function generateBranchConfig( upgrade.prTitle = upgrade.prTitle.toLowerCase(); } } else { - [upgrade.prTitle] = upgrade.commitMessage.split(newlineRegex); + upgrade.prTitle = commitMessage.title; } upgrade.prTitle += upgrade.hasBaseBranches ? ' ({{baseBranch}})' : ''; if (upgrade.isGroup) {