right_hook 0.4.1 → 0.4.2

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -9,6 +9,8 @@ Right Hook is a collection of tools to aid in setting up a web app to handle Git
9
9
 
10
10
  To see some example usage, head over to [right-hook/hookbooks](https://github.com/right-hook/hookbooks).
11
11
 
12
+ To see the documentation for the current version of the gem, visit [rubydoc.info](http://rubydoc.info/gems/right_hook).
13
+
12
14
  ## Installation
13
15
 
14
16
  Add this line to your application's Gemfile:
@@ -4,6 +4,8 @@ require 'json'
4
4
  require 'right_hook/event'
5
5
 
6
6
  module RightHook
7
+ # Inherit from this class and implement the on_issue, on_pull_request, etc. methods to
8
+ # configure how you respond to GitHub hooks.
7
9
  class App < Sinatra::Base
8
10
  post '/hook/:owner/:repo_name/:event_type' do
9
11
  owner = params[:owner]
@@ -27,6 +29,11 @@ module RightHook
27
29
  end
28
30
  end
29
31
 
32
+ # It is up to you to override secret to determine how to look up the correct secret for an owner/repo combo.
33
+ def secret(owner, repo_name, event_type)
34
+ raise NotImplementedError, "You didn't specify how to find the secret for a repo!"
35
+ end
36
+
30
37
  private
31
38
  def require_valid_signature(content, owner, repo_name, event_type)
32
39
  s = secret(owner, repo_name, event_type)
@@ -0,0 +1,28 @@
1
+ require 'openssl'
2
+ require 'uri'
3
+
4
+ module RightHook
5
+ # Helpers for specs!
6
+ # Typical usage is to include this module into your spec context, just like you would with Rack::Test::Methods.
7
+ module SpecHelpers
8
+ # Post to the given path, including the correct signature header based on the payload and secret.
9
+ # @param [Hash] opts The options to use when crafting the request.
10
+ # @option opts [String] :path The full path of the endpoint to which to post
11
+ # @option opts [String] :payload A JSON-parseable string containing a payload as described in http://developer.github.com/v3/activity/events/types/
12
+ # @option opts [String] :secret The secret to use when calculating the HMAC for the X-Hub-Signature header
13
+ def post_with_signature(opts)
14
+ path = opts.fetch(:path)
15
+ payload = opts.fetch(:payload)
16
+ secret = opts.fetch(:secret)
17
+
18
+ post path, {payload: payload}, generate_secret_header(secret, URI.encode_www_form(payload: payload))
19
+ end
20
+
21
+ # :nodoc:
22
+ def generate_secret_header(secret, body)
23
+ sha = OpenSSL::HMAC.hexdigest(OpenSSL::Digest::Digest.new('sha1'), secret, body)
24
+ # GitHub sends it as 'X-Hub-Signature', but Rack provides it as HTTP_X_HUB_SIGNATURE... :/
25
+ {'HTTP_X_HUB_SIGNATURE' => "sha1=#{sha}"}
26
+ end
27
+ end
28
+ end
@@ -1,3 +1,3 @@
1
1
  module RightHook
2
- VERSION = "0.4.1"
2
+ VERSION = "0.4.2"
3
3
  end
@@ -1,10 +1,7 @@
1
1
  require 'spec_helper'
2
- require 'rack/test'
3
2
 
4
3
  describe RightHook::App do
5
4
  describe 'Issues' do
6
- include Rack::Test::Methods
7
-
8
5
  class IssueApp < RightHook::App
9
6
  class << self
10
7
  attr_accessor :owner, :repo_name, :action, :issue_json
@@ -31,9 +28,7 @@ describe RightHook::App do
31
28
  end
32
29
 
33
30
  it 'captures the interesting data' do
34
- post '/ignore', {payload: ISSUE_JSON}
35
- body = last_request.body.read
36
- post '/hook/mark-rushakoff/right_hook/issue', {payload: ISSUE_JSON}, generate_secret_header('issue', body)
31
+ post_with_signature(path: '/hook/mark-rushakoff/right_hook/issue', payload: ISSUE_JSON, secret: 'issue')
37
32
  expect(last_response.status).to eq(200)
38
33
  expect(app.owner).to eq('mark-rushakoff')
39
34
  expect(app.repo_name).to eq('right_hook')
@@ -44,7 +39,7 @@ describe RightHook::App do
44
39
  end
45
40
 
46
41
  it 'fails when the secret is wrong' do
47
- post '/hook/mark-rushakoff/right_hook/issue', {payload: ISSUE_JSON}, generate_secret_header('wrong', 'stuff')
42
+ post_with_signature(path: '/hook/mark-rushakoff/right_hook/issue', payload: ISSUE_JSON, secret: 'wrong')
48
43
  expect(last_response.status).to eq(202)
49
44
  expect(app.owner).to be_nil
50
45
  end
@@ -1,5 +1,4 @@
1
1
  require 'spec_helper'
2
- require 'rack/test'
3
2
 
4
3
  describe RightHook::App do
5
4
  describe 'Pull requests' do
@@ -32,9 +31,7 @@ describe RightHook::App do
32
31
  end
33
32
 
34
33
  it 'captures the interesting data' do
35
- post '/ignore', {payload: PULL_REQUEST_JSON}
36
- body = last_request.body.read
37
- post '/hook/mark-rushakoff/right_hook/pull_request', {payload: PULL_REQUEST_JSON}, generate_secret_header('pull_request', body)
34
+ post_with_signature(path: '/hook/mark-rushakoff/right_hook/pull_request', payload: PULL_REQUEST_JSON, secret: 'pull_request')
38
35
  expect(last_response.status).to eq(200)
39
36
  expect(app.owner).to eq('mark-rushakoff')
40
37
  expect(app.repo_name).to eq('right_hook')
@@ -46,7 +43,7 @@ describe RightHook::App do
46
43
  end
47
44
 
48
45
  it 'fails when the secret is wrong' do
49
- post '/hook/mark-rushakoff/right_hook/pull_request', {payload: PULL_REQUEST_JSON}, generate_secret_header('wrong', 'stuff')
46
+ post_with_signature(path: '/hook/mark-rushakoff/right_hook/pull_request', payload: PULL_REQUEST_JSON, secret: 'wrong')
50
47
  expect(last_response.status).to eq(202)
51
48
  expect(app.owner).to be_nil
52
49
  end
data/spec/app_spec.rb CHANGED
@@ -1,9 +1,6 @@
1
1
  require 'spec_helper'
2
- require 'rack/test'
3
2
 
4
3
  describe RightHook::App do
5
- include Rack::Test::Methods
6
-
7
4
  class BareApp < RightHook::App
8
5
  def secret(owner, repo_name, event_type)
9
6
  ''
@@ -15,12 +12,16 @@ describe RightHook::App do
15
12
  end
16
13
 
17
14
  it 'is status 501 for a non-implemented hook' do
18
- post '/hook/mark-rushakoff/right_hook/issue', '{}', generate_secret_header('secret', '{}')
15
+ post_with_signature(path: '/hook/mark-rushakoff/right_hook/issue', payload: '{}', secret: '')
19
16
  expect(last_response.status).to eq(501)
20
17
  end
21
18
 
22
19
  it 'is 404 for an unknown hook' do
23
- post '/hook/mark-rushakoff/right_hook/foobar', '{}', generate_secret_header('secret', '{}')
20
+ post_with_signature(path: '/hook/mark-rushakoff/right_hook/not_a_real_thing', payload: '{}', secret: '')
24
21
  expect(last_response.status).to eq(404)
25
22
  end
23
+
24
+ it 'raises NotImplementedError for an unimplemented secret' do
25
+ expect { RightHook::App.new!.secret('owner', 'repo', 'issue') }.to raise_error(NotImplementedError)
26
+ end
26
27
  end
data/spec/spec_helper.rb CHANGED
@@ -1,19 +1,19 @@
1
- $LOAD_PATH.unshift File.expand_path('../../lib', __FILE__)
2
1
  require 'right_hook'
3
2
  require 'right_hook/app'
4
3
  require 'right_hook/authenticated_client'
5
4
  require 'right_hook/authenticator'
6
5
  require 'right_hook/commenter'
7
6
  require 'right_hook/event'
7
+ require 'right_hook/spec_helpers'
8
8
  require 'right_hook/subscriber'
9
9
 
10
- require_relative './support/spec_helpers.rb'
11
-
12
10
  require 'webmock/rspec'
11
+ require 'rack/test'
13
12
 
14
13
  require 'coveralls'
15
14
  Coveralls.wear!
16
15
 
17
16
  RSpec.configure do |c|
17
+ c.include Rack::Test::Methods
18
18
  c.include RightHook::SpecHelpers
19
19
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: right_hook
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.1
4
+ version: 0.4.2
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-10-01 00:00:00.000000000 Z
12
+ date: 2013-10-02 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: bundler
@@ -176,6 +176,7 @@ files:
176
176
  - lib/right_hook/commenter.rb
177
177
  - lib/right_hook/event.rb
178
178
  - lib/right_hook/logger.rb
179
+ - lib/right_hook/spec_helpers.rb
179
180
  - lib/right_hook/subscriber.rb
180
181
  - lib/right_hook/version.rb
181
182
  - right_hook.gemspec
@@ -189,7 +190,6 @@ files:
189
190
  - spec/event_spec.rb
190
191
  - spec/spec_helper.rb
191
192
  - spec/subscriber_spec.rb
192
- - spec/support/spec_helpers.rb
193
193
  homepage: https://github.com/mark-rushakoff/right_hook
194
194
  licenses:
195
195
  - MIT
@@ -227,5 +227,4 @@ test_files:
227
227
  - spec/event_spec.rb
228
228
  - spec/spec_helper.rb
229
229
  - spec/subscriber_spec.rb
230
- - spec/support/spec_helpers.rb
231
230
  has_rdoc:
@@ -1,11 +0,0 @@
1
- require 'openssl'
2
-
3
- module RightHook
4
- module SpecHelpers
5
- def generate_secret_header(secret, body)
6
- sha = OpenSSL::HMAC.hexdigest(OpenSSL::Digest::Digest.new('sha1'), secret, body)
7
- # GitHub sends it as 'X-Hub-Signature', but Rack provides it as HTTP_X_HUB_SIGNATURE... :/
8
- {'HTTP_X_HUB_SIGNATURE' => "sha1=#{sha}"}
9
- end
10
- end
11
- end