honeybadger 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (65) hide show
  1. data/Gemfile +13 -0
  2. data/Gemfile.lock +114 -0
  3. data/Guardfile +5 -0
  4. data/MIT-LICENSE +22 -0
  5. data/README.md +271 -0
  6. data/Rakefile +261 -0
  7. data/SUPPORTED_RAILS_VERSIONS +26 -0
  8. data/TESTING.md +33 -0
  9. data/features/metal.feature +18 -0
  10. data/features/rack.feature +56 -0
  11. data/features/rails.feature +211 -0
  12. data/features/rake.feature +27 -0
  13. data/features/sinatra.feature +29 -0
  14. data/features/step_definitions/file_steps.rb +10 -0
  15. data/features/step_definitions/metal_steps.rb +23 -0
  16. data/features/step_definitions/rack_steps.rb +23 -0
  17. data/features/step_definitions/rails_application_steps.rb +394 -0
  18. data/features/step_definitions/rake_steps.rb +17 -0
  19. data/features/support/env.rb +17 -0
  20. data/features/support/honeybadger_shim.rb.template +8 -0
  21. data/features/support/rails.rb +201 -0
  22. data/features/support/rake/Rakefile +68 -0
  23. data/features/support/terminal.rb +107 -0
  24. data/generators/honeybadger/honeybadger_generator.rb +94 -0
  25. data/generators/honeybadger/lib/insert_commands.rb +34 -0
  26. data/generators/honeybadger/lib/rake_commands.rb +24 -0
  27. data/generators/honeybadger/templates/capistrano_hook.rb +6 -0
  28. data/generators/honeybadger/templates/honeybadger_tasks.rake +25 -0
  29. data/generators/honeybadger/templates/initializer.rb +6 -0
  30. data/honeybadger.gemspec +109 -0
  31. data/lib/honeybadger.rb +162 -0
  32. data/lib/honeybadger/backtrace.rb +123 -0
  33. data/lib/honeybadger/capistrano.rb +43 -0
  34. data/lib/honeybadger/configuration.rb +273 -0
  35. data/lib/honeybadger/notice.rb +314 -0
  36. data/lib/honeybadger/rack.rb +55 -0
  37. data/lib/honeybadger/rails.rb +34 -0
  38. data/lib/honeybadger/rails/action_controller_catcher.rb +30 -0
  39. data/lib/honeybadger/rails/controller_methods.rb +69 -0
  40. data/lib/honeybadger/rails/middleware/exceptions_catcher.rb +29 -0
  41. data/lib/honeybadger/rails3_tasks.rb +84 -0
  42. data/lib/honeybadger/railtie.rb +45 -0
  43. data/lib/honeybadger/rake_handler.rb +65 -0
  44. data/lib/honeybadger/sender.rb +120 -0
  45. data/lib/honeybadger/shared_tasks.rb +36 -0
  46. data/lib/honeybadger/tasks.rb +82 -0
  47. data/lib/honeybadger_tasks.rb +65 -0
  48. data/lib/rails/generators/honeybadger/honeybadger_generator.rb +99 -0
  49. data/rails/init.rb +1 -0
  50. data/resources/README.md +34 -0
  51. data/resources/ca-bundle.crt +3376 -0
  52. data/script/integration_test.rb +38 -0
  53. data/test/test_helper.rb +143 -0
  54. data/test/unit/backtrace_test.rb +180 -0
  55. data/test/unit/capistrano_test.rb +34 -0
  56. data/test/unit/configuration_test.rb +201 -0
  57. data/test/unit/honeybadger_tasks_test.rb +163 -0
  58. data/test/unit/logger_test.rb +72 -0
  59. data/test/unit/notice_test.rb +406 -0
  60. data/test/unit/notifier_test.rb +245 -0
  61. data/test/unit/rack_test.rb +56 -0
  62. data/test/unit/rails/action_controller_catcher_test.rb +300 -0
  63. data/test/unit/rails_test.rb +35 -0
  64. data/test/unit/sender_test.rb +257 -0
  65. metadata +315 -0
data/Gemfile ADDED
@@ -0,0 +1,13 @@
1
+ source "https://rubygems.org"
2
+
3
+ gemspec
4
+
5
+ if true
6
+ group :test do
7
+ gem 'turn'
8
+ gem 'pry'
9
+ gem 'guard'
10
+ gem 'guard-test'
11
+ gem 'simplecov'
12
+ end
13
+ end
data/Gemfile.lock ADDED
@@ -0,0 +1,114 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ honeybadger (0.0.1)
5
+ activesupport
6
+ json
7
+
8
+ GEM
9
+ remote: https://rubygems.org/
10
+ specs:
11
+ actionpack (2.3.14)
12
+ activesupport (= 2.3.14)
13
+ rack (~> 1.1.0)
14
+ activerecord (2.3.14)
15
+ activesupport (= 2.3.14)
16
+ activesupport (2.3.14)
17
+ ansi (1.4.2)
18
+ bourne (1.1.2)
19
+ mocha (= 0.10.5)
20
+ builder (3.0.0)
21
+ capistrano (2.8.0)
22
+ highline
23
+ net-scp (>= 1.0.0)
24
+ net-sftp (>= 2.0.0)
25
+ net-ssh (>= 2.0.14)
26
+ net-ssh-gateway (>= 1.1.0)
27
+ coderay (1.0.6)
28
+ cucumber (0.10.7)
29
+ builder (>= 2.1.2)
30
+ diff-lcs (>= 1.1.2)
31
+ gherkin (~> 2.4.0)
32
+ json (>= 1.4.6)
33
+ term-ansicolor (>= 1.0.5)
34
+ diff-lcs (1.1.3)
35
+ fakeweb (1.3.0)
36
+ ffi (1.0.11)
37
+ gherkin (2.4.21)
38
+ json (>= 1.4.6)
39
+ guard (1.2.1)
40
+ listen (>= 0.4.2)
41
+ thor (>= 0.14.6)
42
+ guard-test (0.5.0)
43
+ guard (>= 1.1.0)
44
+ test-unit (~> 2.2)
45
+ highline (1.6.13)
46
+ json (1.7.3)
47
+ listen (0.4.6)
48
+ rb-fchange (~> 0.0.5)
49
+ rb-fsevent (~> 0.9.1)
50
+ rb-inotify (~> 0.8.8)
51
+ metaclass (0.0.1)
52
+ method_source (0.7.1)
53
+ mocha (0.10.5)
54
+ metaclass (~> 0.0.1)
55
+ multi_json (1.3.6)
56
+ net-scp (1.0.4)
57
+ net-ssh (>= 1.99.1)
58
+ net-sftp (2.0.5)
59
+ net-ssh (>= 2.0.9)
60
+ net-ssh (2.5.2)
61
+ net-ssh-gateway (1.1.0)
62
+ net-ssh (>= 1.99.1)
63
+ pry (0.9.9.6)
64
+ coderay (~> 1.0.5)
65
+ method_source (~> 0.7.1)
66
+ slop (>= 2.4.4, < 3)
67
+ rack (1.1.3)
68
+ rb-fchange (0.0.5)
69
+ ffi
70
+ rb-fsevent (0.9.1)
71
+ rb-inotify (0.8.8)
72
+ ffi (>= 0.5.0)
73
+ rspec (2.6.0)
74
+ rspec-core (~> 2.6.0)
75
+ rspec-expectations (~> 2.6.0)
76
+ rspec-mocks (~> 2.6.0)
77
+ rspec-core (2.6.4)
78
+ rspec-expectations (2.6.0)
79
+ diff-lcs (~> 1.1.2)
80
+ rspec-mocks (2.6.0)
81
+ sham_rack (1.3.4)
82
+ rack
83
+ shoulda (2.11.3)
84
+ simplecov (0.6.4)
85
+ multi_json (~> 1.0)
86
+ simplecov-html (~> 0.5.3)
87
+ simplecov-html (0.5.3)
88
+ slop (2.4.4)
89
+ term-ansicolor (1.0.7)
90
+ test-unit (2.5.0)
91
+ thor (0.15.3)
92
+ turn (0.9.5)
93
+ ansi
94
+
95
+ PLATFORMS
96
+ ruby
97
+
98
+ DEPENDENCIES
99
+ actionpack (~> 2.3.8)
100
+ activerecord (~> 2.3.8)
101
+ activesupport (~> 2.3.8)
102
+ bourne (>= 1.0)
103
+ capistrano (~> 2.8.0)
104
+ cucumber (~> 0.10.6)
105
+ fakeweb (~> 1.3.0)
106
+ guard
107
+ guard-test
108
+ honeybadger!
109
+ pry
110
+ rspec (~> 2.6.0)
111
+ sham_rack (~> 1.3.0)
112
+ shoulda (~> 2.11.3)
113
+ simplecov
114
+ turn
data/Guardfile ADDED
@@ -0,0 +1,5 @@
1
+ guard :test do
2
+ watch(%r{^lib/(.+)\.rb$}) { |m| "test/#{m[1]}_test.rb" }
3
+ watch(%r{^test/unit/.+_test\.rb$})
4
+ watch('test/test_helper.rb') { "test" }
5
+ end
data/MIT-LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2012, Honeybadger
2
+
3
+ Permission is hereby granted, free of charge, to any person
4
+ obtaining a copy of this software and associated documentation
5
+ files (the "Software"), to deal in the Software without
6
+ restriction, including without limitation the rights to use,
7
+ copy, modify, merge, publish, distribute, sublicense, and/or sell
8
+ copies of the Software, and to permit persons to whom the
9
+ Software is furnished to do so, subject to the following
10
+ conditions:
11
+
12
+ The above copyright notice and this permission notice shall be
13
+ included in all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
17
+ OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
19
+ HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
20
+ WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21
+ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22
+ OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,271 @@
1
+ Honeybadger
2
+ ===============
3
+
4
+ This is the notifier gem for integrating apps with [Honeybadger](http://honeybadger.io).
5
+
6
+ When an uncaught exception occurs, Honeybadger will POST the relevant data
7
+ to the Honeybadger server specified in your environment.
8
+
9
+ ## Rails Installation
10
+
11
+ Add the Honeybadger gem to your gemfile:
12
+
13
+ gem 'honeybadger'
14
+
15
+ Create an initializer in config/initializers and configure your API key
16
+ for your project:
17
+
18
+ # Uncomment the following line if running lower than Rails 3.2
19
+ # require 'honeybadger/rails'
20
+ Honeybadger.configure do |config|
21
+ config.api_key = '[your-api-key]'
22
+ end
23
+
24
+ That's it!
25
+
26
+ ### Rails 2.x
27
+
28
+ Add the honeybadger gem to your app. In config/environment.rb:
29
+
30
+ config.gem 'honeybadger'
31
+
32
+ or if you are using bundler:
33
+
34
+ gem 'honeybadger', :require => 'honeybadger/rails'
35
+
36
+ Then from your project's RAILS_ROOT, and in your development environment, run:
37
+
38
+ rake gems:install
39
+ rake gems:unpack GEM=honeybadger
40
+
41
+ As always, if you choose not to vendor the honeybadger gem, make sure
42
+ every server you deploy to has the gem installed or your application won't start.
43
+
44
+ Finally, create an initializer in config/initializers and configure your
45
+ API key for your project:
46
+
47
+ require 'honeybadger/rails'
48
+ Honeybadger.configure do |config|
49
+ config.api_key = '[your-api-key]'
50
+ end
51
+
52
+ ## Rack
53
+
54
+ In order to use honeybadger in a non-Rails rack app, just load
55
+ honeybadger, configure your API key, and use the Honeybadger::Rack
56
+ middleware:
57
+
58
+ require 'rack'
59
+ require 'honeybadger'
60
+
61
+ Honeybadger.configure do |config|
62
+ config.api_key = 'my_api_key'
63
+ end
64
+
65
+ app = Rack::Builder.app do
66
+ run lambda { |env| raise "Rack down" }
67
+ end
68
+
69
+ use Honeybadger::Rack
70
+ run app
71
+
72
+ ## Sinatra
73
+
74
+ Using honeybadger in a Sinatra app is just like a Rack app:
75
+
76
+ require 'sinatra'
77
+ require 'honeybadger'
78
+
79
+ Honeybadger.configure do |config|
80
+ config.api_key = 'my api key'
81
+ end
82
+
83
+ use Honeybadger::Rack
84
+
85
+ get '/' do
86
+ raise "Sinatra has left the building"
87
+ end
88
+
89
+ ## Usage
90
+
91
+ For the most part, Honeybadger works for itself.
92
+
93
+ It intercepts the exception middleware calls, sends notifications and continues the middleware call chain.
94
+
95
+ If you want to log arbitrary things which you've rescued yourself from a
96
+ controller, you can do something like this:
97
+
98
+ ...
99
+ rescue => ex
100
+ notify_honeybadger(ex)
101
+ flash[:failure] = 'Encryptions could not be rerouted, try again.'
102
+ end
103
+ ...
104
+
105
+ The `#notify_honeybadger` call will send the notice over to Honeybadger for later
106
+ analysis. While in your controllers you use the `notify_honeybadger` method, anywhere
107
+ else in your code, use `Honeybadger.notify`.
108
+
109
+ To perform custom error processing after Honeybadger has been notified, define the
110
+ instance method `#rescue_action_in_public_without_honeybadger(exception)` in your
111
+ controller.
112
+
113
+ You can test that Honeybadger is working in your production environment by using
114
+ this rake task (from RAILS_ROOT):
115
+
116
+ rake honeybadger:test
117
+
118
+ If everything is configured properly, that task will send a notice to Honeybadger
119
+ which will be visible immediately.
120
+
121
+ ## Going beyond exceptions
122
+
123
+ You can also pass a hash to `Honeybadger.notify` method and store whatever you want,
124
+ not just an exception. And you can also use it anywhere, not just in
125
+ controllers:
126
+
127
+ begin
128
+ params = {
129
+ # params that you pass to a method that can throw an exception
130
+ }
131
+ my_unpredicable_method(params)
132
+ rescue => e
133
+ Honeybadger.notify(
134
+ :error_class => "Special Error",
135
+ :error_message => "Special Error: #{e.message}",
136
+ :parameters => params
137
+ )
138
+ end
139
+
140
+ While in your controllers you use the `notify_honeybadger` method, anywhere else in
141
+ your code, use `Honeybadger.notify`. Honeybadger will get all the information
142
+ about the error itself. As for a hash, these are the keys you should pass:
143
+
144
+ * `:error_class` - Use this to group similar errors together. When Honeybadger catches an exception it sends the class name of that exception object.
145
+ * `:error_message` - This is the title of the error you see in the errors list. For exceptions it is "#{exception.class.name}: #{exception.message}"
146
+ * `:parameters` - While there are several ways to send additional data to Honeybadger, passing a Hash as :parameters as in the example above is the most common use case. When Honeybadger catches an exception in a controller, the actual HTTP client request parameters are sent using this key.
147
+
148
+ Honeybadger merges the hash you pass with these default options:
149
+
150
+ {
151
+ :api_key => Honeybadger.api_key,
152
+ :error_message => 'Notification',
153
+ :backtrace => caller,
154
+ :parameters => {},
155
+ :session => {}
156
+ }
157
+
158
+ You can override any of those parameters.
159
+
160
+ ### Sending shell environment variables when "Going beyond exceptions"
161
+
162
+ One common request we see is to send shell environment variables along with
163
+ manual exception notification. We recommend sending them along with CGI data
164
+ or Rack environment (:cgi_data or :rack_env keys, respectively.)
165
+
166
+ See Honeybadger::Notice#initialize in lib/honeybadger/notice.rb for
167
+ more details.
168
+
169
+ ## Filtering
170
+
171
+ You can specify a whitelist of errors that Honeybadger will not report on. Use
172
+ this feature when you are so apathetic to certain errors that you don't want
173
+ them even logged.
174
+
175
+ This filter will only be applied to automatic notifications, not manual
176
+ notifications (when #notify is called directly).
177
+
178
+ Honeybadger ignores the following exceptions by default:
179
+
180
+ ActiveRecord::RecordNotFound
181
+ ActionController::RoutingError
182
+ ActionController::InvalidAuthenticityToken
183
+ CGI::Session::CookieStore::TamperedWithCookie
184
+ ActionController::UnknownAction
185
+ AbstractController::ActionNotFound
186
+ Mongoid::Errors::DocumentNotFound
187
+
188
+ To ignore errors in addition to those, specify their names in your Honeybadger
189
+ configuration block.
190
+
191
+ Honeybadger.configure do |config|
192
+ config.api_key = '1234567890abcdef'
193
+ config.ignore << "ActiveRecord::IgnoreThisError"
194
+ end
195
+
196
+ To ignore *only* certain errors (and override the defaults), use the #ignore_only attribute.
197
+
198
+ Honeybadger.configure do |config|
199
+ config.api_key = '1234567890abcdef'
200
+ config.ignore_only = ["ActiveRecord::IgnoreThisError"] # or [] to ignore no exceptions.
201
+ end
202
+
203
+ To ignore certain user agents, add in the #ignore_user_agent attribute as a
204
+ string or regexp:
205
+
206
+ Honeybadger.configure do |config|
207
+ config.api_key = '1234567890abcdef'
208
+ config.ignore_user_agent << /Ignored/
209
+ config.ignore_user_agent << 'IgnoredUserAgent'
210
+ end
211
+
212
+ To ignore exceptions based on other conditions, use #ignore_by_filter:
213
+
214
+ Honeybadger.configure do |config|
215
+ config.api_key = '1234567890abcdef'
216
+ config.ignore_by_filter do |exception_data|
217
+ true if exception_data[:error_class] == "RuntimeError"
218
+ end
219
+ end
220
+
221
+ To replace sensitive information sent to the Honeybadger service with [FILTERED] use #params_filters:
222
+
223
+ Honeybadger.configure do |config|
224
+ config.api_key = '1234567890abcdef'
225
+ config.params_filters << "credit_card_number"
226
+ end
227
+
228
+ Note that, when rescuing exceptions within an ActionController method,
229
+ honeybadger will reuse filters specified by #filter_parameter_logging.
230
+
231
+ ## Testing
232
+
233
+ When you run your tests, you might notice that the Honeybadger service is recording
234
+ notices generated using #notify when you don't expect it to. You can
235
+ use code like this in your test_helper.rb or spec_helper.rb files to redefine
236
+ that method so those errors are not reported while running tests.
237
+
238
+ module Honeybadger
239
+ def self.notify(exception, opts = {})
240
+ # do nothing.
241
+ end
242
+ end
243
+
244
+ ## Proxy Support
245
+
246
+ The notifier supports using a proxy, if your server is not able to
247
+ directly reach the Honeybadger servers. To configure the proxy settings,
248
+ added the following information to your Honeybadger configuration block.
249
+
250
+ Honeybadger.configure do |config|
251
+ config.proxy_host = proxy.host.com
252
+ config.proxy_port = 4038
253
+ config.proxy_user = foo # optional
254
+ config.proxy_pass = bar # optional
255
+ end
256
+
257
+ ## Supported Rails versions
258
+
259
+ Honeybadger supports Rails 2.3.14 through rails 3.2.6.
260
+
261
+ ## Credits
262
+
263
+ Original code based on the [airbrake](http://airbrake.io) gem,
264
+ originally by Thoughtbot, Inc.
265
+
266
+ Thank you to Thoughtbot and all of the Airbrake contributors!
267
+
268
+ ## License
269
+
270
+ Honeybadger is Copyright 2012 © Honeybadger. It is free software, and
271
+ may be redistributed under the terms specified in the MIT-LICENSE file.
data/Rakefile ADDED
@@ -0,0 +1,261 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+ require 'date'
4
+ begin
5
+ require 'cucumber/rake/task'
6
+ rescue LoadError
7
+ $stderr.puts "Please install cucumber: `gem install cucumber`"
8
+ exit 1
9
+ end
10
+
11
+ #############################################################################
12
+ #
13
+ # Helper functions
14
+ #
15
+ #############################################################################
16
+
17
+ def name
18
+ @name ||= Dir['*.gemspec'].first.split('.').first
19
+ end
20
+
21
+ def version
22
+ line = File.read("lib/#{name}.rb")[/^\s*VERSION\s*=\s*.*/]
23
+ line.match(/.*VERSION\s*=\s*['"](.*)['"]/)[1]
24
+ end
25
+
26
+ def date
27
+ Date.today.to_s
28
+ end
29
+
30
+ def rubyforge_project
31
+ name
32
+ end
33
+
34
+ def gemspec_file
35
+ "#{name}.gemspec"
36
+ end
37
+
38
+ def gem_file
39
+ "#{name}-#{version}.gem"
40
+ end
41
+
42
+ def replace_header(head, header_name)
43
+ head.sub!(/(\.#{header_name}\s*= ').*'/) { "#{$1}#{send(header_name)}'"}
44
+ end
45
+
46
+ #############################################################################
47
+ #
48
+ # Standard tasks
49
+ #
50
+ #############################################################################
51
+
52
+ require 'rake/testtask'
53
+ Rake::TestTask.new(:test) do |test|
54
+ test.libs << 'lib' << 'test'
55
+ test.pattern = 'test/**/*_test.rb'
56
+ test.verbose = true
57
+ end
58
+
59
+ desc "Generate RCov test coverage and open in your browser"
60
+ task :coverage do
61
+ require 'rcov'
62
+ sh "rm -fr coverage"
63
+ sh "rcov test/*_test.rb"
64
+ sh "open coverage/index.html"
65
+ end
66
+
67
+ require 'rake/rdoctask'
68
+ Rake::RDocTask.new do |rdoc|
69
+ rdoc.rdoc_dir = 'rdoc'
70
+ rdoc.title = "#{name} #{version}"
71
+ rdoc.rdoc_files.include('README*')
72
+ rdoc.rdoc_files.include('lib/**/*.rb')
73
+ end
74
+
75
+ desc "Open an irb session preloaded with this library"
76
+ task :console do
77
+ sh "irb -rubygems -r ./lib/#{name}.rb"
78
+ end
79
+
80
+ #############################################################################
81
+ #
82
+ # Custom tasks (add your own tasks here)
83
+ #
84
+ #############################################################################
85
+
86
+ FEATURES = ['sinatra', 'rack', 'metal']
87
+
88
+ desc 'Default: run unit & acceptance tests.'
89
+ task :default => [:test, "cucumber:rails:all"] + FEATURES
90
+
91
+ GEM_ROOT = File.dirname(__FILE__).freeze
92
+
93
+ LOCAL_GEM_ROOT = File.join(GEM_ROOT, 'tmp', 'local_gems').freeze
94
+ RAILS_VERSIONS = IO.read('SUPPORTED_RAILS_VERSIONS').strip.split("\n")
95
+ LOCAL_GEMS =
96
+ [
97
+ ["rack","1.3.2"],
98
+ ] +
99
+ RAILS_VERSIONS.collect { |version| ['rails', version] } +
100
+ [
101
+ ['sham_rack', nil],
102
+ ['capistrano', nil],
103
+ ['sqlite3-ruby', nil],
104
+ ["therubyracer",nil],
105
+ ["sinatra",nil]
106
+ ]
107
+
108
+ desc "Vendor test gems: Run this once to prepare your test environment"
109
+ task :vendor_test_gems do
110
+ old_gem_path = ENV['GEM_PATH']
111
+ old_gem_home = ENV['GEM_HOME']
112
+ ENV['GEM_PATH'] = LOCAL_GEM_ROOT
113
+ ENV['GEM_HOME'] = LOCAL_GEM_ROOT
114
+
115
+ LOCAL_GEMS.each do |gem_name, version|
116
+ gem_file_pattern = [gem_name, version || '*'].compact.join('-')
117
+ version_option = version ? "-v #{version}" : ''
118
+ pattern = File.join(LOCAL_GEM_ROOT, 'gems', "#{gem_file_pattern}")
119
+ existing = Dir.glob(pattern).first
120
+ if existing
121
+ puts "\nskipping #{gem_name} since it's already vendored," +
122
+ "remove it from the tmp directory first."
123
+ next
124
+ end
125
+
126
+ command = "gem install -i #{LOCAL_GEM_ROOT} --no-ri --no-rdoc --backtrace #{version_option} #{gem_name}"
127
+ puts "Vendoring #{gem_file_pattern}..."
128
+ unless system("#{command} 2>&1")
129
+ puts "Command failed: #{command}"
130
+ exit(1)
131
+ end
132
+ end
133
+
134
+ ENV['GEM_PATH'] = old_gem_path
135
+ ENV['GEM_HOME'] = old_gem_home
136
+ end
137
+
138
+ Cucumber::Rake::Task.new(:cucumber) do |t|
139
+ t.fork = true
140
+ t.cucumber_opts = ['--format', (ENV['CUCUMBER_FORMAT'] || 'progress')]
141
+ end
142
+
143
+ task :cucumber => [:vendor_test_gems]
144
+
145
+ def run_rails_cucumber_task(version, additional_cucumber_args)
146
+ puts "Testing Rails #{version}"
147
+ if version.empty?
148
+ raise "No Rails version specified - make sure ENV['RAILS_VERSION'] is set, e.g. with `rake cucumber:rails:all`"
149
+ end
150
+ ENV['RAILS_VERSION'] = version
151
+ cmd = "cucumber --format #{ENV['CUCUMBER_FORMAT'] || 'progress'} #{additional_cucumber_args} features/rails.feature"
152
+ puts "Running command: #{cmd}"
153
+ system(cmd)
154
+ end
155
+
156
+ def define_rails_cucumber_tasks(additional_cucumber_args = '')
157
+ namespace :rails do
158
+ RAILS_VERSIONS.each do |version|
159
+ desc "Test integration of the gem with Rails #{version}"
160
+ task version => [:vendor_test_gems] do
161
+ exit 1 unless run_rails_cucumber_task(version, additional_cucumber_args)
162
+ end
163
+ end
164
+
165
+ desc "Test integration of the gem with all Rails versions"
166
+ task :all do
167
+ results = RAILS_VERSIONS.map do |version|
168
+ run_rails_cucumber_task(version, additional_cucumber_args)
169
+ end
170
+
171
+ exit 1 unless results.all?
172
+ end
173
+ end
174
+ end
175
+
176
+ namespace :cucumber do
177
+ namespace :wip do
178
+ define_rails_cucumber_tasks('--tags @wip')
179
+ end
180
+
181
+ define_rails_cucumber_tasks
182
+
183
+ rule /#{"(" + FEATURES.join("|") + ")"}/ do |t|
184
+ framework = t.name
185
+ desc "Test integration of the gem with #{framework}"
186
+ task framework.to_sym do
187
+ puts "Testing #{framework.split(":").last}..."
188
+ cmd = "cucumber --format #{ENV['CUCUMBER_FORMAT'] || 'progress'} features/#{framework.split(":").last}.feature"
189
+ puts "Running command: #{cmd}"
190
+ system(cmd)
191
+ end
192
+ end
193
+ end
194
+
195
+ #############################################################################
196
+ #
197
+ # Packaging tasks
198
+ #
199
+ #############################################################################
200
+
201
+ desc "Create tag v#{version} and build and push #{gem_file} to Rubygems"
202
+ task :release => :build do
203
+ unless `git branch` =~ /^\* master$/
204
+ puts "You must be on the master branch to release!"
205
+ exit!
206
+ end
207
+ sh "git commit --allow-empty -a -m 'Release #{version}'"
208
+ sh "git tag v#{version}"
209
+ sh "git push origin master"
210
+ sh "git push origin v#{version}"
211
+ sh "gem push pkg/#{name}-#{version}.gem"
212
+ end
213
+
214
+ desc "Build #{gem_file} into the pkg directory"
215
+ task :build => :gemspec do
216
+ sh "mkdir -p pkg"
217
+ sh "gem build #{gemspec_file}"
218
+ sh "mv #{gem_file} pkg"
219
+ end
220
+
221
+ desc "Generate #{gemspec_file}"
222
+ task :gemspec => :validate do
223
+ # read spec file and split out manifest section
224
+ spec = File.read(gemspec_file)
225
+ head, manifest, tail = spec.split(" # = MANIFEST =\n")
226
+
227
+ # replace name version and date
228
+ replace_header(head, :name)
229
+ replace_header(head, :version)
230
+ replace_header(head, :date)
231
+ #comment this out if your rubyforge_project has a different name
232
+ replace_header(head, :rubyforge_project)
233
+
234
+ # determine file list from git ls-files
235
+ files = `git ls-files`.
236
+ split("\n").
237
+ sort.
238
+ reject { |file| file =~ /^\./ }.
239
+ reject { |file| file =~ /^(rdoc|pkg)/ }.
240
+ map { |file| " #{file}" }.
241
+ join("\n")
242
+
243
+ # piece file back together and write
244
+ manifest = " s.files = %w[\n#{files}\n ]\n"
245
+ spec = [head, manifest, tail].join(" # = MANIFEST =\n")
246
+ File.open(gemspec_file, 'w') { |io| io.write(spec) }
247
+ puts "Updated #{gemspec_file}"
248
+ end
249
+
250
+ desc "Validate #{gemspec_file}"
251
+ task :validate do
252
+ libfiles = Dir['lib/*'] - ["lib/#{name}.rb", "lib/#{name}_tasks.rb", "lib/#{name}", "lib/rails"]
253
+ unless libfiles.empty?
254
+ puts "Directory `lib` should only contain `#{name}.rb` and `#{name}_tasks.rb` files, and `#{name}` and lib/rails dir."
255
+ exit!
256
+ end
257
+ unless Dir['VERSION*'].empty?
258
+ puts "A `VERSION` file at root level violates Gem best practices."
259
+ exit!
260
+ end
261
+ end