Skip to content

Commit

Permalink
Add a collapse-after option for categories (#1095)
Browse files Browse the repository at this point in the history
Co-authored-by: Joseph Petersen <josephp90@gmail.com>
  • Loading branch information
robbinjanssen and jetersen committed Mar 7, 2022
1 parent 29e5df2 commit 3cbe8cc
Show file tree
Hide file tree
Showing 8 changed files with 208 additions and 22 deletions.
10 changes: 10 additions & 0 deletions README.md
Expand Up @@ -251,6 +251,16 @@ Pull requests with the label "feature" or "fix" will now be grouped together:
Adding such labels to your PRs can be automated by using the embedded Autolabeler functionality (see below),
[PR Labeler](https://github.com/TimonVS/pr-labeler-action) or [Probot Auto Labeler](https://github.com/probot/autolabeler).

Optionally you can add a `collapse-after` entry to your category item, if the category has more than the defined `collapse-after` pull requests then it will show all pull requests collapsed for that category. Append the `collapse-after` integer to your category as following:

```yml
categories:
- title: '⬆️ Dependencies'
collapse-after: 3
labels:
- 'dependencies'
```

## Exclude Pull Requests

With the `exclude-labels` option you can exclude pull requests from the release notes using labels. For example, append the following to your `.github/release-drafter.yml` file:
Expand Down
48 changes: 37 additions & 11 deletions dist/index.js
Expand Up @@ -129297,17 +129297,17 @@ const categorizePullRequests = (pullRequests, config) => {
.filter(getFilterIncludedPullRequests(includeLabels))
.filter((pullRequest) => filterUncategorizedPullRequests(pullRequest))

categorizedPullRequests.map((category) => {
filteredPullRequests.map((pullRequest) => {
for (const category of categorizedPullRequests) {
for (const pullRequest of filteredPullRequests) {
// lets categorize some pull request based on labels
// note that having the same label in multiple categories
// then it is intended to "duplicate" the pull request into each category
const labels = pullRequest.labels.nodes
if (labels.some((label) => category.labels.includes(label.name))) {
category.pullRequests.push(pullRequest)
}
})
})
}
}

return [uncategorizedPullRequests, categorizedPullRequests]
}
Expand Down Expand Up @@ -129356,17 +129356,42 @@ const generateChangeLog = (mergedPullRequests, config) => {
changeLog.push(pullRequestToString(uncategorizedPullRequests), '\n\n')
}

categorizedPullRequests.map((category, index) => {
if (category.pullRequests.length > 0) {
for (const [index, category] of categorizedPullRequests.entries()) {
if (category.pullRequests.length === 0) {
continue
}

// Add the category title to the changelog.
changeLog.push(
template(config['category-template'], { $TITLE: category.title }),
'\n\n'
)

// Define the pull requests into a single string.
const pullRequestString = pullRequestToString(category.pullRequests)

// Determine the collapse status.
const shouldCollapse =
category['collapse-after'] !== 0 &&
category.pullRequests.length > category['collapse-after']

// Add the pull requests to the changelog.
if (shouldCollapse) {
changeLog.push(
template(config['category-template'], { $TITLE: category.title }),
'<details>',
'\n',
`<summary>${category.pullRequests.length} changes</summary>`,
'\n\n',
pullRequestToString(category.pullRequests)
pullRequestString,
'\n',
'</details>'
)

if (index + 1 !== categorizedPullRequests.length) changeLog.push('\n\n')
} else {
changeLog.push(pullRequestString)
}
})

if (index + 1 !== categorizedPullRequests.length) changeLog.push('\n\n')
}

return changeLog.join('').trim()
}
Expand Down Expand Up @@ -129661,6 +129686,7 @@ const schema = (context) => {
Joi.object()
.keys({
title: Joi.string().required(),
'collapse-after': Joi.number().integer().min(0).default(0),
label: Joi.string(),
labels: Joi.array().items(Joi.string()).single().default([]),
})
Expand Down
47 changes: 36 additions & 11 deletions lib/releases.js
Expand Up @@ -182,17 +182,17 @@ const categorizePullRequests = (pullRequests, config) => {
.filter(getFilterIncludedPullRequests(includeLabels))
.filter((pullRequest) => filterUncategorizedPullRequests(pullRequest))

categorizedPullRequests.map((category) => {
filteredPullRequests.map((pullRequest) => {
for (const category of categorizedPullRequests) {
for (const pullRequest of filteredPullRequests) {
// lets categorize some pull request based on labels
// note that having the same label in multiple categories
// then it is intended to "duplicate" the pull request into each category
const labels = pullRequest.labels.nodes
if (labels.some((label) => category.labels.includes(label.name))) {
category.pullRequests.push(pullRequest)
}
})
})
}
}

return [uncategorizedPullRequests, categorizedPullRequests]
}
Expand Down Expand Up @@ -241,17 +241,42 @@ const generateChangeLog = (mergedPullRequests, config) => {
changeLog.push(pullRequestToString(uncategorizedPullRequests), '\n\n')
}

categorizedPullRequests.map((category, index) => {
if (category.pullRequests.length > 0) {
for (const [index, category] of categorizedPullRequests.entries()) {
if (category.pullRequests.length === 0) {
continue
}

// Add the category title to the changelog.
changeLog.push(
template(config['category-template'], { $TITLE: category.title }),
'\n\n'
)

// Define the pull requests into a single string.
const pullRequestString = pullRequestToString(category.pullRequests)

// Determine the collapse status.
const shouldCollapse =
category['collapse-after'] !== 0 &&
category.pullRequests.length > category['collapse-after']

// Add the pull requests to the changelog.
if (shouldCollapse) {
changeLog.push(
template(config['category-template'], { $TITLE: category.title }),
'<details>',
'\n',
`<summary>${category.pullRequests.length} changes</summary>`,
'\n\n',
pullRequestToString(category.pullRequests)
pullRequestString,
'\n',
'</details>'
)

if (index + 1 !== categorizedPullRequests.length) changeLog.push('\n\n')
} else {
changeLog.push(pullRequestString)
}
})

if (index + 1 !== categorizedPullRequests.length) changeLog.push('\n\n')
}

return changeLog.join('').trim()
}
Expand Down
1 change: 1 addition & 0 deletions lib/schema.js
Expand Up @@ -115,6 +115,7 @@ const schema = (context) => {
Joi.object()
.keys({
title: Joi.string().required(),
'collapse-after': Joi.number().integer().min(0).default(0),
label: Joi.string(),
labels: Joi.array().items(Joi.string()).single().default([]),
})
Expand Down
5 changes: 5 additions & 0 deletions schema.json
Expand Up @@ -211,6 +211,11 @@
"title": {
"type": "string"
},
"collapse-after": {
"default": 0,
"type": "integer",
"minimum": 0
},
"label": {
"type": "string"
},
Expand Down
@@ -0,0 +1,18 @@
template: |
# What's Changed
$CHANGES
categories:
- title: 🚀 All the things!
collapse-after: 3
labels:
- feature
- enhancement
- fix
- bugfix
- bug
- sentry
- skip-changelog
- title: 👻 Maintenance
label: chore
55 changes: 55 additions & 0 deletions test/index.test.js
Expand Up @@ -1198,6 +1198,61 @@ describe('release-drafter', () => {

expect.assertions(1)
})

it('categorizes pull requests with a collapsed category', async () => {
getConfigMock('config-with-categories-with-collapse-after.yml')

nock('https://api.github.com')
.get('/repos/toolmantim/release-drafter-test-project/releases')
.query(true)
.reply(200, [releasePayload])

nock('https://api.github.com')
.post('/graphql', (body) =>
body.query.includes('query findCommitsWithAssociatedPullRequests')
)
.reply(200, graphqlCommitsMergeCommit)

nock('https://api.github.com')
.post(
'/repos/toolmantim/release-drafter-test-project/releases',
(body) => {
expect(body).toMatchInlineSnapshot(`
Object {
"body": "# What's Changed
* Update dependencies (#4) @TimonVS
## 🚀 All the things!
<details>
<summary>4 changes</summary>
* Add documentation (#5) @TimonVS
* Bug fixes (#3) @TimonVS
* Add big feature (#2) @TimonVS
* 👽 Add alien technology (#1) @TimonVS
</details>
",
"draft": true,
"name": "",
"prerelease": false,
"tag_name": "",
"target_commitish": "refs/heads/master",
}
`)
return true
}
)
.reply(200, releasePayload)

await probot.receive({
name: 'push',
payload: pushPayload,
})

expect.assertions(1)
})
})

describe('with exclude-labels config', () => {
Expand Down
46 changes: 46 additions & 0 deletions test/releases.test.js
Expand Up @@ -187,5 +187,51 @@ describe('releases', () => {
* Adds @<!---->nullable annotations to the 1\\\\*1+2\\\\*4 test in \\\\\`tests.java\\\\\` (#0) @Happypig375"
`)
})
it('adds proper details/summary markdown when collapse-after is set and more than 3 PRs', () => {
const config = {
...baseConfig,
categories: [{ title: 'Bugs', 'collapse-after': 3, labels: 'bug' }],
}
const changelog = generateChangeLog(pullRequests, config)
expect(changelog).toMatchInlineSnapshot(`
"* B2 (#2) @ghost
* Rename __confgs\\\\confg.yml to __configs\\\\config.yml (#7) @ghost
* Adds @nullable annotations to the 1*1+2*4 test in \`tests.java\` (#0) @Happypig375
## Bugs
<details>
<summary>5 changes</summary>
* A1 (#1) @ghost
* Adds missing <example> (#3) @jetersen
* \`#code_block\` (#4) @jetersen
* Fixes #4 (#5) @Happypig375
* 2*2 should equal to 4*1 (#6) @jetersen
</details>"
`)
})
it('does not add proper details/summary markdown when collapse-after is set and less than 3 PRs', () => {
const config = {
...baseConfig,
categories: [
{ title: 'Feature', 'collapse-after': 3, labels: 'feature' },
],
}
const changelog = generateChangeLog(pullRequests, config)
expect(changelog).toMatchInlineSnapshot(`
"* A1 (#1) @ghost
* Adds missing <example> (#3) @jetersen
* \`#code_block\` (#4) @jetersen
* Fixes #4 (#5) @Happypig375
* 2*2 should equal to 4*1 (#6) @jetersen
* Rename __confgs\\\\confg.yml to __configs\\\\config.yml (#7) @ghost
## Feature
* B2 (#2) @ghost
* Adds @nullable annotations to the 1*1+2*4 test in \`tests.java\` (#0) @Happypig375"
`)
})
})
})

0 comments on commit 3cbe8cc

Please sign in to comment.