ruby_ci 0.2.5 → 0.2.7

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: deccb17205a9125cad4257da4d460cdcc1a254b38259a434813437f17e5ba1e8
4
- data.tar.gz: 96457b78c8cdc5573e998ae65260c850dc2d1385fe21ae6f70592076d6efe728
3
+ metadata.gz: 2441626a4b8a03996716c6932e0914bb851eebd62a39b8ce2c8e5282f3abe906
4
+ data.tar.gz: 2942c029042f0a38d533b8410e280e0fc94cf18b9a8871012f3a5d5328a0f44d
5
5
  SHA512:
6
- metadata.gz: 54b2a36f99862e51470b1ca379da26fb993ea13308418417407bb52210230d18467b9873ba6965c9343422c22811794ed3873186ab496f8fbbbc75941f78c420
7
- data.tar.gz: c28f203e0a2d7756544aa4085c10823ce290d43bee1b73923997f8aae53a8a62c200282f7ea66ef016698ffd60949c0ddb3a4107d7a924322b05248dbcbe5084
6
+ metadata.gz: b2bb8f6a266af27120f648ed3a3225d117a4abea4e0ac1ca5f9453a18389ce388f292aa71bbc2349c7252253d732a07855b37a9751fe28475913973f4a63e5ea
7
+ data.tar.gz: b1a433532873916bfe8b0beef1f5e953a77bc69ed143a6bac1e5c018d1c26724f6aa5eed42b39d9334806ab9eeddcd0532210629577ed461022afa865c9d8c6e
@@ -1,5 +1,28 @@
1
1
  module Minitest
2
2
  module Reporters
3
+ class Suite
4
+ attr_reader :name
5
+ def initialize(name)
6
+ @name = name
7
+ end
8
+
9
+ def ==(other)
10
+ name == other.name
11
+ end
12
+
13
+ def eql?(other)
14
+ self == other
15
+ end
16
+
17
+ def hash
18
+ name.hash
19
+ end
20
+
21
+ def to_s
22
+ name.to_s
23
+ end
24
+ end
25
+
3
26
  class RubyciReporter
4
27
  attr_accessor :tests, :test_results, :ids
5
28
 
@@ -7,16 +30,40 @@ module Minitest
7
30
  @tests = {}
8
31
  @test_results = {}
9
32
  @ids = {}
33
+ @events = []
10
34
 
11
- RubyCI.minitest_ws.on(:enq_request) do
12
- tests
13
- end
35
+ $stdout = StringIO.new()
14
36
 
15
- RubyCI.minitest_ws.on(:deq) do |api_tests|
16
- test_results
37
+ if ENV['RBCI_REMOTE_TESTS'] != 'true'
38
+ RubyCI.minitest_ws.on(:enq_request) do
39
+ tests
40
+ end
41
+
42
+ RubyCI.minitest_ws.on(:deq) do |api_tests|
43
+ test_results
44
+ end
17
45
  end
18
46
  end
19
47
 
48
+ def start
49
+ test_count = Runnable.runnables.sum { |s| s.runnable_methods.count }
50
+ msg('start', { test_count: test_count })
51
+ end
52
+
53
+ def get_output
54
+ return if $stdout.pos == 0
55
+ $stdout.rewind
56
+ res = $stdout.read
57
+ $stdout.flush
58
+ $stdout.rewind
59
+ return unless res
60
+ res.strip.chomp if res.strip.chomp != ""
61
+ end
62
+
63
+ def before_test(test)
64
+ $stdout = StringIO.new()
65
+ end
66
+
20
67
  def prerecord(klass, name)
21
68
  description = test_description(name)
22
69
  path = test_path(klass.name)
@@ -36,6 +83,7 @@ module Minitest
36
83
  end
37
84
 
38
85
  def record(result)
86
+ test_finished(result)
39
87
  description = test_description(result.name)
40
88
  id = ids[description]
41
89
  path = test_path(result.klass)
@@ -61,15 +109,133 @@ module Minitest
61
109
  test_results[path][:file_status] = file_status
62
110
  end
63
111
 
64
- RubyCI.minitest_await
112
+
113
+ if ENV['RBCI_REMOTE_TESTS'] == 'true'
114
+ send_events
115
+ else
116
+ RubyCI.minitest_await
117
+ end
65
118
  end
66
119
 
67
120
  def method_missing(method, *args)
68
121
  return
69
122
  end
123
+
124
+ protected
125
+
126
+ def before_suite(suite)
127
+ end
128
+
129
+ def after_suite(_suite)
130
+ end
131
+
132
+ def record_print_status(test)
133
+ test_name = test.name.gsub(/^test_: /, "test:")
134
+ print pad_test(test_name)
135
+ print_colored_status(test)
136
+ print(" (%.2fs)" % test.time) unless test.time.nil?
137
+ puts
138
+ end
139
+
140
+ def record_print_failures_if_any(test)
141
+ if !test.skipped? && test.failure
142
+ print_info(test.failure, test.error?)
143
+ puts
144
+ end
145
+ end
146
+
147
+ def screenshots_base64(output)
148
+ return unless output
149
+ img_path = output&.scan(/\\[Screenshot Image\\]: (.*)$/)&.flatten&.first&.strip&.chomp ||
150
+ output&.scan(/\\[Screenshot\\]: (.*)$/)&.flatten&.first&.strip&.chomp
151
+
152
+ if img_path && File.exist?(img_path)
153
+ STDOUT.puts "SCREENSHOT!"
154
+ Base64.strict_encode64(File.read(img_path))
155
+ end
156
+ end
157
+
158
+ def test_finished(test)
159
+ output = get_output
160
+
161
+ location = if !test.source_location.join(":").start_with?(::Rails.root.join('vendor').to_s)
162
+ test.source_location.join(":")
163
+ else
164
+ if (file = `cat #{::Rails.root.join('vendor', 'bundle', 'minitest_cache_file').to_s} | grep "#{test.klass} => "`.split(" => ").last&.chomp)
165
+ file + ":"
166
+ else
167
+ file = `grep -rw "#{::Rails.root.to_s}" -e "#{test.klass} "`.split(":").first
168
+ `echo "#{test.klass} => #{file}" >> #{::Rails.root.join('vendor', 'bundle', 'minitest_cache_file').to_s}`
169
+ file + ":"
170
+ end
171
+ end
172
+
173
+ fully_formatted = if test.failure
174
+ fully_formatted = "\n" + test.failure.message.split("\n").first
175
+
176
+ test.failure.backtrace.each do |l|
177
+ if !l["/cache/"]
178
+ fully_formatted << "\n " + cyan + l + "\033[0m"
179
+ end
180
+ end
181
+
182
+ fully_formatted
183
+ end
184
+
185
+ output_inside = output&.split("\n")&.select do |line|
186
+ !line["Screenshot"]
187
+ end&.join("\n")
188
+ event_data = {
189
+ test_class: Suite.new(test.klass),
190
+ test_name: test.name.gsub(/^test_\\d*/, "").gsub(/^test_: /, "test:").gsub(/^_/, "").strip,
191
+ assertions_count: test.assertions,
192
+ location: location,
193
+ status: status(test),
194
+ run_time: test.time,
195
+ fully_formatted: fully_formatted,
196
+ output_inside: output_inside,
197
+ screenshots_base64: [screenshots_base64(output)]
198
+ }
199
+
200
+ msg('test_finished', event_data)
201
+ if ENV['RBCI_REMOTE_TESTS'] == 'true'
202
+ send_events if @events.length >= 10
203
+ end
204
+ end
205
+
206
+ def status(test)
207
+ if test.passed?
208
+ "passed"
209
+ elsif test.error?
210
+ "error"
211
+ elsif test.skipped?
212
+ "skipped"
213
+ elsif test.failure
214
+ "failed"
215
+ else
216
+ raise("Status not found")
217
+ end
218
+ end
70
219
 
71
220
  private
72
221
 
222
+ def msg(event, data)
223
+ @events << ["minitest_#{event}".upcase, data]
224
+ end
225
+
226
+ def send_events
227
+ return unless @events.length > 0
228
+
229
+ json_events = {
230
+ build_id: RubyCI.configuration.orig_build_id,
231
+ compressed_data: Base64.strict_encode64(Zlib::Deflate.deflate(JSON.fast_generate(@events), 9)),
232
+ }
233
+
234
+ RubyCI.send_events(json_events)
235
+
236
+ @events = []
237
+ end
238
+
73
239
  def test_description(name)
74
240
  test_name = name.split('test_').last
75
241
  test_name = test_name[2..-1] if test_name.starts_with?(': ')
@@ -6,11 +6,25 @@ require 'zlib'
6
6
  module RubyCI
7
7
  module Brakeman
8
8
  def self.start
9
+ events = []
10
+ events << ['brakeman_run'.upcase, {}]
9
11
  RubyCI::Brakeman::Commandline.start(output_files: ['tmp/brakeman.json'], ensure_ignore_notes: false)
10
12
 
11
13
  content = File.read('tmp/brakeman.json')
12
14
  compressed_data = ::Base64.strict_encode64(Zlib::Deflate.deflate(content, 9))
13
- RubyCI.report_brakeman(compressed_data, 'passed')
15
+
16
+ events << ['brakeman_exit_status'.upcase, ['0', { exitstatus: 0, stderr: '', output: '', compressed_data: compressed_data ]]
17
+
18
+ if ENV['RBCI_REMOTE_TESTS'] == 'true'
19
+ json_events = {
20
+ build_id: RubyCI.configuration.orig_build_id,
21
+ compressed_data: Base64.strict_encode64(Zlib::Deflate.deflate(JSON.fast_generate(events), 9)),
22
+ }
23
+
24
+ RubyCI.send_events(json_events)
25
+ else
26
+ RubyCI.report_brakeman(compressed_data, 'passed')
27
+ end
14
28
  end
15
29
  end
16
30
  end
@@ -3,7 +3,7 @@
3
3
  module RubyCI
4
4
  class Configuration
5
5
  attr_accessor :run_key, :build_id, :commit_msg, :commit, :branch,
6
- :api_url, :secret_key, :author
6
+ :api_url, :secret_key, :author, :rubyci_main_url, :rubyci_api_url, :orig_build_id
7
7
 
8
8
  def initialize
9
9
  # Settings defaults
@@ -15,6 +15,9 @@ module RubyCI
15
15
  self.api_url = ENV["RUBY_CI_API_URL"] || "api.fast.ci"
16
16
  self.secret_key = ENV.fetch("RUBY_CI_SECRET_KEY")
17
17
  self.author = guess_author
18
+ self.rubyci_main_url = ENV.fetch('RUBYCI_MAIN_URL', 'https://events.ruby.ci')
19
+ self.rubyci_api_url = ENV.fetch('RUBYCI_API_RB_URL', 'https://fast.ruby.ci')
20
+ self.orig_build_id = ENV['RBCI_ORIG_BUILD_ID']
18
21
  end
19
22
 
20
23
  def reset
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+ require_relative "rspec_formatter"
3
+ require_relative "extract_definitions"
4
+
5
+ module RubyCI
6
+ module DryrunRunnerPrepend
7
+ def run(err, out)
8
+ @rspec_started_at = Time.now
9
+ super
10
+ end
11
+
12
+ def exit_code(examples_passed=false)
13
+ run_time = Time.now - (@rspec_started_at || 1.second.ago)
14
+ events = @world.non_example_failure ? [['RSPEC_DRYRUN', { failed_after: run_time, test_env_number: ENV["TEST_ENV_NUMBER"], data: 'error' }]] : [['RSPEC_DRYRUN', { succeed_after: run_time, test_env_number: ENV["TEST_ENV_NUMBER"] }]]
15
+ STDOUT.puts events.inspect
16
+ json_events = {
17
+ build_id: RubyCI.configuration.orig_build_id,
18
+ compressed_data: Base64.strict_encode64(Zlib::Deflate.deflate(JSON.fast_generate(events), 9)),
19
+ }
20
+ RubyCI.send_events(json_events)
21
+
22
+ return @configuration.error_exit_code || @configuration.failure_exit_code if @world.non_example_failure
23
+ return @configuration.failure_exit_code unless examples_passed
24
+
25
+ 0
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,113 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RubyCI
4
+ class RspecDryrunFormatter
5
+ RSpec::Core::Formatters.register self,
6
+ :start,
7
+ :message,
8
+ :example_passed,
9
+ :example_failed,
10
+ :example_pending,
11
+ :example_group_finished,
12
+ :example_group_started,
13
+ :dump_summary,
14
+ :close
15
+
16
+ def initialize(output)
17
+ @output = output
18
+ @current_group_path = []
19
+ @current_file = nil
20
+ @current_file_count = 0
21
+ @events = []
22
+ end
23
+
24
+ def message(message_notification)
25
+ @output.print message_notification.message
26
+ @output.print "\n"
27
+ end
28
+
29
+ def start(example_count)
30
+ msg(:start, { "example_count" => example_count.count, "timestamp" => time_now })
31
+ end
32
+
33
+ def close(*args)
34
+ msg(:close, { "timestamp" => time_now })
35
+ send_events
36
+ end
37
+
38
+ def dump_summary(summary_notification)
39
+ end
40
+
41
+ def time_now
42
+ time_frozen? ? Timecop.return { Time.now } : Time.now
43
+ end
44
+
45
+ def time_frozen?
46
+ return unless defined?(Timecop)
47
+ Timecop.frozen?
48
+ end
49
+
50
+ def example_passed(example_notification)
51
+ example_finished(example_notification)
52
+ @output.print RSpec::Core::Formatters::ConsoleCodes.wrap('.', :success)
53
+ end
54
+
55
+ def example_failed(example_notification)
56
+ example_finished(example_notification)
57
+ @output.print RSpec::Core::Formatters::ConsoleCodes.wrap('F', :failure)
58
+ end
59
+
60
+ def example_pending(example_notification)
61
+ example_finished(example_notification)
62
+ @output.print RSpec::Core::Formatters::ConsoleCodes.wrap('*', :pending)
63
+ end
64
+
65
+ def start_dump(_notification)
66
+ @output.print "\n"
67
+ end
68
+
69
+ def example_group_finished(_group_notification)
70
+ @current_group_path.pop
71
+ if @current_group_path.empty? # its a file
72
+ msg(:file_examples_count, [@current_file, @current_file_count])
73
+ @current_file_count = 0
74
+ @current_file = nil
75
+ end
76
+ end
77
+
78
+ def example_group_started(group_notification)
79
+ if @current_group_path.size == 0
80
+ @current_file = group_notification.group.metadata[:file_path].gsub("./".freeze, "".freeze)
81
+ @current_file_count = 0
82
+ end
83
+ @current_group_path << 1
84
+ end
85
+
86
+ private
87
+
88
+ def example_finished(example_notification)
89
+ @current_file_count += 1
90
+ end
91
+
92
+ def send_events
93
+ return unless @events.length > 0
94
+
95
+ json_events = {
96
+ build_id: RubyCI.configuration.orig_build_id,
97
+ compressed_data: Base64.strict_encode64(Zlib::Deflate.deflate(JSON.fast_generate(@events), 9)),
98
+ }
99
+
100
+ RubyCI.send_events(json_events)
101
+
102
+ @events = []
103
+ end
104
+
105
+ def msg(event, data)
106
+ @events << ["rspec_dryrun_#{event}".upcase, ['0', data]]
107
+ end
108
+
109
+ def get_scope_id(metadata)
110
+ metadata[:scoped_id].split(":").last || raise("No scoped id")
111
+ end
112
+ end
113
+ end
@@ -4,9 +4,57 @@ module RubyCI
4
4
  class RspecFormatter
5
5
  attr_reader :current_test_key
6
6
 
7
- def initialize
8
- @output = {}
7
+ def initialize(output)
8
+ @output = output
9
+ @event_output = {}
9
10
  @is_failed = false
11
+ @current_path = []
12
+ @current_path_started_at = []
13
+ @max_heap_live_num = 0
14
+ @dup_stdout = STDOUT.clone
15
+ @events = []
16
+
17
+ $stdout = StringIO.new()
18
+
19
+ @log_thread = Thread.new do
20
+ loop do
21
+ sleep 10
22
+ check_heap_live_num
23
+ @should_send_events = true
24
+ end
25
+ end
26
+ end
27
+
28
+ def time_now
29
+ time_frozen? ? Timecop.return { Time.now } : Time.now
30
+ end
31
+
32
+ def time_frozen?
33
+ return unless defined?(Timecop)
34
+ Timecop.frozen?
35
+ end
36
+
37
+ def rspec_runner_index
38
+ ENV["TEST_ENV_NUMBER"]
39
+ end
40
+
41
+ def send_events
42
+ @should_send_events = false
43
+
44
+ if @events.length > 0
45
+ json_events = {
46
+ build_id: RubyCI.configuration.orig_build_id,
47
+ compressed_data: Base64.strict_encode64(Zlib::Deflate.deflate(JSON.fast_generate(@events), 9)),
48
+ }
49
+
50
+ RubyCI.send_events(json_events)
51
+
52
+ @events = []
53
+ end
54
+ end
55
+
56
+ def check_heap_live_num
57
+ @max_heap_live_num = [@max_heap_live_num, GC.stat[:heap_live_slots] || GC.stat[:heap_live_num]].max
10
58
  end
11
59
 
12
60
  def passed?
@@ -17,13 +65,100 @@ module RubyCI
17
65
  @current_test_key = value
18
66
  end
19
67
 
68
+ def start(start_notification)
69
+ # $stderr = $stdout
70
+
71
+ data = {
72
+ load_time: start_notification.load_time,
73
+ example_count: start_notification.count,
74
+ started_at: time_now.to_s
75
+ }
76
+
77
+ return if running_only_failed? ||
78
+ running_gem_or_engine? ||
79
+ ENV["EXTRA_SLOWER_RUN"]
80
+
81
+ msg(:start, data)
82
+ end
83
+
84
+ def close(null_notification)
85
+ # check_heap_live_num
86
+ msg(:gc_stat, GC.stat.merge(max_heap_live_num: @max_heap_live_num))
87
+ unless running_only_failed? || ENV["EXTRA_SLOWER_RUN"] || running_gem_or_engine?
88
+ msg(:close, {final_output: get_output})
89
+ end
90
+ send_events
91
+ $stdout = @dup_stdout
92
+ end
93
+
94
+ def example_group_started(group_notification)
95
+ metadata = group_notification.group.metadata
96
+ @current_path_started_at << time_now
97
+
98
+ if @current_path.size == 0
99
+ @example_failed_index = 0
100
+ file_path = metadata[:file_path].gsub("./".freeze, "".freeze)
101
+ file_path = [ENV["DIR_PREFIX"], file_path].join("/") if ENV["DIR_PREFIX"]
102
+ @current_path << file_path
103
+ end
104
+
105
+ @current_path << id(metadata)
106
+
107
+ msg(:group_started, [
108
+ path_with_file(group_notification.group),
109
+ {
110
+ line_number: metadata[:line_number],
111
+ description: metadata[:description],
112
+ }
113
+ ])
114
+ end
115
+
116
+ def example_started(example_notification)
117
+ @output_before = get_output
118
+ end
119
+
120
+ def example_passed(example_notification)
121
+ metadata = example_notification.example.metadata
122
+ broadcast_example_finished(serialize_example(metadata, "passed".freeze), example_notification.example)
123
+ end
124
+
125
+ def example_failed(example_notification)
126
+ @example_failed_index += 1
127
+ metadata = example_notification.example.metadata
128
+ fully_formatted = example_notification.fully_formatted(@example_failed_index, ::RSpec::Core::Formatters::ConsoleCodes)
129
+
130
+ broadcast_example_finished(
131
+ serialize_example(metadata, "failed".freeze, fully_formatted),
132
+ example_notification.example
133
+ )
134
+ end
135
+
136
+ def example_pending(example_notification)
137
+ metadata = example_notification.example.metadata
138
+ broadcast_example_finished(
139
+ serialize_example(metadata, "pending".freeze),
140
+ example_notification.example
141
+ )
142
+ end
143
+
144
+ def example_group_finished(group_notification)
145
+ run_time = time_now - @current_path_started_at.pop
146
+ if (run_time < 0) || (run_time > 2400)
147
+ run_time = 0.525
148
+ end
149
+ msg(:group_finished, [path_with_file(group_notification.group), {run_time: run_time}])
150
+ # msg(:group_finished, [@current_path.map(&:to_s), {run_time: run_time}])
151
+ @current_path.pop
152
+ @current_path.pop if @current_path.size == 1 # Remove the file_path at the beggining
153
+ end
154
+
20
155
  def example_finished(notification)
21
156
  example = notification.example
22
157
  metadata = example.metadata
23
158
 
24
159
  *example_group_ids, example_id = metadata[:scoped_id].split(":")
25
160
 
26
- file_output = @output[current_test_key] ||= {}
161
+ file_output = @event_output[current_test_key] ||= {}
27
162
 
28
163
  example_group = example_group_ids.reduce(file_output) do |output, scope_id|
29
164
  output[scope_id] ||= {}
@@ -49,9 +184,91 @@ module RubyCI
49
184
  end
50
185
 
51
186
  def dump_and_reset
52
- output = @output
53
- @output = {}
54
- output
187
+ event_output = @event_output
188
+ @event_output = {}
189
+ event_output
190
+ end
191
+
192
+ def path_with_file(group)
193
+ file_path = group.parent_groups.last.file_path.gsub("./".freeze, "".freeze)
194
+
195
+ group.metadata[:scoped_id].split(":").unshift(file_path)
196
+ end
197
+
198
+ private
199
+
200
+ def running_gem_or_engine?
201
+ !!ENV["DIR_PREFIX"]
202
+ end
203
+
204
+ def running_only_failed?
205
+ !!ENV["RERUN_FAILED_FILES"]
206
+ end
207
+
208
+ def serialize_example(metadata, status, fully_formatted = nil)
209
+ run_time = metadata[:execution_result].run_time
210
+ if (run_time < 0) || (run_time > 2400)
211
+ run_time = 0.525
212
+ end
213
+
214
+ result = {
215
+ id: id(metadata),
216
+ status: status,
217
+ line_number: metadata[:line_number].to_s,
218
+ description: metadata[:description],
219
+ run_time: run_time,
220
+ fully_formatted: fully_formatted,
221
+ scoped_id: metadata[:scoped_id],
222
+ }.compact
223
+
224
+ result[:gem_or_engine] = true if running_gem_or_engine?
225
+
226
+ if running_only_failed?
227
+ result[:reruned] = true
228
+ elsif status == "failed" && !running_gem_or_engine?
229
+ File.write('tmp/rspec_failures', "#{@current_path.first}[#{metadata[:scoped_id]}]", mode: 'a+')
230
+ end
231
+
232
+ if status == "failed"
233
+ img_path = metadata.dig(:screenshot, :image) ||
234
+ fully_formatted&.scan(/\[Screenshot Image\]: (.*)$/).flatten.first&.strip&.chomp ||
235
+ fully_formatted&.scan(/\[Screenshot\]: (.*)$/).flatten.first&.strip&.chomp
236
+
237
+ if img_path && File.exist?(img_path)
238
+ STDOUT.puts "SCREENSHOT!"
239
+ result[:screenshots_base64] ||= []
240
+ result[:screenshots_base64] << Base64.strict_encode64(File.read(img_path))
241
+ end
242
+ end
243
+ @last_example_finished_at = time_now
244
+ # TODO annalyze this: run_time: metadata[:execution_result].run_time,
245
+ result
246
+ end
247
+
248
+ def msg(event, data)
249
+ @events << ["rspec_#{event}".upcase, [rspec_runner_index, data]]
250
+ end
251
+
252
+ def id(metadata)
253
+ metadata[:scoped_id].split(":").last || raise("No scoped id")
254
+ end
255
+
256
+ def broadcast_example_finished(data, example)
257
+ msg(:example_finished, [
258
+ path_with_file(example.example_group),
259
+ data.merge(output_inside: get_output, output_before: @output_before)
260
+ ])
261
+
262
+ send_events if @should_send_events
263
+ end
264
+
265
+ def get_output
266
+ return if $stdout.pos == 0
267
+ $stdout.rewind
268
+ res = $stdout.read
269
+ $stdout.flush
270
+ $stdout.rewind
271
+ res
55
272
  end
56
273
  end
57
274
  end
@@ -10,6 +10,8 @@ module RubyCI
10
10
  module Cli
11
11
  class Application < ::RubyCritic::Cli::Application
12
12
  def execute
13
+ events = []
14
+ events << ['ruby_critic_run'.upcase, {}]
13
15
  status = super
14
16
 
15
17
  content = File.read('tmp/rubycritic/report.json')
@@ -29,8 +31,18 @@ module RubyCI
29
31
  end
30
32
 
31
33
  compressed_data = ::Base64.strict_encode64(Zlib::Deflate.deflate(report.to_json, 9))
32
- RubyCI.report_ruby_critic(compressed_data, 'passed')
34
+ events << ['ruby_critic_exit_status'.upcase, { exitstatus: status, output: '', compressed_data: compressed_data }]
33
35
 
36
+ if ENV['RBCI_REMOTE_TESTS'] == 'true'
37
+ json_events = {
38
+ build_id: RubyCI.configuration.orig_build_id,
39
+ compressed_data: Base64.strict_encode64(Zlib::Deflate.deflate(JSON.fast_generate(events), 9)),
40
+ }
41
+
42
+ RubyCI.send_events(json_events)
43
+ else
44
+ RubyCI.report_ruby_critic(compressed_data, 'passed')
45
+ end
34
46
  return status
35
47
  end
36
48
  end
@@ -5,6 +5,13 @@ require_relative "extract_definitions"
5
5
  module RubyCI
6
6
  module RunnerPrepend
7
7
  def run_specs(example_groups)
8
+ @rspec_started_at = Time.now
9
+ json_events = {
10
+ build_id: RubyCI.configuration.orig_build_id,
11
+ compressed_data: Base64.strict_encode64(Zlib::Deflate.deflate(JSON.fast_generate([['RSPEC_RUN', { started_at: @rspec_started_at, test_env_number: ENV["TEST_ENV_NUMBER"] }]]), 9)),
12
+ }
13
+ RubyCI.send_events(json_events)
14
+
8
15
  examples_count = @world.example_count(example_groups)
9
16
 
10
17
  example_groups = example_groups.reduce({}) do |acc, ex_group|
@@ -43,9 +50,19 @@ module RubyCI
43
50
  return @configuration.failure_exit_code
44
51
  end
45
52
 
46
- formatter = RubyCI::RspecFormatter.new
53
+ formatter = RubyCI::RspecFormatter.new(STDOUT)
47
54
 
48
55
  reporter.register_listener(formatter, :example_finished)
56
+ if ENV['RBCI_REMOTE_TESTS'] == 'true'
57
+ reporter.register_listener(formatter, :start)
58
+ reporter.register_listener(formatter, :example_group_started)
59
+ reporter.register_listener(formatter, :example_started)
60
+ reporter.register_listener(formatter, :example_passed)
61
+ reporter.register_listener(formatter, :example_failed)
62
+ reporter.register_listener(formatter, :example_pending)
63
+ reporter.register_listener(formatter, :example_group_finished)
64
+ reporter.register_listener(formatter, :close)
65
+ end
49
66
 
50
67
  RubyCI.rspec_ws.on(:deq) do |tests|
51
68
  tests.each do |test|
@@ -71,6 +88,14 @@ module RubyCI
71
88
  end
72
89
 
73
90
  def exit_code(examples_passed=false)
91
+ run_time = Time.now - (@rspec_started_at || 1.second.ago)
92
+ events = @world.non_example_failure ? [['RSPEC_RUN', { failed_after: run_time, test_env_number: ENV["TEST_ENV_NUMBER"] }]] : [['RSPEC_RUN', { succeed_after: run_time, test_env_number: ENV["TEST_ENV_NUMBER"] }]]
93
+ json_events = {
94
+ build_id: RubyCI.configuration.orig_build_id,
95
+ compressed_data: Base64.strict_encode64(Zlib::Deflate.deflate(JSON.fast_generate(events), 9)),
96
+ }
97
+ RubyCI.send_events(json_events)
98
+
74
99
  return @configuration.error_exit_code || @configuration.failure_exit_code if @world.non_example_failure
75
100
  return @configuration.failure_exit_code unless examples_passed
76
101
 
@@ -2,6 +2,67 @@ require_relative "simple_cov/reporting"
2
2
 
3
3
  module RubyCI
4
4
  module SimpleCov
5
- ::SimpleCov.send(:include, RubyCI::SimpleCov::Reporting)
5
+ if ENV['RBCI_REMOTE_TESTS'] == 'true' && ENV["SIMPLECOV_ACTIVE"] && ENV['DRYRUN'] != 'true'
6
+ ::SimpleCov.send(:at_exit) do
7
+ ::SimpleCov.result.format!
8
+
9
+ config = {
10
+ minimum_coverage: ::SimpleCov.minimum_coverage,
11
+ maximum_coverage_drop: ::SimpleCov.maximum_coverage_drop,
12
+ minimum_coverage_by_file: ::SimpleCov.minimum_coverage_by_file,
13
+ }
14
+ rspec_runner_index = ENV["TEST_ENV_NUMBER".freeze].to_i
15
+ events = [['simplecov_config'.upcase, [ rspec_runner_index, config ]]]
16
+
17
+ json_events = {
18
+ build_id: RubyCI.configuration.orig_build_id,
19
+ compressed_data: Base64.strict_encode64(Zlib::Deflate.deflate(JSON.fast_generate(events), 9)),
20
+ }
21
+
22
+ RubyCI.send_events(json_events)
23
+ end
24
+
25
+ module PrependSc
26
+ def start(*args, &block)
27
+ add_filter "tmp"
28
+ merge_timeout 3600
29
+ command_name "RSpec_#{ENV["TEST_ENV_NUMBER".freeze].to_i}"
30
+
31
+ if ENV["NO_COVERAGE"]
32
+ use_merging false
33
+ return
34
+ end
35
+ super
36
+ end
37
+ end
38
+ ::SimpleCov.singleton_class.prepend(PrependSc)
39
+
40
+ module Scf
41
+ def format!
42
+ return if ENV["NO_COVERAGE"]
43
+ rspec_runner_index = ENV["TEST_ENV_NUMBER".freeze].to_i
44
+
45
+ original_result_json = if ENV['CI_PROJECT_DIR'].present?
46
+ JSON.fast_generate(original_result.transform_keys {|key| key.sub(ENV['CI_PROJECT_DIR'], '/app') })
47
+ else
48
+ JSON.fast_generate(original_result)
49
+ end
50
+ compressed_data = Base64.strict_encode64(Zlib::Deflate.deflate(original_result_json, 9))
51
+ events = [['simplecov_result'.upcase, [ rspec_runner_index, compressed_data ]]]
52
+
53
+ json_events = {
54
+ build_id: RubyCI.configuration.orig_build_id,
55
+ compressed_data: Base64.strict_encode64(Zlib::Deflate.deflate(JSON.fast_generate(events), 9)),
56
+ }
57
+
58
+ RubyCI.send_events(json_events)
59
+ super
60
+ end
61
+ end
62
+
63
+ ::SimpleCov::Result.prepend(Scf)
64
+ else
65
+ ::SimpleCov.send(:include, RubyCI::SimpleCov::Reporting) unless ENV['DRYRUN'] == 'true'
66
+ end
6
67
  end
7
68
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module RubyCI
4
- VERSION = "0.2.5"
4
+ VERSION = "0.2.7"
5
5
  end
data/lib/ruby_ci.rb CHANGED
@@ -67,7 +67,12 @@ module RubyCI
67
67
  end
68
68
 
69
69
  def post_report(data)
70
- uri = URI('https://fast.ruby.ci/api/runs')
70
+ uri = URI("#{RubyCI.configuration.rubyci_api_url}/api/runs")
71
+ res = Net::HTTP.post_form(uri, data)
72
+ end
73
+
74
+ def send_events(data)
75
+ uri = URI("#{RubyCI.configuration.rubyci_main_url}/api/v1/gitlab_events")
71
76
  res = Net::HTTP.post_form(uri, data)
72
77
  end
73
78
  end
@@ -142,6 +147,9 @@ module RubyCI
142
147
  else
143
148
  puts response
144
149
  end
150
+ rescue => e
151
+ puts e.message
152
+ puts e.backtrace.join("\n")
145
153
  end
146
154
  end
147
155
  end
data/ruby_ci.gemspec CHANGED
@@ -30,5 +30,6 @@ Gem::Specification.new do |spec|
30
30
  spec.add_dependency "async-websocket", '<= 0.20.0'
31
31
  spec.add_dependency "rubycritic", "~> 4.8.0"
32
32
  spec.add_dependency "brakeman", "~> 5.4.1"
33
+ spec.add_dependency "minitest-rails", ">= 5.1"
33
34
  spec.add_development_dependency "pry"
34
35
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ruby_ci
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.5
4
+ version: 0.2.7
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ale ∴
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-02-29 00:00:00.000000000 Z
11
+ date: 2024-07-30 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: console
@@ -66,6 +66,20 @@ dependencies:
66
66
  - - "~>"
67
67
  - !ruby/object:Gem::Version
68
68
  version: 5.4.1
69
+ - !ruby/object:Gem::Dependency
70
+ name: minitest-rails
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '5.1'
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '5.1'
69
83
  - !ruby/object:Gem::Dependency
70
84
  name: pry
71
85
  requirement: !ruby/object:Gem::Requirement
@@ -109,8 +123,10 @@ files:
109
123
  - lib/ruby_ci/brakeman.rb
110
124
  - lib/ruby_ci/brakeman/commandline.rb
111
125
  - lib/ruby_ci/configuration.rb
126
+ - lib/ruby_ci/dryrun_runner_prepend.rb
112
127
  - lib/ruby_ci/exceptions.rb
113
128
  - lib/ruby_ci/extract_definitions.rb
129
+ - lib/ruby_ci/rspec_dryrun_formatter.rb
114
130
  - lib/ruby_ci/rspec_formatter.rb
115
131
  - lib/ruby_ci/ruby_critic/cli/application.rb
116
132
  - lib/ruby_ci/runner_prepend.rb