knapsack_pro 5.5.0 → 5.7.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (97) hide show
  1. checksums.yaml +4 -4
  2. data/.circleci/config.yml +5 -1
  3. data/CHANGELOG.md +20 -0
  4. data/lib/knapsack_pro/adapters/base_adapter.rb +10 -0
  5. data/lib/knapsack_pro/adapters/cucumber_adapter.rb +2 -0
  6. data/lib/knapsack_pro/adapters/minitest_adapter.rb +2 -0
  7. data/lib/knapsack_pro/adapters/rspec_adapter.rb +31 -0
  8. data/lib/knapsack_pro/adapters/spinach_adapter.rb +2 -0
  9. data/lib/knapsack_pro/adapters/test_unit_adapter.rb +2 -0
  10. data/lib/knapsack_pro/allocator.rb +2 -0
  11. data/lib/knapsack_pro/allocator_builder.rb +2 -0
  12. data/lib/knapsack_pro/base_allocator_builder.rb +8 -25
  13. data/lib/knapsack_pro/build_distribution_fetcher.rb +2 -0
  14. data/lib/knapsack_pro/client/api/action.rb +2 -0
  15. data/lib/knapsack_pro/client/api/v1/base.rb +2 -0
  16. data/lib/knapsack_pro/client/api/v1/build_distributions.rb +2 -0
  17. data/lib/knapsack_pro/client/api/v1/build_subsets.rb +2 -0
  18. data/lib/knapsack_pro/client/api/v1/queues.rb +2 -0
  19. data/lib/knapsack_pro/client/connection.rb +2 -0
  20. data/lib/knapsack_pro/config/ci/app_veyor.rb +2 -0
  21. data/lib/knapsack_pro/config/ci/base.rb +2 -0
  22. data/lib/knapsack_pro/config/ci/buildkite.rb +2 -0
  23. data/lib/knapsack_pro/config/ci/circle.rb +2 -0
  24. data/lib/knapsack_pro/config/ci/cirrus_ci.rb +2 -0
  25. data/lib/knapsack_pro/config/ci/codefresh.rb +2 -0
  26. data/lib/knapsack_pro/config/ci/codeship.rb +2 -0
  27. data/lib/knapsack_pro/config/ci/github_actions.rb +2 -0
  28. data/lib/knapsack_pro/config/ci/gitlab_ci.rb +2 -0
  29. data/lib/knapsack_pro/config/ci/heroku.rb +2 -0
  30. data/lib/knapsack_pro/config/ci/semaphore.rb +2 -0
  31. data/lib/knapsack_pro/config/ci/semaphore2.rb +2 -0
  32. data/lib/knapsack_pro/config/ci/travis.rb +2 -0
  33. data/lib/knapsack_pro/config/env.rb +2 -0
  34. data/lib/knapsack_pro/config/env_generator.rb +2 -0
  35. data/lib/knapsack_pro/config/temp_files.rb +8 -4
  36. data/lib/knapsack_pro/crypto/branch_encryptor.rb +2 -0
  37. data/lib/knapsack_pro/crypto/decryptor.rb +2 -0
  38. data/lib/knapsack_pro/crypto/digestor.rb +2 -0
  39. data/lib/knapsack_pro/crypto/encryptor.rb +2 -0
  40. data/lib/knapsack_pro/extensions/time.rb +2 -0
  41. data/lib/knapsack_pro/formatters/rspec_json_formatter.rb +2 -0
  42. data/lib/knapsack_pro/formatters/rspec_queue_profile_formatter_extension.rb +2 -0
  43. data/lib/knapsack_pro/formatters/rspec_queue_summary_formatter.rb +2 -0
  44. data/lib/knapsack_pro/hooks/queue.rb +2 -0
  45. data/lib/knapsack_pro/logger_wrapper.rb +2 -0
  46. data/lib/knapsack_pro/mask_string.rb +2 -0
  47. data/lib/knapsack_pro/presenter.rb +2 -0
  48. data/lib/knapsack_pro/queue_allocator.rb +2 -0
  49. data/lib/knapsack_pro/queue_allocator_builder.rb +2 -0
  50. data/lib/knapsack_pro/railtie.rb +2 -0
  51. data/lib/knapsack_pro/report.rb +2 -0
  52. data/lib/knapsack_pro/repository_adapter_initiator.rb +2 -0
  53. data/lib/knapsack_pro/repository_adapters/base_adapter.rb +2 -0
  54. data/lib/knapsack_pro/repository_adapters/env_adapter.rb +2 -0
  55. data/lib/knapsack_pro/repository_adapters/git_adapter.rb +2 -0
  56. data/lib/knapsack_pro/runners/base_runner.rb +2 -0
  57. data/lib/knapsack_pro/runners/cucumber_runner.rb +2 -0
  58. data/lib/knapsack_pro/runners/minitest_runner.rb +2 -0
  59. data/lib/knapsack_pro/runners/queue/base_runner.rb +2 -0
  60. data/lib/knapsack_pro/runners/queue/cucumber_runner.rb +2 -0
  61. data/lib/knapsack_pro/runners/queue/minitest_runner.rb +2 -0
  62. data/lib/knapsack_pro/runners/queue/rspec_runner.rb +2 -0
  63. data/lib/knapsack_pro/runners/rspec_runner.rb +2 -0
  64. data/lib/knapsack_pro/runners/spinach_runner.rb +2 -0
  65. data/lib/knapsack_pro/runners/test_unit_runner.rb +2 -0
  66. data/lib/knapsack_pro/slow_test_file_determiner.rb +2 -0
  67. data/lib/knapsack_pro/slow_test_file_finder.rb +2 -0
  68. data/lib/knapsack_pro/task_loader.rb +2 -0
  69. data/lib/knapsack_pro/test_case_detectors/rspec_test_example_detector.rb +2 -0
  70. data/lib/knapsack_pro/test_case_mergers/base_merger.rb +2 -0
  71. data/lib/knapsack_pro/test_case_mergers/rspec_merger.rb +2 -0
  72. data/lib/knapsack_pro/test_file_cleaner.rb +2 -0
  73. data/lib/knapsack_pro/test_file_finder.rb +2 -0
  74. data/lib/knapsack_pro/test_file_pattern.rb +2 -0
  75. data/lib/knapsack_pro/test_file_presenter.rb +2 -0
  76. data/lib/knapsack_pro/test_files_with_test_cases_composer.rb +2 -0
  77. data/lib/knapsack_pro/test_flat_distributor.rb +2 -0
  78. data/lib/knapsack_pro/tracker.rb +2 -0
  79. data/lib/knapsack_pro/utils.rb +2 -0
  80. data/lib/knapsack_pro/version.rb +3 -1
  81. data/lib/knapsack_pro.rb +2 -0
  82. data/lib/tasks/cucumber.rake +2 -0
  83. data/lib/tasks/encrypted_branch_names.rake +2 -0
  84. data/lib/tasks/encrypted_test_file_names.rake +2 -0
  85. data/lib/tasks/minitest.rake +2 -0
  86. data/lib/tasks/queue/cucumber.rake +2 -0
  87. data/lib/tasks/queue/minitest.rake +2 -0
  88. data/lib/tasks/queue/rspec.rake +2 -0
  89. data/lib/tasks/rspec.rake +2 -0
  90. data/lib/tasks/salt.rake +2 -0
  91. data/lib/tasks/spinach.rake +2 -0
  92. data/lib/tasks/test_unit.rake +2 -0
  93. data/spec/knapsack_pro/adapters/base_adapter_spec.rb +12 -0
  94. data/spec/knapsack_pro/adapters/rspec_adapter_spec.rb +75 -0
  95. data/spec/knapsack_pro/base_allocator_builder_spec.rb +22 -48
  96. data/spec/knapsack_pro/client/connection_spec.rb +54 -7
  97. metadata +2 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 792df8662b070a5352ff707690d0ea394a938787a2656856aa5e8a4098954765
4
- data.tar.gz: 668a573e3cda8c09b99013d8c2b9ea962e13abc1febc0e88bd8613daf7341bd3
3
+ metadata.gz: 87b8a5c7eb2a78f487c9029cdeda3a1cc367b15e248eb1f3b5aaaf1959ebe333
4
+ data.tar.gz: 12fef31bb8aac248014b3d808190f7f2e7ae6217e83e4af9e40b17b6f98ed379
5
5
  SHA512:
6
- metadata.gz: 1bdd45d85651fc9528a45f9f8604accce2abc04788d0c81809617ce30319901020decb75bdb164cccda7e70fcc9de09c5d08fde4693420684100a502dc5d7bd0
7
- data.tar.gz: 8c500895bf104fdde5e0817e55a30c2d3d54f3020e19039e291fe6dde836f9ede1e5dc5371c91b1413d23fc2fec998242bae539dbade17c21d08bb05a7d87cb5
6
+ metadata.gz: 43379ac46ef1c5fa6a3fccf0d598831e009564ba37bdb264c681799aa893d5a9d8fbb569ce2bd83fe297b9c885117e95a5439731fd16ea35aa2f294acb88d936
7
+ data.tar.gz: 1be1143ac276347a0dee92bb15b7660f36b666c9cb8d025e9b1931f463803f9efc2a38ced34d4ca27bbfaa466fc1b6afc71d2960ced12b09888ca09a6572b14b
data/.circleci/config.yml CHANGED
@@ -30,10 +30,14 @@ jobs:
30
30
  command: |
31
31
  bundle install --jobs=4 --retry=3 --path vendor/bundle
32
32
 
33
+ - run: gem install rubocop
34
+
33
35
  - save_cache:
34
36
  paths:
35
37
  - ./vendor/bundle
36
38
  key: v2-dependencies-bundler-{{ checksum "knapsack_pro.gemspec" }}
37
39
 
38
- # run tests!
40
+ # enforce `frozen_string_literal: true` in the gem files
41
+ - run: rubocop -A --only Style/FrozenStringLiteralComment,Layout/EmptyLineAfterMagicComment lib/
42
+
39
43
  - run: bundle exec rspec spec
data/CHANGELOG.md CHANGED
@@ -1,5 +1,25 @@
1
1
  # Changelog
2
2
 
3
+ ### 5.7.0
4
+
5
+ * Performance improvement: don't run `rake knapsack_pro:rspec_test_example_detector` when no slow test files are detected for RSpec.
6
+
7
+ https://github.com/KnapsackPro/knapsack_pro-ruby/pull/225
8
+
9
+ https://github.com/KnapsackPro/knapsack_pro-ruby/compare/v5.6.0...v5.7.0
10
+
11
+ ### 5.6.0
12
+
13
+ * Use `frozen_string_literal: true` to reduce memory usage
14
+
15
+ https://github.com/KnapsackPro/knapsack_pro-ruby/pull/220
16
+
17
+ * Enforce `frozen_string_literal: true` in the gem files with Rubocop
18
+
19
+ https://github.com/KnapsackPro/knapsack_pro-ruby/pull/222
20
+
21
+ https://github.com/KnapsackPro/knapsack_pro-ruby/compare/v5.5.0...v5.6.0
22
+
3
23
  ### 5.5.0
4
24
 
5
25
  * Detect user seats for AppVeyor, Codefresh, Codeship
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module KnapsackPro
2
4
  module Adapters
3
5
  class BaseAdapter
@@ -9,6 +11,14 @@ module KnapsackPro
9
11
  "#{KnapsackPro::Config::TempFiles::TEMP_DIRECTORY_PATH}/#{adapter_name}-bind_method_called_for_node_#{KnapsackPro::Config::Env.ci_node_index}.txt"
10
12
  end
11
13
 
14
+ def self.split_by_test_cases_enabled?
15
+ false
16
+ end
17
+
18
+ def self.test_file_cases_for(slow_test_files)
19
+ raise NotImplementedError
20
+ end
21
+
12
22
  def self.slow_test_file?(adapter_class, test_file_path)
13
23
  @slow_test_file_paths ||=
14
24
  begin
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module KnapsackPro
2
4
  module Adapters
3
5
  class CucumberAdapter < BaseAdapter
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module KnapsackPro
2
4
  module Adapters
3
5
  class MinitestAdapter < BaseAdapter
@@ -1,8 +1,39 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module KnapsackPro
2
4
  module Adapters
3
5
  class RSpecAdapter < BaseAdapter
4
6
  TEST_DIR_PATTERN = 'spec/**{,/*/**}/*_spec.rb'
5
7
 
8
+ def self.split_by_test_cases_enabled?
9
+ return false unless KnapsackPro::Config::Env.rspec_split_by_test_examples?
10
+
11
+ require 'rspec/core/version'
12
+ unless Gem::Version.new(::RSpec::Core::Version::STRING) >= Gem::Version.new('3.3.0')
13
+ raise "RSpec >= 3.3.0 is required to split test files by test examples. Learn more: #{KnapsackPro::Urls::SPLIT_BY_TEST_EXAMPLES}"
14
+ end
15
+
16
+ true
17
+ end
18
+
19
+ def self.test_file_cases_for(slow_test_files)
20
+ 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.")
21
+
22
+ # generate the RSpec JSON report in a separate process to not pollute the RSpec state
23
+ cmd = [
24
+ 'RACK_ENV=test',
25
+ 'RAILS_ENV=test',
26
+ KnapsackPro::Config::Env.rspec_test_example_detector_prefix,
27
+ 'rake knapsack_pro:rspec_test_example_detector',
28
+ ].join(' ')
29
+ unless Kernel.system(cmd)
30
+ raise "Could not generate JSON report for RSpec. Rake task failed when running #{cmd}"
31
+ end
32
+
33
+ # read the JSON report
34
+ KnapsackPro::TestCaseDetectors::RSpecTestExampleDetector.new.test_file_example_paths
35
+ end
36
+
6
37
  def self.ensure_no_tag_option_when_rspec_split_by_test_examples_enabled!(cli_args)
7
38
  if KnapsackPro::Config::Env.rspec_split_by_test_examples? && has_tag_option?(cli_args)
8
39
  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}"
@@ -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
@@ -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
  class Connection
@@ -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
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module KnapsackPro
2
4
  module Config
3
5
  module CI
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module KnapsackPro
2
4
  module Config
3
5
  module CI
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module KnapsackPro
2
4
  module Config
3
5
  module CI
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module KnapsackPro
2
4
  module Config
3
5
  module CI
@@ -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
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module KnapsackPro
2
4
  module Config
3
5
  module CI
@@ -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
@@ -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
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module KnapsackPro
2
4
  module Config
3
5
  module CI
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module KnapsackPro
2
4
  module Config
3
5
  module CI
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # https://docs.semaphoreci.com/article/12-environment-variables
2
4
  module KnapsackPro
3
5
  module Config
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module KnapsackPro
2
4
  module Config
3
5
  module CI
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module KnapsackPro
2
4
  module Config
3
5
  class Env
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module KnapsackPro
2
4
  module Config
3
5
  class EnvGenerator
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module KnapsackPro
2
4
  module Config
3
5
  class TempFiles
@@ -22,10 +24,12 @@ module KnapsackPro
22
24
  end
23
25
 
24
26
  def self.gitignore_file_content
25
- "# This directory is used by knapsack_pro gem for storing temporary files during tests runtime.\n" <<
26
- "# Ignore all files, and do not commit this directory into your repository.\n" <<
27
- "# Learn more at https://knapsackpro.com\n" <<
28
- "*"
27
+ <<~GITIGNORE
28
+ # This directory is used by knapsack_pro gem for storing temporary files during tests runtime.
29
+ # Ignore all files, and do not commit this directory into your repository.
30
+ # Learn more at https://knapsackpro.com
31
+ *
32
+ GITIGNORE
29
33
  end
30
34
 
31
35
  def self.create_gitignore_file!
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module KnapsackPro
2
4
  module Crypto
3
5
  class BranchEncryptor
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module KnapsackPro
2
4
  module Crypto
3
5
  class Decryptor
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module KnapsackPro
2
4
  module Crypto
3
5
  class Digestor
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module KnapsackPro
2
4
  module Crypto
3
5
  class Encryptor
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'time'
2
4
 
3
5
  class Time
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  RSpec::Support.require_rspec_core('formatters/json_formatter')
2
4
 
3
5
  # based on https://github.com/rspec/rspec-core/blob/master/lib/rspec/core/formatters/json_formatter.rb
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  RSpec::Support.require_rspec_core('formatters/profile_formatter')
2
4
 
3
5
  module KnapsackPro
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  RSpec::Support.require_rspec_core('formatters/base_formatter')
2
4
  RSpec::Support.require_rspec_core('formatters/base_text_formatter')
3
5
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module KnapsackPro
2
4
  module Hooks
3
5
  class Queue
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module KnapsackPro
2
4
  class LoggerWrapper
3
5
  def initialize(logger)
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module KnapsackPro
2
4
  class MaskString
3
5
  def self.call(string)
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module KnapsackPro
2
4
  class Presenter
3
5
  class << self
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module KnapsackPro
2
4
  class QueueAllocator
3
5
  def initialize(args)
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module KnapsackPro
2
4
  class QueueAllocatorBuilder < BaseAllocatorBuilder
3
5
  def allocator
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'rails'
2
4
  require 'knapsack_pro'
3
5
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module KnapsackPro
2
4
  class Report
3
5
  def self.save
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module KnapsackPro
2
4
  class RepositoryAdapterInitiator
3
5
  def self.call
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module KnapsackPro
2
4
  module RepositoryAdapters
3
5
  class BaseAdapter
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module KnapsackPro
2
4
  module RepositoryAdapters
3
5
  class EnvAdapter < BaseAdapter
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module KnapsackPro
2
4
  module RepositoryAdapters
3
5
  class GitAdapter < BaseAdapter
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module KnapsackPro
2
4
  module Runners
3
5
  class BaseRunner
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module KnapsackPro
2
4
  module Runners
3
5
  class CucumberRunner < BaseRunner
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module KnapsackPro
2
4
  module Runners
3
5
  class MinitestRunner < BaseRunner
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module KnapsackPro
2
4
  module Runners
3
5
  module Queue
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module KnapsackPro
2
4
  module Runners
3
5
  module Queue
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module KnapsackPro
2
4
  module Runners
3
5
  module Queue
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module KnapsackPro
2
4
  module Runners
3
5
  module Queue
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module KnapsackPro
2
4
  module Runners
3
5
  class RSpecRunner < BaseRunner
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module KnapsackPro
2
4
  module Runners
3
5
  class SpinachRunner < BaseRunner
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module KnapsackPro
2
4
  module Runners
3
5
  class TestUnitRunner < BaseRunner
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module KnapsackPro
2
4
  class SlowTestFileDeterminer
3
5
  TIME_THRESHOLD_PER_CI_NODE = 0.7 # 70%
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module KnapsackPro
2
4
  class SlowTestFileFinder
3
5
  # Get recorded test files from API.
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'rake'
2
4
 
3
5
  module KnapsackPro
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module KnapsackPro
2
4
  module TestCaseDetectors
3
5
  class RSpecTestExampleDetector
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module KnapsackPro
2
4
  module TestCaseMergers
3
5
  class BaseMerger
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module KnapsackPro
2
4
  module TestCaseMergers
3
5
  class RSpecMerger < BaseMerger
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module KnapsackPro
2
4
  class TestFileCleaner
3
5
  def self.clean(test_file_path)
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module KnapsackPro
2
4
  class TestFileFinder
3
5
  def self.call(test_file_pattern, test_file_list_enabled: true)
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module KnapsackPro
2
4
  class TestFilePattern
3
5
  def self.call(adapter_class)
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module KnapsackPro
2
4
  class TestFilePresenter
3
5
  def self.stringify_paths(test_file_paths)
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module KnapsackPro
2
4
  class TestFilesWithTestCasesComposer
3
5
  # Args:
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module KnapsackPro
2
4
  class TestFlatDistributor
3
5
  DIR_TYPES = [
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module KnapsackPro
2
4
  class Tracker
3
5
  include Singleton
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module KnapsackPro
2
4
  class Utils
3
5
  def self.unsymbolize(obj)
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module KnapsackPro
2
- VERSION = '5.5.0'
4
+ VERSION = '5.7.0'
3
5
  end
data/lib/knapsack_pro.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'logger'
2
4
  require 'singleton'
3
5
  require 'net/http'
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'knapsack_pro'
2
4
 
3
5
  namespace :knapsack_pro do
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'knapsack_pro'
2
4
 
3
5
  namespace :knapsack_pro do
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'knapsack_pro'
2
4
 
3
5
  namespace :knapsack_pro do
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'knapsack_pro'
2
4
 
3
5
  namespace :knapsack_pro do
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'knapsack_pro'
2
4
 
3
5
  namespace :knapsack_pro do
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'knapsack_pro'
2
4
 
3
5
  namespace :knapsack_pro do
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'knapsack_pro'
2
4
 
3
5
  namespace :knapsack_pro do
data/lib/tasks/rspec.rake CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'knapsack_pro'
2
4
 
3
5
  namespace :knapsack_pro do
data/lib/tasks/salt.rake CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  namespace :knapsack_pro do
2
4
  task :salt, [:size] do |_, args|
3
5
  default_size = 32
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'knapsack_pro'
2
4
 
3
5
  namespace :knapsack_pro do
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'knapsack_pro'
2
4
 
3
5
  namespace :knapsack_pro do
@@ -42,6 +42,18 @@ describe KnapsackPro::Adapters::BaseAdapter do
42
42
  end
43
43
  end
44
44
 
45
+ describe '.split_by_test_cases_enabled?' do
46
+ subject { described_class.split_by_test_cases_enabled? }
47
+
48
+ it { expect(subject).to be false }
49
+ end
50
+
51
+ describe '.test_file_cases_for' do
52
+ subject { described_class.test_file_cases_for([]) }
53
+
54
+ it { expect { subject }.to raise_error NotImplementedError }
55
+ end
56
+
45
57
  describe '.slow_test_file?' do
46
58
  let(:adapter_class) { double }
47
59
  let(:slow_test_files) do
@@ -12,6 +12,81 @@ describe KnapsackPro::Adapters::RSpecAdapter do
12
12
  it_behaves_like 'adapter'
13
13
  end
14
14
 
15
+ describe '.split_by_test_cases_enabled?' do
16
+ subject { described_class.split_by_test_cases_enabled? }
17
+
18
+ before do
19
+ expect(KnapsackPro::Config::Env).to receive(:rspec_split_by_test_examples?).and_return(rspec_split_by_test_examples_enabled)
20
+ end
21
+
22
+ context 'when the RSpec split by test examples is enabled' do
23
+ let(:rspec_split_by_test_examples_enabled) { true }
24
+
25
+ it { expect(subject).to be true }
26
+
27
+ context 'when the RSpec version is < 3.3.0' do
28
+ before do
29
+ stub_const('RSpec::Core::Version::STRING', '3.2.0')
30
+ end
31
+
32
+ it do
33
+ expect { subject }.to raise_error RuntimeError, 'RSpec >= 3.3.0 is required to split test files by test examples. Learn more: https://knapsackpro.com/perma/ruby/split-by-test-examples'
34
+ end
35
+ end
36
+ end
37
+
38
+ context 'when the RSpec split by test examples is disabled' do
39
+ let(:rspec_split_by_test_examples_enabled) { false }
40
+
41
+ it { expect(subject).to be false }
42
+ end
43
+ end
44
+
45
+ describe '.test_file_cases_for' do
46
+ let(:slow_test_files) do
47
+ [
48
+ '1_spec.rb',
49
+ '2_spec.rb',
50
+ '3_spec.rb',
51
+ '4_spec.rb',
52
+ '5_spec.rb',
53
+ ]
54
+ end
55
+
56
+ subject { described_class.test_file_cases_for(slow_test_files) }
57
+
58
+ before do
59
+ logger = instance_double(Logger)
60
+ expect(KnapsackPro).to receive(:logger).and_return(logger)
61
+ expect(logger).to receive(:info).with("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 5 slow test files.")
62
+
63
+ cmd = 'RACK_ENV=test RAILS_ENV=test bundle exec rake knapsack_pro:rspec_test_example_detector'
64
+ expect(Kernel).to receive(:system).with(cmd).and_return(cmd_result)
65
+ end
66
+
67
+ context 'when the rake task to detect RSpec test examples succeeded' do
68
+ let(:cmd_result) { true }
69
+
70
+ it 'returns test example paths for slow test files' do
71
+ rspec_test_example_detector = instance_double(KnapsackPro::TestCaseDetectors::RSpecTestExampleDetector)
72
+ expect(KnapsackPro::TestCaseDetectors::RSpecTestExampleDetector).to receive(:new).and_return(rspec_test_example_detector)
73
+
74
+ test_file_example_paths = double
75
+ expect(rspec_test_example_detector).to receive(:test_file_example_paths).and_return(test_file_example_paths)
76
+
77
+ expect(subject).to eq test_file_example_paths
78
+ end
79
+ end
80
+
81
+ context 'when the rake task to detect RSpec test examples failed' do
82
+ let(:cmd_result) { false }
83
+
84
+ it do
85
+ expect { subject }.to raise_error(RuntimeError, 'Could not generate JSON report for RSpec. Rake task failed when running RACK_ENV=test RAILS_ENV=test bundle exec rake knapsack_pro:rspec_test_example_detector')
86
+ end
87
+ end
88
+ end
89
+
15
90
  describe '.ensure_no_tag_option_when_rspec_split_by_test_examples_enabled!' do
16
91
  let(:cli_args) { double }
17
92
 
@@ -117,8 +117,8 @@ describe KnapsackPro::BaseAllocatorBuilder do
117
117
  describe '#fast_and_slow_test_files_to_run' do
118
118
  subject { allocator_builder.fast_and_slow_test_files_to_run }
119
119
 
120
- context 'when looking for test files on disk by default' do
121
- it do
120
+ context 'when split by test cases disabled' do
121
+ it 'returns test files to run based on test files on the disk' do
122
122
  test_file_pattern = double
123
123
  expect(KnapsackPro::TestFilePattern).to receive(:call).with(adapter_class).and_return(test_file_pattern)
124
124
 
@@ -129,70 +129,44 @@ describe KnapsackPro::BaseAllocatorBuilder do
129
129
  end
130
130
  end
131
131
 
132
- context 'when RSpec adapter AND rspec split by test examples is enabled' do
133
- let(:adapter_class) { KnapsackPro::Adapters::RSpecAdapter }
132
+ context 'when split by test cases enabled' do
134
133
  let(:test_files_to_run) { double }
135
- let(:cmd) { 'RACK_ENV=test RAILS_ENV=test bundle exec rake knapsack_pro:rspec_test_example_detector' }
136
134
 
137
- before do
138
- expect(KnapsackPro::Config::Env).to receive(:rspec_split_by_test_examples?).and_return(true)
135
+ before do
136
+ expect(adapter_class).to receive(:split_by_test_cases_enabled?).and_return(true)
139
137
 
140
138
  test_file_pattern = double
141
139
  expect(KnapsackPro::TestFilePattern).to receive(:call).with(adapter_class).and_return(test_file_pattern)
142
140
 
143
141
  expect(KnapsackPro::TestFileFinder).to receive(:call).with(test_file_pattern).and_return(test_files_to_run)
144
- end
145
142
 
146
- context 'when RSpec version < 3.3.0' do
147
- before do
148
- stub_const('RSpec::Core::Version::STRING', '3.2.0')
149
- end
150
-
151
- it do
152
- expect { subject }.to raise_error RuntimeError, 'RSpec >= 3.3.0 is required to split test files by test examples. Learn more: https://knapsackpro.com/perma/ruby/split-by-test-examples'
153
- end
143
+ expect(allocator_builder).to receive(:get_slow_test_files).and_return(slow_test_files)
154
144
  end
155
145
 
156
- context 'when rake task to detect RSpec test examples works' do
157
- let(:slow_test_files) { double(size: 5) }
158
- let(:cmd_result) { true }
159
- let(:test_file_example_paths) { double }
160
- let(:logger) { instance_double(Logger) }
161
- let(:test_files_with_test_cases) { double }
162
-
163
- before do
164
- expect(allocator_builder).to receive(:get_slow_test_files).and_return(slow_test_files)
165
-
166
- expect(KnapsackPro).to receive(:logger).and_return(logger)
167
-
168
- expect(Kernel).to receive(:system).with(cmd).and_return(cmd_result)
169
-
170
- rspec_test_example_detector = instance_double(KnapsackPro::TestCaseDetectors::RSpecTestExampleDetector)
171
- expect(KnapsackPro::TestCaseDetectors::RSpecTestExampleDetector).to receive(:new).and_return(rspec_test_example_detector)
172
- expect(rspec_test_example_detector).to receive(:test_file_example_paths).and_return(test_file_example_paths)
173
-
174
- expect(KnapsackPro::TestFilesWithTestCasesComposer).to receive(:call).with(test_files_to_run, slow_test_files, test_file_example_paths).and_return(test_files_with_test_cases)
146
+ context 'when slow test files are detected' do
147
+ let(:slow_test_files) do
148
+ [
149
+ '1_spec.rb',
150
+ '2_spec.rb',
151
+ ]
175
152
  end
176
153
 
177
- it do
178
- expect(logger).to receive(:info).with("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 5 slow test files.")
154
+ it 'returns test files with test cases' do
155
+ test_file_cases = double
156
+ expect(adapter_class).to receive(:test_file_cases_for).with(slow_test_files).and_return(test_file_cases)
157
+
158
+ test_files_with_test_cases = double
159
+ expect(KnapsackPro::TestFilesWithTestCasesComposer).to receive(:call).with(test_files_to_run, slow_test_files, test_file_cases).and_return(test_files_with_test_cases)
179
160
 
180
161
  expect(subject).to eq test_files_with_test_cases
181
162
  end
182
163
  end
183
164
 
184
- context 'when rake task to detect RSpec test examples failed' do
185
- let(:slow_test_files) { double(size: 5) }
186
- let(:cmd_result) { false }
187
-
188
- before do
189
- expect(allocator_builder).to receive(:get_slow_test_files).and_return(slow_test_files)
190
-
191
- expect(Kernel).to receive(:system).with(cmd).and_return(cmd_result)
192
- end
165
+ context 'when slow test files are not detected' do
166
+ let(:slow_test_files) { [] }
193
167
 
194
- it do
195
- expect { subject }.to raise_error(RuntimeError, 'Could not generate JSON report for RSpec. Rake task failed when running RACK_ENV=test RAILS_ENV=test bundle exec rake knapsack_pro:rspec_test_example_detector')
168
+ it 'returns test files without test cases' do
169
+ expect(subject).to eq test_files_to_run
196
170
  end
197
171
  end
198
172
  end
@@ -282,15 +282,17 @@ describe KnapsackPro::Client::Connection do
282
282
  request_hash: request_hash)
283
283
  end
284
284
  let(:test_suite_token) { '3fa64859337f6e56409d49f865d13fd7' }
285
-
286
285
  let(:connection) { described_class.new(action) }
287
-
288
- before do
289
- stub_const('ENV', {
286
+ let(:headers) do
287
+ {
290
288
  'KNAPSACK_PRO_ENDPOINT' => 'http://api.knapsackpro.test:3000',
291
289
  'KNAPSACK_PRO_TEST_SUITE_TOKEN' => test_suite_token,
292
290
  'GITHUB_ACTIONS' => 'true',
293
- })
291
+ }
292
+ end
293
+
294
+ before do
295
+ stub_const('ENV', headers)
294
296
  end
295
297
 
296
298
  describe '#call' do
@@ -311,7 +313,7 @@ describe KnapsackPro::Client::Connection do
311
313
  expect(http).to receive(:read_timeout=).with(15)
312
314
  end
313
315
 
314
- context 'when http method is POST' do
316
+ context 'when http method is POST on GitHub Actions' do
315
317
  let(:http_method) { :post }
316
318
 
317
319
  before do
@@ -334,7 +336,30 @@ describe KnapsackPro::Client::Connection do
334
336
  end
335
337
  end
336
338
 
337
- context 'when http method is GET' do
339
+ context 'when http method is POST and CI is undetected' do
340
+ let(:http_method) { :post }
341
+
342
+ let(:headers) do
343
+ {
344
+ 'KNAPSACK_PRO_ENDPOINT' => 'http://api.knapsackpro.test:3000',
345
+ 'KNAPSACK_PRO_TEST_SUITE_TOKEN' => test_suite_token,
346
+ }
347
+ end
348
+
349
+ before do
350
+ expect(http).to receive(:post).with(
351
+ anything,
352
+ anything,
353
+ hash_not_including('KNAPSACK-PRO-CI-PROVIDER')
354
+ ).and_return(http_response)
355
+ end
356
+
357
+ it_behaves_like 'when request got response from API' do
358
+ let(:expected_http_method) { 'POST' }
359
+ end
360
+ end
361
+
362
+ context 'when http method is GET on GitHub Actions' do
338
363
  let(:http_method) { :get }
339
364
 
340
365
  before do
@@ -358,6 +383,28 @@ describe KnapsackPro::Client::Connection do
358
383
  end
359
384
  end
360
385
 
386
+ context 'when http method is GET and CI is undetected' do
387
+ let(:http_method) { :get }
388
+
389
+ let(:headers) do
390
+ {
391
+ 'KNAPSACK_PRO_ENDPOINT' => 'http://api.knapsackpro.test:3000',
392
+ 'KNAPSACK_PRO_TEST_SUITE_TOKEN' => test_suite_token,
393
+ }
394
+ end
395
+
396
+ before do
397
+ expect(http).to receive(:get).with(
398
+ anything,
399
+ hash_not_including('KNAPSACK-PRO-CI-PROVIDER')
400
+ ).and_return(http_response)
401
+ end
402
+
403
+ it_behaves_like 'when request got response from API' do
404
+ let(:expected_http_method) { 'GET' }
405
+ end
406
+ end
407
+
361
408
  context 'when retry request for http method POST' do
362
409
  let(:http_method) { :post }
363
410
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: knapsack_pro
3
3
  version: !ruby/object:Gem::Version
4
- version: 5.5.0
4
+ version: 5.7.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - ArturT
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-08-23 00:00:00.000000000 Z
11
+ date: 2023-09-20 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake