stacker_bee 2.0.0 → 2.1.0.pre180

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 (73) hide show
  1. checksums.yaml +13 -5
  2. data/.travis.yml +13 -1
  3. data/README.md +134 -64
  4. data/bin/stacker_bee +4 -3
  5. data/config.default.yml +1 -1
  6. data/lib/stacker_bee/api.rb +2 -3
  7. data/lib/stacker_bee/client.rb +101 -19
  8. data/lib/stacker_bee/connection.rb +31 -16
  9. data/lib/stacker_bee/{middleware → http_middleware}/detokenizer.rb +3 -2
  10. data/lib/stacker_bee/http_middleware/graylog.rb +14 -0
  11. data/lib/stacker_bee/{middleware → http_middleware}/signed_query.rb +1 -1
  12. data/lib/stacker_bee/middleware/adapter.rb +16 -0
  13. data/lib/stacker_bee/middleware/base.rb +33 -0
  14. data/lib/stacker_bee/middleware/clean_response.rb +42 -0
  15. data/lib/stacker_bee/middleware/cloud_stack_api.rb +17 -0
  16. data/lib/stacker_bee/middleware/console_access.rb +38 -0
  17. data/lib/stacker_bee/middleware/de_namespace.rb +15 -0
  18. data/lib/stacker_bee/middleware/dictionary_flattener.rb +44 -0
  19. data/lib/stacker_bee/middleware/endpoint_normalizer.rb +23 -0
  20. data/lib/stacker_bee/middleware/environment.rb +23 -0
  21. data/lib/stacker_bee/middleware/format_keys.rb +13 -0
  22. data/lib/stacker_bee/middleware/format_values.rb +13 -0
  23. data/lib/stacker_bee/middleware/http_status.rb +14 -0
  24. data/lib/stacker_bee/middleware/json_body.rb +14 -0
  25. data/lib/stacker_bee/middleware/raise_on_http_error.rb +11 -0
  26. data/lib/stacker_bee/middleware/rashify_response.rb +21 -0
  27. data/lib/stacker_bee/middleware/remove_empty_strings.rb +11 -0
  28. data/lib/stacker_bee/middleware/remove_nils.rb +9 -0
  29. data/lib/stacker_bee/request_error.rb +8 -16
  30. data/lib/stacker_bee/utilities.rb +30 -0
  31. data/lib/stacker_bee/version.rb +1 -1
  32. data/lib/stacker_bee.rb +1 -1
  33. data/spec/cassettes/A_request_sent_to_CloudStack_for_console_access/returns_html_for_console_access.yml +33 -0
  34. data/spec/cassettes/A_response_to_a_request_sent_to_the_CloudStack_API/{a_request_parameter_with_a_Map → a_request_parameter_with_a_map}/can_create_an_object.yml +0 -0
  35. data/spec/cassettes/A_response_to_a_request_sent_to_the_CloudStack_API/a_request_that_triggers_an_error/properly_signs_the_request.yml +35 -0
  36. data/spec/cassettes/A_response_to_a_request_sent_to_the_CloudStack_API/middleware/a_middleware_that_doesn_t_match_the_content_type/uses_the_middleware.yml +33 -0
  37. data/spec/cassettes/A_response_to_a_request_sent_to_the_CloudStack_API/middleware/a_middleware_that_matches_the_content_type/uses_the_middleware.yml +33 -0
  38. data/spec/integration/check_spec.rb +48 -0
  39. data/spec/integration/configure_middleware_spec.rb +54 -16
  40. data/spec/integration/console_spec.rb +21 -0
  41. data/spec/integration/request_spec.rb +57 -2
  42. data/spec/spec_helper.rb +11 -1
  43. data/spec/units/faraday_graylog_middleware_spec.rb +1 -1
  44. data/spec/units/stacker_bee/client_spec.rb +47 -78
  45. data/spec/units/stacker_bee/connection_spec.rb +34 -11
  46. data/spec/units/stacker_bee/console_spec.rb +0 -0
  47. data/spec/units/stacker_bee/{graylog_faraday_middleware_spec.rb → http_middleware/graylog_spec.rb} +18 -2
  48. data/spec/units/stacker_bee/middleware/adapter_spec.rb +54 -0
  49. data/spec/units/stacker_bee/middleware/base_spec.rb +128 -0
  50. data/spec/units/stacker_bee/middleware/cloudstack_api_spec.rb +37 -0
  51. data/spec/units/stacker_bee/middleware/console_access_spec.rb +59 -0
  52. data/spec/units/stacker_bee/{dictionary_flattener_spec.rb → middleware/dictionary_flattener_spec.rb} +7 -7
  53. data/spec/units/stacker_bee/middleware/endpoint_normalizer_spec.rb +36 -0
  54. data/spec/units/stacker_bee/middleware/format_keys_spec.rb +18 -0
  55. data/spec/units/stacker_bee/middleware/format_values_spec.rb +15 -0
  56. data/spec/units/stacker_bee/middleware/http_status_spec.rb +34 -0
  57. data/spec/units/stacker_bee/middleware/raise_on_http_errors_spec.rb +5 -0
  58. data/spec/units/stacker_bee/middleware/remove_empty_strings_spec.rb +54 -0
  59. data/spec/units/stacker_bee/middleware/remove_nils_spec.rb +8 -0
  60. data/spec/units/stacker_bee/request_error_spec.rb +25 -37
  61. data/spec/units/stacker_bee/utilities_spec.rb +26 -0
  62. data/stacker_bee.gemspec +6 -2
  63. metadata +84 -38
  64. data/lib/stacker_bee/body_parser.rb +0 -23
  65. data/lib/stacker_bee/dictionary_flattener.rb +0 -41
  66. data/lib/stacker_bee/graylog_faraday_middleware.rb +0 -12
  67. data/lib/stacker_bee/middleware/logger.rb +0 -47
  68. data/lib/stacker_bee/request.rb +0 -46
  69. data/lib/stacker_bee/response.rb +0 -29
  70. data/spec/cassettes/A_response_to_a_request_sent_to_the_CloudStack_API/a_request_parameter_with_a_Map/object.yml +0 -153
  71. data/spec/units/stacker_bee/middleware/logger_spec.rb +0 -55
  72. data/spec/units/stacker_bee/request_spec.rb +0 -51
  73. data/spec/units/stacker_bee/response_spec.rb +0 -79
@@ -0,0 +1,128 @@
1
+ require 'spec_helper'
2
+
3
+ describe StackerBee::Middleware::Base do
4
+ let(:env) { StackerBee::Middleware::Environment.new(params: params) }
5
+ let(:params) { {} }
6
+ let(:app) { double(:app, call: response) }
7
+ let(:response) { double(:response) }
8
+ let(:content_type) { double }
9
+ before { env.response.content_type = content_type }
10
+
11
+ let(:middleware) { subclass.new(app: app) }
12
+
13
+ let(:subclass) { Class.new(StackerBee::Middleware::Base, &subclass_body) }
14
+ let(:subclass_body) { proc { } }
15
+
16
+ describe "#call" do
17
+ before do
18
+ middleware.call env
19
+ end
20
+
21
+ def self.it_calls_its_app_with_the_env
22
+ it "calls its app with the env" do
23
+ app.should have_received(:call).with(env)
24
+ end
25
+ end
26
+
27
+ it_calls_its_app_with_the_env
28
+
29
+ context "when overriding #before" do
30
+ let(:subclass_body) do
31
+ proc do
32
+ def before(env)
33
+ env.before_was_run = true
34
+ end
35
+ end
36
+ end
37
+
38
+ it_calls_its_app_with_the_env
39
+
40
+ it "runs the before hook" do
41
+ env.before_was_run.should be_true
42
+ end
43
+ end
44
+
45
+ context "when overriding #after" do
46
+ let(:subclass_body) do
47
+ proc do
48
+ def after(env)
49
+ env.after_was_run = true
50
+ end
51
+ end
52
+ end
53
+
54
+ it_calls_its_app_with_the_env
55
+
56
+ it "runs the after hook" do
57
+ env.after_was_run.should be_true
58
+ end
59
+ end
60
+
61
+ context "when overriding #content_types" do
62
+ let(:subclass_body) do
63
+ proc do
64
+ def after(env)
65
+ env.after_was_run = true
66
+ end
67
+
68
+ def content_types
69
+ /html/
70
+ end
71
+ end
72
+ end
73
+
74
+ it_calls_its_app_with_the_env
75
+
76
+ context "when it matches the content type" do
77
+ let(:content_type) { 'text/html; uft-8' }
78
+ it "runs the after hook" do
79
+ env.after_was_run.should be_true
80
+ end
81
+ end
82
+
83
+ context "when it doesn't match the content type" do
84
+ let(:content_type) { 'text/javascript; uft-8' }
85
+ it "runs the after hook" do
86
+ env.after_was_run.should be_nil
87
+ end
88
+ end
89
+ end
90
+
91
+ context "when overriding #params" do
92
+ let(:subclass_body) do
93
+ proc do
94
+ def params(params)
95
+ params.merge(params_merged?: true)
96
+ end
97
+ end
98
+ end
99
+
100
+ it "changes the params" do
101
+ env.request.params[:params_merged?].should be_true
102
+ end
103
+ end
104
+ end
105
+
106
+ describe "#endpoint_name_for" do
107
+ let(:endpoint_name) { double }
108
+ let(:normalized_endpoint_name) { double }
109
+
110
+ it "delegates to its app" do
111
+ app.should_receive(:endpoint_name_for)
112
+ .with(endpoint_name)
113
+ .and_return(normalized_endpoint_name)
114
+
115
+ middleware.endpoint_name_for(endpoint_name)
116
+ .should == normalized_endpoint_name
117
+ end
118
+ end
119
+
120
+ describe "#matches_content_type?" do
121
+ describe "by default" do
122
+ before { env.response.content_type = '$8^02(324' }
123
+ it "matches anything" do
124
+ middleware.matches_content_type?(env).should be_true
125
+ end
126
+ end
127
+ end
128
+ end
@@ -0,0 +1,37 @@
1
+ require 'spec_helper'
2
+
3
+ describe StackerBee::Middleware::CloudStackAPI do
4
+ let(:env) do
5
+ StackerBee::Middleware::Environment.new(
6
+ endpoint_name: 'endpoint-name',
7
+ path: path
8
+ )
9
+ end
10
+
11
+ let(:middleware) { described_class.new(api_key: "API-KEY", params: {}) }
12
+ let(:path) { nil }
13
+
14
+ before { middleware.before(env) }
15
+
16
+ describe "request" do
17
+ subject { env.request }
18
+
19
+ context "when the path is not set" do
20
+ let(:path) { nil }
21
+ its(:path) { should == described_class::DEFAULT_PATH }
22
+ end
23
+
24
+ context "when the path is already set" do
25
+ let(:path) { "already set" }
26
+ its(:path) { should == path }
27
+ end
28
+ end
29
+
30
+ describe "params" do
31
+ subject { env.request.params }
32
+ its([:api_key]) { should eq "API-KEY" }
33
+ its([:response]) { should eq "json" }
34
+ its([:command]) { should eq "endpoint-name" }
35
+ end
36
+ end
37
+
@@ -0,0 +1,59 @@
1
+ require "spec_helper"
2
+
3
+ describe StackerBee::Middleware::ConsoleAccess do
4
+ let(:env) do
5
+ StackerBee::Middleware::Environment.new(endpoint_name: endpoint_name)
6
+ end
7
+
8
+ let(:middleware) { described_class.new(app: app) }
9
+ let(:app) { double(:app) }
10
+
11
+ context "when it matches the endpoint" do
12
+ let(:endpoint_name) { described_class::ENDPOINT }
13
+
14
+ it "adds its path to the env" do
15
+ middleware.before(env)
16
+ env.request.path.should == described_class::PATH
17
+ end
18
+
19
+ it "adds cmd to the parameters" do
20
+ env.request.params.should_not include described_class::PARAMS
21
+ end
22
+ end
23
+
24
+ context "when it doesn't match the endpoint" do
25
+ let(:endpoint_name) { :other_endpoint }
26
+
27
+ before { middleware.before(env) }
28
+
29
+ it "doesn't add it's path" do
30
+ env.request.path.should_not == described_class::PATH
31
+ end
32
+
33
+ it "doesn't add cmd to the parameters" do
34
+ env.request.params.should_not include described_class::PARAMS
35
+ end
36
+ end
37
+
38
+ it "matches html content typtes" do
39
+ middleware.content_types.should =~ "text/html; charset=utf-8"
40
+ end
41
+
42
+ describe "#endpoint_name_for" do
43
+ context "given names it reponds to" do
44
+ %w[consoleAccess console_access CONSOLEACCESS].each do |name|
45
+ it "returns consoleAccess for '#{name}'" do
46
+ middleware.endpoint_name_for(name).should == described_class::ENDPOINT
47
+ end
48
+ end
49
+ end
50
+
51
+ context "for other names" do
52
+ before { app.stub :endpoint_name_for, &:upcase }
53
+
54
+ it "delegates for other names" do
55
+ middleware.endpoint_name_for('other-name').should == 'OTHER-NAME'
56
+ end
57
+ end
58
+ end
59
+ end
@@ -1,24 +1,24 @@
1
1
  require 'spec_helper'
2
2
 
3
- describe StackerBee::DictionaryFlattener do
4
- let(:lb) { StackerBee::DictionaryFlattener::LB }
5
- let(:rb) { StackerBee::DictionaryFlattener::RB }
3
+ describe StackerBee::Middleware::DictionaryFlattener do
4
+ let(:lb) { described_class::LB }
5
+ let(:rb) { described_class::RB }
6
6
  let(:string) { "cool[0].name%21" }
7
7
  let(:tokenized_string) { "cool#{lb}0#{rb}.name%21" }
8
8
 
9
9
  describe ".detokenize" do
10
- subject { StackerBee::DictionaryFlattener.detokenize(tokenized_string) }
10
+ subject { described_class.detokenize(tokenized_string) }
11
11
  it { should eq string }
12
12
  end
13
13
 
14
14
  describe ".tokenize" do
15
- subject { StackerBee::DictionaryFlattener.tokenize(string) }
15
+ subject { described_class.tokenize(string) }
16
16
  it { should eq tokenized_string }
17
17
  end
18
18
 
19
19
  describe ".new" do
20
20
  def prefix(number)
21
- StackerBee::DictionaryFlattener.tokenize "rebels[#{number}]"
21
+ described_class.tokenize "rebels[#{number}]"
22
22
  end
23
23
 
24
24
  let(:params) do
@@ -27,7 +27,7 @@ describe StackerBee::DictionaryFlattener do
27
27
  end
28
28
 
29
29
  subject do
30
- StackerBee::DictionaryFlattener.new(params).params
30
+ described_class.new.params(params)
31
31
  end
32
32
 
33
33
  it "flattens objects in the manner that cloudstack expects" do
@@ -0,0 +1,36 @@
1
+ require 'spec_helper'
2
+
3
+ describe StackerBee::Middleware::EndpointNormalizer do
4
+ let(:middleware) { described_class.new(app: app, api: api) }
5
+ let(:app) { double(:app) }
6
+
7
+ let(:env) do
8
+ StackerBee::Middleware::Environment.new(
9
+ endpoint_name: endpoint_name
10
+ )
11
+ end
12
+
13
+ context "when it doesn't match" do
14
+ let(:api) { {} }
15
+ let(:endpoint_name) { :some_endpoint }
16
+
17
+ describe "#endpoint_name_for" do
18
+ before { app.stub :endpoint_name_for, &:upcase }
19
+
20
+ it "delegates to its app" do
21
+ middleware.endpoint_name_for('some-name').should == 'SOME-NAME'
22
+ end
23
+ end
24
+
25
+ describe "#before" do
26
+ before { app.stub endpoint_name_for: nil }
27
+
28
+ it "doesn't set the endpoint to nil", :regression do
29
+ middleware.before env
30
+ env.request.endpoint_name.should == endpoint_name
31
+ end
32
+ end
33
+ end
34
+
35
+ context "when it matches an endpoint"
36
+ end
@@ -0,0 +1,18 @@
1
+ require 'spec_helper'
2
+
3
+ describe StackerBee::Middleware::FormatKeys do
4
+ subject { described_class.new.params(params) }
5
+
6
+ let(:params) do
7
+ {
8
+ symbol: true,
9
+ key_case: true
10
+ }
11
+ end
12
+
13
+ it { should have_key "symbol" }
14
+ it { should_not have_key :symbol }
15
+
16
+ it { should have_key "keyCase" }
17
+ it { should_not have_key :key_case }
18
+ end
@@ -0,0 +1,15 @@
1
+ require 'spec_helper'
2
+
3
+ describe StackerBee::Middleware::FormatValues do
4
+ subject { described_class.new.params(params) }
5
+
6
+ let(:params) do
7
+ {
8
+ single: 1,
9
+ list: [1,2,3]
10
+ }
11
+ end
12
+
13
+ its([:single]) { should eq "1" }
14
+ its([:list]) { should eq "1,2,3" }
15
+ end
@@ -0,0 +1,34 @@
1
+ require 'spec_helper'
2
+
3
+ describe StackerBee::Middleware::HTTPStatus do
4
+ subject { env.response }
5
+ before { middleware.after(env) }
6
+
7
+ let(:middleware) { described_class.new }
8
+ let(:env) do
9
+ StackerBee::Middleware::Environment.new.tap do |env|
10
+ env.raw_response = double(status: http_status, success?: success?)
11
+ env.response.body = body
12
+ end
13
+ end
14
+ let(:body) { { errorcode: http_status, errortext: message } }
15
+ let(:message) { "Unable to execute API command deployvirtualmachine " }
16
+
17
+ context "given an error" do
18
+ let(:http_status) { 431 }
19
+ let(:success?) { false }
20
+
21
+ its(:status) { should eq http_status }
22
+ its(:error) { should eq message }
23
+ it { should_not be_success }
24
+ end
25
+
26
+ context "given a success" do
27
+ let(:http_status) { 200 }
28
+ let(:success?) { true }
29
+
30
+ its(:status) { should eq http_status }
31
+ its(:error) { should be_nil }
32
+ it { should be_success }
33
+ end
34
+ end
@@ -0,0 +1,5 @@
1
+ require 'spec_helper'
2
+
3
+ describe StackerBee::Middleware::RaiseOnHTTPError do
4
+ pending
5
+ end
@@ -0,0 +1,54 @@
1
+ require "spec_helper"
2
+
3
+ # TODO: does this really need to work with nested hashes?
4
+ describe StackerBee::Middleware::RemoveEmptyStrings do
5
+ let(:middleware) do
6
+ described_class.new(app: proc { |env| @response_env = env })
7
+ end
8
+ let(:env) { StackerBee::Middleware::Environment.new }
9
+ # TODO: rename response_env
10
+ let(:response_env) { @response_env }
11
+ let(:params) { response_env.request.params }
12
+
13
+ before do
14
+ env.request.params = {
15
+ blank: '',
16
+ ok1: true,
17
+ ok2: nil,
18
+ ok3: 'string',
19
+ ok4: ' ',
20
+
21
+ nested: {
22
+ blank: '',
23
+ ok1: true,
24
+ ok2: nil,
25
+ ok3: 'string',
26
+ ok4: ' ',
27
+
28
+ nested: {
29
+ blank: '',
30
+ ok1: true,
31
+ ok2: nil,
32
+ ok3: 'string',
33
+ ok4: ' '
34
+ }
35
+ }
36
+ }
37
+ end
38
+
39
+ before do
40
+ middleware.call(env)
41
+ end
42
+
43
+ it "removes empty strings from the input" do
44
+ params.keys.should =~ [:ok1, :ok2, :ok3, :ok4, :nested]
45
+ end
46
+
47
+ it "removes empty strings nested in hashes" do
48
+ params[:nested].keys.should =~ [:ok1, :ok2, :ok3, :ok4, :nested]
49
+ end
50
+
51
+ it "removes empty strings deeply nested in hashes" do
52
+ params[:nested][:nested].keys.should =~ [:ok1, :ok2, :ok3, :ok4]
53
+ end
54
+ end
@@ -0,0 +1,8 @@
1
+ require 'spec_helper'
2
+
3
+ describe StackerBee::Middleware::RemoveNils do
4
+ it "removes pairs with nil values from the params" do
5
+ subject.params(something: 'something', nothing: nil)
6
+ .should eq something: 'something'
7
+ end
8
+ end
@@ -1,44 +1,32 @@
1
1
  require "spec_helper"
2
2
 
3
- describe StackerBee::RequestError, ".for" do
4
- let(:raw_response) { double status: status, body: '{"foo": "bar"}' }
5
- subject { StackerBee::RequestError.for raw_response }
3
+ describe "An error occuring" do
4
+ let(:env) { double response: response }
5
+ let(:response) { double status: status, error: error_text }
6
+ let(:error_text) { "There was an error!" }
7
+ let(:status) { 431 }
6
8
 
7
- context "HTTP status in the 400s" do
8
- let(:status) { 431 }
9
- it { should be_a StackerBee::ClientError }
10
- end
11
- context "HTTP status in the 500s" do
12
- let(:status) { 500 }
13
- it { should be_a StackerBee::ServerError }
14
- end
15
- context "HTTP status > 599" do
16
- let(:status) { 999 }
17
- it { should be_a StackerBee::RequestError }
18
- end
19
- end
9
+ describe StackerBee::RequestError, ".for" do
10
+ subject { StackerBee::RequestError.for env }
20
11
 
21
- describe StackerBee::RequestError do
22
- let(:http_status) { 431 }
23
- let(:message) do
24
- "Unable to execute API command deployvirtualmachine " +
25
- "due to missing parameter zoneid"
12
+ context "HTTP status in the 400s" do
13
+ let(:status) { 431 }
14
+ it { should be_a StackerBee::ClientError }
15
+ end
16
+ context "HTTP status in the 500s" do
17
+ let(:status) { 500 }
18
+ it { should be_a StackerBee::ServerError }
19
+ end
20
+ context "HTTP status > 599" do
21
+ let(:status) { 999 }
22
+ it { should be_a StackerBee::RequestError }
23
+ end
26
24
  end
27
- let(:raw_body) do
28
- <<-EOS
29
- {
30
- "deployvirtualmachineresponse": {
31
- "uuidList": [],
32
- "errorcode": #{http_status},
33
- "cserrorcode": 9999,
34
- "errortext": "#{message}"
35
- }
36
- }
37
- EOS
25
+
26
+ describe StackerBee::RequestError do
27
+ subject { StackerBee::ClientError.new(env) }
28
+
29
+ its(:status) { should eq status }
30
+ its(:to_s) { should eq error_text }
38
31
  end
39
- let(:raw_response) { double body: raw_body, :success? => false, status: 431 }
40
- let(:client_error) { StackerBee::ClientError.new raw_response }
41
- subject { client_error }
42
- its(:status) { should eq http_status }
43
- its(:to_s) { should eq message }
44
32
  end
@@ -24,4 +24,30 @@ describe StackerBee::Utilities, "#uncase" do
24
24
  it { camel_case("fooBar", true).should eq "fooBar" }
25
25
  it { camel_case("fooBar", false).should eq "FooBar" }
26
26
  it { camel_case("foo[0].Bar", false).should eq "Foo[0].Bar" }
27
+
28
+ describe "#map_a_hash" do
29
+ let(:original) { { 1 => 1, 2 => 2 } }
30
+ let(:expected) { { 2 => -1, 4 => -2 } }
31
+
32
+ let(:transformed) do
33
+ map_a_hash(original) { |key, value| [key * 2, value * -1] }
34
+ end
35
+
36
+ it "should map over a hash" do
37
+ transformed.should eq expected
38
+ end
39
+
40
+ it "should not modify the original" do
41
+ original.freeze
42
+ transformed
43
+ end
44
+ end
45
+
46
+ describe ".transform_hash_keys" do
47
+ it { transform_hash_keys({ 1 => 2 }, &:odd?).should eq true => 2 }
48
+ end
49
+
50
+ describe ".transform_hash_values" do
51
+ it { transform_hash_values({ 1 => 2 }, &:odd?).should eq 1 => false }
52
+ end
27
53
  end
data/stacker_bee.gemspec CHANGED
@@ -19,10 +19,11 @@ Gem::Specification.new do |spec|
19
19
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
20
20
  spec.require_paths = ["lib"]
21
21
 
22
- spec.add_runtime_dependency "faraday", "~> 0.8"
22
+ spec.add_runtime_dependency "faraday", "~> 0.8", "< 0.9"
23
+ spec.add_runtime_dependency 'multi_json', "~> 1.8"
24
+
23
25
  # this is a dependency for FaradayMiddleware::Graylog
24
26
  spec.add_runtime_dependency "faraday_middleware", "~> 0.9"
25
- spec.add_runtime_dependency 'multi_json', "~> 1.8"
26
27
 
27
28
  spec.add_development_dependency "bundler", "~> 1.3"
28
29
  spec.add_development_dependency "rake", "~> 10.0"
@@ -31,4 +32,7 @@ Gem::Specification.new do |spec|
31
32
  spec.add_development_dependency "vcr", "~> 2.6"
32
33
  spec.add_development_dependency "rubocop"
33
34
  spec.add_development_dependency "pry"
35
+
36
+ # Release every merge to master as a prerelease
37
+ spec.version = "#{spec.version}.pre#{ENV['TRAVIS_BUILD_NUMBER']}" if ENV['TRAVIS']
34
38
  end