Skip to content

Instantly share code, notes, and snippets.

@jerowe
Last active August 29, 2015 14:00
Show Gist options
  • Save jerowe/11398842 to your computer and use it in GitHub Desktop.
Save jerowe/11398842 to your computer and use it in GitHub Desktop.
Git Hook for nicely formatted Redmine Commits

Get nicely formatted commits. Drop the script into projectdir/.git/hooks/git-commit-msg.pl.

git commit -m "commiting some issues refs #1420 @0"

Gets you

[jillian@localhost]$ git commit -m "commiting some issues refs #1420 @0"
======================================================================================================================
              Commiting issue:                                                                  1420
                      Project:                                                           WebServices
                Issue Subject:                                            Change config for all apps
                       Author:                                                          Jillian Rowe
                  Assigned to:                                                          Jillian Rowe
                     Priority:                                                                Normal
                  Spent Hours:                                                                     4
======================================================================================================================
[develop 156b21d] commiting some issues refs #1420 @0

If you are running :Git commit from within vim you must escape the hash key.

:Git commit -m "commiting some issues refs \#1420 @0
#!/usr/bin/env perl 
#===============================================================================
#
#         FILE:  commit-msg-hook.pl
#
#        USAGE:  ./commit-msg-hook.pl  
#
#  DESCRIPTION: Create commit hook that makes sure a message refs/closes/fixes a redmine ticket and prints info about that ticket 
#
#       AUTHOR:  Jillian Rowe, 
#      COMPANY:  
#      VERSION:  1.0
#      CREATED:  03/06/2014 10:35:31 AM
#     REVISION:  ---
#===============================================================================

use strict;
use warnings;

package Init;

use REST::Client;
use MIME::Base64;  
use JSON;  
use Carp qw(carp cluck longmess shortmess);
use URI;
use JSON;
use Data::Dumper;
use Scalar::Util qw(looks_like_number);

#Will change this to Moosex:Getopt command line arguements
use Moose;

$ENV{PERL_LWP_SSL_VERIFY_HOSTNAME}=0;

has 'host' => (
    is => 'rw',
    isa => 'Str',
    required => 0,
    default => qw{https://your-redmine-install-here}, 
);

has 'apiKey' => (
    is => 'rw',
    isa => 'Str',
    required => 0,
    default => qw{your-api-key},
);

has rest => (
    is => 'rw',
    isa => 'REST::Client',
    required => 1,
    default => sub { return REST::Client->new() },
);

has jsonheader => (
    is => 'rw',
    isa => 'HashRef',
    required => 1,
    default => sub { my $headers = {}; $headers->{'Content-Type'} = 'application/json;charset=UTF-8'; return $headers; },
);

has verbose => (
    is => 'rw',
    isa => 'Bool',
    required => 1,
    default => sub {return 0}, 
);

#Connection
sub connect{
    my $self = shift;

    $self->rest->setFollow(1);

    $self->rest->addHeader('X-Redmine-API-Key' =>  $self->apiKey);

    $self->rest->setHost($self->host);

    $self->test;
}

sub test{
    my $self = shift;

    $self->rest->GET('/projects.json', $self->jsonheader);

    if($self->rest->responseCode == 200){
        print "Connection seems ok\n" if $self->verbose;
    }
}

#Ticket
###TODO check for watcher

sub lookup_ticket{
    my($self, $id) = @_;

    carp "Id is not a number ".Dumper($id) unless looks_like_number($id);
    $self->rest->GET("/issues/$id.json");
#    print Dumper($self->rest->responseContent);
    return $self->rest->responseContent;

}

package Main;

use Git::Hooks;
use File::Slurp;
use Data::Dumper;
use JSON; # imports encode_json, decode_json, to_json and from_json.

my $api = Init->new();
$api->connect();

COMMIT_MSG {
    my ($git, $commitfile) = @_;

    my $msg = read_file( $commitfile ) or die print "Couldn't open commit file! $! \n" ;

    if($msg =~ m/closes|refs|fixes/ && $msg =~ m/#(\d+)/){
        die print "Couldn't match ticket id...\n" unless $1;
        my $jstr = $api->lookup_ticket($1);
        my $json = JSON->new->allow_nonref;

        my $href = $json->decode( $jstr );

        print "======================================================================================================================\n";

        printf("%30s%70s\n","Commiting issue:", $1);
        printf("%30s%70s\n","Project:", $href->{issue}->{project}->{name});
        printf("%30s%70s\n","Roadmap Target Version:", $href->{issue}->{fixed_version}->{name}) if exists $href->{issue}->{fixed_version};
        printf("%30s%70s\n","Issue Subject:", $href->{issue}->{subject});
        printf("%30s%70s\n","Author:", $href->{issue}->{author}->{name});
        printf("%30s%70s\n","Assigned to:", $href->{issue}->{assigned_to}->{name});
        printf("%30s%70s\n","Priority:", $href->{issue}->{priority}->{name});
        printf("%30s%70s\n","Spent Hours:", $href->{issue}->{spent_hours});

        print "======================================================================================================================\n";
    }
    else{
        print "Doesn't reference a ticket!\n";
        print "Message is $msg\n";
        die;
    }

    return 1;
};

run_hook($0, @ARGV);

Note for perlbrew users. You must have Git.pm in your $PERL5LIB. It is not offered as a cpan module, and the fix for this is.

cd /tmp
wget https://raw.githubusercontent.com/git/git/master/perl/Git.pm
mv Git.pm $PERL5LIB

Acknowledgements

This module was originally developed at and for Weill Cornell Medical College in Qatar within ITS Advanced Computing Team. With approval from WCMC-Q, this information was generalized and put on github, for which the authors would like to express their gratitude.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment