Skip to content

Commit

Permalink
Merge pull request #1308 from mikepenz/feature/nested_categories
Browse files Browse the repository at this point in the history
Introduce nested categorisation
  • Loading branch information
mikepenz committed Mar 1, 2024
2 parents 8e8a8fc + b7c5179 commit 86847cd
Show file tree
Hide file tree
Showing 17 changed files with 474 additions and 204 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -518,7 +518,7 @@ Regex replace pattern
"source": "TITLE",
"transformer": {
"pattern": "\\s*\\[([A-Z].{2,4}-.{2,5})\\][\\S\\s]*",
"target": ", [$1](https://corp.ticket-system.com/browse/$1)"
"target": "- [$1](https://corp.ticket-system.com/browse/$1)"
}
}
```
Expand Down
2 changes: 2 additions & 0 deletions __tests__/configuration.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import {clear} from '../src/transform'
import {mergeConfiguration, parseConfiguration, resolveConfiguration} from '../src/utils'

jest.setTimeout(180000)
clear()

it('Configurations are merged correctly', async () => {
const configurationJson = parseConfiguration(`{
Expand Down
2 changes: 2 additions & 0 deletions __tests__/gitea/releaseNotesBuilderGitea.test.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import {mergeConfiguration, resolveConfiguration} from '../../src/utils'
import {ReleaseNotesBuilder} from '../../src/releaseNotesBuilder'
import {GiteaRepository} from '../../src/repositories/GiteaRepository'
import {clear} from '../../src/transform'

jest.setTimeout(180000)
clear()

/**
* Before starting testing, you should manually clone the repository
Expand Down
2 changes: 2 additions & 0 deletions __tests__/gitea/releaseNotesBuilderPullGitea.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@ import {checkExportedData, mergeConfiguration, resolveConfiguration} from '../..
import {buildChangelog} from '../../src/transform'
import {pullData} from '../../src/pr-collector/prCollector'
import {GiteaRepository} from '../../src/repositories/GiteaRepository'
import {clear} from '../../src/transform'

jest.setTimeout(180000)
clear()

// load octokit instance
const enablePullData = false
Expand Down
2 changes: 2 additions & 0 deletions __tests__/main.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@ import * as path from 'path'
import * as process from 'process'
import * as cp from 'child_process'
import * as fs from 'fs'
import {clear} from '../src/transform'

jest.setTimeout(180000)
clear()

test('missing values should result in failure', () => {
expect.assertions(1)
Expand Down
26 changes: 14 additions & 12 deletions __tests__/regexUtils.test.ts
Original file line number Diff line number Diff line change
@@ -1,27 +1,29 @@
import { transformStringToValue, validateRegex } from '../src/pr-collector/regexUtils'
import { Regex } from '../src/pr-collector/types'
import {transformStringToValue, validateRegex} from '../src/pr-collector/regexUtils'
import {Regex} from '../src/pr-collector/types'
import {clear} from '../src/transform'

jest.setTimeout(180000)
clear()

it('Replace into target', async () => {
const regex: Regex = {
pattern: '.*(\\[Feature\\]|\\[Issue\\]).*',
target: '$1',
target: '$1'
}
const validatedRegex = validateRegex(regex)
expect(validateRegex).not.toBeNull()
expect(transformStringToValue("[Feature] TEST", validatedRegex!!)).toStrictEqual(`[Feature]`)
expect(transformStringToValue('[Feature] TEST', validatedRegex!!)).toStrictEqual(`[Feature]`)
})

it('Replace all into target', async () => {
const regex: Regex = {
pattern: '.*(\\[Feature\\]|\\[Issue\\]).*',
method: 'replaceAll',
target: '$1',
target: '$1'
}
const validatedRegex = validateRegex(regex)
expect(validateRegex).not.toBeNull()
expect(transformStringToValue("[Feature] TEST", validatedRegex!!)).toStrictEqual(`[Feature]`)
expect(transformStringToValue('[Feature] TEST', validatedRegex!!)).toStrictEqual(`[Feature]`)
})

it('Match without target', async () => {
Expand All @@ -31,27 +33,27 @@ it('Match without target', async () => {
}
const validatedRegex = validateRegex(regex)
expect(validateRegex).not.toBeNull()
expect(transformStringToValue("[Feature] TEST", validatedRegex!!)).toStrictEqual(`[Feature]`)
expect(transformStringToValue('[Feature] TEST', validatedRegex!!)).toStrictEqual(`[Feature]`)
})

it('Match into target', async () => {
const regex: Regex = {
pattern: '(?<label>\\[Feature\\]|\\[Issue\\])',
method: 'match',
target: '$1',
target: '$1'
}
const validatedRegex = validateRegex(regex)
expect(validateRegex).not.toBeNull()
expect(transformStringToValue("[Feature] TEST", validatedRegex!!)).toStrictEqual(`[Feature]`)
expect(transformStringToValue('[Feature] TEST', validatedRegex!!)).toStrictEqual(`[Feature]`)
})

it('Match into named group', async () => {
const regex: Regex = {
pattern: '(?<label>\\[Feature\\]|\\[Issue\\])',
method: 'match',
target: 'label',
target: 'label'
}
const validatedRegex = validateRegex(regex)
expect(validateRegex).not.toBeNull()
expect(transformStringToValue("[Feature] TEST", validatedRegex!!)).toStrictEqual(`[Feature]`)
})
expect(transformStringToValue('[Feature] TEST', validatedRegex!!)).toStrictEqual(`[Feature]`)
})
2 changes: 2 additions & 0 deletions __tests__/releaseNotesBuilder.test.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import {mergeConfiguration, resolveConfiguration} from '../src/utils'
import {ReleaseNotesBuilder} from '../src/releaseNotesBuilder'
import {GithubRepository} from '../src/repositories/GithubRepository'
import {clear} from '../src/transform'

jest.setTimeout(180000)
clear()

const token = process.env.GITHUB_TOKEN || ''
const githubRepository = new GithubRepository(token, undefined, '.')
Expand Down
2 changes: 2 additions & 0 deletions __tests__/releaseNotesBuilderPull.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@ import {checkExportedData, mergeConfiguration, resolveConfiguration} from '../sr
import {buildChangelog} from '../src/transform'
import {pullData} from '../src/pr-collector/prCollector'
import {GithubRepository} from '../src/repositories/GithubRepository'
import {clear} from '../src/transform'

jest.setTimeout(180000)
clear()

// load octokit instance
const enablePullData = false // if false -> use cache for data
Expand Down
13 changes: 7 additions & 6 deletions __tests__/tags.test.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import { TagResolver } from '../src/configuration'
import { validateRegex } from '../src/pr-collector/regexUtils'
import {TagResolver} from '../src/configuration'
import {validateRegex} from '../src/pr-collector/regexUtils'
import {filterTags, prepareAndSortTags, TagInfo, transformTags} from '../src/pr-collector/tags'
import {clear} from '../src/transform'

jest.setTimeout(180000)
clear()

it('Should order tags correctly using semver', async () => {
const tags: TagInfo[] = [
Expand Down Expand Up @@ -152,7 +154,6 @@ it('Should filter tags correctly using the regex (inverse)', async () => {
expect(filtered).toStrictEqual(`0.1.0-b01,1.0.0,1.0.0-a01,2.0.0,10.1.0,20.0.2`)
})


it('Should transform tags correctly using the regex', async () => {
const tags: TagInfo[] = [
{name: 'api-0.0.1', commit: ''},
Expand All @@ -168,13 +169,13 @@ it('Should transform tags correctly using the regex', async () => {
const tagResolver: TagResolver = {
method: 'non-existing-method',
transformer: {
pattern: '(api\-)?(.+)',
target: "$2"
pattern: '(api-)?(.+)',
target: '$2'
}
}

const transformer = validateRegex(tagResolver.transformer)
if(transformer != null) {
if (transformer != null) {
const transformed = transformTags(tags, transformer)
.map(function (tag) {
return tag.name
Expand Down
56 changes: 22 additions & 34 deletions __tests__/transform.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,11 @@ import {Configuration, DefaultConfiguration} from '../src/configuration'
import {PullRequestInfo} from '../src/pr-collector/pullRequests'
import {DefaultDiffInfo} from '../src/pr-collector/commits'
import {GithubRepository} from '../src/repositories/GithubRepository'
import {clear} from '../src/transform'
import {buildChangelogTest} from './utils'

jest.setTimeout(180000)
clear()

const configuration = Object.assign({}, DefaultConfiguration)
configuration.categories = [
Expand Down Expand Up @@ -150,7 +153,7 @@ it('Extract label from title, combined regex', async () => {
on_property: 'title'
}
]
expect(buildChangelogTest(configuration, mergedPullRequests)).toStrictEqual(
expect(buildChangelogTest(configuration, mergedPullRequests, repositoryUtils)).toStrictEqual(
`## 🚀 Features\n\n- [Feature][AB-1234] - this is a PR 1 title message\n - PR: #1\n- [Issue][Feature][AB-1234321] - this is a PR 3 title message\n - PR: #3\n\n## 🐛 Fixes\n\n- [Issue][AB-4321] - this is a PR 2 title message\n - PR: #2\n\n`
)
})
Expand All @@ -166,7 +169,7 @@ it('Extract label from title and body, combined regex', async () => {

let prs = Array.from(mergedPullRequests)
prs.push(pullRequestWithLabelInBody)
expect(buildChangelogTest(configuration, prs)).toStrictEqual(
expect(buildChangelogTest(configuration, prs, repositoryUtils)).toStrictEqual(
`## 🚀 Features\n\n- [Feature][AB-1234] - this is a PR 1 title message\n - PR: #1\n- [Issue][Feature][AB-1234321] - this is a PR 3 title message\n - PR: #3\n- label in body\n - PR: #5\n\n## 🐛 Fixes\n\n- [Issue][AB-4321] - this is a PR 2 title message\n - PR: #2\n\n`
)
})
Expand All @@ -184,7 +187,7 @@ it('Extract label from title, split regex', async () => {
on_property: 'title'
}
]
expect(buildChangelogTest(configuration, mergedPullRequests)).toStrictEqual(
expect(buildChangelogTest(configuration, mergedPullRequests, repositoryUtils)).toStrictEqual(
`## 🚀 Features\n\n- [Feature][AB-1234] - this is a PR 1 title message\n - PR: #1\n- [Issue][Feature][AB-1234321] - this is a PR 3 title message\n - PR: #3\n\n## 🐛 Fixes\n\n- [Issue][AB-4321] - this is a PR 2 title message\n - PR: #2\n- [Issue][Feature][AB-1234321] - this is a PR 3 title message\n - PR: #3\n\n`
)
})
Expand All @@ -202,7 +205,7 @@ it('Extract label from title, match', async () => {
method: 'match'
}
]
expect(buildChangelogTest(configuration, mergedPullRequests)).toStrictEqual(
expect(buildChangelogTest(configuration, mergedPullRequests, repositoryUtils)).toStrictEqual(
`## 🚀 Features\n\n- [Feature][AB-1234] - this is a PR 1 title message\n - PR: #1\n- [Issue][Feature][AB-1234321] - this is a PR 3 title message\n - PR: #3\n\n## 🐛 Fixes\n\n- [Issue][AB-4321] - this is a PR 2 title message\n - PR: #2\n- [Issue][Feature][AB-1234321] - this is a PR 3 title message\n - PR: #3\n\n`
)
})
Expand All @@ -215,7 +218,7 @@ it('Extract label from title, match multiple', async () => {
method: 'match'
}
]
expect(buildChangelogTest(configuration, mergedPullRequests)).toStrictEqual(
expect(buildChangelogTest(configuration, mergedPullRequests, repositoryUtils)).toStrictEqual(
`## 🚀 Features\n\n- [Feature][AB-1234] - this is a PR 1 title message\n - PR: #1\n- [Issue][Feature][AB-1234321] - this is a PR 3 title message\n - PR: #3\n\n## 🐛 Fixes\n\n- [Issue][AB-4321] - this is a PR 2 title message\n - PR: #2\n- [Issue][Feature][AB-1234321] - this is a PR 3 title message\n - PR: #3\n\n`
)
})
Expand All @@ -229,7 +232,7 @@ it('Extract label from title, match multiple, custon non matching label', async
on_empty: '[Other]'
}
]
expect(buildChangelogTest(configuration, mergedPullRequests)).toStrictEqual(
expect(buildChangelogTest(configuration, mergedPullRequests, repositoryUtils)).toStrictEqual(
`## 🚀 Features\n\n- [Feature][AB-1234] - this is a PR 1 title message\n - PR: #1\n- [Issue][Feature][AB-1234321] - this is a PR 3 title message\n - PR: #3\n\n## 🐛 Fixes\n\n- [Issue][AB-4321] - this is a PR 2 title message\n - PR: #2\n- [Issue][Feature][AB-1234321] - this is a PR 3 title message\n - PR: #3\n\n## 🧪 Others\n\n- [AB-404] - not found label\n - PR: #4\n\n`
)
})
Expand Down Expand Up @@ -370,7 +373,7 @@ it('Match multiple labels exhaustive for category', async () => {
exhaustive: true
}
]
expect(buildChangelogTest(customConfig, pullRequestsWithLabels)).toStrictEqual(
expect(buildChangelogTest(customConfig, pullRequestsWithLabels, repositoryUtils)).toStrictEqual(
`## 🚀 Features and 🐛 Issues\n\n- [ABC-1234] - this is a PR 3 title message\n - PR: #3\n\n`
)
})
Expand All @@ -383,7 +386,7 @@ it('Deduplicate duplicated PRs', async () => {
on_property: 'title',
method: 'match'
}
expect(buildChangelogTest(customConfig, pullRequestsWithLabels)).toStrictEqual(
expect(buildChangelogTest(customConfig, pullRequestsWithLabels, repositoryUtils)).toStrictEqual(
`## 🚀 Features\n\n- [ABC-1234] - this is a PR 3 title message\n - PR: #3\n\n## 🐛 Fixes\n\n- [ABC-4321] - this is a PR 2 title message\n - PR: #2\n- [ABC-1234] - this is a PR 3 title message\n - PR: #3\n\n`
)
})
Expand All @@ -397,7 +400,7 @@ it('Deduplicate duplicated PRs DESC', async () => {
on_property: 'title',
method: 'match'
}
expect(buildChangelogTest(customConfig, pullRequestsWithLabels)).toStrictEqual(
expect(buildChangelogTest(customConfig, pullRequestsWithLabels, repositoryUtils)).toStrictEqual(
`## 🚀 Features\n\n- [ABC-1234] - this is a PR 1 title message\n - PR: #1\n\n## 🐛 Fixes\n\n- [ABC-4321] - this is a PR 2 title message\n - PR: #2\n\n`
)
})
Expand All @@ -417,7 +420,7 @@ it('Reference PRs', async () => {
method: 'replace',
target: '$1'
}
expect(buildChangelogTest(customConfig, pullRequestsWithLabels)).toStrictEqual(`1 -- 2\n4 -- \n3 -- \n\n`)
expect(buildChangelogTest(customConfig, pullRequestsWithLabels, repositoryUtils)).toStrictEqual(`1 -- 2\n4 -- \n3 -- \n\n`)
})

it('Use empty_content for empty category', async () => {
Expand All @@ -433,7 +436,7 @@ it('Use empty_content for empty category', async () => {
labels: ['Feature']
}
]
expect(buildChangelogTest(customConfig, pullRequestsWithLabels)).toStrictEqual(
expect(buildChangelogTest(customConfig, pullRequestsWithLabels, repositoryUtils)).toStrictEqual(
`## 🚀 Features and 🐛 Issues\n\n- No PRs in this category\n\n## 🚀 Features\n\n- [ABC-1234] - this is a PR 1 title message\n - PR: #1\n- [ABC-1234] - this is a PR 3 title message\n - PR: #3\n\n`
)
})
Expand Down Expand Up @@ -504,7 +507,7 @@ it('Use exclude labels to not include a PR within a category.', async () => {
exclude_labels: ['Fix']
}
]
expect(buildChangelogTest(customConfig, pullRequestsWithLabels)).toStrictEqual(
expect(buildChangelogTest(customConfig, pullRequestsWithLabels, repositoryUtils)).toStrictEqual(
`## 🚀 Features and 🐛 Issues\n\n- [ABC-1234] - this is a PR 3 title message\n - PR: #3\n\n## 🚀 Features and/or 🐛 Issues But No 🐛 Fixes\n\n- [ABC-1234] - this is a PR 1 title message\n - PR: #1\n\n`
)
})
Expand Down Expand Up @@ -549,7 +552,7 @@ it('Extract custom placeholder from PR body and replace in global template', asy
'#{{CHANGELOG}}\n\n#{{C_PLACEHOLER_2[2]}}\n\n#{{C_PLACEHOLER_2[*]}}#{{C_PLACEHOLDER_1[7]}}#{{C_PLACEHOLER_2[1493]}}#{{C_PLACEHOLER_4[*]}}#{{C_PLACEHOLER_4[0]}}#{{C_PLACEHOLER_3[1]}}'
customConfig.pr_template = '#{{BODY}} ----> #{{C_PLACEHOLDER_1}}#{{C_PLACEHOLER_3}}'

expect(buildChangelogTest(customConfig, mergedPullRequests)).toStrictEqual(
expect(buildChangelogTest(customConfig, mergedPullRequests, repositoryUtils)).toStrictEqual(
`## 🚀 Features\n\nno magic body1 for this matter ----> - body1body1\nno magic body3 for this matter ----> - body3\n\n## 🐛 Fixes\n\nno magic body2 for this matter ----> - body2\nno magic body3 for this matter ----> - body3\n\n## 🧪 Others\n\nno magic body4 for this matter ----> - body4\n\n\n\n\n- ody3\n\n\n- ody1\n- ody2\n- ody3\n- ody4`
)
})
Expand All @@ -574,7 +577,7 @@ it('Use Rules to include a PR within a Category.', async () => {
exhaustive: true
}
]
expect(buildChangelogTest(customConfig, pullRequestsWithLabels)).toStrictEqual(
expect(buildChangelogTest(customConfig, pullRequestsWithLabels, repositoryUtils)).toStrictEqual(
`## 🚀 Features But No 🐛 Fixes and only merged with a title containing \`[ABC-1234]\`\n\n- [ABC-1234] - this is a PR 1 title message\n - PR: #1\n\n`
)
})
Expand All @@ -595,7 +598,9 @@ it('Use Rules to get all open PRs in a Category.', async () => {
]
}
]
expect(buildChangelogTest(customConfig, prs)).toStrictEqual(`## Open PRs only\n\n- Still pending open pull request\n - PR: #6\n\n`)
expect(buildChangelogTest(customConfig, prs, repositoryUtils)).toStrictEqual(
`## Open PRs only\n\n- Still pending open pull request\n - PR: #6\n\n`
)
})

it('Use Rules to get current open PR and merged categorised.', async () => {
Expand Down Expand Up @@ -633,7 +638,7 @@ it('Use Rules to get current open PR and merged categorised.', async () => {
}
]

expect(buildChangelogTest(customConfig, prs)).toStrictEqual(
expect(buildChangelogTest(customConfig, prs, repositoryUtils)).toStrictEqual(
`## 🚀 Features\n\n- [ABC-1234] - this is a PR 1 title message\n - PR: #1\n- Still pending open pull request (Current)\n - PR: #6\n- [ABC-1234] - this is a PR 3 title message\n - PR: #3\n\n## 🐛 Issues\n\n- [ABC-4321] - this is a PR 2 title message\n - PR: #2\n- [ABC-1234] - this is a PR 3 title message\n - PR: #3\n\n`
)
})
Expand Down Expand Up @@ -665,24 +670,7 @@ it('Use Rules to get all open PRs in one Category and merged categorised.', asyn
exhaustive: true
}
]
expect(buildChangelogTest(customConfig, prs)).toStrictEqual(
expect(buildChangelogTest(customConfig, prs, repositoryUtils)).toStrictEqual(
`## Open PRs only\n\n- Still pending open pull request\n - PR: #6\n\n## 🚀 Features and 🐛 Issues\n\n- [ABC-1234] - this is a PR 3 title message\n - PR: #3\n\n`
)
})

function buildChangelogTest(config: Configuration, prs: PullRequestInfo[]): string {
return buildChangelog(DefaultDiffInfo, prs, {
owner: 'mikepenz',
repo: 'test-repo',
fromTag: {name: '1.0.0'},
toTag: {name: '2.0.0'},
includeOpen: false,
failOnError: false,
fetchReviewers: false,
fetchReleaseInformation: false,
fetchReviews: false,
commitMode: false,
configuration: config,
repositoryUtils: repositoryUtils
})
}

0 comments on commit 86847cd

Please sign in to comment.