quarantine 0.0.7

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 85d2c80359510de3dfd3d4c84cea8c04efed552bc11b44eed887f87caf7cd556
4
+ data.tar.gz: 2b075d8cde72b8451c9decbfacc24f0f18022fe446abf13c1a835cc9abd4a39b
5
+ SHA512:
6
+ metadata.gz: 57babcb9ddb17b96c48d3800f9af910998efd2a52cc68ad0b982edf7d0e84fa0f43f2918db039e59bf3ef855861602b662dd0e5beb3d9073e5f5e5247ba18c6a
7
+ data.tar.gz: 0ac7fa45415f46529fee23088a41746e80fd096cb5aea55d181b9147add6b70d67fe5b48407e1508390a69c310a878f96887149b7767170b66a5d97e4efa967d
data/README.md ADDED
@@ -0,0 +1,154 @@
1
+ # Quarantine
2
+ [![Build Status](https://travis-ci.com/flexport/quarantine.svg?branch=master)](https://travis-ci.com/flexport/quarantine)
3
+
4
+ Quarantine provides a run-time solution to diagnosing and disabling flaky tests and automates the workflow around test suite maintenance.
5
+
6
+ The quarantine gem supports testing frameworks:
7
+ - [RSpec](http://rspec.info/)
8
+
9
+ The quarantine gem supports CI pipelines:
10
+ - [Buildkite](https://buildkite.com/docs/tutorials/getting-started)
11
+
12
+ If you are interested in using quarantine but it does not support your CI or testing framework, feel free to reach out or create an issue and we can try to make it happen.
13
+
14
+ ## Purpose
15
+ Flaky tests impact engineering velocity, reduce faith in test reliablity and give a false representation of code coverage. Managing flaky tests is a clunky process that involves constant build monitorization, difficult diagnosis and manual ticket creation. As a result, here at Flexport, we have created a Gem to automate the entire process to help improve the workflow and keep our massive test suites in pristine condition.
16
+
17
+ The workflow at Flexport involves:
18
+
19
+ ![ideal workflow](misc/flexport_workflow.png)
20
+
21
+ ---
22
+ ## Installation and Setup
23
+
24
+ Add these lines to your application's Gemfile:
25
+ ```
26
+ group :test do
27
+ gem 'quarantine'
28
+ gem 'rspec-retry
29
+ end
30
+ ```
31
+
32
+ And then execute:
33
+ ```
34
+ bundle install
35
+ ```
36
+
37
+ In your `spec_helper.rb` setup quarantine and rspec-retry gem. Click [rspec-retry](https://github.com/NoRedInk/rspec-retry) to get a more detailed explaination on rspec-retry configurations and how to setup.
38
+ ```
39
+ require 'quarantine'
40
+ require 'rspec-retry'
41
+
42
+ Quarantine.bind({database: :dynamodb, aws_region: 'us-west-1'})
43
+
44
+ RSpec.configure do |config|
45
+
46
+ config.around(:each) do |ex|
47
+ ex.run_with_retry(retry: 3)
48
+ end
49
+
50
+ end
51
+ ```
52
+
53
+ Consider wrapping `Quarantine.bind` in if statements so local flaky tests don't pollute the list of quarantined tests
54
+
55
+ ```
56
+ if ENV[CI] && ENV[BRANCH] == "master"
57
+ Quarantine.bind({database: :dynamodb, aws_region: 'us-west-1'})
58
+ end
59
+ ```
60
+
61
+ Setup tables in AWS DynamoDB to support pulling and uploading quarantined tests
62
+ ```
63
+ bundle exec quarantine_dynamodb -h # see all options
64
+
65
+ bundle exec quarantine_dynamodb \ # create the tables in us-west-1 in aws dynamodb
66
+ --aws_region us-west-1 # with "quarantine_list" and "master_failed_tests"
67
+ # table names
68
+ ```
69
+
70
+ You are all set to start quarantining tests!
71
+
72
+ ## Try Quarantining Tests Locally
73
+ Add a test that will flake
74
+ ```
75
+ require "spec_helper"
76
+
77
+ describe Quarantine do
78
+ it "this test should flake 33% of the time" do
79
+ Random.rand(3).to eq(3)
80
+ end
81
+ end
82
+ ```
83
+
84
+ Run `rspec` on the test
85
+ ```
86
+ CI=1 BRANCH=master rspec <filename>
87
+ ```
88
+
89
+ If the test fails and passes on the test run (rspec-retry re-ran the test), the test should be quarantined and uploaded to DynamoDB. Check the `quarantine_list` table in DynamoDB.
90
+
91
+ ## Configuration
92
+
93
+ Go to `spec/spec_helper.rb` and set configuration variables through:
94
+ ```
95
+ RSpec.configure do |config|
96
+ config.VAR_NAME = VALUE
97
+ end
98
+ ```
99
+ - Table name for quarantined tests `:quarantine_list_table, default: "quarantine_list"`
100
+
101
+ - Table name where failed test are uploaded `:quarantine_failed_tests_table, default: "master_failed_tests"`
102
+
103
+ - Quarantined tests are not skipped automatically `:skip_quarantined_tests, default: true`
104
+
105
+ - Recording failed tests `:quarantine_record_failed_tests, default: true`
106
+
107
+ - Recording flaky tests `:quarantine_record_flaky_tests, default: true`
108
+
109
+ - Outputting quarantined gem info `:quarantine_logging, default: true`
110
+
111
+ ---
112
+ ## Setup Jira Workflow
113
+
114
+ To automatically create Jira tickets, take a look at: `examples/create_tickets.rb`
115
+
116
+ To automatically unquarantine tests on Jira ticket completion, take a look at: `examples/unquarantine.rb`
117
+
118
+ ---
119
+ ## Contributing
120
+ 1. Create an issue regarding a bug fix or feature request
121
+ 2. Fork the repository
122
+ 3. Create your feature branch, commit changes and create a pull request
123
+
124
+ ## Contributors
125
+ - [Eric Zhu](https://github.com/eric-zhu-uw)
126
+ - [Kevin Miller](https://github.com/Gasparila)
127
+ - [Nicholas Silva](https://github.com/flexportnes)
128
+ - [Ankur Dahiya](https://github.com/legalosLOTR)
129
+ ---
130
+
131
+ ## FAQs
132
+
133
+ #### Why are quarantined tests not being skipped locally?
134
+
135
+ The `quarantine` gem may be configured to only run on certain environments. Make sure you pass all these `ENV` variables to `rspec` when you call it locally
136
+
137
+ ```
138
+ CI="1" BRANCH="master" rspec
139
+ ```
140
+
141
+ #### Why is dynamodb failing to connect?
142
+
143
+ The AWS client loads credentials from the following locations:
144
+ - `ENV['AWS_ACCESS_KEY_ID']` and `ENV['AWS_SECRET_ACCESS_KEY']`
145
+ - `Aws.config[:credentials]`
146
+ - The shared credentials ini file at `~/.aws/credentials`
147
+
148
+ To get AWS credentials, please contact your AWS administrator to get access to dynamodb and create your credentials through IAM.
149
+
150
+ More detailed information can be found: [AWS documentation](https://docs.aws.amazon.com/sdkforruby/api/Aws/S3/Client.html)
151
+
152
+ #### Why is `example.clear_exception` failing locally?
153
+
154
+ `example.clear_exception` is an attribute added through `rspec_retry`. Make sure `rspec-retry` has been installed and configured.
@@ -0,0 +1,10 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'aws-sdk'
4
+ require 'optparse'
5
+
6
+ require_relative '../lib/quarantine/cli'
7
+
8
+ cli = Quarantine::CLI.new
9
+ cli.parse
10
+ cli.create_tables
@@ -0,0 +1,85 @@
1
+ require 'optparse'
2
+ require_relative 'databases/base'
3
+ require_relative 'databases/dynamo_db'
4
+
5
+ class Quarantine
6
+ class CLI
7
+ attr_accessor :options
8
+
9
+ def initialize
10
+ # default options
11
+ @options = {
12
+ quarantine_list_table_name: 'quarantine_list',
13
+ failed_test_table_name: 'master_failed_tests'
14
+ }
15
+ end
16
+
17
+ def parse
18
+ OptionParser.new do |parser|
19
+ parser.banner = 'Usage: quarantine_dynamodb [options]'
20
+
21
+ parser.on('-rREGION', '--aws_region=REGION', String, 'Specify the aws region for DynamoDB') do |aws_region|
22
+ options[:aws_region] = aws_region
23
+ end
24
+
25
+ parser.on(
26
+ '-qTABLE',
27
+ '--quarantine_table=TABLE',
28
+ String,
29
+ "Specify the table name for the quarantine list | Default: #{options[:quarantine_list_table_name]}"
30
+ ) do |table_name|
31
+ options[:quarantine_list_table_name] = table_name
32
+ end
33
+
34
+ parser.on(
35
+ '-fTABLE',
36
+ '--failed_table=TABLE',
37
+ String,
38
+ "Specify the table name for the failed test list | Default: #{options[:failed_test_table_name]}"
39
+ ) do |table_name|
40
+ options[:failed_test_table_name] = table_name
41
+ end
42
+
43
+ parser.on('-h', '--help', 'Prints help page') do
44
+ puts parser # rubocop:disable Rails/Output
45
+ exit
46
+ end
47
+ end.parse!
48
+
49
+ if options[:aws_region].nil?
50
+ error_msg = 'Failed to specify the required aws region with -r option'.freeze
51
+ warn error_msg
52
+ raise ArgumentError.new(error_msg)
53
+ end
54
+ end
55
+
56
+ # TODO: eventually move to a separate file & create_table by db type when my db adapters
57
+ def create_tables
58
+ dynamodb = Quarantine::Databases::DynamoDB.new(options)
59
+
60
+ attributes = [
61
+ { attribute_name: 'id', attribute_type: 'S', key_type: 'HASH' },
62
+ { attribute_name: 'build_number', attribute_type: 'S', key_type: 'RANGE' }
63
+ ]
64
+
65
+ additional_arguments = {
66
+ provisioned_throughput: {
67
+ read_capacity_units: 10,
68
+ write_capacity_units: 5
69
+ }
70
+ }
71
+
72
+ begin
73
+ dynamodb.create_table(options[:quarantine_list_table_name], attributes, additional_arguments)
74
+ rescue Quarantine::DatabaseError => e
75
+ warn "#{e&.cause&.class}: #{e&.cause&.message}"
76
+ end
77
+
78
+ begin
79
+ dynamodb.create_table(options[:failed_test_table_name], attributes, additional_arguments)
80
+ rescue Quarantine::DatabaseError => e
81
+ warn "#{e&.cause&.class}: #{e&.cause&.message}"
82
+ end
83
+ end
84
+ end
85
+ end
@@ -0,0 +1,17 @@
1
+ class Quarantine
2
+ module Databases
3
+ class Base
4
+ def initialize
5
+ raise NotImplementedError
6
+ end
7
+
8
+ def scan
9
+ raise NotImplementedError
10
+ end
11
+
12
+ def batch_write_item
13
+ raise NotImplementedError
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,77 @@
1
+ require 'aws-sdk'
2
+ require 'quarantine/databases/base'
3
+ require 'quarantine/error'
4
+
5
+ class Quarantine
6
+ module Databases
7
+ class DynamoDB < Base
8
+ attr_accessor :dynamodb
9
+
10
+ def initialize(aws_region: 'us-west-1', **_additional_arguments)
11
+ @dynamodb = Aws::DynamoDB::Client.new({ region: aws_region })
12
+ end
13
+
14
+ def scan(table_name)
15
+ begin
16
+ result = dynamodb.scan({ table_name: table_name })
17
+ rescue Aws::DynamoDB::Errors::ServiceError
18
+ raise Quarantine::DatabaseError
19
+ end
20
+
21
+ result&.items
22
+ end
23
+
24
+ def batch_write_item(table_name, items, additional_attributes = {})
25
+ dynamodb.batch_write_item(
26
+ { request_items: {
27
+ table_name => items.map do |item|
28
+ {
29
+ put_request: {
30
+ item: { **item.to_hash, **additional_attributes }
31
+ }
32
+ }
33
+ end
34
+ } }
35
+ )
36
+ rescue Aws::DynamoDB::Errors::ServiceError
37
+ raise Quarantine::DatabaseError
38
+ end
39
+
40
+ def delete_item(table_name, keys)
41
+ dynamodb.delete_item(
42
+ {
43
+ table_name: table_name,
44
+ key: {
45
+ **keys
46
+ }
47
+ }
48
+ )
49
+ rescue Aws::DynamoDB::Errors::ServiceError
50
+ raise Quarantine::DatabaseError
51
+ end
52
+
53
+ def create_table(table_name, attributes, additional_arguments = {})
54
+ dynamodb.create_table(
55
+ {
56
+ table_name: table_name,
57
+ attribute_definitions: attributes.map do |attribute|
58
+ {
59
+ attribute_name: attribute[:attribute_name],
60
+ attribute_type: attribute[:attribute_type]
61
+ }
62
+ end,
63
+ key_schema: attributes.map do |attribute|
64
+ {
65
+ attribute_name: attribute[:attribute_name],
66
+ key_type: attribute[:key_type]
67
+ }
68
+ end,
69
+ **additional_arguments
70
+ }
71
+ )
72
+ rescue Aws::DynamoDB::Errors::ServiceError
73
+ raise Quarantine::DatabaseError
74
+ end
75
+ end
76
+ end
77
+ end
@@ -0,0 +1,13 @@
1
+ class Quarantine
2
+ class Error < StandardError; end
3
+
4
+ # Raised when a database error has occured
5
+ # TODO(ezhu): expand error messages to cover more specific error messages
6
+ class DatabaseError < Error; end
7
+
8
+ # Raised when quarantine does not know how to upload a specific test
9
+ class UnknownUploadError < Error; end
10
+
11
+ # Quarantine does not work with the specificed database
12
+ class UnsupportedDatabaseError < Error; end
13
+ end
@@ -0,0 +1,85 @@
1
+ module RSpecAdapter
2
+ # Purpose: create an instance of Quarantine which contains information
3
+ # about the test suite (ie. quarantined tests) and binds RSpec configurations
4
+ # and hooks onto the global RSpec class
5
+ def bind(options = {})
6
+ quarantine = Quarantine.new(options)
7
+ bind_rspec_configurations
8
+ bind_quarantine_list(quarantine)
9
+ bind_quarantine_checker(quarantine)
10
+ bind_quarantine_record_tests(quarantine)
11
+ bind_logger(quarantine)
12
+ end
13
+
14
+ private
15
+
16
+ # Purpose: binds rspec configuration variables
17
+ def bind_rspec_configurations
18
+ ::RSpec.configure do |config|
19
+ config.add_setting(:quarantine_list_table, { default: 'quarantine_list' })
20
+ config.add_setting(:quarantine_failed_tests_table, { default: 'master_failed_tests' })
21
+ config.add_setting(:skip_quarantined_tests, { default: true })
22
+ config.add_setting(:quarantine_record_failed_tests, { default: true })
23
+ config.add_setting(:quarantine_record_flaky_tests, { default: true })
24
+ config.add_setting(:quarantine_logging, { default: true })
25
+ end
26
+ end
27
+
28
+ # Purpose: binds quarantine to fetch the quarantine_list from dynamodb in the before suite
29
+ def bind_quarantine_list(quarantine)
30
+ ::RSpec.configure do |config|
31
+ config.before(:suite) do
32
+ quarantine.fetch_quarantine_list
33
+ end
34
+ end
35
+ end
36
+
37
+ # Purpose: binds quarantine to skip and pass tests that have been quarantined in the after suite
38
+ def bind_quarantine_checker(quarantine)
39
+ ::RSpec.configure do |config|
40
+ config.after(:each) do |example|
41
+ if RSpec.configuration.skip_quarantined_tests && quarantine.test_quarantined?(example)
42
+ quarantine.pass_flaky_test(example)
43
+ end
44
+ end
45
+ end
46
+ end
47
+
48
+ # Purpose: binds quarantine to record failed and flaky tests
49
+ def bind_quarantine_record_tests(quarantine)
50
+ ::RSpec.configure do |config|
51
+ config.after(:each) do |example|
52
+ metadata = example.metadata
53
+
54
+ # will record the failed test if is not quarantined and it is on it's final retry from the rspec-retry gem
55
+ quarantine.record_failed_test(example) if
56
+ RSpec.configuration.quarantine_record_failed_tests &&
57
+ !quarantine.test_quarantined?(example) &&
58
+ metadata[:retry_attempts] + 1 == metadata[:retry] && example.exception
59
+
60
+ # will record the flaky test if is not quarantined and it failed the first run but passed a subsequent run
61
+ quarantine.record_flaky_test(example) if
62
+ RSpec.configuration.quarantine_record_flaky_tests &&
63
+ !quarantine.test_quarantined?(example) &&
64
+ metadata[:retry_attempts] > 0 && example.exception.nil?
65
+ end
66
+ end
67
+
68
+ ::RSpec.configure do |config|
69
+ config.after(:suite) do
70
+ quarantine.upload_tests(:failed) if RSpec.configuration.quarantine_record_failed_tests
71
+
72
+ quarantine.upload_tests(:flaky) if RSpec.configuration.quarantine_record_flaky_tests
73
+ end
74
+ end
75
+ end
76
+
77
+ # Purpose: binds quarantine logger to output test to RSpec formatter messages
78
+ def bind_logger(quarantine)
79
+ ::RSpec.configure do |config|
80
+ config.after(:suite) do
81
+ RSpec.configuration.reporter.message(quarantine.summary) if RSpec.configuration.quarantine_logging
82
+ end
83
+ end
84
+ end
85
+ end
@@ -0,0 +1,24 @@
1
+ class Quarantine
2
+ class Test
3
+ attr_accessor :id
4
+ attr_accessor :full_description
5
+ attr_accessor :location
6
+ attr_accessor :build_number
7
+
8
+ def initialize(id, full_description, location, build_number)
9
+ @id = id
10
+ @full_description = full_description
11
+ @location = location
12
+ @build_number = build_number
13
+ end
14
+
15
+ def to_hash
16
+ {
17
+ id: id,
18
+ full_description: full_description,
19
+ location: location,
20
+ build_number: build_number
21
+ }
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,3 @@
1
+ class Quarantine
2
+ VERSION = '0.0.7'.freeze
3
+ end
data/lib/quarantine.rb ADDED
@@ -0,0 +1,142 @@
1
+ require 'aws-sdk'
2
+ require 'rspec/retry'
3
+ require 'quarantine/rspec_adapter'
4
+ require 'quarantine/test'
5
+ require 'quarantine/databases/base'
6
+ require 'quarantine/databases/dynamo_db'
7
+
8
+ class Quarantine
9
+ extend RSpecAdapter
10
+
11
+ attr_accessor :database
12
+ attr_reader :quarantine_map
13
+ attr_reader :failed_tests
14
+ attr_reader :flaky_tests
15
+ attr_reader :duplicate_tests
16
+ attr_reader :buildkite_build_number
17
+ attr_reader :summary
18
+
19
+ def initialize(options = {})
20
+ case options[:database]
21
+ # default database option is dynamodb
22
+ when :dynamodb, nil
23
+ @database = Quarantine::Databases::DynamoDB.new(options)
24
+ else
25
+ raise Quarantine::UnsupportedDatabaseError.new("Quarantine does not support #{options[:database]}")
26
+ end
27
+
28
+ @quarantine_map = {}
29
+ @failed_tests = []
30
+ @flaky_tests = []
31
+ @buildkite_build_number = ENV['BUILDKITE_BUILD_NUMBER'] || '-1'
32
+ @summary = { id: 'quarantine', quarantined_tests: [], flaky_tests: [], database_failures: [] }
33
+ end
34
+
35
+ # Scans the quarantine_list from the database and store the individual tests in quarantine_map
36
+ def fetch_quarantine_list
37
+ begin
38
+ quarantine_list = database.scan(RSpec.configuration.quarantine_list_table)
39
+ rescue Quarantine::DatabaseError => e
40
+ add_to_summary(:database_failures, "#{e&.cause&.class}: #{e&.cause&.message}")
41
+ raise Quarantine::DatabaseError.new(
42
+ <<~ERROR_MSG
43
+ Failed to pull the quarantine list from #{RSpec.configuration.quarantine_list_table}
44
+ because of #{e&.cause&.class}: #{e&.cause&.message}
45
+ ERROR_MSG
46
+ )
47
+ end
48
+
49
+ quarantine_list.each do |example|
50
+ # on the rare occassion there are duplicate tests ids in the quarantine_list,
51
+ # quarantine the most recent instance of the test (det. through build_number)
52
+ # and ignore the older instance of the test
53
+ next if
54
+ quarantine_map.key?(example['id']) &&
55
+ example['build_number'].to_i < quarantine_map[example['id']].build_number.to_i
56
+
57
+ quarantine_map.store(
58
+ example['id'],
59
+ Quarantine::Test.new(example['id'], example['full_description'], example['location'], example['build_number'])
60
+ )
61
+ end
62
+ end
63
+
64
+ # Based off the type, upload a list of tests to a particular database table
65
+ def upload_tests(type)
66
+ if type == :failed
67
+ tests = failed_tests
68
+ table_name = RSpec.configuration.quarantine_failed_tests_table
69
+ elsif type == :flaky
70
+ tests = flaky_tests
71
+ table_name = RSpec.configuration.quarantine_list_table
72
+ else
73
+ raise Quarantine::UnknownUploadError.new(
74
+ "Quarantine gem did not know how to handle #{type} upload of tests to dynamodb"
75
+ )
76
+ end
77
+
78
+ return unless tests.length < 10 && tests.length > 0
79
+
80
+ begin
81
+ timestamp = Time.now.to_i / 1000 # Truncated millisecond from timestamp for reasons specific to Flexport
82
+ database.batch_write_item(
83
+ table_name,
84
+ tests,
85
+ {
86
+ build_job_id: ENV['BUILDKITE_JOB_ID'] || '-1',
87
+ created_at: timestamp,
88
+ updated_at: timestamp
89
+ }
90
+ )
91
+ rescue Quarantine::DatabaseError => e
92
+ add_to_summary(:database_failures, "#{e&.cause&.class}: #{e&.cause&.message}")
93
+ end
94
+ end
95
+
96
+ # Param: RSpec::Core::Example
97
+ # Add the example to the internal failed tests list
98
+ def record_failed_test(example)
99
+ failed_tests << Quarantine::Test.new(
100
+ example.id,
101
+ example.full_description,
102
+ example.location,
103
+ buildkite_build_number
104
+ )
105
+ end
106
+
107
+ # Param: RSpec::Core::Example
108
+ # Add the example to the internal flaky tests list
109
+ def record_flaky_test(example)
110
+ flaky_test = Quarantine::Test.new(
111
+ example.id,
112
+ example.full_description,
113
+ example.location,
114
+ buildkite_build_number
115
+ )
116
+
117
+ flaky_tests << flaky_test
118
+ add_to_summary(:flaky_tests, flaky_test.id)
119
+ end
120
+
121
+ # Param: RSpec::Core::Example
122
+ # Clear exceptions on a flaky tests that has been quarantined
123
+ #
124
+ # example.clear_exception is tightly coupled with the rspec-retry gem and will only exist if
125
+ # the rspec-retry gem is enabled
126
+ def pass_flaky_test(example)
127
+ example.clear_exception
128
+ add_to_summary(:quarantined_tests, example.id)
129
+ end
130
+
131
+ # Param: RSpec::Core::Example
132
+ # Check the internal quarantine_map to see if this test should be quarantined
133
+ def test_quarantined?(example)
134
+ quarantine_map.key?(example.id)
135
+ end
136
+
137
+ # Param: Symbol, Any
138
+ # Adds the item to the specified attribute in summary
139
+ def add_to_summary(attribute, item)
140
+ summary[attribute] << item if summary.key?(attribute)
141
+ end
142
+ end
@@ -0,0 +1,23 @@
1
+ # TEAM: backend_infra
2
+ #
3
+ $LOAD_PATH.push(File.expand_path('lib', __dir__))
4
+
5
+ # Maintain your gem's version:
6
+ require 'quarantine/version'
7
+
8
+ # Describe your gem and declare its dependencies:
9
+ Gem::Specification.new do |s|
10
+ s.name = 'quarantine'
11
+ s.version = Quarantine::VERSION
12
+ s.authors = ['Flexport Engineering, Eric Zhu']
13
+ s.email = ['ericzhu77@gmail.com']
14
+ s.summary = 'Quarantine flaky Ruby Rspec tests'
15
+ s.homepage = 'https://github.com/flexport/quarantine'
16
+ s.license = 'MIT'
17
+ s.files = Dir['{lib, bin}/**/*', '*.md', '*.gemspec']
18
+ s.executables = ['quarantine_dynamodb']
19
+
20
+ s.add_dependency('aws-sdk', '~> 2.11.41')
21
+ s.add_dependency('rspec', '>= 3.0')
22
+ s.add_dependency('rspec-retry', '>= 0.6.1')
23
+ end
metadata ADDED
@@ -0,0 +1,97 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: quarantine
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.7
5
+ platform: ruby
6
+ authors:
7
+ - Flexport Engineering, Eric Zhu
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2019-04-22 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: aws-sdk
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: 2.11.41
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: 2.11.41
27
+ - !ruby/object:Gem::Dependency
28
+ name: rspec
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '3.0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '3.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rspec-retry
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: 0.6.1
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: 0.6.1
55
+ description:
56
+ email:
57
+ - ericzhu77@gmail.com
58
+ executables:
59
+ - quarantine_dynamodb
60
+ extensions: []
61
+ extra_rdoc_files: []
62
+ files:
63
+ - README.md
64
+ - bin/quarantine_dynamodb
65
+ - lib/quarantine.rb
66
+ - lib/quarantine/cli.rb
67
+ - lib/quarantine/databases/base.rb
68
+ - lib/quarantine/databases/dynamo_db.rb
69
+ - lib/quarantine/error.rb
70
+ - lib/quarantine/rspec_adapter.rb
71
+ - lib/quarantine/test.rb
72
+ - lib/quarantine/version.rb
73
+ - quarantine.gemspec
74
+ homepage: https://github.com/flexport/quarantine
75
+ licenses:
76
+ - MIT
77
+ metadata: {}
78
+ post_install_message:
79
+ rdoc_options: []
80
+ require_paths:
81
+ - lib
82
+ required_ruby_version: !ruby/object:Gem::Requirement
83
+ requirements:
84
+ - - ">="
85
+ - !ruby/object:Gem::Version
86
+ version: '0'
87
+ required_rubygems_version: !ruby/object:Gem::Requirement
88
+ requirements:
89
+ - - ">="
90
+ - !ruby/object:Gem::Version
91
+ version: '0'
92
+ requirements: []
93
+ rubygems_version: 3.0.2
94
+ signing_key:
95
+ specification_version: 4
96
+ summary: Quarantine flaky Ruby Rspec tests
97
+ test_files: []