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