git+slack連携

技術文書
2015/06/14

※参考URL
http://qiita.com/artifactsauce/items/242c71428fa85307c182

slackでIncoming WebHooks作成

gitサーバーperl環境構築

[root]$ yum install perl-JSON
[root]$ yum install perl-Net-SSLeay
[root]$ yum install perl-Crypt-SSLeay
[root]$ yum install perl-IO-Socket-SSL

gitサーバーにhook作成

[admin]$ vi /home/admin/git/x-generation.git/hooks/post-update

#!/usr/bin/env perl

package MyApp::Git::Hook::Notifier::Webhook;

use strict;
use warnings;
use utf8;
use Data::Dumper;

sub new {
    my $class = shift;
    my $self = { @_ };
    bless($self, $class);
    return $self;
}

sub _generate_ua {
    my $ua = LWP::UserAgent->new;
    return $ua;
}

sub send {
    my $self = shift;
    my ( $repo, $branch, $message ) = @_;
    my ( $url, $post_data, $headers ) = $self->_create_request_parameters( $repo, $branch, $message );
    my $ua = $self->_generate_ua();
    my $response = $ua->post($url, $post_data, %$headers);
    unless ($response->is_success) {
        warn $response->status_line;
        return 0;
    }
    return 1;
}

package MyApp::Git::Hook::Notifier::Slack;

use strict;
use warnings;
use utf8;
use Data::Dumper;
use JSON;

@MyApp::Git::Hook::Notifier::Slack::ISA = qw(MyApp::Git::Hook::Notifier::Webhook);

sub _create_request_parameters {
    my $self = shift;
    my ( $repo, $branch, $message ) = @_;

    my $endpoint = $self->{endpoint};
    #my $token    = $self->{token};
    my $channel  = $self->{channel};

    my $username = 'Git hooks';
    #my $icon     = ':jack_o_lantern:';

    #my $url  = "${endpoint}\?token\=${token}";
    my $url  = "${endpoint}";
    my $text = "(\`${repo}\`) [\`${branch}\`]";

    if ( $branch eq 'master' ) {
        $text = ":bell: PUSHED INTO \`master\` BRANCH!!!\n${text} ${message}";
    }
    elsif ( ! -f "refs/heads/$branch" ) {
        my @emojis = (
            ':neckbeard:',
            ':scream:',
            ':scream_cat:',
            ':see_no_evil:',
            ':hear_no_evil:',
            ':speak_no_evil:',
            ':rage1:',
            ':rage2:',
            ':rage3:',
            ':rage4:',
            ':trollface:',
        );
        my $emoji_index = int(rand(scalar @emojis));
        my $emoji = $emojis[$emoji_index];
        $text = "${text} ${emoji} Branch was deleted.";
    }
    else {
        $text = "${text} ${message}";
    }

    my $post_data = {
        payload => encode_json +{
            channel => $channel,
            username => $username,
            #icon_emoji => $icon,
            text => $text,
        },
    };

    return $url, $post_data, {};
}
package main;

use strict;
use warnings;
use utf8;
use Data::Dumper;
use FindBin qw($Bin);
use File::Basename qw/dirname/;
use JSON;
use Encode;
use Encode::Guess qw/shift-jis euc-jp 7bit-jis/;
use LWP::UserAgent;

if ( scalar @ARGV == 0 ) {
    die "[ERROR] Arguments not enough";
}

my $config  = _load_config();

my $repo = _get_repo_name();
my $branch  = _get_branch_name(@ARGV);
my $message = _get_commit_message($branch);

my %notifiers = (
    'slack' => 'MyApp::Git::Hook::Notifier::Slack',
    );

while ( my ($name, $module) = each %notifiers ) {
    my $notifier = {};
    eval "\$notifier = $module->new( \%{\$config->{$name}} )";
    unless ( $notifier->send( $repo, $branch, $message ) ) {
        warn "[WARN] Faild to send message.";
    }
}

exit;

sub _get_repo_name {
    my @dirs = split( /\//, dirname($Bin) );
    my $repo = pop @dirs;
    $repo =~s/\.git$//;
    return $repo;
}

sub _get_branch_name {
    my @args = @_;
    my $branch = `git rev-parse --symbolic --abbrev-ref $args[0] 2> /dev/null`;
    chomp $branch;
    return $branch;
}

sub _get_commit_message {
    my $branch = shift;
    my $message = `git log -1 --pretty=format:"%h - %an : %s" $branch 2> /dev/null`;
    return 'EMPTY' unless $message;
    my $decoder = Encode::Guess->guess($message);
    if ( ref $decoder ) {
        return $decoder->decode($message);
    }
    else {
        return $message;
    }
}

sub _load_config {
    return decode_json( join '', <DATA> );
}

1; # magic number

__DATA__
{
  "slack": {
    "endpoint": "https://hooks.slack.com/services/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",
    "channel": "#sdk" 
  }
}

endpointの箇所にslackで作成したwebhooksのURLをコピー

[admin]$ chmod 755 /home/admin/git/x-generation.git/hooks/post-update

文字化け対策

rubyバージョン

/home/admin/git/x-generation.git/hooks/post-update.rb

※参考サイト
http://qiita.com/tokumura11/items/a2b0a4af01e7b18a534d

[root]$ yum install rubygems
[root]$ yum install ruby-devel
[root]$ gem install json

rubyバージョンアップ
http://qiita.com/inouet/items/478f4228dbbcd442bfe8

[admin]$ ruby -v
ruby 1.9.3p551 (2014-11-13 revision 48407) [x86_64-linux]

phpバージョン

/home/admin/git/x-generation.git/hooks/post-update.php

#!/usr/bin/php
<?php

// slackで発行したwebhookURLをセット
$slack_webhook = "https://hooks.slack.com/services/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";

// slack channel
$channel = "#sdk";

// slack username
$username = "Git hooks";

// リポジトリ名
$repo = "x-generation";

// リビジョン取得
$rev = $argv[1];

// ブランチ取得
$cmd  = "git rev-parse --symbolic --abbrev-ref $rev 2> /dev/null";
$res = exec($cmd, $ret);
$branch = $ret[0];

// コミットメッセージ取得
$cmd = "git log -1 --pretty=format:\"%h - %an : %s\" $branch 2> /dev/null";
$res = exec($cmd, $ret);
for($i = 1; $i < count($ret); $i++) {
    $commit .= $ret[$i];
}

$text = "[ $repo ][ $branch ] $commit";

$post_array = array(
        'channel' => $channel,
        'username' => $username,
        'text' => $text
    );
//print_r($post_array);

// Start the CURL connection
$process = curl_init($slack_webhook);
curl_setopt($process, CURLOPT_POST, true);
curl_setopt($process, CURLOPT_POSTFIELDS, array('payload' => json_encode($post_array)));
curl_exec($process);
curl_close($process);
?>

ファイル