Enforce a merge strategy per-branch using a merge hook
Asked by talg1978:

I'm trying to create a merge hook which allows/forbids **merge strategy**(ff/squash/commit...) on a per-branch basis.

That is, after clicking the 'Merge' button on a PR, only selective types of merge types shall be available from the drop-down menu.

I have already created a skeleton hook from scratch using Atlassian SDK, but I can't figure out how to tweak it to control the merge menu (or any other field in the merge page).


Answers:
author: Ulrich Kuhnhardt _IzymesCo_
body: Hello there

with your implementation of RepositoryMergeCheck comes

```
@Override
public RepositoryHookResult preUpdate(@Nonnull PreRepositoryHookContext context,
                                      @Nonnull PullRequestMergeHookRequest mergeHookRequest) {
    // get merge strategy by id
    Optional<String> mergeStrategy = request.getStrategyId();
...
}

```

There you can check which strategy is selected to the PR and return

```
RepositoryHookResult.accepted();
```

or

```
RepositoryHookResult.rejected(message, description)
```

Let me know how you go

Best Ulrich

[Izymes](https://marketplace.atlassian.com/vendors/1210584/izymes-pty-ltd) // Eliminate boring from work

comments: author: talg1978
body: Hey Ulrich, Thank you so much. I was using a deprecated alternative and now thanks to you I got it right.


author: talg1978
body: Hi [@Ulrich Kuhnhardt _IzymesCo_](/t5/user/viewprofilepage/user-id/4011392) ,

After some time off, I'm back with this issue (Thanks again, your prior answer got me significantly ahead).  

The thing is:  
The approach you suggested (If I got it right), accepts or rejects the option to proceed from the Pull Request page to the Merge page (by enabling/disabling the 'Merge' button):  
![merge_button.png](https://community.atlassian.com/t5/image/serverpage/image-id/191414i2C4F18F1FAF6BB7E/image-size/large?v=v2&px=999 "merge_button.png")

**I need something slightly different.**   
I would like to control the possible merge strategies in the drop-down menu once **in**the merge page.

<br />

![merge_strategy.png](https://community.atlassian.com/t5/image/serverpage/image-id/191419i927BD0EA2FBC0072/image-size/large?v=v2&px=999 "merge_strategy.png")

**Is there a way to achieve this?**


author: Ulrich Kuhnhardt _IzymesCo_
body: Glad you're making some progress. You can configure available [repository merge strategies](https://confluence.atlassian.com/bitbucketserver/pull-request-merge-strategies-844499235.html#Pullrequestmergestrategies-Configuremergestrategiesforanindividualrepository) - and only those will be enabled for the merge commit dropdown.

If your hook enforces a certain merge strategy and other strategies are available in the dropdown - the PR will be merged by Bitbucket only if the right strategy is selected. Otherwise the hook will block the merge process.

If you want branch-specific merge strategies you may use a tool like [Workzone](https://marketplace.atlassian.com/apps/1211303/workzone-pullrequest-workflow?hosting=datacenter&tab=overview)\^ to configure your merge process with more granular control.

Let me know how you go,

Best, Ulrich

\^ Disclaimer: Workzone is one of our apps for Bitbucket (Cloud, DC and server)


author: talg1978
body: Thanks [@Ulrich Kuhnhardt _IzymesCo_](/t5/user/viewprofilepage/user-id/4011392) ,

That's helpful, but how do I make my hook to "*enforce a certain merge strategy*" ?

BR, Tal.


author: Ulrich Kuhnhardt _IzymesCo_
body: Good question! Your hook implementation (see above) either returns

```
RepositoryHookResult.rejected('reason', 'description')
```

and Bitbucket will not be able to merge.

Or if the right strategy is selected the hook returns

```
RepositoryHookResult.accepted()
```

Hope that helps you further.

Best, Ulrich


author: talg1978
body: Thanks [@Ulrich Kuhnhardt _IzymesCo_](/t5/user/viewprofilepage/user-id/4011392)

Right, I got this.  
The thing is "preUpdate" is executed **when clicking the merge button on the PR page.** At this stage - there is no selected strategy at all, because we select it on the merge dialog box which pops up afterwards:  

![Screenshot 2022-04-06 125132.png](https://community.atlassian.com/t5/image/serverpage/image-id/191734i164ADEB35F599EBF/image-dimensions/304x128?v=v2 "Screenshot 2022-04-06 125132.png")

Returning:

```
RepositoryHookResult.rejected('reason', 'description')
```

by the 'preUpdate' method cannot rely on the merge strategy simply because there is none selected at this point (it is 'Optional.Empty' at this point).  

Maybe I'm using the wrong method? Is there a method which is executed once actually triggering the merge in the **merge dialog box?**BR, Tal


author: Ulrich Kuhnhardt _IzymesCo_
body: 'preUpdate' is used on 2 occasions:

1. When rendering the merge button (disabling it, if rejected)

2. When actually merging the PR, the merge fails if rejected by hook

You can make merge strategies available in [repository or project settings](https://confluence.atlassian.com/bitbucketserver/pull-request-merge-strategies-844499235.html#Pullrequestmergestrategies-Configuremergestrategiesforanindividualrepository).

If more than one is available the user can't merge, I don't know though if the merge popup modal button will be disabled, i.e. if the change in the selected value would trigger a merge-check in the back-end to validate the method.

Can you just configure merge-strategies that are allowed on project or repo level?

Here's another thought: Have you tried for the hook to _update_ the PR merge strategy to the correct one by modifying the pull request? I would confirm with the Atlassian bitbucket team though if that's possible.


author: talg1978
body: Hi Ulrich - thanks again!

**I got it to work!**

My hook now ++accepts++ the first occasion ("*When rendering the merge button* "), by simply checking if the *optional* StrategyId is **empty** (it is empty because I didn't have the chance to set it yet.)  
Now, the second occasion ("*When actually merging the PR* ") is triggered when clicking the merge button on the modal popup. *Here* , a strategy is already selected and I can work with it to run the logic I'm aiming for and ++reject++ forbidden workflows.

*"Can you just configure merge-strategies that are allowed on project or repo level?"*-No... as the header of the discussion says, I need to apply a per-branch logic.

Here's a screenshot (ignore the logic it implements, it's just a POC):

![Screenshot 2022-04-07 145519.png](https://community.atlassian.com/t5/image/serverpage/image-id/191971i02FB38D95CD9C79D/image-size/large?v=v2&px=999 "Screenshot 2022-04-07 145519.png")

**Thanks so much for your valuable and persistent help,**

**BR, Tal.**


author: Juli?n Lastiri
body: [@talg1978](/t5/user/viewprofilepage/user-id/4803712), [@Ulrich Kuhnhardt _IzymesCo_](/t5/user/viewprofilepage/user-id/4011392)  
Have you implemented the hook this though the admin interface?  
I am trying to solve the same issue but I don't have access to the admin interface and I didn't find a hook I can use for this purpose. However, I have access to ScriptRunner and implement a Conditional Merge Check.  
Do you know how can I check the merge strategy using ScriptRunner?  

Thanks.


author: John Alberts
body: I'm trying to do the same thing. [@Juli?n Lastiri](/t5/user/viewprofilepage/user-id/5115157) Did you ever get this implemented and if so, is the code available publicly?

[@talg1978](/t5/user/viewprofilepage/user-id/4803712) Is your code available publicly by chance?

Thanks


Tags: bitbucket-server

hook

merge

server