ククログ

株式会社クリアコード > ククログ > Git でコミットメールを配信する方法

Git でコミットメールを配信する方法

クリアコードが開発に関わっているプロジェクトではdiff付きのコミットメールを流すようにしています。

コミットメールを流すための方法を紹介します1

使用しているのは以下の2つのGemです。

環境はDebian GNU/Linux wheezyを想定しています。Rubyのバージョンは1.9.3以降であれば問題ありません。

専用のユーザを用意します。

$ sudo useradd app

アプリケーションをデプロイするディレクトリを用意します。

$ sudo mkdir -p /srv/www/webapps/web-hooks-receiver
$ sudo chwon -R app:app /srv/www/webapps

/srv/www/webapps/web-hooks-receiver/Gemfileを用意します。

source "https://rubygems.org"

gem "git-commit-mailer"
gem "github-web-hooks-receiver"

ここではApache+Passengerでセットアップします3

以下のコマンドを実行し、必要なGemをインストールします。

$ cd /srv/www/webapps/web-hooks-receiver
$ sudo -u app -H bundle install --binstubs --path vendor/bundle --without=development,test

ここで--binstubsオプションを付けているのは、カレントディレクトリのbin以下にgit-commit-mailerコマンドをインストールするためです。

Rackアプリケーションとして動作させるための設定ファイルconfig.ruを用意します。

require "yaml"
require "pathname"
require "github-web-hooks-receiver"

use Rack::CommonLogger
use Rack::Runtime
use Rack::ContentLength

base_dir = Pathname(__FILE__).realpath.dirname
config_file = base_dir + "config.yaml"
options = YAML.load_file(config_file.to_s)

map "/post-receiver/" do
  run GitHubWebHooksReceiver::App.new(options)
end

もし、GitHubWebHooksReceiver::Appの実行中に発生したエラーをメールで通知したい場合は、exception_notificationrackngaを使うと良いでしょう。

Passenger の設定は以下のようにします4

/etc/apache2/sites-available/github-web-hooks-receiver:

<VirtualHost *:80>
  ServerName web-hooks-receiver.example.com
  DocumentRoot /srv/www/webapps/web-hooks-receiver/public
  <Directory /srv/www/webapps/web-hooks-receiver/public>
     AllowOverride all
     Options -MultiViews
  </Directory>

  ErrorLog ${APACHE_LOG_DIR}/web-hooks-receiver_error.log
  CustomLog ${APACHE_LOG_DIR}/web-hooks-receiver_access.log combined

  AllowEncodedSlashes On
  AcceptPathInfo On
</VirtualHost>

/etc/apache2/mods-available/passenger.conf:

PassengerRoot /path/to/passenger
PassengerRuby /path/to/ruby

/etc/apache2/mods-available/passenger.load:

LoadModule passenger_module /path/to/mod_passenger.so

GitHubWebHooksReceiver用の設定ファイルconfig.yamlを用意します5

base_dir: /srv/www/webapps/web-hooks-receiver
mirrors_directory: mirrors
git_commit_mailer: bin/git-commit-mailer
to: 
  - commit+default@example.com
error_to: commit+error@example.com
exception_notifier:
  subject_label: "[git-commit-mailer]"
sender: null+git-commit-mailer@example.com
add_html: false
domains:
  github.com:
    owners:
      clear-code:
        to: commit@example.com
        from: null+github@example.com
        repositories:
          cutter:
            to:
              - cutter-commit@lists.sourceforge.net
          cutter-macports:
            to:
              - cutter-commit@lists.sourceforge.net
          pikzie:
            to:
              - pikzie-commit@lists.sourceforge.net
      rabbit-shocker:
        to: commit@ml.rabbit-shocker.org
        from: null@rabbit-shocker.org
  gitlab.example.com:
    to: commit+internal@example.com
    from: null+gitlab@example.com

base_dir

基準となるディレクトリを絶対パスで指定します。

mirrors_directory

Gitリポジトリをミラーするディレクトリをbase_dir からの相対パス、または、絶対パスで指定します。 省略すると#&#123;base_dir&#125;/mirrorsを使用します。

git_commit_mailer

git-commit-mailer コマンドへのパスを指定します。 ruby コマンドの引数として実行するので、任意の Ruby スクリプトでも構いません。

error_to

エラーが発生したときの宛先を指定します。

to

コミットメールの宛先を配列で指定します。

sender

送信者のメールアドレスを指定します。 Sender ヘッダーの値や from が指定されなかった場合のエンベロープFromの値として使用します。

from

省略すると Author の name と email から「Commiter Name commiter@example.com」のようなメールアドレスを生成して使用します。指定可能なのはメールアドレスの部分のみです。

add_html

true を指定すると、HTMLメールで色付きのdiffを生成します。

send_per_to

true を指定するとtoごとに別のSMTPセッションでコミットメールを送信します。

sleep_per_mail

コミットメールを一通送信するごとに指定された秒数だけsleepします。

コミットメールの宛先を指定する方法

以下の4つの単位で指定することができます。マッチした条件のうち最も小さい範囲にコミットメールを送信します。

  • 全体
  • ドメイン単位
  • オーナー単位
  • リポジトリ単位

上の例で言うと、以下のように配信します。

  • github.com の clear-code organization にある cutter, cutter-macports リポジトリは cutter-commit@lists.sourceforge.net にコミットメールを配信する。その際 From ヘッダーの値には Author の name と email を使用する。
  • github.com の clear-code organization にある pikzie リポジトリは pikzie-commit@lists.sourceforge.net にコミットメールを配信する。その際 From ヘッダーの値には Author の name と email を使用する。
  • github.com の clear-code organization にある cutter, cutter-macports, pikzie 以外のリポジトリは commit@example.com にコミットメールを配信する。その際 From ヘッダーの値には Author の name と null+github@example.com を使用する。
  • github.com の rabbit-shocker organization の全てのリポジトリは commit@ml.rabbit-shocker.org へコミットメールを配信する。その際 From ヘッダーの値は Author の name と null@rabbit-shocker.org を使用する。
  • gitlab.example.com の全てのリポジトリは commit+internal@example.com へコミットメールを配信する。その際 From ヘッダーの値には Author の name と null+gitlab@example.com を使用する。
  • 上記全ての条件にマッチしないリポジトリは commit+default@example.com へコミットメールを配信する。その際 From ヘッダーの値には Author の name と email を使用する。

プライベートリポジトリのコミットメールを流す場合

GitHubやGH:Eの場合は、検証していないのでわかりません。検証した人はこっそり教えてください。

GitLab の場合は、全てのリポジトリにReporter権限のユーザーを追加して、そのユーザーにパスフレーズなしの公開鍵を登録します。その上で以下のコマンドを一度実行して $HOME/.ssh/known_hosts に情報を登録しておきます。

$ ssh -T git@gitlab.example.com

この作業を忘れると、コミットメール配信用のリポジトリをミラーできません。

予告

GitLab でリポジトリを追加するたびに手動でWeb hookを追加するのは面倒です。 そこで、自動でWeb hookを登録できるWeb hook6としてgitlab-system-hooks-receiverを作りました。

またGitHubで自分の管理下にないリポジトリのdiff付きのコミットメールを読みたくなることがあると思います。GitHubのフィードだとdiffが付いていないため、diffの確認に一手間かかってしまいます。github-event-watcherを使うと自分の管理下にないリポジトリでもdiff付きのコミットメールを配信することができます。

次回はそれらの使い方を紹介します。

まとめ

GitHubやGitLabにあるリポジトリのコミットを色付きのdiffを含むコミットメールで通知する方法を紹介しました。

  1. 元々 git-utilsとして開発していたものですが、より使いやすくするためにGemとして公開しました。

  2. GitLabやGH:Eも対応しています

  3. 他のアプリケーションサーバを使うときは適宜読み替えてください。

  4. Passengerの設定方法はpassenger-install-apache2-moduleコマンドを実行したときにも表示されます。

  5. クリアコードで使用しているものをアレンジしたものです。

  6. GitLabではSystem hookと呼び通常のWeb hookとは区別しています。