knapsack_pro 3.8.0 → 7.0.0

Sign up to get free protection for your applications and to get access to all the features.
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