概要
Gitlab には File hooks と呼ばれる機能がありあるイベント (例えばプロジェクトの作成) が実行されたときにスクリプトを自動で実行する機能があります
File hooks という機能は Gitlab 12.8 までは「Plugins」という名前で呼ばれていました
環境
- macOS 10.15.5
- GitLab Community Edition 12.9.2
- Ruby 2.6.5p114 (on gitlab)
docker を起動する際にプラグインディレクトリをマウントする
今回は gitlab は docker 上で動作させることを想定しています
VM で rails プロセスを動作させる場合でも仕組みは同じで「plugins」というディレクトリを特定の場所に設置しその配下に実行可能なスクリプトを作成すれば OK です
docker run -d -h gitlab.example.com \
-p 443:443 -p 80:80 -p 22:22 \
--name gitlab \
-v $(pwd)/gitlab/config:/etc/gitlab \
-v $(pwd)/gitlab/logs:/var/log/gitlab \
-v $(pwd)/gitlab/data:/var/opt/gitlab \
-v $(pwd)/gitlab/plugins:/opt/gitlab/embedded/service/gitlab-rails/plugins \
gitlab/gitlab-ce:latest
docker の場合は /opt/gitlab/embedded/service/gitlab-rails/plugins
というディレクトリがあるのでここにスクリプト配置するようにすれば OK です
スクリプト作成
docker にマウントしたパスにスクリプトを作成します
ホスト側で同じパスをマウントしているのでホスト側でスクリプトを作成すれば OK です
vim gitlab/plugins/app.rb
#!/opt/gitlab/embedded/bin/ruby
require 'json'
input = JSON.parse(STDIN.read)
File.open('./test.txt', 'w') do |f|
f.write(input)
end
とりあえずイベントの内容をコンテナ内にファイルとして保存するスクリプトです
イベントの内容は標準入力として来るのでそれを読み込みます
またスクリプトには必ずシェバングを入力する必要があります
docker バージョンの gitlab の場合は ruby は /opt/gitlab/embedded/bin/ruby
にあるのでこれを指定します
また Python や Perl などのスクリプトを実行したい場合は予め自分で python や perl をインストールする必要があります
スクリプトに実行権限を与える
chmod 755 gitlab/plugins/app.rb
これも重要です
内部で実行される際にはファイルが直接実行されます
そのためにシェバングも書きました
権限がない場合はスクリプトが実行されないので注意しましょう
動作確認
適当にプロジェクトを作成しましょう
そしてファイルが作成されているか確認します
docker exec gitlab find / -name "test.txt"
docker exec gitlab cat /var/opt/gitlab/gitlab-rails/working/test.txt
{"event_name"=>"project_destroy", "created_at"=>"2020-04-09T23:56:27Z", "updated_at"=>"2020-04-09T23:57:26Z", "name"=>"test3", "path"=>"test3", "path_with_namespace"=>"root/test3", "project_id"=>7, "owner_name"=>"Administrator", "owner_email"=>"admin@example.com", "project_visibility"=>"private"}
こんあ感じで JSON (ハッシュ) としてイベントの情報が記載されていることが確認できると思います
スクリプトを更新する場合は
コンテナにマウントしているので直接ホスト側からスクリプトを修正すれば OK です
特に gitlab コンテナの再起動などは必要ありません
スクリプトのログを標準出力に出すには
スクリプト内で普通に puts
などを実行しても docker logs には表示されませんでした
いろいろ調べたのですが見つからなかったので素直にファイルに吐き出すと良いと思います
#!/opt/gitlab/embedded/bin/ruby
require 'json'
require 'logger'
input = JSON.parse(STDIN.read)
logger = Logger.new('/var/log/gitlab/gitlab-rails/my_plugin.log')
logger.info(input)
File.open('./test.txt', 'w') do |f|
f.write(input)
end
docker exec gitlab cat /var/log/gitlab/gitlab-rails/my_plugin.log
ちなみにスクリプトが動作しなかった場合のエラーログは
docker exec gitlab cat /var/log/gitlab/gitlab-rails/plugin.log
で確認できます
E, [2020-04-09T23:56:30.964800 #494] ERROR -- : File Hook Error => /opt/gitlab/embedded/service/gitlab-rails/plugins/app.rb: /opt/gitlab/embedded/service/gitlab-rails/plugins/app.rb:2:in `sysopen': Permission denied @ rb_sysopen - /proc/1/fd/1 (Errno::EACCES)
特定のプロジェクトや issue にフックするには
例えば issue であれば object_kind
あたりを見ればいいと思います
また特定のプロジェクトにのみ反応するプラグインを作成したいのであれば project_id
あたりを見れば良いと思います
#!/opt/gitlab/embedded/bin/ruby
require 'json'
require 'logger'
input = JSON.parse(STDIN.read)
if input['project_id'] == 9 || input['project']['id'] == 9
logger = Logger.new('/var/log/gitlab/gitlab-rails/my_plugin.log')
logger.info(input)
File.open('./test.txt', 'w') do |f|
f.write(input)
end
end
issue を作成した場合は input['project']['id']
という感じで取得する必要があるようです
イベントによって入力される JSON の情報が若干異なるようなので注意が必要です
最後に
Gitlab で File hooks (Plugins) を試してみました
インストールはシステム全体に行うのが少し不安というかトラブルの元になる感じがします
プロジェクトごとやイベントごとのハンドリングはすべてスクリプト内で行います
ruby gems などのライブラリを使いたい場合は事前に gitlab server にグローバルインストールしておく必要がありそうです
また複数の gitlab server がある場合はすべての server にスクリプトを配置する必要があるのも注意が必要です
0 件のコメント:
コメントを投稿