right_develop 3.1.8 → 3.1.9
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/VERSION +1 -1
- data/lib/right_develop/testing/clients/rest/requests/playback.rb +21 -5
- data/lib/right_develop/testing/recording/config.rb +16 -3
- data/lib/right_develop/testing/recording/metadata.rb +158 -69
- data/lib/right_develop/testing/servers/might_api/Gemfile +1 -1
- data/lib/right_develop/testing/servers/might_api/Gemfile.lock +2 -2
- data/lib/right_develop/testing/servers/might_api/lib/config.rb +3 -1
- data/right_develop.gemspec +4 -4
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f9bea4294ac48a9bb1c124143e96594b3993867c
|
4
|
+
data.tar.gz: 1817c459f9d80fea412f1e1e7a66c011c6629f0d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 814de826f973fd7678c8723ea686bebc140aa18e39497e7d77d683c208dc6dddaa8895ab0bf121400c0005862ba01b49806c2ee9462863d4be55d27b71d20b5c
|
7
|
+
data.tar.gz: 65416ad1cbe5429b1e74b842449b739992f9d1e2d32e53569c209932f6ab8204e43c1596e576ff290d7995d15d393e9bfc62d3057b50bb4d28d7691bb8443e7e
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
3.1.
|
1
|
+
3.1.9
|
@@ -40,9 +40,10 @@ module RightDevelop::Testing::Client::Rest::Request
|
|
40
40
|
|
41
41
|
# fake Net::HTTPResponse
|
42
42
|
class FakeNetHttpResponse
|
43
|
-
attr_reader :code, :body, :elapsed_seconds, :call_count
|
43
|
+
attr_reader :code, :body, :delay_seconds, :elapsed_seconds, :call_count
|
44
44
|
|
45
45
|
def initialize(response_hash, response_metadata)
|
46
|
+
@delay_seconds = response_metadata.delay_seconds
|
46
47
|
@elapsed_seconds = Integer(response_hash[:elapsed_seconds] || 0)
|
47
48
|
@code = response_metadata.http_status.to_s
|
48
49
|
@headers = response_metadata.headers.inject({}) do |h, (k, v)|
|
@@ -140,6 +141,15 @@ module RightDevelop::Testing::Client::Rest::Request
|
|
140
141
|
logger.debug("throttle delay = #{delay}")
|
141
142
|
sleep delay
|
142
143
|
end
|
144
|
+
|
145
|
+
# there may be a configured response delay (in addition to throttling)
|
146
|
+
# which allows for other responses to complete before the current
|
147
|
+
# response thread is unblocked. the response delay is absolute and not
|
148
|
+
# subject to the throttle factor.
|
149
|
+
if (delay = response.delay_seconds) > 0
|
150
|
+
logger.debug("configured response delay = #{delay}")
|
151
|
+
sleep delay
|
152
|
+
end
|
143
153
|
log_response(response)
|
144
154
|
process_result(response, &block)
|
145
155
|
else
|
@@ -170,11 +180,15 @@ module RightDevelop::Testing::Client::Rest::Request
|
|
170
180
|
file_path = nil
|
171
181
|
past_epochs = state[:past_epochs] ||= []
|
172
182
|
try_epochs = [state[:epoch]] + past_epochs
|
173
|
-
|
183
|
+
first_tried_path = nil
|
184
|
+
first_tried_epoch = nil
|
185
|
+
last_tried_epoch = nil
|
174
186
|
try_epochs.each do |epoch|
|
175
187
|
file_path = response_file_path(epoch)
|
176
188
|
break if ::File.file?(file_path)
|
177
|
-
|
189
|
+
first_tried_path = file_path unless first_tried_path
|
190
|
+
first_tried_epoch = epoch unless first_tried_epoch
|
191
|
+
last_tried_epoch = epoch
|
178
192
|
file_path = nil
|
179
193
|
end
|
180
194
|
if file_path
|
@@ -189,8 +203,10 @@ module RightDevelop::Testing::Client::Rest::Request
|
|
189
203
|
response_hash[:body])
|
190
204
|
result = FakeNetHttpResponse.new(response_hash, response_metadata)
|
191
205
|
else
|
192
|
-
|
193
|
-
"
|
206
|
+
msg = 'Unable to locate response file(s) in epoch range ' +
|
207
|
+
"[#{first_tried_epoch} - #{last_tried_epoch}]:\n " +
|
208
|
+
first_tried_path.inspect
|
209
|
+
raise PLAYBACK_ERROR, msg
|
194
210
|
end
|
195
211
|
logger.debug("Played back response from #{file_path.inspect}.")
|
196
212
|
|
@@ -52,7 +52,7 @@ module RightDevelop::Testing::Recording
|
|
52
52
|
|
53
53
|
# keys allowed under the deep route configuration.
|
54
54
|
ALLOWED_KINDS = %w(request response)
|
55
|
-
ALLOWED_CONFIG_ACTIONS = %w(significant timeouts transform variables)
|
55
|
+
ALLOWED_CONFIG_ACTIONS = %w(delay_seconds significant timeouts transform variables)
|
56
56
|
ALLOWED_TIMEOUTS = %w(open_timeout read_timeout)
|
57
57
|
ALLOWED_VARIABLE_TYPES = %w(body header query)
|
58
58
|
|
@@ -178,11 +178,15 @@ module RightDevelop::Testing::Recording
|
|
178
178
|
# normalize routes for efficient usage but keep them separate from
|
179
179
|
# user's config so that .to_hash returns something understandable and
|
180
180
|
# JSONizable/YAMLable.
|
181
|
-
|
181
|
+
mutable_routes = value.inject(RightSupport::Data::Mash.new) do |r, (k, v)|
|
182
182
|
r[normalize_route_prefix(k)] = normalize_route_data(k, v)
|
183
183
|
r
|
184
184
|
end
|
185
|
-
|
185
|
+
|
186
|
+
# deep freeze routes to detect any case where code is unintentionally
|
187
|
+
# modifying the route hash.
|
188
|
+
@normalized_routes = ::RightSupport::Data::HashTools.deep_freeze!(mutable_routes)
|
189
|
+
@config_hash['routes'] = ::RightSupport::Data::HashTools.deep_clone2(value)
|
186
190
|
else
|
187
191
|
raise ConfigError, 'routes must be a hash'
|
188
192
|
end
|
@@ -554,6 +558,15 @@ module RightDevelop::Testing::Recording
|
|
554
558
|
|
555
559
|
rst[rst_k] = rst_v.inject(RightSupport::Data::Mash.new) do |kc, (kc_k, kc_v)|
|
556
560
|
case kc_k
|
561
|
+
when METADATA_CLASS::DELAY_SECONDS_KEY
|
562
|
+
begin
|
563
|
+
kc_v = Float(kc_v)
|
564
|
+
rescue ::ArgumentError
|
565
|
+
location = position_string(position, subpath + [rst_k, kc_k])
|
566
|
+
message = 'Invalid route configuration delay_seconds value at ' +
|
567
|
+
"#{location}: #{kc_v.inspect}"
|
568
|
+
raise ConfigError, message
|
569
|
+
end
|
557
570
|
when METADATA_CLASS::TIMEOUTS_KEY
|
558
571
|
# sanity check.
|
559
572
|
kc_v = kc_v.inject(RightSupport::Data::Mash.new) do |h, (k, v)|
|
@@ -43,11 +43,12 @@ module RightDevelop::Testing::Recording
|
|
43
43
|
KINDS = %w(request response)
|
44
44
|
|
45
45
|
# route-relative config keys.
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
46
|
+
DELAY_SECONDS_KEY = 'delay_seconds'.freeze
|
47
|
+
MATCHERS_KEY = 'matchers'.freeze
|
48
|
+
SIGNIFICANT_KEY = 'significant'.freeze
|
49
|
+
TIMEOUTS_KEY = 'timeouts'.freeze
|
50
|
+
TRANSFORM_KEY = 'transform'.freeze
|
51
|
+
VARIABLES_KEY = 'variables'.freeze
|
51
52
|
|
52
53
|
# finds the value index for a recorded variable, if any.
|
53
54
|
VARIABLE_INDEX_REGEX = /\[(\d+)\]$/
|
@@ -83,6 +84,7 @@ module RightDevelop::Testing::Recording
|
|
83
84
|
end
|
84
85
|
|
85
86
|
# exceptions.
|
87
|
+
class ConfigurationError < StandardError; end
|
86
88
|
class RecordingError < StandardError; end
|
87
89
|
class PlaybackError < StandardError; end
|
88
90
|
|
@@ -142,11 +144,12 @@ module RightDevelop::Testing::Recording
|
|
142
144
|
|
143
145
|
# apply the configuration by substituting for variables in the request and
|
144
146
|
# by obfuscating wherever a variable name is nil.
|
147
|
+
erck = @effective_route_config[@kind]
|
145
148
|
case @mode
|
146
149
|
when 'validate'
|
147
|
-
#
|
150
|
+
# used to validate the fixtures before playback; no variable
|
151
|
+
# substitution should be performed.
|
148
152
|
else
|
149
|
-
erck = @effective_route_config[@kind]
|
150
153
|
if effective_variables = erck && erck[VARIABLES_KEY]
|
151
154
|
recursive_replace_variables(
|
152
155
|
[@kind, VARIABLES_KEY],
|
@@ -154,10 +157,10 @@ module RightDevelop::Testing::Recording
|
|
154
157
|
effective_variables,
|
155
158
|
erck[TRANSFORM_KEY])
|
156
159
|
end
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
160
|
+
end
|
161
|
+
if logger.debug?
|
162
|
+
logger.debug("#{@kind} effective_route_config = #{@effective_route_config[@kind].inspect}")
|
163
|
+
logger.debug("#{@kind} typenames_to_values = #{@typenames_to_values.inspect}")
|
161
164
|
end
|
162
165
|
|
163
166
|
# recreate headers and body from data using variable substitutions and
|
@@ -181,6 +184,12 @@ module RightDevelop::Testing::Recording
|
|
181
184
|
@checksum ||= compute_checksum
|
182
185
|
end
|
183
186
|
|
187
|
+
# @return [Float] delay in seconds (of response) from effective
|
188
|
+
# configuration or empty
|
189
|
+
def delay_seconds
|
190
|
+
Float((@effective_route_config[@kind] || {})[DELAY_SECONDS_KEY] || 0)
|
191
|
+
end
|
192
|
+
|
184
193
|
# @return [Hash] timeouts from effective configuration or empty
|
185
194
|
def timeouts
|
186
195
|
(@effective_route_config[@kind] || {})[TIMEOUTS_KEY] || {}
|
@@ -347,7 +356,7 @@ module RightDevelop::Testing::Recording
|
|
347
356
|
# note that we never want to fail to proxy back a response because
|
348
357
|
# the server doesn't know what JSON is; log a warning and continue.
|
349
358
|
# this actually happens with Right API 1.5 health-check saying
|
350
|
-
# response is 'application/json' but returning "ok"
|
359
|
+
# response is 'application/json' but returning "\"ok\""
|
351
360
|
logger.warn("Failed to parse JSON data from #{body.inspect}: #{e.class} #{e.message}")
|
352
361
|
end
|
353
362
|
else
|
@@ -377,10 +386,10 @@ module RightDevelop::Testing::Recording
|
|
377
386
|
when ::Hash, ::Array
|
378
387
|
body_hash = body
|
379
388
|
when ::String
|
380
|
-
|
381
|
-
|
382
|
-
|
383
|
-
return body
|
389
|
+
# use unparsed original body to avoid losing information when we are
|
390
|
+
# unable to parse or parse a literal JSON string as happens in the case
|
391
|
+
# of RightAPI's health-check.
|
392
|
+
return @body
|
384
393
|
end
|
385
394
|
case ct = compute_content_type(normalized_headers)
|
386
395
|
when 'application/x-www-form-urlencoded'
|
@@ -433,11 +442,16 @@ module RightDevelop::Testing::Recording
|
|
433
442
|
match_deep(@typenames_to_values[qualifier_type], qualifier_name_to_value)
|
434
443
|
end
|
435
444
|
if all_matched
|
445
|
+
# note that we must be careful to deep clone the existing result
|
446
|
+
# before merging as any previously-merged configuration (shared
|
447
|
+
# from the original configuration) would be modified by deep
|
448
|
+
# merging. use .deep_merge instead of .deep_merge!
|
449
|
+
#
|
436
450
|
# the final data is the union of all configurations matching
|
437
451
|
# this request path and qualifiers. the uri regex and other
|
438
452
|
# data used to match the request parameters is eliminated from
|
439
453
|
# the final configuration.
|
440
|
-
::RightSupport::Data::HashTools.deep_merge
|
454
|
+
result = ::RightSupport::Data::HashTools.deep_merge(result, configuration)
|
441
455
|
end
|
442
456
|
end
|
443
457
|
end
|
@@ -771,37 +785,15 @@ module RightDevelop::Testing::Recording
|
|
771
785
|
significant_data = RightSupport::Data::Mash.new(verb: @verb)
|
772
786
|
significant_data[:http_status] = @http_status if @http_status
|
773
787
|
|
774
|
-
#
|
775
|
-
|
776
|
-
|
777
|
-
# query
|
778
|
-
unless copy_if_significant(:query, significant, significant_data)
|
779
|
-
# entire query string is significant by default.
|
780
|
-
significant_data[:query] = @typenames_to_values[:query]
|
781
|
-
end
|
782
|
-
|
783
|
-
# body
|
784
|
-
unless copy_if_significant(:body, significant, significant_data)
|
785
|
-
case body_value = @typenames_to_values[:body]
|
786
|
-
when nil
|
787
|
-
# body is either nil, empty or was not parsable; insert the checksum
|
788
|
-
# of the original body.
|
789
|
-
case @body
|
790
|
-
when nil, '', ' '
|
791
|
-
significant_data[:body_checksum] = 'empty'
|
792
|
-
else
|
793
|
-
significant_data[:body_checksum] = ::Digest::MD5.hexdigest(@body)
|
794
|
-
end
|
795
|
-
else
|
796
|
-
# body was parsed but no single element was considered significant.
|
797
|
-
# use the parsed body so that it can be 'normalized' in sorted order.
|
798
|
-
significant_data[:body] = body_value
|
799
|
-
end
|
788
|
+
# significance by type.
|
789
|
+
[:header, :query, :body].each do |type|
|
790
|
+
copy_if_significant(type, significant, significant_data)
|
800
791
|
end
|
801
792
|
|
802
793
|
# use deep-sorted JSON to prevent random ordering changing the checksum.
|
803
794
|
checksum_data = self.class.deep_sorted_json(significant_data)
|
804
|
-
if logger.debug?
|
795
|
+
if logger.debug?
|
796
|
+
logger.debug("#{@kind} significant = #{significant.inspect}")
|
805
797
|
logger.debug("#{@kind} checksum_data = #{checksum_data.inspect}")
|
806
798
|
end
|
807
799
|
::Digest::MD5.hexdigest(checksum_data)
|
@@ -815,41 +807,138 @@ module RightDevelop::Testing::Recording
|
|
815
807
|
# @param [Hash] significant selectors
|
816
808
|
# @param [Hash] significant_data to populate
|
817
809
|
#
|
818
|
-
# @return [TrueClass
|
810
|
+
# @return [TrueClass] always true
|
819
811
|
def copy_if_significant(type, significant, significant_data)
|
820
|
-
|
821
|
-
|
822
|
-
|
823
|
-
|
812
|
+
case significant_type = significant[type]
|
813
|
+
when nil
|
814
|
+
# no explicit significance declared; use the default behavior for type.
|
815
|
+
default_copy_if_significant(type, significant_data)
|
816
|
+
when false
|
817
|
+
# no fields are significant; copy nothing.
|
818
|
+
when true
|
819
|
+
# all fields are significant; copy everything.
|
820
|
+
significant_data[type] = @typenames_to_values[type]
|
824
821
|
else
|
825
|
-
|
822
|
+
# recursively copy significant values from hash.
|
823
|
+
significant_data[type] = recursive_selective_hash_copy(
|
824
|
+
@typenames_to_values[type],
|
825
|
+
significant_type,
|
826
|
+
[type])
|
826
827
|
end
|
828
|
+
true
|
827
829
|
end
|
828
830
|
|
829
|
-
#
|
830
|
-
|
831
|
-
|
832
|
-
|
831
|
+
# Copies fields by type only if considered significant by default.
|
832
|
+
#
|
833
|
+
# @param [String|Symbol] type of significance
|
834
|
+
# @param [Hash] significant_data to populate
|
835
|
+
#
|
836
|
+
# @return [TrueClass] always true
|
837
|
+
def default_copy_if_significant(type, significant_data)
|
838
|
+
case type
|
839
|
+
when :header
|
840
|
+
# headers are insignificant by default
|
841
|
+
when :query
|
842
|
+
significant_data[:query] = @typenames_to_values[:query]
|
843
|
+
when :body
|
844
|
+
case body_value = @typenames_to_values[:body]
|
833
845
|
when nil
|
834
|
-
#
|
835
|
-
#
|
836
|
-
|
837
|
-
|
838
|
-
|
839
|
-
|
840
|
-
|
841
|
-
|
842
|
-
|
846
|
+
# body is either nil, empty or was not parsable; insert the checksum
|
847
|
+
# of the original body.
|
848
|
+
case @body
|
849
|
+
when nil, '', ' '
|
850
|
+
significant_data[:body_checksum] = 'empty'
|
851
|
+
else
|
852
|
+
significant_data[:body_checksum] = ::Digest::MD5.hexdigest(@body)
|
853
|
+
end
|
854
|
+
else
|
855
|
+
# body was parsed but no single element was considered significant.
|
856
|
+
# use the parsed body so that it can be 'normalized' in sorted order.
|
857
|
+
significant_data[:body] = body_value
|
843
858
|
end
|
859
|
+
else
|
860
|
+
raise ::NotImplementedError,
|
861
|
+
"Unexpected significant type: #{type.inspect}"
|
844
862
|
end
|
845
|
-
|
863
|
+
true
|
846
864
|
end
|
847
865
|
|
848
|
-
#
|
849
|
-
|
850
|
-
|
851
|
-
|
852
|
-
|
866
|
+
# Recursively selects values from source.
|
867
|
+
#
|
868
|
+
# @param [Object] source for selection
|
869
|
+
# @param [Object] selections to perform
|
870
|
+
# @param [Array] log_path as array of keys or indexes for logging only
|
871
|
+
#
|
872
|
+
# @return [Object] target of same type as source
|
873
|
+
#
|
874
|
+
def recursive_selective_hash_copy(source, selections, log_path)
|
875
|
+
return nil if source.nil?
|
876
|
+
result = nil
|
877
|
+
case selections
|
878
|
+
when nil, true
|
879
|
+
# hash to nil or true; nil means that user configured by using flat
|
880
|
+
# hashes instead of arrays, which is a style thing that makes the YAML
|
881
|
+
# look prettier. true means explictly consider all elements at current
|
882
|
+
# key to be significant.
|
883
|
+
result = ::RightSupport::Data::HashTools.deep_clone2(source)
|
884
|
+
when false
|
885
|
+
# explicitly declared nothing at current level to be significant.
|
886
|
+
when ::Array
|
887
|
+
# supporting special case of an array of all key names as a list of
|
888
|
+
# significant hash key/values.
|
889
|
+
if selections.all? { |item| item.is_a?(::String) || item.is_a?(::Symbol) }
|
890
|
+
# select hash values by listed keys.
|
891
|
+
unless source.kind_of?(::Hash)
|
892
|
+
msg = 'Mismatched significant qualifier with source type at ' +
|
893
|
+
"#{log_path.join('/')}: #{source.class}"
|
894
|
+
raise ::ConfigurationError, msg
|
895
|
+
end
|
896
|
+
selections.each do |k|
|
897
|
+
source_value = source[k]
|
898
|
+
unless source_value.nil?
|
899
|
+
result ||= ::RightSupport::Data::Mash.new
|
900
|
+
result[k] = ::RightSupport::Data::HashTools.deep_clone2(source_value)
|
901
|
+
end
|
902
|
+
end
|
903
|
+
else
|
904
|
+
# select specific hash elements of array with specific significance.
|
905
|
+
# if a particular element has no siginificance then its selector can
|
906
|
+
# be a literal false or else it can fall off the end of the listed
|
907
|
+
# selectors.
|
908
|
+
unless source.kind_of?(::Array)
|
909
|
+
msg = 'Mismatched significant qualifier with source type at ' +
|
910
|
+
"#{log_path.join('/')}: #{source.class}"
|
911
|
+
raise ::ConfigurationError, msg
|
912
|
+
end
|
913
|
+
selections.each_with_index do |item, idx|
|
914
|
+
if idx < source.size
|
915
|
+
result ||= []
|
916
|
+
result << recursive_selective_hash_copy(
|
917
|
+
source[idx], item, log_path + ["[#{idx}]"])
|
918
|
+
else
|
919
|
+
break
|
920
|
+
end
|
921
|
+
end
|
922
|
+
end
|
923
|
+
when ::Hash
|
924
|
+
unless source.kind_of?(::Hash)
|
925
|
+
msg = 'Mismatched significant qualifier with source type at ' +
|
926
|
+
"#{log_path.join('/')}: #{source.class}"
|
927
|
+
raise ::ConfigurationError, msg
|
928
|
+
end
|
929
|
+
selections.each do |k, v|
|
930
|
+
target = recursive_selective_hash_copy(source[k], v, log_path + [k])
|
931
|
+
unless target.nil?
|
932
|
+
result ||= ::RightSupport::Data::Mash.new
|
933
|
+
result[k] = target
|
934
|
+
end
|
935
|
+
end
|
936
|
+
result
|
937
|
+
else
|
938
|
+
raise ::ConfigurationError,
|
939
|
+
"Unexpected significant value type at #{log_path.join('/')}: #{v.class}"
|
940
|
+
end
|
941
|
+
result
|
853
942
|
end
|
854
943
|
|
855
944
|
end # Metadata
|
@@ -5,7 +5,7 @@ GEM
|
|
5
5
|
rack (1.5.2)
|
6
6
|
rest-client (1.6.7)
|
7
7
|
mime-types (>= 1.16)
|
8
|
-
right_support (2.8.
|
8
|
+
right_support (2.8.38)
|
9
9
|
|
10
10
|
PLATFORMS
|
11
11
|
ruby
|
@@ -13,4 +13,4 @@ PLATFORMS
|
|
13
13
|
DEPENDENCIES
|
14
14
|
rack
|
15
15
|
rest-client
|
16
|
-
right_support (>= 2.8.
|
16
|
+
right_support (>= 2.8.38)
|
@@ -140,16 +140,18 @@ module RightDevelop::Testing::Server::MightApi
|
|
140
140
|
# load request/response pair to validate.
|
141
141
|
request_file_path = ::File.join(requests_dir, path)
|
142
142
|
response_file_path = ::File.join(responses_dir, path)
|
143
|
+
logger.debug("Normalizing request #{request_file_path.inspect} ...")
|
143
144
|
request_data = RightSupport::Data::Mash.new(::YAML.load_file(request_file_path))
|
144
145
|
response_data = RightSupport::Data::Mash.new(::YAML.load_file(response_file_path))
|
145
146
|
|
146
147
|
# if confing contains unreachable (i.e. no available route) files
|
147
148
|
# then that is ignorable.
|
148
149
|
query_string = request_data[:query]
|
150
|
+
path_parent = ::File.dirname(path)
|
149
151
|
uri = METADATA_CLASS.normalize_uri(
|
150
152
|
URI::HTTP.build(
|
151
153
|
host: 'none',
|
152
|
-
path: (route_path +
|
154
|
+
path: path_parent == '.' ? route_path : (route_path + path_parent),
|
153
155
|
query: request_data[:query]).to_s)
|
154
156
|
|
155
157
|
# compute checksum from recorded request metadata.
|
data/right_develop.gemspec
CHANGED
@@ -2,16 +2,16 @@
|
|
2
2
|
# DO NOT EDIT THIS FILE DIRECTLY
|
3
3
|
# Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
|
4
4
|
# -*- encoding: utf-8 -*-
|
5
|
-
# stub: right_develop 3.1.
|
5
|
+
# stub: right_develop 3.1.9 ruby lib
|
6
6
|
|
7
7
|
Gem::Specification.new do |s|
|
8
8
|
s.name = "right_develop"
|
9
|
-
s.version = "3.1.
|
9
|
+
s.version = "3.1.9"
|
10
10
|
|
11
11
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
12
12
|
s.require_paths = ["lib"]
|
13
13
|
s.authors = ["Tony Spataro"]
|
14
|
-
s.date = "2014-
|
14
|
+
s.date = "2014-12-01"
|
15
15
|
s.description = "A toolkit of development tools created by RightScale."
|
16
16
|
s.email = "support@rightscale.com"
|
17
17
|
s.executables = ["right_develop"]
|
@@ -81,7 +81,7 @@ Gem::Specification.new do |s|
|
|
81
81
|
]
|
82
82
|
s.homepage = "https://github.com/rightscale/right_develop"
|
83
83
|
s.licenses = ["MIT"]
|
84
|
-
s.rubygems_version = "2.2.
|
84
|
+
s.rubygems_version = "2.2.2"
|
85
85
|
s.summary = "Reusable dev & test code."
|
86
86
|
|
87
87
|
if s.respond_to? :specification_version then
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: right_develop
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 3.1.
|
4
|
+
version: 3.1.9
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Tony Spataro
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-
|
11
|
+
date: 2014-12-08 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: right_support
|
@@ -249,7 +249,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
249
249
|
version: '0'
|
250
250
|
requirements: []
|
251
251
|
rubyforge_project:
|
252
|
-
rubygems_version: 2.2.
|
252
|
+
rubygems_version: 2.2.2
|
253
253
|
signing_key:
|
254
254
|
specification_version: 4
|
255
255
|
summary: Reusable dev & test code.
|