ScriptRunner allows you to easily write scripts to handle pre-receive events, which fire when a user pushes changes but before they are accepted in to the repository. The principle purpose of this type of hook is to block the push request and return a message to the user, if certain conditions are not fulfilled.

You can use the built-in content in conjunction with conditions to enforce your workflow. Typical examples of this would be:

  • prevent rewriting history on master or release branches

  • blocking deletion of release tags

  • prevent direct changes on a release branch, i.e. not via a merge

  • block certain users or groups of users from modifying sensitive code

Adding a Pre-Receive Hook

Navigate to Admin → Script Pre Hooks. Click a heading to add a handler. Choose Custom Pre-Hook to use your own scripts to decide whether to allow the push or not.

Diagnosable Conditions

Most of the built-in pre-receive hooks are applied based on an arbitrary condition. Diagnosable conditions allow you to show the user exactly why the hook was applied for their pushed changes in the hook error message.

One use of this is in the protect git references hook to show users what changes caused the hook to block their push.

For example you could use the following condition to verify all the commit authors are valid Bitbucket users and display the ones who aren’t in the hook error message:

import com.atlassian.bitbucket.user.ApplicationUser
import com.atlassian.bitbucket.user.Person

def authors = refChanges.getCommitAuthors(repository)
authors.findAll {
    if (! (it instanceof ApplicationUser)) {
        def person = it as Person
        hookMessage << "\$person.name - \$person.emailAddress is not a Bitbucket user\\n".toString()
        return true
    }

    return false
}
CODE

If you use pathsMatch and other variations of it you can use it as a diagnosable condition to automatically display the blocked paths and changes using the version here.

You could even add instructions or Git commands to the error message so the user can fix their pushed changes before pushing again.