rspecq 0.1.0 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +9 -0
- data/README.md +11 -8
- data/lib/rspecq/queue.rb +14 -0
- data/lib/rspecq/reporter.rb +30 -2
- data/lib/rspecq/version.rb +1 -1
- metadata +4 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 87f2cf8ea2c0b03bf491442902644d24dd001265b2550c0403073d3f34d99903
|
4
|
+
data.tar.gz: 646b803ece2861f4ac8faced44f620ea5608636be38033f6931c0550bf4d79bd
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 418cf064a63ff4ea790495f578bb02f7c76ce6c0536af7a8fbdd8d6a293182f75cc15c587f2bcf798175f1ca0c427a208d8db326d157eacfcc199b783ce00d26
|
7
|
+
data.tar.gz: c109a02fc2412f7bb412422d97ee8096d85795893904d7034bbf7928d9c4d8fc5492f279d3f8cfaa77a4065f2ec591ac23915a7d53c181340610c057558fa16f
|
data/CHANGELOG.md
CHANGED
@@ -4,6 +4,15 @@ Breaking changes are prefixed with a "[BREAKING]" label.
|
|
4
4
|
|
5
5
|
## master (unreleased)
|
6
6
|
|
7
|
+
|
8
|
+
|
9
|
+
## 0.2.0 (2020-08-31)
|
10
|
+
|
11
|
+
### Added
|
12
|
+
|
13
|
+
- Flaky jobs are now printed by the reporter in the final build output and also
|
14
|
+
emitted to Sentry (if the integration is enabled) [[#26](https://github.com/skroutz/rspecq/pull/26)]
|
15
|
+
|
7
16
|
## 0.1.0 (2020-08-27)
|
8
17
|
|
9
18
|
### Added
|
data/README.md
CHANGED
@@ -13,7 +13,7 @@ and [ci-queue](https://github.com/Shopify/ci-queue).
|
|
13
13
|
|
14
14
|
## Features
|
15
15
|
|
16
|
-
- Run an RSpec suite among many workers
|
16
|
+
- Run an RSpec suite among many workers
|
17
17
|
(potentially located in different hosts) in a distributed fashion,
|
18
18
|
facilitating faster CI builds.
|
19
19
|
- Consolidated, real-time reporting of a build's progress.
|
@@ -21,11 +21,11 @@ and [ci-queue](https://github.com/Shopify/ci-queue).
|
|
21
21
|
automatically scheduling slow spec files as individual examples. See
|
22
22
|
[*Spec file splitting*](#spec-file-splitting).
|
23
23
|
- Automatic retry of test failures before being considered legit, in order to
|
24
|
-
rule out flakiness.
|
24
|
+
rule out flakiness. Additionally, flaky tests are detected and provided to
|
25
|
+
the user. See [*Requeues*](#requeues).
|
25
26
|
- Handles intermittent worker failures (e.g. network hiccups, faulty hardware etc.)
|
26
27
|
by detecting non-responsive workers and requeing their jobs. See [*Worker failures*](#worker-failures)
|
27
|
-
-
|
28
|
-
RSpecQ-level events.
|
28
|
+
- Sentry integration for monitoring build-level events. See [*Sentry integration*](#sentry-integration).
|
29
29
|
- [PLANNED] StatsD integration for various build-level metrics and insights.
|
30
30
|
See [#2](https://github.com/skroutz/rspecq/issues/2).
|
31
31
|
|
@@ -124,10 +124,13 @@ dynamically (see #3).
|
|
124
124
|
|
125
125
|
As a mitigation technique against flaky tests, if an example fails it will be
|
126
126
|
put back to the queue to be picked up by another worker. This will be repeated
|
127
|
-
up to a certain number of times (set with the `--max-requeues` option), after
|
128
|
-
which the example will be considered a legit failure and printed as such in the
|
127
|
+
up to a certain number of times (set with the `--max-requeues` option), after
|
128
|
+
which the example will be considered a legit failure and printed as such in the
|
129
129
|
final report.
|
130
130
|
|
131
|
+
Flaky tests are also detected and printed as such in the final report. They are
|
132
|
+
also emitted to Sentry (see [Sentry integration](#sentry-integration)).
|
133
|
+
|
131
134
|
### Worker failures
|
132
135
|
|
133
136
|
It's not uncommon for CI processes to encounter unrecoverable failures for
|
@@ -173,8 +176,8 @@ rejects).
|
|
173
176
|
The downside of this design is that it's more complicated, since the scheduling
|
174
177
|
of spec files happens based on timings calculated from previous runs. This
|
175
178
|
means that RSpecQ maintains a key with the timing of each job and updates it
|
176
|
-
on every run (if the `--timings` option was used). Also, RSpecQ has a
|
177
|
-
file threshold" which, currently has to be set manually (but this can be
|
179
|
+
on every run (if the `--update-timings` option was used). Also, RSpecQ has a
|
180
|
+
"slow file threshold" which, currently has to be set manually (but this can be
|
178
181
|
improved in the future).
|
179
182
|
|
180
183
|
|
data/lib/rspecq/queue.rb
CHANGED
@@ -184,6 +184,7 @@ module RSpecQ
|
|
184
184
|
@redis.hgetall(key_errors)
|
185
185
|
end
|
186
186
|
|
187
|
+
# True if the build is complete, false otherwise
|
187
188
|
def exhausted?
|
188
189
|
return false if !published?
|
189
190
|
|
@@ -216,6 +217,19 @@ module RSpecQ
|
|
216
217
|
@redis.lrange(key_queue_unprocessed, 0, -1)
|
217
218
|
end
|
218
219
|
|
220
|
+
# Returns the jobs considered flaky (i.e. initially failed but passed
|
221
|
+
# after being retried). Must be called after the build is complete,
|
222
|
+
# otherwise an exception will be raised.
|
223
|
+
def flaky_jobs
|
224
|
+
raise "Queue is not yet exhausted" if !exhausted?
|
225
|
+
|
226
|
+
requeued = @redis.hkeys(key_requeues)
|
227
|
+
|
228
|
+
return [] if requeued.empty?
|
229
|
+
|
230
|
+
requeued - @redis.hkeys(key_failures)
|
231
|
+
end
|
232
|
+
|
219
233
|
# redis: STRING [STATUS_INITIALIZING, STATUS_READY]
|
220
234
|
def key_queue_status
|
221
235
|
key("queue", "status")
|
data/lib/rspecq/reporter.rb
CHANGED
@@ -45,8 +45,13 @@ module RSpecQ
|
|
45
45
|
raise "Build not finished after #{@timeout} seconds" if !finished
|
46
46
|
|
47
47
|
@queue.record_build_time(tests_duration)
|
48
|
+
|
49
|
+
flaky_jobs = @queue.flaky_jobs
|
50
|
+
|
48
51
|
puts summary(@queue.example_failures, @queue.non_example_errors,
|
49
|
-
|
52
|
+
flaky_jobs, humanize_duration(tests_duration))
|
53
|
+
|
54
|
+
flaky_jobs_to_sentry(flaky_jobs, tests_duration)
|
50
55
|
|
51
56
|
exit 1 if !@queue.build_successful?
|
52
57
|
end
|
@@ -60,7 +65,7 @@ module RSpecQ
|
|
60
65
|
end
|
61
66
|
|
62
67
|
# We try to keep this output consistent with RSpec's original output
|
63
|
-
def summary(failures, errors, duration)
|
68
|
+
def summary(failures, errors, flaky_jobs, duration)
|
64
69
|
failed_examples_section = "\nFailed examples:\n\n"
|
65
70
|
|
66
71
|
failures.each do |_job, msg|
|
@@ -81,6 +86,14 @@ module RSpecQ
|
|
81
86
|
"#{errors.count} errors"
|
82
87
|
summary << "\n\n"
|
83
88
|
summary << "Spec execution time: #{duration}"
|
89
|
+
|
90
|
+
if !flaky_jobs.empty?
|
91
|
+
summary << "\n\n"
|
92
|
+
summary << "Flaky jobs detected (count=#{flaky_jobs.count}):\n"
|
93
|
+
flaky_jobs.each { |j| summary << " #{j}\n" }
|
94
|
+
end
|
95
|
+
|
96
|
+
summary
|
84
97
|
end
|
85
98
|
|
86
99
|
def failure_formatted(rspec_output)
|
@@ -90,5 +103,20 @@ module RSpecQ
|
|
90
103
|
def humanize_duration(seconds)
|
91
104
|
Time.at(seconds).utc.strftime("%H:%M:%S")
|
92
105
|
end
|
106
|
+
|
107
|
+
def flaky_jobs_to_sentry(jobs, build_duration)
|
108
|
+
return if jobs.empty?
|
109
|
+
|
110
|
+
Raven.capture_message("Flaky jobs detected", level: "warning", extra: {
|
111
|
+
build: @build_id,
|
112
|
+
build_timeout: @timeout,
|
113
|
+
queue: @queue.inspect,
|
114
|
+
object: self.inspect,
|
115
|
+
pid: Process.pid,
|
116
|
+
flaky_jobs: jobs,
|
117
|
+
flaky_jobs_count: jobs.count,
|
118
|
+
build_duration: build_duration
|
119
|
+
})
|
120
|
+
end
|
93
121
|
end
|
94
122
|
end
|
data/lib/rspecq/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rspecq
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Agis Anastasopoulos
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-08-
|
11
|
+
date: 2020-08-31 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rspec-core
|
@@ -148,7 +148,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
148
148
|
- !ruby/object:Gem::Version
|
149
149
|
version: '0'
|
150
150
|
requirements: []
|
151
|
-
|
151
|
+
rubyforge_project:
|
152
|
+
rubygems_version: 2.7.6.2
|
152
153
|
signing_key:
|
153
154
|
specification_version: 4
|
154
155
|
summary: Optimally distribute and run RSpec suites among parallel workers; for faster
|