Commit 3c6daec4b1194f5a2c43fcc5b7e370cd5c8add1e

Authored by Dmitriy Zaporozhets
2 parents 14649525 60ee383e

Merge branch 'sys_hooks' of dev.gitlabhq.com:gitlabhq

@@ -71,7 +71,6 @@ group :development, :test do @@ -71,7 +71,6 @@ group :development, :test do
71 gem "awesome_print" 71 gem "awesome_print"
72 gem "database_cleaner" 72 gem "database_cleaner"
73 gem "launchy" 73 gem "launchy"
74 - gem "webmock"  
75 end 74 end
76 75
77 group :test do 76 group :test do
@@ -82,4 +81,5 @@ group :test do @@ -82,4 +81,5 @@ group :test do
82 gem "shoulda-matchers" 81 gem "shoulda-matchers"
83 gem 'email_spec' 82 gem 'email_spec'
84 gem 'resque_spec' 83 gem 'resque_spec'
  84 + gem "webmock"
85 end 85 end
app/controllers/admin/hooks_controller.rb 0 → 100644
@@ -0,0 +1,44 @@ @@ -0,0 +1,44 @@
  1 +class Admin::HooksController < ApplicationController
  2 + layout "admin"
  3 + before_filter :authenticate_user!
  4 + before_filter :authenticate_admin!
  5 +
  6 + def index
  7 + @hooks = SystemHook.all
  8 + @hook = SystemHook.new
  9 + end
  10 +
  11 + def create
  12 + @hook = SystemHook.new(params[:hook])
  13 +
  14 + if @hook.save
  15 + redirect_to admin_hooks_path, notice: 'Hook was successfully created.'
  16 + else
  17 + @hooks = SystemHook.all
  18 + render :index
  19 + end
  20 + end
  21 +
  22 + def destroy
  23 + @hook = SystemHook.find(params[:id])
  24 + @hook.destroy
  25 +
  26 + redirect_to admin_hooks_path
  27 + end
  28 +
  29 +
  30 + def test
  31 + @hook = SystemHook.find(params[:hook_id])
  32 + data = {
  33 + event_name: "project_create",
  34 + name: "Ruby",
  35 + path: "ruby",
  36 + project_id: 1,
  37 + owner_name: "Someone",
  38 + owner_email: "example@gitlabhq.com"
  39 + }
  40 + @hook.execute(data)
  41 +
  42 + redirect_to :back
  43 + end
  44 +end
app/controllers/admin/mailer_controller.rb
@@ -1,45 +0,0 @@ @@ -1,45 +0,0 @@
1 -class Admin::MailerController < ApplicationController  
2 - layout "admin"  
3 - before_filter :authenticate_user!  
4 - before_filter :authenticate_admin!  
5 -  
6 - def preview  
7 -  
8 - end  
9 -  
10 - def preview_note  
11 - @note = Note.first  
12 - @user = @note.author  
13 - @project = @note.project  
14 - case params[:type]  
15 - when "Commit" then  
16 - @commit = @project.commit  
17 - render :file => 'notify/note_commit_email', :layout => 'notify'  
18 - when "Issue" then  
19 - @issue = Issue.first  
20 - render :file => 'notify/note_issue_email', :layout => 'notify'  
21 - else  
22 - render :file => 'notify/note_wall_email', :layout => 'notify'  
23 - end  
24 - rescue  
25 - render :text => "Preview not available"  
26 - end  
27 -  
28 - def preview_user_new  
29 - @user = User.first  
30 - @password = "DHasJKDHAS!"  
31 -  
32 - render :file => 'notify/new_user_email', :layout => 'notify'  
33 - rescue  
34 - render :text => "Preview not available"  
35 - end  
36 -  
37 - def preview_issue_new  
38 - @issue = Issue.first  
39 - @user = @issue.assignee  
40 - @project = @issue.project  
41 - render :file => 'notify/new_issue_email', :layout => 'notify'  
42 - rescue  
43 - render :text => "Preview not available"  
44 - end  
45 -end  
app/controllers/hooks_controller.rb
@@ -11,24 +11,24 @@ class HooksController &lt; ApplicationController @@ -11,24 +11,24 @@ class HooksController &lt; ApplicationController
11 respond_to :html 11 respond_to :html
12 12
13 def index 13 def index
14 - @hooks = @project.web_hooks.all  
15 - @hook = WebHook.new 14 + @hooks = @project.hooks.all
  15 + @hook = ProjectHook.new
16 end 16 end
17 17
18 def create 18 def create
19 - @hook = @project.web_hooks.new(params[:hook]) 19 + @hook = @project.hooks.new(params[:hook])
20 @hook.save 20 @hook.save
21 21
22 if @hook.valid? 22 if @hook.valid?
23 redirect_to project_hooks_path(@project) 23 redirect_to project_hooks_path(@project)
24 else 24 else
25 - @hooks = @project.web_hooks.all 25 + @hooks = @project.hooks.all
26 render :index 26 render :index
27 end 27 end
28 end 28 end
29 29
30 def test 30 def test
31 - @hook = @project.web_hooks.find(params[:id]) 31 + @hook = @project.hooks.find(params[:id])
32 commits = @project.commits(@project.default_branch, nil, 3) 32 commits = @project.commits(@project.default_branch, nil, 3)
33 data = @project.post_receive_data(commits.last.id, commits.first.id, "refs/heads/#{@project.default_branch}", current_user) 33 data = @project.post_receive_data(commits.last.id, commits.first.id, "refs/heads/#{@project.default_branch}", current_user)
34 @hook.execute(data) 34 @hook.execute(data)
@@ -37,7 +37,7 @@ class HooksController &lt; ApplicationController @@ -37,7 +37,7 @@ class HooksController &lt; ApplicationController
37 end 37 end
38 38
39 def destroy 39 def destroy
40 - @hook = @project.web_hooks.find(params[:id]) 40 + @hook = @project.hooks.find(params[:id])
41 @hook.destroy 41 @hook.destroy
42 42
43 redirect_to project_hooks_path(@project) 43 redirect_to project_hooks_path(@project)
app/models/project.rb
@@ -19,7 +19,7 @@ class Project &lt; ActiveRecord::Base @@ -19,7 +19,7 @@ class Project &lt; ActiveRecord::Base
19 has_many :notes, :dependent => :destroy 19 has_many :notes, :dependent => :destroy
20 has_many :snippets, :dependent => :destroy 20 has_many :snippets, :dependent => :destroy
21 has_many :deploy_keys, :dependent => :destroy, :foreign_key => "project_id", :class_name => "Key" 21 has_many :deploy_keys, :dependent => :destroy, :foreign_key => "project_id", :class_name => "Key"
22 - has_many :web_hooks, :dependent => :destroy 22 + has_many :hooks, :dependent => :destroy, :class_name => "ProjectHook"
23 has_many :wikis, :dependent => :destroy 23 has_many :wikis, :dependent => :destroy
24 has_many :protected_branches, :dependent => :destroy 24 has_many :protected_branches, :dependent => :destroy
25 25
@@ -120,7 +120,7 @@ class Project &lt; ActiveRecord::Base @@ -120,7 +120,7 @@ class Project &lt; ActiveRecord::Base
120 errors.add(:path, " like 'gitolite-admin' is not allowed") 120 errors.add(:path, " like 'gitolite-admin' is not allowed")
121 end 121 end
122 end 122 end
123 - 123 +
124 def self.access_options 124 def self.access_options
125 UsersProject.access_roles 125 UsersProject.access_roles
126 end 126 end
app/models/project_hook.rb 0 → 100644
@@ -0,0 +1,3 @@ @@ -0,0 +1,3 @@
  1 +class ProjectHook < WebHook
  2 + belongs_to :project
  3 +end
app/models/system_hook.rb 0 → 100644
@@ -0,0 +1,13 @@ @@ -0,0 +1,13 @@
  1 +class SystemHook < WebHook
  2 +
  3 + def async_execute(data)
  4 + Resque.enqueue(SystemHookWorker, id, data)
  5 + end
  6 +
  7 + def self.all_hooks_fire(data)
  8 + SystemHook.all.each do |sh|
  9 + sh.async_execute data
  10 + end
  11 + end
  12 +
  13 +end
app/models/user.rb
1 class User < ActiveRecord::Base 1 class User < ActiveRecord::Base
  2 +
2 include Account 3 include Account
3 4
4 devise :database_authenticatable, :token_authenticatable, :lockable, 5 devise :database_authenticatable, :token_authenticatable, :lockable,
app/models/users_project.rb
@@ -68,7 +68,7 @@ class UsersProject &lt; ActiveRecord::Base @@ -68,7 +68,7 @@ class UsersProject &lt; ActiveRecord::Base
68 end 68 end
69 69
70 def repo_access_human 70 def repo_access_human
71 - "" 71 + self.class.access_roles.invert[self.project_access]
72 end 72 end
73 end 73 end
74 # == Schema Information 74 # == Schema Information
app/models/web_hook.rb
@@ -4,8 +4,6 @@ class WebHook &lt; ActiveRecord::Base @@ -4,8 +4,6 @@ class WebHook &lt; ActiveRecord::Base
4 # HTTParty timeout 4 # HTTParty timeout
5 default_timeout 10 5 default_timeout 10
6 6
7 - belongs_to :project  
8 -  
9 validates :url, 7 validates :url,
10 presence: true, 8 presence: true,
11 format: { 9 format: {
@@ -14,9 +12,8 @@ class WebHook &lt; ActiveRecord::Base @@ -14,9 +12,8 @@ class WebHook &lt; ActiveRecord::Base
14 12
15 def execute(data) 13 def execute(data)
16 WebHook.post(url, body: data.to_json, headers: { "Content-Type" => "application/json" }) 14 WebHook.post(url, body: data.to_json, headers: { "Content-Type" => "application/json" })
17 - rescue  
18 - # There was a problem calling this web hook, let's forget about it.  
19 end 15 end
  16 +
20 end 17 end
21 # == Schema Information 18 # == Schema Information
22 # 19 #
app/observers/system_hook_observer.rb 0 → 100644
@@ -0,0 +1,67 @@ @@ -0,0 +1,67 @@
  1 +class SystemHookObserver < ActiveRecord::Observer
  2 + observe :user, :project, :users_project
  3 +
  4 + def after_create(model)
  5 + if model.kind_of? Project
  6 + SystemHook.all_hooks_fire({
  7 + event_name: "project_create",
  8 + name: model.name,
  9 + path: model.path,
  10 + project_id: model.id,
  11 + owner_name: model.owner.name,
  12 + owner_email: model.owner.email,
  13 + created_at: model.created_at
  14 + })
  15 + elsif model.kind_of? User
  16 + SystemHook.all_hooks_fire({
  17 + event_name: "user_create",
  18 + name: model.name,
  19 + email: model.email,
  20 + created_at: model.created_at
  21 + })
  22 +
  23 + elsif model.kind_of? UsersProject
  24 + SystemHook.all_hooks_fire({
  25 + event_name: "user_add_to_team",
  26 + project_name: model.project.name,
  27 + project_path: model.project.path,
  28 + project_id: model.project_id,
  29 + user_name: model.user.name,
  30 + user_email: model.user.email,
  31 + project_access: model.repo_access_human,
  32 + created_at: model.created_at
  33 + })
  34 +
  35 + end
  36 + end
  37 +
  38 + def after_destroy(model)
  39 + if model.kind_of? Project
  40 + SystemHook.all_hooks_fire({
  41 + event_name: "project_destroy",
  42 + name: model.name,
  43 + path: model.path,
  44 + project_id: model.id,
  45 + owner_name: model.owner.name,
  46 + owner_email: model.owner.email,
  47 + })
  48 + elsif model.kind_of? User
  49 + SystemHook.all_hooks_fire({
  50 + event_name: "user_destroy",
  51 + name: model.name,
  52 + email: model.email
  53 + })
  54 +
  55 + elsif model.kind_of? UsersProject
  56 + SystemHook.all_hooks_fire({
  57 + event_name: "user_remove_from_team",
  58 + project_name: model.project.name,
  59 + project_path: model.project.path,
  60 + project_id: model.project_id,
  61 + user_name: model.user.name,
  62 + user_email: model.user.email,
  63 + project_access: model.repo_access_human
  64 + })
  65 + end
  66 + end
  67 +end
app/roles/git_push.rb
@@ -27,7 +27,7 @@ module GitPush @@ -27,7 +27,7 @@ module GitPush
27 true 27 true
28 end 28 end
29 29
30 - def execute_web_hooks(oldrev, newrev, ref, user) 30 + def execute_hooks(oldrev, newrev, ref, user)
31 ref_parts = ref.split('/') 31 ref_parts = ref.split('/')
32 32
33 # Return if this is not a push to a branch (e.g. new commits) 33 # Return if this is not a push to a branch (e.g. new commits)
@@ -35,7 +35,7 @@ module GitPush @@ -35,7 +35,7 @@ module GitPush
35 35
36 data = post_receive_data(oldrev, newrev, ref, user) 36 data = post_receive_data(oldrev, newrev, ref, user)
37 37
38 - web_hooks.each { |web_hook| web_hook.execute(data) } 38 + hooks.each { |hook| hook.execute(data) }
39 end 39 end
40 40
41 def post_receive_data(oldrev, newrev, ref, user) 41 def post_receive_data(oldrev, newrev, ref, user)
@@ -97,7 +97,7 @@ module GitPush @@ -97,7 +97,7 @@ module GitPush
97 self.update_merge_requests(oldrev, newrev, ref, user) 97 self.update_merge_requests(oldrev, newrev, ref, user)
98 98
99 # Execute web hooks 99 # Execute web hooks
100 - self.execute_web_hooks(oldrev, newrev, ref, user) 100 + self.execute_hooks(oldrev, newrev, ref, user)
101 101
102 # Create satellite 102 # Create satellite
103 self.satellite.create unless self.satellite.exists? 103 self.satellite.create unless self.satellite.exists?
app/views/admin/hooks/_data_ex.html.erb 0 → 100644
@@ -0,0 +1,45 @@ @@ -0,0 +1,45 @@
  1 +<% data_ex_str = <<eos
  2 +{
  3 + :before => "95790bf891e76fee5e1747ab589903a6a1f80f22",
  4 + :after => "da1560886d4f094c3e6c9ef40349f7d38b5d27d7",
  5 + :ref => "refs/heads/master",
  6 + :user_id => 4,
  7 + :user_name => "John Smith",
  8 + :repository => {
  9 + :name => "Diaspora",
  10 + :url => "localhost/diaspora",
  11 + :description => "",
  12 + :homepage => "localhost/diaspora",
  13 + :private => true
  14 + },
  15 + :commits => [
  16 + [0] {
  17 + :id => "450d0de7532f8b663b9c5cce183b...",
  18 + :message => "Update Catalan translation to e38cb41.",
  19 + :timestamp => "2011-12-12T14:27:31+02:00",
  20 + :url => "http://localhost/diaspora/commits/450d0de7532f...",
  21 + :author => {
  22 + :name => "Jordi Mallach",
  23 + :email => "jordi@softcatala.org"
  24 + }
  25 + },
  26 +
  27 + ....
  28 +
  29 + [3] {
  30 + :id => "da1560886d4f094c3e6c9ef40349...",
  31 + :message => "fixed readme",
  32 + :timestamp => "2012-01-03T23:36:29+02:00",
  33 + :url => "http://localhost/diaspora/commits/da1560886d...",
  34 + :author => {
  35 + :name => "gitlab dev user",
  36 + :email => "gitlabdev@dv6700.(none)"
  37 + }
  38 + }
  39 + ],
  40 + total_commits_count => 3
  41 +}
  42 +eos
  43 +%>
  44 +<% js_lexer = Pygments::Lexer[:js] %>
  45 +<%= raw js_lexer.highlight(data_ex_str) %>
app/views/admin/hooks/index.html.haml 0 → 100644
@@ -0,0 +1,39 @@ @@ -0,0 +1,39 @@
  1 +.alert.alert-info
  2 + %span
  3 + Post receive hooks for binding events.
  4 + %br
  5 + Read more about system hooks
  6 + %strong #{link_to "here", help_system_hooks_path, :class => "vlink"}
  7 +
  8 += form_for @hook, :as => :hook, :url => admin_hooks_path do |f|
  9 + -if @hook.errors.any?
  10 + .alert-message.block-message.error
  11 + - @hook.errors.full_messages.each do |msg|
  12 + %p= msg
  13 + .clearfix
  14 + = f.label :url, "URL:"
  15 + .input
  16 + = f.text_field :url, :class => "text_field xxlarge"
  17 + &nbsp;
  18 + = f.submit "Add System Hook", :class => "btn primary"
  19 +%hr
  20 +
  21 +-if @hooks.any?
  22 + %h3
  23 + Hooks
  24 + %small (#{@hooks.count})
  25 + %br
  26 + %table.admin-table
  27 + %tr
  28 + %th URL
  29 + %th Method
  30 + %th
  31 + - @hooks.each do |hook|
  32 + %tr
  33 + %td
  34 + = link_to admin_hook_path(hook) do
  35 + %strong= hook.url
  36 + = link_to 'Test Hook', admin_hook_test_path(hook), :class => "btn small right"
  37 + %td POST
  38 + %td
  39 + = link_to 'Remove', admin_hook_path(hook), :confirm => 'Are you sure?', :method => :delete, :class => "danger btn small right"
app/views/admin/mailer/preview.html.haml
@@ -1,28 +0,0 @@ @@ -1,28 +0,0 @@
1 -%p This is page with preview for all system emails that are sent to user  
2 -%p Email previews built based on existing Project/Commit/Issue base - so some preview maybe unavailable unless object appear in system  
3 -  
4 -#accordion  
5 - %h3  
6 - %a New user  
7 - %div  
8 - %iframe{ :src=> admin_mailer_preview_user_new_path, :width=>"100%", :height=>"350"}  
9 - %h3  
10 - %a New issue  
11 - %div  
12 - %iframe{ :src=> admin_mailer_preview_issue_new_path, :width=>"100%", :height=>"350"}  
13 - %h3  
14 - %a Commit note  
15 - %div  
16 - %iframe{ :src=> admin_mailer_preview_note_path(:type => "Commit"), :width=>"100%", :height=>"350"}  
17 - %h3  
18 - %a Issue note  
19 - %div  
20 - %iframe{ :src=> admin_mailer_preview_note_path(:type => "Issue"), :width=>"100%", :height=>"350"}  
21 - %h3  
22 - %a Wall note  
23 - %div  
24 - %iframe{ :src=> admin_mailer_preview_note_path(:type => "Wall"), :width=>"100%", :height=>"350"}  
25 -  
26 -:javascript  
27 - $(function() {  
28 - $("#accordion").accordion(); });  
app/views/help/system_hooks.html.haml 0 → 100644
@@ -0,0 +1,13 @@ @@ -0,0 +1,13 @@
  1 +%h3 System hooks
  2 +.back_link
  3 + = link_to :back do
  4 + &larr; back
  5 +%hr
  6 +
  7 +%p.slead
  8 + Your Gitlab instance can perform HTTP POST request on next event: create_project, delete_project, create_user, delete_user, change_team_member.
  9 + %br
  10 + System Hooks can be used for logging or change information in LDAP server.
  11 + %br
  12 +%h5 Hooks request example:
  13 += render "admin/hooks/data_ex"
app/views/layouts/admin.html.haml
@@ -15,7 +15,7 @@ @@ -15,7 +15,7 @@
15 %li{:class => tab_class(:admin_logs)} 15 %li{:class => tab_class(:admin_logs)}
16 = link_to "Logs", admin_logs_path 16 = link_to "Logs", admin_logs_path
17 %li{:class => tab_class(:admin_emails)} 17 %li{:class => tab_class(:admin_emails)}
18 - = link_to "Emails", admin_emails_path 18 + = link_to "Hooks", admin_hooks_path
19 %li{:class => tab_class(:admin_resque)} 19 %li{:class => tab_class(:admin_resque)}
20 = link_to "Resque", admin_resque_path 20 = link_to "Resque", admin_resque_path
21 21
app/workers/system_hook_worker.rb 0 → 100644
@@ -0,0 +1,7 @@ @@ -0,0 +1,7 @@
  1 +class SystemHookWorker
  2 + @queue = :system_hook
  3 +
  4 + def self.perform(hook_id, data)
  5 + SystemHook.find(hook_id).execute data
  6 + end
  7 +end
config/application.rb
@@ -23,7 +23,7 @@ module Gitlab @@ -23,7 +23,7 @@ module Gitlab
23 # config.plugins = [ :exception_notification, :ssl_requirement, :all ] 23 # config.plugins = [ :exception_notification, :ssl_requirement, :all ]
24 24
25 # Activate observers that should always be running. 25 # Activate observers that should always be running.
26 - config.active_record.observers = :mailer_observer, :activity_observer, :project_observer, :key_observer, :issue_observer, :user_observer 26 + config.active_record.observers = :mailer_observer, :activity_observer, :project_observer, :key_observer, :issue_observer, :user_observer, :system_hook_observer
27 27
28 # Set Time.zone default to the specified zone and make Active Record auto-convert to this zone. 28 # Set Time.zone default to the specified zone and make Active Record auto-convert to this zone.
29 # Run "rake -D time" for a list of tasks for finding time zone names. Default is UTC. 29 # Run "rake -D time" for a list of tasks for finding time zone names. Default is UTC.
config/routes.rb
@@ -28,6 +28,7 @@ Gitlab::Application.routes.draw do @@ -28,6 +28,7 @@ Gitlab::Application.routes.draw do
28 get 'help/workflow' => 'help#workflow' 28 get 'help/workflow' => 'help#workflow'
29 get 'help/api' => 'help#api' 29 get 'help/api' => 'help#api'
30 get 'help/web_hooks' => 'help#web_hooks' 30 get 'help/web_hooks' => 'help#web_hooks'
  31 + get 'help/system_hooks' => 'help#system_hooks'
31 32
32 # 33 #
33 # Admin Area 34 # Admin Area
@@ -47,11 +48,13 @@ Gitlab::Application.routes.draw do @@ -47,11 +48,13 @@ Gitlab::Application.routes.draw do
47 end 48 end
48 end 49 end
49 resources :team_members, :only => [:edit, :update, :destroy] 50 resources :team_members, :only => [:edit, :update, :destroy]
50 - get 'emails', :to => 'mailer#preview'  
51 get 'mailer/preview_note' 51 get 'mailer/preview_note'
52 get 'mailer/preview_user_new' 52 get 'mailer/preview_user_new'
53 get 'mailer/preview_issue_new' 53 get 'mailer/preview_issue_new'
54 54
  55 + resources :hooks, :only => [:index, :create, :destroy] do
  56 + get :test
  57 + end
55 resource :logs 58 resource :logs
56 resource :resque, :controller => 'resque' 59 resource :resque, :controller => 'resque'
57 root :to => "dashboard#index" 60 root :to => "dashboard#index"
db/migrate/20120712080407_add_type_to_web_hook.rb 0 → 100644
@@ -0,0 +1,5 @@ @@ -0,0 +1,5 @@
  1 +class AddTypeToWebHook < ActiveRecord::Migration
  2 + def change
  3 + add_column :web_hooks, :type, :string, :default => "ProjectHook"
  4 + end
  5 +end
@@ -11,7 +11,7 @@ @@ -11,7 +11,7 @@
11 # 11 #
12 # It's strongly recommended to check this file into your version control system. 12 # It's strongly recommended to check this file into your version control system.
13 13
14 -ActiveRecord::Schema.define(:version => 20120706065612) do 14 +ActiveRecord::Schema.define(:version => 20120712080407) do
15 15
16 create_table "events", :force => true do |t| 16 create_table "events", :force => true do |t|
17 t.string "target_type" 17 t.string "target_type"
@@ -187,8 +187,9 @@ ActiveRecord::Schema.define(:version =&gt; 20120706065612) do @@ -187,8 +187,9 @@ ActiveRecord::Schema.define(:version =&gt; 20120706065612) do
187 create_table "web_hooks", :force => true do |t| 187 create_table "web_hooks", :force => true do |t|
188 t.string "url" 188 t.string "url"
189 t.integer "project_id" 189 t.integer "project_id"
190 - t.datetime "created_at", :null => false  
191 - t.datetime "updated_at", :null => false 190 + t.datetime "created_at", :null => false
  191 + t.datetime "updated_at", :null => false
  192 + t.string "type", :default => "ProjectHook"
192 end 193 end
193 194
194 create_table "wikis", :force => true do |t| 195 create_table "wikis", :force => true do |t|
1 mkdir -p tmp/pids 1 mkdir -p tmp/pids
2 -bundle exec rake environment resque:work QUEUE=post_receive,mailer RAILS_ENV=production PIDFILE=tmp/pids/resque_worker.pid BACKGROUND=yes 2 +bundle exec rake environment resque:work QUEUE=post_receive,mailer,system_hook RAILS_ENV=production PIDFILE=tmp/pids/resque_worker.pid BACKGROUND=yes
1 -bundle exec rake environment resque:work QUEUE=* VVERBOSE=1 1 +bundle exec rake environment resque:work QUEUE=post_receive,mailer,system_hook VVERBOSE=1
spec/factories.rb
@@ -7,6 +7,12 @@ Factory.add(:project, Project) do |obj| @@ -7,6 +7,12 @@ Factory.add(:project, Project) do |obj|
7 obj.code = 'LGT' 7 obj.code = 'LGT'
8 end 8 end
9 9
  10 +Factory.add(:project_without_owner, Project) do |obj|
  11 + obj.name = Faker::Internet.user_name
  12 + obj.path = 'gitlabhq'
  13 + obj.code = 'LGT'
  14 +end
  15 +
10 Factory.add(:public_project, Project) do |obj| 16 Factory.add(:public_project, Project) do |obj|
11 obj.name = Faker::Internet.user_name 17 obj.name = Faker::Internet.user_name
12 obj.path = 'gitlabhq' 18 obj.path = 'gitlabhq'
@@ -60,7 +66,11 @@ Factory.add(:key, Key) do |obj| @@ -60,7 +66,11 @@ Factory.add(:key, Key) do |obj|
60 obj.key = File.read(File.join(Rails.root, "db", "pkey.example")) 66 obj.key = File.read(File.join(Rails.root, "db", "pkey.example"))
61 end 67 end
62 68
63 -Factory.add(:web_hook, WebHook) do |obj| 69 +Factory.add(:project_hook, ProjectHook) do |obj|
  70 + obj.url = Faker::Internet.uri("http")
  71 +end
  72 +
  73 +Factory.add(:system_hook, SystemHook) do |obj|
64 obj.url = Faker::Internet.uri("http") 74 obj.url = Faker::Internet.uri("http")
65 end 75 end
66 76
spec/models/project_hooks_spec.rb
@@ -21,44 +21,44 @@ describe Project, &quot;Hooks&quot; do @@ -21,44 +21,44 @@ describe Project, &quot;Hooks&quot; do
21 end 21 end
22 end 22 end
23 23
24 - describe "Web hooks" do 24 + describe "Project hooks" do
25 context "with no web hooks" do 25 context "with no web hooks" do
26 it "raises no errors" do 26 it "raises no errors" do
27 lambda { 27 lambda {
28 - project.execute_web_hooks('oldrev', 'newrev', 'ref', @user) 28 + project.execute_hooks('oldrev', 'newrev', 'ref', @user)
29 }.should_not raise_error 29 }.should_not raise_error
30 end 30 end
31 end 31 end
32 32
33 context "with web hooks" do 33 context "with web hooks" do
34 before do 34 before do
35 - @webhook = Factory(:web_hook)  
36 - @webhook_2 = Factory(:web_hook)  
37 - project.web_hooks << [@webhook, @webhook_2] 35 + @project_hook = Factory(:project_hook)
  36 + @project_hook_2 = Factory(:project_hook)
  37 + project.hooks << [@project_hook, @project_hook_2]
38 end 38 end
39 39
40 it "executes multiple web hook" do 40 it "executes multiple web hook" do
41 - @webhook.should_receive(:execute).once  
42 - @webhook_2.should_receive(:execute).once 41 + @project_hook.should_receive(:execute).once
  42 + @project_hook_2.should_receive(:execute).once
43 43
44 - project.execute_web_hooks('oldrev', 'newrev', 'refs/heads/master', @user) 44 + project.execute_hooks('oldrev', 'newrev', 'refs/heads/master', @user)
45 end 45 end
46 end 46 end
47 47
48 context "does not execute web hooks" do 48 context "does not execute web hooks" do
49 before do 49 before do
50 - @webhook = Factory(:web_hook)  
51 - project.web_hooks << [@webhook] 50 + @project_hook = Factory(:project_hook)
  51 + project.hooks << [@project_hook]
52 end 52 end
53 53
54 it "when pushing a branch for the first time" do 54 it "when pushing a branch for the first time" do
55 - @webhook.should_not_receive(:execute)  
56 - project.execute_web_hooks('00000000000000000000000000000000', 'newrev', 'refs/heads/master', @user) 55 + @project_hook.should_not_receive(:execute)
  56 + project.execute_hooks('00000000000000000000000000000000', 'newrev', 'refs/heads/master', @user)
57 end 57 end
58 58
59 it "when pushing tags" do 59 it "when pushing tags" do
60 - @webhook.should_not_receive(:execute)  
61 - project.execute_web_hooks('oldrev', 'newrev', 'refs/tags/v1.0.0', @user) 60 + @project_hook.should_not_receive(:execute)
  61 + project.execute_hooks('oldrev', 'newrev', 'refs/tags/v1.0.0', @user)
62 end 62 end
63 end 63 end
64 64
spec/models/project_spec.rb
@@ -11,7 +11,7 @@ describe Project do @@ -11,7 +11,7 @@ describe Project do
11 it { should have_many(:issues).dependent(:destroy) } 11 it { should have_many(:issues).dependent(:destroy) }
12 it { should have_many(:notes).dependent(:destroy) } 12 it { should have_many(:notes).dependent(:destroy) }
13 it { should have_many(:snippets).dependent(:destroy) } 13 it { should have_many(:snippets).dependent(:destroy) }
14 - it { should have_many(:web_hooks).dependent(:destroy) } 14 + it { should have_many(:hooks).dependent(:destroy) }
15 it { should have_many(:deploy_keys).dependent(:destroy) } 15 it { should have_many(:deploy_keys).dependent(:destroy) }
16 end 16 end
17 17
spec/models/system_hook_spec.rb 0 → 100644
@@ -0,0 +1,63 @@ @@ -0,0 +1,63 @@
  1 +require "spec_helper"
  2 +
  3 +describe SystemHook do
  4 + describe "execute" do
  5 + before(:each) { ActiveRecord::Base.observers.enable(:all) }
  6 +
  7 + before(:each) do
  8 + @system_hook = Factory :system_hook
  9 + WebMock.stub_request(:post, @system_hook.url)
  10 + end
  11 +
  12 + it "project_create hook" do
  13 + user = Factory :user
  14 + with_resque do
  15 + project = Factory :project_without_owner, :owner => user
  16 + end
  17 + WebMock.should have_requested(:post, @system_hook.url).with(body: /project_create/).once
  18 + end
  19 +
  20 + it "project_destroy hook" do
  21 + project = Factory :project
  22 + with_resque do
  23 + project.destroy
  24 + end
  25 + WebMock.should have_requested(:post, @system_hook.url).with(body: /project_destroy/).once
  26 + end
  27 +
  28 + it "user_create hook" do
  29 + with_resque do
  30 + Factory :user
  31 + end
  32 + WebMock.should have_requested(:post, @system_hook.url).with(body: /user_create/).once
  33 + end
  34 +
  35 + it "user_destroy hook" do
  36 + user = Factory :user
  37 + with_resque do
  38 + user.destroy
  39 + end
  40 + WebMock.should have_requested(:post, @system_hook.url).with(body: /user_destroy/).once
  41 + end
  42 +
  43 + it "project_create hook" do
  44 + user = Factory :user
  45 + project = Factory :project
  46 + with_resque do
  47 + project.users << user
  48 + end
  49 + WebMock.should have_requested(:post, @system_hook.url).with(body: /user_add_to_team/).once
  50 + end
  51 +
  52 + it "project_destroy hook" do
  53 + user = Factory :user
  54 + project = Factory :project
  55 + project.users << user
  56 + with_resque do
  57 + project.users_projects.clear
  58 + end
  59 + WebMock.should have_requested(:post, @system_hook.url).with(body: /user_remove_from_team/).once
  60 + end
  61 + end
  62 +
  63 +end
spec/models/web_hook_spec.rb
1 require 'spec_helper' 1 require 'spec_helper'
2 2
3 -describe WebHook do 3 +describe ProjectHook do
4 describe "Associations" do 4 describe "Associations" do
5 it { should belong_to :project } 5 it { should belong_to :project }
6 end 6 end
@@ -23,32 +23,32 @@ describe WebHook do @@ -23,32 +23,32 @@ describe WebHook do
23 23
24 describe "execute" do 24 describe "execute" do
25 before(:each) do 25 before(:each) do
26 - @webhook = Factory :web_hook 26 + @project_hook = Factory :project_hook
27 @project = Factory :project 27 @project = Factory :project
28 - @project.web_hooks << [@webhook] 28 + @project.hooks << [@project_hook]
29 @data = { before: 'oldrev', after: 'newrev', ref: 'ref'} 29 @data = { before: 'oldrev', after: 'newrev', ref: 'ref'}
30 30
31 - WebMock.stub_request(:post, @webhook.url) 31 + WebMock.stub_request(:post, @project_hook.url)
32 end 32 end
33 33
34 it "POSTs to the web hook URL" do 34 it "POSTs to the web hook URL" do
35 - @webhook.execute(@data)  
36 - WebMock.should have_requested(:post, @webhook.url).once 35 + @project_hook.execute(@data)
  36 + WebMock.should have_requested(:post, @project_hook.url).once
37 end 37 end
38 38
39 it "POSTs the data as JSON" do 39 it "POSTs the data as JSON" do
40 json = @data.to_json 40 json = @data.to_json
41 41
42 - @webhook.execute(@data)  
43 - WebMock.should have_requested(:post, @webhook.url).with(body: json).once 42 + @project_hook.execute(@data)
  43 + WebMock.should have_requested(:post, @project_hook.url).with(body: json).once
44 end 44 end
45 45
46 it "catches exceptions" do 46 it "catches exceptions" do
47 WebHook.should_receive(:post).and_raise("Some HTTP Post error") 47 WebHook.should_receive(:post).and_raise("Some HTTP Post error")
48 48
49 lambda { 49 lambda {
50 - @webhook.execute(@data)  
51 - }.should_not raise_error 50 + @project_hook.execute(@data)
  51 + }.should raise_error
52 end 52 end
53 end 53 end
54 end 54 end
spec/requests/admin/admin_hooks_spec.rb 0 → 100644
@@ -0,0 +1,53 @@ @@ -0,0 +1,53 @@
  1 +require 'spec_helper'
  2 +
  3 +describe "Admin::Hooks" do
  4 + before do
  5 + @project = Factory :project,
  6 + :name => "LeGiT",
  7 + :code => "LGT"
  8 + login_as :admin
  9 +
  10 + @system_hook = Factory :system_hook
  11 +
  12 + end
  13 +
  14 + describe "GET /admin/hooks" do
  15 + it "should be ok" do
  16 + visit admin_root_path
  17 + within ".main_menu" do
  18 + click_on "Hooks"
  19 + end
  20 + current_path.should == admin_hooks_path
  21 + end
  22 +
  23 + it "should have hooks list" do
  24 + visit admin_hooks_path
  25 + page.should have_content(@system_hook.url)
  26 + end
  27 + end
  28 +
  29 + describe "New Hook" do
  30 + before do
  31 + @url = Faker::Internet.uri("http")
  32 + visit admin_hooks_path
  33 + fill_in "hook_url", :with => @url
  34 + expect { click_button "Add System Hook" }.to change(SystemHook, :count).by(1)
  35 + end
  36 +
  37 + it "should open new hook popup" do
  38 + page.current_path.should == admin_hooks_path
  39 + page.should have_content(@url)
  40 + end
  41 + end
  42 +
  43 + describe "Test" do
  44 + before do
  45 + WebMock.stub_request(:post, @system_hook.url)
  46 + visit admin_hooks_path
  47 + click_link "Test Hook"
  48 + end
  49 +
  50 + it { page.current_path.should == admin_hooks_path }
  51 + end
  52 +
  53 +end
spec/requests/admin/security_spec.rb
@@ -13,9 +13,9 @@ describe &quot;Admin::Projects&quot; do @@ -13,9 +13,9 @@ describe &quot;Admin::Projects&quot; do
13 it { admin_users_path.should be_denied_for :visitor } 13 it { admin_users_path.should be_denied_for :visitor }
14 end 14 end
15 15
16 - describe "GET /admin/emails" do  
17 - it { admin_emails_path.should be_allowed_for :admin }  
18 - it { admin_emails_path.should be_denied_for :user }  
19 - it { admin_emails_path.should be_denied_for :visitor } 16 + describe "GET /admin/hooks" do
  17 + it { admin_hooks_path.should be_allowed_for :admin }
  18 + it { admin_hooks_path.should be_denied_for :user }
  19 + it { admin_hooks_path.should be_denied_for :visitor }
20 end 20 end
21 end 21 end
spec/requests/hooks_spec.rb
@@ -9,7 +9,7 @@ describe &quot;Hooks&quot; do @@ -9,7 +9,7 @@ describe &quot;Hooks&quot; do
9 9
10 describe "GET index" do 10 describe "GET index" do
11 it "should be available" do 11 it "should be available" do
12 - @hook = Factory :web_hook, :project => @project 12 + @hook = Factory :project_hook, :project => @project
13 visit project_hooks_path(@project) 13 visit project_hooks_path(@project)
14 page.should have_content "Hooks" 14 page.should have_content "Hooks"
15 page.should have_content @hook.url 15 page.should have_content @hook.url
@@ -21,7 +21,7 @@ describe &quot;Hooks&quot; do @@ -21,7 +21,7 @@ describe &quot;Hooks&quot; do
21 @url = Faker::Internet.uri("http") 21 @url = Faker::Internet.uri("http")
22 visit project_hooks_path(@project) 22 visit project_hooks_path(@project)
23 fill_in "hook_url", :with => @url 23 fill_in "hook_url", :with => @url
24 - expect { click_button "Add Web Hook" }.to change(WebHook, :count).by(1) 24 + expect { click_button "Add Web Hook" }.to change(ProjectHook, :count).by(1)
25 end 25 end
26 26
27 it "should open new team member popup" do 27 it "should open new team member popup" do
@@ -32,7 +32,8 @@ describe &quot;Hooks&quot; do @@ -32,7 +32,8 @@ describe &quot;Hooks&quot; do
32 32
33 describe "Test" do 33 describe "Test" do
34 before do 34 before do
35 - @hook = Factory :web_hook, :project => @project 35 + @hook = Factory :project_hook, :project => @project
  36 + stub_request(:post, @hook.url)
36 visit project_hooks_path(@project) 37 visit project_hooks_path(@project)
37 click_link "Test Hook" 38 click_link "Test Hook"
38 end 39 end
spec/workers/post_receive_spec.rb
@@ -22,14 +22,14 @@ describe PostReceive do @@ -22,14 +22,14 @@ describe PostReceive do
22 Key.stub(find_by_identifier: nil) 22 Key.stub(find_by_identifier: nil)
23 23
24 project.should_not_receive(:observe_push) 24 project.should_not_receive(:observe_push)
25 - project.should_not_receive(:execute_web_hooks) 25 + project.should_not_receive(:execute_hooks)
26 26
27 PostReceive.perform(project.path, 'sha-old', 'sha-new', 'refs/heads/master', key_id).should be_false 27 PostReceive.perform(project.path, 'sha-old', 'sha-new', 'refs/heads/master', key_id).should be_false
28 end 28 end
29 29
30 it "asks the project to execute web hooks" do 30 it "asks the project to execute web hooks" do
31 Project.stub(find_by_path: project) 31 Project.stub(find_by_path: project)
32 - project.should_receive(:execute_web_hooks).with('sha-old', 'sha-new', 'refs/heads/master', project.owner) 32 + project.should_receive(:execute_hooks).with('sha-old', 'sha-new', 'refs/heads/master', project.owner)
33 33
34 PostReceive.perform(project.path, 'sha-old', 'sha-new', 'refs/heads/master', key_id) 34 PostReceive.perform(project.path, 'sha-old', 'sha-new', 'refs/heads/master', key_id)
35 end 35 end