Custom Partials with Lerna and conventional-changelog
Out of the box, conventional-changelog
is a great addition to any release flow. But in my case, I needed a few additions to graduate my release notes from “dev readable” to “stakeholder readable”.
While the old <type>(scope): subject
is often sufficient for a glancing developer, more than 72 characters is needed to really articulate a fix or feat to those with no context of a codebase.
In my case, I needed to accomplish a few things:
- Add the commit
body
to changelogs. - Automatically link to our third party project management software.
- Get my team onboard with:
git commit -m "type(scope): subject" -m "A nice message for stakeholders and devs" -m "#<issue id>"
Getting Started
I decided to go with conventional-changelog-conventionalcommits
since its parser will extract an issue/ticket number for you via the issuePrefixes
property.
While great, it doesn’t solve the issue of adding the commit body
out of the box. This requires an update to the commitPartial
property.
Let’s take a look at conventional-changelog-conventionalcommits
and how to use it as a function, and also use it with lerna
.
Basic Usage
Basic usage looks like this:
'use strict'
const config = require('conventional-changelog-conventionalcommits')module.exports = config({
"issuePrefixes": ["TEST-"],
"issueUrlFormat": "myBugTracker.com/{prefix}{id}"
})
It’s pretty straightforward.
- Create a file called
changelog-preset.config.js
. - Toss the code above into it.
- In your
lerna.json
, add"changelogPreset": "./changelog-preset.config.js"
.
Updating Templates
The problem we’re left with is the API itself doesn’t expose a way to change the commitPartial.hbs
template file (see here), so we have to modify the output of the config
function. Where it gets a bit confusing is the output object has two objects with different names that are identical:
{ conventionalChangelog, writerOpts, ...rest }
conventionalChangelog
and writerOps
.
For lerna
, we need to update properties on conventionalChangelog
to make a change to a changelog template.
This means we need to do something like this in our changelog-preset.config.js
:
const commitPartial = `// some hbs code`module.exports = config({
"issuePrefixes": ["TEST-"],
"issueUrlFormat": "myBugTracker.com/{prefix}{id}"
}).then((preset => {
preset.conventionalChangelog.writerOpts.commitPartial = commitPartial
return preset
})
Our handlebars (hbs) code will be a variation of the default template with the addition of body
, and we’ll inline it with a template literal:
const commitPartial = `
*{{#if scope}} **{{scope}}:**
{{~/if}} {{#if subject}}
{{~subject}}
{{~else}}
{{~header}}
{{~/if}}
{{~!-- commit link --}}{{~#if hash}} {{#if @root.linkReferences~}}
([{{shortHash}}]({{commitUrlFormat}}))
{{~else}}
{{~shortHash}}
{{~/if}}{{~/if}}
{{~!-- commit references --}}
{{~#if references~}}
, closes
{{~#each references}} {{#if @root.linkReferences~}}
[
{{~#if this.owner}}
{{~this.owner}}/
{{~/if}}
{{~this.repository}}{{this.prefix}}{{this.issue}}]({{issueUrlFormat}})
{{~else}}
{{~#if this.owner}}
{{~this.owner}}/
{{~/if}}
{{~this.repository}}{{this.prefix}}{{this.issue}}
{{~/if}}{{/each}}
{{~/if}}
{{#if body}}
<br/>
{{body}} // The addition
{{~/if}}`module.exports = config({
"issuePrefixes": ["TEST-"],
"issueUrlFormat": "myBugTracker.com/{prefix}{id}"
}).then((preset => {
preset.conventionalChangelog.writerOpts.commitPartial = commitPartial
return preset
})
Issue URL
If you have trouble getting the results you want from issueUrlFormat
, you can hardcode your issue URL, and grab the issue number from this.issue
:
const commitPartial = `
*{{#if scope}} **{{scope}}:**
// ...some code {{~this.repository}}{{this.prefix}}{{this.issue}}](https://some-tracker.com/project/{{this.issue}}) // ...some code
`
Lerna Config
In your lerna.json
, you’ll want something like this:
{
"packages": ["packages/*"],
"version": "independent",
"changelogPreset": "./changelog-preset.config.js",
"command": {
"version": {
"message": "chore(release): release",
}
}
}
Release Command
In your release pipeline, add the following:
npx lerna version --yes --conventional-commits --create-release github
That’s it! You’ll now have a commit body
in your release notes. Additional formatting to the template is completely up to you.