quarantine 2.1.2 → 2.1.3
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.
- checksums.yaml +4 -4
- data/lib/quarantine.rb +31 -22
- data/lib/quarantine/databases/google_sheets.rb +2 -2
- data/lib/quarantine/rspec_adapter.rb +21 -29
- data/lib/quarantine/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6ab8e4aa2ba3c2ab497cb3adfb08b6c14459eab525f26a00f4bc1fb9b27e1084
|
4
|
+
data.tar.gz: ffafe0bdf3508389ae614ab5b8946c4cb9b5303f7697ca4b378b6284f335375f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c4d12718e41b13558f30add75b2a5d5e25f5d29d4e19b55704e7500c1980f7192ed1a8fa3e4fc83e45329486c94bae42bd56f99a718144f42c6884878b926faf
|
7
|
+
data.tar.gz: 283aa10d1dafe98d3e5ed08f1add97facdcfbe6f4a1761759e42677b7dd26fafbc323d958ab81965076a1d19e951e18c67e35e01679ad43e44d622876649641f
|
data/lib/quarantine.rb
CHANGED
@@ -66,7 +66,7 @@ class Quarantine
|
|
66
66
|
|
67
67
|
# Scans the test_statuses from the database and store their IDs in quarantined_ids
|
68
68
|
sig { void }
|
69
|
-
def
|
69
|
+
def on_start
|
70
70
|
begin
|
71
71
|
test_statuses = database.fetch_items(@options[:test_statuses_table_name])
|
72
72
|
rescue Quarantine::DatabaseError => e
|
@@ -103,24 +103,40 @@ class Quarantine
|
|
103
103
|
end
|
104
104
|
|
105
105
|
sig { void }
|
106
|
-
def
|
107
|
-
|
106
|
+
def on_complete
|
107
|
+
quarantined_tests = @tests.values.select { |test| test.status == :quarantined }.sort_by(&:id)
|
108
108
|
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
)
|
115
|
-
|
116
|
-
|
109
|
+
if !@options[:record_tests]
|
110
|
+
log('Recording tests disabled; skipping')
|
111
|
+
elsif @tests.empty?
|
112
|
+
log('No tests found; skipping recording')
|
113
|
+
elsif quarantined_tests.count { |test| old_tests[test.id]&.status != :quarantined } >= @options[:failsafe_limit]
|
114
|
+
log('Number of quarantined tests above failsafe limit; skipping recording')
|
115
|
+
else
|
116
|
+
begin
|
117
|
+
timestamp = Time.now.to_i / 1000 # Truncated millisecond from timestamp for reasons specific to Flexport
|
118
|
+
database.write_items(
|
119
|
+
@options[:test_statuses_table_name],
|
120
|
+
@tests.values.map { |item| item.to_hash.merge('updated_at' => timestamp) }
|
121
|
+
)
|
122
|
+
rescue Quarantine::DatabaseError => e
|
123
|
+
@database_failures << "#{e.cause&.class}: #{e.cause&.message}"
|
124
|
+
end
|
117
125
|
end
|
126
|
+
|
127
|
+
log(<<~MESSAGE)
|
128
|
+
\n[quarantine] Quarantined tests:
|
129
|
+
#{quarantined_tests.map { |test| "#{test.id} #{test.full_description}" }.join("\n ")}
|
130
|
+
|
131
|
+
[quarantine] Database errors:
|
132
|
+
#{@database_failures.join("\n ")}
|
133
|
+
MESSAGE
|
118
134
|
end
|
119
135
|
|
120
136
|
# Param: RSpec::Core::Example
|
121
137
|
# Add the example to the internal tests list
|
122
138
|
sig { params(example: T.untyped, status: Symbol, passed: T::Boolean).void }
|
123
|
-
def
|
139
|
+
def on_test(example, status, passed:)
|
124
140
|
extra_attributes = @options[:extra_attributes] ? @options[:extra_attributes].call(example) : {}
|
125
141
|
|
126
142
|
new_consecutive_passes = passed ? (@old_tests[example.id]&.consecutive_passes || 0) + 1 : 0
|
@@ -145,15 +161,8 @@ class Quarantine
|
|
145
161
|
@old_tests[example.id]&.status == :quarantined
|
146
162
|
end
|
147
163
|
|
148
|
-
sig {
|
149
|
-
def
|
150
|
-
|
151
|
-
<<~MESSAGE
|
152
|
-
\n[quarantine] Quarantined tests:
|
153
|
-
#{quarantined_tests.map { |test| "#{test.id} #{test.full_description}" }.join("\n ")}
|
154
|
-
|
155
|
-
[quarantine] Database errors:
|
156
|
-
#{@database_failures.join("\n ")}
|
157
|
-
MESSAGE
|
164
|
+
sig { params(message: String).void }
|
165
|
+
def log(message)
|
166
|
+
@options[:log].call(message) if @options[:logging]
|
158
167
|
end
|
159
168
|
end
|
@@ -21,7 +21,7 @@ class Quarantine
|
|
21
21
|
sig { override.params(table_name: String).returns(T::Enumerable[Item]) }
|
22
22
|
def fetch_items(table_name)
|
23
23
|
parse_rows(spreadsheet.worksheet_by_title(table_name))
|
24
|
-
rescue GoogleDrive::Error
|
24
|
+
rescue GoogleDrive::Error, Google::Apis::Error
|
25
25
|
raise Quarantine::DatabaseError
|
26
26
|
end
|
27
27
|
|
@@ -56,7 +56,7 @@ class Quarantine
|
|
56
56
|
# Insert any items whose IDs weren't found in existing rows at the end
|
57
57
|
worksheet.insert_rows(parsed_rows.count + 2, new_rows)
|
58
58
|
worksheet.save
|
59
|
-
rescue GoogleDrive::Error
|
59
|
+
rescue GoogleDrive::Error, Google::Apis::Error
|
60
60
|
raise Quarantine::DatabaseError
|
61
61
|
end
|
62
62
|
|
@@ -4,16 +4,12 @@ class Quarantine
|
|
4
4
|
module RSpecAdapter
|
5
5
|
extend T::Sig
|
6
6
|
|
7
|
-
# Purpose: create an instance of Quarantine which contains information
|
8
|
-
# about the test suite (ie. quarantined tests) and binds RSpec configurations
|
9
|
-
# and hooks onto the global RSpec class
|
10
7
|
sig { void }
|
11
8
|
def self.bind
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
bind_logger
|
9
|
+
register_rspec_configurations
|
10
|
+
bind_on_start
|
11
|
+
bind_on_test
|
12
|
+
bind_on_complete
|
17
13
|
end
|
18
14
|
|
19
15
|
sig { returns(Quarantine) }
|
@@ -25,12 +21,15 @@ class Quarantine
|
|
25
21
|
extra_attributes: RSpec.configuration.quarantine_extra_attributes,
|
26
22
|
failsafe_limit: RSpec.configuration.quarantine_failsafe_limit,
|
27
23
|
release_at_consecutive_passes: RSpec.configuration.quarantine_release_at_consecutive_passes,
|
24
|
+
logging: RSpec.configuration.quarantine_logging,
|
25
|
+
log: method(:log),
|
26
|
+
record_tests: RSpec.configuration.quarantine_record_tests
|
28
27
|
)
|
29
28
|
end
|
30
29
|
|
31
30
|
# Purpose: binds rspec configuration variables
|
32
31
|
sig { void }
|
33
|
-
def self.
|
32
|
+
def self.register_rspec_configurations
|
34
33
|
::RSpec.configure do |config|
|
35
34
|
config.add_setting(:quarantine_database, default: { type: :dynamodb, region: 'us-west-1' })
|
36
35
|
config.add_setting(:quarantine_test_statuses, { default: 'test_statuses' })
|
@@ -45,17 +44,17 @@ class Quarantine
|
|
45
44
|
|
46
45
|
# Purpose: binds quarantine to fetch the test_statuses from dynamodb in the before suite
|
47
46
|
sig { void }
|
48
|
-
def self.
|
47
|
+
def self.bind_on_start
|
49
48
|
::RSpec.configure do |config|
|
50
49
|
config.before(:suite) do
|
51
|
-
Quarantine::RSpecAdapter.quarantine.
|
50
|
+
Quarantine::RSpecAdapter.quarantine.on_start
|
52
51
|
end
|
53
52
|
end
|
54
53
|
end
|
55
54
|
|
56
55
|
# Purpose: binds quarantine to record test statuses
|
57
56
|
sig { void }
|
58
|
-
def self.
|
57
|
+
def self.bind_on_test
|
59
58
|
::RSpec.configure do |config|
|
60
59
|
config.after(:each) do |example|
|
61
60
|
metadata = example.metadata
|
@@ -68,42 +67,35 @@ class Quarantine
|
|
68
67
|
# will record the failed test if it's final retry from the rspec-retry gem
|
69
68
|
if RSpec.configuration.skip_quarantined_tests && quarantined
|
70
69
|
example.clear_exception!
|
71
|
-
Quarantine::RSpecAdapter.quarantine.
|
70
|
+
Quarantine::RSpecAdapter.quarantine.on_test(example, :quarantined, passed: false)
|
72
71
|
else
|
73
|
-
Quarantine::RSpecAdapter.quarantine.
|
72
|
+
Quarantine::RSpecAdapter.quarantine.on_test(example, :failing, passed: false)
|
74
73
|
end
|
75
74
|
end
|
76
75
|
elsif metadata[:retry_attempts] > 0
|
77
76
|
# will record the flaky test if it failed the first run but passed a subsequent run
|
78
|
-
Quarantine::RSpecAdapter.quarantine.
|
77
|
+
Quarantine::RSpecAdapter.quarantine.on_test(example, :quarantined, passed: false)
|
79
78
|
elsif quarantined
|
80
|
-
Quarantine::RSpecAdapter.quarantine.
|
79
|
+
Quarantine::RSpecAdapter.quarantine.on_test(example, :quarantined, passed: true)
|
81
80
|
else
|
82
|
-
Quarantine::RSpecAdapter.quarantine.
|
81
|
+
Quarantine::RSpecAdapter.quarantine.on_test(example, :passing, passed: true)
|
83
82
|
end
|
84
83
|
end
|
85
84
|
end
|
86
85
|
end
|
87
86
|
|
88
87
|
sig { void }
|
89
|
-
def self.
|
88
|
+
def self.bind_on_complete
|
90
89
|
::RSpec.configure do |config|
|
91
90
|
config.after(:suite) do
|
92
|
-
Quarantine::RSpecAdapter.quarantine.
|
91
|
+
Quarantine::RSpecAdapter.quarantine.on_complete
|
93
92
|
end
|
94
93
|
end
|
95
94
|
end
|
96
95
|
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
::RSpec.configure do |config|
|
101
|
-
config.after(:suite) do
|
102
|
-
if RSpec.configuration.quarantine_logging
|
103
|
-
RSpec.configuration.reporter.message(Quarantine::RSpecAdapter.quarantine.summary)
|
104
|
-
end
|
105
|
-
end
|
106
|
-
end
|
96
|
+
sig { params(message: String).void }
|
97
|
+
def self.log(message)
|
98
|
+
RSpec.configuration.reporter.message(message)
|
107
99
|
end
|
108
100
|
end
|
109
101
|
end
|
data/lib/quarantine/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: quarantine
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.1.
|
4
|
+
version: 2.1.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Flexport Engineering, Eric Zhu
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-04-
|
11
|
+
date: 2021-04-15 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rspec
|