knapsack_pro 3.8.0 → 7.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 (147) hide show
  1. checksums.yaml +4 -4
  2. data/.circleci/config.yml +377 -23
  3. data/.github/dependabot.yml +11 -0
  4. data/.github/pull_request_template.md +22 -0
  5. data/.gitignore +4 -0
  6. data/CHANGELOG.md +325 -1
  7. data/Gemfile +9 -0
  8. data/README.md +3 -10
  9. data/bin/test +15 -0
  10. data/knapsack_pro.gemspec +7 -6
  11. data/lib/knapsack_pro/adapters/base_adapter.rb +17 -2
  12. data/lib/knapsack_pro/adapters/cucumber_adapter.rb +3 -3
  13. data/lib/knapsack_pro/adapters/minitest_adapter.rb +2 -0
  14. data/lib/knapsack_pro/adapters/rspec_adapter.rb +88 -49
  15. data/lib/knapsack_pro/adapters/spinach_adapter.rb +2 -0
  16. data/lib/knapsack_pro/adapters/test_unit_adapter.rb +2 -0
  17. data/lib/knapsack_pro/allocator.rb +2 -0
  18. data/lib/knapsack_pro/allocator_builder.rb +2 -0
  19. data/lib/knapsack_pro/base_allocator_builder.rb +8 -25
  20. data/lib/knapsack_pro/build_distribution_fetcher.rb +2 -0
  21. data/lib/knapsack_pro/client/api/action.rb +2 -0
  22. data/lib/knapsack_pro/client/api/v1/base.rb +2 -0
  23. data/lib/knapsack_pro/client/api/v1/build_distributions.rb +5 -0
  24. data/lib/knapsack_pro/client/api/v1/build_subsets.rb +2 -0
  25. data/lib/knapsack_pro/client/api/v1/queues.rb +6 -1
  26. data/lib/knapsack_pro/client/connection.rb +5 -6
  27. data/lib/knapsack_pro/config/ci/app_veyor.rb +18 -0
  28. data/lib/knapsack_pro/config/ci/base.rb +27 -0
  29. data/lib/knapsack_pro/config/ci/buildkite.rb +18 -0
  30. data/lib/knapsack_pro/config/ci/circle.rb +18 -0
  31. data/lib/knapsack_pro/config/ci/cirrus_ci.rb +18 -0
  32. data/lib/knapsack_pro/config/ci/codefresh.rb +18 -0
  33. data/lib/knapsack_pro/config/ci/codeship.rb +18 -0
  34. data/lib/knapsack_pro/config/ci/github_actions.rb +26 -0
  35. data/lib/knapsack_pro/config/ci/gitlab_ci.rb +20 -1
  36. data/lib/knapsack_pro/config/ci/heroku.rb +18 -0
  37. data/lib/knapsack_pro/config/ci/semaphore.rb +16 -0
  38. data/lib/knapsack_pro/config/ci/semaphore2.rb +19 -0
  39. data/lib/knapsack_pro/config/ci/travis.rb +18 -0
  40. data/lib/knapsack_pro/config/env.rb +46 -22
  41. data/lib/knapsack_pro/config/env_generator.rb +2 -0
  42. data/lib/knapsack_pro/config/temp_files.rb +8 -4
  43. data/lib/knapsack_pro/crypto/branch_encryptor.rb +2 -0
  44. data/lib/knapsack_pro/crypto/decryptor.rb +2 -0
  45. data/lib/knapsack_pro/crypto/digestor.rb +2 -0
  46. data/lib/knapsack_pro/crypto/encryptor.rb +2 -0
  47. data/lib/knapsack_pro/extensions/rspec_extension.rb +137 -0
  48. data/lib/knapsack_pro/formatters/rspec_json_formatter.rb +2 -0
  49. data/lib/knapsack_pro/formatters/time_tracker.rb +152 -0
  50. data/lib/knapsack_pro/formatters/time_tracker_fetcher.rb +20 -0
  51. data/lib/knapsack_pro/hooks/queue.rb +2 -0
  52. data/lib/knapsack_pro/logger_wrapper.rb +2 -0
  53. data/lib/knapsack_pro/mask_string.rb +9 -0
  54. data/lib/knapsack_pro/presenter.rb +6 -3
  55. data/lib/knapsack_pro/pure/queue/rspec_pure.rb +92 -0
  56. data/lib/knapsack_pro/queue_allocator.rb +2 -0
  57. data/lib/knapsack_pro/queue_allocator_builder.rb +2 -0
  58. data/lib/knapsack_pro/railtie.rb +2 -0
  59. data/lib/knapsack_pro/report.rb +15 -9
  60. data/lib/knapsack_pro/repository_adapter_initiator.rb +2 -0
  61. data/lib/knapsack_pro/repository_adapters/base_adapter.rb +2 -0
  62. data/lib/knapsack_pro/repository_adapters/env_adapter.rb +2 -0
  63. data/lib/knapsack_pro/repository_adapters/git_adapter.rb +50 -0
  64. data/lib/knapsack_pro/runners/base_runner.rb +2 -0
  65. data/lib/knapsack_pro/runners/cucumber_runner.rb +2 -0
  66. data/lib/knapsack_pro/runners/minitest_runner.rb +2 -0
  67. data/lib/knapsack_pro/runners/queue/base_runner.rb +29 -0
  68. data/lib/knapsack_pro/runners/queue/cucumber_runner.rb +9 -6
  69. data/lib/knapsack_pro/runners/queue/minitest_runner.rb +13 -6
  70. data/lib/knapsack_pro/runners/queue/rspec_runner.rb +128 -135
  71. data/lib/knapsack_pro/runners/rspec_runner.rb +22 -3
  72. data/lib/knapsack_pro/runners/spinach_runner.rb +2 -0
  73. data/lib/knapsack_pro/runners/test_unit_runner.rb +2 -0
  74. data/lib/knapsack_pro/slow_test_file_determiner.rb +2 -0
  75. data/lib/knapsack_pro/slow_test_file_finder.rb +2 -0
  76. data/lib/knapsack_pro/task_loader.rb +2 -0
  77. data/lib/knapsack_pro/test_case_detectors/rspec_test_example_detector.rb +2 -0
  78. data/lib/knapsack_pro/test_case_mergers/base_merger.rb +2 -0
  79. data/lib/knapsack_pro/test_case_mergers/rspec_merger.rb +2 -0
  80. data/lib/knapsack_pro/test_file_cleaner.rb +2 -0
  81. data/lib/knapsack_pro/test_file_finder.rb +2 -0
  82. data/lib/knapsack_pro/test_file_pattern.rb +2 -0
  83. data/lib/knapsack_pro/test_file_presenter.rb +2 -0
  84. data/lib/knapsack_pro/test_files_with_test_cases_composer.rb +2 -0
  85. data/lib/knapsack_pro/test_flat_distributor.rb +2 -0
  86. data/lib/knapsack_pro/tracker.rb +3 -3
  87. data/lib/knapsack_pro/urls.rb +4 -0
  88. data/lib/knapsack_pro/utils.rb +2 -0
  89. data/lib/knapsack_pro/version.rb +3 -1
  90. data/lib/knapsack_pro.rb +5 -3
  91. data/lib/tasks/cucumber.rake +2 -0
  92. data/lib/tasks/encrypted_branch_names.rake +2 -0
  93. data/lib/tasks/encrypted_test_file_names.rake +2 -0
  94. data/lib/tasks/minitest.rake +2 -0
  95. data/lib/tasks/queue/cucumber.rake +13 -0
  96. data/lib/tasks/queue/minitest.rake +13 -0
  97. data/lib/tasks/queue/rspec.rake +13 -0
  98. data/lib/tasks/rspec.rake +5 -0
  99. data/lib/tasks/salt.rake +2 -0
  100. data/lib/tasks/spinach.rake +2 -0
  101. data/lib/tasks/test_unit.rake +2 -0
  102. data/spec/integration/api/build_distributions_subset_spec.rb +1 -0
  103. data/spec/integration/runners/queue/rspec_runner.rb +80 -0
  104. data/spec/integration/runners/queue/rspec_runner_spec.rb +2232 -0
  105. data/spec/knapsack_pro/adapters/base_adapter_spec.rb +30 -11
  106. data/spec/knapsack_pro/adapters/cucumber_adapter_spec.rb +2 -5
  107. data/spec/knapsack_pro/adapters/rspec_adapter_spec.rb +146 -174
  108. data/spec/knapsack_pro/base_allocator_builder_spec.rb +22 -48
  109. data/spec/knapsack_pro/client/api/v1/build_distributions_spec.rb +19 -27
  110. data/spec/knapsack_pro/client/api/v1/queues_spec.rb +23 -43
  111. data/spec/knapsack_pro/client/connection_spec.rb +59 -7
  112. data/spec/knapsack_pro/config/ci/app_veyor_spec.rb +22 -8
  113. data/spec/knapsack_pro/config/ci/base_spec.rb +1 -0
  114. data/spec/knapsack_pro/config/ci/buildkite_spec.rb +51 -16
  115. data/spec/knapsack_pro/config/ci/circle_spec.rb +48 -13
  116. data/spec/knapsack_pro/config/ci/cirrus_ci_spec.rb +12 -12
  117. data/spec/knapsack_pro/config/ci/codefresh_spec.rb +21 -6
  118. data/spec/knapsack_pro/config/ci/codeship_spec.rb +20 -6
  119. data/spec/knapsack_pro/config/ci/github_actions_spec.rb +37 -10
  120. data/spec/knapsack_pro/config/ci/gitlab_ci_spec.rb +48 -13
  121. data/spec/knapsack_pro/config/ci/heroku_spec.rb +12 -12
  122. data/spec/knapsack_pro/config/ci/semaphore2_spec.rb +11 -11
  123. data/spec/knapsack_pro/config/ci/semaphore_spec.rb +12 -12
  124. data/spec/knapsack_pro/config/ci/travis_spec.rb +8 -8
  125. data/spec/knapsack_pro/config/env_spec.rb +204 -124
  126. data/spec/knapsack_pro/formatters/time_tracker_specs.rb +424 -0
  127. data/spec/knapsack_pro/hooks/queue_spec.rb +2 -2
  128. data/spec/knapsack_pro/presenter_spec.rb +1 -1
  129. data/spec/knapsack_pro/pure/queue/rspec_pure_spec.rb +224 -0
  130. data/spec/knapsack_pro/repository_adapters/git_adapter_spec.rb +72 -0
  131. data/spec/knapsack_pro/runners/queue/cucumber_runner_spec.rb +18 -16
  132. data/spec/knapsack_pro/runners/queue/minitest_runner_spec.rb +17 -14
  133. data/spec/knapsack_pro/runners/rspec_runner_spec.rb +40 -23
  134. data/spec/knapsack_pro/test_case_detectors/rspec_test_example_detector_spec.rb +1 -0
  135. data/spec/knapsack_pro/tracker_spec.rb +0 -4
  136. data/spec/knapsack_pro_spec.rb +3 -3
  137. data/spec/spec_helper.rb +0 -1
  138. metadata +26 -23
  139. data/lib/knapsack_pro/config/ci/snap_ci.rb +0 -35
  140. data/lib/knapsack_pro/config/ci/solano_ci.rb +0 -32
  141. data/lib/knapsack_pro/extensions/time.rb +0 -7
  142. data/lib/knapsack_pro/formatters/rspec_queue_profile_formatter_extension.rb +0 -56
  143. data/lib/knapsack_pro/formatters/rspec_queue_summary_formatter.rb +0 -112
  144. data/spec/knapsack_pro/config/ci/snap_ci_spec.rb +0 -104
  145. data/spec/knapsack_pro/config/ci/solano_ci_spec.rb +0 -73
  146. data/spec/knapsack_pro/extensions/time_spec.rb +0 -5
  147. data/spec/knapsack_pro/runners/queue/rspec_runner_spec.rb +0 -342
@@ -1,8 +1,41 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../formatters/time_tracker_fetcher'
4
+
1
5
  module KnapsackPro
2
6
  module Adapters
3
7
  class RSpecAdapter < BaseAdapter
4
8
  TEST_DIR_PATTERN = 'spec/**{,/*/**}/*_spec.rb'
5
9
 
10
+ def self.split_by_test_cases_enabled?
11
+ return false unless KnapsackPro::Config::Env.rspec_split_by_test_examples?
12
+
13
+ require 'rspec/core/version'
14
+ unless Gem::Version.new(::RSpec::Core::Version::STRING) >= Gem::Version.new('3.3.0')
15
+ raise "RSpec >= 3.3.0 is required to split test files by test examples. Learn more: #{KnapsackPro::Urls::SPLIT_BY_TEST_EXAMPLES}"
16
+ end
17
+
18
+ true
19
+ end
20
+
21
+ def self.test_file_cases_for(slow_test_files)
22
+ KnapsackPro.logger.info("Generating RSpec test examples JSON report for slow test files to prepare it to be split by test examples (by individual test cases). Thanks to that, a single slow test file can be split across parallel CI nodes. Analyzing #{slow_test_files.size} slow test files.")
23
+
24
+ # generate the RSpec JSON report in a separate process to not pollute the RSpec state
25
+ cmd = [
26
+ 'RACK_ENV=test',
27
+ 'RAILS_ENV=test',
28
+ KnapsackPro::Config::Env.rspec_test_example_detector_prefix,
29
+ 'rake knapsack_pro:rspec_test_example_detector',
30
+ ].join(' ')
31
+ unless Kernel.system(cmd)
32
+ raise "Could not generate JSON report for RSpec. Rake task failed when running #{cmd}"
33
+ end
34
+
35
+ # read the JSON report
36
+ KnapsackPro::TestCaseDetectors::RSpecTestExampleDetector.new.test_file_example_paths
37
+ end
38
+
6
39
  def self.ensure_no_tag_option_when_rspec_split_by_test_examples_enabled!(cli_args)
7
40
  if KnapsackPro::Config::Env.rspec_split_by_test_examples? && has_tag_option?(cli_args)
8
41
  error_message = "It is not allowed to use the RSpec tag option together with the RSpec split by test examples feature. Please see: #{KnapsackPro::Urls::RSPEC__SPLIT_BY_TEST_EXAMPLES__TAG}"
@@ -23,63 +56,63 @@ module KnapsackPro
23
56
  parsed_options(cli_args)&.[](:order)
24
57
  end
25
58
 
26
- def self.test_path(example)
27
- example_group = example.metadata[:example_group]
28
-
29
- if defined?(::Turnip) && Gem::Version.new(::Turnip::VERSION) < Gem::Version.new('2.0.0')
30
- unless example_group[:turnip]
31
- until example_group[:parent_example_group].nil?
32
- example_group = example_group[:parent_example_group]
33
- end
34
- end
35
- else
36
- until example_group[:parent_example_group].nil?
37
- example_group = example_group[:parent_example_group]
59
+ def self.file_path_for(example)
60
+ [
61
+ -> { parse_file_path(example.id) },
62
+ -> { example.metadata[:file_path] },
63
+ -> { example.metadata[:example_group][:file_path] },
64
+ -> { top_level_group(example)[:file_path] },
65
+ ]
66
+ .each do |path|
67
+ p = path.call
68
+ return p if p.include?('_spec.rb') || p.include?('.feature')
38
69
  end
39
- end
40
70
 
41
- example_group[:file_path]
71
+ return ''
42
72
  end
43
73
 
44
- def bind_time_tracker
45
- ::RSpec.configure do |config|
46
- config.prepend_before(:context) do
47
- KnapsackPro.tracker.start_timer
48
- end
74
+ def self.parse_file_path(id)
75
+ # https://github.com/rspec/rspec-core/blob/1eeadce5aa7137ead054783c31ff35cbfe9d07cc/lib/rspec/core/example.rb#L122
76
+ id.match(/\A(.*?)(?:\[([\d\s:,]+)\])?\z/).captures.first
77
+ end
49
78
 
50
- config.around(:each) do |example|
51
- current_test_path = KnapsackPro::Adapters::RSpecAdapter.test_path(example)
52
-
53
- # Stop timer to update time for a previously run test example.
54
- # This way we count time spent in runtime for the previous test example after around(:each) is already done.
55
- # Only do that if we're in the same test file. Otherwise, `before(:all)` execution time in the current file
56
- # will be applied to the previously ran test file.
57
- if KnapsackPro.tracker.current_test_path&.start_with?(KnapsackPro::TestFileCleaner.clean(current_test_path))
58
- KnapsackPro.tracker.stop_timer
59
- end
79
+ # private
80
+ def self.top_level_group(example)
81
+ group = example.metadata[:example_group]
82
+ until group[:parent_example_group].nil?
83
+ group = group[:parent_example_group]
84
+ end
85
+ group
86
+ end
60
87
 
61
- KnapsackPro.tracker.current_test_path =
62
- if KnapsackPro::Config::Env.rspec_split_by_test_examples? && KnapsackPro::Adapters::RSpecAdapter.slow_test_file?(RSpecAdapter, current_test_path)
63
- example.id
64
- else
65
- current_test_path
66
- end
88
+ def bind_time_tracker
89
+ ensure_no_focus!
90
+ log_tests_duration
91
+ end
67
92
 
93
+ def ensure_no_focus!
94
+ ::RSpec.configure do |config|
95
+ config.around(:each) do |example|
68
96
  if example.metadata[:focus] && KnapsackPro::Adapters::RSpecAdapter.rspec_configuration.filter.rules[:focus]
69
- raise "We detected a test file path #{current_test_path} with a test using the metadata `:focus` tag. RSpec might not run some tests in the Queue Mode (causing random tests skipping problem). Please remove the `:focus` tag from your codebase. See more: #{KnapsackPro::Urls::RSPEC__SKIPS_TESTS}"
97
+ file_path = KnapsackPro::Adapters::RSpecAdapter.file_path_for(example)
98
+ file_path = KnapsackPro::TestFileCleaner.clean(file_path)
99
+
100
+ raise "Knapsack Pro found an example tagged with focus in #{file_path}, please remove it. See more: #{KnapsackPro::Urls::RSPEC__SKIPS_TESTS}"
70
101
  end
71
102
 
72
103
  example.run
73
104
  end
105
+ end
106
+ end
74
107
 
75
- config.append_after(:context) do
76
- # after(:context) hook is run one time only, after all of the examples in a group
77
- # stop timer to count time for the very last executed test example
78
- KnapsackPro.tracker.stop_timer
79
- end
80
-
81
- config.after(:suite) do
82
- KnapsackPro.logger.debug(KnapsackPro::Presenter.global_time)
108
+ def log_tests_duration
109
+ ::RSpec.configure do |config|
110
+ config.append_after(:suite) do
111
+ time_tracker = KnapsackPro::Formatters::TimeTrackerFetcher.call
112
+ if time_tracker
113
+ formatted = KnapsackPro::Presenter.global_time(time_tracker.duration)
114
+ KnapsackPro.logger.debug(formatted)
115
+ end
83
116
  end
84
117
  end
85
118
  end
@@ -87,7 +120,8 @@ module KnapsackPro
87
120
  def bind_save_report
88
121
  ::RSpec.configure do |config|
89
122
  config.after(:suite) do
90
- KnapsackPro::Report.save
123
+ time_tracker = KnapsackPro::Formatters::TimeTrackerFetcher.call
124
+ KnapsackPro::Report.save(time_tracker.batch)
91
125
  end
92
126
  end
93
127
  end
@@ -95,10 +129,15 @@ module KnapsackPro
95
129
  def bind_before_queue_hook
96
130
  ::RSpec.configure do |config|
97
131
  config.before(:suite) do
98
- unless ENV['KNAPSACK_PRO_BEFORE_QUEUE_HOOK_CALLED']
99
- ENV['KNAPSACK_PRO_BEFORE_QUEUE_HOOK_CALLED'] = 'true'
100
- KnapsackPro::Hooks::Queue.call_before_queue
101
- end
132
+ KnapsackPro::Hooks::Queue.call_before_queue
133
+ end
134
+ end
135
+ end
136
+
137
+ def bind_after_queue_hook
138
+ ::RSpec.configure do |config|
139
+ config.after(:suite) do
140
+ KnapsackPro::Hooks::Queue.call_after_queue
102
141
  end
103
142
  end
104
143
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module KnapsackPro
2
4
  module Adapters
3
5
  class SpinachAdapter < BaseAdapter
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module KnapsackPro
2
4
  module Adapters
3
5
  class TestUnitAdapter < BaseAdapter
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module KnapsackPro
2
4
  class Allocator
3
5
  def initialize(args)
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module KnapsackPro
2
4
  class AllocatorBuilder < BaseAllocatorBuilder
3
5
  def allocator
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module KnapsackPro
2
4
  class BaseAllocatorBuilder
3
5
  TEST_RUNNER_MAP = {
@@ -33,35 +35,16 @@ module KnapsackPro
33
35
  def fast_and_slow_test_files_to_run
34
36
  test_files_to_run = all_test_files_to_run
35
37
 
36
- if adapter_class == KnapsackPro::Adapters::RSpecAdapter && KnapsackPro::Config::Env.rspec_split_by_test_examples?
37
- require 'rspec/core/version'
38
- unless Gem::Version.new(::RSpec::Core::Version::STRING) >= Gem::Version.new('3.3.0')
39
- raise "RSpec >= 3.3.0 is required to split test files by test examples. Learn more: #{KnapsackPro::Urls::SPLIT_BY_TEST_EXAMPLES}"
40
- end
41
-
38
+ if adapter_class.split_by_test_cases_enabled?
42
39
  slow_test_files = get_slow_test_files
40
+ return test_files_to_run if slow_test_files.empty?
43
41
 
44
- KnapsackPro.logger.info("Generating RSpec test examples JSON report for slow test files to prepare it to be split by test examples (by individual 'it's. Thanks to that a single slow test file can be split across parallel CI nodes). Analyzing #{slow_test_files.size} slow test files.")
45
-
46
- # generate RSpec JSON report in separate process to not pollute RSpec state
47
- cmd = [
48
- 'RACK_ENV=test',
49
- 'RAILS_ENV=test',
50
- KnapsackPro::Config::Env.rspec_test_example_detector_prefix,
51
- 'rake knapsack_pro:rspec_test_example_detector',
52
- ].join(' ')
53
- unless Kernel.system(cmd)
54
- raise "Could not generate JSON report for RSpec. Rake task failed when running #{cmd}"
55
- end
56
-
57
- # read JSON report
58
- detector = KnapsackPro::TestCaseDetectors::RSpecTestExampleDetector.new
59
- test_file_example_paths = detector.test_file_example_paths
42
+ test_file_cases = adapter_class.test_file_cases_for(slow_test_files)
60
43
 
61
- KnapsackPro::TestFilesWithTestCasesComposer.call(test_files_to_run, slow_test_files, test_file_example_paths)
62
- else
63
- test_files_to_run
44
+ return KnapsackPro::TestFilesWithTestCasesComposer.call(test_files_to_run, slow_test_files, test_file_cases)
64
45
  end
46
+
47
+ test_files_to_run
65
48
  end
66
49
 
67
50
  private
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module KnapsackPro
2
4
  class BuildDistributionFetcher
3
5
  class BuildDistributionEntity
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module KnapsackPro
2
4
  module Client
3
5
  module API
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module KnapsackPro
2
4
  module Client
3
5
  module API
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module KnapsackPro
2
4
  module Client
3
5
  module API
@@ -15,6 +17,9 @@ module KnapsackPro
15
17
  :node_total => args.fetch(:node_total),
16
18
  :node_index => args.fetch(:node_index),
17
19
  :ci_build_id => KnapsackPro::Config::Env.ci_node_build_id,
20
+ :user_seat => KnapsackPro::Config::Env.masked_user_seat,
21
+ :build_author => KnapsackPro::RepositoryAdapters::GitAdapter.new.build_author,
22
+ :commit_authors => KnapsackPro::RepositoryAdapters::GitAdapter.new.commit_authors,
18
23
  }
19
24
 
20
25
  unless request_hash[:cache_read_attempt]
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module KnapsackPro
2
4
  module Client
3
5
  module API
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module KnapsackPro
2
4
  module Client
3
5
  module API
@@ -16,11 +18,14 @@ module KnapsackPro
16
18
  :node_total => args.fetch(:node_total),
17
19
  :node_index => args.fetch(:node_index),
18
20
  :node_build_id => KnapsackPro::Config::Env.ci_node_build_id,
21
+ :user_seat => KnapsackPro::Config::Env.masked_user_seat,
19
22
  }
20
23
 
21
24
  if request_hash[:can_initialize_queue] && !request_hash[:attempt_connect_to_queue]
22
25
  request_hash.merge!({
23
- :test_files => args.fetch(:test_files)
26
+ :test_files => args.fetch(:test_files),
27
+ :build_author => KnapsackPro::RepositoryAdapters::GitAdapter.new.build_author,
28
+ :commit_authors => KnapsackPro::RepositoryAdapters::GitAdapter.new.commit_authors,
24
29
  })
25
30
  end
26
31
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module KnapsackPro
2
4
  module Client
3
5
  class Connection
@@ -59,18 +61,15 @@ module KnapsackPro
59
61
  request_hash.to_json
60
62
  end
61
63
 
62
- def test_suite_token
63
- KnapsackPro::Config::Env.test_suite_token
64
- end
65
-
66
64
  def json_headers
67
65
  {
68
66
  'Content-Type' => 'application/json',
69
67
  'Accept' => 'application/json',
70
68
  'KNAPSACK-PRO-CLIENT-NAME' => client_name,
71
69
  'KNAPSACK-PRO-CLIENT-VERSION' => KnapsackPro::VERSION,
72
- 'KNAPSACK-PRO-TEST-SUITE-TOKEN' => test_suite_token,
73
- }
70
+ 'KNAPSACK-PRO-TEST-SUITE-TOKEN' => KnapsackPro::Config::Env.test_suite_token,
71
+ 'KNAPSACK-PRO-CI-PROVIDER' => KnapsackPro::Config::Env.ci_provider,
72
+ }.compact
74
73
  end
75
74
 
76
75
  def client_name
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # https://www.appveyor.com/docs/environment-variables/
2
4
  module KnapsackPro
3
5
  module Config
@@ -26,6 +28,22 @@ module KnapsackPro
26
28
  def project_dir
27
29
  ENV['APPVEYOR_BUILD_FOLDER']
28
30
  end
31
+
32
+ def user_seat
33
+ ENV['APPVEYOR_REPO_COMMIT_AUTHOR']
34
+ end
35
+
36
+ def detected
37
+ ENV.key?('APPVEYOR') ? self.class : nil
38
+ end
39
+
40
+ def fixed_queue_split
41
+ false
42
+ end
43
+
44
+ def ci_provider
45
+ "AppVeyor"
46
+ end
29
47
  end
30
48
  end
31
49
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module KnapsackPro
2
4
  module Config
3
5
  module CI
@@ -22,6 +24,31 @@ module KnapsackPro
22
24
 
23
25
  def project_dir
24
26
  end
27
+
28
+ def user_seat
29
+ end
30
+
31
+ def detected
32
+ end
33
+
34
+ def fixed_queue_split
35
+ true
36
+ end
37
+
38
+ def ci_provider
39
+ return 'AWS CodeBuild' if ENV.key?('CODEBUILD_BUILD_ARN')
40
+ return 'Azure Pipelines' if ENV.key?('SYSTEM_TEAMFOUNDATIONCOLLECTIONURI')
41
+ return 'Bamboo' if ENV.key?('bamboo_planKey')
42
+ return 'Bitbucket Pipelines' if ENV.key?('BITBUCKET_COMMIT')
43
+ return 'Buddy.works' if ENV.key?('BUDDY')
44
+ return 'Drone.io' if ENV.key?('DRONE')
45
+ return 'Google Cloud Build' if ENV.key?('BUILDER_OUTPUT')
46
+ return 'Jenkins' if ENV.key?('JENKINS_URL')
47
+ return 'TeamCity' if ENV.key?('TEAMCITY_VERSION')
48
+ return 'Other' if KnapsackPro::Config::Env.ci?
49
+
50
+ nil
51
+ end
25
52
  end
26
53
  end
27
54
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module KnapsackPro
2
4
  module Config
3
5
  module CI
@@ -29,6 +31,22 @@ module KnapsackPro
29
31
  def project_dir
30
32
  ENV['BUILDKITE_BUILD_CHECKOUT_PATH']
31
33
  end
34
+
35
+ def user_seat
36
+ ENV['BUILDKITE_BUILD_AUTHOR'] || ENV['BUILDKITE_BUILD_CREATOR']
37
+ end
38
+
39
+ def detected
40
+ ENV.key?('BUILDKITE') ? self.class : nil
41
+ end
42
+
43
+ def fixed_queue_split
44
+ true
45
+ end
46
+
47
+ def ci_provider
48
+ "Buildkite"
49
+ end
32
50
  end
33
51
  end
34
52
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module KnapsackPro
2
4
  module Config
3
5
  module CI
@@ -25,6 +27,22 @@ module KnapsackPro
25
27
  def project_dir
26
28
  ENV['CIRCLE_WORKING_DIRECTORY']
27
29
  end
30
+
31
+ def user_seat
32
+ ENV['CIRCLE_USERNAME'] || ENV['CIRCLE_PR_USERNAME']
33
+ end
34
+
35
+ def detected
36
+ ENV.key?('CIRCLECI') ? self.class : nil
37
+ end
38
+
39
+ def fixed_queue_split
40
+ false
41
+ end
42
+
43
+ def ci_provider
44
+ "CircleCI"
45
+ end
28
46
  end
29
47
  end
30
48
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module KnapsackPro
2
4
  module Config
3
5
  module CI
@@ -25,6 +27,22 @@ module KnapsackPro
25
27
  def project_dir
26
28
  ENV['CIRRUS_WORKING_DIR']
27
29
  end
30
+
31
+ def user_seat
32
+ # not provided
33
+ end
34
+
35
+ def detected
36
+ ENV.key?('CIRRUS_CI') ? self.class : nil
37
+ end
38
+
39
+ def fixed_queue_split
40
+ false
41
+ end
42
+
43
+ def ci_provider
44
+ "Cirrus CI"
45
+ end
28
46
  end
29
47
  end
30
48
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # https://codefresh.io/docs/docs/codefresh-yaml/variables/#system-provided-variables
2
4
  module KnapsackPro
3
5
  module Config
@@ -26,6 +28,22 @@ module KnapsackPro
26
28
  def project_dir
27
29
  # not provided
28
30
  end
31
+
32
+ def user_seat
33
+ ENV['CF_BUILD_INITIATOR']
34
+ end
35
+
36
+ def detected
37
+ ENV.key?('CF_BUILD_ID') ? self.class : nil
38
+ end
39
+
40
+ def fixed_queue_split
41
+ false
42
+ end
43
+
44
+ def ci_provider
45
+ "Codefresh"
46
+ end
29
47
  end
30
48
  end
31
49
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module KnapsackPro
2
4
  module Config
3
5
  module CI
@@ -25,6 +27,22 @@ module KnapsackPro
25
27
  def project_dir
26
28
  # not provided
27
29
  end
30
+
31
+ def user_seat
32
+ ENV['CI_COMMITTER_NAME']
33
+ end
34
+
35
+ def detected
36
+ ENV['CI_NAME'] == 'codeship' ? self.class : nil
37
+ end
38
+
39
+ def fixed_queue_split
40
+ true
41
+ end
42
+
43
+ def ci_provider
44
+ "Codeship"
45
+ end
28
46
  end
29
47
  end
30
48
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # https://help.github.com/en/actions/configuring-and-managing-workflows/using-environment-variables#default-environment-variables
2
4
  module KnapsackPro
3
5
  module Config
@@ -16,6 +18,14 @@ module KnapsackPro
16
18
  ENV['GITHUB_RUN_ID']
17
19
  end
18
20
 
21
+ def node_retry_count
22
+ # A unique number for each attempt of a particular workflow run in a repository.
23
+ # This number begins at 1 for the workflow run's first attempt, and increments with each re-run.
24
+ run_attempt = ENV['GITHUB_RUN_ATTEMPT']
25
+ return unless run_attempt
26
+ run_attempt.to_i - 1
27
+ end
28
+
19
29
  def commit_hash
20
30
  ENV['GITHUB_SHA']
21
31
  end
@@ -29,6 +39,22 @@ module KnapsackPro
29
39
  def project_dir
30
40
  ENV['GITHUB_WORKSPACE']
31
41
  end
42
+
43
+ def user_seat
44
+ ENV['GITHUB_ACTOR']
45
+ end
46
+
47
+ def detected
48
+ ENV.key?('GITHUB_ACTIONS') ? self.class : nil
49
+ end
50
+
51
+ def fixed_queue_split
52
+ true
53
+ end
54
+
55
+ def ci_provider
56
+ "GitHub Actions"
57
+ end
32
58
  end
33
59
  end
34
60
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # https://docs.gitlab.com/ce/ci/variables/
2
4
  module KnapsackPro
3
5
  module Config
@@ -16,7 +18,7 @@ module KnapsackPro
16
18
 
17
19
  def node_build_id
18
20
  ENV['CI_PIPELINE_ID'] || # Gitlab Release 9.0+
19
- ENV['CI_BUILD_ID'] # Gitlab Release 8.x
21
+ ENV['CI_BUILD_ID'] # Gitlab Release 8.x
20
22
  end
21
23
 
22
24
  def commit_hash
@@ -32,6 +34,23 @@ module KnapsackPro
32
34
  def project_dir
33
35
  ENV['CI_PROJECT_DIR']
34
36
  end
37
+
38
+ def user_seat
39
+ ENV['GITLAB_USER_NAME'] || # Gitlab Release 10.0
40
+ ENV['GITLAB_USER_EMAIL'] # Gitlab Release 8.12
41
+ end
42
+
43
+ def detected
44
+ ENV.key?('GITLAB_CI') ? self.class : nil
45
+ end
46
+
47
+ def fixed_queue_split
48
+ true
49
+ end
50
+
51
+ def ci_provider
52
+ "Gitlab CI"
53
+ end
35
54
  end
36
55
  end
37
56
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module KnapsackPro
2
4
  module Config
3
5
  module CI
@@ -25,6 +27,22 @@ module KnapsackPro
25
27
  def project_dir
26
28
  '/app' if node_build_id
27
29
  end
30
+
31
+ def user_seat
32
+ # not provided
33
+ end
34
+
35
+ def detected
36
+ ENV.key?('HEROKU_TEST_RUN_ID') ? self.class : nil
37
+ end
38
+
39
+ def fixed_queue_split
40
+ false
41
+ end
42
+
43
+ def ci_provider
44
+ "Heroku CI"
45
+ end
28
46
  end
29
47
  end
30
48
  end