Skip to content

Commit

Permalink
feat(version): provide custom format to include commit author fullname (
Browse files Browse the repository at this point in the history
  • Loading branch information
ghiscoding committed Jul 21, 2022
1 parent be39852 commit 1f5a94e
Show file tree
Hide file tree
Showing 8 changed files with 118 additions and 35 deletions.
2 changes: 1 addition & 1 deletion lerna.json
Expand Up @@ -11,7 +11,7 @@
"createRelease": "github",
"gitDryRun": false,
"syncWorkspaceLock": true,
"changelogIncludeCommitAuthor": true,
"changelogIncludeCommitAuthorFullname": " by <%a>",
"changelogHeaderMessage": "### Automate your Workspace Versions, Changelogs & Publish with [Lerna-Lite](https://github.com/ghiscoding/lerna-lite) 🚀",
"message": "chore(release): publish new version %v"
},
Expand Down
7 changes: 4 additions & 3 deletions packages/cli/src/cli-commands/cli-version-commands.ts
Expand Up @@ -63,11 +63,12 @@ export default {
requiresArg: true,
type: 'string',
},
'changelog-include-commit-author': {
'changelog-include-commit-author-fullname': {
describe:
"Specify if we want to include the commit author's name when using conventional-commits with changelog",
"Specify if we want to include the commit author's name, when using conventional-commits with changelog. We can optionally provide a custom message or else a default format will be used.",
group: 'Version Command Options:',
type: 'boolean',
requiresArg: false,
type: 'string',
},
'changelog-version-message': {
describe:
Expand Down
Expand Up @@ -418,7 +418,7 @@ describe('conventional-commits', () => {
`);
});

it('supports custom tagPrefix in fixed mode and include commit author', async () => {
it('supports custom tagPrefix in fixed mode and include commit author full name', async () => {
const cwd = await initFixture('fixed');

await gitTag(cwd, 'dragons-are-awesome1.0.0');
Expand All @@ -435,11 +435,11 @@ describe('conventional-commits', () => {

const [leafChangelog, rootChangelog] = await Promise.all([
updateChangelog(pkg1, 'fixed', {
changelogIncludeCommitAuthor: true,
changelogIncludeCommitAuthorFullname: true,
tagPrefix: 'dragons-are-awesome',
}),
updateChangelog({ location: cwd } as Package, 'root', {
changelogIncludeCommitAuthor: true,
changelogIncludeCommitAuthorFullname: true,
tagPrefix: 'dragons-are-awesome',
version: '1.0.1',
}),
Expand All @@ -451,15 +451,15 @@ describe('conventional-commits', () => {
### Bug Fixes
* A second commit for our CHANGELOG ([SHA](https://github.com/lerna/conventional-commits-fixed/commit/GIT_HEAD)) (@Tester-McPerson)
* A second commit for our CHANGELOG ([SHA](https://github.com/lerna/conventional-commits-fixed/commit/GIT_HEAD)) (Tester McPerson)
`);
expect(rootChangelog.newEntry.trimRight()).toMatchInlineSnapshot(`
## [1.0.1](/compare/dragons-are-awesome1.0.0...dragons-are-awesome1.0.1) (YYYY-MM-DD)
### Bug Fixes
* A second commit for our CHANGELOG ([SHA](https://github.com/lerna/conventional-commits-fixed/commit/GIT_HEAD)) (@Tester-McPerson)
* A second commit for our CHANGELOG ([SHA](https://github.com/lerna/conventional-commits-fixed/commit/GIT_HEAD)) (Tester McPerson)
`);

await gitAdd(cwd, pkg1.manifestLocation);
Expand All @@ -472,7 +472,7 @@ describe('conventional-commits', () => {
await gitCommit(cwd, 'fix: A third commit for our CHANGELOG');

const lastRootChangelog = await updateChangelog({ location: cwd } as Package, 'root', {
changelogIncludeCommitAuthor: true,
changelogIncludeCommitAuthorFullname: true,
tagPrefix: 'dragons-are-awesome',
version: '1.0.2',
});
Expand All @@ -484,7 +484,7 @@ describe('conventional-commits', () => {
### Bug Fixes
* A third commit for our CHANGELOG ([SHA](https://github.com/lerna/conventional-commits-fixed/commit/GIT_HEAD)) (@Tester-McPerson)
* A third commit for our CHANGELOG ([SHA](https://github.com/lerna/conventional-commits-fixed/commit/GIT_HEAD)) (Tester McPerson)
`);
});

Expand Down Expand Up @@ -656,7 +656,7 @@ describe('conventional-commits', () => {
`);
});

it('updates independent changelogs and include commit author', async () => {
it('updates independent changelogs and include commit author full name', async () => {
const cwd = await initFixture('independent');

await gitTag(cwd, 'package-1@1.0.0');
Expand All @@ -680,7 +680,7 @@ describe('conventional-commits', () => {

const opts = {
changelogPreset: 'conventional-changelog-angular',
changelogIncludeCommitAuthor: true,
changelogIncludeCommitAuthorFullname: true,
};
const [changelogOne, changelogTwo] = await Promise.all([
updateChangelog(pkg1, 'independent', opts),
Expand All @@ -693,15 +693,64 @@ describe('conventional-commits', () => {
### Bug Fixes
* **stuff:** changed ([SHA](https://github.com/lerna/conventional-commits-independent/commit/GIT_HEAD)) (@Tester-McPerson)
* **stuff:** changed ([SHA](https://github.com/lerna/conventional-commits-independent/commit/GIT_HEAD)) (Tester McPerson)
`);
expect(changelogTwo.newEntry.trimRight()).toMatchInlineSnapshot(`
# [1.1.0](/compare/package-2@1.0.0...package-2@1.1.0) (YYYY-MM-DD)
### Features
* **thing:** added ([SHA](https://github.com/lerna/conventional-commits-independent/commit/GIT_HEAD)) (@Tester-McPerson)
* **thing:** added ([SHA](https://github.com/lerna/conventional-commits-independent/commit/GIT_HEAD)) (Tester McPerson)
`);
});

it('updates independent changelogs and include commit author full name with a custom format when defined', async () => {
const cwd = await initFixture('independent');

await gitTag(cwd, 'package-1@1.0.0');
await gitTag(cwd, 'package-2@1.0.0');

const [pkg1, pkg2] = await Project.getPackages(cwd);

// make a change in package-1 and package-2
await pkg1.set('changed', 1).serialize();
await pkg2.set('changed', 2).serialize();

await gitAdd(cwd, pkg1.manifestLocation);
await gitCommit(cwd, 'fix(stuff): changed');

await gitAdd(cwd, pkg2.manifestLocation);
await gitCommit(cwd, 'feat(thing): added');

// update versions
await pkg1.set('version', '1.0.1').serialize();
await pkg2.set('version', '1.1.0').serialize();

const opts = {
changelogPreset: 'conventional-changelog-angular',
changelogIncludeCommitAuthorFullname: ' by <**%a**>',
};
const [changelogOne, changelogTwo] = await Promise.all([
updateChangelog(pkg1, 'independent', opts),
updateChangelog(pkg2, 'independent', opts),
]);

expect(changelogOne.newEntry.trimRight()).toMatchInlineSnapshot(`
## [1.0.1](/compare/package-1@1.0.0...package-1@1.0.1) (YYYY-MM-DD)
### Bug Fixes
* **stuff:** changed ([SHA](https://github.com/lerna/conventional-commits-independent/commit/GIT_HEAD)) by <**Tester McPerson**>
`);
expect(changelogTwo.newEntry.trimRight()).toMatchInlineSnapshot(`
# [1.1.0](/compare/package-2@1.0.0...package-2@1.1.0) (YYYY-MM-DD)
### Features
* **thing:** added ([SHA](https://github.com/lerna/conventional-commits-independent/commit/GIT_HEAD)) by <**Tester McPerson**>
`);
});
});
Expand Down
25 changes: 17 additions & 8 deletions packages/core/src/conventional-commits/update-changelog.ts
Expand Up @@ -26,8 +26,8 @@ export async function updateChangelog(
changelogPreset,
rootPath,
tagPrefix = 'v',
version = undefined,
changelogIncludeCommitAuthor = false,
version,
changelogIncludeCommitAuthorFullname,
changelogHeaderMessage = '',
changelogVersionMessage = '',
} = updateOptions;
Expand All @@ -53,7 +53,7 @@ export async function updateChangelog(
// we will later extract a defined token from the string, of ">>author=%an<<",
// and reformat the string to get a commit string that would add (@authorName) to the end of the commit string, ie:
// **deps:** update all non-major dependencies ([ed1db35](https://github.com/ghiscoding/lerna-lite/commit/ed1db35)) (@Renovate-Bot)
if (changelogIncludeCommitAuthor) {
if (changelogIncludeCommitAuthorFullname) {
gitRawCommitsOpts.format = '%B%n-hash-%n%H>>author=%an<<';
}

Expand Down Expand Up @@ -91,7 +91,9 @@ export async function updateChangelog(
readExistingChangelog(pkg),
]).then(([inputEntry, [changelogFileLoc, changelogContents]]) => {
// are we including commit author's name in changelog?
const newEntry = changelogIncludeCommitAuthor ? parseChangelogCommitAuthorName(inputEntry) : inputEntry;
const newEntry = changelogIncludeCommitAuthorFullname
? parseChangelogCommitAuthorFullName(inputEntry, changelogIncludeCommitAuthorFullname)
: inputEntry;

log.silly(type, 'writing new entry: %j', newEntry);

Expand Down Expand Up @@ -132,17 +134,24 @@ export async function updateChangelog(
* @param changelogEntry - changelog entry of a version being released which can contain multiple line entries
* @returns
*/
function parseChangelogCommitAuthorName(changelogEntry: string) {
function parseChangelogCommitAuthorFullName(changelogEntry: string, commitAuthorFullnameMessage?: string | boolean) {
// to transform the string into what we want, we need to move the substring outside of the url and remove extra search tokens
// from this:
// "...ed1db35>>author=Renovate Bot<<))"
// into this:
// "...ed1db35)) (@Renovate-Bot)"
// "...ed1db35)) (Renovate-Bot)"
// or as a custom message like this " by **%a**" into this:
// "...ed1db35)) by **Renovate-Bot**"
return changelogEntry.replace(
/(.*)(>>author=)(.*)(<<)(.*)/g,
(_: string, lineStart: string, _tokenStart?: string, author?: string, _tokenEnd?: string, lineEnd?: string) => {
(_: string, lineStart: string, _tokenStart?: string, authorName?: string, _tokenEnd?: string, lineEnd?: string) => {
// rebuild the commit string, we'll also replace any whitespaces to hypen in author's name to make it a valid "@" user ref
return `${lineStart}${lineEnd || ''} (@${author?.replace(/\s/g, '-') ?? ''})`;
const commitMsg = `${lineStart}${lineEnd || ''}`;
const authorMsg =
typeof commitAuthorFullnameMessage === 'string'
? commitAuthorFullnameMessage.replace(/%a/g, authorName || '')
: ` (${authorName})`;
return commitMsg + authorMsg;
}
);
}
12 changes: 9 additions & 3 deletions packages/core/src/models/command-options.ts
Expand Up @@ -189,10 +189,16 @@ export interface VersionCommandOption {
/** Add a custom message at the top of your "changelog.md" which is located in the root of your project. This option only works when using --conventional-commits. */
changelogHeaderMessage?: string;

/** Specify if we want to include the commit author's name when using conventional-commits with changelog */
changelogIncludeCommitAuthor?: boolean;
/**
* Specify if we want to include the commit author's name, when using conventional-commits with changelog.
* We can optionally provide a custom message or else a default format will be used.
*/
changelogIncludeCommitAuthorFullname?: boolean | string;

/** Add a custom message as a prefix to each new version in your "changelog.md" which is located in the root of your project. This option only works when using --conventional-commits. */
/**
* Add a custom message as a prefix to each new version in your "changelog.md" which is located in the root of your project.
* This option only works when using --conventional-commits.
*/
changelogVersionMessage?: string;

/** Defaults 'angular', custom conventional-changelog preset. */
Expand Down
2 changes: 1 addition & 1 deletion packages/core/src/models/interfaces.ts
Expand Up @@ -74,7 +74,7 @@ export interface UpdateChangelogOption {
changelogHeaderMessage?: string;
changelogVersionMessage?: string;
changelogPreset?: string;
changelogIncludeCommitAuthor?: boolean;
changelogIncludeCommitAuthorFullname?: boolean | string;
rootPath?: string;
tagPrefix?: string;
version?: string;
Expand Down
30 changes: 24 additions & 6 deletions packages/version/README.md
Expand Up @@ -76,7 +76,7 @@ Running `lerna version --conventional-commits` without the above flags will rele
- [`--conventional-commits`](#--conventional-commits)
- [`--conventional-graduate`](#--conventional-graduate)
- [`--conventional-prerelease`](#--conventional-prerelease)
- [`--changelog-include-commit-author`](#--changelog-include-commit-author) (new)
- [`--changelog-include-commit-author-fullname [msg]`](#--changelog-include-commit-author-fullname-msg) (new)
- [`--changelog-header-message <msg>`](#--changelog-header-message-msg) (new)
- [`--changelog-version-message <msg>`](#--changelog-version-message-msg) (new)
- [`--create-release <type>`](#--create-release-type)
Expand Down Expand Up @@ -230,16 +230,34 @@ lerna version --conventional-commits --conventional-prerelease

When run with this flag, `lerna version` will release with prerelease versions the specified packages (comma-separated) or all packages using `*`. Releases all unreleased changes as pre(patch/minor/major/release) by prefixing the version recommendation from `conventional-commits` with `pre`, eg. if present changes include a feature commit, the recommended bump will be `minor`, so this flag will result in a `preminor` release. If changes are present for packages that are not specified (if specifying packages), or for packages that are already in prerelease, those packages will be versioned as they normally would using `--conventional-commits`.

### `--changelog-include-commit-author`
Specify if we want to include the commit author's name, at the end of each commit entry, when using `--conventional-commits` with changelogs.
### `--changelog-include-commit-author-fullname [msg]`
Specify if we want to include the git commit author's name, at the end of each changelog commit entry, this is only available when using `--conventional-commits` with changelogs. The default format will append the author's name at the end of each commit entry and wrapped in `()`, for exampe "feat: commit message (Author Name)". We could also use a custom format by providing the `%a` token. Note that in every case, the author's name will always be appended as a suffix to each changelog commit entry.

> **Note** that the author name is the name that was given in the user's Git config, refer to [Git Configuration](https://www.git-scm.com/book/en/v2/Customizing-Git-Git-Configuration) for more info. In other words, this is **not** the same as a GitHub login username.
```sh
lerna version --conventional-commits --changelog-include-commit-author-fullname
```

See below for a sample of a changelog entry with the author's full name (note the url was shorten up for simplicity)
#### Default Format
The default format will append the author's name (wrapped in `()`) to the end of the commit message

```sh
lerna version --conventional-commits --changelog-include-commit-author
* **deps:** update dependency git-url-parse to v12 ([978bf36](https://github.com/ghiscoding/lerna-lite/commit/978bf36)) (Renovate Bot)
```

See below for a sample of a changelog entry with author (note the url was shorten up for simplicity)
#### Custom Format
If we want to provide a default format, we can do so by using the `%a` token

```sh
lerna version --conventional-commits --changelog-include-commit-author-fullname " by _%a_"
```

will show the following (the use of `_` in this case would display the name in italic)

```sh
* **deps:** update dependency git-url-parse to v12 ([978bf36](https://github.com/ghiscoding/lerna-lite/commit/978bf36)) (@Renovate-Bot)
* **deps:** update dependency git-url-parse to v12 ([978bf36](https://github.com/ghiscoding/lerna-lite/commit/978bf36)) by _Renovate Bot_
```

### `--changelog-header-message <msg>`
Expand Down
4 changes: 2 additions & 2 deletions packages/version/src/version-command.ts
Expand Up @@ -601,7 +601,7 @@ export class VersionCommand extends Command<VersionCommandOption> {
changelogPreset,
rootPath,
tagPrefix: this.tagPrefix,
changelogIncludeCommitAuthor: this.options.changelogIncludeCommitAuthor,
changelogIncludeCommitAuthorFullname: this.options.changelogIncludeCommitAuthorFullname,
changelogHeaderMessage: this.options.changelogHeaderMessage,
changelogVersionMessage: this.options.changelogVersionMessage,
}).then(({ logPath, newEntry }) => {
Expand Down Expand Up @@ -683,7 +683,7 @@ export class VersionCommand extends Command<VersionCommandOption> {
rootPath,
tagPrefix: this.tagPrefix,
version: this.globalVersion,
changelogIncludeCommitAuthor: this.options.changelogIncludeCommitAuthor,
changelogIncludeCommitAuthorFullname: this.options.changelogIncludeCommitAuthorFullname,
changelogHeaderMessage: this.options.changelogHeaderMessage,
changelogVersionMessage: this.options.changelogVersionMessage,
}).then(({ logPath, newEntry }) => {
Expand Down

0 comments on commit 1f5a94e

Please sign in to comment.