convox_installer 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,50 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support"
4
+ require "active_support/core_ext"
5
+ require "convox_installer/config"
6
+ require "convox_installer/requirements"
7
+ require "convox"
8
+
9
+ module ConvoxInstaller
10
+ def client
11
+ @client ||= Convox::Client.new(log_level: @log_level, config: config.config)
12
+ end
13
+
14
+ def config
15
+ options = {log_level: @log_level}
16
+ options[:prompts] = @prompts if @prompts
17
+ @config ||= Config.new(options)
18
+ end
19
+
20
+ def requirements
21
+ @requirements ||= Requirements.new(log_level: @log_level)
22
+ end
23
+
24
+ def ensure_requirements!
25
+ requirements.ensure_requirements!
26
+ end
27
+
28
+ def prompt_for_config
29
+ config.prompt_for_config
30
+ end
31
+
32
+ %w[
33
+ backup_convox_host_and_rack
34
+ install_convox
35
+ validate_convox_auth_and_set_host!
36
+ validate_convox_rack!
37
+ create_convox_app!
38
+ set_default_app_for_directory!
39
+ create_s3_bucket!
40
+ add_docker_registry!
41
+ s3_bucket_details
42
+ convox_rack_data
43
+ default_service_domain_name
44
+ run_convox_command!
45
+ ].each do |method|
46
+ define_method(method) do |*args|
47
+ client.send(method, *args)
48
+ end
49
+ end
50
+ end
data/log/.gitkeep ADDED
File without changes
@@ -0,0 +1,154 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "convox/client"
4
+
5
+ RSpec.describe Convox::Client do
6
+ let(:home_dir) { File.expand_path("~") }
7
+
8
+ it "finds the authentication details in ~/.convox/auth" do
9
+ expect(File).to receive(:exist?).with("#{home_dir}/.convox/auth").and_return(true)
10
+ expect(File).to receive(:read).with("#{home_dir}/.convox/auth").and_return(
11
+ '{ "test.example.com": "1234567890" }'
12
+ )
13
+ client = described_class.new
14
+ expect(client.auth).to eq("test.example.com" => "1234567890")
15
+ end
16
+
17
+ it "should backup existing Convox host and rack files" do
18
+ expect(File).to receive(:exist?).with(
19
+ "#{home_dir}/.convox/host"
20
+ ).and_return(true)
21
+ expect(File).to receive(:exist?).with(
22
+ "#{home_dir}/.convox/rack"
23
+ ).and_return(true)
24
+ expect(FileUtils).to receive(:mv).with(
25
+ "#{home_dir}/.convox/host", "#{home_dir}/.convox/host.bak"
26
+ )
27
+ expect(FileUtils).to receive(:mv).with(
28
+ "#{home_dir}/.convox/rack", "#{home_dir}/.convox/rack.bak"
29
+ )
30
+
31
+ client = described_class.new
32
+ expect(client.logger).to receive(:info).twice
33
+
34
+ client.backup_convox_host_and_rack
35
+ end
36
+
37
+ describe "#install" do
38
+ it "should require the correct config vars" do
39
+ client = described_class.new
40
+ expect { client.install_convox }.to raise_error("aws_region is missing from the config!")
41
+
42
+ client = described_class.new(config: {aws_region: "asdf"})
43
+ expect { client.install_convox }.to raise_error("aws_access_key_id is missing from the config!")
44
+ end
45
+
46
+ it "should run the correct convox CLI command" do
47
+ client = described_class.new(
48
+ config: {
49
+ aws_region: "us-east-1",
50
+ aws_access_key_id: "asdf",
51
+ aws_secret_access_key: "1234",
52
+ stack_name: "asdf",
53
+ instance_type: "t3.medium",
54
+ },
55
+ )
56
+
57
+ expect(client.logger).to receive(:info)
58
+ expect(client).to receive(:run_convox_command!).with(
59
+ "rack install aws --name \"asdf\" \"InstanceType=t3.medium\" " \
60
+ "\"BuildInstance=\"",
61
+ "AWS_ACCESS_KEY_ID" => "asdf",
62
+ "AWS_REGION" => "us-east-1",
63
+ "AWS_SECRET_ACCESS_KEY" => "1234",
64
+ )
65
+ client.install_convox
66
+ end
67
+ end
68
+
69
+ describe "#validate_convox_auth_and_set_host!" do
70
+ it "should require the correct config vars" do
71
+ client = described_class.new
72
+ expect { client.validate_convox_auth_and_set_host! }.to raise_error("aws_region is missing from the config!")
73
+ end
74
+
75
+ it "should raise an error if auth file is missing" do
76
+ client = described_class.new(
77
+ config: {
78
+ aws_region: "us-east-1",
79
+ stack_name: "asdf",
80
+ },
81
+ )
82
+ expect(File).to receive(:exist?).with(
83
+ "#{home_dir}/.convox/auth"
84
+ ).and_return(false)
85
+
86
+ expect {
87
+ client.validate_convox_auth_and_set_host!
88
+ }.to raise_error(/Could not find auth file at /)
89
+ end
90
+
91
+ it "should set ~/.convox/host if a matching host is found in the auth file" do
92
+ expect(File).to receive(:exist?).with(
93
+ "#{home_dir}/.convox/auth"
94
+ ).twice.and_return(true)
95
+
96
+ expect(File).to receive(:read).with("#{home_dir}/.convox/auth").and_return(
97
+ '{ "convox-test-697645520.us-west-2.elb.amazonaws.com": "1234567890" }'
98
+ )
99
+ client = described_class.new(
100
+ config: {
101
+ aws_region: "us-west-2",
102
+ stack_name: "convox-test",
103
+ },
104
+ )
105
+ expect(client).to receive(:set_host).with(
106
+ "convox-test-697645520.us-west-2.elb.amazonaws.com"
107
+ )
108
+ expect(client.validate_convox_auth_and_set_host!).to(
109
+ eq("convox-test-697645520.us-west-2.elb.amazonaws.com")
110
+ )
111
+ end
112
+
113
+ it "should raise an error if no matching host is found" do
114
+ expect(File).to receive(:exist?).with(
115
+ "#{home_dir}/.convox/auth"
116
+ ).twice.and_return(true)
117
+
118
+ expect(File).to receive(:read).with("#{home_dir}/.convox/auth").and_return(
119
+ '{ "convox-test-697645520.us-west-2.elb.amazonaws.com": "1234567890" }'
120
+ )
121
+ client = described_class.new(
122
+ config: {
123
+ aws_region: "us-east-1",
124
+ stack_name: "convox-test",
125
+ },
126
+ )
127
+ expect {
128
+ client.validate_convox_auth_and_set_host!
129
+ }.to raise_error("Could not find matching authentication for " \
130
+ "region: us-east-1, stack: convox-test")
131
+ end
132
+
133
+ it "should raise an error if it finds multiple matching hosts" do
134
+ expect(File).to receive(:exist?).with(
135
+ "#{home_dir}/.convox/auth"
136
+ ).twice.and_return(true)
137
+
138
+ expect(File).to receive(:read).with("#{home_dir}/.convox/auth").and_return(
139
+ '{ "convox-test-697645520.us-west-2.elb.amazonaws.com": "1234567890", ' \
140
+ '"convox-test-1234123412.us-west-2.elb.amazonaws.com": "1234567890" }'
141
+ )
142
+ client = described_class.new(
143
+ config: {
144
+ aws_region: "us-west-2",
145
+ stack_name: "convox-test",
146
+ },
147
+ )
148
+ expect {
149
+ client.validate_convox_auth_and_set_host!
150
+ }.to raise_error("Found multiple matching hosts for " \
151
+ "region: us-west-2, stack: convox-test")
152
+ end
153
+ end
154
+ end
@@ -0,0 +1,208 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "convox_installer"
4
+ require "securerandom"
5
+
6
+ RSpec.describe ConvoxInstaller::Config do
7
+ after(:each) do
8
+ ENV.delete "AWS_REGION"
9
+ ENV.delete "AWS_ACCESS_KEY_ID"
10
+ end
11
+
12
+ it "loads the saved config from ~/.convox/installer_config" do
13
+ expect(described_class).to receive(:config_file_exists?).and_return(true)
14
+ expect(described_class).to receive(:read_config_file).and_return(
15
+ '{ "config": { "aws_region": "us-west-2", "aws_access_key_id": "1234" } }'
16
+ )
17
+ config = described_class.new
18
+
19
+ expect(config.config).to eq(
20
+ aws_region: "us-west-2",
21
+ aws_access_key_id: "1234",
22
+ )
23
+ end
24
+
25
+ it "loads config from ENV vars" do
26
+ expect(described_class).to receive(:config_file_exists?).and_return(false)
27
+ ENV["AWS_REGION"] = "us-east-1"
28
+ ENV["AWS_ACCESS_KEY_ID"] = "2345"
29
+
30
+ config = described_class.new
31
+ expect(config.config).to eq(
32
+ aws_region: "us-east-1",
33
+ aws_access_key_id: "2345",
34
+ )
35
+ end
36
+
37
+ it "prompts the user for their AWS details, and re-prompts to correct mistakes" do
38
+ expect(described_class).to receive(:config_file_exists?).and_return(false)
39
+ input = StringIO.new
40
+ output = StringIO.new
41
+ highline = HighLine.new(input, output)
42
+
43
+ input << "\nus-north-12\nasdf\nxkcd\n\nn\nconvox-test\n\nsdfg\n\n\ny\n"
44
+ input.rewind
45
+
46
+ config = described_class.new(highline: highline)
47
+ expect(config).to receive(:save_config_to_file).exactly(10).times
48
+
49
+ expect(config.config).to eq({})
50
+ config.prompt_for_config
51
+ expect(config.config).to eq(
52
+ :stack_name => "convox-test",
53
+ :aws_access_key_id => "sdfg",
54
+ :aws_region => "us-north-12",
55
+ :aws_secret_access_key => "xkcd",
56
+ :instance_type => "t3.medium",
57
+ )
58
+ output.rewind
59
+ stripped_output = output.read.lines.map(&:rstrip).join("\n")
60
+ expected_output = <<-EOS
61
+ Please enter a name for your Convox installation |convox|
62
+ Please enter your AWS Region: |us-east-1|
63
+ Admin AWS Credentials
64
+ ============================================
65
+
66
+ Please enter your AWS Access Key ID: Please enter your AWS Secret Access Key: Please enter your EC2 Instance Type: |t3.medium|
67
+ ============================================
68
+ SUMMARY
69
+ ============================================
70
+
71
+ Convox Stack Name: convox
72
+ AWS Region: us-north-12
73
+ AWS Access Key ID: asdf
74
+ AWS Secret Access Key: xkcd
75
+ EC2 Instance Type: t3.medium
76
+
77
+ We've saved your configuration to: /Users/ndbroadbent/.convox/installer_config
78
+ If anything goes wrong during the installation, you can restart the script to reload the config and continue.
79
+
80
+ Please double check all of these configuration details.
81
+ Would you like to start the Convox installation? (press 'n' to correct any settings)
82
+
83
+ Please enter a name for your Convox installation |convox|
84
+ Please enter your AWS Region: |us-north-12|
85
+ Admin AWS Credentials
86
+ ============================================
87
+
88
+ Please enter your AWS Access Key ID: |asdf| Please enter your AWS Secret Access Key: |xkcd| Please enter your EC2 Instance Type: |t3.medium|
89
+ ============================================
90
+ SUMMARY
91
+ ============================================
92
+
93
+ Convox Stack Name: convox-test
94
+ AWS Region: us-north-12
95
+ AWS Access Key ID: sdfg
96
+ AWS Secret Access Key: xkcd
97
+ EC2 Instance Type: t3.medium
98
+
99
+ We've saved your configuration to: /Users/ndbroadbent/.convox/installer_config
100
+ If anything goes wrong during the installation, you can restart the script to reload the config and continue.
101
+
102
+ Please double check all of these configuration details.
103
+ Would you like to start the Convox installation? (press 'n' to correct any settings)
104
+ EOS
105
+
106
+ # puts stripped_output
107
+ # puts "---------------"
108
+ # puts expected_output
109
+ expect(stripped_output).to eq expected_output.strip
110
+ end
111
+
112
+ it "prompts for custom configuration" do
113
+ expect(described_class).to receive(:config_file_exists?).and_return(false)
114
+ input = StringIO.new
115
+ output = StringIO.new
116
+ highline = HighLine.new(input, output)
117
+
118
+ custom_prompts = ConvoxInstaller::Config::DEFAULT_PROMPTS + [
119
+ {
120
+ section: "ECR Authentication",
121
+ info: "You should have received authentication details for the Docker Registry\n" \
122
+ "via email. If not, please contact support@example.com",
123
+ },
124
+ {
125
+ key: :docker_registry_username,
126
+ title: "Docker Registry Access Key ID",
127
+ },
128
+ {
129
+ key: :docker_registry_password,
130
+ title: "Docker Registry Secret Access Key",
131
+ },
132
+ {
133
+ key: :admin_email,
134
+ title: "Admin Email",
135
+ prompt: "Please enter the email address you would like to use " \
136
+ "for the default admin user",
137
+ default: "admin@example.com",
138
+ },
139
+ {
140
+ key: :admin_password,
141
+ title: "Admin Password",
142
+ value: -> () { SecureRandom.hex(8) },
143
+ },
144
+ ]
145
+
146
+ input << "\n\nasdf\nxkcd\n\nsdfg\nqwer\n\ny\n"
147
+ input.rewind
148
+
149
+ config = described_class.new(highline: highline, prompts: custom_prompts)
150
+ expect(config).to receive(:save_config_to_file).exactly(8).times
151
+ expect(SecureRandom).to receive(:hex).with(8).and_return("99a6f67de0c7a117")
152
+
153
+ expect(config.config).to eq({})
154
+
155
+ config.prompt_for_config
156
+
157
+ expect(config.config).to eq(
158
+ :stack_name => "convox",
159
+ :aws_region => "us-east-1",
160
+ :aws_access_key_id => "asdf",
161
+ :aws_secret_access_key => "xkcd",
162
+ :instance_type => "t3.medium",
163
+ :docker_registry_username => "sdfg",
164
+ :docker_registry_password => "qwer",
165
+ :admin_email => "admin@example.com",
166
+ :admin_password => "99a6f67de0c7a117",
167
+ )
168
+ output.rewind
169
+ stripped_output = output.read.lines.map(&:rstrip).join("\n")
170
+ expected_output = <<-EOS
171
+ Please enter a name for your Convox installation |convox|
172
+ Please enter your AWS Region: |us-east-1|
173
+ Admin AWS Credentials
174
+ ============================================
175
+
176
+ Please enter your AWS Access Key ID: Please enter your AWS Secret Access Key: Please enter your EC2 Instance Type: |t3.medium|
177
+ ECR Authentication
178
+ ============================================
179
+
180
+ Please enter your Docker Registry Access Key ID: Please enter your Docker Registry Secret Access Key: Please enter the email address you would like to use for the default admin user |admin@example.com|
181
+
182
+ ============================================
183
+ SUMMARY
184
+ ============================================
185
+
186
+ Convox Stack Name: convox
187
+ AWS Region: us-east-1
188
+ AWS Access Key ID: asdf
189
+ AWS Secret Access Key: xkcd
190
+ EC2 Instance Type: t3.medium
191
+ Docker Registry Access Key ID: sdfg
192
+ Docker Registry Secret Access Key: qwer
193
+ Admin Email: admin@example.com
194
+ Admin Password: 99a6f67de0c7a117
195
+
196
+ We've saved your configuration to: /Users/ndbroadbent/.convox/installer_config
197
+ If anything goes wrong during the installation, you can restart the script to reload the config and continue.
198
+
199
+ Please double check all of these configuration details.
200
+ Would you like to start the Convox installation? (press 'n' to correct any settings)
201
+ EOS
202
+
203
+ # puts stripped_output
204
+ # puts "---------------"
205
+ # puts expected_output
206
+ expect(stripped_output).to eq expected_output.strip
207
+ end
208
+ end
@@ -0,0 +1,87 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "convox_installer"
4
+
5
+ RSpec.describe ConvoxInstaller::Requirements do
6
+ context "with no missing packages" do
7
+ it "should do nothing" do
8
+ req = ConvoxInstaller::Requirements.new
9
+ expect(req).to receive(:find_command).with("convox").and_return(true)
10
+ expect(req).to receive(:find_command).with("aws").and_return(true)
11
+ expect(req).to_not receive(:quit!)
12
+
13
+ expect(req.logger).to_not receive(:error)
14
+
15
+ req.ensure_requirements!
16
+ end
17
+ end
18
+
19
+ context "on Mac" do
20
+ context "with two missing packages" do
21
+ it "should show the correct error message and quit" do
22
+ expect(OS).to receive(:mac?).and_return(true)
23
+
24
+ req = ConvoxInstaller::Requirements.new
25
+ expect(req).to receive(:find_command).with("convox").and_return(false)
26
+ expect(req).to receive(:find_command).with("aws").and_return(false)
27
+ expect(req).to receive(:quit!)
28
+
29
+ expect(req.logger).to receive(:error).with(
30
+ "This script requires the convox and AWS CLI tools."
31
+ )
32
+ expect(req.logger).to receive(:error).with(
33
+ "Please run: brew install convox awscli"
34
+ )
35
+
36
+ req.ensure_requirements!
37
+ end
38
+ end
39
+
40
+ context "with one missing packages" do
41
+ it "should show the correct error message and quit" do
42
+ expect(OS).to receive(:mac?).and_return(true)
43
+
44
+ req = ConvoxInstaller::Requirements.new
45
+ expect(req).to receive(:find_command).with("convox").and_return(false)
46
+ expect(req).to receive(:find_command).with("aws").and_return(true)
47
+ expect(req).to receive(:quit!)
48
+
49
+ expect(req.logger).to receive(:error).with(
50
+ "This script requires the convox and AWS CLI tools."
51
+ )
52
+ expect(req.logger).to receive(:error).with(
53
+ "Please run: brew install convox"
54
+ )
55
+
56
+ req.ensure_requirements!
57
+ end
58
+ end
59
+ end
60
+
61
+ context "on Linux" do
62
+ context "with two missing packages" do
63
+ it "should show the correct error message and quit" do
64
+ expect(OS).to receive(:mac?).and_return(false)
65
+
66
+ req = ConvoxInstaller::Requirements.new
67
+ expect(req).to receive(:find_command).with("convox").and_return(false)
68
+ expect(req).to receive(:find_command).with("aws").and_return(false)
69
+ expect(req).to receive(:quit!)
70
+
71
+ expect(req.logger).to receive(:error).with(
72
+ "This script requires the convox and AWS CLI tools."
73
+ )
74
+ expect(req.logger).to receive(:error).with("Installation Instructions:")
75
+ expect(req.logger).to receive(:error).with(
76
+ "* convox: https://docs.convox.com/introduction/installation"
77
+ )
78
+ expect(req.logger).to receive(:error).with(
79
+ "* aws: https://docs.aws.amazon.com/cli/latest/" \
80
+ "userguide/cli-chap-install.html"
81
+ )
82
+
83
+ req.ensure_requirements!
84
+ end
85
+ end
86
+ end
87
+ end
@@ -0,0 +1,118 @@
1
+ # frozen_string_literal: true
2
+
3
+ # This file was generated by the `rspec --init` command. Conventionally, all
4
+ # specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
5
+ # The generated `.rspec` file contains `--require spec_helper` which will cause
6
+ # this file to always be loaded, without a need to explicitly require it in any
7
+ # files.
8
+ #
9
+ # Given that it is always loaded, you are encouraged to keep this file as
10
+ # light-weight as possible. Requiring heavyweight dependencies from this file
11
+ # will add to the boot time of your test suite on EVERY test run, even for an
12
+ # individual file that may not need all of that loaded. Instead, consider making
13
+ # a separate helper file that requires the additional dependencies and performs
14
+ # the additional setup, and require it from the spec files that actually need
15
+ # it.
16
+ #
17
+ # See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
18
+
19
+ $LOAD_PATH << File.expand_path(__dir__, '../lib')
20
+
21
+ require 'vcr'
22
+ require 'webmock/rspec'
23
+ require 'pry-byebug'
24
+
25
+ VCR.configure do |config|
26
+ config.cassette_library_dir = 'spec/vcr_cassettes'
27
+ config.hook_into :webmock
28
+ config.configure_rspec_metadata!
29
+
30
+ config.debug_logger = File.open(
31
+ File.join(__dir__, '../log/vcr_debug.log'), 'w'
32
+ )
33
+ config.default_cassette_options = { record: :none, erb: true }
34
+ end
35
+
36
+ RSpec.configure do |config|
37
+ # rspec-expectations config goes here. You can use an alternate
38
+ # assertion/expectation library such as wrong or the stdlib/minitest
39
+ # assertions if you prefer.
40
+ config.expect_with :rspec do |expectations|
41
+ # This option will default to `true` in RSpec 4. It makes the `description`
42
+ # and `failure_message` of custom matchers include text for helper methods
43
+ # defined using `chain`, e.g.:
44
+ # be_bigger_than(2).and_smaller_than(4).description
45
+ # # => "be bigger than 2 and smaller than 4"
46
+ # ...rather than:
47
+ # # => "be bigger than 2"
48
+ expectations.include_chain_clauses_in_custom_matcher_descriptions = true
49
+ end
50
+
51
+ # rspec-mocks config goes here. You can use an alternate test double
52
+ # library (such as bogus or mocha) by changing the `mock_with` option here.
53
+ config.mock_with :rspec do |mocks|
54
+ # Prevents you from mocking or stubbing a method that does not exist on
55
+ # a real object. This is generally recommended, and will default to
56
+ # `true` in RSpec 4.
57
+ mocks.verify_partial_doubles = true
58
+ end
59
+
60
+ # This option will default to `:apply_to_host_groups` in RSpec 4 (and will
61
+ # have no way to turn it off -- the option exists only for backwards
62
+ # compatibility in RSpec 3). It causes shared context metadata to be
63
+ # inherited by the metadata hash of host groups and examples, rather than
64
+ # triggering implicit auto-inclusion in groups with matching metadata.
65
+ config.shared_context_metadata_behavior = :apply_to_host_groups
66
+
67
+ # The settings below are suggested to provide a good initial experience
68
+ # with RSpec, but feel free to customize to your heart's content.
69
+ # # This allows you to limit a spec run to individual examples or groups
70
+ # # you care about by tagging them with `:focus` metadata. When nothing
71
+ # # is tagged with `:focus`, all examples get run. RSpec also provides
72
+ # # aliases for `it`, `describe`, and `context` that include `:focus`
73
+ # # metadata: `fit`, `fdescribe` and `fcontext`, respectively.
74
+ # config.filter_run_when_matching :focus
75
+ #
76
+ # # Allows RSpec to persist some state between runs in order to support
77
+ # # the `--only-failures` and `--next-failure` CLI options. We recommend
78
+ # # you configure your source control system to ignore this file.
79
+ # config.example_status_persistence_file_path = "spec/examples.txt"
80
+ #
81
+ # # Limits the available syntax to the non-monkey patched syntax that is
82
+ # # recommended. For more details, see:
83
+ # # - http://rspec.info/blog/2012/06/rspecs-new-expectation-syntax/
84
+ # # - http://www.teaisaweso.me/blog/2013/05/27/rspecs-new-message-expectation-syntax/
85
+ # # - http://rspec.info/blog/2014/05/notable-changes-in-rspec-3/#zero-monkey-patching-mode
86
+ # config.disable_monkey_patching!
87
+ #
88
+ # # This setting enables warnings. It's recommended, but in some cases may
89
+ # # be too noisy due to issues in dependencies.
90
+ # config.warnings = true
91
+ #
92
+ # # Many RSpec users commonly either run the entire suite or an individual
93
+ # # file, and it's useful to allow more verbose output when running an
94
+ # # individual spec file.
95
+ # if config.files_to_run.one?
96
+ # # Use the documentation formatter for detailed output,
97
+ # # unless a formatter has already been configured
98
+ # # (e.g. via a command-line flag).
99
+ # config.default_formatter = "doc"
100
+ # end
101
+ #
102
+ # # Print the 10 slowest examples and example groups at the
103
+ # # end of the spec run, to help surface which specs are running
104
+ # # particularly slow.
105
+ # config.profile_examples = 10
106
+ #
107
+ # # Run specs in random order to surface order dependencies. If you find an
108
+ # # order dependency and want to debug it, you can fix the order by providing
109
+ # # the seed, which is printed after each run.
110
+ # # --seed 1234
111
+ # config.order = :random
112
+ #
113
+ # # Seed global randomization in this process using the `--seed` CLI option.
114
+ # # Setting this allows you to use `--seed` to deterministically reproduce
115
+ # # test failures related to randomization by passing the same `--seed` value
116
+ # # as the one that triggered the failure.
117
+ # Kernel.srand config.seed
118
+ end