diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md index a4d2700e24..e0c60da780 100644 --- a/CODE_OF_CONDUCT.md +++ b/CODE_OF_CONDUCT.md @@ -8,19 +8,19 @@ In the interest of fostering an open and welcoming environment, we as contributo Examples of behavior that contributes to creating a positive environment include: -* Using welcoming and inclusive language -* Being respectful of differing viewpoints and experiences -* Gracefully accepting constructive criticism -* Focusing on what is best for the community -* Showing empathy towards other community members +- Using welcoming and inclusive language +- Being respectful of differing viewpoints and experiences +- Gracefully accepting constructive criticism +- Focusing on what is best for the community +- Showing empathy towards other community members Examples of unacceptable behavior by participants include: -* The use of sexualized language or imagery and unwelcome sexual attention or advances -* Trolling, insulting/derogatory comments, and personal or political attacks -* Public or private harassment -* Publishing others' private information, such as a physical or electronic address, without explicit permission -* Other conduct which could reasonably be considered inappropriate in a professional setting +- The use of sexualized language or imagery and unwelcome sexual attention or advances +- Trolling, insulting/derogatory comments, and personal or political attacks +- Public or private harassment +- Publishing others' private information, such as a physical or electronic address, without explicit permission +- Other conduct which could reasonably be considered inappropriate in a professional setting ## Our Responsibilities diff --git a/README.md b/README.md index eb28eb79ac..5d6675a1c8 100644 --- a/README.md +++ b/README.md @@ -36,13 +36,13 @@ As pull requests are merged, a draft release is kept up-to-date listing the chan You can configure Release Drafter using the following key in your `.github/release-drafter.yml` file: -|Key|Required|Description| -|-|-|-| -|`template`|Required|The template for the body of the draft release. Use [template variables](#template-variables) to insert values.| -|`change-template`|Optional|The template to use for each merged pull request. Use [change template variables](#change-template-variables) to insert values. Default: `* $TITLE (#$NUMBER) @$AUTHOR`| -|`no-changes-template`|Optional|The template to use for when there’s no changes. Default: `* No changes`| -|`branches`|Optional|The branches to listen for configuration updates to `.github/release-drafter.yml` and for merge commits. Useful if you want to test the app on a pull request branch. Default is the repository’s default branch.| -|`categories`|Optional|Categorize pull requests using labels. Refer to [Categorize Pull Requests](#categorize-pull-requests) to learn more about this option.| +| Key | Required | Description | +| --------------------- | -------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `template` | Required | The template for the body of the draft release. Use [template variables](#template-variables) to insert values. | +| `change-template` | Optional | The template to use for each merged pull request. Use [change template variables](#change-template-variables) to insert values. Default: `* $TITLE (#$NUMBER) @$AUTHOR` | +| `no-changes-template` | Optional | The template to use for when there’s no changes. Default: `* No changes` | +| `branches` | Optional | The branches to listen for configuration updates to `.github/release-drafter.yml` and for merge commits. Useful if you want to test the app on a pull request branch. Default is the repository’s default branch. | +| `categories` | Optional | Categorize pull requests using labels. Refer to [Categorize Pull Requests](#categorize-pull-requests) to learn more about this option. | Release Drafter also supports [Probot Config](https://github.com/probot/probot-config), if you want to store your configuration files in a central repository. This allows you to share configurations between projects, and create a organization-wide configuration file by creating a repository named `.github` and file named `release-drafter.yml`. @@ -50,21 +50,21 @@ Release Drafter also supports [Probot Config](https://github.com/probot/probot-c You can use any of the following variables in your `template`: -|Variable|Description| -|-|-| -|`$CHANGES`|The markdown list of pull requests that have been merged.| -|`$CONTRIBUTORS`|A comma separated list of contributors to this release (pull request authors, commit authors, and commit committers).| -|`$PREVIOUS_TAG`|The previous releases’s tag.| +| Variable | Description | +| --------------- | --------------------------------------------------------------------------------------------------------------------- | +| `$CHANGES` | The markdown list of pull requests that have been merged. | +| `$CONTRIBUTORS` | A comma separated list of contributors to this release (pull request authors, commit authors, and commit committers). | +| `$PREVIOUS_TAG` | The previous releases’s tag. | ## Change Template variables You can use any of the following variables in `change-template`: -|Variable|Description| -|-|-| -|`$NUMBER`|The number of the pull request, e.g. `42`| -|`$TITLE`|The title of the pull request, e.g. `Add alien technology`| -|`$AUTHOR`|The pull request author’s username, e.g. `gracehopper`| +| Variable | Description | +| --------- | ---------------------------------------------------------- | +| `$NUMBER` | The number of the pull request, e.g. `42` | +| `$TITLE` | The title of the pull request, e.g. `Add alien technology` | +| `$AUTHOR` | The pull request author’s username, e.g. `gracehopper` | ## Categorize Pull Requests @@ -130,10 +130,10 @@ git checkout master && git pull && npm version [major | minor | patch] The command does the following: -* Ensures you’re on master and don’t have local, un-commited changes -* Bumps the version number in [package.json](package.json) based on major, minor or patch -* Runs the `postversion` npm script in [package.json](package.json), which: - * Pushes the tag to GitHub - * Publishes the npm release - * Deploys to [Now](https://now.sh) - * Opens the GitHub releases page so you can publish the release notes +- Ensures you’re on master and don’t have local, un-commited changes +- Bumps the version number in [package.json](package.json) based on major, minor or patch +- Runs the `postversion` npm script in [package.json](package.json), which: + - Pushes the tag to GitHub + - Publishes the npm release + - Deploys to [Now](https://now.sh) + - Opens the GitHub releases page so you can publish the release notes diff --git a/lib/base64.js b/lib/base64.js index e7066d2e5c..936d797b5a 100644 --- a/lib/base64.js +++ b/lib/base64.js @@ -1,3 +1,3 @@ -module.exports.encodeContent = (content) => { +module.exports.encodeContent = content => { return Buffer.from(content).toString('base64') } diff --git a/lib/commits.js b/lib/commits.js index 42fea32410..743ae6b9d8 100644 --- a/lib/commits.js +++ b/lib/commits.js @@ -2,38 +2,53 @@ const log = require('./log') module.exports.findCommits = async ({ app, context, branch, lastRelease }) => { if (lastRelease) { - log({ app, context, message: `Comparing commits ${lastRelease.tag_name}..${branch}` }) + log({ + app, + context, + message: `Comparing commits ${lastRelease.tag_name}..${branch}` + }) // Only supports up to 250 commits - return context.github.repos.compareCommits(context.repo({ - base: lastRelease.tag_name, - head: branch - })).then(res => res.data.commits) + return context.github.repos + .compareCommits( + context.repo({ + base: lastRelease.tag_name, + head: branch + }) + ) + .then(res => res.data.commits) } else { log({ app, context, message: `Fetching all commits for branch ${branch}` }) return context.github.paginate( - context.github.repos.getCommits(context.repo({ - sha: branch, - per_page: 100 - })), + context.github.repos.getCommits( + context.repo({ + sha: branch, + per_page: 100 + }) + ), res => res.data ) } } -module.exports.extractPullRequestNumber = (commit) => { +module.exports.extractPullRequestNumber = commit => { // There are two types of GitHub pull request merges, normal and squashed. // Normal ones look like 'Merge pull request #123' // Squashed ones have multiple lines, first one looks like 'Some changes (#123)' - const match = commit.commit.message.split('\n')[0].match(/\(#(\d+)\)$|^Merge pull request #(\d+)/) + const match = commit.commit.message + .split('\n')[0] + .match(/\(#(\d+)\)$|^Merge pull request #(\d+)/) return match && (match[1] || match[2]) } const findPullRequest = ({ context, number }) => { - return context.github.pullRequests.get(context.repo({ number: number })) - .then(res => res.data) - // We ignore any problems, in case the PR number pulled out of the commits - // are bonkers - .catch(() => false) + return ( + context.github.pullRequests + .get(context.repo({ number: number })) + .then(res => res.data) + // We ignore any problems, in case the PR number pulled out of the commits + // are bonkers + .catch(() => false) + ) } module.exports.findPullRequests = ({ app, context, commits }) => { @@ -45,13 +60,20 @@ module.exports.findPullRequests = ({ app, context, commits }) => { .map(module.exports.extractPullRequestNumber) .filter(number => number) - log({ app, context, message: `Found pull request numbers: ${pullRequestNumbers.join(', ')}` }) + log({ + app, + context, + message: `Found pull request numbers: ${pullRequestNumbers.join(', ')}` + }) - const pullRequestPromises = pullRequestNumbers - .map(number => findPullRequest({ context, number })) + const pullRequestPromises = pullRequestNumbers.map(number => + findPullRequest({ context, number }) + ) - return Promise.all(pullRequestPromises) - // Filter out PR lookups that failed - .then(prs => prs.filter(pr => pr)) - .catch(() => []) + return ( + Promise.all(pullRequestPromises) + // Filter out PR lookups that failed + .then(prs => prs.filter(pr => pr)) + .catch(() => []) + ) } diff --git a/lib/releases.js b/lib/releases.js index 4af02ae3df..9244cdae7f 100644 --- a/lib/releases.js +++ b/lib/releases.js @@ -4,29 +4,34 @@ const log = require('./log') const UNCATEGORIZED = 'UNCATEGORIZED' -const sortReleases = (releases) => { +const sortReleases = releases => { // For semver, we find the greatest release number // For non-semver, we use the most recently merged try { return releases.sort((r1, r2) => compareVersions(r1.tag_name, r2.tag_name)) } catch (error) { - return releases.sort((r1, r2) => new Date(r1.published_at) - new Date(r2.published_at)) + return releases.sort( + (r1, r2) => new Date(r1.published_at) - new Date(r2.published_at) + ) } } module.exports.findReleases = async ({ app, context }) => { let releases = await context.github.paginate( - context.github.repos.getReleases(context.repo({ - per_page: 100 - })), + context.github.repos.getReleases( + context.repo({ + per_page: 100 + }) + ), res => res.data ) log({ app, context, message: `Found ${releases.length} releases` }) const sortedPublishedReleases = sortReleases(releases.filter(r => !r.draft)) - const draftRelease = releases.find((r) => r.draft) - const lastRelease = sortedPublishedReleases[sortedPublishedReleases.length - 1] + const draftRelease = releases.find(r => r.draft) + const lastRelease = + sortedPublishedReleases[sortedPublishedReleases.length - 1] if (draftRelease) { log({ app, context, message: `Draft release: ${draftRelease.tag_name}` }) @@ -46,7 +51,7 @@ module.exports.findReleases = async ({ app, context }) => { const contributorsSentence = ({ commits, pullRequests }) => { const contributors = new Set() - commits.forEach((commit) => { + commits.forEach(commit => { if (commit.author) { contributors.add(`@${commit.author.login}`) } else { @@ -54,12 +59,16 @@ const contributorsSentence = ({ commits, pullRequests }) => { } }) - pullRequests.forEach((pullRequest) => { + pullRequests.forEach(pullRequest => { contributors.add(`@${pullRequest.user.login}`) }) const sortedContributors = Array.from(contributors).sort() - return sortedContributors.slice(0, sortedContributors.length - 1).join(', ') + ' and ' + sortedContributors.slice(-1) + return ( + sortedContributors.slice(0, sortedContributors.length - 1).join(', ') + + ' and ' + + sortedContributors.slice(-1) + ) } const getCategoriesConfig = ({ config }) => { @@ -68,31 +77,44 @@ const getCategoriesConfig = ({ config }) => { return acc }, {}) - const orderedCategories = [UNCATEGORIZED, ...config.categories.map(category => category.label)] + const orderedCategories = [ + UNCATEGORIZED, + ...config.categories.map(category => category.label) + ] return [categoriesConfig, orderedCategories] } const categorizePullRequests = (pullRequests, categories) => { - return pullRequests.reduce((acc, pullRequest) => { - if (pullRequest.labels.length === 0 || - !pullRequest.labels.some(label => categories.includes(label.name))) { - acc[UNCATEGORIZED].push(pullRequest) - } else { - pullRequest.labels.forEach(label => { - if (!acc[label.name]) acc[label.name] = [] + return pullRequests.reduce( + (acc, pullRequest) => { + if ( + pullRequest.labels.length === 0 || + !pullRequest.labels.some(label => categories.includes(label.name)) + ) { + acc[UNCATEGORIZED].push(pullRequest) + } else { + pullRequest.labels.forEach(label => { + if (!acc[label.name]) acc[label.name] = [] + + acc[label.name].push(pullRequest) + }) + } - acc[label.name].push(pullRequest) - }) + return acc + }, + { + [UNCATEGORIZED]: [] } - - return acc - }, { - [UNCATEGORIZED]: [] - }) + ) } -module.exports.generateReleaseBody = ({ commits, config, lastRelease, mergedPullRequests }) => { +module.exports.generateReleaseBody = ({ + commits, + config, + lastRelease, + mergedPullRequests +}) => { let body = config.template const [categoriesConfig, orderedCategories] = getCategoriesConfig({ config }) @@ -105,30 +127,48 @@ module.exports.generateReleaseBody = ({ commits, config, lastRelease, mergedPull if (mergedPullRequests.length === 0) { body = body.replace('$CHANGES', config['no-changes-template']) } else { - const categorizedPullRequests = categorizePullRequests(mergedPullRequests, orderedCategories) - - body = body.replace('$CHANGES', orderedCategories.reduce((acc, category, index) => { - if (!categorizedPullRequests[category] || - categorizedPullRequests[category].length === 0) return acc - - if (category !== UNCATEGORIZED) { - acc.push(`## ${categoriesConfig[category].title}\n\n`) - } - - acc.push(categorizedPullRequests[category].map((pullRequest) => ( - config['change-template'] - .replace('$TITLE', pullRequest.title) - .replace('$NUMBER', pullRequest.number) - .replace('$AUTHOR', pullRequest.user.login) - )).join('\n')) - - if ((index + 1) !== orderedCategories.length) acc.push('\n\n') - - return acc - }, []).join('')) + const categorizedPullRequests = categorizePullRequests( + mergedPullRequests, + orderedCategories + ) + + body = body.replace( + '$CHANGES', + orderedCategories + .reduce((acc, category, index) => { + if ( + !categorizedPullRequests[category] || + categorizedPullRequests[category].length === 0 + ) + return acc + + if (category !== UNCATEGORIZED) { + acc.push(`## ${categoriesConfig[category].title}\n\n`) + } + + acc.push( + categorizedPullRequests[category] + .map(pullRequest => + config['change-template'] + .replace('$TITLE', pullRequest.title) + .replace('$NUMBER', pullRequest.number) + .replace('$AUTHOR', pullRequest.user.login) + ) + .join('\n') + ) + + if (index + 1 !== orderedCategories.length) acc.push('\n\n') + + return acc + }, []) + .join('') + ) } - body = body.replace('$CONTRIBUTORS', contributorsSentence({ commits, pullRequests: mergedPullRequests })) + body = body.replace( + '$CONTRIBUTORS', + contributorsSentence({ commits, pullRequests: mergedPullRequests }) + ) return body } diff --git a/lib/triggerable-branch.js b/lib/triggerable-branch.js index 117d999051..9b32b36c5c 100644 --- a/lib/triggerable-branch.js +++ b/lib/triggerable-branch.js @@ -1,6 +1,6 @@ const log = require('./log') -const flatten = (arr) => { +const flatten = arr => { return Array.prototype.concat(...arr) } @@ -8,7 +8,13 @@ module.exports.isTriggerableBranch = ({ app, context, branch, config }) => { const validBranches = flatten([config.branches]) const relevant = validBranches.indexOf(branch) !== -1 if (!relevant) { - log({ app, context, message: `Ignoring push. ${branch} is not one of: ${validBranches.join(', ')}` }) + log({ + app, + context, + message: `Ignoring push. ${branch} is not one of: ${validBranches.join( + ', ' + )}` + }) } return relevant } diff --git a/test/commits.test.js b/test/commits.test.js index e40b7b7f4e..5df810185d 100644 --- a/test/commits.test.js +++ b/test/commits.test.js @@ -5,21 +5,25 @@ const mockCommit = message => ({ commit: { message } }) describe('extractPullRequestNumber', () => { it('extracts from merge commit message', () => { expect( - commits.extractPullRequestNumber(mockCommit( - 'Merge pull request #37 from JasonEtco/patch-1') - )).toEqual('37') + commits.extractPullRequestNumber( + mockCommit('Merge pull request #37 from JasonEtco/patch-1') + ) + ).toEqual('37') }) it('extracts from squash & merge commit message', () => { expect( - commits.extractPullRequestNumber(mockCommit( - ` + commits.extractPullRequestNumber( + mockCommit( + ` Fixed conditional card state on 1st render (#1537) * Fixed conditional card state on 1st render * Moved method to correct location - `.trim()) - )).toEqual('1537') + `.trim() + ) + ) + ).toEqual('1537') }) }) diff --git a/test/index.test.js b/test/index.test.js index cd5b2f6967..a928f2c622 100644 --- a/test/index.test.js +++ b/test/index.test.js @@ -48,9 +48,14 @@ describe('release-drafter', () => { describe('to a non-master branch', () => { it('does nothing', async () => { - github.repos.getContent = fn().mockReturnValueOnce(mockConfig('config.yml')) + github.repos.getContent = fn().mockReturnValueOnce( + mockConfig('config.yml') + ) - await app.receive({ name: 'push', payload: require('./fixtures/push-non-master-branch') }) + await app.receive({ + name: 'push', + payload: require('./fixtures/push-non-master-branch') + }) expect(github.repos.createRelease).not.toHaveBeenCalled() expect(github.repos.editRelease).not.toHaveBeenCalled() @@ -58,12 +63,21 @@ describe('release-drafter', () => { describe('when configured for that branch', () => { it('creates a release draft', async () => { - github.repos.getContent = fn().mockReturnValueOnce(mockConfig('config-non-master-branch.yml')) - github.repos.getReleases = fn().mockReturnValueOnce(Promise.resolve({ data: [ require('./fixtures/release') ] })) - github.repos.compareCommits = fn().mockReturnValueOnce(Promise.resolve({ data: { commits: [] } })) + github.repos.getContent = fn().mockReturnValueOnce( + mockConfig('config-non-master-branch.yml') + ) + github.repos.getReleases = fn().mockReturnValueOnce( + Promise.resolve({ data: [require('./fixtures/release')] }) + ) + github.repos.compareCommits = fn().mockReturnValueOnce( + Promise.resolve({ data: { commits: [] } }) + ) github.repos.createRelease = fn() - await app.receive({ name: 'push', payload: require('./fixtures/push-non-master-branch') }) + await app.receive({ + name: 'push', + payload: require('./fixtures/push-non-master-branch') + }) expect(github.repos.createRelease).toBeCalledWith( expect.objectContaining({ @@ -78,12 +92,22 @@ describe('release-drafter', () => { describe('with no past releases', () => { it('sets $CHANGES based on all commits, and $PREVIOUS_TAG to blank', async () => { - github.repos.getContent = fn().mockReturnValueOnce(mockConfig('config-previous-tag.yml')) - github.repos.getReleases = fn().mockReturnValueOnce(Promise.resolve({ data: [] })) - github.repos.getCommits = fn().mockReturnValueOnce(Promise.resolve({ data: require('./fixtures/commits') })) + github.repos.getContent = fn().mockReturnValueOnce( + mockConfig('config-previous-tag.yml') + ) + github.repos.getReleases = fn().mockReturnValueOnce( + Promise.resolve({ data: [] }) + ) + github.repos.getCommits = fn().mockReturnValueOnce( + Promise.resolve({ data: require('./fixtures/commits') }) + ) github.pullRequests.get = fn() - .mockReturnValueOnce(Promise.resolve(require('./fixtures/pull-request-1'))) - .mockReturnValueOnce(Promise.resolve(require('./fixtures/pull-request-2'))) + .mockReturnValueOnce( + Promise.resolve(require('./fixtures/pull-request-1')) + ) + .mockReturnValueOnce( + Promise.resolve(require('./fixtures/pull-request-2')) + ) github.repos.createRelease = fn() await app.receive({ name: 'push', payload: require('./fixtures/push') }) @@ -105,19 +129,34 @@ Previous tag: '' describe('with past releases', () => { it('creates a new draft listing the changes', async () => { - github.repos.getContent = fn().mockReturnValueOnce(mockConfig('config.yml')) - github.repos.getReleases = fn().mockReturnValueOnce(Promise.resolve({ data: - // Tests whether it sorts releases properly - [ require('./fixtures/release-2'), - require('./fixtures/release'), - require('./fixtures/release-3') ] - })) - github.repos.compareCommits = fn().mockReturnValueOnce(Promise.resolve({ data: { - commits: require('./fixtures/commits') - } })) + github.repos.getContent = fn().mockReturnValueOnce( + mockConfig('config.yml') + ) + github.repos.getReleases = fn().mockReturnValueOnce( + Promise.resolve({ + data: + // Tests whether it sorts releases properly + [ + require('./fixtures/release-2'), + require('./fixtures/release'), + require('./fixtures/release-3') + ] + }) + ) + github.repos.compareCommits = fn().mockReturnValueOnce( + Promise.resolve({ + data: { + commits: require('./fixtures/commits') + } + }) + ) github.pullRequests.get = fn() - .mockReturnValueOnce(Promise.resolve(require('./fixtures/pull-request-1'))) - .mockReturnValueOnce(Promise.resolve(require('./fixtures/pull-request-2'))) + .mockReturnValueOnce( + Promise.resolve(require('./fixtures/pull-request-1')) + ) + .mockReturnValueOnce( + Promise.resolve(require('./fixtures/pull-request-2')) + ) github.repos.createRelease = fn() @@ -125,8 +164,8 @@ Previous tag: '' expect(github.repos.compareCommits).toBeCalledWith( expect.objectContaining({ - 'base': 'v2.0.0', - 'head': 'master' + base: 'v2.0.0', + head: 'master' }) ) expect(github.repos.createRelease).toBeCalledWith( @@ -144,18 +183,33 @@ Previous tag: '' describe('with custom changes-template config', () => { it('creates a new draft using the template', async () => { - github.repos.getContent = fn().mockReturnValueOnce(mockConfig('config-with-changes-templates.yml')) - github.repos.getReleases = fn().mockReturnValueOnce(Promise.resolve({ data: [ require('./fixtures/release') ] })) - github.repos.compareCommits = fn().mockReturnValueOnce(Promise.resolve({ data: { - commits: require('./fixtures/commits') - } })) + github.repos.getContent = fn().mockReturnValueOnce( + mockConfig('config-with-changes-templates.yml') + ) + github.repos.getReleases = fn().mockReturnValueOnce( + Promise.resolve({ data: [require('./fixtures/release')] }) + ) + github.repos.compareCommits = fn().mockReturnValueOnce( + Promise.resolve({ + data: { + commits: require('./fixtures/commits') + } + }) + ) github.pullRequests.get = fn() - .mockReturnValueOnce(Promise.resolve(require('./fixtures/pull-request-1'))) - .mockReturnValueOnce(Promise.resolve(require('./fixtures/pull-request-2'))) + .mockReturnValueOnce( + Promise.resolve(require('./fixtures/pull-request-1')) + ) + .mockReturnValueOnce( + Promise.resolve(require('./fixtures/pull-request-2')) + ) github.repos.createRelease = fn() - await app.receive({ name: 'push', payload: require('./fixtures/push') }) + await app.receive({ + name: 'push', + payload: require('./fixtures/push') + }) expect(github.repos.createRelease).toBeCalledWith( expect.objectContaining({ @@ -170,18 +224,33 @@ Previous tag: '' describe('with contributors config', () => { it('adds the contributors', async () => { - github.repos.getContent = fn().mockReturnValueOnce(mockConfig('config-with-contributors.yml')) - github.repos.getReleases = fn().mockReturnValueOnce(Promise.resolve({ data: [ require('./fixtures/release') ] })) - github.repos.compareCommits = fn().mockReturnValueOnce(Promise.resolve({ data: { - commits: require('./fixtures/commits') - } })) + github.repos.getContent = fn().mockReturnValueOnce( + mockConfig('config-with-contributors.yml') + ) + github.repos.getReleases = fn().mockReturnValueOnce( + Promise.resolve({ data: [require('./fixtures/release')] }) + ) + github.repos.compareCommits = fn().mockReturnValueOnce( + Promise.resolve({ + data: { + commits: require('./fixtures/commits') + } + }) + ) github.pullRequests.get = fn() - .mockReturnValueOnce(Promise.resolve(require('./fixtures/pull-request-1'))) - .mockReturnValueOnce(Promise.resolve(require('./fixtures/pull-request-2'))) + .mockReturnValueOnce( + Promise.resolve(require('./fixtures/pull-request-1')) + ) + .mockReturnValueOnce( + Promise.resolve(require('./fixtures/pull-request-2')) + ) github.repos.createRelease = fn() - await app.receive({ name: 'push', payload: require('./fixtures/push') }) + await app.receive({ + name: 'push', + payload: require('./fixtures/push') + }) expect(github.repos.createRelease).toBeCalledWith( expect.objectContaining({ @@ -196,22 +265,31 @@ Previous tag: '' describe('with no changes since the last release', () => { it('creates a new draft with no changes', async () => { - github.repos.getContent = fn().mockReturnValueOnce(mockConfig('config.yml')) - github.repos.getReleases = fn().mockReturnValueOnce(Promise.resolve({ data: - // Tests whether it sorts releases properly - [ require('./fixtures/release-2'), - require('./fixtures/release'), - require('./fixtures/release-3') ] - })) - github.repos.compareCommits = fn().mockReturnValueOnce(Promise.resolve({ data: { commits: [] } })) + github.repos.getContent = fn().mockReturnValueOnce( + mockConfig('config.yml') + ) + github.repos.getReleases = fn().mockReturnValueOnce( + Promise.resolve({ + data: + // Tests whether it sorts releases properly + [ + require('./fixtures/release-2'), + require('./fixtures/release'), + require('./fixtures/release-3') + ] + }) + ) + github.repos.compareCommits = fn().mockReturnValueOnce( + Promise.resolve({ data: { commits: [] } }) + ) github.repos.createRelease = fn() await app.receive({ name: 'push', payload: require('./fixtures/push') }) expect(github.repos.compareCommits).toBeCalledWith( expect.objectContaining({ - 'base': 'v2.0.0', - 'head': 'master' + base: 'v2.0.0', + head: 'master' }) ) expect(github.repos.createRelease).toBeCalledWith( @@ -228,12 +306,21 @@ Previous tag: '' describe('with custom no-changes-template config', () => { it('creates a new draft with the template', async () => { - github.repos.getContent = fn().mockReturnValueOnce(mockConfig('config-with-changes-templates.yml')) - github.repos.getReleases = fn().mockReturnValueOnce(Promise.resolve({ data: [] })) - github.repos.getCommits = fn().mockReturnValueOnce(Promise.resolve({ data: [] })) + github.repos.getContent = fn().mockReturnValueOnce( + mockConfig('config-with-changes-templates.yml') + ) + github.repos.getReleases = fn().mockReturnValueOnce( + Promise.resolve({ data: [] }) + ) + github.repos.getCommits = fn().mockReturnValueOnce( + Promise.resolve({ data: [] }) + ) github.repos.createRelease = fn() - await app.receive({ name: 'push', payload: require('./fixtures/push') }) + await app.receive({ + name: 'push', + payload: require('./fixtures/push') + }) expect(github.repos.createRelease).toBeCalledWith( expect.objectContaining({ @@ -248,12 +335,22 @@ Previous tag: '' describe('with an existing draft release', () => { it('updates the existing release’s body', async () => { - github.repos.getContent = fn().mockReturnValueOnce(mockConfig('config.yml')) - github.repos.getReleases = fn().mockReturnValueOnce(Promise.resolve({ data: [ require('./fixtures/release-draft.json') ] })) - github.repos.getCommits = fn().mockReturnValueOnce(Promise.resolve({ data: require('./fixtures/commits') })) + github.repos.getContent = fn().mockReturnValueOnce( + mockConfig('config.yml') + ) + github.repos.getReleases = fn().mockReturnValueOnce( + Promise.resolve({ data: [require('./fixtures/release-draft.json')] }) + ) + github.repos.getCommits = fn().mockReturnValueOnce( + Promise.resolve({ data: require('./fixtures/commits') }) + ) github.pullRequests.get = fn() - .mockReturnValueOnce(Promise.resolve(require('./fixtures/pull-request-1'))) - .mockReturnValueOnce(Promise.resolve(require('./fixtures/pull-request-2'))) + .mockReturnValueOnce( + Promise.resolve(require('./fixtures/pull-request-1')) + ) + .mockReturnValueOnce( + Promise.resolve(require('./fixtures/pull-request-2')) + ) github.repos.editRelease = fn() await app.receive({ name: 'push', payload: require('./fixtures/push') }) @@ -272,16 +369,32 @@ Previous tag: '' describe('with categories config', () => { it('categorizes pull requests', async () => { - github.repos.getContent = fn().mockReturnValueOnce(mockConfig('config-with-categories.yml')) - github.repos.getReleases = fn().mockReturnValueOnce(Promise.resolve({ data: [ require('./fixtures/release') ] })) - github.repos.compareCommits = fn().mockReturnValueOnce(Promise.resolve({ data: { - commits: require('./fixtures/commits-2') - } })) + github.repos.getContent = fn().mockReturnValueOnce( + mockConfig('config-with-categories.yml') + ) + github.repos.getReleases = fn().mockReturnValueOnce( + Promise.resolve({ data: [require('./fixtures/release')] }) + ) + github.repos.compareCommits = fn().mockReturnValueOnce( + Promise.resolve({ + data: { + commits: require('./fixtures/commits-2') + } + }) + ) github.pullRequests.get = fn() - .mockReturnValueOnce(Promise.resolve(require('./fixtures/pull-request-1'))) - .mockReturnValueOnce(Promise.resolve(require('./fixtures/pull-request-2'))) - .mockReturnValueOnce(Promise.resolve(require('./fixtures/pull-request-3'))) - .mockReturnValueOnce(Promise.resolve(require('./fixtures/pull-request-4'))) + .mockReturnValueOnce( + Promise.resolve(require('./fixtures/pull-request-1')) + ) + .mockReturnValueOnce( + Promise.resolve(require('./fixtures/pull-request-2')) + ) + .mockReturnValueOnce( + Promise.resolve(require('./fixtures/pull-request-3')) + ) + .mockReturnValueOnce( + Promise.resolve(require('./fixtures/pull-request-4')) + ) github.repos.createRelease = fn()