hookworm-handlers 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (44) hide show
  1. checksums.yaml +15 -0
  2. data/.gitignore +17 -0
  3. data/.rspec +3 -0
  4. data/.rubocop.yml +3 -0
  5. data/.simplecov +6 -0
  6. data/.travis.yml +17 -0
  7. data/.yardopts +1 -0
  8. data/Gemfile +4 -0
  9. data/LICENSE.md +23 -0
  10. data/README.md +29 -0
  11. data/Rakefile +20 -0
  12. data/bin/hookworm-annotator +6 -0
  13. data/bin/hookworm-build-index-handler +6 -0
  14. data/bin/hookworm-logging-handler +6 -0
  15. data/bin/hookworm-rogue-commit-handler +6 -0
  16. data/hookworm-handlers.gemspec +32 -0
  17. data/lib/hookworm/annotator.rb +49 -0
  18. data/lib/hookworm/build_index_handler.rb +132 -0
  19. data/lib/hookworm/github_payload_annotator.rb +110 -0
  20. data/lib/hookworm/handlers/version.rb +5 -0
  21. data/lib/hookworm/handlers.rb +5 -0
  22. data/lib/hookworm/logging_handler.rb +55 -0
  23. data/lib/hookworm/rogue-commit-email-tmpl.erb +153 -0
  24. data/lib/hookworm/rogue_commit_handler.rb +240 -0
  25. data/lib/hookworm/travis_payload_annotator.rb +23 -0
  26. data/lib/hookworm-handlers.rb +7 -0
  27. data/sampledata/github-payloads/bogus.json +4 -0
  28. data/sampledata/github-payloads/branch_delete.json +41 -0
  29. data/sampledata/github-payloads/pull_request.json +153 -0
  30. data/sampledata/github-payloads/rogue.json +152 -0
  31. data/sampledata/github-payloads/rogue_unwatched_branch.json +152 -0
  32. data/sampledata/github-payloads/rogue_unwatched_path.json +91 -0
  33. data/sampledata/github-payloads/valid.json +66 -0
  34. data/sampledata/github-payloads/with_nulls.json +67 -0
  35. data/sampledata/travis-payloads/annotated_success.json +76 -0
  36. data/sampledata/travis-payloads/success.json +74 -0
  37. data/sampledata/travis-payloads/valid.json +56 -0
  38. data/spec/lib/hookworm/annotator_spec.rb +103 -0
  39. data/spec/lib/hookworm/build_index_handler_spec.rb +110 -0
  40. data/spec/lib/hookworm/logging_handler_spec.rb +134 -0
  41. data/spec/lib/hookworm/rogue_commit_handler_spec.rb +65 -0
  42. data/spec/spec_helper.rb +3 -0
  43. data/spec/support.rb +117 -0
  44. metadata +222 -0
@@ -0,0 +1,56 @@
1
+ {
2
+ "payload": {
3
+ "id": 1,
4
+ "number": 1,
5
+ "status": null,
6
+ "started_at": null,
7
+ "finished_at": null,
8
+ "status_message": "Passed",
9
+ "commit": "62aae5f70ceee39123ef",
10
+ "branch": "master",
11
+ "message": "the commit message",
12
+ "compare_url": "https://github.com/svenfuchs/minimal/compare/master...develop",
13
+ "committed_at": "2011-11-11T11:11:11Z",
14
+ "committer_name": "Sven Fuchs",
15
+ "committer_email": "svenfuchs@artweb-design.de",
16
+ "author_name": "Sven Fuchs",
17
+ "author_email": "svenfuchs@artweb-design.de",
18
+ "repository": {
19
+ "id": 1,
20
+ "name": "minimæl",
21
+ "owner_name": "svenfuchs",
22
+ "url": "http://github.com/svenfuchs/minimal"
23
+ },
24
+ "matrix": [
25
+ {
26
+ "id": 2,
27
+ "repository_id": 1,
28
+ "number": "1.1",
29
+ "state": "created",
30
+ "started_at": null,
31
+ "finished_at": null,
32
+ "config": {
33
+ "notifications": {
34
+ "webhooks": [
35
+ "http://evome.fr/notifications",
36
+ "http://example.com/"
37
+ ]
38
+ }
39
+ },
40
+ "status": null,
41
+ "log": "",
42
+ "result": null,
43
+ "parent_id": 1,
44
+ "commit": "62aae5f70ceee39123ef",
45
+ "branch": "master",
46
+ "message": "the commit message",
47
+ "committed_at": "2011-11-11T11: 11: 11Z",
48
+ "committer_name": "Sven Fuchs",
49
+ "committer_email": "svenfuchs@artweb-design.de",
50
+ "author_name": "Sven Fuchs",
51
+ "author_email": "svenfuchs@artweb-design.de",
52
+ "compare_url": "https://github.com/svenfuchs/minimal/compare/master...develop"
53
+ }
54
+ ]
55
+ }
56
+ }
@@ -0,0 +1,103 @@
1
+ describe Hookworm::Annotator do
2
+ include Support::JunkDrawer
3
+
4
+ let(:fake_stderr) { StringIO.new }
5
+ let(:fake_stdout) { StringIO.new }
6
+ let(:handler) { described_class.new }
7
+ let(:tempdir) { setup_tempdir }
8
+
9
+ let(:fizz) { rand(0..999) }
10
+
11
+ let :handler_config do
12
+ {
13
+ fizz: fizz,
14
+ working_dir: tempdir,
15
+ worm_flags: {
16
+ watched_branches: '^master$',
17
+ watched_paths: '.*'
18
+ }
19
+ }
20
+ end
21
+
22
+ before do
23
+ $stderr = fake_stderr
24
+ end
25
+
26
+ after do
27
+ $stderr = STDERR
28
+ end
29
+
30
+ context 'when handling github payloads' do
31
+ let(:github_payload_name) { 'pull_request' }
32
+
33
+ let :github_payload do
34
+ github_payload_hash(github_payload_name).tap do |p|
35
+ p[:repository].merge!(id: fizz)
36
+ end
37
+ end
38
+
39
+ let :annotated_result do
40
+ handler.run!(%w(handle github))
41
+ JSON.parse(
42
+ fake_stdout.string, symbolize_names: true
43
+ )
44
+ end
45
+
46
+ before do
47
+ handler.stub(
48
+ cfg: handler_config,
49
+ input_stream: StringIO.new(JSON.dump(github_payload)),
50
+ output_stream: fake_stdout
51
+ )
52
+ end
53
+
54
+ it 'annotates is_pr_merge' do
55
+ annotated_result[:is_pr_merge].should be_true
56
+ end
57
+
58
+ it 'annotates is_watched_branch' do
59
+ annotated_result[:is_watched_branch].should be_true
60
+ end
61
+
62
+ it 'annotates has_watched_path' do
63
+ annotated_result[:has_watched_path].should be_true
64
+ end
65
+
66
+ context 'when the payload is for a branch delete' do
67
+ let(:github_payload_name) { 'branch_delete' }
68
+
69
+ it 'does not explode' do
70
+ handler.run!(%w(handle github)).should == 0
71
+ end
72
+ end
73
+ end
74
+
75
+ context 'when handling travis payloads' do
76
+ let(:travis_payload_name) { 'success' }
77
+
78
+ let :travis_payload do
79
+ travis_payload_hash(travis_payload_name).tap do |p|
80
+ p[:repository].merge!(id: fizz)
81
+ end
82
+ end
83
+
84
+ let :annotated_result do
85
+ handler.run!(%w(handle travis))
86
+ JSON.parse(
87
+ fake_stdout.string, symbolize_names: true
88
+ )
89
+ end
90
+
91
+ before do
92
+ handler.stub(
93
+ cfg: handler_config,
94
+ input_stream: StringIO.new(JSON.dump(travis_payload)),
95
+ output_stream: fake_stdout
96
+ )
97
+ end
98
+
99
+ it 'annotates success' do
100
+ annotated_result[:success].should be_true
101
+ end
102
+ end
103
+ end
@@ -0,0 +1,110 @@
1
+ describe Hookworm::BuildIndexHandler do
2
+ include Support::JunkDrawer
3
+
4
+ let(:fake_stderr) { StringIO.new }
5
+ let(:fake_stdout) { StringIO.new }
6
+ let(:handler) { described_class.new }
7
+ let(:tempdir) { setup_tempdir }
8
+
9
+ let(:fizz) { rand(0..39) }
10
+
11
+ let :handler_config do
12
+ {
13
+ fizz: fizz,
14
+ working_dir: tempdir,
15
+ static_dir: "#{tempdir}/public"
16
+ }
17
+ end
18
+
19
+ before do
20
+ $stderr = fake_stderr
21
+ $stdout = fake_stdout
22
+ end
23
+
24
+ after do
25
+ $stderr = STDERR
26
+ $stdout = STDOUT
27
+ end
28
+
29
+ context 'when handling github payloads' do
30
+ it 'exits 78' do
31
+ handler.run!(%w(handle github)).should == 78
32
+ end
33
+ end
34
+
35
+ context 'when handling travis payloads', integration: true do
36
+ let :static_dir do
37
+ "#{tempdir}/public"
38
+ end
39
+
40
+ let :build_index_prefix do
41
+ "#{static_dir}/build-index/meatballhat/fuzzy-octo-archer"
42
+ end
43
+
44
+ let :build_id_path do
45
+ "#{build_index_prefix}/builds/10180613.json"
46
+ end
47
+
48
+ let :build_number_path do
49
+ "#{build_index_prefix}/builds/_by_number/7.json"
50
+ end
51
+
52
+ let :latest_build_path do
53
+ "#{build_index_prefix}/builds/_latest.json"
54
+ end
55
+
56
+ let :commit_path do
57
+ "#{build_index_prefix}/builds/_by_commit/" <<
58
+ 'ad281ff8a9d7be26da84a65147b42ca7f6cf6857.json'
59
+ end
60
+
61
+ let :short_commit_path do
62
+ "#{build_index_prefix}/builds/_by_commit/ad281ff.json"
63
+ end
64
+
65
+ let :datetime_path do
66
+ "#{build_index_prefix}/builds/_by_datetime/20130814_022637.json"
67
+ end
68
+
69
+ let :travis_payload do
70
+ travis_payload_hash('annotated_success')
71
+ end
72
+
73
+ before do
74
+ handler.stub(
75
+ cfg: handler_config,
76
+ input_stream: StringIO.new(JSON.dump(travis_payload))
77
+ )
78
+ end
79
+
80
+ %w(
81
+ build_id
82
+ build_number
83
+ commit
84
+ datetime
85
+ latest_build
86
+ short_commit
87
+ ).each do |path_type|
88
+ it "stores the payload to the #{path_type} path" do
89
+ handler.run!(%w(handle travis))
90
+ path = send(:"#{path_type}_path")
91
+ File.exists?(path).should be_true
92
+ JSON.parse(File.read(path))['id'].should == 10_180_613
93
+ end
94
+ end
95
+
96
+ context 'when there is no repo slug present' do
97
+ before do
98
+ handler.stub(
99
+ input_stream: StringIO.new(JSON.dump(
100
+ travis_payload.merge(repository: nil)
101
+ ))
102
+ )
103
+ end
104
+
105
+ it 'exits 1' do
106
+ handler.run!(%w(handle travis)).should == 1
107
+ end
108
+ end
109
+ end
110
+ end
@@ -0,0 +1,134 @@
1
+ describe Hookworm::LoggingHandler do
2
+ include Support::JunkDrawer
3
+
4
+ let(:fizz) { rand(0..999) }
5
+ let(:tempdir) { setup_tempdir }
6
+ let(:fake_stdout) { StringIO.new }
7
+ let(:fake_stderr) { StringIO.new }
8
+ let(:handler) { described_class.new }
9
+
10
+ let :handler_config do
11
+ {
12
+ fizz: fizz,
13
+ working_dir: tempdir
14
+ }
15
+ end
16
+
17
+ before do
18
+ $stderr = fake_stderr
19
+ end
20
+
21
+ after do
22
+ $stderr = STDERR
23
+ end
24
+
25
+ context 'when handling github payloads' do
26
+ let :github_payload do
27
+ github_payload_hash('pull_request').tap do |p|
28
+ p[:repository].merge!(id: @fizz)
29
+ end
30
+ end
31
+
32
+ before do
33
+ handler.stub(
34
+ cfg: handler_config,
35
+ input_stream: StringIO.new(JSON.dump(github_payload)),
36
+ output_stream: fake_stdout
37
+ )
38
+ end
39
+
40
+ it 'echoes the payload unaltered' do
41
+ handler.run!(%w(handle github))
42
+ JSON.parse(
43
+ fake_stdout.string, symbolize_names: true
44
+ ).should == github_payload
45
+ end
46
+
47
+ context 'when syslog worm flag is given' do
48
+ let :fake_syslog do
49
+ double('syslog', info: true)
50
+ end
51
+
52
+ before do
53
+ handler.stub(
54
+ cfg: handler_config.merge(worm_flags: { syslog: true }),
55
+ input_stream: StringIO.new(JSON.dump(github_payload)),
56
+ output_stream: fake_stdout
57
+ )
58
+ Syslog.stub(:open).and_yield(fake_syslog)
59
+ end
60
+
61
+ it 'logs the payload to syslog' do
62
+ fake_syslog.should_receive(:info)
63
+ handler.run!(%w(handle github))
64
+ end
65
+ end
66
+
67
+ context 'when things explode' do
68
+ before do
69
+ handler.stub(
70
+ cfg: {},
71
+ input_stream: StringIO.new('{')
72
+ )
73
+ end
74
+
75
+ it 'exits 1' do
76
+ handler.run!(%w(handle github)).should == 1
77
+ end
78
+ end
79
+ end
80
+
81
+ context 'when handling travis payloads' do
82
+ let :travis_payload do
83
+ travis_payload_hash('success')
84
+ end
85
+
86
+ before do
87
+ handler.stub(
88
+ cfg: handler_config,
89
+ input_stream: StringIO.new(JSON.dump(travis_payload)),
90
+ output_stream: fake_stdout
91
+ )
92
+ end
93
+
94
+ it 'echoes the payload unaltered' do
95
+ handler.run!(%w(handle travis))
96
+ JSON.parse(
97
+ fake_stdout.string, symbolize_names: true
98
+ ).should == travis_payload
99
+ end
100
+
101
+ context 'when syslog worm flag is given' do
102
+ let :fake_syslog do
103
+ double('syslog', info: true)
104
+ end
105
+
106
+ before do
107
+ handler.stub(
108
+ cfg: handler_config.merge(worm_flags: { syslog: true }),
109
+ input_stream: StringIO.new(JSON.dump(travis_payload)),
110
+ output_stream: fake_stdout
111
+ )
112
+ Syslog.stub(:open).and_yield(fake_syslog)
113
+ end
114
+
115
+ it 'logs the payload to syslog' do
116
+ fake_syslog.should_receive(:info)
117
+ handler.run!(%w(handle travis))
118
+ end
119
+ end
120
+
121
+ context 'when things explode' do
122
+ before do
123
+ handler.stub(
124
+ cfg: {},
125
+ input_stream: StringIO.new('{')
126
+ )
127
+ end
128
+
129
+ it 'exits 1' do
130
+ handler.run!(%w(handle travis)).should == 1
131
+ end
132
+ end
133
+ end
134
+ end
@@ -0,0 +1,65 @@
1
+ describe Hookworm::RogueCommitHandler do
2
+ include Support::JunkDrawer
3
+
4
+ let(:fake_stderr) { StringIO.new }
5
+ let(:fake_stdout) { StringIO.new }
6
+ let(:handler) { described_class.new }
7
+ let(:tempdir) { setup_tempdir }
8
+
9
+ let(:fizz) { rand(0..999) }
10
+
11
+ let :handler_config do
12
+ {
13
+ fizz: fizz,
14
+ working_dir: tempdir
15
+ }
16
+ end
17
+
18
+ before do
19
+ $stderr = fake_stderr
20
+ end
21
+
22
+ after do
23
+ $stderr = STDERR
24
+ end
25
+
26
+ context 'when handling github payloads' do
27
+ let :github_payload do
28
+ github_payload_hash('pull_request').tap do |p|
29
+ p[:repository].merge!(id: fizz)
30
+ end
31
+ end
32
+
33
+ before do
34
+ handler.stub(
35
+ cfg: handler_config,
36
+ input_stream: StringIO.new(JSON.dump(github_payload)),
37
+ output_stream: fake_stdout
38
+ )
39
+ end
40
+
41
+ it 'echoes the payload unaltered' do
42
+ handler.run!(%w(handle github))
43
+ JSON.parse(
44
+ fake_stdout.string, symbolize_names: true
45
+ ).should == github_payload
46
+ end
47
+ end
48
+
49
+ context 'when handling travis payloads' do
50
+ let :travis_payload do
51
+ travis_payload_hash('success')
52
+ end
53
+
54
+ before do
55
+ handler.stub(
56
+ cfg: handler_config,
57
+ input_stream: StringIO.new(JSON.dump(travis_payload))
58
+ )
59
+ end
60
+
61
+ it 'exits 78' do
62
+ handler.run!(%w(handle travis)).should == 78
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,3 @@
1
+ require 'simplecov'
2
+ require 'hookworm-handlers'
3
+ require_relative 'support'
data/spec/support.rb ADDED
@@ -0,0 +1,117 @@
1
+ require 'json'
2
+ require 'tmpdir'
3
+ require 'uri'
4
+ require 'mail'
5
+
6
+ module Support
7
+ module JunkDrawer
8
+ def execute_command_in_tmpdir(command, stdin_string)
9
+ Dir.chdir(tempdir) { execute_command(command, stdin_string) }
10
+ end
11
+
12
+ def setup_tempdir
13
+ dir = Dir.mktmpdir
14
+ at_exit { FileUtils.rm_rf(dir) }
15
+ dir
16
+ end
17
+
18
+ def github_payload(name, format)
19
+ case format
20
+ when :form
21
+ "payload=#{URI.escape(github_payload_string(name))}"
22
+ when :json
23
+ github_payload_string(name)
24
+ end
25
+ end
26
+
27
+ def github_payload_hash(name)
28
+ JSON.parse(github_payload_string(name), symbolize_names: true)
29
+ end
30
+
31
+ def github_payload_string(name)
32
+ File.read(github_payload_file(name))
33
+ end
34
+
35
+ def github_payload_file(name)
36
+ File.expand_path(
37
+ "../../sampledata/github-payloads/#{name.to_s}.json", __FILE__
38
+ )
39
+ end
40
+
41
+ def post_github_payload(port, payload_name, format)
42
+ pre_request_messages = current_mail_messages
43
+ response = post_request(
44
+ port: port,
45
+ body: github_payload(payload_name, format),
46
+ path: '/github',
47
+ content_type: content_type(format)
48
+ )
49
+ [response, current_mail_messages - pre_request_messages]
50
+ end
51
+
52
+ def content_type(format)
53
+ {
54
+ form: 'application/x-www-form-urlencoded',
55
+ json: 'application/json'
56
+ }[format]
57
+ end
58
+
59
+ def travis_payload(name)
60
+ "payload=#{URI.escape(travis_payload_string(name))}"
61
+ end
62
+
63
+ def travis_payload_hash(name)
64
+ JSON.parse(travis_payload_string(name), symbolize_names: true)
65
+ end
66
+
67
+ def travis_payload_string(name)
68
+ File.read(travis_payload_file(name))
69
+ end
70
+
71
+ def travis_payload_file(name)
72
+ File.expand_path(
73
+ "../../sampledata/travis-payloads/#{name.to_s}.json", __FILE__
74
+ )
75
+ end
76
+
77
+ def post_travis_payload(port, payload_name, format)
78
+ pre_request_messages = current_mail_messages
79
+ response = post_request(
80
+ port: port,
81
+ body: travis_payload(payload_name),
82
+ path: '/travis',
83
+ content_type: content_type(format)
84
+ )
85
+ [response, current_mail_messages - pre_request_messages]
86
+ end
87
+
88
+ def current_mail_messages
89
+ JSON.parse(
90
+ get_request(
91
+ path: '/messages', port: Mtbb.server(:fakesmtpd).port + 1
92
+ ).body
93
+ ).fetch('_embedded').fetch('messages')
94
+ .map { |h| h['_links']['self']['href'] }
95
+ end
96
+
97
+ def clear_mail_messages
98
+ delete_request(
99
+ path: '/messages',
100
+ port: Mtbb.server(:fakesmtpd).port + 1
101
+ )
102
+ end
103
+
104
+ def last_message
105
+ message = JSON.parse(get_request(
106
+ path: current_mail_messages.last,
107
+ port: Mtbb.server(:fakesmtpd).port + 1
108
+ ).body)
109
+ return Mail.new if message['body'].nil?
110
+ Mail.new(message['body'].join("\n"))
111
+ end
112
+
113
+ def last_message_header(header_name)
114
+ last_message[header_name].to_s
115
+ end
116
+ end
117
+ end