Commit 4f067ae931bef908312bbf7162abb3b6fdb85f8d
Exists in
master
and in
4 other branches
Merge branch 'feature/event_hooks' of /home/git/repositories/gitlab/gitlabhq
Showing
27 changed files
with
447 additions
and
268 deletions
Show diff stats
CHANGELOG
@@ -7,6 +7,7 @@ v 6.4.0 | @@ -7,6 +7,7 @@ v 6.4.0 | ||
7 | - Side-by-side diff view (Steven Thonus) | 7 | - Side-by-side diff view (Steven Thonus) |
8 | - Internal projects (Jason Hollingsworth) | 8 | - Internal projects (Jason Hollingsworth) |
9 | - Allow removal of avatar (Drew Blessing) | 9 | - Allow removal of avatar (Drew Blessing) |
10 | + - Project web hooks now support issues and merge request events | ||
10 | 11 | ||
11 | v 6.3.0 | 12 | v 6.3.0 |
12 | - API for adding gitlab-ci service | 13 | - API for adding gitlab-ci service |
app/assets/stylesheets/gitlab_bootstrap/forms.scss
app/helpers/application_helper.rb
@@ -207,4 +207,12 @@ module ApplicationHelper | @@ -207,4 +207,12 @@ module ApplicationHelper | ||
207 | def broadcast_message | 207 | def broadcast_message |
208 | BroadcastMessage.current | 208 | BroadcastMessage.current |
209 | end | 209 | end |
210 | + | ||
211 | + def highlight_js(&block) | ||
212 | + string = capture(&block) | ||
213 | + | ||
214 | + content_tag :div, class: user_color_scheme_class do | ||
215 | + Pygments::Lexer[:js].highlight(string).html_safe | ||
216 | + end | ||
217 | + end | ||
210 | end | 218 | end |
app/models/concerns/issuable.rb
@@ -111,4 +111,11 @@ module Issuable | @@ -111,4 +111,11 @@ module Issuable | ||
111 | end | 111 | end |
112 | users.concat(mentions.reduce([], :|)).uniq | 112 | users.concat(mentions.reduce([], :|)).uniq |
113 | end | 113 | end |
114 | + | ||
115 | + def to_hook_data | ||
116 | + { | ||
117 | + object_kind: self.class.name.underscore, | ||
118 | + object_attributes: self.attributes | ||
119 | + } | ||
120 | + end | ||
114 | end | 121 | end |
app/models/project.rb
@@ -298,8 +298,10 @@ class Project < ActiveRecord::Base | @@ -298,8 +298,10 @@ class Project < ActiveRecord::Base | ||
298 | ProjectTransferService.new.transfer(self, new_namespace) | 298 | ProjectTransferService.new.transfer(self, new_namespace) |
299 | end | 299 | end |
300 | 300 | ||
301 | - def execute_hooks(data) | ||
302 | - hooks.each { |hook| hook.async_execute(data) } | 301 | + def execute_hooks(data, hooks_scope = :push_hooks) |
302 | + hooks.send(hooks_scope).each do |hook| | ||
303 | + hook.async_execute(data) | ||
304 | + end | ||
303 | end | 305 | end |
304 | 306 | ||
305 | def execute_services(data) | 307 | def execute_services(data) |
app/models/project_hook.rb
@@ -2,15 +2,24 @@ | @@ -2,15 +2,24 @@ | ||
2 | # | 2 | # |
3 | # Table name: web_hooks | 3 | # Table name: web_hooks |
4 | # | 4 | # |
5 | -# id :integer not null, primary key | ||
6 | -# url :string(255) | ||
7 | -# project_id :integer | ||
8 | -# created_at :datetime not null | ||
9 | -# updated_at :datetime not null | ||
10 | -# type :string(255) default("ProjectHook") | ||
11 | -# service_id :integer | 5 | +# id :integer not null, primary key |
6 | +# url :string(255) | ||
7 | +# project_id :integer | ||
8 | +# created_at :datetime not null | ||
9 | +# updated_at :datetime not null | ||
10 | +# type :string(255) default("ProjectHook") | ||
11 | +# service_id :integer | ||
12 | +# push_events :boolean default(TRUE), not null | ||
13 | +# issues_events :boolean default(FALSE), not null | ||
14 | +# merge_requests_events :boolean default(FALSE), not null | ||
12 | # | 15 | # |
13 | 16 | ||
14 | class ProjectHook < WebHook | 17 | class ProjectHook < WebHook |
15 | belongs_to :project | 18 | belongs_to :project |
19 | + | ||
20 | + attr_accessible :push_events, :issues_events, :merge_requests_events | ||
21 | + | ||
22 | + scope :push_hooks, -> { where(push_events: true) } | ||
23 | + scope :issue_hooks, -> { where(issues_events: true) } | ||
24 | + scope :merge_request_hooks, -> { where(merge_requests_events: true) } | ||
16 | end | 25 | end |
app/models/service_hook.rb
@@ -2,13 +2,16 @@ | @@ -2,13 +2,16 @@ | ||
2 | # | 2 | # |
3 | # Table name: web_hooks | 3 | # Table name: web_hooks |
4 | # | 4 | # |
5 | -# id :integer not null, primary key | ||
6 | -# url :string(255) | ||
7 | -# project_id :integer | ||
8 | -# created_at :datetime not null | ||
9 | -# updated_at :datetime not null | ||
10 | -# type :string(255) default("ProjectHook") | ||
11 | -# service_id :integer | 5 | +# id :integer not null, primary key |
6 | +# url :string(255) | ||
7 | +# project_id :integer | ||
8 | +# created_at :datetime not null | ||
9 | +# updated_at :datetime not null | ||
10 | +# type :string(255) default("ProjectHook") | ||
11 | +# service_id :integer | ||
12 | +# push_events :boolean default(TRUE), not null | ||
13 | +# issues_events :boolean default(FALSE), not null | ||
14 | +# merge_requests_events :boolean default(FALSE), not null | ||
12 | # | 15 | # |
13 | 16 | ||
14 | class ServiceHook < WebHook | 17 | class ServiceHook < WebHook |
app/models/system_hook.rb
@@ -2,13 +2,16 @@ | @@ -2,13 +2,16 @@ | ||
2 | # | 2 | # |
3 | # Table name: web_hooks | 3 | # Table name: web_hooks |
4 | # | 4 | # |
5 | -# id :integer not null, primary key | ||
6 | -# url :string(255) | ||
7 | -# project_id :integer | ||
8 | -# created_at :datetime not null | ||
9 | -# updated_at :datetime not null | ||
10 | -# type :string(255) default("ProjectHook") | ||
11 | -# service_id :integer | 5 | +# id :integer not null, primary key |
6 | +# url :string(255) | ||
7 | +# project_id :integer | ||
8 | +# created_at :datetime not null | ||
9 | +# updated_at :datetime not null | ||
10 | +# type :string(255) default("ProjectHook") | ||
11 | +# service_id :integer | ||
12 | +# push_events :boolean default(TRUE), not null | ||
13 | +# issues_events :boolean default(FALSE), not null | ||
14 | +# merge_requests_events :boolean default(FALSE), not null | ||
12 | # | 15 | # |
13 | 16 | ||
14 | class SystemHook < WebHook | 17 | class SystemHook < WebHook |
app/models/web_hook.rb
@@ -2,13 +2,16 @@ | @@ -2,13 +2,16 @@ | ||
2 | # | 2 | # |
3 | # Table name: web_hooks | 3 | # Table name: web_hooks |
4 | # | 4 | # |
5 | -# id :integer not null, primary key | ||
6 | -# url :string(255) | ||
7 | -# project_id :integer | ||
8 | -# created_at :datetime not null | ||
9 | -# updated_at :datetime not null | ||
10 | -# type :string(255) default("ProjectHook") | ||
11 | -# service_id :integer | 5 | +# id :integer not null, primary key |
6 | +# url :string(255) | ||
7 | +# project_id :integer | ||
8 | +# created_at :datetime not null | ||
9 | +# updated_at :datetime not null | ||
10 | +# type :string(255) default("ProjectHook") | ||
11 | +# service_id :integer | ||
12 | +# push_events :boolean default(TRUE), not null | ||
13 | +# issues_events :boolean default(FALSE), not null | ||
14 | +# merge_requests_events :boolean default(FALSE), not null | ||
12 | # | 15 | # |
13 | 16 | ||
14 | class WebHook < ActiveRecord::Base | 17 | class WebHook < ActiveRecord::Base |
app/observers/issue_observer.rb
1 | class IssueObserver < BaseObserver | 1 | class IssueObserver < BaseObserver |
2 | def after_create(issue) | 2 | def after_create(issue) |
3 | notification.new_issue(issue, current_user) | 3 | notification.new_issue(issue, current_user) |
4 | - | ||
5 | issue.create_cross_references!(issue.project, current_user) | 4 | issue.create_cross_references!(issue.project, current_user) |
5 | + execute_hooks(issue) | ||
6 | end | 6 | end |
7 | 7 | ||
8 | def after_close(issue, transition) | 8 | def after_close(issue, transition) |
9 | notification.close_issue(issue, current_user) | 9 | notification.close_issue(issue, current_user) |
10 | - | ||
11 | create_note(issue) | 10 | create_note(issue) |
11 | + execute_hooks(issue) | ||
12 | end | 12 | end |
13 | 13 | ||
14 | def after_reopen(issue, transition) | 14 | def after_reopen(issue, transition) |
@@ -29,4 +29,8 @@ class IssueObserver < BaseObserver | @@ -29,4 +29,8 @@ class IssueObserver < BaseObserver | ||
29 | def create_note(issue) | 29 | def create_note(issue) |
30 | Note.create_status_change_note(issue, issue.project, current_user, issue.state, current_commit) | 30 | Note.create_status_change_note(issue, issue.project, current_user, issue.state, current_commit) |
31 | end | 31 | end |
32 | + | ||
33 | + def execute_hooks(issue) | ||
34 | + issue.project.execute_hooks(issue.to_hook_data, :issue_hooks) | ||
35 | + end | ||
32 | end | 36 | end |
app/observers/merge_request_observer.rb
@@ -7,15 +7,15 @@ class MergeRequestObserver < ActivityObserver | @@ -7,15 +7,15 @@ class MergeRequestObserver < ActivityObserver | ||
7 | end | 7 | end |
8 | 8 | ||
9 | notification.new_merge_request(merge_request, current_user) | 9 | notification.new_merge_request(merge_request, current_user) |
10 | - | ||
11 | merge_request.create_cross_references!(merge_request.project, current_user) | 10 | merge_request.create_cross_references!(merge_request.project, current_user) |
11 | + execute_hooks(merge_request) | ||
12 | end | 12 | end |
13 | 13 | ||
14 | def after_close(merge_request, transition) | 14 | def after_close(merge_request, transition) |
15 | create_event(merge_request, Event::CLOSED) | 15 | create_event(merge_request, Event::CLOSED) |
16 | - Note.create_status_change_note(merge_request, merge_request.target_project, current_user, merge_request.state, nil) | ||
17 | - | ||
18 | notification.close_mr(merge_request, current_user) | 16 | notification.close_mr(merge_request, current_user) |
17 | + create_note(merge_request) | ||
18 | + execute_hooks(merge_request) | ||
19 | end | 19 | end |
20 | 20 | ||
21 | def after_merge(merge_request, transition) | 21 | def after_merge(merge_request, transition) |
@@ -31,11 +31,13 @@ class MergeRequestObserver < ActivityObserver | @@ -31,11 +31,13 @@ class MergeRequestObserver < ActivityObserver | ||
31 | action: Event::MERGED, | 31 | action: Event::MERGED, |
32 | author_id: merge_request.author_id_of_changes | 32 | author_id: merge_request.author_id_of_changes |
33 | ) | 33 | ) |
34 | + | ||
35 | + execute_hooks(merge_request) | ||
34 | end | 36 | end |
35 | 37 | ||
36 | def after_reopen(merge_request, transition) | 38 | def after_reopen(merge_request, transition) |
37 | create_event(merge_request, Event::REOPENED) | 39 | create_event(merge_request, Event::REOPENED) |
38 | - Note.create_status_change_note(merge_request, merge_request.target_project, current_user, merge_request.state, nil) | 40 | + create_note(merge_request) |
39 | end | 41 | end |
40 | 42 | ||
41 | def after_update(merge_request) | 43 | def after_update(merge_request) |
@@ -53,4 +55,17 @@ class MergeRequestObserver < ActivityObserver | @@ -53,4 +55,17 @@ class MergeRequestObserver < ActivityObserver | ||
53 | author_id: current_user.id | 55 | author_id: current_user.id |
54 | ) | 56 | ) |
55 | end | 57 | end |
58 | + | ||
59 | + private | ||
60 | + | ||
61 | + # Create merge request note with service comment like 'Status changed to closed' | ||
62 | + def create_note(merge_request) | ||
63 | + Note.create_status_change_note(merge_request, merge_request.target_project, current_user, merge_request.state, nil) | ||
64 | + end | ||
65 | + | ||
66 | + def execute_hooks(merge_request) | ||
67 | + if merge_request.project | ||
68 | + merge_request.project.execute_hooks(merge_request.to_hook_data, :merge_request_hooks) | ||
69 | + end | ||
70 | + end | ||
56 | end | 71 | end |
app/services/git_push_service.rb
@@ -32,7 +32,7 @@ class GitPushService | @@ -32,7 +32,7 @@ class GitPushService | ||
32 | end | 32 | end |
33 | 33 | ||
34 | if push_to_branch?(ref) | 34 | if push_to_branch?(ref) |
35 | - project.execute_hooks(@push_data.dup) | 35 | + project.execute_hooks(@push_data.dup, :push_hooks) |
36 | project.execute_services(@push_data.dup) | 36 | project.execute_services(@push_data.dup) |
37 | end | 37 | end |
38 | 38 |
app/views/help/web_hooks.html.haml
1 | = render layout: 'help/layout' do | 1 | = render layout: 'help/layout' do |
2 | - %h3.page-title Web hooks | 2 | + %h3.page-title Project web hooks |
3 | + %p.light | ||
4 | + Project web hooks allow you to trigger url if new code is pushed or new issue is created | ||
5 | + %hr | ||
3 | 6 | ||
4 | %p.slead | 7 | %p.slead |
5 | - Every GitLab project can trigger a web server whenever the repo is pushed to. | 8 | + You can configure web hook to listen for specific events like pushes, issues, merge requests. |
9 | + %br | ||
10 | + GitLab will send POST request with data to web hook url. | ||
6 | %br | 11 | %br |
7 | Web Hooks can be used to update an external issue tracker, trigger CI builds, update a backup mirror, or even deploy to your production server. | 12 | Web Hooks can be used to update an external issue tracker, trigger CI builds, update a backup mirror, or even deploy to your production server. |
13 | + %hr | ||
14 | + | ||
15 | + %h4 Push events | ||
16 | + %p.light | ||
17 | + Triggered when you push to the repository except pushing tags. | ||
8 | %br | 18 | %br |
9 | - GitLab will send POST request with commits information on every push. | ||
10 | - %h5 Hooks request example: | ||
11 | - = render "projects/hooks/data_ex" | 19 | + Request body: |
20 | + = highlight_js do | ||
21 | + :erb | ||
22 | + { | ||
23 | + "before": "95790bf891e76fee5e1747ab589903a6a1f80f22", | ||
24 | + "after": "da1560886d4f094c3e6c9ef40349f7d38b5d27d7", | ||
25 | + "ref": "refs/heads/master", | ||
26 | + "user_id": 4, | ||
27 | + "user_name": "John Smith", | ||
28 | + "project_id": 15, | ||
29 | + "repository": { | ||
30 | + "name": "Diaspora", | ||
31 | + "url": "git@localhost:diaspora.git", | ||
32 | + "description": "", | ||
33 | + "homepage": "http://localhost/diaspora", | ||
34 | + }, | ||
35 | + "commits": [ | ||
36 | + { | ||
37 | + "id": "b6568db1bc1dcd7f8b4d5a946b0b91f9dacd7327", | ||
38 | + "message": "Update Catalan translation to e38cb41.", | ||
39 | + "timestamp": "2011-12-12T14:27:31+02:00", | ||
40 | + "url": "http://localhost/diaspora/commits/b6568db1bc1dcd7f8b4d5a946b0b91f9dacd7327", | ||
41 | + "author": { | ||
42 | + "name": "Jordi Mallach", | ||
43 | + "email": "jordi@softcatala.org", | ||
44 | + } | ||
45 | + }, | ||
46 | + // ... | ||
47 | + { | ||
48 | + "id": "da1560886d4f094c3e6c9ef40349f7d38b5d27d7", | ||
49 | + "message": "fixed readme", | ||
50 | + "timestamp": "2012-01-03T23:36:29+02:00", | ||
51 | + "url": "http://localhost/diaspora/commits/da1560886d4f094c3e6c9ef40349f7d38b5d27d7", | ||
52 | + "author": { | ||
53 | + "name": "GitLab dev user", | ||
54 | + "email": "gitlabdev@dv6700.(none)", | ||
55 | + }, | ||
56 | + }, | ||
57 | + ], | ||
58 | + "total_commits_count": 4, | ||
59 | + }; | ||
60 | + | ||
12 | 61 | ||
62 | + %h4.prepend-top-20 Issues events | ||
63 | + %p.light | ||
64 | + Triggered when new issue created or existing issue was closed. | ||
65 | + %br | ||
66 | + Request body: | ||
67 | + = highlight_js do | ||
68 | + :erb | ||
69 | + { | ||
70 | + "object_kind":"issue", | ||
71 | + "object_attributes":{ | ||
72 | + "id":301, | ||
73 | + "title":"New API: create/update/delete file", | ||
74 | + "assignee_id":51, | ||
75 | + "author_id":51, | ||
76 | + "project_id":14, | ||
77 | + "created_at":"2013-12-03T17:15:43Z", | ||
78 | + "updated_at":"2013-12-03T17:15:43Z", | ||
79 | + "position":0, | ||
80 | + "branch_name":null, | ||
81 | + "description":"Create new API for manipulations with repository", | ||
82 | + "milestone_id":null, | ||
83 | + "state":"opened", | ||
84 | + "iid":23 | ||
85 | + } | ||
86 | + } | ||
87 | + %h4.prepend-top-20 Merge request events | ||
88 | + %p.light | ||
89 | + Triggered when new merge request created or existing merge request was merged/closed. | ||
90 | + %br | ||
91 | + Request body: | ||
92 | + = highlight_js do | ||
93 | + :erb | ||
94 | + { | ||
95 | + "object_kind":"merge_request", | ||
96 | + "object_attributes":{ | ||
97 | + "id":99, | ||
98 | + "target_branch":"master", | ||
99 | + "source_branch":"ms-viewport", | ||
100 | + "source_project_id":14, | ||
101 | + "author_id":51, | ||
102 | + "assignee_id":6, | ||
103 | + "title":"MS-Viewport", | ||
104 | + "created_at":"2013-12-03T17:23:34Z", | ||
105 | + "updated_at":"2013-12-03T17:23:34Z", | ||
106 | + "st_commits":null, | ||
107 | + "st_diffs":null, | ||
108 | + "milestone_id":null, | ||
109 | + "state":"opened", | ||
110 | + "merge_status":"unchecked", | ||
111 | + "target_project_id":14, | ||
112 | + "iid":1, | ||
113 | + "description":"" | ||
114 | + } | ||
115 | + } |
app/views/projects/hooks/_data_ex.html.erb
@@ -1,44 +0,0 @@ | @@ -1,44 +0,0 @@ | ||
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 | - "project_id": 15, | ||
9 | - "repository": { | ||
10 | - "name": "Diaspora", | ||
11 | - "url": "git@localhost:diaspora.git", | ||
12 | - "description": "", | ||
13 | - "homepage": "http://localhost/diaspora", | ||
14 | - }, | ||
15 | - "commits": [ | ||
16 | - { | ||
17 | - "id": "b6568db1bc1dcd7f8b4d5a946b0b91f9dacd7327", | ||
18 | - "message": "Update Catalan translation to e38cb41.", | ||
19 | - "timestamp": "2011-12-12T14:27:31+02:00", | ||
20 | - "url": "http://localhost/diaspora/commits/b6568db1bc1dcd7f8b4d5a946b0b91f9dacd7327", | ||
21 | - "author": { | ||
22 | - "name": "Jordi Mallach", | ||
23 | - "email": "jordi@softcatala.org", | ||
24 | - } | ||
25 | - }, | ||
26 | - // ... | ||
27 | - { | ||
28 | - "id": "da1560886d4f094c3e6c9ef40349f7d38b5d27d7", | ||
29 | - "message": "fixed readme", | ||
30 | - "timestamp": "2012-01-03T23:36:29+02:00", | ||
31 | - "url": "http://localhost/diaspora/commits/da1560886d4f094c3e6c9ef40349f7d38b5d27d7", | ||
32 | - "author": { | ||
33 | - "name": "GitLab dev user", | ||
34 | - "email": "gitlabdev@dv6700.(none)", | ||
35 | - }, | ||
36 | - }, | ||
37 | - ], | ||
38 | - "total_commits_count": 4, | ||
39 | -}; | ||
40 | -eos | ||
41 | -%> | ||
42 | -<div class="<%= user_color_scheme_class%>"> | ||
43 | - <%= raw Pygments::Lexer[:js].highlight(data_ex_str) %> | ||
44 | -</div> |
app/views/projects/hooks/index.html.haml
1 | %h3.page-title | 1 | %h3.page-title |
2 | - Post-receive hooks | 2 | + Web hooks |
3 | 3 | ||
4 | %p.light | 4 | %p.light |
5 | - #{link_to "Post-receive hooks ", help_web_hooks_path, class: "vlink"} can be | ||
6 | - used for binding events when someone pushes to the repository. | 5 | + #{link_to "Web hooks ", help_web_hooks_path, class: "vlink"} can be |
6 | + used for binding events when something happends to the the project. | ||
7 | 7 | ||
8 | %hr.clearfix | 8 | %hr.clearfix |
9 | 9 | ||
@@ -13,23 +13,50 @@ | @@ -13,23 +13,50 @@ | ||
13 | - @hook.errors.full_messages.each do |msg| | 13 | - @hook.errors.full_messages.each do |msg| |
14 | %p= msg | 14 | %p= msg |
15 | .control-group | 15 | .control-group |
16 | - = f.label :url, "URL:" | 16 | + = f.label :url, "URL" |
17 | .controls | 17 | .controls |
18 | = f.text_field :url, class: "text_field input-xxlarge input-xpadding", placeholder: 'http://example.com/trigger-ci.json' | 18 | = f.text_field :url, class: "text_field input-xxlarge input-xpadding", placeholder: 'http://example.com/trigger-ci.json' |
19 | | 19 | |
20 | = f.submit "Add Web Hook", class: "btn btn-create" | 20 | = f.submit "Add Web Hook", class: "btn btn-create" |
21 | + .control-group | ||
22 | + = f.label :url, "Trigger" | ||
23 | + .controls | ||
24 | + %div | ||
25 | + = f.check_box :push_events, class: 'pull-left' | ||
26 | + .prepend-left-20 | ||
27 | + = f.label :push_events, class: 'list-label' do | ||
28 | + %strong Push events | ||
29 | + %p.light | ||
30 | + This url will be triggered in case of push to repository | ||
31 | + %div | ||
32 | + = f.check_box :issues_events, class: 'pull-left' | ||
33 | + .prepend-left-20 | ||
34 | + = f.label :issues_events, class: 'list-label' do | ||
35 | + %strong Issues events | ||
36 | + %p.light | ||
37 | + This url will be triggered for created issues | ||
38 | + %div | ||
39 | + = f.check_box :merge_requests_events, class: 'pull-left' | ||
40 | + .prepend-left-20 | ||
41 | + = f.label :merge_requests_events, class: 'list-label' do | ||
42 | + %strong Merge Request events | ||
43 | + %p.light | ||
44 | + This url will be triggered for created merge requests | ||
21 | %hr | 45 | %hr |
22 | 46 | ||
23 | -if @hooks.any? | 47 | -if @hooks.any? |
24 | .ui-box | 48 | .ui-box |
25 | .title | 49 | .title |
26 | - Hooks (#{@hooks.count}) | 50 | + Web Hooks (#{@hooks.count}) |
27 | %ul.well-list | 51 | %ul.well-list |
28 | - @hooks.each do |hook| | 52 | - @hooks.each do |hook| |
29 | %li | 53 | %li |
30 | - %span.badge.badge-info POST | ||
31 | - → | ||
32 | - %span.monospace= hook.url | ||
33 | .pull-right | 54 | .pull-right |
34 | = link_to 'Test Hook', test_project_hook_path(@project, hook), class: "btn btn-small grouped" | 55 | = link_to 'Test Hook', test_project_hook_path(@project, hook), class: "btn btn-small grouped" |
35 | = link_to 'Remove', project_hook_path(@project, hook), confirm: 'Are you sure?', method: :delete, class: "btn btn-remove btn-small grouped" | 56 | = link_to 'Remove', project_hook_path(@project, hook), confirm: 'Are you sure?', method: :delete, class: "btn btn-remove btn-small grouped" |
57 | + .clearfix | ||
58 | + %span.monospace= hook.url | ||
59 | + %p | ||
60 | + - %w(push_events issues_events merge_requests_events).each do |trigger| | ||
61 | + - if hook.send(trigger) | ||
62 | + %span.label.label-gray= trigger.titleize |
db/migrate/20131202192556_add_event_fields_for_web_hook.rb
0 → 100644
@@ -0,0 +1,7 @@ | @@ -0,0 +1,7 @@ | ||
1 | +class AddEventFieldsForWebHook < ActiveRecord::Migration | ||
2 | + def change | ||
3 | + add_column :web_hooks, :push_events, :boolean, default: true, null: false | ||
4 | + add_column :web_hooks, :issues_events, :boolean, default: false, null: false | ||
5 | + add_column :web_hooks, :merge_requests_events, :boolean, default: false, null: false | ||
6 | + end | ||
7 | +end |
db/schema.rb
@@ -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 => 20131112220935) do | 14 | +ActiveRecord::Schema.define(:version => 20131202192556) do |
15 | 15 | ||
16 | create_table "broadcast_messages", :force => true do |t| | 16 | create_table "broadcast_messages", :force => true do |t| |
17 | t.text "message", :null => false | 17 | t.text "message", :null => false |
@@ -334,10 +334,13 @@ ActiveRecord::Schema.define(:version => 20131112220935) do | @@ -334,10 +334,13 @@ ActiveRecord::Schema.define(:version => 20131112220935) do | ||
334 | create_table "web_hooks", :force => true do |t| | 334 | create_table "web_hooks", :force => true do |t| |
335 | t.string "url" | 335 | t.string "url" |
336 | t.integer "project_id" | 336 | t.integer "project_id" |
337 | - t.datetime "created_at", :null => false | ||
338 | - t.datetime "updated_at", :null => false | ||
339 | - t.string "type", :default => "ProjectHook" | 337 | + t.datetime "created_at", :null => false |
338 | + t.datetime "updated_at", :null => false | ||
339 | + t.string "type", :default => "ProjectHook" | ||
340 | t.integer "service_id" | 340 | t.integer "service_id" |
341 | + t.boolean "push_events", :default => true, :null => false | ||
342 | + t.boolean "issues_events", :default => false, :null => false | ||
343 | + t.boolean "merge_requests_events", :default => false, :null => false | ||
341 | end | 344 | end |
342 | 345 | ||
343 | add_index "web_hooks", ["project_id"], :name => "index_web_hooks_on_project_id" | 346 | add_index "web_hooks", ["project_id"], :name => "index_web_hooks_on_project_id" |
doc/api/projects.md
@@ -402,6 +402,10 @@ Parameters: | @@ -402,6 +402,10 @@ Parameters: | ||
402 | { | 402 | { |
403 | "id": 1, | 403 | "id": 1, |
404 | "url": "http://example.com/hook", | 404 | "url": "http://example.com/hook", |
405 | + "project_id": 3, | ||
406 | + "push_events": "true", | ||
407 | + "issues_events": "true", | ||
408 | + "merge_requests_events": "true", | ||
405 | "created_at": "2012-10-12T17:04:47Z" | 409 | "created_at": "2012-10-12T17:04:47Z" |
406 | } | 410 | } |
407 | ``` | 411 | ``` |
@@ -419,6 +423,9 @@ Parameters: | @@ -419,6 +423,9 @@ Parameters: | ||
419 | 423 | ||
420 | + `id` (required) - The ID or NAME of a project | 424 | + `id` (required) - The ID or NAME of a project |
421 | + `url` (required) - The hook URL | 425 | + `url` (required) - The hook URL |
426 | ++ `push_events` - Trigger hook on push events | ||
427 | ++ `issues_events` - Trigger hook on issues events | ||
428 | ++ `merge_requests_events` - Trigger hook on merge_requests events | ||
422 | 429 | ||
423 | 430 | ||
424 | ### Edit project hook | 431 | ### Edit project hook |
@@ -434,6 +441,9 @@ Parameters: | @@ -434,6 +441,9 @@ Parameters: | ||
434 | + `id` (required) - The ID or NAME of a project | 441 | + `id` (required) - The ID or NAME of a project |
435 | + `hook_id` (required) - The ID of a project hook | 442 | + `hook_id` (required) - The ID of a project hook |
436 | + `url` (required) - The hook URL | 443 | + `url` (required) - The hook URL |
444 | ++ `push_events` - Trigger hook on push events | ||
445 | ++ `issues_events` - Trigger hook on issues events | ||
446 | ++ `merge_requests_events` - Trigger hook on merge_requests events | ||
437 | 447 | ||
438 | 448 | ||
439 | ### Delete project hook | 449 | ### Delete project hook |
lib/api/entities.rb
@@ -24,6 +24,10 @@ module API | @@ -24,6 +24,10 @@ module API | ||
24 | expose :id, :url, :created_at | 24 | expose :id, :url, :created_at |
25 | end | 25 | end |
26 | 26 | ||
27 | + class ProjectHook < Hook | ||
28 | + expose :project_id, :push_events, :issues_events, :merge_requests_events | ||
29 | + end | ||
30 | + | ||
27 | class ForkedFromProject < Grape::Entity | 31 | class ForkedFromProject < Grape::Entity |
28 | expose :id | 32 | expose :id |
29 | expose :name, :name_with_namespace | 33 | expose :name, :name_with_namespace |
lib/api/project_hooks.rb
@@ -22,7 +22,7 @@ module API | @@ -22,7 +22,7 @@ module API | ||
22 | # GET /projects/:id/hooks | 22 | # GET /projects/:id/hooks |
23 | get ":id/hooks" do | 23 | get ":id/hooks" do |
24 | @hooks = paginate user_project.hooks | 24 | @hooks = paginate user_project.hooks |
25 | - present @hooks, with: Entities::Hook | 25 | + present @hooks, with: Entities::ProjectHook |
26 | end | 26 | end |
27 | 27 | ||
28 | # Get a project hook | 28 | # Get a project hook |
@@ -34,7 +34,7 @@ module API | @@ -34,7 +34,7 @@ module API | ||
34 | # GET /projects/:id/hooks/:hook_id | 34 | # GET /projects/:id/hooks/:hook_id |
35 | get ":id/hooks/:hook_id" do | 35 | get ":id/hooks/:hook_id" do |
36 | @hook = user_project.hooks.find(params[:hook_id]) | 36 | @hook = user_project.hooks.find(params[:hook_id]) |
37 | - present @hook, with: Entities::Hook | 37 | + present @hook, with: Entities::ProjectHook |
38 | end | 38 | end |
39 | 39 | ||
40 | 40 | ||
@@ -47,10 +47,11 @@ module API | @@ -47,10 +47,11 @@ module API | ||
47 | # POST /projects/:id/hooks | 47 | # POST /projects/:id/hooks |
48 | post ":id/hooks" do | 48 | post ":id/hooks" do |
49 | required_attributes! [:url] | 49 | required_attributes! [:url] |
50 | + attrs = attributes_for_keys [:url, :push_events, :issues_events, :merge_requests_events] | ||
51 | + @hook = user_project.hooks.new(attrs) | ||
50 | 52 | ||
51 | - @hook = user_project.hooks.new({"url" => params[:url]}) | ||
52 | if @hook.save | 53 | if @hook.save |
53 | - present @hook, with: Entities::Hook | 54 | + present @hook, with: Entities::ProjectHook |
54 | else | 55 | else |
55 | if @hook.errors[:url].present? | 56 | if @hook.errors[:url].present? |
56 | error!("Invalid url given", 422) | 57 | error!("Invalid url given", 422) |
@@ -70,10 +71,10 @@ module API | @@ -70,10 +71,10 @@ module API | ||
70 | put ":id/hooks/:hook_id" do | 71 | put ":id/hooks/:hook_id" do |
71 | @hook = user_project.hooks.find(params[:hook_id]) | 72 | @hook = user_project.hooks.find(params[:hook_id]) |
72 | required_attributes! [:url] | 73 | required_attributes! [:url] |
74 | + attrs = attributes_for_keys [:url, :push_events, :issues_events, :merge_requests_events] | ||
73 | 75 | ||
74 | - attrs = attributes_for_keys [:url] | ||
75 | if @hook.update_attributes attrs | 76 | if @hook.update_attributes attrs |
76 | - present @hook, with: Entities::Hook | 77 | + present @hook, with: Entities::ProjectHook |
77 | else | 78 | else |
78 | if @hook.errors[:url].present? | 79 | if @hook.errors[:url].present? |
79 | error!("Invalid url given", 422) | 80 | error!("Invalid url given", 422) |
spec/models/service_hook_spec.rb
@@ -2,13 +2,16 @@ | @@ -2,13 +2,16 @@ | ||
2 | # | 2 | # |
3 | # Table name: web_hooks | 3 | # Table name: web_hooks |
4 | # | 4 | # |
5 | -# id :integer not null, primary key | ||
6 | -# url :string(255) | ||
7 | -# project_id :integer | ||
8 | -# created_at :datetime not null | ||
9 | -# updated_at :datetime not null | ||
10 | -# type :string(255) default("ProjectHook") | ||
11 | -# service_id :integer | 5 | +# id :integer not null, primary key |
6 | +# url :string(255) | ||
7 | +# project_id :integer | ||
8 | +# created_at :datetime not null | ||
9 | +# updated_at :datetime not null | ||
10 | +# type :string(255) default("ProjectHook") | ||
11 | +# service_id :integer | ||
12 | +# push_events :boolean default(TRUE), not null | ||
13 | +# issues_events :boolean default(FALSE), not null | ||
14 | +# merge_requests_events :boolean default(FALSE), not null | ||
12 | # | 15 | # |
13 | 16 | ||
14 | require "spec_helper" | 17 | require "spec_helper" |
spec/models/system_hook_spec.rb
@@ -2,13 +2,16 @@ | @@ -2,13 +2,16 @@ | ||
2 | # | 2 | # |
3 | # Table name: web_hooks | 3 | # Table name: web_hooks |
4 | # | 4 | # |
5 | -# id :integer not null, primary key | ||
6 | -# url :string(255) | ||
7 | -# project_id :integer | ||
8 | -# created_at :datetime not null | ||
9 | -# updated_at :datetime not null | ||
10 | -# type :string(255) default("ProjectHook") | ||
11 | -# service_id :integer | 5 | +# id :integer not null, primary key |
6 | +# url :string(255) | ||
7 | +# project_id :integer | ||
8 | +# created_at :datetime not null | ||
9 | +# updated_at :datetime not null | ||
10 | +# type :string(255) default("ProjectHook") | ||
11 | +# service_id :integer | ||
12 | +# push_events :boolean default(TRUE), not null | ||
13 | +# issues_events :boolean default(FALSE), not null | ||
14 | +# merge_requests_events :boolean default(FALSE), not null | ||
12 | # | 15 | # |
13 | 16 | ||
14 | require "spec_helper" | 17 | require "spec_helper" |
spec/models/web_hook_spec.rb
@@ -2,13 +2,16 @@ | @@ -2,13 +2,16 @@ | ||
2 | # | 2 | # |
3 | # Table name: web_hooks | 3 | # Table name: web_hooks |
4 | # | 4 | # |
5 | -# id :integer not null, primary key | ||
6 | -# url :string(255) | ||
7 | -# project_id :integer | ||
8 | -# created_at :datetime not null | ||
9 | -# updated_at :datetime not null | ||
10 | -# type :string(255) default("ProjectHook") | ||
11 | -# service_id :integer | 5 | +# id :integer not null, primary key |
6 | +# url :string(255) | ||
7 | +# project_id :integer | ||
8 | +# created_at :datetime not null | ||
9 | +# updated_at :datetime not null | ||
10 | +# type :string(255) default("ProjectHook") | ||
11 | +# service_id :integer | ||
12 | +# push_events :boolean default(TRUE), not null | ||
13 | +# issues_events :boolean default(FALSE), not null | ||
14 | +# merge_requests_events :boolean default(FALSE), not null | ||
12 | # | 15 | # |
13 | 16 | ||
14 | require 'spec_helper' | 17 | require 'spec_helper' |
spec/observers/merge_request_observer_spec.rb
@@ -4,7 +4,7 @@ describe MergeRequestObserver do | @@ -4,7 +4,7 @@ describe MergeRequestObserver do | ||
4 | let(:some_user) { create :user } | 4 | let(:some_user) { create :user } |
5 | let(:assignee) { create :user } | 5 | let(:assignee) { create :user } |
6 | let(:author) { create :user } | 6 | let(:author) { create :user } |
7 | - let(:mr_mock) { double(:merge_request, id: 42, assignee: assignee, author: author) } | 7 | + let(:mr_mock) { double(:merge_request, id: 42, assignee: assignee, author: author).as_null_object } |
8 | let(:assigned_mr) { create(:merge_request, assignee: assignee, author: author, target_project: create(:project)) } | 8 | let(:assigned_mr) { create(:merge_request, assignee: assignee, author: author, target_project: create(:project)) } |
9 | let(:unassigned_mr) { create(:merge_request, author: author, target_project: create(:project)) } | 9 | let(:unassigned_mr) { create(:merge_request, author: author, target_project: create(:project)) } |
10 | let(:closed_assigned_mr) { create(:closed_merge_request, assignee: assignee, author: author, target_project: create(:project)) } | 10 | let(:closed_assigned_mr) { create(:closed_merge_request, assignee: assignee, author: author, target_project: create(:project)) } |
@@ -0,0 +1,132 @@ | @@ -0,0 +1,132 @@ | ||
1 | +require 'spec_helper' | ||
2 | + | ||
3 | +describe API::API, 'ProjectHooks' do | ||
4 | + include ApiHelpers | ||
5 | + before(:each) { enable_observers } | ||
6 | + after(:each) { disable_observers } | ||
7 | + | ||
8 | + let(:user) { create(:user) } | ||
9 | + let(:user3) { create(:user) } | ||
10 | + let!(:project) { create(:project_with_code, creator_id: user.id, namespace: user.namespace) } | ||
11 | + let!(:hook) { create(:project_hook, project: project, url: "http://example.com") } | ||
12 | + | ||
13 | + before do | ||
14 | + project.team << [user, :master] | ||
15 | + project.team << [user3, :developer] | ||
16 | + end | ||
17 | + | ||
18 | + describe "GET /projects/:id/hooks" do | ||
19 | + context "authorized user" do | ||
20 | + it "should return project hooks" do | ||
21 | + get api("/projects/#{project.id}/hooks", user) | ||
22 | + response.status.should == 200 | ||
23 | + | ||
24 | + json_response.should be_an Array | ||
25 | + json_response.count.should == 1 | ||
26 | + json_response.first['url'].should == "http://example.com" | ||
27 | + end | ||
28 | + end | ||
29 | + | ||
30 | + context "unauthorized user" do | ||
31 | + it "should not access project hooks" do | ||
32 | + get api("/projects/#{project.id}/hooks", user3) | ||
33 | + response.status.should == 403 | ||
34 | + end | ||
35 | + end | ||
36 | + end | ||
37 | + | ||
38 | + describe "GET /projects/:id/hooks/:hook_id" do | ||
39 | + context "authorized user" do | ||
40 | + it "should return a project hook" do | ||
41 | + get api("/projects/#{project.id}/hooks/#{hook.id}", user) | ||
42 | + response.status.should == 200 | ||
43 | + json_response['url'].should == hook.url | ||
44 | + end | ||
45 | + | ||
46 | + it "should return a 404 error if hook id is not available" do | ||
47 | + get api("/projects/#{project.id}/hooks/1234", user) | ||
48 | + response.status.should == 404 | ||
49 | + end | ||
50 | + end | ||
51 | + | ||
52 | + context "unauthorized user" do | ||
53 | + it "should not access an existing hook" do | ||
54 | + get api("/projects/#{project.id}/hooks/#{hook.id}", user3) | ||
55 | + response.status.should == 403 | ||
56 | + end | ||
57 | + end | ||
58 | + | ||
59 | + it "should return a 404 error if hook id is not available" do | ||
60 | + get api("/projects/#{project.id}/hooks/1234", user) | ||
61 | + response.status.should == 404 | ||
62 | + end | ||
63 | + end | ||
64 | + | ||
65 | + describe "POST /projects/:id/hooks" do | ||
66 | + it "should add hook to project" do | ||
67 | + expect { | ||
68 | + post api("/projects/#{project.id}/hooks", user), | ||
69 | + url: "http://example.com", issues_events: true | ||
70 | + }.to change {project.hooks.count}.by(1) | ||
71 | + response.status.should == 201 | ||
72 | + end | ||
73 | + | ||
74 | + it "should return a 400 error if url not given" do | ||
75 | + post api("/projects/#{project.id}/hooks", user) | ||
76 | + response.status.should == 400 | ||
77 | + end | ||
78 | + | ||
79 | + it "should return a 422 error if url not valid" do | ||
80 | + post api("/projects/#{project.id}/hooks", user), "url" => "ftp://example.com" | ||
81 | + response.status.should == 422 | ||
82 | + end | ||
83 | + end | ||
84 | + | ||
85 | + describe "PUT /projects/:id/hooks/:hook_id" do | ||
86 | + it "should update an existing project hook" do | ||
87 | + put api("/projects/#{project.id}/hooks/#{hook.id}", user), | ||
88 | + url: 'http://example.org', push_events: false | ||
89 | + response.status.should == 200 | ||
90 | + json_response['url'].should == 'http://example.org' | ||
91 | + end | ||
92 | + | ||
93 | + it "should return 404 error if hook id not found" do | ||
94 | + put api("/projects/#{project.id}/hooks/1234", user), url: 'http://example.org' | ||
95 | + response.status.should == 404 | ||
96 | + end | ||
97 | + | ||
98 | + it "should return 400 error if url is not given" do | ||
99 | + put api("/projects/#{project.id}/hooks/#{hook.id}", user) | ||
100 | + response.status.should == 400 | ||
101 | + end | ||
102 | + | ||
103 | + it "should return a 422 error if url is not valid" do | ||
104 | + put api("/projects/#{project.id}/hooks/#{hook.id}", user), url: 'ftp://example.com' | ||
105 | + response.status.should == 422 | ||
106 | + end | ||
107 | + end | ||
108 | + | ||
109 | + describe "DELETE /projects/:id/hooks/:hook_id" do | ||
110 | + it "should delete hook from project" do | ||
111 | + expect { | ||
112 | + delete api("/projects/#{project.id}/hooks/#{hook.id}", user) | ||
113 | + }.to change {project.hooks.count}.by(-1) | ||
114 | + response.status.should == 200 | ||
115 | + end | ||
116 | + | ||
117 | + it "should return success when deleting hook" do | ||
118 | + delete api("/projects/#{project.id}/hooks/#{hook.id}", user) | ||
119 | + response.status.should == 200 | ||
120 | + end | ||
121 | + | ||
122 | + it "should return success when deleting non existent hook" do | ||
123 | + delete api("/projects/#{project.id}/hooks/42", user) | ||
124 | + response.status.should == 200 | ||
125 | + end | ||
126 | + | ||
127 | + it "should return a 405 error if hook id not given" do | ||
128 | + delete api("/projects/#{project.id}/hooks", user) | ||
129 | + response.status.should == 405 | ||
130 | + end | ||
131 | + end | ||
132 | +end |
spec/requests/api/projects_spec.rb
@@ -10,7 +10,6 @@ describe API::API do | @@ -10,7 +10,6 @@ describe API::API do | ||
10 | let(:user3) { create(:user) } | 10 | let(:user3) { create(:user) } |
11 | let(:admin) { create(:admin) } | 11 | let(:admin) { create(:admin) } |
12 | let!(:project) { create(:project_with_code, creator_id: user.id, namespace: user.namespace) } | 12 | let!(:project) { create(:project_with_code, creator_id: user.id, namespace: user.namespace) } |
13 | - let!(:hook) { create(:project_hook, project: project, url: "http://example.com") } | ||
14 | let!(:snippet) { create(:project_snippet, author: user, project: project, title: 'example') } | 13 | let!(:snippet) { create(:project_snippet, author: user, project: project, title: 'example') } |
15 | let!(:users_project) { create(:users_project, user: user, project: project, project_access: UsersProject::MASTER) } | 14 | let!(:users_project) { create(:users_project, user: user, project: project, project_access: UsersProject::MASTER) } |
16 | let!(:users_project2) { create(:users_project, user: user3, project: project, project_access: UsersProject::DEVELOPER) } | 15 | let!(:users_project2) { create(:users_project, user: user3, project: project, project_access: UsersProject::DEVELOPER) } |
@@ -439,121 +438,6 @@ describe API::API do | @@ -439,121 +438,6 @@ describe API::API do | ||
439 | end | 438 | end |
440 | end | 439 | end |
441 | 440 | ||
442 | - describe "GET /projects/:id/hooks" do | ||
443 | - context "authorized user" do | ||
444 | - it "should return project hooks" do | ||
445 | - get api("/projects/#{project.id}/hooks", user) | ||
446 | - response.status.should == 200 | ||
447 | - | ||
448 | - json_response.should be_an Array | ||
449 | - json_response.count.should == 1 | ||
450 | - json_response.first['url'].should == "http://example.com" | ||
451 | - end | ||
452 | - end | ||
453 | - | ||
454 | - context "unauthorized user" do | ||
455 | - it "should not access project hooks" do | ||
456 | - get api("/projects/#{project.id}/hooks", user3) | ||
457 | - response.status.should == 403 | ||
458 | - end | ||
459 | - end | ||
460 | - end | ||
461 | - | ||
462 | - describe "GET /projects/:id/hooks/:hook_id" do | ||
463 | - context "authorized user" do | ||
464 | - it "should return a project hook" do | ||
465 | - get api("/projects/#{project.id}/hooks/#{hook.id}", user) | ||
466 | - response.status.should == 200 | ||
467 | - json_response['url'].should == hook.url | ||
468 | - end | ||
469 | - | ||
470 | - it "should return a 404 error if hook id is not available" do | ||
471 | - get api("/projects/#{project.id}/hooks/1234", user) | ||
472 | - response.status.should == 404 | ||
473 | - end | ||
474 | - end | ||
475 | - | ||
476 | - context "unauthorized user" do | ||
477 | - it "should not access an existing hook" do | ||
478 | - get api("/projects/#{project.id}/hooks/#{hook.id}", user3) | ||
479 | - response.status.should == 403 | ||
480 | - end | ||
481 | - end | ||
482 | - | ||
483 | - it "should return a 404 error if hook id is not available" do | ||
484 | - get api("/projects/#{project.id}/hooks/1234", user) | ||
485 | - response.status.should == 404 | ||
486 | - end | ||
487 | - end | ||
488 | - | ||
489 | - describe "POST /projects/:id/hooks" do | ||
490 | - it "should add hook to project" do | ||
491 | - expect { | ||
492 | - post api("/projects/#{project.id}/hooks", user), | ||
493 | - url: "http://example.com" | ||
494 | - }.to change {project.hooks.count}.by(1) | ||
495 | - response.status.should == 201 | ||
496 | - end | ||
497 | - | ||
498 | - it "should return a 400 error if url not given" do | ||
499 | - post api("/projects/#{project.id}/hooks", user) | ||
500 | - response.status.should == 400 | ||
501 | - end | ||
502 | - | ||
503 | - it "should return a 422 error if url not valid" do | ||
504 | - post api("/projects/#{project.id}/hooks", user), "url" => "ftp://example.com" | ||
505 | - response.status.should == 422 | ||
506 | - end | ||
507 | - end | ||
508 | - | ||
509 | - describe "PUT /projects/:id/hooks/:hook_id" do | ||
510 | - it "should update an existing project hook" do | ||
511 | - put api("/projects/#{project.id}/hooks/#{hook.id}", user), | ||
512 | - url: 'http://example.org' | ||
513 | - response.status.should == 200 | ||
514 | - json_response['url'].should == 'http://example.org' | ||
515 | - end | ||
516 | - | ||
517 | - it "should return 404 error if hook id not found" do | ||
518 | - put api("/projects/#{project.id}/hooks/1234", user), url: 'http://example.org' | ||
519 | - response.status.should == 404 | ||
520 | - end | ||
521 | - | ||
522 | - it "should return 400 error if url is not given" do | ||
523 | - put api("/projects/#{project.id}/hooks/#{hook.id}", user) | ||
524 | - response.status.should == 400 | ||
525 | - end | ||
526 | - | ||
527 | - it "should return a 422 error if url is not valid" do | ||
528 | - put api("/projects/#{project.id}/hooks/#{hook.id}", user), url: 'ftp://example.com' | ||
529 | - response.status.should == 422 | ||
530 | - end | ||
531 | - end | ||
532 | - | ||
533 | - describe "DELETE /projects/:id/hooks/:hook_id" do | ||
534 | - it "should delete hook from project" do | ||
535 | - expect { | ||
536 | - delete api("/projects/#{project.id}/hooks/#{hook.id}", user) | ||
537 | - }.to change {project.hooks.count}.by(-1) | ||
538 | - response.status.should == 200 | ||
539 | - end | ||
540 | - | ||
541 | - it "should return success when deleting hook" do | ||
542 | - delete api("/projects/#{project.id}/hooks/#{hook.id}", user) | ||
543 | - response.status.should == 200 | ||
544 | - end | ||
545 | - | ||
546 | - it "should return success when deleting non existent hook" do | ||
547 | - delete api("/projects/#{project.id}/hooks/42", user) | ||
548 | - response.status.should == 200 | ||
549 | - end | ||
550 | - | ||
551 | - it "should return a 405 error if hook id not given" do | ||
552 | - delete api("/projects/#{project.id}/hooks", user) | ||
553 | - response.status.should == 405 | ||
554 | - end | ||
555 | - end | ||
556 | - | ||
557 | describe "GET /projects/:id/snippets" do | 441 | describe "GET /projects/:id/snippets" do |
558 | it "should return an array of project snippets" do | 442 | it "should return an array of project snippets" do |
559 | get api("/projects/#{project.id}/snippets", user) | 443 | get api("/projects/#{project.id}/snippets", user) |
spec/services/git_push_service_spec.rb
@@ -74,38 +74,19 @@ describe GitPushService do | @@ -74,38 +74,19 @@ describe GitPushService do | ||
74 | end | 74 | end |
75 | 75 | ||
76 | describe "Web Hooks" do | 76 | describe "Web Hooks" do |
77 | - context "with web hooks" do | ||
78 | - before do | ||
79 | - @project_hook = create(:project_hook) | ||
80 | - @project_hook_2 = create(:project_hook) | ||
81 | - project.hooks << [@project_hook, @project_hook_2] | ||
82 | - | ||
83 | - stub_request(:post, @project_hook.url) | ||
84 | - stub_request(:post, @project_hook_2.url) | ||
85 | - end | ||
86 | - | ||
87 | - it "executes multiple web hook" do | ||
88 | - @project_hook.should_receive(:async_execute).once | ||
89 | - @project_hook_2.should_receive(:async_execute).once | ||
90 | - | ||
91 | - service.execute(project, user, @oldrev, @newrev, @ref) | ||
92 | - end | ||
93 | - end | ||
94 | - | ||
95 | context "execute web hooks" do | 77 | context "execute web hooks" do |
96 | - before do | ||
97 | - @project_hook = create(:project_hook) | ||
98 | - project.hooks << [@project_hook] | ||
99 | - stub_request(:post, @project_hook.url) | ||
100 | - end | ||
101 | - | ||
102 | it "when pushing a branch for the first time" do | 78 | it "when pushing a branch for the first time" do |
103 | - @project_hook.should_receive(:async_execute) | 79 | + project.should_receive(:execute_hooks) |
104 | service.execute(project, user, @blankrev, 'newrev', 'refs/heads/master') | 80 | service.execute(project, user, @blankrev, 'newrev', 'refs/heads/master') |
105 | end | 81 | end |
106 | 82 | ||
83 | + it "when pushing new commits to existing branch" do | ||
84 | + project.should_receive(:execute_hooks) | ||
85 | + service.execute(project, user, 'oldrev', 'newrev', 'refs/heads/master') | ||
86 | + end | ||
87 | + | ||
107 | it "when pushing tags" do | 88 | it "when pushing tags" do |
108 | - @project_hook.should_not_receive(:async_execute) | 89 | + project.should_not_receive(:execute_hooks) |
109 | service.execute(project, user, 'newrev', 'newrev', 'refs/tags/v1.0.0') | 90 | service.execute(project, user, 'newrev', 'newrev', 'refs/tags/v1.0.0') |
110 | end | 91 | end |
111 | end | 92 | end |