rspec-tracer 1.2.3 → 2.0.0.pre.2

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 (144) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +384 -67
  3. data/README.md +454 -429
  4. data/bin/rspec-tracer +15 -0
  5. data/lib/rspec_tracer/cache/Rakefile +43 -0
  6. data/lib/rspec_tracer/cli/cache_clear.rb +111 -0
  7. data/lib/rspec_tracer/cli/cache_info.rb +104 -0
  8. data/lib/rspec_tracer/cli/doctor.rb +284 -0
  9. data/lib/rspec_tracer/cli/explain.rb +158 -0
  10. data/lib/rspec_tracer/cli/report_open.rb +82 -0
  11. data/lib/rspec_tracer/cli.rb +116 -0
  12. data/lib/rspec_tracer/configuration.rb +1196 -3
  13. data/lib/rspec_tracer/engine.rb +1168 -0
  14. data/lib/rspec_tracer/example.rb +141 -11
  15. data/lib/rspec_tracer/filter.rb +35 -0
  16. data/lib/rspec_tracer/line_stub.rb +61 -0
  17. data/lib/rspec_tracer/load_config.rb +2 -2
  18. data/lib/rspec_tracer/logger.rb +15 -0
  19. data/lib/rspec_tracer/rails/README.md +78 -0
  20. data/lib/rspec_tracer/rails/i18n_tracking.rb +137 -0
  21. data/lib/rspec_tracer/rails/notifications.rb +263 -0
  22. data/lib/rspec_tracer/rails/preset.rb +94 -0
  23. data/lib/rspec_tracer/rails/railtie.rb +22 -0
  24. data/lib/rspec_tracer/rails.rb +15 -0
  25. data/lib/rspec_tracer/remote_cache/README.md +140 -0
  26. data/lib/rspec_tracer/remote_cache/Rakefile +35 -11
  27. data/lib/rspec_tracer/remote_cache/archive.rb +137 -0
  28. data/lib/rspec_tracer/remote_cache/backend.rb +73 -0
  29. data/lib/rspec_tracer/remote_cache/git_ancestry.rb +241 -0
  30. data/lib/rspec_tracer/remote_cache/local_fs_backend.rb +439 -0
  31. data/lib/rspec_tracer/remote_cache/redis_backend.rb +554 -0
  32. data/lib/rspec_tracer/remote_cache/s3_backend.rb +712 -0
  33. data/lib/rspec_tracer/remote_cache/user_tasks.rb +436 -0
  34. data/lib/rspec_tracer/remote_cache/validator.rb +40 -62
  35. data/lib/rspec_tracer/remote_cache.rb +22 -0
  36. data/lib/rspec_tracer/reporters/README.md +103 -0
  37. data/lib/rspec_tracer/reporters/base.rb +87 -0
  38. data/lib/rspec_tracer/reporters/coverage_json_reporter.rb +338 -0
  39. data/lib/rspec_tracer/reporters/html/.gitignore +19 -0
  40. data/lib/rspec_tracer/reporters/html/.prettierignore +4 -0
  41. data/lib/rspec_tracer/reporters/html/.prettierrc.json +9 -0
  42. data/lib/rspec_tracer/reporters/html/README.md +80 -0
  43. data/lib/rspec_tracer/reporters/html/dist/assets/index.css +2 -0
  44. data/lib/rspec_tracer/reporters/html/dist/assets/index.js +1 -0
  45. data/lib/rspec_tracer/reporters/html/dist/index.html +24 -0
  46. data/lib/rspec_tracer/reporters/html/eslint.config.js +62 -0
  47. data/lib/rspec_tracer/reporters/html/package-lock.json +4941 -0
  48. data/lib/rspec_tracer/reporters/html/package.json +29 -0
  49. data/lib/rspec_tracer/reporters/html/src/app.jsx +130 -0
  50. data/lib/rspec_tracer/reporters/html/src/components/AllExamples.jsx +86 -0
  51. data/lib/rspec_tracer/reporters/html/src/components/DuplicateExamples.jsx +68 -0
  52. data/lib/rspec_tracer/reporters/html/src/components/ExamplesDependency.jsx +78 -0
  53. data/lib/rspec_tracer/reporters/html/src/components/FilesDependency.jsx +72 -0
  54. data/lib/rspec_tracer/reporters/html/src/components/FlakyExamples.jsx +42 -0
  55. data/lib/rspec_tracer/reporters/html/src/components/ReportTable.jsx +131 -0
  56. data/lib/rspec_tracer/reporters/html/src/components/SearchBar.jsx +19 -0
  57. data/lib/rspec_tracer/reporters/html/src/index.html +23 -0
  58. data/lib/rspec_tracer/reporters/html/src/main.jsx +37 -0
  59. data/lib/rspec_tracer/reporters/html/src/styles.css +434 -0
  60. data/lib/rspec_tracer/reporters/html/vite.config.js +42 -0
  61. data/lib/rspec_tracer/reporters/html_reporter.rb +266 -0
  62. data/lib/rspec_tracer/reporters/json_reporter.rb +88 -0
  63. data/lib/rspec_tracer/reporters/payload_builder.rb +235 -0
  64. data/lib/rspec_tracer/reporters/registry.rb +120 -0
  65. data/lib/rspec_tracer/reporters/terminal_reporter.rb +264 -0
  66. data/lib/rspec_tracer/rspec/README.md +73 -0
  67. data/lib/rspec_tracer/rspec/installation.rb +97 -0
  68. data/lib/rspec_tracer/rspec/metadata.rb +96 -0
  69. data/lib/rspec_tracer/rspec/parallel_tests.rb +459 -0
  70. data/lib/rspec_tracer/rspec/reporter_hook.rb +84 -0
  71. data/lib/rspec_tracer/rspec/runner_hook.rb +239 -0
  72. data/lib/rspec_tracer/source_file.rb +24 -7
  73. data/lib/rspec_tracer/storage/README.md +35 -0
  74. data/lib/rspec_tracer/storage/backend.rb +130 -0
  75. data/lib/rspec_tracer/storage/json_backend.rb +884 -0
  76. data/lib/rspec_tracer/storage/lazy_snapshot.rb +65 -0
  77. data/lib/rspec_tracer/storage/schema.rb +50 -0
  78. data/lib/rspec_tracer/storage/serializer/json.rb +41 -0
  79. data/lib/rspec_tracer/storage/serializer/msgpack.rb +167 -0
  80. data/lib/rspec_tracer/storage/snapshot.rb +141 -0
  81. data/lib/rspec_tracer/storage/sqlite_backend.rb +693 -0
  82. data/lib/rspec_tracer/time_formatter.rb +37 -18
  83. data/lib/rspec_tracer/tracker/README.md +36 -0
  84. data/lib/rspec_tracer/tracker/coverage_adapter.rb +174 -0
  85. data/lib/rspec_tracer/tracker/declared_globs.rb +100 -0
  86. data/lib/rspec_tracer/tracker/dependency_graph.rb +134 -0
  87. data/lib/rspec_tracer/tracker/env_matcher.rb +127 -0
  88. data/lib/rspec_tracer/tracker/env_snapshot.rb +77 -0
  89. data/lib/rspec_tracer/tracker/example_registry.rb +153 -0
  90. data/lib/rspec_tracer/tracker/file_digest.rb +61 -0
  91. data/lib/rspec_tracer/tracker/filter.rb +127 -0
  92. data/lib/rspec_tracer/tracker/input.rb +99 -0
  93. data/lib/rspec_tracer/tracker/io_hooks/file.rb +55 -0
  94. data/lib/rspec_tracer/tracker/io_hooks/io.rb +24 -0
  95. data/lib/rspec_tracer/tracker/io_hooks/json.rb +23 -0
  96. data/lib/rspec_tracer/tracker/io_hooks/kernel.rb +26 -0
  97. data/lib/rspec_tracer/tracker/io_hooks/yaml.rb +38 -0
  98. data/lib/rspec_tracer/tracker/io_hooks.rb +195 -0
  99. data/lib/rspec_tracer/tracker/loaded_files_tracker.rb +295 -0
  100. data/lib/rspec_tracer/tracker/new_file_detector.rb +62 -0
  101. data/lib/rspec_tracer/tracker/whole_suite_invalidators.rb +96 -0
  102. data/lib/rspec_tracer/version.rb +4 -1
  103. data/lib/rspec_tracer.rb +231 -491
  104. metadata +94 -43
  105. data/lib/rspec_tracer/cache.rb +0 -207
  106. data/lib/rspec_tracer/coverage_merger.rb +0 -42
  107. data/lib/rspec_tracer/coverage_reporter.rb +0 -187
  108. data/lib/rspec_tracer/coverage_writer.rb +0 -58
  109. data/lib/rspec_tracer/html_reporter/Rakefile +0 -18
  110. data/lib/rspec_tracer/html_reporter/assets/javascripts/application.js +0 -56
  111. data/lib/rspec_tracer/html_reporter/assets/javascripts/libraries/jquery.js +0 -10881
  112. data/lib/rspec_tracer/html_reporter/assets/javascripts/plugins/datatables.js +0 -15381
  113. data/lib/rspec_tracer/html_reporter/assets/stylesheets/application.css +0 -196
  114. data/lib/rspec_tracer/html_reporter/assets/stylesheets/plugins/datatables.css +0 -459
  115. data/lib/rspec_tracer/html_reporter/assets/stylesheets/plugins/jquery-ui.css +0 -436
  116. data/lib/rspec_tracer/html_reporter/assets/stylesheets/print.css +0 -92
  117. data/lib/rspec_tracer/html_reporter/assets/stylesheets/reset.css +0 -265
  118. data/lib/rspec_tracer/html_reporter/public/application.css +0 -5
  119. data/lib/rspec_tracer/html_reporter/public/application.js +0 -6
  120. data/lib/rspec_tracer/html_reporter/public/datatables/images/sort_asc.png +0 -0
  121. data/lib/rspec_tracer/html_reporter/public/datatables/images/sort_asc_disabled.png +0 -0
  122. data/lib/rspec_tracer/html_reporter/public/datatables/images/sort_both.png +0 -0
  123. data/lib/rspec_tracer/html_reporter/public/datatables/images/sort_desc.png +0 -0
  124. data/lib/rspec_tracer/html_reporter/public/datatables/images/sort_desc_disabled.png +0 -0
  125. data/lib/rspec_tracer/html_reporter/public/favicon.png +0 -0
  126. data/lib/rspec_tracer/html_reporter/public/loading.gif +0 -0
  127. data/lib/rspec_tracer/html_reporter/reporter.rb +0 -242
  128. data/lib/rspec_tracer/html_reporter/views/duplicate_examples.erb +0 -34
  129. data/lib/rspec_tracer/html_reporter/views/examples.erb +0 -58
  130. data/lib/rspec_tracer/html_reporter/views/examples_dependency.erb +0 -36
  131. data/lib/rspec_tracer/html_reporter/views/files_dependency.erb +0 -36
  132. data/lib/rspec_tracer/html_reporter/views/flaky_examples.erb +0 -38
  133. data/lib/rspec_tracer/html_reporter/views/layout.erb +0 -38
  134. data/lib/rspec_tracer/remote_cache/aws.rb +0 -176
  135. data/lib/rspec_tracer/remote_cache/cache.rb +0 -75
  136. data/lib/rspec_tracer/remote_cache/repo.rb +0 -210
  137. data/lib/rspec_tracer/report_generator.rb +0 -158
  138. data/lib/rspec_tracer/report_merger.rb +0 -68
  139. data/lib/rspec_tracer/report_writer.rb +0 -141
  140. data/lib/rspec_tracer/reporter.rb +0 -204
  141. data/lib/rspec_tracer/rspec_reporter.rb +0 -41
  142. data/lib/rspec_tracer/rspec_runner.rb +0 -56
  143. data/lib/rspec_tracer/ruby_coverage.rb +0 -9
  144. data/lib/rspec_tracer/runner.rb +0 -278
@@ -1,242 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'erb'
4
- require 'time'
5
-
6
- module RSpecTracer
7
- module HTMLReporter
8
- class Reporter
9
- attr_reader :last_run, :examples, :flaky_examples, :examples_dependency, :files_dependency
10
-
11
- def initialize(report_dir, reporter)
12
- @report_dir = report_dir
13
- @reporter = reporter
14
- end
15
-
16
- def generate_report
17
- starting = Process.clock_gettime(Process::CLOCK_MONOTONIC)
18
-
19
- prepare
20
-
21
- file_name = File.join(@report_dir, 'index.html')
22
-
23
- File.open(file_name, 'wb') do |file|
24
- file.puts(template('layout').result(binding))
25
- end
26
-
27
- ending = Process.clock_gettime(Process::CLOCK_MONOTONIC)
28
- elapsed = RSpecTracer::TimeFormatter.format_time(ending - starting)
29
-
30
- RSpecTracer.logger.debug "RSpecTracer generated HTML report to #{file_name} (took #{elapsed})"
31
- end
32
-
33
- private
34
-
35
- def prepare
36
- format_last_run
37
- format_examples
38
- format_duplicate_examples
39
- format_flaky_examples
40
- format_examples_dependency
41
- format_files_dependency
42
- copy_assets
43
- end
44
-
45
- def copy_assets
46
- Dir[File.join(File.dirname(__FILE__), 'public/*')].each do |path|
47
- FileUtils.cp_r(path, asset_output_path)
48
- end
49
- end
50
-
51
- def format_last_run
52
- @last_run = @reporter.last_run.slice(
53
- :actual_count,
54
- :duplicate_examples,
55
- :failed_examples,
56
- :pending_examples,
57
- :skipped_examples
58
- )
59
- end
60
-
61
- def format_examples
62
- @examples = {}
63
-
64
- @reporter.all_examples.each_pair do |example_id, example|
65
- @examples[example_id] = {
66
- id: example_id,
67
- description: example[:full_description],
68
- location: example_location(example[:rerun_file_name], example[:rerun_line_number]),
69
- status: example[:run_reason] || 'Skipped'
70
- }.merge(example_result(example_id, example))
71
- end
72
- end
73
-
74
- def example_result(example_id, example)
75
- if example[:execution_result].nil?
76
- {
77
- result: @reporter.example_interrupted?(example_id) ? 'Interrupted' : '_',
78
- last_run: '_'
79
- }
80
- else
81
- {
82
- result: example[:execution_result][:status].capitalize,
83
- last_run: example_run_local_time(example[:execution_result][:finished_at])
84
- }
85
- end
86
- end
87
-
88
- def format_duplicate_examples
89
- @duplicate_examples = []
90
-
91
- @reporter.duplicate_examples.each_pair do |example_id, examples|
92
- examples.each do |example|
93
- @duplicate_examples << {
94
- id: example_id,
95
- description: example[:full_description],
96
- location: example_location(example[:rerun_file_name], example[:rerun_line_number])
97
- }
98
- end
99
- end
100
- end
101
-
102
- def format_flaky_examples
103
- @flaky_examples = @examples.slice(*@reporter.flaky_examples).values
104
- end
105
-
106
- def example_run_local_time(utc_time)
107
- case utc_time
108
- when Time
109
- utc_time.localtime.strftime('%Y-%m-%d %H:%M:%S')
110
- when String
111
- Time.parse(utc_time).localtime.strftime('%Y-%m-%d %H:%M:%S')
112
- else
113
- utc_time.inspect
114
- end
115
- end
116
-
117
- def format_examples_dependency
118
- @examples_dependency = []
119
-
120
- @reporter.dependency.each_pair do |example_id, files|
121
- @examples_dependency << {
122
- example_id: example_id,
123
- example: @examples[example_id][:description],
124
- files_count: files.count,
125
- files: files.map { |file_name| shortened_file_name(file_name) }.sort.join(', ')
126
- }
127
- end
128
- end
129
-
130
- def format_files_dependency
131
- @files_dependency = []
132
-
133
- @reporter.reverse_dependency.each_pair do |main_file_name, data|
134
- short_file_name = shortened_file_name(main_file_name)
135
-
136
- @files_dependency << {
137
- name: short_file_name,
138
- example_count: data[:example_count],
139
- file_count: data[:examples].count,
140
- files: data[:examples]
141
- .map { |file_name, count| "#{shortened_file_name(file_name)}: #{count}" }
142
- .join(', ')
143
- }
144
- end
145
- end
146
-
147
- def example_location(file_name, line_number)
148
- "#{shortened_file_name(file_name)}:#{line_number}"
149
- end
150
-
151
- def shortened_file_name(file_name)
152
- file_name.sub(%r{^/}, '')
153
- end
154
-
155
- def asset_output_path
156
- @asset_output_path ||= begin
157
- asset_output_path = File.join(@report_dir, 'assets', RSpecTracer::VERSION)
158
-
159
- FileUtils.mkdir_p(asset_output_path)
160
-
161
- asset_output_path
162
- end
163
- end
164
-
165
- def assets_path(name)
166
- File.join('./assets', RSpecTracer::VERSION, name)
167
- end
168
-
169
- def formatted_examples(title, examples)
170
- title_id = report_container_id(title)
171
- current_binding = binding
172
-
173
- current_binding.local_variable_set(:title_id, title_id)
174
- template(title_id).result(current_binding)
175
- end
176
-
177
- def formatted_duplicate_examples(title, duplicate_examples)
178
- title_id = report_container_id(title)
179
- current_binding = binding
180
-
181
- current_binding.local_variable_set(:title_id, title_id)
182
- template(title_id).result(current_binding)
183
- end
184
-
185
- def formatted_flaky_examples(title, flaky_examples)
186
- title_id = report_container_id(title)
187
- current_binding = binding
188
-
189
- current_binding.local_variable_set(:title_id, title_id)
190
- template(title_id).result(current_binding)
191
- end
192
-
193
- def formatted_examples_dependency(title, examples_dependency)
194
- title_id = report_container_id(title)
195
- current_binding = binding
196
-
197
- current_binding.local_variable_set(:title_id, title_id)
198
- template(title_id).result(current_binding)
199
- end
200
-
201
- def formatted_files_dependency(title, files_dependency)
202
- title_id = report_container_id(title)
203
- current_binding = binding
204
-
205
- current_binding.local_variable_set(:title_id, title_id)
206
- template(title_id).result(current_binding)
207
- end
208
-
209
- def report_container_id(title)
210
- title.gsub(/\s+/, ' ').downcase.tr(' ', '_')
211
- end
212
-
213
- def template(name)
214
- ERB.new(File.read(File.join(File.dirname(__FILE__), 'views/', "#{name}.erb"), encoding: 'UTF-8'))
215
- end
216
-
217
- def example_status_css_class(example_status)
218
- case example_status.split.first
219
- when 'Failed', 'Flaky', 'Interrupted'
220
- 'red'
221
- when 'Pending'
222
- 'yellow'
223
- else
224
- 'blue'
225
- end
226
- end
227
-
228
- def example_result_css_class(example_result)
229
- case example_result
230
- when 'Passed'
231
- 'green'
232
- when 'Failed', 'Interrupted'
233
- 'red'
234
- when 'Pending'
235
- 'yellow'
236
- else
237
- 'blue'
238
- end
239
- end
240
- end
241
- end
242
- end
@@ -1,34 +0,0 @@
1
- <div class="report_container" id="<%= title_id %>">
2
- <h2>
3
- <span class="group_name"><%= title %></span>
4
- (
5
- <span class="blue">
6
- <strong><%= duplicate_examples.count %></strong>
7
- </span> examples
8
- )
9
- </h2>
10
-
11
- <a name="<%= title_id %>"></a>
12
-
13
- <div class="report-table--responsive">
14
- <table class="report-table">
15
- <thead>
16
- <tr>
17
- <th>ID</th>
18
- <th>Description</th>
19
- <th>Location</th>
20
- </tr>
21
- </thead>
22
-
23
- <tbody>
24
- <% duplicate_examples.each do |example| %>
25
- <tr>
26
- <td><%= example[:id] %></td>
27
- <td><%= example[:description] %></td>
28
- <td><%= example[:location] %></td>
29
- </tr>
30
- <% end %>
31
- </tbody>
32
- </table>
33
- </div>
34
- </div>
@@ -1,58 +0,0 @@
1
- <div class="report_container" id="<%= title_id %>">
2
- <h2>
3
- <span class="group_name"><%= title %></span>
4
- (
5
- <span class="blue">
6
- <strong><%= last_run[:actual_count] %></strong>
7
- </span> examples,
8
- <% if last_run[:duplicate_examples].positive? %>
9
- <span class="blue">
10
- <strong><%= last_run[:duplicate_examples] %></strong>
11
- </span> duplicates,
12
- <% end %>
13
- <% if last_run[:failed_examples].positive? %>
14
- <span class="red">
15
- <strong><%= last_run[:failed_examples] %></strong>
16
- </span> failures,
17
- <% end %>
18
- <% if last_run[:pending_examples].positive? %>
19
- <span class="yellow">
20
- <strong><%= last_run[:pending_examples] %></strong>
21
- </span> pending,
22
- <% end %>
23
- <span class="blue">
24
- <strong><%= last_run[:skipped_examples] %></strong>
25
- </span> skipped by rspec-tracer
26
- )
27
- </h2>
28
-
29
- <a name="<%= title_id %>"></a>
30
-
31
- <div class="report-table--responsive">
32
- <table class="report-table">
33
- <thead>
34
- <tr>
35
- <th>ID</th>
36
- <th>Description</th>
37
- <th>Location</th>
38
- <th>Run Reason</th>
39
- <th>Result</th>
40
- <th>Run At</th>
41
- </tr>
42
- </thead>
43
-
44
- <tbody>
45
- <% examples.each do |example| %>
46
- <tr>
47
- <td><%= example[:id] %></td>
48
- <td><%= example[:description] %></td>
49
- <td><%= example[:location] %></td>
50
- <td><strong class="<%= example_status_css_class(example[:status]) %>"><%= example[:status] %></strong></td>
51
- <td><strong class="<%= example_result_css_class(example[:result]) %>"><%= example[:result] %></strong></td>
52
- <td width="8%"><%= example[:last_run] %></td>
53
- </tr>
54
- <% end %>
55
- </tbody>
56
- </table>
57
- </div>
58
- </div>
@@ -1,36 +0,0 @@
1
- <div class="report_container" id="<%= title_id %>">
2
- <h2>
3
- <span class="group_name"><%= title %></span>
4
- (
5
- <span class="blue">
6
- <strong><%= examples_dependency.count %></strong>
7
- </span> examples
8
- )
9
- </h2>
10
-
11
- <a name="<%= title_id %>"></a>
12
-
13
- <div class="report-table--responsive">
14
- <table class="report-table">
15
- <thead>
16
- <tr>
17
- <th>Example ID</th>
18
- <th>Example</th>
19
- <th>Files Count</th>
20
- <th data-orderable="false">Files Name</th>
21
- </tr>
22
- </thead>
23
-
24
- <tbody>
25
- <% examples_dependency.each do |example_dependency| %>
26
- <tr>
27
- <td><%= example_dependency[:example_id] %></td>
28
- <td><%= example_dependency[:example] %></td>
29
- <td class="number" width="8%"><strong><%= example_dependency[:files_count] %></strong></td>
30
- <td><%= example_dependency[:files] %></td>
31
- </tr>
32
- <% end %>
33
- </tbody>
34
- </table>
35
- </div>
36
- </div>
@@ -1,36 +0,0 @@
1
- <div class="report_container" id="<%= title_id %>">
2
- <h2>
3
- <span class="group_name"><%= title %></span>
4
- (
5
- <span class="blue">
6
- <strong><%= files_dependency.count %></strong>
7
- </span> files
8
- )
9
- </h2>
10
-
11
- <a name="<%= title_id %>"></a>
12
-
13
- <div class="report-table--responsive">
14
- <table class="report-table">
15
- <thead>
16
- <tr>
17
- <th searchable="true">File</th>
18
- <th>Examples Count</th>
19
- <th>Files Count</th>
20
- <th data-orderable="false">Dependent Files</th>
21
- </tr>
22
- </thead>
23
-
24
- <tbody>
25
- <% files_dependency.each do |file_dependency| %>
26
- <tr class="t-example">
27
- <td><%= file_dependency[:name] %></td>
28
- <td class="number" width="8%"><strong><%= file_dependency[:example_count] %></strong></td>
29
- <td class="number" width="8%"><strong><%= file_dependency[:file_count] %></strong></td>
30
- <td><%= file_dependency[:files] %></td>
31
- </tr>
32
- <% end %>
33
- </tbody>
34
- </table>
35
- </div>
36
- </div>
@@ -1,38 +0,0 @@
1
- <div class="report_container" id="<%= title_id %>">
2
- <h2>
3
- <span class="group_name"><%= title %></span>
4
- (
5
- <span class="blue">
6
- <strong><%= flaky_examples.count %></strong>
7
- </span> examples
8
- )
9
- </h2>
10
-
11
- <a name="<%= title_id %>"></a>
12
-
13
- <div class="report-table--responsive">
14
- <table class="report-table">
15
- <thead>
16
- <tr>
17
- <th>ID</th>
18
- <th>Description</th>
19
- <th>Location</th>
20
- <th>Result</th>
21
- <th>Run At</th>
22
- </tr>
23
- </thead>
24
-
25
- <tbody>
26
- <% flaky_examples.each do |example| %>
27
- <tr>
28
- <td><%= example[:id] %></td>
29
- <td><%= example[:description] %></td>
30
- <td><%= example[:location] %></td>
31
- <td><strong class="<%= example_result_css_class(example[:result]) %>"><%= example[:result] %></strong></td>
32
- <td width="8%"><%= example[:last_run] %></td>
33
- </tr>
34
- <% end %>
35
- </tbody>
36
- </table>
37
- </div>
38
- </div>
@@ -1,38 +0,0 @@
1
- <!DOCTYPE html>
2
-
3
- <html xmlns='http://www.w3.org/1999/xhtml'>
4
- <head>
5
- <title>RSpec Tracer Report for <%= RSpecTracer.project_name %></title>
6
- <meta http-equiv="content-type" content="text/html; charset=utf-8" />
7
- <script src='<%= assets_path('application.js') %>' type='text/javascript'></script>
8
- <link href='<%= assets_path('application.css') %>' media='screen, projection, print' rel='stylesheet' type='text/css' />
9
- <link rel="icon" type="image/png" href="<%= assets_path('favicon.png') %>" />
10
- </head>
11
-
12
- <body>
13
- <div id="loading">
14
- <img src="<%= assets_path('loading.gif') %>" width="60" height="60" alt="loading" />
15
- </div>
16
-
17
- <div id="wrapper" class="hide">
18
- <ul class="group_tabs"></ul>
19
-
20
- <div id="content">
21
- <%= formatted_examples('Examples', @examples.values) %>
22
- <% unless @duplicate_examples.empty? %>
23
- <%= formatted_duplicate_examples('Duplicate Examples', @duplicate_examples) %>
24
- <% end %>
25
- <% unless @flaky_examples.empty? %>
26
- <%= formatted_flaky_examples('Flaky Examples', @flaky_examples) %>
27
- <% end %>
28
- <%= formatted_examples_dependency('Examples Dependency', @examples_dependency) %>
29
- <%= formatted_files_dependency("Files Dependency", @files_dependency) %>
30
- </div>
31
-
32
- <div id="footer">
33
- Generated by <a href="https://github.com/avmnu-sng/rspec-tracer">rspec-tracer</a>
34
- v<%= RSpecTracer::VERSION %>
35
- </div>
36
- </div>
37
- </body>
38
- </html>
@@ -1,176 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module RSpecTracer
4
- module RemoteCache
5
- class Aws
6
- class AwsError < StandardError; end
7
-
8
- def initialize
9
- @s3_bucket, @s3_path = setup_s3
10
- @aws_cli = RSpecTracer.use_local_aws ? 'awslocal' : 'aws'
11
- @use_test_suite_id_cache = ENV.fetch('USE_TEST_SUITE_ID_CACHE', nil) == 'true'
12
- @test_suite_id = ENV.fetch('TEST_SUITE_ID', nil) if @use_test_suite_id_cache
13
- end
14
-
15
- def branch_refs?(branch_name)
16
- key = "#{@s3_path}/branch-refs/#{branch_name}/branch_refs.json"
17
-
18
- system(
19
- @aws_cli,
20
- 's3api',
21
- 'head-object',
22
- '--bucket',
23
- @s3_bucket,
24
- '--key',
25
- key,
26
- out: File::NULL,
27
- err: File::NULL
28
- )
29
- end
30
-
31
- def download_branch_refs(branch_name, file_name)
32
- key = "#{@s3_path}/branch-refs/#{branch_name}/branch_refs.json"
33
-
34
- system(
35
- @aws_cli,
36
- 's3api',
37
- 'get-object',
38
- '--bucket',
39
- @s3_bucket,
40
- '--key',
41
- key,
42
- file_name,
43
- out: File::NULL,
44
- err: File::NULL
45
- )
46
- end
47
-
48
- def upload_branch_refs(branch_name, file_name)
49
- remote_path = "s3://#{@s3_bucket}/#{@s3_path}/branch-refs/#{branch_name}/branch_refs.json"
50
-
51
- raise AwsError, "Failed to upload branch refs for #{branch_name} branch" unless system(
52
- @aws_cli,
53
- 's3',
54
- 'cp',
55
- file_name,
56
- remote_path,
57
- out: File::NULL,
58
- err: File::NULL
59
- )
60
-
61
- RSpecTracer.logger.debug "Uploaded branch refs for #{branch_name} branch to #{remote_path}"
62
- end
63
-
64
- def cache_files_list(ref)
65
- prefix = if @use_test_suite_id_cache && !@test_suite_id.nil?
66
- "s3://#{@s3_bucket}/#{@s3_path}/#{ref}/#{@test_suite_id}/"
67
- else
68
- "s3://#{@s3_bucket}/#{@s3_path}/#{ref}/"
69
- end
70
-
71
- `#{@aws_cli} s3 ls #{prefix} --recursive`.chomp.split("\n")
72
- end
73
-
74
- def download_file(ref, file_name)
75
- remote_path = File.join(s3_dir(ref), file_name)
76
- local_path = File.join(RSpecTracer.cache_path, file_name)
77
-
78
- raise AwsError, "Failed to download file #{remote_path}" unless system(
79
- @aws_cli,
80
- 's3',
81
- 'cp',
82
- remote_path,
83
- local_path,
84
- out: File::NULL,
85
- err: File::NULL
86
- )
87
-
88
- RSpecTracer.logger.debug "Downloaded file #{remote_path} to #{local_path}"
89
- end
90
-
91
- def download_dir(ref, run_id)
92
- remote_dir = s3_dir(ref, run_id)
93
- local_dir = File.join(RSpecTracer.cache_path, run_id)
94
-
95
- raise AwsError, "Failed to download files from #{remote_dir}" unless system(
96
- @aws_cli,
97
- 's3',
98
- 'cp',
99
- remote_dir,
100
- local_dir,
101
- '--recursive',
102
- out: File::NULL,
103
- err: File::NULL
104
- )
105
-
106
- RSpecTracer.logger.debug "Downloaded cache files from #{remote_dir} to #{local_dir}"
107
- rescue AwsError => e
108
- FileUtils.rm_rf(local_dir)
109
-
110
- raise e
111
- end
112
-
113
- def upload_file(ref, file_name)
114
- remote_path = File.join(s3_dir(ref), file_name)
115
- local_path = File.join(RSpecTracer.cache_path, file_name)
116
-
117
- raise AwsError, "Failed to upload file #{local_path}" unless system(
118
- @aws_cli,
119
- 's3',
120
- 'cp',
121
- local_path,
122
- remote_path,
123
- out: File::NULL,
124
- err: File::NULL
125
- )
126
-
127
- RSpecTracer.logger.debug "Uploaded file #{local_path} to #{remote_path}"
128
- end
129
-
130
- def upload_dir(ref, run_id)
131
- remote_dir = s3_dir(ref, run_id)
132
- local_dir = File.join(RSpecTracer.cache_path, run_id)
133
-
134
- raise AwsError, "Failed to upload files from #{local_dir}" unless system(
135
- @aws_cli,
136
- 's3',
137
- 'cp',
138
- local_dir,
139
- remote_dir,
140
- '--recursive',
141
- out: File::NULL,
142
- err: File::NULL
143
- )
144
-
145
- RSpecTracer.logger.debug "Uploaded files from #{local_dir} to #{remote_dir}"
146
- end
147
-
148
- private
149
-
150
- def setup_s3
151
- s3_uri = RSpecTracer.reports_s3_path
152
-
153
- raise AwsError, 'Invalid reports S3 path' if s3_uri.nil?
154
-
155
- uri_parts = s3_uri[4..].split('/')
156
-
157
- raise AwsError, "Invalid S3 URI #{s3_uri}" unless uri_parts.length >= 3 && uri_parts.first.empty?
158
-
159
- [
160
- uri_parts[1],
161
- uri_parts[2..].join('/')
162
- ]
163
- end
164
-
165
- def s3_dir(ref, run_id = nil)
166
- test_suite_id = ENV.fetch('TEST_SUITE_ID', nil)
167
-
168
- if test_suite_id.nil?
169
- "s3://#{@s3_bucket}/#{@s3_path}/#{ref}/#{run_id}/".sub(%r{/+$}, '/')
170
- else
171
- "s3://#{@s3_bucket}/#{@s3_path}/#{ref}/#{test_suite_id}/#{run_id}/".sub(%r{/+$}, '/')
172
- end
173
- end
174
- end
175
- end
176
- end