In this page

Overview

This page is about implementing custom hook scripts that integrate seamlessly with Better Commit Policy via its REST API.

Keep in mind that the app provides hook scripts for most major Version Control Systems out-of-the-box. In some situations, however, you may need to modify existing hook scripts or build custom hook scripts:

  • You use a Version Control System that is not supported. As the REST API is open and documented, you can add support for any proprietary system and any environment.
  • You already have some hooks implemented in your system and you want to "combine" those with the commit policy verifier hook scripts. Typically, verify the commit policy first, then execute your existing hook second.
  • Your environment does not meet the app's requirements. For instance, if you are using some exotic Python version and it cannot be upgraded, you may need to make minor changes in the hook script code.

What is a hook script?

All major Version Control Systems allow arbitrary program code to be executed on certain events. These so-called hook scripts (hooks in short) can be used to block certain operations on your source code repository or trigger external tasks, e.g. sending emails or initiating builds in a Continuous Integration System.

Better Commit Policy hooks naturally fall into the former category: right before a change in a repository would be committed, it contacts the server-side component (the app running in Jira, exposing a JSON-based REST API) to verify the changes. The REST returns whether the change is accepted, then the hook script instructs the Version Control System to accept or reject the commit.

Developing hook scripts

Different Version Control Systems have different requirements for hook scripts, but in general, hook scripts are pieces of executable code that are automatically launched by the Version Control System, receive some parameters and may return some result. Hook scripts can be written in any programming language that your target Version Control System supports, as long as it is capable of making REST API calls and processing the result correctly.

The built-in hook scripts are written in Python. We chose this, being a popular, portable and easy-to-read general-purpose programming language.

You are absolutely not restricted to use Python, however. For example, Git is very flexible in this question: you may choose Perl, PHP, shell script or even JavaScript if you wish.

Anatomy of a hook script

If you are writing your custom hook script, these are the general steps to be performed:

  1. Collect all information needed for the verification: the commit message, the file list, the author and so on. Your hook script will either receive those from the VCS as arguments, or it has to run VCS specific commands to find those out. These depend on the actual VCS, so please consult the documentation of the VCS on how to do that.
  2. Transform this information to the JSON schema used expected by the REST API end-point that does the actual verification. (See next item for link.)
  3. Authenticate to the Jira REST API. (The Better Commit Policy's REST API integrates into the standard Jira REST API, by adding new end-points, but by reusing authentication, for example.)
  4. Call the commit policy verification REST endpoint with the JSON you compiled.
  5. Process the result: parse JSON returned by the REST call.
  6. If the change is rejected, output the rejection message to the standard output (console) so that the user will see what's going on.
  7. Allow/block the VCS operation based on the verification result (accepted/rejected). Most VCS' expect the hook script to return a zero (accepted) or non-zero (rejected) status code, but it is better to check your VCS documentation.

Building hook scripts in Python

If you don't have a strong argument to use another programming language, we recommend writing your new hook scripts in Python for two reasons:

  • You can use the default hook scripts as examples.
  • You can re-use building blocks from the default hook scripts' code. Honestly, we encourage you to do that!
  • Python offers proven libraries for making REST calls and for any other sub-problem that may arise.
  • Python dictionaries are super-easy to convert to JSON, so they feel natural and straightforward to use.

Reusable Python modules

If you decide to use Python, we recommend you to a generate hook script package, extract the ZIP and study the following files.

jcp_common.py

This module is a "common utilities for any VCS" type of library, with features like:

  • create_file_update() creates a file descriptor for a single file change.
  • create_commit_dict() creates a descriptor for a single commit, to be sent for the REST verification service.
  • invoke_verify_service() contacts Jira and the REST verification service. It handles all details of the authentication, extracting and logging the result.
  • Platform allows you to check whether you are running on Windows or Linux, Python 2 or Python 3.
  • Logger is a simple logging facility.
jcp_git_common.py

This module offers utilities specifically for the Git VCS. Although this is small, it is definitely worth using it if you are working with Git.

A minimal hook script implementation

Assuming you are building on the top of jcp_common.py, implementing a basic hook is just a few lines of code. Note that we encourage keeping the configuration separately from the actual hook script logic, as the former may need to be different for different deployments, while the latter can be exactly the same.

First off, create jcp_config.py with this minimal configuration:

commit_policy_id = 1
jira_base_url = 'http://localhost:2990/jira'
jira_login = 'username'
jira_password = 'password'

jcp_token = ''
windows_default_encoding = None
ssl_verify = True

Then create the hook script with the file name that is probably determined by your VCS:

#!/usr/bin/python
# coding: utf-8

import sys
from jcp_config import *
from jcp_common import *

logger = Logger()
logger.script_start()

hook_platform.vcs = "git-local"

commits = [create_commit_dict(id=1234, committer="John Smith", branch="master",
		message="This is my commit message!", file_list=[create_file_update("test.txt", "m")])]

error_code = invoke_verify_service(commit_policy_id, commits, jira_base_url,
		jira_login, jira_password, jcp_token, hook_script_version="3.0.0")

logger.script_end()

sys.exit(error_code)

As you see, this snippet verifies a commit containing demo data. In the real world, you'd collect that from the VCS.

You can test this with Git (as a commit-msg hook):

> git commit -am "test"
========================================================================
                               REJECTED!
========================================================================
1.1 COMMIT [1234] on [master] Exactly one issue key must be mentioned in the commit message "This is my commit..."
========================================================================
                               REJECTED!
========================================================================

Questions?

Ask us any time.