fast_ci 0.1.1 → 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.
@@ -0,0 +1,287 @@
1
+ module Minitest
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
+
26
+ class FastCIReporter
27
+ attr_accessor :tests, :test_results, :ids
28
+
29
+ def initialize
30
+ @tests = {}
31
+ @test_results = {}
32
+ @ids = {}
33
+ @events = []
34
+
35
+ $stdout = StringIO.new()
36
+
37
+ if ENV['RBCI_REMOTE_TESTS'] != 'true'
38
+ FastCI.minitest_ws.on(:enq_request) do
39
+ tests
40
+ end
41
+
42
+ FastCI.minitest_ws.on(:deq) do |api_tests|
43
+ test_results
44
+ end
45
+ end
46
+ end
47
+
48
+ def start
49
+ test_count = Runnable.runnables.sum { |s| s.runnable_methods.count }
50
+ msg('start', { test_count: test_count })
51
+ @events << ['run_minitest'.upcase, { started_at: Time.current }]
52
+ send_events if ENV['RBCI_REMOTE_TESTS'] == 'true'
53
+ end
54
+
55
+ def get_output
56
+ return if $stdout.pos == 0
57
+ $stdout.rewind
58
+ res = $stdout.read
59
+ $stdout.flush
60
+ $stdout.rewind
61
+ return unless res
62
+ res.strip.chomp if res.strip.chomp != ""
63
+ end
64
+
65
+ def before_test(test)
66
+ $stdout = StringIO.new()
67
+ end
68
+
69
+ def prerecord(klass, name)
70
+ description = test_description(name)
71
+ path = test_path(klass.name)
72
+
73
+ test_results[path] ||= { run_time: 0.0, file_status: 'pending', test_count: 0, test_counters: { failed: 0, passed: 0, pending: 0 }, '1' => { description: klass.name } }
74
+ test_results[path][:test_count] += 1
75
+
76
+ id = (test_results[path]['1'].keys.size + 1).to_s
77
+ ids[description] = id
78
+
79
+ test_results[path]['1'][id] ||= { status: 'pending', description: description }
80
+ test_results[path]['1'][id][:start] = Minitest.clock_time
81
+
82
+ tests[path] ||= { run_time: 0.0, file_status: 'pending', test_count: 0, test_counters: { failed: 0, passed: 0, pending: 0 }, '1' => {} }
83
+ tests[path][:test_count] += 1
84
+ tests[path]['1'][id] ||= { status: 'pending' }
85
+ end
86
+
87
+ def record(result)
88
+ test_finished(result)
89
+ description = test_description(result.name)
90
+ id = ids[description]
91
+ path = test_path(result.klass)
92
+
93
+ test_results[path]['1'][id][:end] = Minitest.clock_time
94
+ test_results[path]['1'][id][:run_time] = test_results[path]['1'][id][:end] - test_results[path]['1'][id][:start]
95
+ test_results[path]['1'][id][:status] = result_status(result).to_s
96
+ test_results[path][:test_counters][result_status(result)] += 1
97
+ test_results[path][:run_time] += test_results[path]['1'][id][:run_time]
98
+ end
99
+
100
+ def report
101
+ test_results.each do |path, file_results|
102
+ file_status = 'pending'
103
+ file_results['1'].each do |id, test_result|
104
+ next if id == :description
105
+ if (test_result[:status] == 'passed') && (file_status != 'failed')
106
+ file_status = 'passed'
107
+ elsif file_status == 'failed'
108
+ file_status = 'failed'
109
+ end
110
+ end
111
+ test_results[path][:file_status] = file_status
112
+ end
113
+
114
+ if ENV['RBCI_REMOTE_TESTS'] == 'true'
115
+ send_events
116
+ else
117
+ FastCI.minitest_await
118
+ end
119
+ end
120
+
121
+ def passed?
122
+ results = []
123
+ test_results.map do |path, file_results|
124
+ file_results['1'].each do |id, test_result|
125
+ next if id == :description
126
+ if test_result[:status] == 'failed'
127
+ results << false
128
+ else
129
+ results << true
130
+ end
131
+ end
132
+ end
133
+
134
+ pass = results.any? {|reult| !result }
135
+
136
+ if pass
137
+ @events << ['run_minitest'.upcase, { succeed_after: 1 }]
138
+ else
139
+ @events << ['run_minitest'.upcase, { failed_after: 1 }]
140
+ end
141
+ send_events if ENV['RBCI_REMOTE_TESTS'] == 'true'
142
+
143
+ return pass
144
+ end
145
+
146
+ def method_missing(method, *args)
147
+ return
148
+ end
149
+
150
+ protected
151
+
152
+ def before_suite(suite)
153
+ end
154
+
155
+ def after_suite(_suite)
156
+ end
157
+
158
+ def record_print_status(test)
159
+ test_name = test.name.gsub(/^test_: /, "test:")
160
+ print pad_test(test_name)
161
+ print_colored_status(test)
162
+ print(" (%.2fs)" % test.time) unless test.time.nil?
163
+ puts
164
+ end
165
+
166
+ def record_print_failures_if_any(test)
167
+ if !test.skipped? && test.failure
168
+ print_info(test.failure, test.error?)
169
+ puts
170
+ end
171
+ end
172
+
173
+ def screenshots_base64(output)
174
+ return unless output
175
+ img_path = output&.scan(/\\[Screenshot Image\\]: (.*)$/)&.flatten&.first&.strip&.chomp ||
176
+ output&.scan(/\\[Screenshot\\]: (.*)$/)&.flatten&.first&.strip&.chomp
177
+
178
+ if img_path && File.exist?(img_path)
179
+ STDOUT.puts "SCREENSHOT!"
180
+ Base64.strict_encode64(File.read(img_path))
181
+ end
182
+ end
183
+
184
+ def test_finished(test)
185
+ output = get_output
186
+
187
+ location = if !test.source_location.join(":").start_with?(::Rails.root.join('vendor').to_s)
188
+ test.source_location.join(":")
189
+ else
190
+ if (file = `cat #{::Rails.root.join('vendor', 'bundle', 'minitest_cache_file').to_s} | grep "#{test.klass} => "`.split(" => ").last&.chomp)
191
+ file + ":"
192
+ else
193
+ file = `grep -rw "#{::Rails.root.to_s}" -e "#{test.klass} "`.split(":").first
194
+ `echo "#{test.klass} => #{file}" >> #{::Rails.root.join('vendor', 'bundle', 'minitest_cache_file').to_s}`
195
+ file + ":"
196
+ end
197
+ end
198
+
199
+ fully_formatted = if test.failure
200
+ fully_formatted = "\n" + test.failure.message.split("\n").first
201
+
202
+ test.failure.backtrace.each do |l|
203
+ if !l["/cache/"]
204
+ fully_formatted << "\n " + cyan + l + "\033[0m"
205
+ end
206
+ end
207
+
208
+ fully_formatted
209
+ end
210
+
211
+ output_inside = output&.split("\n")&.select do |line|
212
+ !line["Screenshot"]
213
+ end&.join("\n")
214
+ event_data = {
215
+ test_class: Suite.new(test.klass),
216
+ test_name: test.name.gsub(/^test_\\d*/, "").gsub(/^test_: /, "test:").gsub(/^_/, "").strip,
217
+ assertions_count: test.assertions,
218
+ location: location,
219
+ status: status(test),
220
+ run_time: test.time,
221
+ fully_formatted: fully_formatted,
222
+ output_inside: output_inside,
223
+ screenshots_base64: [screenshots_base64(output)]
224
+ }
225
+
226
+ msg('test_finished', event_data)
227
+ if ENV['RBCI_REMOTE_TESTS'] == 'true'
228
+ send_events if @events.length >= 10
229
+ end
230
+ end
231
+
232
+ def status(test)
233
+ if test.passed?
234
+ "passed"
235
+ elsif test.error?
236
+ "error"
237
+ elsif test.skipped?
238
+ "skipped"
239
+ elsif test.failure
240
+ "failed"
241
+ else
242
+ raise("Status not found")
243
+ end
244
+ end
245
+
246
+ private
247
+
248
+ def msg(event, data)
249
+ @events << ["minitest_#{event}".upcase, data]
250
+ end
251
+
252
+ def send_events
253
+ return unless @events.length > 0
254
+
255
+ json_events = {
256
+ build_id: FastCI.configuration.orig_build_id,
257
+ compressed_data: Base64.strict_encode64(Zlib::Deflate.deflate(JSON.fast_generate(@events), 9)),
258
+ }
259
+
260
+ FastCI.send_events(json_events)
261
+
262
+ @events = []
263
+ end
264
+
265
+ def test_description(name)
266
+ test_name = name.split('test_').last
267
+ test_name = test_name[2..-1] if test_name.starts_with?(': ')
268
+
269
+ return test_name.strip
270
+ end
271
+
272
+ def test_path(klass)
273
+ return "./#{Object.const_source_location(klass)[0].gsub(Regexp.new("^#{::Rails.root}/"), '')}"
274
+ end
275
+
276
+ def result_status(result)
277
+ if result.passed?
278
+ :passed
279
+ elsif result.skipped?
280
+ :skipped
281
+ else
282
+ :failed
283
+ end
284
+ end
285
+ end
286
+ end
287
+ end
@@ -0,0 +1,9 @@
1
+ require_relative "reporters/FastCI_reporter"
2
+
3
+ module Minitest
4
+ def self.plugin_fastci_init(options)
5
+ if ENV['FAST_CI_SECRET_KEY'].present?
6
+ Minitest.reporter << Minitest::Reporters::FastCIReporter.new
7
+ end
8
+ end
9
+ end
metadata CHANGED
@@ -1,29 +1,85 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fast_ci
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 1.0.0
5
5
  platform: ruby
6
6
  authors:
7
- - Ale
8
- autorequire:
9
- bindir: exe
7
+ - Nesha Zoric
8
+ autorequire:
9
+ bindir: bin
10
10
  cert_chain: []
11
- date: 2021-10-01 00:00:00.000000000 Z
11
+ date: 2024-10-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
- name: async-websocket
14
+ name: console
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: '0.19'
19
+ version: 1.10.0
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: '0.19'
26
+ version: 1.10.0
27
+ - !ruby/object:Gem::Dependency
28
+ name: async-websocket
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "<="
32
+ - !ruby/object:Gem::Version
33
+ version: 0.20.0
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "<="
39
+ - !ruby/object:Gem::Version
40
+ version: 0.20.0
41
+ - !ruby/object:Gem::Dependency
42
+ name: rubycritic
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: 4.1.0
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: 4.1.0
55
+ - !ruby/object:Gem::Dependency
56
+ name: brakeman
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: 5.4.1
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
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'
27
83
  - !ruby/object:Gem::Dependency
28
84
  name: pry
29
85
  requirement: !ruby/object:Gem::Requirement
@@ -40,34 +96,55 @@ dependencies:
40
96
  version: '0'
41
97
  description: Ruby wrapper for creating FastCI integrations
42
98
  email:
43
- - ale@alexvko.com
44
- executables: []
99
+ - no-reply@ruby.ci
100
+ executables:
101
+ - fastci_rubycritic
102
+ - fastci_brakeman
103
+ - fastci_bundle_audit
45
104
  extensions: []
46
105
  extra_rdoc_files: []
47
106
  files:
107
+ - ".github/workflows/main.yml"
48
108
  - ".gitignore"
49
109
  - ".rspec"
50
110
  - ".rubocop.yml"
111
+ - CODE_OF_CONDUCT.md
51
112
  - Gemfile
52
113
  - Gemfile.lock
53
114
  - LICENSE.txt
54
115
  - README.md
55
116
  - Rakefile
56
117
  - bin/console
118
+ - bin/fastci_brakeman
119
+ - bin/fastci_bundle_audit
120
+ - bin/fastci_rubycritic
57
121
  - bin/setup
58
122
  - fast_ci.gemspec
59
123
  - lib/fast_ci.rb
124
+ - lib/fast_ci/brakeman.rb
125
+ - lib/fast_ci/brakeman/commandline.rb
60
126
  - lib/fast_ci/configuration.rb
127
+ - lib/fast_ci/dryrun_runner_prepend.rb
61
128
  - lib/fast_ci/exceptions.rb
129
+ - lib/fast_ci/extract_definitions.rb
130
+ - lib/fast_ci/rspec_dryrun_formatter.rb
131
+ - lib/fast_ci/rspec_formatter.rb
132
+ - lib/fast_ci/rspec_run_formatter.rb
133
+ - lib/fast_ci/ruby_critic/cli/application.rb
134
+ - lib/fast_ci/runner_prepend.rb
135
+ - lib/fast_ci/simple_cov.rb
136
+ - lib/fast_ci/simple_cov/reporting.rb
62
137
  - lib/fast_ci/version.rb
63
- homepage: https://github.com/alexvko/fast_ci-rb
138
+ - lib/minitest/reporters/fastci_reporter.rb
139
+ - lib/minitest/rubyci_plugin.rb
140
+ homepage: https://github.com/RubyCI/fast_ci_gem
64
141
  licenses:
65
142
  - MIT
66
143
  metadata:
67
- homepage_uri: https://github.com/alexvko/fast_ci-rb
68
- source_code_uri: https://github.com/alexvko/fast_ci-rb
69
- changelog_uri: https://github.com/alexvko/fast_ci-rb
70
- post_install_message:
144
+ homepage_uri: https://github.com/RubyCI/fast_ci_gem
145
+ source_code_uri: https://github.com/RubyCI/fast_ci_gem
146
+ changelog_uri: https://github.com/RubyCI/fast_ci_gem
147
+ post_install_message:
71
148
  rdoc_options: []
72
149
  require_paths:
73
150
  - lib
@@ -82,8 +159,9 @@ required_rubygems_version: !ruby/object:Gem::Requirement
82
159
  - !ruby/object:Gem::Version
83
160
  version: '0'
84
161
  requirements: []
85
- rubygems_version: 3.2.22
86
- signing_key:
162
+ rubyforge_project:
163
+ rubygems_version: 2.7.7
164
+ signing_key:
87
165
  specification_version: 4
88
166
  summary: Ruby wrapper for creating FastCI integrations
89
167
  test_files: []