Skip to content

Commit

Permalink
feat: make changelog groups configurable
Browse files Browse the repository at this point in the history
  • Loading branch information
lekterable committed May 2, 2020
1 parent a1736a2 commit a2ec46e
Show file tree
Hide file tree
Showing 7 changed files with 97 additions and 39 deletions.
2 changes: 1 addition & 1 deletion src/changelog.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ export const changelog = async (version, options, config) => {

if (!commits.length) throw new Error('No commits found since the last tag')

const grouped = groupCommits(commits)
const grouped = groupCommits(commits, config)
const changelog = generateChangelog(version, grouped, config)

if (!options.write) return process.stdout.write(changelog)
Expand Down
2 changes: 1 addition & 1 deletion src/changelog.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ describe('changelog', () => {
expect(getCommits).toBeCalledTimes(1)
expect(getCommits).toBeCalledWith(mockedTag)
expect(groupCommits).toBeCalledTimes(1)
expect(groupCommits).toBeCalledWith(mockedCommits)
expect(groupCommits).toBeCalledWith(mockedCommits, defaultConfig)
expect(generateChangelog).toBeCalledTimes(1)
expect(generateChangelog).toBeCalledWith(null, mockedGrouped, defaultConfig)
expect(generateReleased).not.toBeCalled()
Expand Down
4 changes: 4 additions & 0 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@ export * from './release'
export const defaultConfig = {
unreleasedFormat: '# Latest',
releaseFormat: '# %version%',
groups: [
['## Features', 'feat', 'feature'],
['## Fixes', 'fix']
],
lineFormat: '- %message% %hash%'
}

Expand Down
27 changes: 10 additions & 17 deletions src/utils/changelog.js
Original file line number Diff line number Diff line change
Expand Up @@ -49,23 +49,16 @@ export const generateChangelog = (version, groups, config) => {

const entries = Object.entries(group)

entries.sort().forEach(([title, commits]) => {
if (title === 'release') return

switch (title) {
case 'breaking':
groupChangelog += '## BREAKING\n\n'
break
case 'feat':
groupChangelog += '## Features\n\n'
break
case 'fix':
groupChangelog += '## Fixes\n\n'
break
default:
groupChangelog += '## Misc\n\n'
break
}
entries.sort().forEach(([type, commits]) => {
if (type === 'release') return

const matchingGroup = config.groups.find(([_, ...types]) =>
types.includes(type)
)

if (type === 'breaking') groupChangelog += '## BREAKING\n\n'
else if (!matchingGroup) groupChangelog += '## Misc\n\n'
else groupChangelog += `${matchingGroup[0]}\n\n`

return commits.forEach((commit, index) => {
const { message, hash } = getCommitDetails(commit)
Expand Down
15 changes: 13 additions & 2 deletions src/utils/changelog.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,15 @@ describe('changelog', () => {
})

it('should generate changelog with custom config', () => {
const config = { ...defaultConfig, unreleasedFormat: '## Unreleased' }
const config = {
...defaultConfig,
groups: [
['## Feat', 'feat', 'feature'],
['## Fix', 'fix'],
['## Custom', 'custom']
],
unreleasedFormat: '## Unreleased'
}
const mockedInput = [
{
breaking: [
Expand All @@ -100,6 +108,9 @@ describe('changelog', () => {
feat: [
'aa805ce71ee103965ce3db46d4f6ed2658efd08d feat: add option to write to local CHANGELOG file'
],
custom: [
'2ea04355c1e81c5088eeabc6e242fb1ade978524 custom: make changelog customizable'
],
misc: [
'bffc2f9e8da1c7ac133689bc9cd14494f3be08e3 refactor: extract line generating logic to function and promisify exec'
]
Expand All @@ -119,7 +130,7 @@ describe('changelog', () => {
}
]
const mockedOutput =
'## Unreleased\n\n## BREAKING\n\n- add new api b2f59019\n- deprecate function 2ea04355\n\n## Features\n\n- add option to write to local CHANGELOG file aa805ce7\n\n## Misc\n\n- extract line generating logic to function and promisify exec bffc2f9e\n\n# 0.1.0\n\n## Features\n\n- add execute release feature 4e02179c\n\n## Fixes\n\n- support other conventions b2f59019\n\n## Misc\n\n- update dependencies 4e02179c\n\n'
'## Unreleased\n\n## BREAKING\n\n- add new api b2f59019\n- deprecate function 2ea04355\n\n## Custom\n\n- make changelog customizable 2ea04355\n\n## Feat\n\n- add option to write to local CHANGELOG file aa805ce7\n\n## Misc\n\n- extract line generating logic to function and promisify exec bffc2f9e\n\n# 0.1.0\n\n## Feat\n\n- add execute release feature 4e02179c\n\n## Fix\n\n- support other conventions b2f59019\n\n## Misc\n\n- update dependencies 4e02179c\n\n'

expect(generateChangelog(null, mockedInput, config)).toBe(mockedOutput)
})
Expand Down
26 changes: 12 additions & 14 deletions src/utils/misc.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ export const execAsync = command =>
})
)

export const groupCommits = commits =>
export const groupCommits = (commits, config) =>
commits.reduce(
(grouped, commit) => {
const group = grouped[grouped.length - 1]
Expand All @@ -31,20 +31,18 @@ export const groupCommits = commits =>
return [...rest, { ...group, breaking: [...existing, commit] }]
}

switch (commitDetails.type) {
case 'feat': {
const existing = group.feat ? group.feat : []
return [...rest, { ...group, feat: [...existing, commit] }]
}
case 'fix': {
const existing = group.fix ? group.fix : []
return [...rest, { ...group, fix: [...existing, commit] }]
}
default: {
const existing = group.misc ? group.misc : []
return [...rest, { ...group, misc: [...existing, commit] }]
}
const matchingGroup = config.groups.find(([_, ...types]) =>
types.includes(commitDetails.type)
)

if (!matchingGroup) {
const existing = group.misc ? group.misc : []
return [...rest, { ...group, misc: [...existing, commit] }]
}

const key = matchingGroup[1]
const existing = group[key] ? group[key] : []
return [...rest, { ...group, [key]: [...existing, commit] }]
},
[{}]
)
Expand Down
60 changes: 56 additions & 4 deletions src/utils/misc.test.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { exec } from 'child_process'
import { defaultConfig } from '../'
import { groupCommits, isObjectEmpty, updateVersion } from './misc'

jest.mock('child_process', () => ({
Expand Down Expand Up @@ -36,7 +37,7 @@ describe('misc', () => {
]
}
]
const grouped = await groupCommits(mockedInput)
const grouped = await groupCommits(mockedInput, defaultConfig)

expect(grouped).toEqual(mockedOutput)
})
Expand Down Expand Up @@ -75,7 +76,58 @@ describe('misc', () => {
]
}
]
const grouped = await groupCommits(mockedInput)
const grouped = await groupCommits(mockedInput, defaultConfig)

expect(grouped).toEqual(mockedOutput)
})

it('should group commits with custom config', async () => {
const config = {
...defaultConfig,
groups: [
['## Feat', 'feat', 'feature'],
['## Fix', 'fix'],
['## Custom', 'custom']
]
}
const mockedInput = [
'b2f5901922505efbfb6dd684252e8df0cdffeeb2 chore!: generate changelog',
'2ea04355c1e81c5088eeabc6e242fb1ade978524 chore!: version releases',
'bffc2f9e8da1c7ac133689bc9cd14494f3be08e3 refactor: extract line generating logic to function and promisify exec',
'aa805ce71ee103965ce3db46d4f6ed2658efd08d feat: add option to write to local CHANGELOG file',
'b2f5901922505efbfb6dd684252e8df0cdffeeb2 custom: make changelog customizable',
'f2191200bf7b6e5eec3d61fcef9eb756e0129cfb chore(release): 0.1.0',
'b2f5901922505efbfb6dd684252e8df0cdffeeb2 fix: support other conventions',
'4e02179cae1234d7083036024080a3f25fcb52c2 feat: add execute release feature'
]
const mockedOutput = [
{
breaking: [
'b2f5901922505efbfb6dd684252e8df0cdffeeb2 chore!: generate changelog',
'2ea04355c1e81c5088eeabc6e242fb1ade978524 chore!: version releases'
],
feat: [
'aa805ce71ee103965ce3db46d4f6ed2658efd08d feat: add option to write to local CHANGELOG file'
],
custom: [
'b2f5901922505efbfb6dd684252e8df0cdffeeb2 custom: make changelog customizable'
],
misc: [
'bffc2f9e8da1c7ac133689bc9cd14494f3be08e3 refactor: extract line generating logic to function and promisify exec'
]
},
{
release:
'f2191200bf7b6e5eec3d61fcef9eb756e0129cfb chore(release): 0.1.0',
fix: [
'b2f5901922505efbfb6dd684252e8df0cdffeeb2 fix: support other conventions'
],
feat: [
'4e02179cae1234d7083036024080a3f25fcb52c2 feat: add execute release feature'
]
}
]
const grouped = await groupCommits(mockedInput, config)

expect(grouped).toEqual(mockedOutput)
})
Expand Down Expand Up @@ -106,7 +158,7 @@ describe('misc', () => {
]
}
]
const grouped = await groupCommits(mockedInput)
const grouped = await groupCommits(mockedInput, defaultConfig)

expect(grouped).toEqual(mockedOutput)
})
Expand All @@ -132,7 +184,7 @@ describe('misc', () => {
'f2191200bf7b6e5eec3d61fcef9eb756e0129cfb chore(release): 0.1.0'
}
]
const grouped = await groupCommits(mockedInput)
const grouped = await groupCommits(mockedInput, defaultConfig)

expect(grouped).toEqual(mockedOutput)
})
Expand Down

0 comments on commit a2ec46e

Please sign in to comment.