knapsack_pro 8.3.3 → 9.0.0

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 (31) hide show
  1. checksums.yaml +4 -4
  2. data/.circleci/config.yml +1 -2
  3. data/.gitignore +0 -1
  4. data/CHANGELOG.md +23 -2
  5. data/README.md +1 -1
  6. data/knapsack_pro.gemspec +1 -1
  7. data/lib/knapsack_pro/client/api/v1/queues.rb +1 -0
  8. data/lib/knapsack_pro/client/connection.rb +97 -52
  9. data/lib/knapsack_pro/config/ci/github_actions.rb +6 -4
  10. data/lib/knapsack_pro/queue_allocator.rb +13 -12
  11. data/lib/knapsack_pro/version.rb +1 -1
  12. data/lib/knapsack_pro.rb +9 -3
  13. data/spec/integration/runners/fallback_spec.rb +4 -4
  14. data/spec/integration/runners/queue/cucumber_runner_fallback_spec.rb +4 -4
  15. data/spec/integration/runners/queue/minitest_runner_fallback_spec.rb +4 -4
  16. data/spec/integration/runners/queue/rspec_runner_fallback_spec.rb +4 -4
  17. data/spec/integration/runners/queue/rspec_runner_spec.rb +20 -20
  18. data/spec/knapsack_pro/client/api/v1/queues_spec.rb +3 -1
  19. data/spec/knapsack_pro/client/connection_spec.rb +19 -15
  20. data/spec/knapsack_pro/config/ci/github_actions_spec.rb +40 -18
  21. data/spec/knapsack_pro/config/env_spec.rb +330 -352
  22. data/spec/knapsack_pro/formatters/time_tracker_spec.rb +448 -0
  23. data/spec/knapsack_pro/pure/queue/rspec_pure_spec.rb +5 -5
  24. data/spec/knapsack_pro/test_case_detectors/rspec_test_example_detector_spec.rb +1 -1
  25. data/spec/knapsack_pro_spec.rb +63 -39
  26. data/spec_time_tracker/spec_helper.rb +29 -0
  27. metadata +6 -9
  28. data/bin/test +0 -15
  29. data/lib/knapsack_pro/logger_wrapper.rb +0 -22
  30. data/spec/knapsack_pro/formatters/time_tracker_specs.rb +0 -545
  31. data/spec/knapsack_pro/logger_wrapper_spec.rb +0 -21
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 7a43269c3d826dc9e9faed08299cffbc2d12afc454de28b58435e2bc05861e55
4
- data.tar.gz: 41c2129c7f580d3637a2cf7a189d4b4cf4e0ce10fa677162fd82640c2bf1b582
3
+ metadata.gz: 3f83ec80d7b3dcbd9415335f5f340e48908fbeaeee13e92203cb78df1232f82e
4
+ data.tar.gz: 19c08fe18b1555fd1a5d218b32d8baf1534e9cc87b63fc9d17d1c7ddb0129f46
5
5
  SHA512:
6
- metadata.gz: e3a172a78479d59fd9a5becff1606df2555e5db961573ab42786ee37942f8a3c56305c996c3c774a5890189ad1ad75be1057066b0043f3260d4ce97668154a84
7
- data.tar.gz: a8176152345555ddcac3024a903cc6749b7d32ea0f432f5b01b8e10813202288f511b5ba06f5a1dd6b20738d4f4a25d9af7f6604d70544c771c2b30f186cc4e0
6
+ metadata.gz: d00064e828c1a90a3f2001cbbbee5086f7ac565b6f6ffe015237b6cab12bbdcc48a6a6199f615aaf1ff73ec4bdf4c666c84df44a8e6bc792e4d33387f4c55d71
7
+ data.tar.gz: b5dd5757440d7e38a54a44c69fe0c650185ade87dc00b00ebf24242fb637e3a062cdb45b7b85e39eae28547cd8513ad888aa8c6488a3734750a44530c64b6596
data/.circleci/config.yml CHANGED
@@ -65,7 +65,6 @@ jobs:
65
65
  - run: bundle update rspec
66
66
  - run: bundle exec rspec --version
67
67
  - run: bundle exec rspec spec
68
- - run: bundle exec ruby spec/knapsack_pro/formatters/time_tracker_specs.rb
69
68
 
70
69
  integration-rspec:
71
70
  parallelism: 1
@@ -292,7 +291,7 @@ jobs:
292
291
  working_directory: ~/rails-app-with-knapsack_pro
293
292
  command: |
294
293
  # split by test examples AND a single CI node ||
295
- export KNAPSACK_PRO_BRANCH="$CIRCLE_BRANCH--$CIRCLE_BUILD_NUM--queue--split--single-node"
294
+ export KNAPSACK_PRO_BRANCH="$CIRCLE_BRANCH--$CIRCLE_BUILD_NUM--queue--split--single-node--$CIRCLE_NODE_INDEX"
296
295
  export KNAPSACK_PRO_FIXED_QUEUE_SPLIT=true
297
296
  export KNAPSACK_PRO_RSPEC_SPLIT_BY_TEST_EXAMPLES=true
298
297
  export KNAPSACK_PRO_CI_NODE_TOTAL=1
data/.gitignore CHANGED
@@ -36,5 +36,4 @@ Gemfile.lock
36
36
  .rvmrc
37
37
 
38
38
  # dynamically generated specs
39
- spec/knapsack_pro/formatters/tmp_time_tracker*_spec.rb
40
39
  spec_integration/
data/CHANGELOG.md CHANGED
@@ -1,10 +1,31 @@
1
1
  # Changelog
2
2
 
3
- ### UNRELEASED (patch)
3
+ ### 9.0.0
4
+
5
+ * __(breaking change)__ Require Ruby >=3.0.0
6
+ * Implement IP rotation for Ruby <3.4 to mitigate connection errors
7
+ * Upon connection failure, log additional diagnostics to gather more context
8
+ * Change log format from `LEVEL -- : [knapsack_pro] ...` to `ERROR -- knapsack_pro: ...`
9
+
10
+ https://github.com/KnapsackPro/knapsack_pro-ruby/pull/313
11
+
12
+ * GitHub Actions: Detect either head branch in Pull Requests or short ref name (vs fully-formed ref) in the other cases
13
+
14
+ https://github.com/KnapsackPro/knapsack_pro-ruby/pull/308
15
+
16
+ https://github.com/KnapsackPro/knapsack_pro-ruby/compare/v8.4.0...v9.0.0
17
+
18
+ ### 8.4.0
19
+
20
+ * Add a batch UUID to the V1 Queue API request payload to improve handling of retried requests
21
+
22
+ https://github.com/KnapsackPro/knapsack_pro-ruby/pull/307
23
+
24
+ https://github.com/KnapsackPro/knapsack_pro-ruby/compare/v8.3.3...v8.4.0
4
25
 
5
26
  ### 8.3.3
6
27
 
7
- * Fix a `Hash#sum` bug in the time tracker for RSpec
28
+ * Replace `Hash#sum` with `Hash#reduce` to fix a rare bug in the RSpec time tracker for a specific project
8
29
 
9
30
  https://github.com/KnapsackPro/knapsack_pro-ruby/pull/305
10
31
 
data/README.md CHANGED
@@ -67,7 +67,7 @@ bundle update knapsack_pro
67
67
  RSpec:
68
68
 
69
69
  ```bash
70
- bin/test
70
+ bundle exec rspec
71
71
  ```
72
72
 
73
73
  Scripted tests can be found in the [Rails App With Knapsack Pro repository](https://github.com/KnapsackPro/rails-app-with-knapsack_pro/blob/master/bin/knapsack_pro_all.rb).
data/knapsack_pro.gemspec CHANGED
@@ -6,7 +6,7 @@ require 'knapsack_pro/version'
6
6
  Gem::Specification.new do |spec|
7
7
  spec.name = 'knapsack_pro'
8
8
  spec.version = KnapsackPro::VERSION
9
- spec.required_ruby_version = '>= 2.7.0'
9
+ spec.required_ruby_version = '>= 3.0.0'
10
10
  spec.authors = ['ArturT']
11
11
  spec.email = ['support@knapsackpro.com']
12
12
  spec.summary = %q{Knapsack Pro splits tests across parallel CI nodes and ensures each parallel job finish work at a similar time.}
@@ -19,6 +19,7 @@ module KnapsackPro
19
19
  :node_index => args.fetch(:node_index),
20
20
  :node_build_id => KnapsackPro::Config::Env.ci_node_build_id,
21
21
  :user_seat => KnapsackPro::Config::Env.masked_user_seat,
22
+ batch_uuid: args.fetch(:batch_uuid)
22
23
  }
23
24
 
24
25
  if request_hash[:can_initialize_queue] && !request_hash[:attempt_connect_to_queue]
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'stringio'
4
+
3
5
  module KnapsackPro
4
6
  module Client
5
7
  class Connection
@@ -10,6 +12,7 @@ module KnapsackPro
10
12
 
11
13
  def initialize(action)
12
14
  @action = action
15
+ @http_debug_output = StringIO.new
13
16
  end
14
17
 
15
18
  def call
@@ -17,7 +20,7 @@ module KnapsackPro
17
20
  end
18
21
 
19
22
  def success?
20
- return false if !response_body
23
+ return false unless response_body
21
24
 
22
25
  status = http_response.code.to_i
23
26
  status >= 200 && status < 500
@@ -29,6 +32,7 @@ module KnapsackPro
29
32
 
30
33
  def api_code
31
34
  return unless response_body
35
+
32
36
  response_body['code']
33
37
  end
34
38
 
@@ -45,20 +49,8 @@ module KnapsackPro
45
49
  KnapsackPro.logger
46
50
  end
47
51
 
48
- def endpoint
49
- KnapsackPro::Config::Env.endpoint
50
- end
51
-
52
- def endpoint_url
53
- endpoint + action.endpoint_path
54
- end
55
-
56
- def request_hash
57
- action.request_hash
58
- end
59
-
60
- def request_body
61
- request_hash.to_json
52
+ def endpoint_uri
53
+ URI.parse(KnapsackPro::Config::Env.endpoint + action.endpoint_path)
62
54
  end
63
55
 
64
56
  def json_headers
@@ -68,19 +60,20 @@ module KnapsackPro
68
60
  'KNAPSACK-PRO-CLIENT-NAME' => client_name,
69
61
  'KNAPSACK-PRO-CLIENT-VERSION' => KnapsackPro::VERSION,
70
62
  'KNAPSACK-PRO-TEST-SUITE-TOKEN' => KnapsackPro::Config::Env.test_suite_token,
71
- 'KNAPSACK-PRO-CI-PROVIDER' => KnapsackPro::Config::Env.ci_provider,
63
+ 'KNAPSACK-PRO-CI-PROVIDER' => KnapsackPro::Config::Env.ci_provider
72
64
  }.compact
73
65
  end
74
66
 
75
67
  def client_name
76
68
  [
77
69
  'knapsack_pro-ruby',
78
- ENV['KNAPSACK_PRO_TEST_RUNNER'],
70
+ ENV['KNAPSACK_PRO_TEST_RUNNER']
79
71
  ].compact.join('/')
80
72
  end
81
73
 
82
74
  def parse_response_body(body)
83
75
  return '' if body == '' || body.nil?
76
+
84
77
  JSON.parse(body)
85
78
  rescue JSON::ParserError
86
79
  nil
@@ -88,11 +81,8 @@ module KnapsackPro
88
81
 
89
82
  def seed
90
83
  return if @response_body.nil? || @response_body == ''
91
- response_body['build_distribution_id']
92
- end
93
84
 
94
- def has_seed?
95
- !seed.nil?
85
+ response_body['build_distribution_id']
96
86
  end
97
87
 
98
88
  def make_request(&block)
@@ -103,9 +93,9 @@ module KnapsackPro
103
93
 
104
94
  request_uuid = http_response.header['X-Request-Id'] || 'N/A'
105
95
 
106
- logger.debug("#{action.http_method.to_s.upcase} #{endpoint_url}")
96
+ logger.debug("#{action.http_method.to_s.upcase} #{endpoint_uri}")
107
97
  logger.debug("API request UUID: #{request_uuid}")
108
- logger.debug("Test suite split seed: #{seed}") if has_seed?
98
+ logger.debug("Test suite split seed: #{seed}") unless seed.nil?
109
99
  logger.debug('API response:')
110
100
  if errors?
111
101
  logger.error(response_body)
@@ -113,39 +103,95 @@ module KnapsackPro
113
103
  logger.debug(response_body)
114
104
  end
115
105
 
116
- if server_error?
117
- raise ServerError.new(response_body)
118
- end
106
+ raise ServerError.new(response_body) if server_error?
119
107
 
120
108
  response_body
121
- rescue ServerError, Errno::ECONNREFUSED, Errno::ECONNRESET, Errno::ETIMEDOUT, Errno::EPIPE, EOFError, SocketError, Net::OpenTimeout, Net::ReadTimeout, OpenSSL::SSL::SSLError => e
122
- logger.warn("#{action.http_method.to_s.upcase} #{endpoint_url}")
123
- logger.warn('Request failed due to:')
124
- logger.warn(e.inspect)
109
+ rescue ServerError, Errno::ECONNREFUSED, Errno::ECONNRESET, Errno::ETIMEDOUT, Errno::EPIPE, EOFError,
110
+ SocketError, Net::OpenTimeout, Net::ReadTimeout, OpenSSL::SSL::SSLError => e
125
111
  retries += 1
112
+ log_diagnostics(e, retries)
113
+ @http.set_debug_output(@http_debug_output) if retries == max_request_retries - 1
126
114
  if retries < max_request_retries
127
- wait = retries * REQUEST_RETRY_TIMEBOX
128
- print_every = 2 # seconds
129
- (wait / print_every).ceil.times do |i|
130
- if i == 0
131
- logger.warn("Wait for #{wait}s before retrying the request to Knapsack Pro API.")
132
- else
133
- logger.warn("#{wait - i * print_every}s left before retry...")
134
- end
135
- Kernel.sleep(print_every)
136
- end
115
+ backoff(retries)
116
+ rotate_ip
137
117
  retry
138
118
  else
139
119
  response_body
140
120
  end
141
121
  end
142
122
 
123
+ def log_diagnostics(error, retries)
124
+ message = [
125
+ action.http_method.to_s.upcase,
126
+ endpoint_uri,
127
+ @http.ipaddr # value from @http.ipaddr= or nil
128
+ ].compact.join(' ')
129
+ logger.warn(message)
130
+ logger.warn('Request failed due to:')
131
+ logger.warn(error.inspect)
132
+ return if retries < max_request_retries
133
+
134
+ error.backtrace.each { |line| logger.warn(line) }
135
+ logger.warn('Net::HTTP debug output:')
136
+ @http_debug_output.string.each_line { |line| logger.warn(line.chomp) }
137
+
138
+ require 'open3'
139
+ [
140
+ "dig #{endpoint_uri.host}",
141
+ "nslookup #{endpoint_uri.host}",
142
+ "curl -v #{endpoint_uri.host}:#{endpoint_uri.port}",
143
+ "nc -vz #{endpoint_uri.host} #{endpoint_uri.port}",
144
+ "openssl s_client -connect #{endpoint_uri.host}:#{endpoint_uri.port} < /dev/null",
145
+ 'env'
146
+ ].each do |cmd|
147
+ logger.warn(cmd)
148
+ logger.warn('=' * cmd.size)
149
+ begin
150
+ outerr, status = Open3.capture2e(cmd)
151
+ logger.warn("Exit status: #{status.exitstatus}")
152
+ outerr.each_line { |line| logger.warn(line.chomp) }
153
+ rescue Errno::ENOENT => e
154
+ logger.warn("Error: #{e}")
155
+ end
156
+ end
157
+ end
158
+
159
+ def backoff(retries)
160
+ wait = retries * REQUEST_RETRY_TIMEBOX
161
+ print_every = 2 # seconds
162
+ (wait / print_every).ceil.times do |i|
163
+ if i.zero?
164
+ logger.warn("Wait for #{wait}s before retrying the request to the Knapsack Pro API.")
165
+ else
166
+ logger.warn("#{wait - i * print_every}s left before retry...")
167
+ end
168
+ Kernel.sleep(print_every)
169
+ end
170
+ end
171
+
143
172
  def build_http(uri)
144
- http = net_http.new(uri.host, uri.port)
145
- http.use_ssl = (uri.scheme == 'https')
146
- http.open_timeout = TIMEOUT
147
- http.read_timeout = TIMEOUT
148
- http
173
+ @http = net_http.new(uri.host, uri.port)
174
+ @http.use_ssl = (uri.scheme == 'https')
175
+ @http.open_timeout = TIMEOUT
176
+ @http.read_timeout = TIMEOUT
177
+ rotate_ip
178
+ end
179
+
180
+ def rotate_ip
181
+ # Ruby v3.4 implements Happy Eyeballs Version 2 (RFC 8305)
182
+ return if Gem::Version.new(RUBY_VERSION) >= Gem::Version.new('3.4')
183
+
184
+ @ipaddrs ||=
185
+ begin
186
+ require 'resolv'
187
+ resolvers = [
188
+ Resolv::Hosts.new,
189
+ Resolv::DNS.new(Resolv::DNS::Config.default_config_hash.merge(use_ipv6: false))
190
+ ]
191
+ Resolv.new(resolvers).getaddresses(endpoint_uri.host).shuffle
192
+ end
193
+
194
+ @http.ipaddr = @ipaddrs.rotate!.first
149
195
  end
150
196
 
151
197
  def net_http
@@ -157,19 +203,18 @@ module KnapsackPro
157
203
  end
158
204
 
159
205
  def post
160
- uri = URI.parse(endpoint_url)
161
- http = build_http(uri)
206
+ build_http(endpoint_uri)
162
207
  make_request do
163
- http.post(uri.path, request_body, json_headers)
208
+ @http.post(endpoint_uri.path, action.request_hash.to_json, json_headers)
164
209
  end
165
210
  end
166
211
 
167
212
  def get
168
- uri = URI.parse(endpoint_url)
169
- uri.query = URI.encode_www_form(request_hash)
170
- http = build_http(uri)
213
+ uri = endpoint_uri
214
+ uri.query = URI.encode_www_form(action.request_hash)
215
+ build_http(uri)
171
216
  make_request do
172
- http.get(uri, json_headers)
217
+ @http.get(uri, json_headers)
173
218
  end
174
219
  end
175
220
 
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # https://help.github.com/en/actions/configuring-and-managing-workflows/using-environment-variables#default-environment-variables
3
+ # https://docs.github.com/en/actions/reference/workflows-and-actions/variables
4
4
  module KnapsackPro
5
5
  module Config
6
6
  module CI
@@ -31,9 +31,11 @@ module KnapsackPro
31
31
  end
32
32
 
33
33
  def branch
34
- # GITHUB_REF - The branch or tag ref that triggered the workflow. For example, refs/heads/feature-branch-1.
35
- # If neither a branch or tag is available for the event type, the variable will not exist.
36
- ENV['GITHUB_REF'] || ENV['GITHUB_SHA']
34
+ # `on: push` has `GITHUB_HEAD_REF=`
35
+ head_ref = ENV.fetch('GITHUB_HEAD_REF', '')
36
+ return head_ref unless head_ref == ''
37
+
38
+ ENV['GITHUB_REF_NAME'] || ENV['GITHUB_SHA']
37
39
  end
38
40
 
39
41
  def project_dir
@@ -41,26 +41,26 @@ module KnapsackPro
41
41
  @fallback_mode = false
42
42
  end
43
43
 
44
- def test_file_paths(can_initialize_queue, executed_test_files)
44
+ def test_file_paths(can_initialize_queue, executed_test_files, batch_uuid: SecureRandom.uuid)
45
45
  return [] if @fallback_mode
46
46
 
47
- batch = pull_tests_from_queue(can_initialize_queue)
47
+ batch = pull_tests_from_queue(can_initialize_queue, batch_uuid)
48
48
 
49
49
  return switch_to_fallback_mode(executed_test_files: executed_test_files) if batch.connection_failed?
50
50
  return normalize_test_files(batch.test_files) if batch.queue_exists?
51
51
 
52
52
  test_files_result = test_suite.calculate_test_files
53
53
 
54
- return try_initializing_queue(test_files_result.test_files) if test_files_result.quick?
54
+ return try_initializing_queue(test_files_result.test_files, batch_uuid) if test_files_result.quick?
55
55
 
56
56
  # The tests to run were found slowly. By that time, the queue could have already been initialized by another CI node.
57
57
  # Attempt to pull tests from the queue to avoid the attempt to initialize the queue unnecessarily (queue initialization is an expensive request with a big test files payload).
58
- batch = pull_tests_from_queue(can_initialize_queue)
58
+ batch = pull_tests_from_queue(can_initialize_queue, batch_uuid)
59
59
 
60
60
  return switch_to_fallback_mode(executed_test_files: executed_test_files) if batch.connection_failed?
61
61
  return normalize_test_files(batch.test_files) if batch.queue_exists?
62
62
 
63
- try_initializing_queue(test_files_result.test_files)
63
+ try_initializing_queue(test_files_result.test_files, batch_uuid)
64
64
  end
65
65
 
66
66
  private
@@ -80,7 +80,7 @@ module KnapsackPro
80
80
  KnapsackPro::TestFilePresenter.paths(decrypted_test_files)
81
81
  end
82
82
 
83
- def build_action(can_initialize_queue:, attempt_connect_to_queue:, test_files: nil)
83
+ def build_action(can_initialize_queue:, attempt_connect_to_queue:, batch_uuid:, test_files: nil)
84
84
  if can_initialize_queue && !attempt_connect_to_queue
85
85
  raise 'Test files are required when initializing a new queue.' if test_files.nil?
86
86
  test_files = KnapsackPro::Crypto::Encryptor.call(test_files)
@@ -95,25 +95,26 @@ module KnapsackPro
95
95
  node_index: ci_node_index,
96
96
  node_build_id: ci_node_build_id,
97
97
  test_files: test_files,
98
+ batch_uuid: batch_uuid
98
99
  )
99
100
  end
100
101
 
101
- def pull_tests_from_queue(can_initialize_queue)
102
- action = build_action(can_initialize_queue: can_initialize_queue, attempt_connect_to_queue: can_initialize_queue)
102
+ def pull_tests_from_queue(can_initialize_queue, batch_uuid)
103
+ action = build_action(can_initialize_queue: can_initialize_queue, attempt_connect_to_queue: can_initialize_queue, batch_uuid: batch_uuid)
103
104
  connection = KnapsackPro::Client::Connection.new(action)
104
105
  response = connection.call
105
106
  Batch.new(connection, response)
106
107
  end
107
108
 
108
- def initialize_queue(tests_to_run)
109
- action = build_action(can_initialize_queue: true, attempt_connect_to_queue: false, test_files: tests_to_run)
109
+ def initialize_queue(tests_to_run, batch_uuid)
110
+ action = build_action(can_initialize_queue: true, attempt_connect_to_queue: false, batch_uuid: batch_uuid, test_files: tests_to_run)
110
111
  connection = KnapsackPro::Client::Connection.new(action)
111
112
  response = connection.call
112
113
  Batch.new(connection, response)
113
114
  end
114
115
 
115
- def try_initializing_queue(tests)
116
- result = initialize_queue(tests)
116
+ def try_initializing_queue(tests, batch_uuid)
117
+ result = initialize_queue(tests, batch_uuid)
117
118
 
118
119
  return switch_to_fallback_mode(executed_test_files: []) if result.connection_failed?
119
120
 
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module KnapsackPro
4
- VERSION = '8.3.3'
4
+ VERSION = '9.0.0'
5
5
  end
data/lib/knapsack_pro.rb CHANGED
@@ -29,7 +29,6 @@ require_relative 'knapsack_pro/config/ci/heroku'
29
29
  require_relative 'knapsack_pro/config/env'
30
30
  require_relative 'knapsack_pro/config/env_generator'
31
31
  require_relative 'knapsack_pro/config/temp_files'
32
- require_relative 'knapsack_pro/logger_wrapper'
33
32
  require_relative 'knapsack_pro/client/api/action'
34
33
  require_relative 'knapsack_pro/client/api/v1/base'
35
34
  require_relative 'knapsack_pro/client/api/v1/build_distributions'
@@ -91,6 +90,11 @@ require 'knapsack_pro/railtie' if defined?(Rails::Railtie)
91
90
 
92
91
  module KnapsackPro
93
92
  class << self
93
+ attr_writer :stdout
94
+ def stdout
95
+ @stdout ||= STDOUT
96
+ end
97
+
94
98
  def root
95
99
  File.expand_path('../..', __FILE__)
96
100
  end
@@ -103,15 +107,17 @@ module KnapsackPro
103
107
  end
104
108
 
105
109
  unless @logger
106
- default_logger = ::Logger.new(STDOUT)
110
+ default_logger = ::Logger.new(stdout)
107
111
  default_logger.level = KnapsackPro::Config::Env.log_level
108
112
  self.logger = default_logger
109
113
  end
114
+
110
115
  @logger
111
116
  end
112
117
 
113
118
  def logger=(logger)
114
- @logger = KnapsackPro::LoggerWrapper.new(logger)
119
+ @logger = logger
120
+ @logger.progname = 'knapsack_pro'
115
121
  end
116
122
 
117
123
  def reset_logger!
@@ -68,7 +68,7 @@ require 'tempfile'
68
68
 
69
69
  expect(actual.exit_code).to eq 1
70
70
 
71
- expect(actual.stdout).to include('ERROR -- : [knapsack_pro] Fallback Mode was disabled with KNAPSACK_PRO_FALLBACK_MODE_ENABLED=false. Please restart this CI node to retry tests. Most likely Fallback Mode was disabled due to https://knapsackpro.com/perma/ruby/regular-mode-connection-error-with-fallback-enabled-false')
71
+ expect(actual.stdout).to include('ERROR -- knapsack_pro: Fallback Mode was disabled with KNAPSACK_PRO_FALLBACK_MODE_ENABLED=false. Please restart this CI node to retry tests. Most likely Fallback Mode was disabled due to https://knapsackpro.com/perma/ruby/regular-mode-connection-error-with-fallback-enabled-false')
72
72
  end
73
73
 
74
74
  context 'with a user defined exit code' do
@@ -85,7 +85,7 @@ require 'tempfile'
85
85
 
86
86
  expect(actual.exit_code).to eq 123
87
87
 
88
- expect(actual.stdout).to include('ERROR -- : [knapsack_pro] Fallback Mode was disabled with KNAPSACK_PRO_FALLBACK_MODE_ENABLED=false. Please restart this CI node to retry tests. Most likely Fallback Mode was disabled due to https://knapsackpro.com/perma/ruby/regular-mode-connection-error-with-fallback-enabled-false')
88
+ expect(actual.stdout).to include('ERROR -- knapsack_pro: Fallback Mode was disabled with KNAPSACK_PRO_FALLBACK_MODE_ENABLED=false. Please restart this CI node to retry tests. Most likely Fallback Mode was disabled due to https://knapsackpro.com/perma/ruby/regular-mode-connection-error-with-fallback-enabled-false')
89
89
  end
90
90
  end
91
91
  end
@@ -106,7 +106,7 @@ require 'tempfile'
106
106
 
107
107
  expect(actual.exit_code).to eq 1
108
108
 
109
- expect(actual.stdout).to include('ERROR -- : [knapsack_pro] knapsack_pro gem could not connect to Knapsack Pro API and the Fallback Mode cannot be used this time. Running tests in Fallback Mode are not allowed for retried parallel CI node to avoid running the wrong set of tests. Please manually retry this parallel job on your CI server then knapsack_pro gem will try to connect to Knapsack Pro API again and will run a correct set of tests for this CI node. Learn more https://knapsackpro.com/perma/ruby/regular-mode-connection-error-with-fallback-enabled-true-and-positive-retry-count')
109
+ expect(actual.stdout).to include('ERROR -- knapsack_pro: knapsack_pro gem could not connect to Knapsack Pro API and the Fallback Mode cannot be used this time. Running tests in Fallback Mode are not allowed for retried parallel CI node to avoid running the wrong set of tests. Please manually retry this parallel job on your CI server then knapsack_pro gem will try to connect to Knapsack Pro API again and will run a correct set of tests for this CI node. Learn more https://knapsackpro.com/perma/ruby/regular-mode-connection-error-with-fallback-enabled-true-and-positive-retry-count')
110
110
  end
111
111
 
112
112
  context 'with a user defined exit code' do
@@ -123,7 +123,7 @@ require 'tempfile'
123
123
 
124
124
  expect(actual.exit_code).to eq 123
125
125
 
126
- expect(actual.stdout).to include('ERROR -- : [knapsack_pro] knapsack_pro gem could not connect to Knapsack Pro API and the Fallback Mode cannot be used this time. Running tests in Fallback Mode are not allowed for retried parallel CI node to avoid running the wrong set of tests. Please manually retry this parallel job on your CI server then knapsack_pro gem will try to connect to Knapsack Pro API again and will run a correct set of tests for this CI node. Learn more https://knapsackpro.com/perma/ruby/regular-mode-connection-error-with-fallback-enabled-true-and-positive-retry-count')
126
+ expect(actual.stdout).to include('ERROR -- knapsack_pro: knapsack_pro gem could not connect to Knapsack Pro API and the Fallback Mode cannot be used this time. Running tests in Fallback Mode are not allowed for retried parallel CI node to avoid running the wrong set of tests. Please manually retry this parallel job on your CI server then knapsack_pro gem will try to connect to Knapsack Pro API again and will run a correct set of tests for this CI node. Learn more https://knapsackpro.com/perma/ruby/regular-mode-connection-error-with-fallback-enabled-true-and-positive-retry-count')
127
127
  end
128
128
  end
129
129
  end
@@ -67,7 +67,7 @@ describe "#{KnapsackPro::Runners::Queue::CucumberRunner} Fallback - Integration
67
67
 
68
68
  expect(actual.exit_code).to eq 1
69
69
 
70
- expect(actual.stdout).to include('ERROR -- : [knapsack_pro] Fallback Mode was disabled with KNAPSACK_PRO_FALLBACK_MODE_ENABLED=false. Please restart this CI node to retry tests. Most likely Fallback Mode was disabled due to https://knapsackpro.com/perma/ruby/queue-mode-connection-error-with-fallback-enabled-false')
70
+ expect(actual.stdout).to include('ERROR -- knapsack_pro: Fallback Mode was disabled with KNAPSACK_PRO_FALLBACK_MODE_ENABLED=false. Please restart this CI node to retry tests. Most likely Fallback Mode was disabled due to https://knapsackpro.com/perma/ruby/queue-mode-connection-error-with-fallback-enabled-false')
71
71
  end
72
72
 
73
73
  context 'with a user defined exit code' do
@@ -84,7 +84,7 @@ describe "#{KnapsackPro::Runners::Queue::CucumberRunner} Fallback - Integration
84
84
 
85
85
  expect(actual.exit_code).to eq 123
86
86
 
87
- expect(actual.stdout).to include('ERROR -- : [knapsack_pro] Fallback Mode was disabled with KNAPSACK_PRO_FALLBACK_MODE_ENABLED=false. Please restart this CI node to retry tests. Most likely Fallback Mode was disabled due to https://knapsackpro.com/perma/ruby/queue-mode-connection-error-with-fallback-enabled-false')
87
+ expect(actual.stdout).to include('ERROR -- knapsack_pro: Fallback Mode was disabled with KNAPSACK_PRO_FALLBACK_MODE_ENABLED=false. Please restart this CI node to retry tests. Most likely Fallback Mode was disabled due to https://knapsackpro.com/perma/ruby/queue-mode-connection-error-with-fallback-enabled-false')
88
88
  end
89
89
  end
90
90
  end
@@ -105,7 +105,7 @@ describe "#{KnapsackPro::Runners::Queue::CucumberRunner} Fallback - Integration
105
105
 
106
106
  expect(actual.exit_code).to eq 1
107
107
 
108
- expect(actual.stdout).to include('ERROR -- : [knapsack_pro] knapsack_pro gem could not connect to Knapsack Pro API and the Fallback Mode cannot be used this time. Running tests in Fallback Mode are not allowed for retried parallel CI node to avoid running the wrong set of tests. Please manually retry this parallel job on your CI server then knapsack_pro gem will try to connect to Knapsack Pro API again and will run a correct set of tests for this CI node. Learn more https://knapsackpro.com/perma/ruby/queue-mode-connection-error-with-fallback-enabled-true-and-positive-retry-count')
108
+ expect(actual.stdout).to include('ERROR -- knapsack_pro: knapsack_pro gem could not connect to Knapsack Pro API and the Fallback Mode cannot be used this time. Running tests in Fallback Mode are not allowed for retried parallel CI node to avoid running the wrong set of tests. Please manually retry this parallel job on your CI server then knapsack_pro gem will try to connect to Knapsack Pro API again and will run a correct set of tests for this CI node. Learn more https://knapsackpro.com/perma/ruby/queue-mode-connection-error-with-fallback-enabled-true-and-positive-retry-count')
109
109
  end
110
110
 
111
111
  context 'with a user defined exit code' do
@@ -122,7 +122,7 @@ describe "#{KnapsackPro::Runners::Queue::CucumberRunner} Fallback - Integration
122
122
 
123
123
  expect(actual.exit_code).to eq 123
124
124
 
125
- expect(actual.stdout).to include('ERROR -- : [knapsack_pro] knapsack_pro gem could not connect to Knapsack Pro API and the Fallback Mode cannot be used this time. Running tests in Fallback Mode are not allowed for retried parallel CI node to avoid running the wrong set of tests. Please manually retry this parallel job on your CI server then knapsack_pro gem will try to connect to Knapsack Pro API again and will run a correct set of tests for this CI node. Learn more https://knapsackpro.com/perma/ruby/queue-mode-connection-error-with-fallback-enabled-true-and-positive-retry-count')
125
+ expect(actual.stdout).to include('ERROR -- knapsack_pro: knapsack_pro gem could not connect to Knapsack Pro API and the Fallback Mode cannot be used this time. Running tests in Fallback Mode are not allowed for retried parallel CI node to avoid running the wrong set of tests. Please manually retry this parallel job on your CI server then knapsack_pro gem will try to connect to Knapsack Pro API again and will run a correct set of tests for this CI node. Learn more https://knapsackpro.com/perma/ruby/queue-mode-connection-error-with-fallback-enabled-true-and-positive-retry-count')
126
126
  end
127
127
  end
128
128
  end
@@ -67,7 +67,7 @@ describe "#{KnapsackPro::Runners::Queue::MinitestRunner} Fallback - Integration
67
67
 
68
68
  expect(actual.exit_code).to eq 1
69
69
 
70
- expect(actual.stdout).to include('ERROR -- : [knapsack_pro] Fallback Mode was disabled with KNAPSACK_PRO_FALLBACK_MODE_ENABLED=false. Please restart this CI node to retry tests. Most likely Fallback Mode was disabled due to https://knapsackpro.com/perma/ruby/queue-mode-connection-error-with-fallback-enabled-false')
70
+ expect(actual.stdout).to include('ERROR -- knapsack_pro: Fallback Mode was disabled with KNAPSACK_PRO_FALLBACK_MODE_ENABLED=false. Please restart this CI node to retry tests. Most likely Fallback Mode was disabled due to https://knapsackpro.com/perma/ruby/queue-mode-connection-error-with-fallback-enabled-false')
71
71
  end
72
72
 
73
73
  context 'with a user defined exit code' do
@@ -84,7 +84,7 @@ describe "#{KnapsackPro::Runners::Queue::MinitestRunner} Fallback - Integration
84
84
 
85
85
  expect(actual.exit_code).to eq 123
86
86
 
87
- expect(actual.stdout).to include('ERROR -- : [knapsack_pro] Fallback Mode was disabled with KNAPSACK_PRO_FALLBACK_MODE_ENABLED=false. Please restart this CI node to retry tests. Most likely Fallback Mode was disabled due to https://knapsackpro.com/perma/ruby/queue-mode-connection-error-with-fallback-enabled-false')
87
+ expect(actual.stdout).to include('ERROR -- knapsack_pro: Fallback Mode was disabled with KNAPSACK_PRO_FALLBACK_MODE_ENABLED=false. Please restart this CI node to retry tests. Most likely Fallback Mode was disabled due to https://knapsackpro.com/perma/ruby/queue-mode-connection-error-with-fallback-enabled-false')
88
88
  end
89
89
  end
90
90
  end
@@ -105,7 +105,7 @@ describe "#{KnapsackPro::Runners::Queue::MinitestRunner} Fallback - Integration
105
105
 
106
106
  expect(actual.exit_code).to eq 1
107
107
 
108
- expect(actual.stdout).to include('ERROR -- : [knapsack_pro] knapsack_pro gem could not connect to Knapsack Pro API and the Fallback Mode cannot be used this time. Running tests in Fallback Mode are not allowed for retried parallel CI node to avoid running the wrong set of tests. Please manually retry this parallel job on your CI server then knapsack_pro gem will try to connect to Knapsack Pro API again and will run a correct set of tests for this CI node. Learn more https://knapsackpro.com/perma/ruby/queue-mode-connection-error-with-fallback-enabled-true-and-positive-retry-count')
108
+ expect(actual.stdout).to include('ERROR -- knapsack_pro: knapsack_pro gem could not connect to Knapsack Pro API and the Fallback Mode cannot be used this time. Running tests in Fallback Mode are not allowed for retried parallel CI node to avoid running the wrong set of tests. Please manually retry this parallel job on your CI server then knapsack_pro gem will try to connect to Knapsack Pro API again and will run a correct set of tests for this CI node. Learn more https://knapsackpro.com/perma/ruby/queue-mode-connection-error-with-fallback-enabled-true-and-positive-retry-count')
109
109
  end
110
110
 
111
111
  context 'with a user defined exit code' do
@@ -122,7 +122,7 @@ describe "#{KnapsackPro::Runners::Queue::MinitestRunner} Fallback - Integration
122
122
 
123
123
  expect(actual.exit_code).to eq 123
124
124
 
125
- expect(actual.stdout).to include('ERROR -- : [knapsack_pro] knapsack_pro gem could not connect to Knapsack Pro API and the Fallback Mode cannot be used this time. Running tests in Fallback Mode are not allowed for retried parallel CI node to avoid running the wrong set of tests. Please manually retry this parallel job on your CI server then knapsack_pro gem will try to connect to Knapsack Pro API again and will run a correct set of tests for this CI node. Learn more https://knapsackpro.com/perma/ruby/queue-mode-connection-error-with-fallback-enabled-true-and-positive-retry-count')
125
+ expect(actual.stdout).to include('ERROR -- knapsack_pro: knapsack_pro gem could not connect to Knapsack Pro API and the Fallback Mode cannot be used this time. Running tests in Fallback Mode are not allowed for retried parallel CI node to avoid running the wrong set of tests. Please manually retry this parallel job on your CI server then knapsack_pro gem will try to connect to Knapsack Pro API again and will run a correct set of tests for this CI node. Learn more https://knapsackpro.com/perma/ruby/queue-mode-connection-error-with-fallback-enabled-true-and-positive-retry-count')
126
126
  end
127
127
  end
128
128
  end
@@ -67,7 +67,7 @@ describe "#{KnapsackPro::Runners::Queue::RSpecRunner} Fallback - Integration tes
67
67
 
68
68
  expect(actual.exit_code).to eq 1
69
69
 
70
- expect(actual.stdout).to include('ERROR -- : [knapsack_pro] Fallback Mode was disabled with KNAPSACK_PRO_FALLBACK_MODE_ENABLED=false. Please restart this CI node to retry tests. Most likely Fallback Mode was disabled due to https://knapsackpro.com/perma/ruby/queue-mode-connection-error-with-fallback-enabled-false')
70
+ expect(actual.stdout).to include('ERROR -- knapsack_pro: Fallback Mode was disabled with KNAPSACK_PRO_FALLBACK_MODE_ENABLED=false. Please restart this CI node to retry tests. Most likely Fallback Mode was disabled due to https://knapsackpro.com/perma/ruby/queue-mode-connection-error-with-fallback-enabled-false')
71
71
  expect(actual.stdout).to include(/Finished in .* seconds \(files took .* seconds to load\)/)
72
72
  expect(actual.stdout).to include('0 examples, 0 failures')
73
73
  end
@@ -86,7 +86,7 @@ describe "#{KnapsackPro::Runners::Queue::RSpecRunner} Fallback - Integration tes
86
86
 
87
87
  expect(actual.exit_code).to eq 123
88
88
 
89
- expect(actual.stdout).to include('ERROR -- : [knapsack_pro] Fallback Mode was disabled with KNAPSACK_PRO_FALLBACK_MODE_ENABLED=false. Please restart this CI node to retry tests. Most likely Fallback Mode was disabled due to https://knapsackpro.com/perma/ruby/queue-mode-connection-error-with-fallback-enabled-false')
89
+ expect(actual.stdout).to include('ERROR -- knapsack_pro: Fallback Mode was disabled with KNAPSACK_PRO_FALLBACK_MODE_ENABLED=false. Please restart this CI node to retry tests. Most likely Fallback Mode was disabled due to https://knapsackpro.com/perma/ruby/queue-mode-connection-error-with-fallback-enabled-false')
90
90
  expect(actual.stdout).to include(/Finished in .* seconds \(files took .* seconds to load\)/)
91
91
  expect(actual.stdout).to include('0 examples, 0 failures')
92
92
  end
@@ -109,7 +109,7 @@ describe "#{KnapsackPro::Runners::Queue::RSpecRunner} Fallback - Integration tes
109
109
 
110
110
  expect(actual.exit_code).to eq 1
111
111
 
112
- expect(actual.stdout).to include('ERROR -- : [knapsack_pro] knapsack_pro gem could not connect to Knapsack Pro API and the Fallback Mode cannot be used this time. Running tests in Fallback Mode are not allowed for retried parallel CI node to avoid running the wrong set of tests. Please manually retry this parallel job on your CI server then knapsack_pro gem will try to connect to Knapsack Pro API again and will run a correct set of tests for this CI node. Learn more https://knapsackpro.com/perma/ruby/queue-mode-connection-error-with-fallback-enabled-true-and-positive-retry-count')
112
+ expect(actual.stdout).to include('ERROR -- knapsack_pro: knapsack_pro gem could not connect to Knapsack Pro API and the Fallback Mode cannot be used this time. Running tests in Fallback Mode are not allowed for retried parallel CI node to avoid running the wrong set of tests. Please manually retry this parallel job on your CI server then knapsack_pro gem will try to connect to Knapsack Pro API again and will run a correct set of tests for this CI node. Learn more https://knapsackpro.com/perma/ruby/queue-mode-connection-error-with-fallback-enabled-true-and-positive-retry-count')
113
113
  expect(actual.stdout).to include(/Finished in .* seconds \(files took .* seconds to load\)/)
114
114
  expect(actual.stdout).to include('0 examples, 0 failures')
115
115
  end
@@ -128,7 +128,7 @@ describe "#{KnapsackPro::Runners::Queue::RSpecRunner} Fallback - Integration tes
128
128
 
129
129
  expect(actual.exit_code).to eq 123
130
130
 
131
- expect(actual.stdout).to include('ERROR -- : [knapsack_pro] knapsack_pro gem could not connect to Knapsack Pro API and the Fallback Mode cannot be used this time. Running tests in Fallback Mode are not allowed for retried parallel CI node to avoid running the wrong set of tests. Please manually retry this parallel job on your CI server then knapsack_pro gem will try to connect to Knapsack Pro API again and will run a correct set of tests for this CI node. Learn more https://knapsackpro.com/perma/ruby/queue-mode-connection-error-with-fallback-enabled-true-and-positive-retry-count')
131
+ expect(actual.stdout).to include('ERROR -- knapsack_pro: knapsack_pro gem could not connect to Knapsack Pro API and the Fallback Mode cannot be used this time. Running tests in Fallback Mode are not allowed for retried parallel CI node to avoid running the wrong set of tests. Please manually retry this parallel job on your CI server then knapsack_pro gem will try to connect to Knapsack Pro API again and will run a correct set of tests for this CI node. Learn more https://knapsackpro.com/perma/ruby/queue-mode-connection-error-with-fallback-enabled-true-and-positive-retry-count')
132
132
  expect(actual.stdout).to include(/Finished in .* seconds \(files took .* seconds to load\)/)
133
133
  expect(actual.stdout).to include('0 examples, 0 failures')
134
134
  end