honeybadger 1.0.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 (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