Last Updated: February 25, 2016
·
8.396K
· mavimo

Git commit message & Redmine

In our company we use Redmine and Git in our daily activities (yes,we coding every day :) ). We also like referencing Redmine issue in our commit message, eg:

git commit -m "refs #123: Lorem ipsum message"

and this is really usefull to connect code to issue.

Git have opportunity to use hooks to executing check during operation (commit, push, ...) so we can use a specific hook (commit-msg) to ensure our commit message are correctly conected to Redmine.

I create a simple script that you can use to "block" commit that don't match a specific pattern or refereicing a wrong issue in Redmine, eg:

git commit -m "refs 1234566890: Lorem ipsum" 
Commit need to be "[refs|fix] #ID: message"

or

git commit -m "refs #1234: Lorem ipsum"
You are working as user 3 but issue is not assigned to you

Requirement

You need to have git and bash on your machine, python is also required but I'm working to remove this dependence.

You need to enable REST WS in your Redmine, this is possible from admin / settings / autentication .

You need to find your API key in your profile page in Redmine ( https://redmine.yourcompany.com/my/account ).

Setup

You need to copy the following code in commit-msg hook. The hook file will be in yourepo/.git/hooks/commit-msg, and must be executable:

touch $YOUR_REPO/.git/hooks/commit-msg
chmod +x $YOUR_REPO/.git/hooks/commit-msg
edit $YOUR_REPO/.git/hooks/commit-msg

Paste the following code:

#!/bin/bash

regex="^(refs|fix)\s\#[0-9]+\:"
var=`head -n 1 $1`

function info {
  echo >&2 $1
}

function debug {
  debug=false
  if $debug
  then
    echo >&2 $1
  fi
}

function get_json {
  python -c "import sys;import json;j=json.loads(sys.stdin.read());print str(j$1);"
}

function redmine_json {
  redmine_host=$(git config redmine.host)
  redmine_apikey=$(git config redmine.apikey)
  curl  --silent -k -H "Content-Type: application/json" -X GET -H "X-Redmine-API-Key: $redmine_apikey" "$redmine_host/$1"
}

if [[ "$var" =~ $regex ]]
then
  debug "Commit message: OK"
else
  # Define format  message forfirst line in commit message
  info "Commit need to be \"[refs|fix] #ID: message\""
  exit 1
fi

issue_id=`echo $var | sed 's/\(refs\|fix\)\ \#\([0-9]*\).*/\2/'`
issue=`redmine_json "issues/$issue_id\.json"`

if [[ "$issue" != " " ]]
then
  debug "Issue exist:    OK"
else
  info "Issue $issue_id don't exist"
  exit 2;
fi

user=`redmine_json "users/current.json"`
user_id=`echo $user | get_json "['user']['id']"`
assigner_id=`echo $issue | get_json "['issue']['assigned_to']['id']"`

if [[ $user_id == $assigner_id ]]
then
  debug "Assigner:       OK"
else
  info "You are working as user $user_id but issue is not assigned to you"
  exit 3;
fi

redmine_host=$(git config redmine.host)

echo ""
echo "Issue ==========================="
echo "  refs:        $redmine_host/issues/$issue_id"
echo "  number:      #"`echo $issue | get_json "['issue']['id']"`
echo "  priority:    "`echo $issue | get_json "['issue']['priority']['name']"`
echo "  create from: "`echo $issue | get_json "['issue']['author']['name']"`
echo "  assigned to: "`echo $issue | get_json "['issue']['assigned_to']['name']"`
echo ""

More info in the script are in the more info section.

Configure

You also need to configure git to find redmine instance:

git config redmine.host https://redmine.yourcompany.com
git config redmine.apikey 1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef

now if you try to writing a wrong commit message recive an error and the commit will stop. If your commit message is ok, you can see:

Issue ===========================
  refs:        https://redmine.yourcompany.com/issues/1234
  number:      #1234
  priority:    Normal
  create from: Issue Creator
  assigned to: Your Name

Sometime you need to commit without referencing an issue or referencing an issue that is not assigned to you, you can skip control using --no-verify parameter.

More info

Our script is composed from two main function:

function get_json {
  python -c "import sys;import json;j=json.loads(sys.stdin.read());print str(j$1);"
}

This function parse input string (from stdin)9 asjson and and extract specified item, eg:

echo "{'test': {'some': 1,'element':3}}" | get_json '["test"]["element"]'

return 3.

The second function is

function redmine_json {
  redmine_host=$(git config redmine.host)
  redmine_apikey=$(git config redmine.apikey)
  curl  --silent -k -H "Content-Type: application/json" -X GET -H "X-Redmine-API-Key: $redmine_apikey" "$redmine_host/$1"
}

This make a request to redmine using API Key and host specified in git config and return response as JSON string.

redmine_json "users/current.json"

the other element of script are some simple check about data consistence.

2 Responses
Add your response

Hello,

Great Article!

But looks like the following portion will always succeed because you will get a 404 response even if the issue is not found. Am I missing something?

if [[ "$issue" != " " ]]
then
debug "Issue exist: OK"
else
info "Issue $issue_id don't exist"
exit 2;
fi

over 1 year ago ·

If your issue is not found hook exit without complete command (exit 2)

over 1 year ago ·