From 1d2c5ea974cfc3afed57615402e585dfbe187439 Mon Sep 17 00:00:00 2001 From: Matthias Kurz Date: Tue, 1 Feb 2022 18:11:07 +0100 Subject: [PATCH 1/2] Add header and footer --- README.md | 6 ++++-- dist/index.js | 7 ++++++- lib/releases.js | 3 ++- lib/schema.js | 4 ++++ schema.json | 6 ++++++ 5 files changed, 22 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 76b11519b..d1d7d818d 100644 --- a/README.md +++ b/README.md @@ -109,6 +109,8 @@ You can configure Release Drafter using the following key in your `.github/relea | Key | Required | Description | | -------------------------- | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `template` | Required | The template for the body of the draft release. Use [template variables](#template-variables) to insert values. | +| `header` | Optional | Will be prepended to `template`. Use [template variables](#template-variables) to insert values. | +| `footer` | Optional | Will be appended to `template`. Use [template variables](#template-variables) to insert values. | | `category-template` | Optional | The template to use for each category. Use [category template variables](#category-template-variables) to insert values. Default: `"## $TITLE"`. | | `name-template` | Optional | The template for the name of the draft release. For example: `"v$NEXT_PATCH_VERSION"`. | | `tag-template` | Optional | The template for the tag of the draft release. For example: `"v$NEXT_PATCH_VERSION"`. | @@ -134,7 +136,7 @@ Release Drafter also supports [Probot Config](https://github.com/probot/probot-c ## Template Variables -You can use any of the following variables in your `template`: +You can use any of the following variables in your `template`, `header` and `footer`: | Variable | Description | | --------------- | --------------------------------------------------------------------------------------------------------------------- | @@ -154,7 +156,7 @@ You can use any of the following variables in `category-template`: ## Next Version Variables -You can use any of the following variables in your `template`, `name-template` and `tag-template`: +You can use any of the following variables in your `template`, `header`, `footer`, `name-template` and `tag-template`: | Variable | Description | | --------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------- | diff --git a/dist/index.js b/dist/index.js index 0d87e2478..173a742e0 100644 --- a/dist/index.js +++ b/dist/index.js @@ -129311,7 +129311,8 @@ const generateReleaseInfo = ({ }) => { const { owner, repo } = context.repo() - let body = config.template + let body = + (config['header'] || '') + config.template + (config['footer'] || '') body = template( body, @@ -129571,8 +129572,12 @@ const schema = (context) => { .allow('') .default(DEFAULT_CONFIG['category-template']), + header: Joi.string(), + template: Joi.string().required(), + footer: Joi.string(), + _extends: Joi.string(), }) .rename('branches', 'references', { diff --git a/lib/releases.js b/lib/releases.js index d251ac193..616721e33 100644 --- a/lib/releases.js +++ b/lib/releases.js @@ -273,7 +273,8 @@ const generateReleaseInfo = ({ }) => { const { owner, repo } = context.repo() - let body = config.template + let body = + (config['header'] || '') + config.template + (config['footer'] || '') body = template( body, diff --git a/lib/schema.js b/lib/schema.js index 849816265..a4368cb79 100644 --- a/lib/schema.js +++ b/lib/schema.js @@ -147,8 +147,12 @@ const schema = (context) => { .allow('') .default(DEFAULT_CONFIG['category-template']), + header: Joi.string(), + template: Joi.string().required(), + footer: Joi.string(), + _extends: Joi.string(), }) .rename('branches', 'references', { diff --git a/schema.json b/schema.json index 1b03521d5..9208f6bb6 100644 --- a/schema.json +++ b/schema.json @@ -286,9 +286,15 @@ } ] }, + "header": { + "type": "string" + }, "template": { "type": "string" }, + "footer": { + "type": "string" + }, "_extends": { "type": "string" } From aadff3627329abc824dcf48c2f1203789e5f5226 Mon Sep 17 00:00:00 2001 From: Matthias Kurz Date: Tue, 1 Feb 2022 21:20:56 +0100 Subject: [PATCH 2/2] Add tests for header and footer --- .../config/config-with-footer-template.yml | 5 + ...der-and-footer-no-nl-no-space-template.yml | 3 + ...config-with-header-and-footer-template.yml | 8 + .../config/config-with-header-template.yml | 5 + test/index.test.js | 172 ++++++++++++++++++ test/schema.test.js | 13 ++ 6 files changed, 206 insertions(+) create mode 100644 test/fixtures/config/config-with-footer-template.yml create mode 100644 test/fixtures/config/config-with-header-and-footer-no-nl-no-space-template.yml create mode 100644 test/fixtures/config/config-with-header-and-footer-template.yml create mode 100644 test/fixtures/config/config-with-header-template.yml diff --git a/test/fixtures/config/config-with-footer-template.yml b/test/fixtures/config/config-with-footer-template.yml new file mode 100644 index 000000000..1fe7ba391 --- /dev/null +++ b/test/fixtures/config/config-with-footer-template.yml @@ -0,0 +1,5 @@ +template: | + This is the template in the middle + +footer: | + This is at bottom diff --git a/test/fixtures/config/config-with-header-and-footer-no-nl-no-space-template.yml b/test/fixtures/config/config-with-header-and-footer-no-nl-no-space-template.yml new file mode 100644 index 000000000..f363f9108 --- /dev/null +++ b/test/fixtures/config/config-with-header-and-footer-no-nl-no-space-template.yml @@ -0,0 +1,3 @@ +template: This is the template in the middle +header: This is at top +footer: This is at bottom diff --git a/test/fixtures/config/config-with-header-and-footer-template.yml b/test/fixtures/config/config-with-header-and-footer-template.yml new file mode 100644 index 000000000..903202e16 --- /dev/null +++ b/test/fixtures/config/config-with-header-and-footer-template.yml @@ -0,0 +1,8 @@ +template: | + This is the template in the middle + +header: | + This is at top + +footer: | + This is at bottom diff --git a/test/fixtures/config/config-with-header-template.yml b/test/fixtures/config/config-with-header-template.yml new file mode 100644 index 000000000..4f7681dd0 --- /dev/null +++ b/test/fixtures/config/config-with-header-template.yml @@ -0,0 +1,5 @@ +template: | + This is the template in the middle + +header: | + This is at top diff --git a/test/index.test.js b/test/index.test.js index 106793605..f07642d59 100644 --- a/test/index.test.js +++ b/test/index.test.js @@ -1426,6 +1426,178 @@ describe('release-drafter', () => { }) }) + describe('with header and footer config', () => { + it('only header', async () => { + getConfigMock('config-with-header-template.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": "This is at top + This is the template in the middle + ", + "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('only footer', async () => { + getConfigMock('config-with-footer-template.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": "This is the template in the middle + This is at bottom + ", + "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('header and footer', async () => { + getConfigMock('config-with-header-and-footer-template.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": "This is at top + This is the template in the middle + This is at bottom + ", + "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('header and footer without line break and without space', async () => { + getConfigMock( + 'config-with-header-and-footer-no-nl-no-space-template.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": "This is at topThis is the template in the middleThis is at bottom", + "draft": true, + "name": "", + "prerelease": false, + "tag_name": "", + "target_commitish": "", + } + `) + return true + } + ) + .reply(200, releasePayload) + + await probot.receive({ + name: 'push', + payload: pushPayload, + }) + + expect.assertions(1) + }) + }) + describe('merging strategies', () => { describe('merge commit', () => { it('sets $CHANGES based on all commits', async () => { diff --git a/test/schema.test.js b/test/schema.test.js index 8a69c766f..9599a2b8b 100644 --- a/test/schema.test.js +++ b/test/schema.test.js @@ -17,6 +17,9 @@ const validConfigs = [ [{ template, replacers: [{ search: '123', replace: '' }] }], [{ template, replacers: [{ search: '/123/gi', replace: '' }] }], [{ template, replacers: [{ search: '/123/gi', replace: '123' }] }], + [{ template, header: 'I am on top' }], + [{ template, footer: 'I am on bottm' }], + [{ template, header: 'I am on top', footer: 'I am on bottm' }], ] const invalidConfigs = [ @@ -26,6 +29,16 @@ const invalidConfigs = [ [{ template: { '👶': 'a' } }, 'must be a string'], [{ template: null }, 'must be a string'], [{ template: '' }, 'is not allowed to be empty'], + [{ header: true }, 'must be a string'], + [{ header: 1 }, 'must be a string'], + [{ header: ['👶'] }, 'must be a string'], + [{ header: { '👶': 'a' } }, 'must be a string'], + [{ header: null }, 'must be a string'], + [{ footer: true }, 'must be a string'], + [{ footer: 1 }, 'must be a string'], + [{ footer: ['👶'] }, 'must be a string'], + [{ footer: { '👶': 'a' } }, 'must be a string'], + [{ footer: null }, 'must be a string'], [{ 'category-template': ['## $TITLE'] }, 'must be a string'], [{ 'category-template': null }, 'must be a string'], [{ 'change-template': ['* $TITLE (#$NUMBER) @$AUTHOR'] }, 'must be a string'],