Commit 3c6daec4b1194f5a2c43fcc5b7e370cd5c8add1e

Authored by Dmitriy Zaporozhets
2 parents 14649525 60ee383e

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

Gemfile
... ... @@ -71,7 +71,6 @@ group :development, :test do
71 71 gem "awesome_print"
72 72 gem "database_cleaner"
73 73 gem "launchy"
74   - gem "webmock"
75 74 end
76 75  
77 76 group :test do
... ... @@ -82,4 +81,5 @@ group :test do
82 81 gem "shoulda-matchers"
83 82 gem 'email_spec'
84 83 gem 'resque_spec'
  84 + gem "webmock"
85 85 end
... ...
app/controllers/admin/hooks_controller.rb 0 → 100644
... ... @@ -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   -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 11 respond_to :html
12 12  
13 13 def index
14   - @hooks = @project.web_hooks.all
15   - @hook = WebHook.new
  14 + @hooks = @project.hooks.all
  15 + @hook = ProjectHook.new
16 16 end
17 17  
18 18 def create
19   - @hook = @project.web_hooks.new(params[:hook])
  19 + @hook = @project.hooks.new(params[:hook])
20 20 @hook.save
21 21  
22 22 if @hook.valid?
23 23 redirect_to project_hooks_path(@project)
24 24 else
25   - @hooks = @project.web_hooks.all
  25 + @hooks = @project.hooks.all
26 26 render :index
27 27 end
28 28 end
29 29  
30 30 def test
31   - @hook = @project.web_hooks.find(params[:id])
  31 + @hook = @project.hooks.find(params[:id])
32 32 commits = @project.commits(@project.default_branch, nil, 3)
33 33 data = @project.post_receive_data(commits.last.id, commits.first.id, "refs/heads/#{@project.default_branch}", current_user)
34 34 @hook.execute(data)
... ... @@ -37,7 +37,7 @@ class HooksController &lt; ApplicationController
37 37 end
38 38  
39 39 def destroy
40   - @hook = @project.web_hooks.find(params[:id])
  40 + @hook = @project.hooks.find(params[:id])
41 41 @hook.destroy
42 42  
43 43 redirect_to project_hooks_path(@project)
... ...
app/models/project.rb
... ... @@ -19,7 +19,7 @@ class Project &lt; ActiveRecord::Base
19 19 has_many :notes, :dependent => :destroy
20 20 has_many :snippets, :dependent => :destroy
21 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 23 has_many :wikis, :dependent => :destroy
24 24 has_many :protected_branches, :dependent => :destroy
25 25  
... ... @@ -120,7 +120,7 @@ class Project &lt; ActiveRecord::Base
120 120 errors.add(:path, " like 'gitolite-admin' is not allowed")
121 121 end
122 122 end
123   -
  123 +
124 124 def self.access_options
125 125 UsersProject.access_roles
126 126 end
... ...
app/models/project_hook.rb 0 → 100644
... ... @@ -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 @@
  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 1 class User < ActiveRecord::Base
  2 +
2 3 include Account
3 4  
4 5 devise :database_authenticatable, :token_authenticatable, :lockable,
... ...
app/models/users_project.rb
... ... @@ -68,7 +68,7 @@ class UsersProject &lt; ActiveRecord::Base
68 68 end
69 69  
70 70 def repo_access_human
71   - ""
  71 + self.class.access_roles.invert[self.project_access]
72 72 end
73 73 end
74 74 # == Schema Information
... ...
app/models/web_hook.rb
... ... @@ -4,8 +4,6 @@ class WebHook &lt; ActiveRecord::Base
4 4 # HTTParty timeout
5 5 default_timeout 10
6 6  
7   - belongs_to :project
8   -
9 7 validates :url,
10 8 presence: true,
11 9 format: {
... ... @@ -14,9 +12,8 @@ class WebHook &lt; ActiveRecord::Base
14 12  
15 13 def execute(data)
16 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 15 end
  16 +
20 17 end
21 18 # == Schema Information
22 19 #
... ...
app/observers/system_hook_observer.rb 0 → 100644
... ... @@ -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 27 true
28 28 end
29 29  
30   - def execute_web_hooks(oldrev, newrev, ref, user)
  30 + def execute_hooks(oldrev, newrev, ref, user)
31 31 ref_parts = ref.split('/')
32 32  
33 33 # Return if this is not a push to a branch (e.g. new commits)
... ... @@ -35,7 +35,7 @@ module GitPush
35 35  
36 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 39 end
40 40  
41 41 def post_receive_data(oldrev, newrev, ref, user)
... ... @@ -97,7 +97,7 @@ module GitPush
97 97 self.update_merge_requests(oldrev, newrev, ref, user)
98 98  
99 99 # Execute web hooks
100   - self.execute_web_hooks(oldrev, newrev, ref, user)
  100 + self.execute_hooks(oldrev, newrev, ref, user)
101 101  
102 102 # Create satellite
103 103 self.satellite.create unless self.satellite.exists?
... ...
app/views/admin/hooks/_data_ex.html.erb 0 → 100644
... ... @@ -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 @@
  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   -%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 @@
  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 15 %li{:class => tab_class(:admin_logs)}
16 16 = link_to "Logs", admin_logs_path
17 17 %li{:class => tab_class(:admin_emails)}
18   - = link_to "Emails", admin_emails_path
  18 + = link_to "Hooks", admin_hooks_path
19 19 %li{:class => tab_class(:admin_resque)}
20 20 = link_to "Resque", admin_resque_path
21 21  
... ...
app/workers/system_hook_worker.rb 0 → 100644
... ... @@ -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 23 # config.plugins = [ :exception_notification, :ssl_requirement, :all ]
24 24  
25 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 28 # Set Time.zone default to the specified zone and make Active Record auto-convert to this zone.
29 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 28 get 'help/workflow' => 'help#workflow'
29 29 get 'help/api' => 'help#api'
30 30 get 'help/web_hooks' => 'help#web_hooks'
  31 + get 'help/system_hooks' => 'help#system_hooks'
31 32  
32 33 #
33 34 # Admin Area
... ... @@ -47,11 +48,13 @@ Gitlab::Application.routes.draw do
47 48 end
48 49 end
49 50 resources :team_members, :only => [:edit, :update, :destroy]
50   - get 'emails', :to => 'mailer#preview'
51 51 get 'mailer/preview_note'
52 52 get 'mailer/preview_user_new'
53 53 get 'mailer/preview_issue_new'
54 54  
  55 + resources :hooks, :only => [:index, :create, :destroy] do
  56 + get :test
  57 + end
55 58 resource :logs
56 59 resource :resque, :controller => 'resque'
57 60 root :to => "dashboard#index"
... ...
db/migrate/20120712080407_add_type_to_web_hook.rb 0 → 100644
... ... @@ -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
... ...
db/schema.rb
... ... @@ -11,7 +11,7 @@
11 11 #
12 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 16 create_table "events", :force => true do |t|
17 17 t.string "target_type"
... ... @@ -187,8 +187,9 @@ ActiveRecord::Schema.define(:version =&gt; 20120706065612) do
187 187 create_table "web_hooks", :force => true do |t|
188 188 t.string "url"
189 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 193 end
193 194  
194 195 create_table "wikis", :force => true do |t|
... ...
resque.sh
1 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
... ...
resque_dev.sh
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 7 obj.code = 'LGT'
8 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 16 Factory.add(:public_project, Project) do |obj|
11 17 obj.name = Faker::Internet.user_name
12 18 obj.path = 'gitlabhq'
... ... @@ -60,7 +66,11 @@ Factory.add(:key, Key) do |obj|
60 66 obj.key = File.read(File.join(Rails.root, "db", "pkey.example"))
61 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 74 obj.url = Faker::Internet.uri("http")
65 75 end
66 76  
... ...
spec/models/project_hooks_spec.rb
... ... @@ -21,44 +21,44 @@ describe Project, &quot;Hooks&quot; do
21 21 end
22 22 end
23 23  
24   - describe "Web hooks" do
  24 + describe "Project hooks" do
25 25 context "with no web hooks" do
26 26 it "raises no errors" do
27 27 lambda {
28   - project.execute_web_hooks('oldrev', 'newrev', 'ref', @user)
  28 + project.execute_hooks('oldrev', 'newrev', 'ref', @user)
29 29 }.should_not raise_error
30 30 end
31 31 end
32 32  
33 33 context "with web hooks" do
34 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 38 end
39 39  
40 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 45 end
46 46 end
47 47  
48 48 context "does not execute web hooks" do
49 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 52 end
53 53  
54 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 57 end
58 58  
59 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 62 end
63 63 end
64 64  
... ...
spec/models/project_spec.rb
... ... @@ -11,7 +11,7 @@ describe Project do
11 11 it { should have_many(:issues).dependent(:destroy) }
12 12 it { should have_many(:notes).dependent(:destroy) }
13 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 15 it { should have_many(:deploy_keys).dependent(:destroy) }
16 16 end
17 17  
... ...
spec/models/system_hook_spec.rb 0 → 100644
... ... @@ -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 1 require 'spec_helper'
2 2  
3   -describe WebHook do
  3 +describe ProjectHook do
4 4 describe "Associations" do
5 5 it { should belong_to :project }
6 6 end
... ... @@ -23,32 +23,32 @@ describe WebHook do
23 23  
24 24 describe "execute" do
25 25 before(:each) do
26   - @webhook = Factory :web_hook
  26 + @project_hook = Factory :project_hook
27 27 @project = Factory :project
28   - @project.web_hooks << [@webhook]
  28 + @project.hooks << [@project_hook]
29 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 32 end
33 33  
34 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 37 end
38 38  
39 39 it "POSTs the data as JSON" do
40 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 44 end
45 45  
46 46 it "catches exceptions" do
47 47 WebHook.should_receive(:post).and_raise("Some HTTP Post error")
48 48  
49 49 lambda {
50   - @webhook.execute(@data)
51   - }.should_not raise_error
  50 + @project_hook.execute(@data)
  51 + }.should raise_error
52 52 end
53 53 end
54 54 end
... ...
spec/requests/admin/admin_hooks_spec.rb 0 → 100644
... ... @@ -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 13 it { admin_users_path.should be_denied_for :visitor }
14 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 20 end
21 21 end
... ...
spec/requests/hooks_spec.rb
... ... @@ -9,7 +9,7 @@ describe &quot;Hooks&quot; do
9 9  
10 10 describe "GET index" do
11 11 it "should be available" do
12   - @hook = Factory :web_hook, :project => @project
  12 + @hook = Factory :project_hook, :project => @project
13 13 visit project_hooks_path(@project)
14 14 page.should have_content "Hooks"
15 15 page.should have_content @hook.url
... ... @@ -21,7 +21,7 @@ describe &quot;Hooks&quot; do
21 21 @url = Faker::Internet.uri("http")
22 22 visit project_hooks_path(@project)
23 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 25 end
26 26  
27 27 it "should open new team member popup" do
... ... @@ -32,7 +32,8 @@ describe &quot;Hooks&quot; do
32 32  
33 33 describe "Test" do
34 34 before do
35   - @hook = Factory :web_hook, :project => @project
  35 + @hook = Factory :project_hook, :project => @project
  36 + stub_request(:post, @hook.url)
36 37 visit project_hooks_path(@project)
37 38 click_link "Test Hook"
38 39 end
... ...
spec/workers/post_receive_spec.rb
... ... @@ -22,14 +22,14 @@ describe PostReceive do
22 22 Key.stub(find_by_identifier: nil)
23 23  
24 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 27 PostReceive.perform(project.path, 'sha-old', 'sha-new', 'refs/heads/master', key_id).should be_false
28 28 end
29 29  
30 30 it "asks the project to execute web hooks" do
31 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 34 PostReceive.perform(project.path, 'sha-old', 'sha-new', 'refs/heads/master', key_id)
35 35 end
... ...