jira_exception_collector 0.0.1
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/.gitignore +19 -0
- data/.travis.yml +7 -0
- data/Gemfile +18 -0
- data/LICENSE +21 -0
- data/README.md +66 -0
- data/Rakefile +11 -0
- data/jira_exception_collector.gemspec +23 -0
- data/lib/rack/exception.erb +53 -0
- data/lib/rack/jira_exception_collector.rb +195 -0
- data/lib/rack/jira_exception_collector_version.rb +5 -0
- data/test/helper.rb +9 -0
- data/test/test_log_exception.rb +28 -0
- metadata +134 -0
data/.gitignore
ADDED
data/.travis.yml
ADDED
data/Gemfile
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
source 'http://rubygems.org'
|
2
|
+
|
3
|
+
# Specify your gem's dependencies in jira_notifier.gemspec
|
4
|
+
gemspec
|
5
|
+
|
6
|
+
group :test do
|
7
|
+
gem 'rake'
|
8
|
+
gem 'test-unit'
|
9
|
+
gem 'fakeweb'
|
10
|
+
gem 'bundler', '>= 1.0.0'
|
11
|
+
gem 'rack'
|
12
|
+
if RUBY_VERSION =~ /^1\.9/
|
13
|
+
gem 'ruby-debug19'
|
14
|
+
else
|
15
|
+
gem 'ruby-debug'
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
data/LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
Copyright (c) 2011 Rich Manalang
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
21
|
+
|
data/README.md
ADDED
@@ -0,0 +1,66 @@
|
|
1
|
+
# JIRA Exception Collector
|
2
|
+
|
3
|
+
A gem that logs your exceptions as a JIRA issue. Once it's in JIRA, you can route it to
|
4
|
+
the appropriate developer to fix the issue using JIRA's workflow engine.
|
5
|
+
|
6
|
+

|
7
|
+
|
8
|
+
## Installation
|
9
|
+
|
10
|
+
JIRA Exception Collector is a gem. To install:
|
11
|
+
|
12
|
+
gem install jira-exception-collector
|
13
|
+
|
14
|
+
... or, add this to your Gemfile:
|
15
|
+
|
16
|
+
gem jira-exception-collector
|
17
|
+
|
18
|
+
... then:
|
19
|
+
|
20
|
+
bundle install
|
21
|
+
|
22
|
+
|
23
|
+
## Usage
|
24
|
+
|
25
|
+
This gem utilizes the [JIRA Issue Collector plugin](https://plugins.atlassian.com/583856).
|
26
|
+
Make sure your JIRA instance has this plugin installed before using this gem.
|
27
|
+
|
28
|
+
## Setup an Issue Collector in JIRA
|
29
|
+
|
30
|
+
In JIRA, go to Administration > Issue Collectors. You'll need to be a JIRA administrator
|
31
|
+
to do this. Add a new Issue Collector pointing to the project you want the exceptions to
|
32
|
+
go to. Also, if you don't already have an Issue Type for exceptions, you might want to
|
33
|
+
create one so that you have a better way of organizing the issues in your project.
|
34
|
+
|
35
|
+
Once you create the Issue Collector, copy the Collector URL (found on the Issue Collector's
|
36
|
+
page).
|
37
|
+
|
38
|
+
## Configure your Rack app with the Collector URL
|
39
|
+
|
40
|
+
This gem works with any Rack based app. To configure it, first crack open your config.ru
|
41
|
+
and add this before the `run` statement:
|
42
|
+
|
43
|
+
````ruby
|
44
|
+
use Rack::JiraExceptionCollector, "[collector url]"
|
45
|
+
````
|
46
|
+
|
47
|
+
By default, JIRA Exception Collector is enabled under production and staging environments.
|
48
|
+
To modify this, just supply an array of the environments you want exceptions to be logged:
|
49
|
+
|
50
|
+
````ruby
|
51
|
+
use Rack::JiraExceptionCollector, "[collector url]", %w(prod1 prod2 stage deploy)
|
52
|
+
````
|
53
|
+
|
54
|
+
## Compatibility with JIRA
|
55
|
+
|
56
|
+
Because this gem relies on the [JIRA Issue Collector plugin](https://plugins.atlassian.com/583856),
|
57
|
+
this gem is only compatible with the JIRA versions that the JIRA Issue Collector supports.
|
58
|
+
|
59
|
+
## Contributing
|
60
|
+
|
61
|
+
This is a pushmepullyou type of project. Fork it hard, push in your awesome sauce, then
|
62
|
+
send in your pull request. Oh, don't forget to add tests.
|
63
|
+
|
64
|
+
## Copyright
|
65
|
+
|
66
|
+
Copyright (c) Rich Manalang and Atlassian, Inc. See LICENSE for details.
|
data/Rakefile
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
require File.expand_path('../lib/rack/jira_exception_collector_version', __FILE__)
|
3
|
+
|
4
|
+
Gem::Specification.new do |gem|
|
5
|
+
gem.name = "jira_exception_collector"
|
6
|
+
gem.authors = ["Rich Manalang"]
|
7
|
+
gem.email = ["rmanalang@atlassian.com"]
|
8
|
+
gem.description = %q{A basic exception logger that logs to a JIRA instance}
|
9
|
+
gem.summary = %q{jira_notifier will log your exceptions to a JIRA instance}
|
10
|
+
gem.homepage = "https://github.com/manalang/jira_exception_collector"
|
11
|
+
|
12
|
+
gem.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
13
|
+
gem.files = `git ls-files`.split("\n")
|
14
|
+
gem.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
15
|
+
gem.require_paths = ["lib"]
|
16
|
+
gem.version = Rack::JiraExceptionCollector::VERSION
|
17
|
+
gem.add_dependency 'rack'
|
18
|
+
gem.extra_rdoc_files = ['README.md','LICENSE']
|
19
|
+
|
20
|
+
gem.add_development_dependency 'rake'
|
21
|
+
gem.add_development_dependency 'test-unit'
|
22
|
+
gem.add_development_dependency 'fakeweb'
|
23
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
{code}
|
2
|
+
Server Environment:
|
3
|
+
===================
|
4
|
+
|
5
|
+
Project root: <%=project_root %>
|
6
|
+
Environment name: <%=framework_env %>
|
7
|
+
|
8
|
+
|
9
|
+
Error:
|
10
|
+
======
|
11
|
+
|
12
|
+
Class: <%=error.class.name %>
|
13
|
+
<%- if error.respond_to?(:message) -%>
|
14
|
+
Message: <%=error.message %>
|
15
|
+
<%- end -%>
|
16
|
+
|
17
|
+
<%- if backtrace.respond_to?(:each) -%>
|
18
|
+
<%- backtrace.each do |line| -%>
|
19
|
+
<%=line.file %> [<%=line.method %>] (<%=line.number %>)
|
20
|
+
<%- end -%>
|
21
|
+
<%- end -%>
|
22
|
+
|
23
|
+
Request:
|
24
|
+
========
|
25
|
+
|
26
|
+
URL: <%=url %>
|
27
|
+
|
28
|
+
<%- if params && params.any? -%>
|
29
|
+
Request Parameters:
|
30
|
+
-------------------
|
31
|
+
|
32
|
+
<%- params.each do |key, value| -%>
|
33
|
+
<%=key %>: <%=value %>
|
34
|
+
<%- end -%>
|
35
|
+
|
36
|
+
<%- end -%>
|
37
|
+
<%- if session && session.any? -%>
|
38
|
+
Session:
|
39
|
+
========
|
40
|
+
|
41
|
+
<%- session.each do |key, value| -%>
|
42
|
+
<%=key %>: <%=value %>
|
43
|
+
<%- end -%>
|
44
|
+
|
45
|
+
<%- end -%>
|
46
|
+
<%- if environment && environment.any? -%>
|
47
|
+
Environment:
|
48
|
+
============
|
49
|
+
<%- environment.each do |key,value| -%>
|
50
|
+
<%=key %>: <%=value %>
|
51
|
+
<%- end -%>
|
52
|
+
<%- end -%>
|
53
|
+
{code}
|
@@ -0,0 +1,195 @@
|
|
1
|
+
require 'rack/jira_exception_collector_version'
|
2
|
+
require 'net/http'
|
3
|
+
require 'net/https'
|
4
|
+
require 'uri'
|
5
|
+
require 'erb'
|
6
|
+
require 'ostruct'
|
7
|
+
|
8
|
+
module Rack
|
9
|
+
class JiraExceptionCollector
|
10
|
+
|
11
|
+
FILTER_REPLACEMENT = "[FILTERED]"
|
12
|
+
|
13
|
+
class Error < StandardError; end
|
14
|
+
|
15
|
+
def initialize(app, collector_url = nil, report_under = %w(staging production),
|
16
|
+
rack_environment = 'RACK_ENV')
|
17
|
+
@app = app
|
18
|
+
@collector_url = collector_url
|
19
|
+
@report_under = report_under
|
20
|
+
@rack_environment = rack_environment
|
21
|
+
@filters = %w(AWS_ACCESS_KEY AWS_SECRET_ACCESS_KEY AWS_ACCOUNT SSH_AUTH_SOCK)
|
22
|
+
@failsafe = $stderr
|
23
|
+
yield self if block_given?
|
24
|
+
end
|
25
|
+
|
26
|
+
def call(env)
|
27
|
+
status, headers, body =
|
28
|
+
begin
|
29
|
+
@app.call(env)
|
30
|
+
rescue StandardError, LoadError, SyntaxError => boom
|
31
|
+
notified = send_exception boom, env
|
32
|
+
raise
|
33
|
+
end
|
34
|
+
send_exception env['rack.exception'], env if env['rack.exception']
|
35
|
+
[status, headers, body]
|
36
|
+
end
|
37
|
+
|
38
|
+
def environment_filter_keys
|
39
|
+
@filters.flatten
|
40
|
+
end
|
41
|
+
|
42
|
+
def environment_filter_regexps
|
43
|
+
environment_filter_keys.map do |key|
|
44
|
+
"^#{Regexp.escape(wrapped_key_for(key))}$"
|
45
|
+
end
|
46
|
+
end
|
47
|
+
private
|
48
|
+
def report?
|
49
|
+
@report_under.include?(rack_env) || rack_env == "test"
|
50
|
+
end
|
51
|
+
|
52
|
+
def send_exception(exception, env)
|
53
|
+
return true unless report?
|
54
|
+
request = Rack::Request.new(env)
|
55
|
+
env['rack.session'] = {:a => 1}
|
56
|
+
|
57
|
+
options = {
|
58
|
+
:url => env['REQUEST_URI'],
|
59
|
+
:params => request.params,
|
60
|
+
:framework_env => rack_env,
|
61
|
+
:notifier_name => 'Rack::JiraExceptionCollector',
|
62
|
+
:notifier_version => VERSION,
|
63
|
+
:environment => environment_data_for(env),
|
64
|
+
:session => env['rack.session']
|
65
|
+
}
|
66
|
+
|
67
|
+
if result = post_to_jira(exception, options)
|
68
|
+
if result.code == "200"
|
69
|
+
env['jira.notified'] = true
|
70
|
+
else
|
71
|
+
raise Error, "Status: #{result.code} #{result.body.inspect}"
|
72
|
+
end
|
73
|
+
else
|
74
|
+
raise Error, "No response from JIRA"
|
75
|
+
end
|
76
|
+
rescue Exception => e
|
77
|
+
return unless @failsafe
|
78
|
+
@failsafe.puts "Fail safe error caught: #{e.class}: #{e.message}"
|
79
|
+
@failsafe.puts e.backtrace
|
80
|
+
@failsafe.puts "Exception is #{exception.class}: #{exception.message}"
|
81
|
+
@failsafe.puts exception.backtrace
|
82
|
+
false
|
83
|
+
end
|
84
|
+
|
85
|
+
def rack_env
|
86
|
+
ENV[@rack_environment] || 'development'
|
87
|
+
end
|
88
|
+
|
89
|
+
def document_defaults(error)
|
90
|
+
{
|
91
|
+
:error => error,
|
92
|
+
:environment => ENV.to_hash,
|
93
|
+
:backtrace => backtrace_for(error),
|
94
|
+
:url => nil,
|
95
|
+
:request => nil,
|
96
|
+
:params => nil,
|
97
|
+
:notifier_version => VERSION,
|
98
|
+
:session => {},
|
99
|
+
:framework_env => ENV['RACK_ENV'] || 'development',
|
100
|
+
:project_root => Dir.pwd
|
101
|
+
}
|
102
|
+
end
|
103
|
+
|
104
|
+
def document_data(error, options)
|
105
|
+
data = document_defaults(error).merge(options)
|
106
|
+
[:params, :session, :environment].each{|n| data[n] = clean(data[n]) if data[n] }
|
107
|
+
data
|
108
|
+
end
|
109
|
+
|
110
|
+
def document_for(exception, options={})
|
111
|
+
data = document_data(exception, options)
|
112
|
+
scope = OpenStruct.new(data).extend(ERB::Util)
|
113
|
+
scope.instance_eval ERB.new(notice_template, nil, '-').src
|
114
|
+
end
|
115
|
+
|
116
|
+
def notice_template
|
117
|
+
::File.read(::File.join(::File.dirname(__FILE__), 'exception.erb'))
|
118
|
+
end
|
119
|
+
|
120
|
+
BacktraceLine = Struct.new(:file, :number, :method)
|
121
|
+
|
122
|
+
def backtrace_for(error)
|
123
|
+
return "" unless error.respond_to? :backtrace
|
124
|
+
lines = Array(error.backtrace).map {|l| backtrace_line(l)}
|
125
|
+
if lines.empty?
|
126
|
+
lines << BacktraceLine.new("no-backtrace", "1", nil)
|
127
|
+
end
|
128
|
+
lines
|
129
|
+
end
|
130
|
+
|
131
|
+
def backtrace_line(line)
|
132
|
+
if match = line.match(%r{^(.+):(\d+)(?::in `([^']+)')?$})
|
133
|
+
BacktraceLine.new(*match.captures)
|
134
|
+
else
|
135
|
+
BacktraceLine.new(line, "1", nil)
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
def post_to_jira(exception,options={})
|
140
|
+
uri = URI.parse(@collector_url)
|
141
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
142
|
+
http.use_ssl = true if uri.scheme == "https"
|
143
|
+
request = Net::HTTP::Post.new(uri.request_uri)
|
144
|
+
request['X-JIRA-Client-Name'] = "Rack::JiraExceptionCollector"
|
145
|
+
error = document_for(exception, options)
|
146
|
+
request.set_form_data({
|
147
|
+
"description" => "#{exception.class.name}: #{exception.message}",
|
148
|
+
"webInfo" => error
|
149
|
+
})
|
150
|
+
response = http.request(request)
|
151
|
+
end
|
152
|
+
|
153
|
+
def environment_data_for(env)
|
154
|
+
data = {}
|
155
|
+
ENV.each do |key,value|
|
156
|
+
data[wrapped_key_for(key)] = value.inspect
|
157
|
+
end
|
158
|
+
env.each do |key,value|
|
159
|
+
data["rack[#{key.inspect}]"] = value.inspect
|
160
|
+
end
|
161
|
+
data
|
162
|
+
end
|
163
|
+
|
164
|
+
def clean(hash)
|
165
|
+
hash.inject({}) do |acc, (k, v)|
|
166
|
+
acc[k] = (v.is_a?(Hash) ? clean(v) : filtered_value(k,v))
|
167
|
+
acc
|
168
|
+
end
|
169
|
+
end
|
170
|
+
|
171
|
+
def filters
|
172
|
+
environment_filter_keys.flatten.compact
|
173
|
+
end
|
174
|
+
|
175
|
+
def filtered_value(key, value)
|
176
|
+
if filters.any? {|f| key.to_s =~ Regexp.new(f)}
|
177
|
+
FILTER_REPLACEMENT
|
178
|
+
else
|
179
|
+
value.to_s
|
180
|
+
end
|
181
|
+
end
|
182
|
+
|
183
|
+
def wrapped_key_for(key)
|
184
|
+
"ENV[#{key.inspect}]"
|
185
|
+
end
|
186
|
+
|
187
|
+
def extract_body(env)
|
188
|
+
if io = env['rack.input']
|
189
|
+
io.rewind if io.respond_to?(:rewind)
|
190
|
+
io.read
|
191
|
+
end
|
192
|
+
end
|
193
|
+
|
194
|
+
end
|
195
|
+
end
|
data/test/helper.rb
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
class Rack::JiraExceptionCollector::TestLogException < Test::Unit::TestCase
|
4
|
+
def setup
|
5
|
+
@collector_url = "http://example.com/rest/collectors/1.0/template/form/ac29dace"
|
6
|
+
FakeWeb.register_uri(:post, @collector_url,
|
7
|
+
:body => "Thanks for providing your feedback", :status => ["200", "OK"])
|
8
|
+
|
9
|
+
@app = Rack::Lobster.new
|
10
|
+
@collector = Rack::JiraExceptionCollector.new @app, @collector_url
|
11
|
+
@request = Rack::MockRequest.new @collector
|
12
|
+
end
|
13
|
+
|
14
|
+
def test_exception_was_sent
|
15
|
+
ENV['RACK_ENV'] = 'test'
|
16
|
+
env = Rack::MockRequest.env_for('/?flip=crash', :method => 'GET')
|
17
|
+
assert_raise(RuntimeError) { @collector.call(env) }
|
18
|
+
assert_true env['jira.notified'], "JIRA exception created"
|
19
|
+
end
|
20
|
+
|
21
|
+
def test_exception_can_be_sent_from_a_custom_env
|
22
|
+
ENV['RACK_ENV'] = "my_custom_env"
|
23
|
+
env = Rack::MockRequest.env_for('/?flip=crash', :method => 'GET')
|
24
|
+
collector = Rack::JiraExceptionCollector.new @app, @collector_url, "my_custom_env"
|
25
|
+
assert_raise(RuntimeError) { collector.call(env) }
|
26
|
+
assert_true env['jira.notified'], "JIRA exception created"
|
27
|
+
end
|
28
|
+
end
|
metadata
ADDED
@@ -0,0 +1,134 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: jira_exception_collector
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 29
|
5
|
+
prerelease:
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 0
|
9
|
+
- 1
|
10
|
+
version: 0.0.1
|
11
|
+
platform: ruby
|
12
|
+
authors:
|
13
|
+
- Rich Manalang
|
14
|
+
autorequire:
|
15
|
+
bindir: bin
|
16
|
+
cert_chain: []
|
17
|
+
|
18
|
+
date: 2011-11-30 00:00:00 Z
|
19
|
+
dependencies:
|
20
|
+
- !ruby/object:Gem::Dependency
|
21
|
+
name: rack
|
22
|
+
prerelease: false
|
23
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
24
|
+
none: false
|
25
|
+
requirements:
|
26
|
+
- - ">="
|
27
|
+
- !ruby/object:Gem::Version
|
28
|
+
hash: 3
|
29
|
+
segments:
|
30
|
+
- 0
|
31
|
+
version: "0"
|
32
|
+
type: :runtime
|
33
|
+
version_requirements: *id001
|
34
|
+
- !ruby/object:Gem::Dependency
|
35
|
+
name: rake
|
36
|
+
prerelease: false
|
37
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
38
|
+
none: false
|
39
|
+
requirements:
|
40
|
+
- - ">="
|
41
|
+
- !ruby/object:Gem::Version
|
42
|
+
hash: 3
|
43
|
+
segments:
|
44
|
+
- 0
|
45
|
+
version: "0"
|
46
|
+
type: :development
|
47
|
+
version_requirements: *id002
|
48
|
+
- !ruby/object:Gem::Dependency
|
49
|
+
name: test-unit
|
50
|
+
prerelease: false
|
51
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
52
|
+
none: false
|
53
|
+
requirements:
|
54
|
+
- - ">="
|
55
|
+
- !ruby/object:Gem::Version
|
56
|
+
hash: 3
|
57
|
+
segments:
|
58
|
+
- 0
|
59
|
+
version: "0"
|
60
|
+
type: :development
|
61
|
+
version_requirements: *id003
|
62
|
+
- !ruby/object:Gem::Dependency
|
63
|
+
name: fakeweb
|
64
|
+
prerelease: false
|
65
|
+
requirement: &id004 !ruby/object:Gem::Requirement
|
66
|
+
none: false
|
67
|
+
requirements:
|
68
|
+
- - ">="
|
69
|
+
- !ruby/object:Gem::Version
|
70
|
+
hash: 3
|
71
|
+
segments:
|
72
|
+
- 0
|
73
|
+
version: "0"
|
74
|
+
type: :development
|
75
|
+
version_requirements: *id004
|
76
|
+
description: A basic exception logger that logs to a JIRA instance
|
77
|
+
email:
|
78
|
+
- rmanalang@atlassian.com
|
79
|
+
executables: []
|
80
|
+
|
81
|
+
extensions: []
|
82
|
+
|
83
|
+
extra_rdoc_files:
|
84
|
+
- README.md
|
85
|
+
- LICENSE
|
86
|
+
files:
|
87
|
+
- .gitignore
|
88
|
+
- .travis.yml
|
89
|
+
- Gemfile
|
90
|
+
- LICENSE
|
91
|
+
- README.md
|
92
|
+
- Rakefile
|
93
|
+
- jira_exception_collector.gemspec
|
94
|
+
- lib/rack/exception.erb
|
95
|
+
- lib/rack/jira_exception_collector.rb
|
96
|
+
- lib/rack/jira_exception_collector_version.rb
|
97
|
+
- test/helper.rb
|
98
|
+
- test/test_log_exception.rb
|
99
|
+
homepage: https://github.com/manalang/jira_exception_collector
|
100
|
+
licenses: []
|
101
|
+
|
102
|
+
post_install_message:
|
103
|
+
rdoc_options: []
|
104
|
+
|
105
|
+
require_paths:
|
106
|
+
- lib
|
107
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
108
|
+
none: false
|
109
|
+
requirements:
|
110
|
+
- - ">="
|
111
|
+
- !ruby/object:Gem::Version
|
112
|
+
hash: 3
|
113
|
+
segments:
|
114
|
+
- 0
|
115
|
+
version: "0"
|
116
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
117
|
+
none: false
|
118
|
+
requirements:
|
119
|
+
- - ">="
|
120
|
+
- !ruby/object:Gem::Version
|
121
|
+
hash: 3
|
122
|
+
segments:
|
123
|
+
- 0
|
124
|
+
version: "0"
|
125
|
+
requirements: []
|
126
|
+
|
127
|
+
rubyforge_project:
|
128
|
+
rubygems_version: 1.8.10
|
129
|
+
signing_key:
|
130
|
+
specification_version: 3
|
131
|
+
summary: jira_notifier will log your exceptions to a JIRA instance
|
132
|
+
test_files:
|
133
|
+
- test/helper.rb
|
134
|
+
- test/test_log_exception.rb
|