party_foul 0.1.0 → 0.2.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.
- data/README.md +64 -13
- data/lib/generators/party_foul/install_generator.rb +19 -48
- data/lib/generators/party_foul/templates/party_foul.rb +18 -0
- data/lib/party_foul/exception_handler.rb +28 -16
- data/lib/party_foul/sync_adapter.rb +5 -0
- data/lib/party_foul/version.rb +1 -1
- data/lib/party_foul.rb +30 -1
- data/test/generator_test.rb +26 -0
- data/test/party_foul/exception_handler_test.rb +44 -13
- data/test/party_foul/middleware_test.rb +10 -1
- data/test/test_helper.rb +3 -2
- data/test/tmp/config/initializers/party_foul.rb +18 -0
- metadata +36 -14
data/README.md
CHANGED
@@ -14,22 +14,20 @@ following:
|
|
14
14
|
1. Will attempt to find a matching issue in your Github repo
|
15
15
|
2. If no matching issue is found an new issue will be created with a
|
16
16
|
unique title, session information, and stack trace. The issue will be
|
17
|
-
tagged as a `bug
|
17
|
+
tagged as a `bug`. A new comment will be added with relevant data on the
|
18
|
+
application state.
|
18
19
|
3. If an open issue is found the occurance count and time stamp will be
|
19
|
-
updated
|
20
|
+
updated. A new comment will be added with relevant data on the
|
21
|
+
application state.
|
20
22
|
4. If a closed issue is found the occurance count and time stamp will be
|
21
23
|
updated. The issue will be reopened and a `regression` tag will be
|
22
|
-
added.
|
24
|
+
added. A new comment will be added with relevant data on the
|
25
|
+
application state.
|
23
26
|
5. If the issue is marked as `wontfix` the issue is not updated nor is
|
24
|
-
a new issue created.
|
27
|
+
a new issue created. No comments will be added.
|
25
28
|
|
26
29
|
## Installation ##
|
27
30
|
|
28
|
-
Prior to installing the gem you will need to set up an OAuth application
|
29
|
-
on Github to provide access to your repository. Once this OAuth
|
30
|
-
application is setup you will have a `ClientID` and `ClientSecret` that
|
31
|
-
you will need to complete the installation.
|
32
|
-
|
33
31
|
**Note** We highly recommend that you create a new Github account that is
|
34
32
|
a collaborator on your repository. Use this new account's credentials
|
35
33
|
for the installation below. If you use your own account you will
|
@@ -58,7 +56,7 @@ token in version control.
|
|
58
56
|
Add as the very last middleware in your production `Rack` stack in `config/environments/production.rb`
|
59
57
|
|
60
58
|
```ruby
|
61
|
-
config.middleware.
|
59
|
+
config.middleware.use('PartyFoul::Middleware')
|
62
60
|
```
|
63
61
|
### Other ###
|
64
62
|
|
@@ -69,7 +67,7 @@ so:
|
|
69
67
|
PartyFoul.configure do |config|
|
70
68
|
# the collection of exceptions to be ignored by PartyFoul
|
71
69
|
# The constants here *must* be represented as strings
|
72
|
-
config.ignored_exceptions = ['ActiveRecord::RecordNotFound']
|
70
|
+
config.ignored_exceptions = ['ActiveRecord::RecordNotFound', 'ActionController::RoutingError']
|
73
71
|
|
74
72
|
# The OAuth token for the account that will be opening the issues on Github
|
75
73
|
config.oauth_token = 'abcdefgh1234567890'
|
@@ -86,10 +84,63 @@ PartyFoul.configure do |config|
|
|
86
84
|
end
|
87
85
|
```
|
88
86
|
|
87
|
+
You can generate an OAuth token from via the
|
88
|
+
[OAuth Authorizations API](http://developer.github.com/v3/oauth/#oauth-authorizations-api)
|
89
|
+
with cURL:
|
90
|
+
|
91
|
+
```bash
|
92
|
+
curl -X POST -i -d "{ \"scopes\": [\"repo\"] }" \
|
93
|
+
https://<github_login>:<github_password>@api.github.com/authorizations
|
94
|
+
```
|
95
|
+
|
89
96
|
Add as the very last middleware in your production `Rack` stack.
|
90
97
|
|
91
|
-
##
|
98
|
+
## Customization ##
|
99
|
+
|
100
|
+
### Async Adapters ###
|
101
|
+
|
102
|
+
You can specify the adapter with which the exceptions should be
|
103
|
+
handled. By default, PartyFoul includes the
|
104
|
+
[`PartyFoul::SyncAdapter`](https://github.com/dockyard/party_foul/tree/master/lib/party_foul/sync_adapter.rb)
|
105
|
+
which will handle the exception synchronously. To use your own adapter,
|
106
|
+
include the following in your `PartyFoul.configure` block:
|
107
|
+
|
108
|
+
```ruby
|
109
|
+
PartyFoul.configure do |config|
|
110
|
+
config.adapter = MyAsyncAdatper
|
111
|
+
end
|
112
|
+
|
113
|
+
class MyAsyncAdapter
|
114
|
+
def self.handle(exception, env)
|
115
|
+
# Enqueue the exception, then in your worker, call
|
116
|
+
# PartyFoul::ExceptionHandler.new(exception, env).run
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
```
|
121
|
+
|
122
|
+
## Changing How Issues Are Reported ##
|
123
|
+
|
124
|
+
`PartyFoul` comes with default templates for what the body of issues and
|
125
|
+
comments are. If you want to override these templates you simply need to
|
126
|
+
add them as an option in your initializer:
|
127
|
+
|
128
|
+
```ruby
|
129
|
+
PartyFoul.configure do |config|
|
130
|
+
config.issue_body = <<-TEMPLATE
|
131
|
+
:issue_title
|
132
|
+
TEMPLATE
|
133
|
+
|
134
|
+
config.comment_body = <<-TEMPLATE
|
135
|
+
:occurred_at
|
136
|
+
TEMPLATE
|
137
|
+
```
|
92
138
|
|
139
|
+
In this over-simplistic example the words that start with `:` in the
|
140
|
+
templates will be evaluated with the value of the corresponding named
|
141
|
+
instance method on the instance of `PartyFoul::ExceptionHandler`. If you
|
142
|
+
want to add additional values for replacement you should open that class
|
143
|
+
to add the methods.
|
93
144
|
|
94
145
|
## Authors ##
|
95
146
|
|
@@ -111,7 +162,7 @@ on how to properly submit issues and pull requests.
|
|
111
162
|
|
112
163
|
## Legal ##
|
113
164
|
|
114
|
-
[DockYard](http://dockyard.com), LLC ©
|
165
|
+
[DockYard](http://dockyard.com), LLC © 2013
|
115
166
|
|
116
167
|
[@dockyard](http://twitter.com/dockyard)
|
117
168
|
|
@@ -4,71 +4,42 @@ require 'net/http'
|
|
4
4
|
|
5
5
|
module PartyFoul
|
6
6
|
class InstallGenerator < Rails::Generators::Base
|
7
|
+
source_root File.expand_path('../templates', __FILE__)
|
7
8
|
|
8
9
|
def create_initializer_file
|
9
|
-
|
10
|
-
|
11
|
-
client_id = ask 'Github App Client ID:'
|
12
|
-
client_secret = ask 'Github App Client Secret:'
|
13
|
-
username = ask 'Github username:'
|
14
|
-
password = STDIN.noecho do
|
10
|
+
username = ask 'Github username:'
|
11
|
+
password = STDIN.noecho do
|
15
12
|
ask 'Github password:'
|
16
13
|
end
|
17
|
-
say ''
|
18
|
-
|
19
|
-
owner = ask 'Repository owner:'
|
20
|
-
repo = ask 'Repository name:'
|
21
|
-
auth_uri = URI("https://api.github.com/authorizations")
|
22
|
-
|
23
|
-
response = nil
|
24
|
-
Net::HTTP.start(auth_uri.host, auth_uri.port, :use_ssl => auth_uri.scheme == 'https') do |http|
|
25
|
-
request = Net::HTTP::Post.new auth_uri.request_uri
|
26
|
-
body = { :scopes => ['repo'], :client_id => client_id, :client_secret => client_secret }
|
27
|
-
request.body = body.to_json
|
28
|
-
|
29
|
-
request.basic_auth username, password
|
30
|
-
|
31
|
-
response = http.request request
|
32
|
-
end
|
33
14
|
|
34
|
-
|
35
|
-
oauth_token = JSON.parse(response.body)['token']
|
36
|
-
|
37
|
-
File.open('config/initializers/party_foul.rb', 'w') do |f|
|
38
|
-
f.puts <<-CONTENTS
|
39
|
-
PartyFoul.configure do |config|
|
40
|
-
# the collection of exceptions to be ignored by PartyFoul
|
41
|
-
# The constants here *must* be represented as strings
|
42
|
-
config.ignored_exceptions = ['ActiveRecord::RecordNotFound']
|
43
|
-
|
44
|
-
# The OAuth token for the account that will be opening the issues on Github
|
45
|
-
config.oauth_token = '#{oauth_token}'
|
15
|
+
say ''
|
46
16
|
|
47
|
-
|
48
|
-
|
49
|
-
|
17
|
+
@owner = ask_with_default 'Repository owner:', username
|
18
|
+
@repo = ask 'Repository name:'
|
19
|
+
@endpoint = ask_with_default 'Endpoint:', 'https://api.github.com'
|
50
20
|
|
51
|
-
|
52
|
-
config.owner = '#{owner}'
|
21
|
+
github = Github.new :login => username, :password => password, :endpoint => @endpoint
|
53
22
|
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
else
|
23
|
+
begin
|
24
|
+
github.oauth.create 'scopes' => ['repo']
|
25
|
+
@oauth_token = github.oauth_token
|
26
|
+
template 'party_foul.rb', 'config/initializers/party_foul.rb'
|
27
|
+
rescue Github::Error::Unauthorized
|
60
28
|
say 'There was an error retrieving your Github OAuth token'
|
61
29
|
end
|
62
|
-
|
63
|
-
say 'Done'
|
64
30
|
end
|
65
31
|
|
66
32
|
private
|
67
33
|
|
68
34
|
def self.installation_message
|
69
|
-
'Generates the
|
35
|
+
'Generates the initializer'
|
70
36
|
end
|
71
37
|
|
72
38
|
desc installation_message
|
39
|
+
|
40
|
+
def ask_with_default(prompt, default)
|
41
|
+
value = ask("#{prompt} [#{default}]")
|
42
|
+
value.blank? ? default : value
|
43
|
+
end
|
73
44
|
end
|
74
45
|
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
PartyFoul.configure do |config|
|
2
|
+
# the collection of exceptions to be ignored by PartyFoul
|
3
|
+
# The constants here *must* be represented as strings
|
4
|
+
config.ignored_exceptions = ['ActiveRecord::RecordNotFound', 'ActionController::RoutingError']
|
5
|
+
|
6
|
+
# The OAuth token for the account that will be opening the issues on Github
|
7
|
+
config.oauth_token = '<%= @oauth_token %>'
|
8
|
+
|
9
|
+
# The API endpoint for Github. Unless you are hosting a private
|
10
|
+
# instance of Enterprise Github you do not need to include this
|
11
|
+
config.endpoint = '<%= @endpoint %>'
|
12
|
+
|
13
|
+
# The organization or user that owns the target repository
|
14
|
+
config.owner = '<%= @owner %>'
|
15
|
+
|
16
|
+
# The repository for this application
|
17
|
+
config.repo = '<%= @repo %>'
|
18
|
+
end
|
@@ -2,8 +2,7 @@ class PartyFoul::ExceptionHandler
|
|
2
2
|
attr_accessor :exception, :env
|
3
3
|
|
4
4
|
def self.handle(exception, env)
|
5
|
-
|
6
|
-
handler.run
|
5
|
+
PartyFoul.adapter.handle(exception, env)
|
7
6
|
end
|
8
7
|
|
9
8
|
def initialize(exception, env)
|
@@ -38,7 +37,8 @@ class PartyFoul::ExceptionHandler
|
|
38
37
|
end
|
39
38
|
|
40
39
|
def create_issue
|
41
|
-
PartyFoul.github.issues.create(PartyFoul.owner, PartyFoul.repo, title: issue_title, body: issue_body, labels: ['bug'])
|
40
|
+
issue = PartyFoul.github.issues.create(PartyFoul.owner, PartyFoul.repo, title: issue_title, body: issue_body, labels: ['bug'])
|
41
|
+
PartyFoul.github.issues.comments.create(PartyFoul.owner, PartyFoul.repo, issue['number'], body: comment_body)
|
42
42
|
end
|
43
43
|
|
44
44
|
def update_issue(issue)
|
@@ -50,6 +50,7 @@ class PartyFoul::ExceptionHandler
|
|
50
50
|
end
|
51
51
|
|
52
52
|
PartyFoul.github.issues.edit(PartyFoul.owner, PartyFoul.repo, issue['number'], params)
|
53
|
+
PartyFoul.github.issues.comments.create(PartyFoul.owner, PartyFoul.repo, issue['number'], body: comment_body)
|
53
54
|
end
|
54
55
|
end
|
55
56
|
|
@@ -67,7 +68,7 @@ class PartyFoul::ExceptionHandler
|
|
67
68
|
begin
|
68
69
|
current_count = body.match(/<th>Count<\/th><td>(\d+)<\/td>/)[1].to_i
|
69
70
|
body.sub!("<th>Count</th><td>#{current_count}</td>", "<th>Count</th><td>#{current_count + 1}</td>")
|
70
|
-
body.sub!(/<th>Last Occurance<\/th><td>.+<\/td>/, "<th>Last Occurance</th><td>#{
|
71
|
+
body.sub!(/<th>Last Occurance<\/th><td>.+<\/td>/, "<th>Last Occurance</th><td>#{occurred_at}</td>")
|
71
72
|
body
|
72
73
|
rescue
|
73
74
|
issue_body
|
@@ -84,18 +85,29 @@ class PartyFoul::ExceptionHandler
|
|
84
85
|
end
|
85
86
|
|
86
87
|
def issue_body
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
88
|
+
compile_template(PartyFoul.issue_template)
|
89
|
+
end
|
90
|
+
|
91
|
+
def comment_body
|
92
|
+
compile_template(PartyFoul.comment_template)
|
93
|
+
end
|
94
|
+
|
95
|
+
def compile_template(template)
|
96
|
+
template.gsub(/:\w+/) do |method|
|
97
|
+
self.send(method.split(':').last)
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
def occurred_at
|
102
|
+
Time.now.strftime('%B %d, %Y %H:%M:%S %z')
|
103
|
+
end
|
104
|
+
|
105
|
+
def ip_address
|
106
|
+
env['REMOTE_ADDR']
|
107
|
+
end
|
108
|
+
|
109
|
+
def http_headers
|
110
|
+
"<table>#{env.keys.select { |k| k =~ /^HTTP_/ }.sort.map { |k| "<tr><th>#{k.split('HTTP_').last.split('_').map(&:capitalize).join(' ')}</th><td>#{env[k]}</td></tr>" }.join }</table>"
|
99
111
|
end
|
100
112
|
|
101
113
|
private
|
data/lib/party_foul/version.rb
CHANGED
data/lib/party_foul.rb
CHANGED
@@ -2,7 +2,34 @@ require 'github_api'
|
|
2
2
|
|
3
3
|
module PartyFoul
|
4
4
|
class << self
|
5
|
-
attr_accessor :github, :oauth_token, :endpoint, :owner, :repo, :ignored_exceptions
|
5
|
+
attr_accessor :github, :oauth_token, :endpoint, :owner, :repo, :ignored_exceptions, :adapter, :issue_template, :comment_template
|
6
|
+
end
|
7
|
+
|
8
|
+
def self.issue_template
|
9
|
+
@issue_template ||=
|
10
|
+
<<-TEMPLATE
|
11
|
+
<table>
|
12
|
+
<tr><th>Exception</th><td>:exception</td></tr>
|
13
|
+
<tr><th>Count</th><td>1</td></tr>
|
14
|
+
<tr><th>Last Occurance</th><td>:occurred_at</td></tr>
|
15
|
+
</table>
|
16
|
+
|
17
|
+
## Stack Trace
|
18
|
+
<pre>:stack_trace</pre>
|
19
|
+
Fingerprint: `:fingerprint`
|
20
|
+
TEMPLATE
|
21
|
+
end
|
22
|
+
|
23
|
+
def self.comment_template
|
24
|
+
@comment_template ||=
|
25
|
+
<<-TEMPLATE
|
26
|
+
<table>
|
27
|
+
<tr><th>Occurred at</th><td>:occurred_at</td></tr>
|
28
|
+
<tr><th>Params</th><td>:params</td></tr>
|
29
|
+
<tr><th>IP Address</th><td>:ip_address</td></tr>
|
30
|
+
<tr><th>HTTP Headers</th><td>:http_headers</td></tr>
|
31
|
+
</table>
|
32
|
+
TEMPLATE
|
6
33
|
end
|
7
34
|
|
8
35
|
def self.ignored_exceptions
|
@@ -11,6 +38,7 @@ module PartyFoul
|
|
11
38
|
|
12
39
|
def self.configure(&block)
|
13
40
|
yield self
|
41
|
+
self.adapter ||= SyncAdapter
|
14
42
|
_self = self
|
15
43
|
self.github ||= Github.new do |config|
|
16
44
|
%w{endpoint oauth_token}.each do |option|
|
@@ -22,3 +50,4 @@ end
|
|
22
50
|
|
23
51
|
require 'party_foul/exception_handler'
|
24
52
|
require 'party_foul/middleware'
|
53
|
+
require 'party_foul/sync_adapter'
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
require 'rails/generators/test_case'
|
3
|
+
require 'generators/party_foul/install_generator'
|
4
|
+
|
5
|
+
class PartyFoul::GeneratorTest < Rails::Generators::TestCase
|
6
|
+
destination File.expand_path('../tmp', __FILE__)
|
7
|
+
tests PartyFoul::InstallGenerator
|
8
|
+
test 'it copies the initializer' do
|
9
|
+
oauth = mock('Oauth')
|
10
|
+
oauth.stubs(:create)
|
11
|
+
oauth.expects(:create).with('scopes' => ['repo'])
|
12
|
+
github = mock('Github')
|
13
|
+
github.stubs(:oauth).returns(oauth)
|
14
|
+
github.stubs(:oauth_token).returns('test_token')
|
15
|
+
Github.stubs(:new).with(:login => 'test_login', :password => 'test_password', :endpoint => 'test_endpoint').returns(github)
|
16
|
+
$stdin.stubs(:gets).returns('test_login').then.returns('test_password').then.returns('').then.returns('test_repo').then.returns("test_endpoint").then.returns('')
|
17
|
+
run_generator
|
18
|
+
|
19
|
+
assert_file 'config/initializers/party_foul.rb' do |initializer|
|
20
|
+
assert_match(/config.endpoint\s+=\s'test_endpoint'/, initializer)
|
21
|
+
assert_match(/config.owner\s+=\s'test_login'/, initializer)
|
22
|
+
assert_match(/config.repo\s+=\s'test_repo'/, initializer)
|
23
|
+
assert_match(/config.oauth_token\s+=\s'test_token'/, initializer)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -11,19 +11,17 @@ describe 'Party Foul Exception Handler' do
|
|
11
11
|
describe 'updating issue body' do
|
12
12
|
before do
|
13
13
|
@handler = PartyFoul::ExceptionHandler.new(nil, nil)
|
14
|
+
@handler.stubs(:exception).returns('Test Exception')
|
14
15
|
@handler.stubs(:fingerprint).returns('abcdefg1234567890')
|
15
16
|
@handler.stubs(:stack_trace)
|
16
|
-
@handler.stubs(:params)
|
17
|
-
@handler.stubs(:exception)
|
18
17
|
end
|
19
18
|
|
20
19
|
it 'updates count and timestamp' do
|
21
20
|
body = <<-BODY
|
22
21
|
<table>
|
22
|
+
<tr><th>Exception</th><td>Test Exception</td></tr>
|
23
23
|
<tr><th>Count</th><td>1</td></tr>
|
24
|
-
<tr><th>Last Occurance</th><td
|
25
|
-
<tr><th>Params</th><td></td></tr>
|
26
|
-
<tr><th>Exception</th><td></td></tr>
|
24
|
+
<tr><th>Last Occurance</th><td>December 31, 1969 19:00:00 -0500</td></tr>
|
27
25
|
</table>
|
28
26
|
|
29
27
|
## Stack Trace
|
@@ -35,10 +33,9 @@ Fingerprint: `abcdefg1234567890`
|
|
35
33
|
|
36
34
|
expected_body = <<-BODY
|
37
35
|
<table>
|
36
|
+
<tr><th>Exception</th><td>Test Exception</td></tr>
|
38
37
|
<tr><th>Count</th><td>2</td></tr>
|
39
|
-
<tr><th>Last Occurance</th><td
|
40
|
-
<tr><th>Params</th><td></td></tr>
|
41
|
-
<tr><th>Exception</th><td></td></tr>
|
38
|
+
<tr><th>Last Occurance</th><td>October 25, 1985 01:22:00 -0500</td></tr>
|
42
39
|
</table>
|
43
40
|
|
44
41
|
## Stack Trace
|
@@ -53,19 +50,17 @@ Fingerprint: `abcdefg1234567890`
|
|
53
50
|
describe 'empty body' do
|
54
51
|
before do
|
55
52
|
@handler = PartyFoul::ExceptionHandler.new(nil, nil)
|
53
|
+
@handler.stubs(:exception).returns('Test Exception')
|
56
54
|
@handler.stubs(:fingerprint).returns('abcdefg1234567890')
|
57
55
|
@handler.stubs(:stack_trace)
|
58
|
-
@handler.stubs(:params)
|
59
|
-
@handler.stubs(:exception)
|
60
56
|
end
|
61
57
|
|
62
58
|
it 'resets body' do
|
63
59
|
expected_body = <<-BODY
|
64
60
|
<table>
|
61
|
+
<tr><th>Exception</th><td>Test Exception</td></tr>
|
65
62
|
<tr><th>Count</th><td>1</td></tr>
|
66
|
-
<tr><th>Last Occurance</th><td
|
67
|
-
<tr><th>Params</th><td></td></tr>
|
68
|
-
<tr><th>Exception</th><td></td></tr>
|
63
|
+
<tr><th>Last Occurance</th><td>December 31, 1969 19:00:00 -0500</td></tr>
|
69
64
|
</table>
|
70
65
|
|
71
66
|
## Stack Trace
|
@@ -99,4 +94,40 @@ Fingerprint: `abcdefg1234567890`
|
|
99
94
|
end
|
100
95
|
end
|
101
96
|
end
|
97
|
+
|
98
|
+
describe '#issue_comment' do
|
99
|
+
before do
|
100
|
+
env = {
|
101
|
+
'REQUEST_URI' => 'http://example.com/',
|
102
|
+
'HTTP_USER_AGENT' => 'test_user_agent',
|
103
|
+
'REMOTE_ADDR' => '127.0.0.1',
|
104
|
+
'HTTP_HOST' => 'localhost:3000',
|
105
|
+
'QUERY_STRING' => { :controller => 'landing', :action => 'index' }
|
106
|
+
}
|
107
|
+
@handler = PartyFoul::ExceptionHandler.new(nil, env)
|
108
|
+
end
|
109
|
+
|
110
|
+
it 'renders a new comment' do
|
111
|
+
expected_comment = <<-COMMENT
|
112
|
+
<table>
|
113
|
+
<tr><th>Occurred at</th><td>December 31, 1969 19:00:00 -0500</td></tr>
|
114
|
+
<tr><th>Params</th><td>{:controller=>"landing", :action=>"index"}</td></tr>
|
115
|
+
<tr><th>IP Address</th><td>127.0.0.1</td></tr>
|
116
|
+
<tr><th>HTTP Headers</th><td><table><tr><th>Host</th><td>localhost:3000</td></tr><tr><th>User Agent</th><td>test_user_agent</td></tr></table></td></tr>
|
117
|
+
</table>
|
118
|
+
COMMENT
|
119
|
+
|
120
|
+
@handler.comment_body.must_equal expected_comment
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
describe '#compile_template' do
|
125
|
+
it 'it parses the tags and inserts proper data' do
|
126
|
+
template = '<span>:data1</span><div>:data2</div>'
|
127
|
+
@handler = PartyFoul::ExceptionHandler.new(nil, nil)
|
128
|
+
@handler.stubs(:data1).returns('123')
|
129
|
+
@handler.stubs(:data2).returns('abc')
|
130
|
+
@handler.compile_template(template).must_equal '<span>123</span><div>abc</div>'
|
131
|
+
end
|
132
|
+
end
|
102
133
|
end
|
@@ -31,6 +31,8 @@ describe 'Party Foul Middleware' do
|
|
31
31
|
PartyFoul.github.stubs(:search).returns(mock('Search'))
|
32
32
|
PartyFoul.github.issues.stubs(:create)
|
33
33
|
PartyFoul.github.issues.stubs(:edit)
|
34
|
+
PartyFoul.github.issues.stubs(:comments).returns(mock('Comments'))
|
35
|
+
PartyFoul.github.issues.comments.stubs(:create)
|
34
36
|
PartyFoul::ExceptionHandler.any_instance.stubs(:issue_title).returns('Test Title')
|
35
37
|
PartyFoul::ExceptionHandler.any_instance.stubs(:fingerprint).returns('test_fingerprint')
|
36
38
|
end
|
@@ -38,9 +40,11 @@ describe 'Party Foul Middleware' do
|
|
38
40
|
context 'when error is new' do
|
39
41
|
it 'will open a new error on Github' do
|
40
42
|
PartyFoul::ExceptionHandler.any_instance.stubs(:issue_body).returns('Test Body')
|
43
|
+
PartyFoul::ExceptionHandler.any_instance.stubs(:comment_body).returns('Test Comment')
|
41
44
|
PartyFoul.github.search.stubs(:issues).with(owner: 'test_owner', repo: 'test_repo', keyword: 'test_fingerprint', state: 'open').returns(Hashie::Mash.new(issues: []))
|
42
45
|
PartyFoul.github.search.stubs(:issues).with(owner: 'test_owner', repo: 'test_repo', keyword: 'test_fingerprint', state: 'closed').returns(Hashie::Mash.new(issues: []))
|
43
|
-
PartyFoul.github.issues.expects(:create).with('test_owner', 'test_repo', title: 'Test Title', body: 'Test Body', :labels => ['bug'])
|
46
|
+
PartyFoul.github.issues.expects(:create).with('test_owner', 'test_repo', title: 'Test Title', body: 'Test Body', :labels => ['bug']).returns(Hashie::Mash.new('number' => 1))
|
47
|
+
PartyFoul.github.issues.comments.expects(:create).with('test_owner', 'test_repo', 1, body: 'Test Comment')
|
44
48
|
lambda {
|
45
49
|
get '/'
|
46
50
|
}.must_raise(Exception)
|
@@ -50,12 +54,14 @@ describe 'Party Foul Middleware' do
|
|
50
54
|
context 'when error is not new' do
|
51
55
|
before do
|
52
56
|
PartyFoul::ExceptionHandler.any_instance.stubs(:update_body).returns('New Body')
|
57
|
+
PartyFoul::ExceptionHandler.any_instance.stubs(:comment_body).returns('Test Comment')
|
53
58
|
end
|
54
59
|
|
55
60
|
context 'and open' do
|
56
61
|
it 'will update the issue' do
|
57
62
|
PartyFoul.github.search.stubs(:issues).with(owner: 'test_owner', repo: 'test_repo', keyword: 'test_fingerprint', state: 'open').returns(Hashie::Mash.new(issues: [{title: 'Test Title', body: 'Test Body', state: 'open', number: 1}]))
|
58
63
|
PartyFoul.github.issues.expects(:edit).with('test_owner', 'test_repo', 1, body: 'New Body', state: 'open')
|
64
|
+
PartyFoul.github.issues.comments.expects(:create).with('test_owner', 'test_repo', 1, body: 'Test Comment')
|
59
65
|
lambda {
|
60
66
|
get '/'
|
61
67
|
}.must_raise(Exception)
|
@@ -67,6 +73,7 @@ describe 'Party Foul Middleware' do
|
|
67
73
|
PartyFoul.github.search.stubs(:issues).with(owner: 'test_owner', repo: 'test_repo', keyword: 'test_fingerprint', state: 'open').returns(Hashie::Mash.new(issues: []))
|
68
74
|
PartyFoul.github.search.stubs(:issues).with(owner: 'test_owner', repo: 'test_repo', keyword: 'test_fingerprint', state: 'closed').returns(Hashie::Mash.new(issues: [{title: 'Test Title', body: 'Test Body', state: 'closed', number: 1}]))
|
69
75
|
PartyFoul.github.issues.expects(:edit).with('test_owner', 'test_repo', 1, body: 'New Body', state: 'open', labels: ['bug', 'regression'])
|
76
|
+
PartyFoul.github.issues.comments.expects(:create).with('test_owner', 'test_repo', 1, body: 'Test Comment')
|
70
77
|
lambda {
|
71
78
|
get '/'
|
72
79
|
}.must_raise(Exception)
|
@@ -81,6 +88,7 @@ describe 'Party Foul Middleware' do
|
|
81
88
|
PartyFoul.github.search.stubs(:issues).with(owner: 'test_owner', repo: 'test_repo', keyword: 'test_fingerprint', state: 'closed').returns(Hashie::Mash.new(issues: [{title: 'Test Title', body: 'Test Body', state: 'closed', number: 1, 'labels' => ['wontfix']}]))
|
82
89
|
PartyFoul.github.issues.expects(:create).never
|
83
90
|
PartyFoul.github.issues.expects(:edit).never
|
91
|
+
PartyFoul.github.issues.comments.expects(:create).never
|
84
92
|
lambda {
|
85
93
|
get '/'
|
86
94
|
}.must_raise(Exception)
|
@@ -98,6 +106,7 @@ describe 'Party Foul Middleware' do
|
|
98
106
|
PartyFoul.github.search.stubs(:issues).with(owner: 'test_owner', repo: 'test_repo', keyword: 'test_fingerprint', state: 'open').returns(Hashie::Mash.new(issues: []))
|
99
107
|
PartyFoul.github.search.stubs(:issues).with(owner: 'test_owner', repo: 'test_repo', keyword: 'test_fingerprint', state: 'closed').returns(Hashie::Mash.new(issues: []))
|
100
108
|
PartyFoul.github.issues.expects(:create).never
|
109
|
+
PartyFoul.github.issues.comments.expects(:create).never
|
101
110
|
lambda {
|
102
111
|
get '/'
|
103
112
|
}.must_raise(StandardError)
|
data/test/test_helper.rb
CHANGED
@@ -0,0 +1,18 @@
|
|
1
|
+
PartyFoul.configure do |config|
|
2
|
+
# the collection of exceptions to be ignored by PartyFoul
|
3
|
+
# The constants here *must* be represented as strings
|
4
|
+
config.ignored_exceptions = ['ActiveRecord::RecordNotFound', 'ActionController::RoutingError']
|
5
|
+
|
6
|
+
# The OAuth token for the account that will be opening the issues on Github
|
7
|
+
config.oauth_token = 'test_token'
|
8
|
+
|
9
|
+
# The API endpoint for Github. Unless you are hosting a private
|
10
|
+
# instance of Enterprise Github you do not need to include this
|
11
|
+
config.endpoint = 'test_endpoint'
|
12
|
+
|
13
|
+
# The organization or user that owns the target repository
|
14
|
+
config.owner = 'test_login'
|
15
|
+
|
16
|
+
# The repository for this application
|
17
|
+
config.repo = 'test_repo'
|
18
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: party_foul
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -10,7 +10,7 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date: 2013-01-
|
13
|
+
date: 2013-01-25 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: github_api
|
@@ -33,33 +33,49 @@ dependencies:
|
|
33
33
|
requirement: !ruby/object:Gem::Requirement
|
34
34
|
none: false
|
35
35
|
requirements:
|
36
|
-
- -
|
36
|
+
- - ~>
|
37
37
|
- !ruby/object:Gem::Version
|
38
|
-
version:
|
38
|
+
version: 3.2.11
|
39
39
|
type: :development
|
40
40
|
prerelease: false
|
41
41
|
version_requirements: !ruby/object:Gem::Requirement
|
42
42
|
none: false
|
43
43
|
requirements:
|
44
|
-
- -
|
44
|
+
- - ~>
|
45
45
|
- !ruby/object:Gem::Version
|
46
|
-
version:
|
46
|
+
version: 3.2.11
|
47
47
|
- !ruby/object:Gem::Dependency
|
48
|
-
name:
|
48
|
+
name: activesupport
|
49
49
|
requirement: !ruby/object:Gem::Requirement
|
50
50
|
none: false
|
51
51
|
requirements:
|
52
|
-
- -
|
52
|
+
- - ~>
|
53
53
|
- !ruby/object:Gem::Version
|
54
|
-
version:
|
54
|
+
version: 3.2.11
|
55
55
|
type: :development
|
56
56
|
prerelease: false
|
57
57
|
version_requirements: !ruby/object:Gem::Requirement
|
58
58
|
none: false
|
59
59
|
requirements:
|
60
|
-
- -
|
60
|
+
- - ~>
|
61
61
|
- !ruby/object:Gem::Version
|
62
|
-
version:
|
62
|
+
version: 3.2.11
|
63
|
+
- !ruby/object:Gem::Dependency
|
64
|
+
name: railties
|
65
|
+
requirement: !ruby/object:Gem::Requirement
|
66
|
+
none: false
|
67
|
+
requirements:
|
68
|
+
- - ~>
|
69
|
+
- !ruby/object:Gem::Version
|
70
|
+
version: 3.2.11
|
71
|
+
type: :development
|
72
|
+
prerelease: false
|
73
|
+
version_requirements: !ruby/object:Gem::Requirement
|
74
|
+
none: false
|
75
|
+
requirements:
|
76
|
+
- - ~>
|
77
|
+
- !ruby/object:Gem::Version
|
78
|
+
version: 3.2.11
|
63
79
|
- !ruby/object:Gem::Dependency
|
64
80
|
name: minitest
|
65
81
|
requirement: !ruby/object:Gem::Requirement
|
@@ -109,7 +125,7 @@ dependencies:
|
|
109
125
|
- !ruby/object:Gem::Version
|
110
126
|
version: '0'
|
111
127
|
- !ruby/object:Gem::Dependency
|
112
|
-
name:
|
128
|
+
name: mocha
|
113
129
|
requirement: !ruby/object:Gem::Requirement
|
114
130
|
none: false
|
115
131
|
requirements:
|
@@ -149,16 +165,20 @@ extensions: []
|
|
149
165
|
extra_rdoc_files: []
|
150
166
|
files:
|
151
167
|
- lib/generators/party_foul/install_generator.rb
|
168
|
+
- lib/generators/party_foul/templates/party_foul.rb
|
152
169
|
- lib/party_foul/exception_handler.rb
|
153
170
|
- lib/party_foul/middleware.rb
|
171
|
+
- lib/party_foul/sync_adapter.rb
|
154
172
|
- lib/party_foul/version.rb
|
155
173
|
- lib/party_foul.rb
|
156
174
|
- Rakefile
|
157
175
|
- README.md
|
176
|
+
- test/generator_test.rb
|
158
177
|
- test/party_foul/configure_test.rb
|
159
178
|
- test/party_foul/exception_handler_test.rb
|
160
179
|
- test/party_foul/middleware_test.rb
|
161
180
|
- test/test_helper.rb
|
181
|
+
- test/tmp/config/initializers/party_foul.rb
|
162
182
|
homepage: https://github.com/dockyard/party_foul
|
163
183
|
licenses: []
|
164
184
|
post_install_message:
|
@@ -173,7 +193,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
173
193
|
version: '0'
|
174
194
|
segments:
|
175
195
|
- 0
|
176
|
-
hash:
|
196
|
+
hash: -1173897567857159302
|
177
197
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
178
198
|
none: false
|
179
199
|
requirements:
|
@@ -182,7 +202,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
182
202
|
version: '0'
|
183
203
|
segments:
|
184
204
|
- 0
|
185
|
-
hash:
|
205
|
+
hash: -1173897567857159302
|
186
206
|
requirements: []
|
187
207
|
rubyforge_project:
|
188
208
|
rubygems_version: 1.8.23
|
@@ -190,7 +210,9 @@ signing_key:
|
|
190
210
|
specification_version: 3
|
191
211
|
summary: Auto-submit Rails exceptions as new isues on Github
|
192
212
|
test_files:
|
213
|
+
- test/generator_test.rb
|
193
214
|
- test/party_foul/configure_test.rb
|
194
215
|
- test/party_foul/exception_handler_test.rb
|
195
216
|
- test/party_foul/middleware_test.rb
|
196
217
|
- test/test_helper.rb
|
218
|
+
- test/tmp/config/initializers/party_foul.rb
|