github-web-hooks-receiver 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,240 @@
1
+ # -*- coding: utf-8 -*-
2
+ #
3
+ # Copyright (C) 2013 Kenji Okimoto <okimoto@clear-code.com>
4
+ #
5
+ # This program is free software: you can redistribute it and/or modify
6
+ # it under the terms of the GNU General Public License as published by
7
+ # the Free Software Foundation, either version 3 of the License, or
8
+ # (at your option) any later version.
9
+ #
10
+ # This program is distributed in the hope that it will be useful,
11
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
+ # GNU General Public License for more details.
14
+ #
15
+ # You should have received a copy of the GNU General Public License
16
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
17
+
18
+ require "test-unit"
19
+ require "yaml"
20
+
21
+ require "github-web-hooks-receiver"
22
+
23
+ class ReceiverConfigTest < Test::Unit::TestCase
24
+ def setup
25
+ fixtures_dir = File.expand_path(File.join(File.dirname(__FILE__), "fixtures"))
26
+ options = YAML.load_file(File.join(fixtures_dir, "config-multi-site.yaml"))
27
+ @receiver = GitHubWebHooksReceiver::App.new(options)
28
+ end
29
+
30
+ data("github.com/clear-code/git-utils" => {
31
+ :expected => {
32
+ :to => "commit@clear-code.com",
33
+ :add_html => true,
34
+ :from => nil,
35
+ },
36
+ :params => {
37
+ :domain => "github.com",
38
+ :owner => "clear-code",
39
+ :repository => "git-utils",
40
+ }
41
+ },
42
+ "github.com/ranguba/examples" => {
43
+ :expected => {
44
+ :to => "null@example.com",
45
+ :add_html => true,
46
+ :from => nil,
47
+ },
48
+ :params => {
49
+ :domain => "github.com",
50
+ :owner => "ranguba",
51
+ :repository => "examples",
52
+ }
53
+ },
54
+ "github.com/ranguba/ranguba" => {
55
+ :expected => {
56
+ :to => ["groonga-commit@rubyforge.org", "commit@clear-code.com"],
57
+ :add_html => true,
58
+ :from => nil,
59
+ },
60
+ :params => {
61
+ :domain => "github.com",
62
+ :owner => "ranguba",
63
+ :repository => "ranguba",
64
+ }
65
+ },
66
+ "gitlab.example.net/support/firefox" => {
67
+ :expected => {
68
+ :to => "support@example.net",
69
+ :add_html => false,
70
+ :from => "support+null@example.net",
71
+ },
72
+ :params => {
73
+ :domain => "gitlab.example.net",
74
+ :owner => "support",
75
+ :repository => "firefox",
76
+ }
77
+ },
78
+ "gitlab.example.org/clear-code/other" => {
79
+ :expected => {
80
+ :to => ["commit@example.org"],
81
+ :add_html => false,
82
+ :from => "null@example.org",
83
+ },
84
+ :params => {
85
+ :domain => "gitlab.example.org",
86
+ :owner => "clear-code",
87
+ :repository => "other",
88
+ }
89
+ },
90
+ "gitlab.example.org/clear-code/test-project1" => {
91
+ :expected => {
92
+ :to => "commit+test-project1@example.org",
93
+ :add_html => true,
94
+ :from => "null@example.org",
95
+ },
96
+ :params => {
97
+ :domain => "gitlab.example.org",
98
+ :owner => "clear-code",
99
+ :repository => "test-project1",
100
+ }
101
+ },
102
+ "gitlab.example.org/clear-code/test-project2" => {
103
+ :expected => {
104
+ :to => "commit+test-project2@example.org",
105
+ :add_html => false,
106
+ :from => "null@example.org",
107
+ },
108
+ :params => {
109
+ :domain => "gitlab.example.org",
110
+ :owner => "clear-code",
111
+ :repository => "test-project2",
112
+ }
113
+ },
114
+ "gitlab.example.org/support/thunderbird" => {
115
+ :expected => {
116
+ :to => "support@example.org",
117
+ :add_html => false,
118
+ :from => "null+support@example.org",
119
+ },
120
+ :params => {
121
+ :domain => "gitlab.example.org",
122
+ :owner => "support",
123
+ :repository => "thunderbird",
124
+ }
125
+ },
126
+ "ghe.example.com/clear-code/other" => {
127
+ :expected => {
128
+ :to => ["commit@example.com"],
129
+ :add_html => false,
130
+ :from => "null@example.com",
131
+ },
132
+ :params => {
133
+ :domain => "ghe.example.com",
134
+ :owner => "clear-code",
135
+ :repository => "other",
136
+ }
137
+ },
138
+ "ghe.example.com/clear-code/test-project1" => {
139
+ :expected => {
140
+ :to => "commit+test-project1@example.com",
141
+ :add_html => false,
142
+ :from => "null@example.com",
143
+ },
144
+ :params => {
145
+ :domain => "ghe.example.com",
146
+ :owner => "clear-code",
147
+ :repository => "test-project1",
148
+ }
149
+ },
150
+ "ghe.example.com/clear-code/test-project2" => {
151
+ :expected => {
152
+ :to => "commit+test-project2@example.com",
153
+ :add_html => false,
154
+ :from => "null@example.com",
155
+ },
156
+ :params => {
157
+ :domain => "ghe.example.com",
158
+ :owner => "clear-code",
159
+ :repository => "test-project2",
160
+ }
161
+ },
162
+ "ghe.example.com/support/thunderbird" => {
163
+ :expected => {
164
+ :to => "support@example.com",
165
+ :add_html => false,
166
+ :from => "null+support@example.com",
167
+ },
168
+ :params => {
169
+ :domain => "ghe.example.com",
170
+ :owner => "support",
171
+ :repository => "thunderbird",
172
+ }
173
+ },
174
+ "ghe.example.co.jp/clear-code/other" => {
175
+ :expected => {
176
+ :to => ["commit@example.co.jp"],
177
+ :add_html => true,
178
+ :from => "null@example.co.jp",
179
+ },
180
+ :params => {
181
+ :domain => "ghe.example.co.jp",
182
+ :owner => "clear-code",
183
+ :repository => "other",
184
+ }
185
+ },
186
+ "ghe.example.co.jp/clear-code/test-project1" => {
187
+ :expected => {
188
+ :to => "commit+test-project1@example.co.jp",
189
+ :add_html => true,
190
+ :from => "null@example.co.jp",
191
+ },
192
+ :params => {
193
+ :domain => "ghe.example.co.jp",
194
+ :owner => "clear-code",
195
+ :repository => "test-project1",
196
+ }
197
+ },
198
+ "ghe.example.co.jp/clear-code/test-project2" => {
199
+ :expected => {
200
+ :to => "commit+test-project2@example.co.jp",
201
+ :add_html => true,
202
+ :from => "null@example.co.jp",
203
+ },
204
+ :params => {
205
+ :domain => "ghe.example.co.jp",
206
+ :owner => "clear-code",
207
+ :repository => "test-project2",
208
+ }
209
+ },
210
+ "ghe.example.co.jp/support/thunderbird" => {
211
+ :expected => {
212
+ :to => "support@example.co.jp",
213
+ :add_html => true,
214
+ :from => "null+support@example.co.jp",
215
+ },
216
+ :params => {
217
+ :domain => "ghe.example.co.jp",
218
+ :owner => "support",
219
+ :repository => "thunderbird",
220
+ }
221
+ })
222
+ def test_repository_options(data)
223
+ params = data[:params]
224
+ domain = params[:domain]
225
+ owner = params[:owner]
226
+ repository = params[:repository]
227
+ options = @receiver.__send__(:repository_options, domain, owner, repository)
228
+ assert_options(data[:expected], options)
229
+ end
230
+
231
+ private
232
+ def assert_options(expected, options)
233
+ actual = {
234
+ :to => options[:to],
235
+ :add_html => options[:add_html],
236
+ :from => options[:from],
237
+ }
238
+ assert_equal(expected, actual)
239
+ end
240
+ end
@@ -0,0 +1,386 @@
1
+ # Copyright (C) 2010-2014 Kouhei Sutou <kou@clear-code.com>
2
+ #
3
+ # This program is free software: you can redistribute it and/or modify
4
+ # it under the terms of the GNU General Public License as published by
5
+ # the Free Software Foundation, either version 3 of the License, or
6
+ # (at your option) any later version.
7
+ #
8
+ # This program is distributed in the hope that it will be useful,
9
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
10
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11
+ # GNU General Public License for more details.
12
+ #
13
+ # You should have received a copy of the GNU General Public License
14
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
15
+
16
+ class ReceiverTest < Test::Unit::TestCase
17
+ include GitHubWebHooksReceiverTestUtils
18
+
19
+ class << self
20
+ def startup
21
+ test_dir = File.dirname(__FILE__)
22
+ fixtures_dir = File.join(test_dir, "fixtures")
23
+ @rroonga_git_dir = File.join(fixtures_dir, "rroonga.git")
24
+ system("git", "clone", "--mirror", "-q",
25
+ "https://github.com/ranguba/rroonga.git", @rroonga_git_dir)
26
+ end
27
+
28
+ def shutdown
29
+ FileUtils.rm_rf(@rroonga_git_dir)
30
+ end
31
+ end
32
+
33
+ def setup
34
+ test_dir = File.dirname(__FILE__)
35
+ @fixtures_dir = File.join(test_dir, "fixtures")
36
+ @tmp_dir = File.join(test_dir, "tmp")
37
+ FileUtils.mkdir_p(@tmp_dir)
38
+ Capybara.app = app
39
+ end
40
+
41
+ def teardown
42
+ FileUtils.rm_rf(@tmp_dir)
43
+ end
44
+
45
+ def app
46
+ GitHubWebHooksReceiver::App.new(options)
47
+ end
48
+
49
+ def test_get
50
+ visit "/"
51
+ assert_response("Method Not Allowed")
52
+ end
53
+
54
+ def test_post_ping
55
+ payload = {
56
+ "zen" => "Speak like a human.",
57
+ "hook_id" => 2043443,
58
+ }
59
+ env = {
60
+ "HTTP_X_GITHUB_EVENT" => "ping",
61
+ }
62
+ post_payload(payload, env)
63
+ assert_response("OK")
64
+ assert_equal("", body)
65
+ end
66
+
67
+ def test_post_without_parameters
68
+ page.driver.post("/")
69
+ assert_response("Bad Request")
70
+ assert_equal("payload is missing", body)
71
+ end
72
+
73
+ def test_post_with_empty_payload
74
+ page.driver.post("/", :payload => "")
75
+ assert_response("Bad Request")
76
+ error_message = nil
77
+ begin
78
+ JSON.parse("")
79
+ rescue
80
+ error_message = $!.message
81
+ end
82
+ assert_equal("invalid JSON format: <#{error_message}>",
83
+ body)
84
+ end
85
+
86
+ class GitHubTest < self
87
+ class << self
88
+ def startup
89
+ end
90
+
91
+ def shutdown
92
+ end
93
+ end
94
+
95
+ def test_post_with_non_target_repository
96
+ owner_name = "devil"
97
+ repository_name = "evil-repository"
98
+ post_payload(:repository => {
99
+ :name => repository_name,
100
+ :url => "https://github.com/super-devil/evil-repository",
101
+ :owner => {
102
+ :name => owner_name,
103
+ },
104
+ })
105
+ assert_response("Forbidden")
106
+ assert_equal("unacceptable repository: " +
107
+ "<#{owner_name.inspect}>:<#{repository_name.inspect}>",
108
+ body)
109
+ end
110
+
111
+ def test_post_without_owner
112
+ repository = {
113
+ "url" => "https://github.com/ranguba/rroonga",
114
+ "name" => "rroonga",
115
+ }
116
+ payload = {
117
+ "repository" => repository,
118
+ }
119
+ post_payload(payload)
120
+ assert_response("Bad Request")
121
+ assert_equal("repository owner or owner name is missing: <#{repository.inspect}>",
122
+ body)
123
+ end
124
+
125
+ def test_post_without_owner_name
126
+ repository = {
127
+ "url" => "https://github.com/ranguba/rroonga",
128
+ "name" => "rroonga",
129
+ "owner" => {},
130
+ }
131
+ payload = {
132
+ "repository" => repository,
133
+ }
134
+ post_payload(payload)
135
+ assert_response("Bad Request")
136
+ assert_equal("repository owner or owner name is missing: <#{repository.inspect}>",
137
+ body)
138
+ end
139
+
140
+ def test_post_without_before
141
+ payload = {
142
+ "repository" => {
143
+ "url" => "https://github.com/ranguba/rroonga",
144
+ "name" => "rroonga",
145
+ "owner" => {
146
+ "name" => "ranguba",
147
+ },
148
+ }
149
+ }
150
+ post_payload(payload)
151
+ assert_response("Bad Request")
152
+ assert_equal("before commit ID is missing",
153
+ body)
154
+ end
155
+
156
+ def test_post_without_after
157
+ payload = {
158
+ "before" => "0f2be32a3671360a323f1dee64c757bc9fc44998",
159
+ "repository" => {
160
+ "url" => "https://github.com/ranguba/rroonga",
161
+ "name" => "rroonga",
162
+ "owner" => {
163
+ "name" => "ranguba",
164
+ },
165
+ },
166
+ }
167
+ post_payload(payload)
168
+ assert_response("Bad Request")
169
+ assert_equal("after commit ID is missing",
170
+ body)
171
+ end
172
+
173
+ def test_post_without_reference
174
+ payload = {
175
+ "before" => "0f2be32a3671360a323f1dee64c757bc9fc44998",
176
+ "after" => "c7bf92799225d67788be7c42ea4f504a47708390",
177
+ "repository" => {
178
+ "url" => "https://github.com/ranguba/rroonga",
179
+ "name" => "rroonga",
180
+ "owner" => {
181
+ "name" => "ranguba",
182
+ },
183
+ },
184
+ }
185
+ post_payload(payload)
186
+ assert_response("Bad Request")
187
+ assert_equal("reference is missing",
188
+ body)
189
+ end
190
+
191
+ def test_post
192
+ repository_mirror_path = mirror_path("github.com", "ranguba", "rroonga")
193
+ assert_false(File.exist?(repository_mirror_path))
194
+ before = "0f2be32a3671360a323f1dee64c757bc9fc44998"
195
+ after = "c7bf92799225d67788be7c42ea4f504a47708390"
196
+ reference = "refs/heads/master"
197
+ post_payload(:repository => {
198
+ :url => "https://github.com/ranguba/rroonga",
199
+ :name => "rroonga",
200
+ :owner => {
201
+ :name => "ranguba",
202
+ },
203
+ },
204
+ :before => before,
205
+ :after => after,
206
+ :ref => reference)
207
+ assert_response("OK")
208
+ assert_true(File.exist?(repository_mirror_path))
209
+ result = YAML.load_file(File.join(@tmp_dir, "commit-email-result.yaml"))
210
+ assert_equal([{
211
+ "argv" => ["--repository", repository_mirror_path,
212
+ "--max-size", "1M",
213
+ "--repository-browser", "github",
214
+ "--github-user", "ranguba",
215
+ "--github-repository", "rroonga",
216
+ "--name", "ranguba/rroonga",
217
+ "null@example.com"],
218
+ "lines" => ["#{before} #{after} #{reference}\n"],
219
+ }],
220
+ result)
221
+ end
222
+
223
+ def test_per_owner_configuration
224
+ repository_mirror_path = mirror_path("github.com", "ranguba", "rroonga")
225
+ assert_false(File.exist?(repository_mirror_path))
226
+ options[:owners] = {
227
+ "ranguba" => {
228
+ :to => "ranguba-commit@example.org",
229
+ :from => "ranguba+commit@example.org",
230
+ :sender => "null@example.org",
231
+ }
232
+ }
233
+ Capybara.app = app # TODO: extract option change tess to a sub test case
234
+ before = "0f2be32a3671360a323f1dee64c757bc9fc44998"
235
+ after = "c7bf92799225d67788be7c42ea4f504a47708390"
236
+ reference = "refs/heads/master"
237
+ post_payload(:repository => {
238
+ :url => "https://github.com/ranguba/rroonga",
239
+ :name => "rroonga",
240
+ :owner => {
241
+ :name => "ranguba",
242
+ },
243
+ },
244
+ :before => before,
245
+ :after => after,
246
+ :ref => reference)
247
+ assert_response("OK")
248
+ assert_true(File.exist?(repository_mirror_path))
249
+ result = YAML.load_file(File.join(@tmp_dir, "commit-email-result.yaml"))
250
+ assert_equal([{
251
+ "argv" => ["--repository", repository_mirror_path,
252
+ "--max-size", "1M",
253
+ "--repository-browser", "github",
254
+ "--github-user", "ranguba",
255
+ "--github-repository", "rroonga",
256
+ "--name", "ranguba/rroonga",
257
+ "--from", "ranguba+commit@example.org",
258
+ "--sender", "null@example.org",
259
+ "ranguba-commit@example.org"],
260
+ "lines" => ["#{before} #{after} #{reference}\n"],
261
+ }],
262
+ result)
263
+ end
264
+
265
+ def test_per_repository_configuration
266
+ repository_mirror_path = mirror_path("github.com", "ranguba", "rroonga")
267
+ assert_false(File.exist?(repository_mirror_path))
268
+ options[:owners] = {
269
+ "ranguba" => {
270
+ :to => "ranguba-commit@example.org",
271
+ :from => "ranguba+commit@example.org",
272
+ :sender => "null@example.org",
273
+ "repositories" => {
274
+ "rroonga" => {
275
+ :to => "ranguba-commit@example.net",
276
+ :from => "ranguba+commit@example.net",
277
+ :sender => "null@example.net",
278
+ }
279
+ }
280
+ }
281
+ }
282
+ Capybara.app = app # TODO: extract option change tess to a sub test case
283
+ before = "0f2be32a3671360a323f1dee64c757bc9fc44998"
284
+ after = "c7bf92799225d67788be7c42ea4f504a47708390"
285
+ reference = "refs/heads/master"
286
+ post_payload(:repository => {
287
+ :url => "https://github.com/ranguba/rroonga",
288
+ :name => "rroonga",
289
+ :owner => {
290
+ :name => "ranguba",
291
+ },
292
+ },
293
+ :before => before,
294
+ :after => after,
295
+ :ref => reference)
296
+ assert_response("OK")
297
+ assert_true(File.exist?(repository_mirror_path))
298
+ result = YAML.load_file(File.join(@tmp_dir, "commit-email-result.yaml"))
299
+ assert_equal([{
300
+ "argv" => ["--repository", repository_mirror_path,
301
+ "--max-size", "1M",
302
+ "--repository-browser", "github",
303
+ "--github-user", "ranguba",
304
+ "--github-repository", "rroonga",
305
+ "--name", "ranguba/rroonga",
306
+ "--from", "ranguba+commit@example.net",
307
+ "--sender", "null@example.net",
308
+ "ranguba-commit@example.net"],
309
+ "lines" => ["#{before} #{after} #{reference}\n"],
310
+ }],
311
+ result)
312
+ end
313
+
314
+ def test_gollum
315
+ repository_mirror_path =
316
+ mirror_path("github.com", "ranguba", "rroonga.wiki")
317
+ assert_false(File.exist?(repository_mirror_path))
318
+ before = "83841cd1576e28d85aa5ec312fd3804d1352e5ab^"
319
+ after = "83841cd1576e28d85aa5ec312fd3804d1352e5ab"
320
+ reference = "refs/heads/master"
321
+ payload = {
322
+ "repository" => {
323
+ "url" => "https://github.com/ranguba/rroonga",
324
+ "clone_url" => "https://github.com/ranguba/rroonga.git",
325
+ "name" => "rroonga",
326
+ "owner" => {
327
+ "login" => "ranguba",
328
+ },
329
+ },
330
+ "pages" => [
331
+ {
332
+ "sha" => "83841cd1576e28d85aa5ec312fd3804d1352e5ab",
333
+ },
334
+ ],
335
+ }
336
+ env = {
337
+ "HTTP_X_GITHUB_EVENT" => "gollum",
338
+ }
339
+ post_payload(payload, env)
340
+ assert_response("OK")
341
+ assert_true(File.exist?(repository_mirror_path))
342
+ result = YAML.load_file(File.join(@tmp_dir, "commit-email-result.yaml"))
343
+ assert_equal([
344
+ {
345
+ "argv" => [
346
+ "--repository", repository_mirror_path,
347
+ "--max-size", "1M",
348
+ "--repository-browser", "github-wiki",
349
+ "--github-user", "ranguba",
350
+ "--github-repository", "rroonga",
351
+ "--name", "ranguba/rroonga.wiki",
352
+ "null@example.com"],
353
+ "lines" => ["#{before} #{after} #{reference}\n"],
354
+ },
355
+ ],
356
+ result)
357
+ end
358
+ end
359
+
360
+ private
361
+ def post_payload(payload, env={})
362
+ env = default_env.merge(env)
363
+ page.driver.post("/", {:payload => JSON.generate(payload)}, env)
364
+ end
365
+
366
+ def default_env
367
+ {
368
+ "HTTP_X_GITHUB_EVENT" => "push",
369
+ }
370
+ end
371
+
372
+ def options
373
+ @options ||= {
374
+ :targets => ["rroonga"],
375
+ :base_dir => @tmp_dir,
376
+ :fixtures_dir => @fixtures_dir,
377
+ :repository_class => LocalRepository,
378
+ :commit_email => File.join(@fixtures_dir, "mock-commit-email.rb"),
379
+ :to => "null@example.com",
380
+ }
381
+ end
382
+
383
+ def mirror_path(*components)
384
+ File.join(@tmp_dir, "mirrors", *components)
385
+ end
386
+ end