Edited at

gitの共有リポジトリにpushしたらChatworkにメッセージを通知する

More than 3 years have passed since last update.


追記

Slackにも通知できるようにした記事を書きました。


目的

複数人でgitの共有リポジトリにpushするようになると、コンフリクトの可能性や同僚の進捗などが気になることがあります。その際には変更の度に何らかのお知らせが届くと嬉しいですよね。今回はChatworkを使ったpushの通知機能を実装してみます。


仕様

今回は下記のような状況を想定しています。


  • gitを使ってソースコードを管理している。

  • GitHubなどの外部サービスを使わずに、自前のサーバー中にgit共有リポジトリを置いている。

  • Chatworkを利用している。

gitリポジトリに誰かがpushしたことを検知して、Chatworkの特定のチャットルームにコミット・メッセージを投稿します。あなたが管理しているリポジトリはおそらく1つや2つではないでしょうから、メッセージにはリポジトリ名とpushしたブランチ名が含まれるようにします。


githooks

古くからバージョン管理システムには様々なタイミングでプログラムを実行させる機構、通称 hooks と呼ばれる仕組みが有りました。当然gitにもhooksの仕組みが備わっています。gitのhooksはクライアントサイドフックとサーバーサイドフックに大別され、今回の目的ではサーバーサイドフックを利用します。サーバーサイドフックには下記の4種類があります。


  • pre-recieve

  • post-recieve

  • pre-update

  • post-update

フック名はフックを掛けるアクションと実行されるタイミングで構成されています。上記のフック名では、 prepost はそれぞれ該当するアクションの前後に実行されることを示しています。それでは recieveupdate が示しているアクションは何なのでしょうか? recieveupdate は双方ともにpushされたタイミングで呼び出されます。その違いはPro Git Bookに端的に示されています。


複数のブランチへのプッシュがあったときに pre-receive が実行されるのは一度だけですが、update はブランチ単位でそれぞれ一度ずつ実行されます。


今回の仕様では、ブランチ名を取得してブランチごとに投稿する必要が有り、また特にpushを拒否したりする必要はないため、post-updateを使用します。


参考


Chatwork API

Chatworkはクラウド型ビジネスチャットサービスで、複数人でのリアルタイムコミュニケーションを実現するためのツールです。また、API Tokenを申請すればWeb APIを利用することもでき、今回のような通知先として機能することができます。ただし、このAPIはまだベータ版という扱いらしく、申請してから許可が出るまで非常に時間がかかるので、思い立ったらすぐに申請しましょう。


参考


post-update

今回の仕様を満たすようなhooksスクリプトを作成しました。下記のBashスクリプトを適当に修正して、通知対象としたいすべてのリモートリポジトリの $REPOSITORY_ROOT/hooks/に置きます。実行権限をつけることも忘れないでください。

#!/bin/bash

set -eu

API_TOKEN="<CHANGE_THIS>"
ROOM_ID="<CHANGE_THIS>"

REPOS=$(basename $(pwd))
REPOS=${REPOS%.*}

BRANCH=$(git rev-parse --symbolic --abbrev-ref $1)
MSG=$(git log -1 --pretty=format:"%h - %an : %s" $BRANCH)

BODY="(${REPOS}) [${BRANCH}] ${MSG}"
if [[ "$BRANCH" = 'master' ]]; then
BODY="[info][title]PUSHED INTO \`master\` BRANCH!!![/title]${BODY}[/info]"
fi

curl -X POST -H "X-ChatWorkToken: ${API_TOKEN}" -d "body=${BODY}" "https://api.chatwork.com/v1/rooms/${ROOM_ID}/messages" > /dev/null 2>&1

exit 0

curl -LO https://gist.githubusercontent.com/artifactsauce/9480292/raw/post-update

vi post-update # 変数を修正
chmod 755 post-update
scp ./post-update $REMOTE_HOST:$REPOSITORY_ROOT/hooks/

$REPOSITORY_ROOT$REMOTE_HOSTはそれぞれ、リポジトリの最上位ディレクトリとリモートリポジトリを置いてあるホストの名前を示す任意の値とします。

次項以降でこのスクリプトの内容を解説します。


設定値

このスクリプトを正常に動作させるためには、冒頭の3つの変数の値を修正する必要があります。

まずはChatworkに投稿するための設定です。投稿ユーザーのAPIトークンと、投稿先のチャットルームのIDを設定します。

API_TOKEN="<CHANGE_THIS>"

ROOM_ID="<CHANGE_THIS>"

もう一つ、リポジトリ名を設定します。ハードコーディングしてありますが、上位ディレクトリの名前を動的に取得するという方法でも良いでしょう。

REPOS="<CHANGE_THIS>"


ブランチ名の取得

post-updateは引数を1つ受け取ります。それはリモート側のリポジトリの参照名(例:refs/heads/master)です。まずはこの値からブランチ名を取得します。

BRANCH=$(git rev-parse --symbolic --abbrev-ref $1)


メッセージの作成

取得した値からメッセージ・ボディーを作成します。メッセージはpushしたブランチの最後のコミットメッセージに、リポジトリ名およびブランチ名を付加したものとします。

MSG=$(git log -1 --pretty=format:"%h - %an : %s" $BRANCH)

BODY="(${REPOS}) [${BRANCH}] ${MSG}"

メッセージ・ボディーはもちろんご自由ですが、こんな感じになっていると嬉しいんじゃないでしょうか。masterにpushしたときだけ、強調されるようにしてみましょう。

if [[ "$BRANCH" = 'master' ]]; then

BODY="[info][title]PUSHED INTO \`master\` BRANCH!!![/title]${BODY}[/info]"
fi


投稿

最後にこの内容でWeb APIを通して投稿します。

curl -X POST -H "X-ChatWorkToken: ${API_TOKEN}" -d "body=${BODY}" "https://api.chatwork.com/v1/rooms/${ROOM_ID}/messages" > /dev/null

標準出力の内容がpush時に表示されるので/dev/nullに吐き出しておくことをお勧めします。


参考