# Merge Check with simple configuration

Here is an example of a merge check that ensures that pull requests must have a minimum number of (configurable) acceptances.
This might be a good way to enforce a minimum standard of code-quality on a team.
The source is available for download from Bitbucket [here](https://bitbucket.org/atlassian/bitbucket-example-merge-check-config).

## src/main/resources/atlassian-plugin.xml

```xml
<atlassian-plugin key="${project.groupId}.${project.artifactId}" name="${project.name}" plugins-version="2">
    <plugin-info>
        <description>Enforces that pull requests must have a minimum number of acceptances before they can be merged</description>
        <vendor name="${project.organization.name}" url="${project.organization.url}"/>
        <version>${project.version}</version>
    </plugin-info>

    <resource type="i18n" name="i18n" location="i18n/merge-check" />

    <repository-hook key="examplehook" name="Enforce Reviewers" class="com.mycompany.example.plugin.myhook.MyRepositoryHook">
        <description>Enforces that pull requests must have a minimum number of acceptances before they can be merged.</description>
        <icon>icons/example.png</icon>
        <config-form name="Simple Hook Config" key="simpleHook-config">
            <view>bitbucket.config.example.hook.simple.formContents</view>
            <directory location="/static/"/>
        </config-form>
        <!-- Validators can be declared separately -->
        <validator>com.mycompany.example.plugin.myhook.ReviewerValidator</validator>
    </repository-hook>

</atlassian-plugin>
```

## src/main/java/com/mycompany/example/plugin/myhook/MyRepositoryHook.java

```java
package com.mycompany.example.plugin.myhook;

import com.atlassian.bitbucket.hook.repository.*;
import com.atlassian.bitbucket.pull.PullRequestParticipant;

public class MyRepositoryHook implements RepositoryMergeRequestCheck {

    /**
     * Vetoes a pull-request if there aren't enough reviewers.
     */
    @Override
    public void check(RepositoryMergeRequestCheckContext context) {
        int requiredReviewers = context.getSettings().getInt("reviewers", 0);
        int acceptedCount = 0;
        for (PullRequestParticipant reviewer : context.getMergeRequest().getPullRequest().getReviewers()) {
            acceptedCount = acceptedCount + (reviewer.isApproved() ? 1 : 0);
        }
        if (acceptedCount < requiredReviewers) {
            context.getMergeRequest().veto("Not enough approved reviewers", acceptedCount
                    + " reviewers have approved your pull request. You need "
                    + requiredReviewers + " (total) before you may merge.");
        }
    }
}

```

## src/main/java/com/mycompany/example/plugin/myhook/ReviewerValidator.java

```java
package com.mycompany.example.plugin.myhook;

import com.atlassian.bitbucket.repository.Repository;
import com.atlassian.bitbucket.setting.*;

import javax.annotation.Nonnull;

public class ReviewerValidator implements RepositorySettingsValidator {

    @Override
    public void validate(@Nonnull Settings settings, @Nonnull SettingsValidationErrors errors,
                         @Nonnull Repository repository) {
        if (settings.getInt("reviewers", 0) == 0) {
            errors.addFieldError("reviewers", "Number of reviewers must be greater than zero");
        }
    }
}

```

## src/main/resources/static/simple.soy

```soy
{namespace bitbucket.config.example.hook.simple}

/**
 * @param config
 * @param? errors
 */
{template .formContents}
    {call aui.form.textField}
        {param id: 'reviewers' /}
        {param value: $config['reviewers'] /}
        {param labelContent: getText('bitbucket.web.test.hook.config.label') /}
        {param description: getText('bitbucket.web.test.hook.config.description') /}
        {param extraClasses: 'long' /}
        {param errorTexts: $errors ? $errors['reviewers'] : null /}
    {/call}
{/template}
```

## src/main/resources/i18n/merge-check.properties

```
bitbucket.web.test.hook.config.label=Approvals required
bitbucket.web.test.hook.config.description=The number of approvals from reviewers required before the pull request can be merged.
```
