diff --git a/lib/lifecycles/changelog.js b/lib/lifecycles/changelog.js
index 6d4ba990a..5bdd573ac 100644
--- a/lib/lifecycles/changelog.js
+++ b/lib/lifecycles/changelog.js
@@ -18,17 +18,38 @@ Changelog.START_OF_LAST_RELEASE_PATTERN = START_OF_LAST_RELEASE_PATTERN
module.exports = Changelog
+/**
+ * Front matter is only extracted and therefore retained in final output where Changelog "header" begins with #Changelog,
+ * e.g. meets Standard-Version (last release) or commit-and-tag-version(current) format
+ */
+function extractFrontMatter (oldContent) {
+ const headerStart = oldContent.indexOf('# Changelog')
+ return headerStart !== -1 || headerStart !== 0
+ ? oldContent.substring(0, headerStart)
+ : ''
+}
+
+/**
+ * find the position of the last release and remove header
+ */
+function extractChangelogBody (oldContent) {
+ const oldContentStart = oldContent.search(START_OF_LAST_RELEASE_PATTERN)
+ return oldContentStart !== -1
+ ? oldContent.substring(oldContentStart)
+ : oldContent
+}
+
function outputChangelog (args, newVersion) {
return new Promise((resolve, reject) => {
createIfMissing(args)
const header = args.header
- let oldContent = args.dryRun || args.releaseCount === 0 ? '' : fs.readFileSync(args.infile, 'utf-8')
- const oldContentStart = oldContent.search(START_OF_LAST_RELEASE_PATTERN)
- // find the position of the last release and remove header:
- if (oldContentStart !== -1) {
- oldContent = oldContent.substring(oldContentStart)
- }
+ const oldContent = args.dryRun || args.releaseCount === 0 ? '' : fs.readFileSync(args.infile, 'utf-8')
+
+ const oldContentBody = extractChangelogBody(oldContent)
+
+ const changelogFrontMatter = extractFrontMatter(oldContent)
+
let content = ''
const context = { version: newVersion }
const changelogStream = conventionalChangelog({
@@ -48,7 +69,7 @@ function outputChangelog (args, newVersion) {
changelogStream.on('end', function () {
checkpoint(args, 'outputting changes to %s', [args.infile])
if (args.dryRun) console.info(`\n---\n${chalk.gray(content.trim())}\n---\n`)
- else writeFile(args, args.infile, header + '\n' + (content + oldContent).replace(/\n+$/, '\n'))
+ else writeFile(args, args.infile, changelogFrontMatter + header + '\n' + (content + oldContentBody).replace(/\n+$/, '\n'))
return resolve()
})
})
diff --git a/test/core.spec.js b/test/core.spec.js
index ab097ba57..8b7f17c69 100644
--- a/test/core.spec.js
+++ b/test/core.spec.js
@@ -165,17 +165,73 @@ describe('cli', function () {
})
describe('CHANGELOG.md exists', function () {
- it('appends the new release above the last release, removing the old header (legacy format)', async function () {
+ it('appends the new release above the last release, removing the old header (legacy format), and does not retain any front matter', async function () {
+ const frontMatter =
+ '---\nstatus: new\n---\n'
mock({
bump: 'patch',
changelog: 'release 1.0.1\n',
- fs: { 'CHANGELOG.md': 'legacy header format\n' },
+ fs: { 'CHANGELOG.md': frontMatter + 'legacy header format\n' },
tags: ['v1.0.0']
})
await exec()
const content = fs.readFileSync('CHANGELOG.md', 'utf-8')
content.should.match(/1\.0\.1/)
content.should.not.match(/legacy header format/)
+ content.should.not.match(/---status: new---/)
+ })
+
+ it('appends the new release above the last release, replacing the old header (standard-version format) with header (new format), and retains any front matter', async function () {
+ const { header } = require('../defaults')
+
+ const standardVersionHeader =
+ '# Changelog\n\nAll notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.'
+
+ const frontMatter =
+ '---\nstatus: new\n---\n'
+
+ const changelog101 =
+ '### [1.0.1](/compare/v1.0.0...v1.0.1) (YYYY-MM-DD)\n\n\n### Bug Fixes\n\n* patch release ABCDEFXY\n'
+
+ const changelog100 =
+ '### [1.0.0](/compare/v0.0.1...v1.0.0) (YYYY-MM-DD)\n\n\n### Features\n\n* Version one feature set\n'
+
+ const initialChangelog = frontMatter + '\n' + standardVersionHeader + '\n' + changelog100
+
+ mock({
+ bump: 'patch',
+ changelog: changelog101,
+ fs: { 'CHANGELOG.md': initialChangelog },
+ tags: ['v1.0.0']
+ })
+ await exec()
+ const content = fs.readFileSync('CHANGELOG.md', 'utf-8')
+ content.should.equal(frontMatter + '\n' + header + '\n' + changelog101 + changelog100)
+ })
+
+ it('appends the new release above the last release, removing the old header (new format), and retains any front matter', async function () {
+ const { header } = require('../defaults')
+ const frontMatter =
+ '---\nstatus: new\n---\n'
+
+ const changelog101 =
+ '### [1.0.1](/compare/v1.0.0...v1.0.1) (YYYY-MM-DD)\n\n\n### Bug Fixes\n\n* patch release ABCDEFXY\n'
+
+ const changelog100 =
+ '### [1.0.0](/compare/v0.0.1...v1.0.0) (YYYY-MM-DD)\n\n\n### Features\n\n* Version one feature set\n'
+
+ const initialChangelog = frontMatter + '\n' + header + '\n' + changelog100
+
+ mock({
+ bump: 'patch',
+ changelog: changelog101,
+ fs: { 'CHANGELOG.md': initialChangelog },
+ tags: ['v1.0.0']
+ })
+ await exec()
+
+ const content = fs.readFileSync('CHANGELOG.md', 'utf-8')
+ content.should.equal(frontMatter + '\n' + header + '\n' + changelog101 + changelog100)
})
it('appends the new release above the last release, removing the old header (new format)', async function () {