Last updatedApr 9, 2019

Registering and maintaining hook scripts

Overview

Hook scripts allow you to customize Git’s internal behavior and trigger customizable actions at key points in the development life cycle. They are programs that run automatically every time a particular event occurs in a Git repository, such as a push or merge. As a system admin, you can add one hook script and then enable (i.e.: configure) it for the entire system, all the repositories in selected projects, or individual repositories.

In addition:

  • you can use pre-commit hook scripts to reject pushes
  • hook scripts can echo information to the user’s terminal to tell them why their commit was rejected or give other information

This page describes how to register new scripts in the system and maintain existing ones.

Registering new hook scripts

There are two parts to registering a new hook script to be executed for a specific scope:

  1. Adding the hook script to the system
  2. Configuring the hook script for one or more repositories or projects

Adding hook scripts to the system

Adding a new script to Bitbucket Server is done using the HookScriptService. This passes a HookScriptCreateRequest into the create method. (Note: This method can only be called when the current user has SYS_ADMIN permissions)

The HookScriptCreateRequest needs the following information:

Variable nameDescription
NameThe name of the hook script you want to create.
PluginKeyThe key of your plugin as specified atlassian-plugin.xml. For example: com.atlassian.example.bitbucket.hook-script
TypeWhether it is a pre or post-style hook. Value: PRE or POST
ContentThe content of the hook script that will be executed
DescriptionAn optional description of the hook script

As an example, let's create a HookScriptCreateRequest for a script that prints the word hello every time you push to your repository.

1
2
3
4
5
6
HookScriptCreateRequest request = new HookScriptCreateRequest.Builder("script-name", "com.atlassian.example.bitbucket.hook-script", HookScriptType.PRE)
    .content("#!/bin/bash \n echo \"hello\"")
    .description("Just a hello world script")
    .build();

HookScript myScript = hookScriptService.create(request);

Configuring hook scripts

After adding a hook script, you need to configure it so the system knows when to execute it. You can do this by passing a HookScriptSetConfigurationRequest to setConfiguration in the HookScriptService. One thing to be aware of is the current user must have ADMIN permissions for the related scope.

The HookScriptSetConfigurationRequest needs the following information:

Variable nameDescription
Hook scriptThe hook script you want to use.
ScopeThe scope of your hook script. For example: Project, Repository, or Global.
TriggersThe triggers that define when to invoke the hook script. This needs to be a RepositoryHookTrigger.

Now let's use a HookScriptSetConfigurationRequest to configure the hook script.

1
2
3
4
5
6
7
8
9
10
Repository myRepository = repositoryService.getBySlug("PROJ", "my-repository");

//com.atlassian.bitbucket.scope.Scopes is a useful utility for creating a scope.
RepositoryScope scope = Scopes.repository(myRepository);

HookScriptSetConfigurationRequest configurationRequest = new HookScriptSetConfigurationRequest.Builder(myScript, scope)
    .triggers(StandardRepositoryHookTrigger.REPO_PUSH)
    .build();

HookScriptConfig config = HookScriptService.setConfiguration(configurationRequest);

Congratulations, you now have a script that prints hello every time you push to your repository!

Updating hook scripts

Updating existing hook scripts in the system

So far your script prints hello when you push to your repository. Next, let's update it to print hello world. You can do this by passing a HookScriptUpdateRequest into the update method of the HookScriptService.

The HookScriptUpdateRequest needs the following information:

Variable nameDescription
Hook scriptThe hook script you want to update.
ContentThe content of the script that will be executed
DescriptionAn optional description of the script

The HookScriptUpdateRequest will look like this:

1
2
3
4
5
HookScriptUpdateRequest update = new HookScriptUpdateRequest.Builder(myScript)
                .content("#!/bin/bash\n echo \"Hello world from $BB_REPO_SLUG\"")
                .build();

HookScript updatedScript = hookScriptService.create(update);

Updating a configuration

Updating a hook script configuration follows the process described above for creating a HookScriptSetConfigurationRequest.

Deleting hook scripts

Deleting hook script configurations

Deleting a configuration is as simple as passing a HookScriptRemoveConfigurationRequest into the hookScriptService. One thing to be aware of is the current user must have ADMIN permissions for the related scope.

A HookScriptRemoveConfigurationRequest needs the following information:

Variable nameDescription
Hook scriptThe hook script of the configuration that you want to remove.
ScopeThe scope the configuration that you want to remove.

Here's how you would delete the configuration of your hook script that prints hello world.

1
2
3
4
5
6
//com.atlassian.bitbucket.scope.Scopes is a usefull utility for creating a scope.
RepositoryScope scope = Scopes.repository(myRepository);

HookScriptRemoveConfigurationRequest deleteRequest = new HookScriptRemoveConfigurationRequest.Builder(myScript, scope).build();

hookScriptService.removeConfiguration(deleteRequest);

Deleting scripts from the system

You can delete a script from the system by calling the delete method on the HookScriptService. This method can only be called when the current user has SYS_ADMIN permissions. It will also delete all related configurations.

1
hookScriptService.delete(myScript);

Useful information

Retrieving a specific script

To retrieve a hook script, you need its id. This is why we recommend storing script ids for future usage. Here's a simple example of how to store and retrieve a specific script.

1
2
3
4
5
6
7
8
9
pluginSettings = pluginSettingsFactory.createGlobalSettings()

//Storing
HookScript myScript = hookScriptService.create(createRequest);
pluginSettings.put("com.atlassian.example.bitbucket.hook-script", myScript.getId());

//Retrieving
Long id = (Long) pluginSettings.get("com.atlassian.example.bitbucket.hook-script:my-script-id");
HookScript myScript = hookScriptService.getById(id);

Responding to operating system changes

When uploading a script it might have some operating specific logic attached to it, so it would be good to know when Bitbucket is migrated onto a different major operating system. This can be done by listening to a OperatingSystemChangedEvent.

What happens when a plugin is enabled or disabled

When a plugin that was previously used to create a script is disabled or uninstalled, all related hook scripts remain stored in the system along with their configurations and specific plugin key. As long as the plugin is disabled or uninstalled, these hook scripts will not be executed. When the plugin is re-enabled or reinstalled the scripts will then work as before.

Updating your plugin keys

For various reasons, plugin keys can sometimes change. To make sure your plugins still work, you may need to update the references to their keys. This can be done with the HookScriptService, specifically by using the updatePluginKey method.

Notes

See also Writing hook scripts