diff --git a/dist/index.js b/dist/index.js index 02c0311fc..864605c15 100644 --- a/dist/index.js +++ b/dist/index.js @@ -133525,6 +133525,10 @@ const categorizePullRequests = (pullRequests, config) => { return { ...category, pullRequests: [] } }) + const uncategorizedCategoryIndex = categories.findIndex( + (category) => category.labels.length === 0 + ) + const filterUncategorizedPullRequests = (pullRequest) => { const labels = pullRequest.labels.nodes @@ -133532,7 +133536,13 @@ const categorizePullRequests = (pullRequests, config) => { labels.length === 0 || !labels.some((label) => allCategoryLabels.has(label.name)) ) { - uncategorizedPullRequests.push(pullRequest) + if (uncategorizedCategoryIndex === -1) { + uncategorizedPullRequests.push(pullRequest) + } else { + categorizedPullRequests[uncategorizedCategoryIndex].pullRequests.push( + pullRequest + ) + } return false } return true @@ -133769,7 +133779,11 @@ const _ = __nccwpck_require__(90250) const Joi = __nccwpck_require__(44010) const { SORT_BY, SORT_DIRECTIONS } = __nccwpck_require__(11940) const { DEFAULT_CONFIG } = __nccwpck_require__(85869) -const { validateReplacers, validateAutolabeler } = __nccwpck_require__(47282) +const { + validateReplacers, + validateAutolabeler, + validateCategories, +} = __nccwpck_require__(47282) const merge = __nccwpck_require__(56323) const schema = (context) => { @@ -133918,6 +133932,8 @@ const validateSchema = (context, repoConfig) => { if (error) throw error + validateCategories({ categories: config.categories }) + try { config.replacers = validateReplacers({ context, @@ -134079,9 +134095,20 @@ function validateAutolabeler({ context, autolabeler }) { .filter(Boolean) } +function validateCategories({ categories }) { + if ( + categories.filter((category) => category.labels.length === 0).length > 1 + ) { + throw new Error( + 'Multiple categories detected with no labels.\nOnly one category with no labels is supported for uncategorized pull requests.' + ) + } +} + exports.template = template exports.validateReplacers = validateReplacers exports.validateAutolabeler = validateAutolabeler +exports.validateCategories = validateCategories /***/ }), diff --git a/lib/releases.js b/lib/releases.js index 5d8e34be7..a129708fb 100644 --- a/lib/releases.js +++ b/lib/releases.js @@ -129,6 +129,10 @@ const categorizePullRequests = (pullRequests, config) => { return { ...category, pullRequests: [] } }) + const uncategorizedCategoryIndex = categories.findIndex( + (category) => category.labels.length === 0 + ) + const filterUncategorizedPullRequests = (pullRequest) => { const labels = pullRequest.labels.nodes @@ -136,7 +140,13 @@ const categorizePullRequests = (pullRequests, config) => { labels.length === 0 || !labels.some((label) => allCategoryLabels.has(label.name)) ) { - uncategorizedPullRequests.push(pullRequest) + if (uncategorizedCategoryIndex === -1) { + uncategorizedPullRequests.push(pullRequest) + } else { + categorizedPullRequests[uncategorizedCategoryIndex].pullRequests.push( + pullRequest + ) + } return false } return true diff --git a/lib/schema.js b/lib/schema.js index 1c80cac2c..95b52fa9b 100644 --- a/lib/schema.js +++ b/lib/schema.js @@ -2,7 +2,11 @@ const _ = require('lodash') const Joi = require('@hapi/joi') const { SORT_BY, SORT_DIRECTIONS } = require('./sort-pull-requests') const { DEFAULT_CONFIG } = require('./default-config') -const { validateReplacers, validateAutolabeler } = require('./template') +const { + validateReplacers, + validateAutolabeler, + validateCategories, +} = require('./template') const merge = require('deepmerge') const schema = (context) => { @@ -151,6 +155,8 @@ const validateSchema = (context, repoConfig) => { if (error) throw error + validateCategories({ categories: config.categories }) + try { config.replacers = validateReplacers({ context, diff --git a/lib/template.js b/lib/template.js index f35a8aed9..1a18fd23c 100644 --- a/lib/template.js +++ b/lib/template.js @@ -76,6 +76,17 @@ function validateAutolabeler({ context, autolabeler }) { .filter(Boolean) } +function validateCategories({ categories }) { + if ( + categories.filter((category) => category.labels.length === 0).length > 1 + ) { + throw new Error( + 'Multiple categories detected with no labels.\nOnly one category with no labels is supported for uncategorized pull requests.' + ) + } +} + exports.template = template exports.validateReplacers = validateReplacers exports.validateAutolabeler = validateAutolabeler +exports.validateCategories = validateCategories diff --git a/test/fixtures/config/config-with-categories-with-other-category.yml b/test/fixtures/config/config-with-categories-with-other-category.yml new file mode 100644 index 000000000..4017b63c7 --- /dev/null +++ b/test/fixtures/config/config-with-categories-with-other-category.yml @@ -0,0 +1,13 @@ +template: | + # What's Changed + + $CHANGES + +categories: + - title: 🚀 Features + labels: + - feature + - title: 🐛 Bug Fixes + labels: + - fix + - title: 📝 Other Changes diff --git a/test/index.test.js b/test/index.test.js index f7044d500..1f046dd6b 100644 --- a/test/index.test.js +++ b/test/index.test.js @@ -916,6 +916,62 @@ describe('release-drafter', () => { expect.assertions(1) }) + it('categorizes pull requests with other category at the bottom', async () => { + getConfigMock('config-with-categories-with-other-category.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 + + ## 🚀 Features + + * Add big feature (#2) @TimonVS + * 👽 Add alien technology (#1) @TimonVS + + ## 🐛 Bug Fixes + + * Bug fixes (#3) @TimonVS + + ## 📝 Other Changes + + * Add documentation (#5) @TimonVS + * Update dependencies (#4) @TimonVS + ", + "draft": true, + "name": "", + "prerelease": false, + "tag_name": "", + "target_commitish": "", + } + `) + return true + } + ) + .reply(200, releasePayload) + + await probot.receive({ + name: 'push', + payload: pushPayload, + }) + + expect.assertions(1) + }) + it('categorizes pull requests with multiple labels', async () => { getConfigMock('config-with-categories-2.yml') diff --git a/test/schema.test.js b/test/schema.test.js index 08ed281dc..75ac33999 100644 --- a/test/schema.test.js +++ b/test/schema.test.js @@ -1,4 +1,4 @@ -const { schema } = require('../lib/schema') +const { schema, validateSchema } = require('../lib/schema') const schemaJson = require('../schema.json') const { jsonSchema } = require('../bin/generate-schema') @@ -73,4 +73,37 @@ describe('schema', () => { it('current schema matches the generated JSON Schema, update schema with `yarn generate-schema`', () => { expect(jsonSchema).toMatchObject(schemaJson) }) + + describe('validateSchema', () => { + it('Multiple other categories', () => { + expect(() => { + validateSchema(context, { + template, + categories: [ + { + title: '📝 Other Changes', + }, + { + title: '📝 Yet Other Changes', + }, + ], + }) + }).toThrowErrorMatchingInlineSnapshot(` + "Multiple categories detected with no labels. + Only one category with no labels is supported for uncategorized pull requests." + `) + }) + + it('Single other categories', () => { + const expected = { + template, + categories: [ + { + title: '📝 Other Changes', + }, + ], + } + expect(validateSchema(context, expected)).toMatchObject(expected) + }) + }) })