hookworm-handlers 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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