Gitlab 読み (2)

sidekiq で掘削ログとなります。
とりあえず Sidekiq で検索。

$ find |xargs grep Sidekiq
./app/models/system_hook.rb:    Sidekiq::Client.enqueue(SystemHookWorker, id, data)
./app/workers/post_receive.rb:  include Sidekiq::Worker
./app/workers/system_hook_worker.rb:  include Sidekiq::Worker
./lib/tasks/gitlab/check.rake:    desc "GITLAB | Check the configuration of Sidekiq"
./lib/tasks/gitlab/check.rake:      start_checking "Sidekiq"
./lib/tasks/gitlab/check.rake:      finished_checking "Sidekiq"
./config/routes.rb:    mount Sidekiq::Web, at: "/admin/sidekiq", as: :sidekiq
./config/initializers/4_sidekiq.rb:Sidekiq.configure_server do |config|
./config/initializers/4_sidekiq.rb:Sidekiq.configure_client do |config|

Sidekiq::Worker を include してるソレを確認してみます。
app/workers/post_receive.rb が以下 (一部のみ)。

class PostReceive
  include Sidekiq::Worker

  sidekiq_options queue: :post_receive

  def perform(repo_path, oldrev, newrev, ref, identifier)

あるいは app/workers/system_hook_worker.rb が以下。

class SystemHookWorker
  include Sidekiq::Worker

  sidekiq_options queue: :system_hook

  def perform(hook_id, data)
    SystemHook.find(hook_id).execute data
  end
end

中身はスルーでとりあえずクラス名で grep してみます。

$ find app lib spec |xargs grep PostReceive
app/workers/post_receive.rb:class PostReceive
lib/hooks/post-receive:  env -i redis-cli rpush "resque:gitlab:queue:post_receive" "{\"class\":\"PostReceive\",\"args\":[\"$repo_path\",\"$oldrev\",\"$newrev\",\"$ref\",\"$GL_USER\"]}" > /dev/null 2>&1
spec/workers/post_receive_spec.rb:describe PostReceive do
spec/workers/post_receive_spec.rb:      PostReceive.new.should respond_to(:perform)
spec/workers/post_receive_spec.rb:      PostReceive.new.perform(pwd(project), 'sha-old', 'sha-new', 'refs/heads/master', key_id)
spec/workers/post_receive_spec.rb:      PostReceive.new.perform(pwd(project), 'sha-old', 'sha-new', 'refs/heads/master', key_id).should be_false
spec/workers/post_receive_spec.rb:      PostReceive.new.perform(pwd(project), 'sha-old', 'sha-new', 'refs/heads/master', key_id)

ちなみに lib/hooks/post-receive は doc/install/installation.md に以下な記述がありますね。

./doc/install/installation.md:    sudo cp ./lib/hooks/post-receive /home/git/.gitolite/hooks/common/post-receive

中身の一部が以下ですね。

$ cat lib/hooks/post-receive 
#!/usr/bin/env bash

# Version 4.1
# This file was placed here by GitLab. It makes sure that your pushed commits
# will be processed properly.

while read oldrev newrev ref
do
  # For every branch or tag that was pushed, create a Resque job in redis.

ちょっと hook 云々なあたりは確認必要かも。あるいは SystemHookWorker で grep してみると以下な出力。

$ find app lib spec |xargs grep SystemHookWorker
app/models/system_hook.rb:    Sidekiq::Client.enqueue(SystemHookWorker, id, data)
app/workers/system_hook_worker.rb:class SystemHookWorker

app/models/system_hook.rb の定義が以下。

# == Schema Information
#
# Table name: web_hooks
#
#  id         :integer          not null, primary key
#  url        :string(255)
#  project_id :integer
#  created_at :datetime         not null
#  updated_at :datetime         not null
#  type       :string(255)      default("ProjectHook")
#  service_id :integer
#

class SystemHook < WebHook
  def self.all_hooks_fire(data)
    SystemHook.all.each do |sh|
      sh.async_execute data
    end
  end

  def async_execute(data)
    Sidekiq::Client.enqueue(SystemHookWorker, id, data)
  end
end

ええと、SystemHook で grep してみるか。

$ find app lib spec |xargs grep SystemHook
app/models/system_hook.rb:class SystemHook < WebHook
app/models/system_hook.rb:    SystemHook.all.each do |sh|
app/models/system_hook.rb:    Sidekiq::Client.enqueue(SystemHookWorker, id, data)
app/observers/system_hook_observer.rb:class SystemHookObserver < ActiveRecord::Observer
app/observers/system_hook_observer.rb:      SystemHook.all_hooks_fire({
app/observers/system_hook_observer.rb:      SystemHook.all_hooks_fire({
app/observers/system_hook_observer.rb:      SystemHook.all_hooks_fire({
app/observers/system_hook_observer.rb:      SystemHook.all_hooks_fire({
app/observers/system_hook_observer.rb:      SystemHook.all_hooks_fire({
app/observers/system_hook_observer.rb:      SystemHook.all_hooks_fire({
app/controllers/admin/hooks_controller.rb:    @hooks = SystemHook.all
app/controllers/admin/hooks_controller.rb:    @hook = SystemHook.new
app/controllers/admin/hooks_controller.rb:    @hook = SystemHook.new(params[:hook])
app/controllers/admin/hooks_controller.rb:      @hooks = SystemHook.all
app/controllers/admin/hooks_controller.rb:    @hook = SystemHook.find(params[:id])
app/controllers/admin/hooks_controller.rb:    @hook = SystemHook.find(params[:hook_id])
app/workers/system_hook_worker.rb:class SystemHookWorker
app/workers/system_hook_worker.rb:    SystemHook.find(hook_id).execute data
spec/models/system_hook_spec.rb:describe SystemHook do
spec/requests/admin/admin_hooks_spec.rb:      expect { click_button "Add System Hook" }.to change(SystemHook, :count).by(1)

これ、help/system_hooks で諸々確認できますね。すばら。

Your GitLab instance can perform HTTP POST requests on the following events: create_project, delete_project, create_user, delete_user, change_team_member.

とのこと。で、admin/hooks では POST を送付する URL を登録できる形になっているのかどうか。LDAP が云々、な記述もありましたが Jenkins に云々、が可能なのかどうなのか。
あら、プロジェクトの Hooks から web hooks という項目がありますがこれは何かな。app/controllers/hooks_controller.rb というソレもありますね。model は project_hook.rb になるのか。

# == Schema Information
#
# Table name: web_hooks
#
#  id         :integer          not null, primary key
#  url        :string(255)
#  project_id :integer
#  created_at :datetime         not null
#  updated_at :datetime         not null
#  type       :string(255)      default("ProjectHook")
#  service_id :integer
#

class ProjectHook < WebHook
  belongs_to :project
end

むむ。Web Hook なヘルプが以下。

Every GitLab project can trigger a web server whenever the repo is pushed to.
Web Hooks can be used to update an external issue tracker, trigger CI builds, update a backup mirror, or even deploy to your production server.
GitLab will send POST request with commits information on every push.

push 契機で CI に POST して云々、というアレなのか。CI 側から poll しなくて良いのは確かに良いのですが、merge request 契機で云々、な機能があるんかな。
と、Jenkins に Github の pull request な plugin があるそうな。Gitlab で同様のソレがあるのかどうなのか。む、gitlab_ci というソレと merge_request が連携してそうなコードがありますね。

gitlab_ci?

以下なソレを発見

これ、どっかで試せないかな。

あるいは

以下を発見。

でもこれでは弱い。つうか jenkins の git-plugin に gitlab が云々、という記述が見えますね。Version 1.1.16 (released February 28, 2012) に

Support GitLab scm browser

という記述あり。あら、gitlab hook plugin というソレもあるみたい?

これは push な hook を云々、なのだな。

色々探してたら以下なのを発見。

うーん

app/controllers/merge_requests_controller.rb 掘削かな。
や、push 云々で、ってあたりなのか。app/models/web_hook.rb のあたり?
execute というメソドが見えますね。これを kickoff してるのはどこなのか。明日、掘削の時間が確保できるので確認してみます。