stackify-ruby-apm 0.9.0 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile +18 -0
- data/Gemfile.lock +181 -8
- data/LICENSE.md +66 -0
- data/README.md +5 -3
- data/Rakefile +4 -0
- data/docker-compose.yml +46 -0
- data/lib/stackify/agent.rb +22 -9
- data/lib/stackify/config.rb +65 -29
- data/lib/stackify/context/response.rb +13 -0
- data/lib/stackify/context_builder.rb +0 -2
- data/lib/stackify/error.rb +2 -2
- data/lib/stackify/error_builder.rb +1 -1
- data/lib/stackify/instrumenter.rb +4 -4
- data/lib/stackify/logger/logger_high_version.rb +65 -0
- data/lib/stackify/logger/logger_lower_version.rb +63 -0
- data/lib/stackify/middleware.rb +0 -4
- data/lib/stackify/normalizers.rb +0 -1
- data/lib/stackify/normalizers/active_record.rb +3 -1
- data/lib/stackify/railtie.rb +0 -1
- data/lib/stackify/serializers/errors.rb +8 -7
- data/lib/stackify/serializers/transactions.rb +3 -2
- data/lib/stackify/span.rb +1 -2
- data/lib/stackify/span/context.rb +5 -1
- data/lib/stackify/spies/action_dispatch.rb +8 -1
- data/lib/stackify/spies/httpclient.rb +14 -5
- data/lib/stackify/spies/httprb.rb +45 -0
- data/lib/stackify/spies/mongo.rb +13 -1
- data/lib/stackify/spies/net_http.rb +14 -3
- data/lib/stackify/spies/redis.rb +66 -0
- data/lib/stackify/spies/sinatra.rb +3 -1
- data/lib/stackify/spies/sinatra_activerecord/mysql_adapter.rb +177 -0
- data/lib/stackify/spies/sinatra_activerecord/postgresql_adapter.rb +96 -0
- data/lib/stackify/spies/sinatra_activerecord/sqlite_adapter.rb +48 -0
- data/lib/stackify/spies/tilt.rb +8 -1
- data/lib/stackify/stacktrace_builder.rb +4 -3
- data/lib/stackify/subscriber.rb +4 -4
- data/lib/stackify/trace_logger.rb +6 -23
- data/lib/stackify/transaction.rb +10 -1
- data/lib/stackify/util.rb +0 -13
- data/lib/stackify/version.rb +1 -1
- data/lib/stackify/worker.rb +5 -5
- data/lib/stackify_ruby_apm.rb +2 -6
- data/run-test.sh +75 -0
- data/stackify-ruby-apm.gemspec +0 -1
- metadata +12 -17
- data/lib/stackify/logger.rb +0 -10
@@ -0,0 +1,96 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
# Spies for active record when sinatra framework is used and active_record is being extended. (mysql adapter)
|
3
|
+
#
|
4
|
+
module StackifyRubyAPM
|
5
|
+
# @api private
|
6
|
+
module Spies
|
7
|
+
# @api private
|
8
|
+
class PostgresqlAdapterSpy
|
9
|
+
TYPE = 'db.sinatra_active_record.sql'.freeze
|
10
|
+
|
11
|
+
# rubocop:disable Metrics/MethodLength
|
12
|
+
def install
|
13
|
+
ActiveRecord::ConnectionAdapters::PostgreSQL::DatabaseStatements.class_eval do
|
14
|
+
alias exec_query_without_apm exec_query
|
15
|
+
alias exec_delete_without_apm exec_delete
|
16
|
+
alias exec_update_without_apm exec_update
|
17
|
+
|
18
|
+
def exec_update(sql, name = nil, binds = [])
|
19
|
+
result = nil
|
20
|
+
|
21
|
+
unless StackifyRubyAPM.current_transaction
|
22
|
+
exec_update_without_apm(sql, name, binds)
|
23
|
+
end
|
24
|
+
|
25
|
+
ctx = Span::Context.new(
|
26
|
+
CATEGORY: 'Database',
|
27
|
+
SUBCATEGORY: 'Execute',
|
28
|
+
COMPONENT_CATEGORY: 'DB Query',
|
29
|
+
COMPONENT_DETAIL: 'Execute SQL Query',
|
30
|
+
SQL: sql,
|
31
|
+
PROVIDER: "mysql"
|
32
|
+
)
|
33
|
+
|
34
|
+
result = exec_update_without_apm(sql, name, binds)
|
35
|
+
|
36
|
+
StackifyRubyAPM.span name, TYPE, context: ctx do
|
37
|
+
return result
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def exec_delete(sql, name = nil, binds = [])
|
42
|
+
result = nil
|
43
|
+
|
44
|
+
unless StackifyRubyAPM.current_transaction
|
45
|
+
exec_delete_without_apm(sql, name, binds)
|
46
|
+
end
|
47
|
+
|
48
|
+
ctx = Span::Context.new(
|
49
|
+
CATEGORY: 'Database',
|
50
|
+
SUBCATEGORY: 'Execute',
|
51
|
+
COMPONENT_CATEGORY: 'DB Query',
|
52
|
+
COMPONENT_DETAIL: 'Execute SQL Query',
|
53
|
+
SQL: sql,
|
54
|
+
PROVIDER: "postgresql"
|
55
|
+
)
|
56
|
+
|
57
|
+
result = exec_delete_without_apm(sql, name, binds)
|
58
|
+
|
59
|
+
StackifyRubyAPM.span name, TYPE, context: ctx do
|
60
|
+
return result
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
|
65
|
+
def exec_query(sql, name = "SQL", binds = [], prepare: false)
|
66
|
+
result = nil
|
67
|
+
|
68
|
+
unless StackifyRubyAPM.current_transaction
|
69
|
+
exec_query_without_apm(sql, name, binds)
|
70
|
+
end
|
71
|
+
|
72
|
+
ctx = Span::Context.new(
|
73
|
+
CATEGORY: 'Database',
|
74
|
+
SUBCATEGORY: 'Execute',
|
75
|
+
COMPONENT_CATEGORY: 'DB Query',
|
76
|
+
COMPONENT_DETAIL: 'Execute SQL Query',
|
77
|
+
SQL: sql,
|
78
|
+
PROVIDER: "postgresql"
|
79
|
+
)
|
80
|
+
|
81
|
+
result = exec_query_without_apm(sql, name, binds)
|
82
|
+
|
83
|
+
StackifyRubyAPM.span name, TYPE, context: ctx do
|
84
|
+
return result
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
end
|
89
|
+
end
|
90
|
+
# rubocop:enable Metrics/MethodLength
|
91
|
+
end
|
92
|
+
|
93
|
+
register 'ActiveRecord::ConnectionAdapters::PostgreSQL::DatabaseStatements', 'active_record/connection_adapters/postgresql/database_statements', PostgresqlAdapterSpy.new
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
@@ -0,0 +1,48 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
# Spies for active record when sinatra framework is used and active_record is being extended. (mysql adapter)
|
3
|
+
#
|
4
|
+
module StackifyRubyAPM
|
5
|
+
# @api private
|
6
|
+
module Spies
|
7
|
+
# @api private
|
8
|
+
class SqliteAdapterSpy
|
9
|
+
TYPE = 'db.sinatra_active_record.sql'.freeze
|
10
|
+
|
11
|
+
# rubocop:disable Metrics/MethodLength
|
12
|
+
def install
|
13
|
+
ActiveRecord::ConnectionAdapters::SQLite3Adapter.class_eval do
|
14
|
+
alias exec_query_without_apm exec_query
|
15
|
+
|
16
|
+
|
17
|
+
def exec_query(sql, name = "SQL", binds = [], prepare: false)
|
18
|
+
result = nil
|
19
|
+
|
20
|
+
unless StackifyRubyAPM.current_transaction
|
21
|
+
exec_query_without_apm(sql, name, binds)
|
22
|
+
end
|
23
|
+
|
24
|
+
ctx = Span::Context.new(
|
25
|
+
CATEGORY: 'Database',
|
26
|
+
SUBCATEGORY: 'Execute',
|
27
|
+
COMPONENT_CATEGORY: 'DB Query',
|
28
|
+
COMPONENT_DETAIL: 'Execute SQL Query',
|
29
|
+
SQL: sql,
|
30
|
+
PROVIDER: "sqlite"
|
31
|
+
)
|
32
|
+
|
33
|
+
result = exec_query_without_apm(sql, name, binds)
|
34
|
+
|
35
|
+
StackifyRubyAPM.span name, TYPE, context: ctx do
|
36
|
+
return result
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
41
|
+
end
|
42
|
+
# rubocop:enable Metrics/MethodLength
|
43
|
+
end
|
44
|
+
|
45
|
+
register 'ActiveRecord::ConnectionAdapters::SQLite3Adapter', 'active_record/connection_adapters/sqlite3_adapter', SqliteAdapterSpy.new
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
data/lib/stackify/spies/tilt.rb
CHANGED
@@ -1,11 +1,14 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
#
|
3
|
+
# Monkey patch for the Tilt::Template class on template rendering and span creation.
|
4
|
+
#
|
2
5
|
|
3
6
|
module StackifyRubyAPM
|
4
7
|
# @api private
|
5
8
|
module Spies
|
6
9
|
# @api private
|
7
10
|
class TiltSpy
|
8
|
-
|
11
|
+
|
9
12
|
TYPE = 'template.tilt'.freeze
|
10
13
|
|
11
14
|
def install
|
@@ -15,6 +18,8 @@ module StackifyRubyAPM
|
|
15
18
|
def render(*args, &block)
|
16
19
|
name = options[:__stackify_apm_template_name] || 'Unknown template'
|
17
20
|
|
21
|
+
# Creates new span for Tilt templating
|
22
|
+
#
|
18
23
|
StackifyRubyAPM.span name, TYPE do
|
19
24
|
render_without_apm(*args, &block)
|
20
25
|
end
|
@@ -23,6 +28,8 @@ module StackifyRubyAPM
|
|
23
28
|
end
|
24
29
|
end
|
25
30
|
|
31
|
+
# Registers Tilt spy, go to: /stackify/spies.rb
|
32
|
+
#
|
26
33
|
register 'Tilt::Template', 'tilt/template', TiltSpy.new
|
27
34
|
end
|
28
35
|
end
|
@@ -21,7 +21,7 @@ module StackifyRubyAPM
|
|
21
21
|
|
22
22
|
attr_reader :config
|
23
23
|
|
24
|
-
def build(backtrace, type
|
24
|
+
def build(backtrace, type)
|
25
25
|
Stacktrace.new.tap do |s|
|
26
26
|
s.frames = backtrace.map do |line|
|
27
27
|
@cache[[line, type]]
|
@@ -36,6 +36,7 @@ module StackifyRubyAPM
|
|
36
36
|
line, type = keys
|
37
37
|
abs_path, lineno, function, _module_name = parse_line(line)
|
38
38
|
current_filename = strip_load_path(abs_path)
|
39
|
+
library_frame = library_frame?(config, abs_path)
|
39
40
|
|
40
41
|
frame = Stacktrace::Frame.new
|
41
42
|
#frame.abs_path = abs_path
|
@@ -45,7 +46,7 @@ module StackifyRubyAPM
|
|
45
46
|
#frame.library_frame = library_frame?(config, abs_path)
|
46
47
|
|
47
48
|
line_count =
|
48
|
-
context_lines_for(config, type, library_frame
|
49
|
+
context_lines_for(config, type, library_frame)
|
49
50
|
frame.build_context line_count
|
50
51
|
|
51
52
|
cache[[line, type]] = frame
|
@@ -93,7 +94,7 @@ module StackifyRubyAPM
|
|
93
94
|
prefix ? path[prefix.chomp(File::SEPARATOR).length + 1..-1] : path
|
94
95
|
end
|
95
96
|
|
96
|
-
def context_lines_for(config, type, library_frame
|
97
|
+
def context_lines_for(config, type, library_frame)
|
97
98
|
key = "source_lines_#{type}_#{library_frame ? 'library' : 'app'}_frames"
|
98
99
|
config.send(key.to_sym)
|
99
100
|
end
|
data/lib/stackify/subscriber.rb
CHANGED
@@ -13,7 +13,7 @@ module StackifyRubyAPM
|
|
13
13
|
include Log
|
14
14
|
|
15
15
|
def initialize(agent)
|
16
|
-
debug '
|
16
|
+
debug '[Subscriber] initialize()'
|
17
17
|
debug agent.inspect
|
18
18
|
@agent = agent
|
19
19
|
@normalizers = Normalizers.build(agent.config)
|
@@ -38,7 +38,7 @@ module StackifyRubyAPM
|
|
38
38
|
# [call] Called when the rails version is 3.x
|
39
39
|
def call(name, started, finished, id, payload)
|
40
40
|
return unless (transaction = @agent.current_transaction)
|
41
|
-
debug '
|
41
|
+
debug '[Subscriber] call():'
|
42
42
|
debug id
|
43
43
|
debug name
|
44
44
|
debug transaction
|
@@ -71,7 +71,7 @@ module StackifyRubyAPM
|
|
71
71
|
# [start] Called when the rails version is NOT 3.x
|
72
72
|
def start(name, id, payload)
|
73
73
|
return unless (transaction = @agent.current_transaction)
|
74
|
-
debug '
|
74
|
+
debug '[Subscriber] start():'
|
75
75
|
debug id
|
76
76
|
debug name
|
77
77
|
debug transaction
|
@@ -91,7 +91,7 @@ module StackifyRubyAPM
|
|
91
91
|
# [finish] Called when the rails version is NOT 3.x
|
92
92
|
def finish(_name, id, _payload)
|
93
93
|
# debug "AS::Notification#finish:#{name}:#{id}"
|
94
|
-
debug '
|
94
|
+
debug '[Subscriber] finish():'
|
95
95
|
return unless (transaction = @agent.current_transaction)
|
96
96
|
|
97
97
|
while (notification = transaction.notifications.pop)
|
@@ -22,7 +22,7 @@ module StackifyRubyAPM
|
|
22
22
|
attr_accessor :trace_file_counter, :process_id
|
23
23
|
|
24
24
|
def post(transactions = [])
|
25
|
-
|
25
|
+
|
26
26
|
# convert transactions to json
|
27
27
|
json_traces = []
|
28
28
|
transactions.each do |transaction|
|
@@ -36,31 +36,14 @@ module StackifyRubyAPM
|
|
36
36
|
pid = $PID || Process.pid
|
37
37
|
host_name = @config.hostname || `hostname`
|
38
38
|
date_now = Time.now
|
39
|
-
|
40
|
-
trace_path = @config.log_trace_path
|
41
|
-
trace_file_result = @config.check_lastlog_needs_new(trace_path)
|
42
|
-
current_trace_file = trace_file_result['latest_file']
|
43
|
-
|
44
|
-
if trace_file_result['new_flagger'] == true
|
45
|
-
@trace_file_counter = @trace_file_counter + 1
|
46
|
-
file_ctr = @trace_file_counter
|
47
|
-
current_trace_file = trace_path + host_name + "#" + pid.to_s + "-" + file_ctr.to_s + ".log"
|
48
|
-
else
|
49
|
-
if @process_id != pid
|
50
|
-
@trace_file_counter = 1
|
51
|
-
@process_id = pid
|
52
|
-
file_ctr = @trace_file_counter
|
53
|
-
current_trace_file = trace_path + host_name + "#" + pid.to_s + "-" + file_ctr.to_s + ".log"
|
54
|
-
end
|
55
|
-
end
|
39
|
+
current_datetime = date_now.strftime("%Y-%m-%d, %H:%M:%S.%6N")
|
56
40
|
|
57
|
-
|
58
|
-
open(current_trace_file, 'a') {|f|
|
41
|
+
if(ENV['STACKIFY_RUBY_ENV'] != 'rspec')
|
59
42
|
json_traces.each do |json_trace|
|
60
|
-
|
43
|
+
update_json = current_datetime + " > " + json_trace + "\n"
|
44
|
+
@config.tracer_logger.<<(update_json)
|
61
45
|
end
|
62
|
-
|
63
|
-
|
46
|
+
end
|
64
47
|
end
|
65
48
|
end
|
66
49
|
end
|
data/lib/stackify/transaction.rb
CHANGED
@@ -24,6 +24,7 @@ module StackifyRubyAPM
|
|
24
24
|
|
25
25
|
@notifications = [] # for AS::Notifications
|
26
26
|
@context = context || Context.new
|
27
|
+
@exceptions = []
|
27
28
|
|
28
29
|
yield self if block_given?
|
29
30
|
end
|
@@ -31,7 +32,11 @@ module StackifyRubyAPM
|
|
31
32
|
|
32
33
|
attr_accessor :name, :type, :http_status
|
33
34
|
attr_reader :id, :context, :duration, :dropped_spans,
|
34
|
-
:timestamp, :spans, :result, :notifications, :instrumenter
|
35
|
+
:timestamp, :spans, :result, :notifications, :instrumenter, :exceptions
|
36
|
+
|
37
|
+
def add_exception exception
|
38
|
+
@exceptions << exception
|
39
|
+
end
|
35
40
|
|
36
41
|
def release
|
37
42
|
@instrumenter.current_transaction = nil
|
@@ -60,6 +65,10 @@ module StackifyRubyAPM
|
|
60
65
|
|
61
66
|
self
|
62
67
|
end
|
68
|
+
# This method is being used in unit testing
|
69
|
+
def running_spans
|
70
|
+
spans.select(&:running?)
|
71
|
+
end
|
63
72
|
# rubocop:disable Metrics/MethodLength
|
64
73
|
def span name, type = nil, backtrace: nil, context: nil
|
65
74
|
span = build_and_start_span(name, type, context, backtrace)
|
data/lib/stackify/util.rb
CHANGED
@@ -2,22 +2,9 @@
|
|
2
2
|
module StackifyRubyAPM
|
3
3
|
# @api private
|
4
4
|
module Util
|
5
|
-
def self.nearest_minute(target = Time.now.utc)
|
6
|
-
target - target.to_i % 60
|
7
|
-
end
|
8
|
-
|
9
5
|
def self.micros(target = Time.now.utc)
|
10
6
|
target.to_i * 1_000_000 + target.usec
|
11
7
|
end
|
12
|
-
|
13
|
-
def self.inspect_transaction(transaction)
|
14
|
-
Inspector.new.transaction transaction
|
15
|
-
end
|
16
|
-
|
17
|
-
def self.git_sha
|
18
|
-
sha = `git rev-parse --verify HEAD 2>&1`.chomp
|
19
|
-
$? && $?.success? ? sha : nil # rubocop:disable Style/SpecialGlobalVars
|
20
|
-
end
|
21
8
|
end
|
22
9
|
end
|
23
10
|
require 'stackify/util/inspector'
|
data/lib/stackify/version.rb
CHANGED
data/lib/stackify/worker.rb
CHANGED
@@ -83,13 +83,13 @@ module StackifyRubyAPM
|
|
83
83
|
def collect_and_send_transactions
|
84
84
|
return if pending_transactions.empty?
|
85
85
|
transactions = collect_batched_transactions
|
86
|
-
debug '
|
86
|
+
debug '[Worker] Successfully collect and send transaction to the to trace logger.'
|
87
87
|
begin
|
88
88
|
@trace_logger.post(transactions)
|
89
89
|
rescue ::Exception => e
|
90
|
-
|
91
|
-
|
92
|
-
|
90
|
+
error '[Worker] Collect_and_send_transactions error:'
|
91
|
+
error e.inspect
|
92
|
+
error e.backtrace.join("\n")
|
93
93
|
nil
|
94
94
|
end
|
95
95
|
end
|
@@ -98,7 +98,7 @@ module StackifyRubyAPM
|
|
98
98
|
return if pending_transactions.empty?
|
99
99
|
transactions = collect_batched_transactions
|
100
100
|
payload = @serializers.errors.build_all([msg.error])
|
101
|
-
debug '
|
101
|
+
debug '[Worker] post_error()'
|
102
102
|
# @trace_logger.post(payload, transactions[0])
|
103
103
|
end
|
104
104
|
|
data/lib/stackify_ruby_apm.rb
CHANGED
@@ -15,10 +15,10 @@
|
|
15
15
|
require 'stackify/log'
|
16
16
|
require 'stackify/version'
|
17
17
|
require 'stackify/util/dig'
|
18
|
-
|
19
18
|
require 'stackify/agent'
|
19
|
+
# Checks ruby version
|
20
|
+
require (RUBY_VERSION.to_f >= 2.4) ? 'stackify/logger/logger_high_version' : 'stackify/logger/logger_lower_version'
|
20
21
|
require 'stackify/config'
|
21
|
-
require 'stackify/logger'
|
22
22
|
require 'stackify/context'
|
23
23
|
require 'stackify/instrumenter'
|
24
24
|
require 'stackify/internal_error'
|
@@ -35,8 +35,6 @@ module StackifyRubyAPM
|
|
35
35
|
# @param config [Config] An instance of Config
|
36
36
|
# @return [Agent] The resulting [Agent]
|
37
37
|
def self.start(config = {})
|
38
|
-
# debug "Starts the StackifyRubyAPM Agent self.start()"
|
39
|
-
|
40
38
|
Agent.start config
|
41
39
|
end
|
42
40
|
|
@@ -73,7 +71,6 @@ module StackifyRubyAPM
|
|
73
71
|
# @yield [Transaction] Optional block encapsulating transaction
|
74
72
|
# @return [Transaction] Unless block given
|
75
73
|
def self.transaction(name = nil, type = nil, context: nil, &block)
|
76
|
-
# debug "@stackify_ruby [lib/stackify_ruby_apm.rb] loads self.transaction(name = nil, type = nil, context: nil, &block)"
|
77
74
|
return (block_given? ? yield : nil) unless agent
|
78
75
|
|
79
76
|
agent.transaction(name, type, context: context, &block)
|
@@ -105,7 +102,6 @@ module StackifyRubyAPM
|
|
105
102
|
# @param rack_env [Rack::Env] A Rack env
|
106
103
|
# @return [Context] The built context
|
107
104
|
def self.build_context(rack_env)
|
108
|
-
# debug "@stackify_ruby [lib/stackify_ruby_apm.rb] self.build_context(rack_env)"
|
109
105
|
agent && agent.build_context(rack_env)
|
110
106
|
end
|
111
107
|
|
data/run-test.sh
ADDED
@@ -0,0 +1,75 @@
|
|
1
|
+
#!/bin/bash
|
2
|
+
|
3
|
+
function startContainers() {
|
4
|
+
echo "Starting up containers..."
|
5
|
+
docker-compose up -d -V --remove-orphans --force-recreate
|
6
|
+
}
|
7
|
+
|
8
|
+
function waitForContainers() {
|
9
|
+
echo 'Waiting for container startup 10s...'
|
10
|
+
sleep 5
|
11
|
+
echo 'Waiting for container startup 5s...'
|
12
|
+
sleep 5
|
13
|
+
}
|
14
|
+
|
15
|
+
function stopContainers() {
|
16
|
+
echo "Stopping Containers..."
|
17
|
+
docker-compose down --remove-orphans
|
18
|
+
|
19
|
+
# delete volumes
|
20
|
+
echo "Delete Volumes..."
|
21
|
+
docker volume rm stackify-ruby-apm_postgresdata &> /dev/null
|
22
|
+
docker volume rm stackify-ruby-apm_mysqldata &> /dev/null
|
23
|
+
docker volume rm stackify-ruby-apm_mongodata &> /dev/null
|
24
|
+
docker volume rm stackify-ruby-apm_mongodata_config &> /dev/null
|
25
|
+
echo "Deleted Volumes"
|
26
|
+
}
|
27
|
+
|
28
|
+
function rspec_on_multiple_versions(){
|
29
|
+
# test against multiple ruby versions
|
30
|
+
set -e
|
31
|
+
|
32
|
+
RUBY_VERSIONS=('2.0.0-p648' '2.1.10' '2.2.10' '2.3.7' '2.4.0' '2.5.1' '2.6.0-preview3')
|
33
|
+
# BUNDLER ERROR
|
34
|
+
# '2.0.0-p648' 2.1.10
|
35
|
+
|
36
|
+
for ver in "${RUBY_VERSIONS[@]}"
|
37
|
+
do
|
38
|
+
if ! rbenv versions | grep -w $ver; then
|
39
|
+
# remove stale rbenv shim before rehashing
|
40
|
+
SHIM=/home/$USER/.rbenv/shims/.rbenv-shim
|
41
|
+
if [ -f $SHIM ]; then
|
42
|
+
rm $SHIM
|
43
|
+
fi
|
44
|
+
|
45
|
+
rbenv install --verbose $ver
|
46
|
+
rbenv rehash
|
47
|
+
rbenv local $ver
|
48
|
+
gem install bundler -v '~> 1.16'
|
49
|
+
fi
|
50
|
+
|
51
|
+
rbenv local $ver
|
52
|
+
rbenv exec bundle update
|
53
|
+
|
54
|
+
echo "====================================================="
|
55
|
+
echo "$ver: Start Test"
|
56
|
+
echo "====================================================="
|
57
|
+
|
58
|
+
if ! bundle exec rspec spec/ --format documentation --fail-fast; then
|
59
|
+
echo ">>>Unit Test Error on Version: $ver<<<"
|
60
|
+
stopContainers
|
61
|
+
exit 1
|
62
|
+
else
|
63
|
+
echo "====================================================="
|
64
|
+
echo "$ver: End Test"
|
65
|
+
echo "====================================================="
|
66
|
+
fi
|
67
|
+
done
|
68
|
+
}
|
69
|
+
|
70
|
+
|
71
|
+
startContainers
|
72
|
+
waitForContainers
|
73
|
+
|
74
|
+
rspec_on_multiple_versions
|
75
|
+
stopContainers
|