#  Repository Hooks and Merge Checks

## Introduction

For users familiar with the [Git](http://git-scm.com/book/en/Customizing-Git-Git-Hooks) hook system, Bitbucket Server 
[now provides a way](http://blogs.atlassian.com/2013/03/stash-git-hooks-api/) for plugin developers to create their own 
hooks that can be installed and managed without having to touch the filesystem.

Hooks have been implemented using familiar modules within the Atlassian plugin system.

There are countless examples of hooks that could be deployed to a Bitbucket Server instance:

* Restrict deletion of branches
* Restrict 'force-pushes' to select branches
* Integrate with a CI server (e.g. Bamboo) or other 3rd party application, to notify when code is pushed or branches are 
  created, merged or deleted
* Require that pull requests have a minimum number of reviewers who have accepted
* Enforce a specific workflow (e.g. master cannot be merged into a release branch)
* Mirror a repository with another instance of Bitbucket Server
* Ensure all commits contain a JIRA key

Bitbucket Server supports this through [Repository Hook Modules](../reference/plugin-module-types/repository-hook-plugin-module.html).

## Categories

Currently there are three types of hooks that are available in Bitbucket Server.

### Pre-receive

Pre-receive hooks are used to potentially block pushes to Bitbucket Server. An example might be to stop deletion of branches or
limit force-pushes to personal branches. Pre-receive hooks do not fire when a pull-request is merged - for that, you may
also want to implement a repository merge-check.

### Asynchronous Post-receive

Post-receive hooks are invoked after a push _or_ merge has taken place. An example might be to notify a build server, such
as Bamboo, that there are new commits on a branch to be built.

Asynchronous post-receive hooks are preferred when there is no need to return any information to the client, as they are
triggered _after_ the push is complete. This is a better experience for the user as they will not have to wait for
potentially slow operations.

### Merge-checks

Merge checks are used to block pull requests from being merged until a required set of conditions have been met.
An example might be that all reviewers must accept the request, or that any associated builds are green.

A `RepositoryMergeRequestCheck` has similar functionality to the [Merge Check Plugin Module](../reference/plugin-module-types/merge-check.html),
but additionally allows users to enable, disable and provide configuration on a per-repository basis via the Bitbucket Server UI.

## How-to

<div class="aui-message info shadowed">
    <h4 class="title"><a name="Video-Tutorial"></a>Repository hook video tutorial</h4>
    <span class="aui-icon icon-info"></span>
    <p>
        Learn to build a simple repository hook from scratch in this <a href="https://developer.atlassian.com/blog/2015/01/beer-o-clock-stash-plugin-tutorial/">30 minute video tutorial</a>.
    </p>
    <p>
        Note: This tutorial pre-dates the renaming of the product to "Bitbucket Server" from "Stash", but is still a useful resource.
    </p>
</div>

### Generate a Bitbucket Server plugin using the Atlassian SDK

Ensure you have a Bitbucket Server plugin which will contain your hook,
which you can create by [following this guide](creating-a-bitbucket-server-plugin.html).
Don't forget to add `bitbucket-spi` to your `pom.xml` as this will be required to compile against the hook API.

### Enabling your hook

Repository hooks need to be enabled and configured on a per repository basis, [details are here.] (https://confluence.atlassian.com/display/BitbucketServer/Using+repository+hooks)

### Examples

- [Pre-Receive with no configuration](repo-hook-examples/pre-receive-no-config.html)
- [Pre-Receive with configuration](repo-hook-examples/pre-receive-branch-config.html)
- [Asynchronous Post-Receive with simple configuration and validation](repo-hook-examples/async-post-receive-config.html)
- [Merge check with simple configuration](repo-hook-examples/merge-check-config.html)

### Javadoc

For Java API specific documentation, please see the accompanying Javadoc for the revelant classes/packages.

- [Repository Hooks](https://developer.atlassian.com/static/javadoc/bitbucket-server/${project.version}/spi/reference/com/atlassian/bitbucket/hook/repository/package-summary.html)
- [Settings](https://developer.atlassian.com/static/javadoc/bitbucket-server/${project.version}/api/reference/com/atlassian/bitbucket/setting/Settings.html)
- [Settings Validation](https://developer.atlassian.com/static/javadoc/bitbucket-server/${project.version}/spi/reference/com/atlassian/bitbucket/setting/package-summary.html)

### Configuration

It is possible to add configuration to your hook by specifying a configuration screen. The values of input elements defined in the screen will be saved by the framework and passed to the hook each time it is called.
Generally we use AUI templates to generate our controls to keep styling the same, however a simple element &lt;input name="x" type="text"/> would work.

Hook configuration screens can be defined using [Closure Templates](https://developers.google.com/closure/templates/docs/overview). Atlassian is currently running an older version of
Closure Templates, so you might find the best documentation in the [Internet Archive](http://web.archive.org/web/20121018175803/https://developers.google.com/closure/templates/docs/overview).

Bitbucket Server provides [bitbucket.component.branchSelector field and input templates](../reference/soy/branch-selector-field.html) that you can include to let users select a branch or tag.

#### Atlassian User Interface (AUI)

A number of AUI Soy templates are also available to assist in creating a configuration form for your hook.
For more information about AUI please read the [AUI Docs](https://developer.atlassian.com/display/AUI) or
try out the live demos in the [sandbox](http://docs.atlassian.com/aui/latest).
For an a list of available AUI Soy templates that you can use in your own configuration form, consult the
[AUI Soy source](https://bitbucket.org/atlassian/aui/src/5.8.14/src/soy/form.soy).

#### Example

This template adds an AUI style text field with the id "url", user inputted text data will be saved with the key "url" and passed to the hook inside a Settings object.

```soy
/**
 * @param config
 * @param? errors
 */
{template .formContents}
    {call aui.form.textField}
        /** set the name of the input field -- this will be used as the setting key */
        {param id: 'url' /}
        /** supply the previous value to the text field so the user can see the saved data */
        {param value: $config['url'] /}
        {param labelContent: getText('bitbucket.web.test.hook.config.label') /}
        {param descriptionText: getText('bitbucket.web.test.hook.config.description') /}
        {param extraClasses: 'long' /}
        /** if validation returned errors then display them in the error text. */
        {param errorTexts: $errors ? $errors['url'] : null /}
    {/call}
{/template}
```

The matching hook accesses the "url" value and also validates it.

```java
public class MyRepositoryHook implements AsyncPostReceiveRepositoryHook, RepositorySettingsValidator {

    @Override
    public void postReceive(RepositoryHookContext context, Collection<RefChange> refChanges) {
        String url = context.getSettings().getString("url");
        if (url != null) {
            //do stuff
        }
    }

    @Override
    public void validate(Settings settings, SettingsValidationErrors errors, Repository repository) {
        if (settings.getString("url", "").isEmpty()) {
            errors.addFieldError("url", "Url field is blank, please supply one");
        }
    }
}
```

### Adding Icons

Each hook can have an icon to display in the repository hook administration screen.
See the [repository hook module type](../reference/plugin-module-types/repository-hook-plugin-module.html) for details.

### Marketplace

If and when you decide to add your plugin to Atlassian's [Marketplace](https://marketplace.atlassian.com), you can make
your plugin more discoverable by selecting the "Repository Hooks" category when creating your plugin.

### Tips

<div class="aui-message info shadowed">
    <h4 class="title"><a name="Hooks_and_Forks"></a>Hooks and Forks</h4>
    <span class="aui-icon icon-info"></span>
    <p>
        With the introduction of Forks in Stash 2.4 there are some extra considerations with regard to hooks. Due to
        the nature of forks, hooks on the parent repository will not fire for pushes made to the forked copy. When those
        changes are merged into the parent repository via a pull request, only merge checks are run, not pre-receive hooks.
        Instead, in addition to any checks that you wish to enforce with a pre-receive hook, consider also adding a
        companion <a href="../tutorials-and-examples/controlling-when-pull-requests-can-be-merged.html">merge-check</a>
        that ensures the same set of conditions still hold, which may be crucial for quality control.
    </p>
    <p>
        For more information please see <a href="https://confluence.atlassian.com/display/BitbucketServer/Workflow+strategies+in+Bitbucket+Server">Workflow strategies in Bitbucket Server</a>.
    </p>
</div>

<div class="aui-message warning shadowed">
    <h4 class="title"><a name="Performance"></a>Performance</h4>
    <span class="aui-icon icon-warning"></span>
    <p>
        When writing a <a href="../tutorials-and-examples/controlling-when-pull-requests-can-be-merged.html">merge-check</a>,
        it is important to realise that they are run on every page view of a pull request.
        This impacts the kinds of operations that can or should be run, such as contacting an external service or
        performing CPU-intensive tasks. In the case of slow operations the caching of results, based on something like
        the pull request commit, may need to be considered.
    </p>
</div>

<div class="aui-message warning shadowed">
    <h4 class="title"><a name="Thread_safety"></a>Thread safety</h4>
    <span class="aui-icon icon-warning"></span>
    In both examples the repository hooks follow the convention that the module class should be written to be thread-safe.
    If in-memory state or caching needs to be done then it is suggested that a separate 'component' be injected into the
    hook.
    <p />
    When writing hooks keep in mind that the ordering of the hooks is non-deterministic, and shouldn't be relied on.
    Passing state between hooks of the same type is fraught with danger and should not be attempted; each hook should be
    completely standalone.
</div>
