knapsack_pro 1.20.2 → 1.22.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (46) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +45 -0
  3. data/README.md +43 -18
  4. data/lib/knapsack_pro.rb +6 -0
  5. data/lib/knapsack_pro/adapters/base_adapter.rb +16 -0
  6. data/lib/knapsack_pro/adapters/rspec_adapter.rb +11 -9
  7. data/lib/knapsack_pro/allocator.rb +7 -5
  8. data/lib/knapsack_pro/allocator_builder.rb +2 -1
  9. data/lib/knapsack_pro/base_allocator_builder.rb +41 -10
  10. data/lib/knapsack_pro/build_distribution_fetcher.rb +57 -0
  11. data/lib/knapsack_pro/client/api/v1/build_distributions.rb +13 -0
  12. data/lib/knapsack_pro/client/connection.rb +38 -16
  13. data/lib/knapsack_pro/config/env.rb +4 -0
  14. data/lib/knapsack_pro/queue_allocator.rb +7 -5
  15. data/lib/knapsack_pro/queue_allocator_builder.rb +2 -1
  16. data/lib/knapsack_pro/runners/queue/rspec_runner.rb +8 -1
  17. data/lib/knapsack_pro/runners/rspec_runner.rb +5 -2
  18. data/lib/knapsack_pro/slow_test_file_determiner.rb +33 -0
  19. data/lib/knapsack_pro/slow_test_file_finder.rb +27 -0
  20. data/lib/knapsack_pro/test_case_detectors/rspec_test_example_detector.rb +26 -7
  21. data/lib/knapsack_pro/test_case_mergers/base_merger.rb +29 -0
  22. data/lib/knapsack_pro/test_case_mergers/rspec_merger.rb +34 -0
  23. data/lib/knapsack_pro/test_file_finder.rb +43 -5
  24. data/lib/knapsack_pro/test_files_with_test_cases_composer.rb +22 -0
  25. data/lib/knapsack_pro/version.rb +1 -1
  26. data/spec/knapsack_pro/adapters/base_adapter_spec.rb +55 -0
  27. data/spec/knapsack_pro/adapters/rspec_adapter_spec.rb +61 -25
  28. data/spec/knapsack_pro/allocator_builder_spec.rb +7 -3
  29. data/spec/knapsack_pro/allocator_spec.rb +7 -5
  30. data/spec/knapsack_pro/base_allocator_builder_spec.rb +79 -27
  31. data/spec/knapsack_pro/build_distribution_fetcher_spec.rb +89 -0
  32. data/spec/knapsack_pro/client/api/v1/build_distributions_spec.rb +31 -0
  33. data/spec/knapsack_pro/client/connection_spec.rb +235 -104
  34. data/spec/knapsack_pro/config/env_spec.rb +14 -0
  35. data/spec/knapsack_pro/queue_allocator_builder_spec.rb +7 -3
  36. data/spec/knapsack_pro/queue_allocator_spec.rb +7 -5
  37. data/spec/knapsack_pro/runners/queue/rspec_runner_spec.rb +25 -0
  38. data/spec/knapsack_pro/runners/rspec_runner_spec.rb +4 -4
  39. data/spec/knapsack_pro/slow_test_file_determiner_spec.rb +74 -0
  40. data/spec/knapsack_pro/slow_test_file_finder_spec.rb +43 -0
  41. data/spec/knapsack_pro/test_case_detectors/rspec_test_example_detector_spec.rb +83 -37
  42. data/spec/knapsack_pro/test_case_mergers/base_merger_spec.rb +27 -0
  43. data/spec/knapsack_pro/test_case_mergers/rspec_merger_spec.rb +59 -0
  44. data/spec/knapsack_pro/test_file_finder_spec.rb +105 -29
  45. data/spec/knapsack_pro/test_files_with_test_cases_composer_spec.rb +41 -0
  46. metadata +27 -10
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 6bbc828d338c810094114953894489db0696b70f013beac451b1c45602c323cd
4
- data.tar.gz: ae287454ad0658666d1d0cd85c4eaf91eabe009ee95b05b3a76d719a245395ae
3
+ metadata.gz: 36d79c8a60d76dff5b549e0507820264cf35c2f07f90eee9934f30e593191664
4
+ data.tar.gz: 532d70f5b50274cca485f527d3f553929c8a1e0432ede3bb517f0b29a5414df4
5
5
  SHA512:
6
- metadata.gz: f70aca52cc3808f0028d036dd8b5057130cf6610ede948075a293c3165ddf46e44e8fdf922e7457808dca8f390ded887adb5f4c95146a5b925535621b1de7a93
7
- data.tar.gz: 32e5fb5098e39fdb93694184b16c26603ca1edcdc193ab1c513ab9cd55800fa2c54157b28b365260d2e2231bd3bea6ffcc5b2b1921c9076ab75e37095433e5ef
6
+ metadata.gz: 9b8755b6d9d1deb27982fc4c156baa1160fcf531799e77996248aa828070dbdcdbe8d5475b591bd2c5f3257de309056b2b39f685b42dd1c2378ce6dc9222f339
7
+ data.tar.gz: 7c24ae262d1691331b840783c530645440e22872372a56d8584e39b8e2a350c6235e75c9eac79dd5ecc4d0d05d74d65bdc4b176e937ee2b0277028d4c870b2f3
@@ -1,5 +1,50 @@
1
1
  # Change Log
2
2
 
3
+ ### 1.22.3
4
+
5
+ * Support for non-delimited formatting params of RSpec like `-fMyCustomFormatter`
6
+
7
+ https://github.com/KnapsackPro/knapsack_pro-ruby/pull/115
8
+
9
+ https://github.com/KnapsackPro/knapsack_pro-ruby/compare/v1.22.2...v1.22.3
10
+
11
+ ### 1.22.2
12
+
13
+ * Log when next retry request to Knapsack Pro API happens before starting Fallback Mode
14
+
15
+ https://github.com/KnapsackPro/knapsack_pro-ruby/pull/114
16
+
17
+ https://github.com/KnapsackPro/knapsack_pro-ruby/compare/v1.22.1...v1.22.2
18
+
19
+ ### 1.22.1
20
+
21
+ * Fix for an auto split of slow RSpec test files by test examples when using `KNAPSACK_PRO_RSPEC_SPLIT_BY_TEST_EXAMPLES=true` and `parallel_tests` gem. Save the JSON reports with unique file names with the CI node index in the name to avoid accidentally overriding the files on the same disk.
22
+
23
+ https://github.com/KnapsackPro/knapsack_pro-ruby/pull/113
24
+
25
+ https://github.com/KnapsackPro/knapsack_pro-ruby/compare/v1.22.0...v1.22.1
26
+
27
+ ### 1.22.0
28
+
29
+ * Increase request retry timebox from 4s to 8s to not flood Knapsack Pro API with too many requests in a short period of time and to give time for API server to autoscale and add additional machines to serve traffic
30
+ * When Fallback Mode is disabled with env `KNAPSACK_PRO_FALLBACK_MODE_ENABLED=false` then retry the request to Knapsack Pro API for 6 times instead of only 3 times.
31
+
32
+ Here is related [info why some users want to disable Fallback Mode](https://github.com/KnapsackPro/knapsack_pro-ruby#required-ci-configuration-if-you-use-retry-single-failed-ci-node-feature-on-your-ci-server-when-knapsack_pro_fixed_queue_splittrue-in-queue-mode-or-knapsack_pro_fixed_test_suite_splittrue-in-regular-mode).
33
+
34
+ https://github.com/KnapsackPro/knapsack_pro-ruby/pull/112
35
+
36
+ https://github.com/KnapsackPro/knapsack_pro-ruby/compare/v1.21.0...v1.22.0
37
+
38
+ ### 1.21.0
39
+
40
+ * Automatically detect slow test files for RSpec and split them by test examples when `KNAPSACK_PRO_RSPEC_SPLIT_BY_TEST_EXAMPLES=true`
41
+ * Add slow test file pattern `KNAPSACK_PRO_SLOW_TEST_FILE_PATTERN` to define RSpec slow test files that should be split by test examples
42
+ * Start sending API token in header `KNAPSACK-PRO-TEST-SUITE-TOKEN` instead of a key `test_suite_token` in JSON payload.
43
+
44
+ https://github.com/KnapsackPro/knapsack_pro-ruby/pull/106
45
+
46
+ https://github.com/KnapsackPro/knapsack_pro-ruby/compare/v1.20.2...v1.21.0
47
+
3
48
  ### 1.20.2
4
49
 
5
50
  * Raise an error when running Cucumber in Queue Mode and Cucumber system process doesn't finish execution correctly (for instance Cucumber process was killed by CI server due to lack of memory)
data/README.md CHANGED
@@ -83,7 +83,8 @@ We keep this old FAQ in README to not break old links spread across the web. You
83
83
  - [KNAPSACK_PRO_MODIFY_DEFAULT_RSPEC_FORMATTERS (hide duplicated summary of pending and failed tests)](#knapsack_pro_modify_default_rspec_formatters-hide-duplicated-summary-of-pending-and-failed-tests)
84
84
  - [Supported test runners in queue mode](#supported-test-runners-in-queue-mode)
85
85
  - [Split test files by test cases](#split-test-files-by-test-cases)
86
- - [RSpec split test files by test examples (individual `it`)](#rspec-split-test-files-by-test-examples-individual-it)
86
+ - [RSpec split test files by test examples (by individual `it`s)](#rspec-split-test-files-by-test-examples-by-individual-its)
87
+ - [How to manually define a list of slow test files to be split by test cases](#how-to-manually-define-a-list-of-slow-test-files-to-be-split-by-test-cases)
87
88
  - [Extra configuration for CI server](#extra-configuration-for-ci-server)
88
89
  - [Info about ENV variables](#info-about-env-variables)
89
90
  - [KNAPSACK_PRO_FIXED_TEST_SUITE_SPLIT (test suite split based on seed)](#knapsack_pro_fixed_test_suite_split-test-suite-split-based-on-seed)
@@ -597,33 +598,44 @@ At this moment the queue mode works for:
597
598
 
598
599
  ## Split test files by test cases
599
600
 
600
- > __Note:__ this is an experimental feature. It works for Regular Mode and Queue Mode. For large test suite with a few thousand test files, it may generate too many RSpec test example paths that may lead to too large JSON payload in request to Knapsack Pro API and this could trigger the API timeout.
601
- >
602
- > Please give us feedback so we could improve the feature.
603
- > https://knapsackpro.com/contact
601
+ __How it works__: You can split slow test file by test cases. Thanks to that the slow test file can be split across parallel CI nodes because test cases from the test file will run on different CI nodes.
602
+
603
+ This is helpful when you have one or a few very slow test files that are a bottleneck for CI build speed and you don't want to manually create a few smaller test files from the slow test files. Instead, you can tell `knapsack_pro` gem to split your slow test files by test cases across parallel CI nodes.
604
604
 
605
- __How it works__: You can split slow test file by test cases. Thanks to that the test file can be split across parallel CI nodes because test cases from the test file will run on different CI nodes.
605
+ Knapsack Pro API provides recorded timing of test files from your previously recorded CI builds and `knapsack_pro` gem will use this suggestion to determine slow test files. `knapsack_pro` gem splits only slow test files by test cases. Test files that are fast won't be split by test cases because it is not needed.
606
606
 
607
- This is helpful when you have one or a few very slow test files that are a bottleneck for CI build speed and you don't want to manually create a few smaller test files from the slow test files. Instead, you can tell `knapsack_pro` gem to split your test files by test cases across parallel CI nodes.
607
+ > __Note:__ This feature works for below test runners in Knapsack Pro Regular Mode and Queue Mode.
608
608
 
609
609
  ### RSpec split test files by test examples (by individual `it`s)
610
610
 
611
- > ❗ __WARNING (known issues):__ This is an experimental feature. We detected edge cases for Queue Mode when test examples might be ignored by RSpec and won't run test. Do not use this feature for production yet. We'll appreciate your [feedback](https://knapsackpro.com/contact) how it works while you test it on a separate branch. We work on improvements.
611
+ > ❗ __RSpec requirement:__ You need `RSpec >= 3.3.0` in order to use this feature.
612
612
 
613
- In order to split RSpec test files by test examples across parallel CI nodes you need to set environment variable:
613
+ In order to split RSpec slow test files by test examples across parallel CI nodes you need to set environment variable:
614
614
 
615
615
  ```
616
616
  KNAPSACK_PRO_RSPEC_SPLIT_BY_TEST_EXAMPLES=true
617
617
  ```
618
618
 
619
- Thanks to that your CI build speed can be faster. We recommend using this feature with Queue Mode to ensure parallel CI nodes finish work at a similar time which gives you the shortest CI build time.
619
+ Thanks to that your CI build speed can be faster. We recommend using this feature with [Queue Mode](https://youtu.be/hUEB1XDKEFY) to ensure parallel CI nodes finish work at a similar time which gives you the shortest CI build time.
620
+
621
+ ### How to manually define a list of slow test files to be split by test cases
620
622
 
621
- Doing tests split by test examples can generate a lot of logs by `knapsack_pro` gem in Queue Mode. We recommend to set log level to:
623
+ If you don't want to rely on a list of test files from Knapsack Pro API to determine slow test files that should be split by test cases then you can define your own list of slow test files.
622
624
 
623
625
  ```
624
- KNAPSACK_PRO_LOG_LEVEL=warn
626
+ # enable split by test cases for RSpec
627
+ KNAPSACK_PRO_RSPEC_SPLIT_BY_TEST_EXAMPLES=true
628
+
629
+ # example slow test files pattern for RSpec
630
+ KNAPSACK_PRO_SLOW_TEST_FILE_PATTERN="{spec/models/user_spec.rb,spec/controllers/**/*_spec.rb}"
625
631
  ```
626
632
 
633
+ `KNAPSACK_PRO_SLOW_TEST_FILE_PATTERN` must be subset of `KNAPSACK_PRO_TEST_FILE_PATTERN` (example default pattern for RSpec is `KNAPSACK_PRO_TEST_FILE_PATTERN="spec/**{,/*/**}/*_spec.rb"`).
634
+
635
+ > __Warning:__ `KNAPSACK_PRO_SLOW_TEST_FILE_PATTERN` pattern is mostly useful for debugging purposes by developers of `knapsack_pro` gem. If you want to use it then __it is recommended to provide a shortlist of slow test files__ with the pattern.
636
+ >
637
+ > If you use a too broad list of slow test files then you may end up slowing your test suite, especially for RSpec it may result in a slow generating list of test examples in your project. The long list of test file example paths won't be accepted by Knapsack Pro API due to API timeout. CI providers like CircleCI may exceed server memory when running too many RSpec test examples.
638
+
627
639
  ## Extra configuration for CI server
628
640
 
629
641
  ### Info about ENV variables
@@ -699,7 +711,7 @@ Read below required configuration step if you use Queue Mode and you set [`KNAPS
699
711
 
700
712
  If you use other CI server you need to manually configure your CI server to set `KNAPSACK_PRO_CI_NODE_RETRY_COUNT=1` only during retry CI node attempt. If `KNAPSACK_PRO_CI_NODE_RETRY_COUNT > 0` then knapsack_pro won't allow starting running tests in Fallback Mode and instead will raise error so a user can manually retry CI node later when a connection to Knapsack Pro API can be established.
701
713
 
702
- If you cannot set `KNAPSACK_PRO_CI_NODE_RETRY_COUNT` only for retried CI node or it is not possible for your CI server then you can disable Fallback Mode completely `KNAPSACK_PRO_FALLBACK_MODE_ENABLED=false`.
714
+ If you cannot set `KNAPSACK_PRO_CI_NODE_RETRY_COUNT` only for retried CI node or it is not possible for your CI server then you can disable Fallback Mode completely `KNAPSACK_PRO_FALLBACK_MODE_ENABLED=false`. When Fallback Mode is disabled then knapsack_pro gem will try to connect to Knapsack Pro API 6 times instead of only 3 times to ensure there is a low chance of failing your CI node due to lost connection with the API.
703
715
 
704
716
  ### Passing arguments to rake task
705
717
 
@@ -979,19 +991,28 @@ You can parallelize your builds across virtual machines with [travis matrix feat
979
991
 
980
992
  ```yaml
981
993
  script:
982
- # Step for RSpec
994
+ # Step for RSpec in Regular Mode
983
995
  - "bundle exec rake knapsack_pro:rspec"
984
996
 
985
- # Step for Cucumber
997
+ # Step for RSpec in Queue Mode
998
+ - "bundle exec rake knapsack_pro:queue:rspec"
999
+
1000
+ # Step for Cucumber in Regular Mode
986
1001
  - "bundle exec rake knapsack_pro:cucumber"
987
1002
 
988
- # Step for Minitest
1003
+ # Step for Cucumber in Queue Mode
1004
+ - "bundle exec rake knapsack_pro:queue:cucumber"
1005
+
1006
+ # Step for Minitest in Regular Mode
989
1007
  - "bundle exec rake knapsack_pro:minitest"
990
1008
 
991
- # Step for test-unit
1009
+ # Step for Minitest in Queue Mode
1010
+ - "bundle exec rake knapsack_pro:queue:minitest"
1011
+
1012
+ # Step for test-unit in Regular Mode
992
1013
  - "bundle exec rake knapsack_pro:test_unit"
993
1014
 
994
- # Step for Spinach
1015
+ # Step for Spinach in Regular Mode
995
1016
  - "bundle exec rake knapsack_pro:spinach"
996
1017
 
997
1018
  env:
@@ -1003,6 +1024,10 @@ env:
1003
1024
  - KNAPSACK_PRO_TEST_SUITE_TOKEN_TEST_UNIT=test-unit-token
1004
1025
  - KNAPSACK_PRO_TEST_SUITE_TOKEN_SPINACH=spinach-token
1005
1026
 
1027
+ # if you use Knapsack Pro Queue Mode you must set below env variable
1028
+ # to be able to retry single failed parallel job from Travis UI
1029
+ - KNAPSACK_PRO_FIXED_QUEUE_SPLIT=true
1030
+
1006
1031
  - KNAPSACK_PRO_CI_NODE_TOTAL=2
1007
1032
  jobs:
1008
1033
  - KNAPSACK_PRO_CI_NODE_INDEX=0
@@ -55,6 +55,12 @@ require_relative 'knapsack_pro/adapters/test_unit_adapter'
55
55
  require_relative 'knapsack_pro/adapters/spinach_adapter'
56
56
  require_relative 'knapsack_pro/allocator'
57
57
  require_relative 'knapsack_pro/queue_allocator'
58
+ require_relative 'knapsack_pro/test_case_mergers/base_merger'
59
+ require_relative 'knapsack_pro/test_case_mergers/rspec_merger'
60
+ require_relative 'knapsack_pro/build_distribution_fetcher'
61
+ require_relative 'knapsack_pro/slow_test_file_determiner'
62
+ require_relative 'knapsack_pro/slow_test_file_finder'
63
+ require_relative 'knapsack_pro/test_files_with_test_cases_composer'
58
64
  require_relative 'knapsack_pro/base_allocator_builder'
59
65
  require_relative 'knapsack_pro/allocator_builder'
60
66
  require_relative 'knapsack_pro/queue_allocator_builder'
@@ -4,6 +4,22 @@ module KnapsackPro
4
4
  # Just example, please overwrite constant in subclass
5
5
  TEST_DIR_PATTERN = 'test/**{,/*/**}/*_test.rb'
6
6
 
7
+ def self.slow_test_file?(adapter_class, test_file_path)
8
+ @slow_test_file_paths ||=
9
+ begin
10
+ slow_test_files =
11
+ if KnapsackPro::Config::Env.slow_test_file_pattern
12
+ KnapsackPro::TestFileFinder.slow_test_files_by_pattern(adapter_class)
13
+ else
14
+ # get slow test files from JSON file based on data from API
15
+ KnapsackPro::SlowTestFileDeterminer.read_from_json_report
16
+ end
17
+ KnapsackPro::TestFilePresenter.paths(slow_test_files)
18
+ end
19
+ clean_path = KnapsackPro::TestFileCleaner.clean(test_file_path)
20
+ @slow_test_file_paths.include?(clean_path)
21
+ end
22
+
7
23
  def self.bind
8
24
  adapter = new
9
25
  adapter.bind
@@ -22,18 +22,20 @@ module KnapsackPro
22
22
  def bind_time_tracker
23
23
  ::RSpec.configure do |config|
24
24
  config.around(:each) do |example|
25
+ current_example_group =
26
+ if ::RSpec.respond_to?(:current_example)
27
+ ::RSpec.current_example.metadata[:example_group]
28
+ else
29
+ example.metadata
30
+ end
31
+
32
+ current_test_path = KnapsackPro::Adapters::RSpecAdapter.test_path(current_example_group)
33
+
25
34
  KnapsackPro.tracker.current_test_path =
26
- if KnapsackPro::Config::Env.rspec_split_by_test_examples?
35
+ if KnapsackPro::Config::Env.rspec_split_by_test_examples? && KnapsackPro::Adapters::RSpecAdapter.slow_test_file?(RSpecAdapter, current_test_path)
27
36
  example.id
28
37
  else
29
- current_example_group =
30
- if ::RSpec.respond_to?(:current_example)
31
- ::RSpec.current_example.metadata[:example_group]
32
- else
33
- example.metadata
34
- end
35
-
36
- KnapsackPro::Adapters::RSpecAdapter.test_path(current_example_group)
38
+ current_test_path
37
39
  end
38
40
 
39
41
  KnapsackPro.tracker.start_timer
@@ -1,7 +1,8 @@
1
1
  module KnapsackPro
2
2
  class Allocator
3
3
  def initialize(args)
4
- @test_files = args.fetch(:test_files)
4
+ @fast_and_slow_test_files_to_run = args.fetch(:fast_and_slow_test_files_to_run)
5
+ @fallback_mode_test_files = args.fetch(:fallback_mode_test_files)
5
6
  @ci_node_total = args.fetch(:ci_node_total)
6
7
  @ci_node_index = args.fetch(:ci_node_index)
7
8
  @repository_adapter = args.fetch(:repository_adapter)
@@ -32,13 +33,14 @@ module KnapsackPro
32
33
 
33
34
  private
34
35
 
35
- attr_reader :test_files,
36
+ attr_reader :fast_and_slow_test_files_to_run,
37
+ :fallback_mode_test_files,
36
38
  :ci_node_total,
37
39
  :ci_node_index,
38
40
  :repository_adapter
39
41
 
40
42
  def encrypted_test_files
41
- KnapsackPro::Crypto::Encryptor.call(test_files)
43
+ KnapsackPro::Crypto::Encryptor.call(fast_and_slow_test_files_to_run)
42
44
  end
43
45
 
44
46
  def encrypted_branch
@@ -56,12 +58,12 @@ module KnapsackPro
56
58
  end
57
59
 
58
60
  def prepare_test_files(response)
59
- decrypted_test_files = KnapsackPro::Crypto::Decryptor.call(test_files, response['test_files'])
61
+ decrypted_test_files = KnapsackPro::Crypto::Decryptor.call(fast_and_slow_test_files_to_run, response['test_files'])
60
62
  KnapsackPro::TestFilePresenter.paths(decrypted_test_files)
61
63
  end
62
64
 
63
65
  def fallback_test_files
64
- test_flat_distributor = KnapsackPro::TestFlatDistributor.new(test_files, ci_node_total)
66
+ test_flat_distributor = KnapsackPro::TestFlatDistributor.new(fallback_mode_test_files, ci_node_total)
65
67
  test_files_for_node_index = test_flat_distributor.test_files_for_node(ci_node_index)
66
68
  KnapsackPro::TestFilePresenter.paths(test_files_for_node_index)
67
69
  end
@@ -2,7 +2,8 @@ module KnapsackPro
2
2
  class AllocatorBuilder < BaseAllocatorBuilder
3
3
  def allocator
4
4
  KnapsackPro::Allocator.new(
5
- test_files: test_files,
5
+ fast_and_slow_test_files_to_run: fast_and_slow_test_files_to_run,
6
+ fallback_mode_test_files: fallback_mode_test_files,
6
7
  ci_node_total: env.ci_node_total,
7
8
  ci_node_index: env.ci_node_index,
8
9
  repository_adapter: repository_adapter,
@@ -21,29 +21,40 @@ module KnapsackPro
21
21
  KnapsackPro::Config::Env.test_dir || TestFilePattern.test_dir(adapter_class)
22
22
  end
23
23
 
24
- def test_files
25
- found_test_files = KnapsackPro::TestFileFinder.call(test_file_pattern)
24
+ # in fallback mode we always want to run the whole test files
25
+ # (not split by test cases) to guarantee that each test will be executed
26
+ # at least once across parallel CI nodes
27
+ def fallback_mode_test_files
28
+ all_test_files_to_run
29
+ end
30
+
31
+ # detect test files present on the disk that should be run
32
+ # this may include some fast test files + slow test files split by test cases
33
+ def fast_and_slow_test_files_to_run
34
+ test_files_to_run = all_test_files_to_run
26
35
 
27
36
  if adapter_class == KnapsackPro::Adapters::RSpecAdapter && KnapsackPro::Config::Env.rspec_split_by_test_examples?
28
- test_files_count = found_test_files.size
37
+ unless Gem::Version.new(RSpec::Core::Version::STRING) >= Gem::Version.new('3.3.0')
38
+ raise 'RSpec >= 3.3.0 is required to split test files by test examples. Learn more: https://github.com/KnapsackPro/knapsack_pro-ruby#split-test-files-by-test-cases'
39
+ end
29
40
 
30
- KnapsackPro.logger.warn("Generating RSpec test examples JSON report to prepare your test suite to be split by test examples (by individual 'it's. Thanks to that a single test file can be split across parallel CI nodes). Analyzing #{test_files_count} test files.")
41
+ slow_test_files = get_slow_test_files
31
42
 
32
- if test_files_count > 1000
33
- KnapsackPro.logger.warn("You have more than 1000 test files, it may take longer to generate test examples. Please wait...")
34
- end
43
+ 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.")
35
44
 
36
45
  # generate RSpec JSON report in separate process to not pollute RSpec state
37
- cmd = 'bundle exec rake knapsack_pro:rspec_test_example_detector'
46
+ cmd = 'RACK_ENV=test RAILS_ENV=test bundle exec rake knapsack_pro:rspec_test_example_detector'
38
47
  unless Kernel.system(cmd)
39
48
  raise "Could not generate JSON report for RSpec. Rake task failed when running #{cmd}"
40
49
  end
41
50
 
42
51
  # read JSON report
43
52
  detector = KnapsackPro::TestCaseDetectors::RSpecTestExampleDetector.new
44
- detector.test_file_example_paths
53
+ test_file_example_paths = detector.test_file_example_paths
54
+
55
+ KnapsackPro::TestFilesWithTestCasesComposer.call(test_files_to_run, slow_test_files, test_file_example_paths)
45
56
  else
46
- found_test_files
57
+ test_files_to_run
47
58
  end
48
59
  end
49
60
 
@@ -62,5 +73,25 @@ module KnapsackPro
62
73
  def test_file_pattern
63
74
  TestFilePattern.call(adapter_class)
64
75
  end
76
+
77
+ def all_test_files_to_run
78
+ KnapsackPro::TestFileFinder.call(test_file_pattern)
79
+ end
80
+
81
+ def slow_test_file_pattern
82
+ KnapsackPro::Config::Env.slow_test_file_pattern
83
+ end
84
+
85
+ def get_slow_test_files
86
+ slow_test_files =
87
+ if slow_test_file_pattern
88
+ KnapsackPro::TestFileFinder.slow_test_files_by_pattern(adapter_class)
89
+ else
90
+ # get slow test files from API and ensure they exist on disk
91
+ KnapsackPro::SlowTestFileFinder.call(adapter_class)
92
+ end
93
+ KnapsackPro.logger.debug("Detected #{slow_test_files.size} slow test files: #{slow_test_files.inspect}")
94
+ slow_test_files
95
+ end
65
96
  end
66
97
  end
@@ -0,0 +1,57 @@
1
+ module KnapsackPro
2
+ class BuildDistributionFetcher
3
+ class BuildDistributionEntity
4
+ def initialize(response)
5
+ @response = response
6
+ end
7
+
8
+ def time_execution
9
+ response.fetch('time_execution')
10
+ end
11
+
12
+ def test_files
13
+ response.fetch('test_files')
14
+ end
15
+
16
+ private
17
+
18
+ attr_reader :response
19
+ end
20
+
21
+ def self.call
22
+ new.call
23
+ end
24
+
25
+ # get test files and time execution for last build distribution matching:
26
+ # branch, node_total, node_index
27
+ def call
28
+ connection = KnapsackPro::Client::Connection.new(build_action)
29
+ response = connection.call
30
+ if connection.success?
31
+ raise ArgumentError.new(response) if connection.errors?
32
+ BuildDistributionEntity.new(response)
33
+ else
34
+ KnapsackPro.logger.warn("Slow test files fallback behaviour started. We could not connect with Knapsack Pro API to fetch last CI build test files that are needed to determine slow test files. No test files will be split by test cases. It means all test files will be split by the whole test files as if split by test cases would be disabled https://github.com/KnapsackPro/knapsack_pro-ruby#split-test-files-by-test-cases")
35
+ BuildDistributionEntity.new({
36
+ 'time_execution' => 0.0,
37
+ 'test_files' => [],
38
+ })
39
+ end
40
+ end
41
+
42
+ private
43
+
44
+ def repository_adapter
45
+ @repository_adapter ||= KnapsackPro::RepositoryAdapterInitiator.call
46
+ end
47
+
48
+ def build_action
49
+ KnapsackPro::Client::API::V1::BuildDistributions.last(
50
+ commit_hash: repository_adapter.commit_hash,
51
+ branch: repository_adapter.branch,
52
+ node_total: KnapsackPro::Config::Env.ci_node_total,
53
+ node_index: KnapsackPro::Config::Env.ci_node_index,
54
+ )
55
+ end
56
+ end
57
+ end
@@ -18,6 +18,19 @@ module KnapsackPro
18
18
  }
19
19
  )
20
20
  end
21
+
22
+ def last(args)
23
+ action_class.new(
24
+ endpoint_path: '/v1/build_distributions/last',
25
+ http_method: :get,
26
+ request_hash: {
27
+ :commit_hash => args.fetch(:commit_hash),
28
+ :branch => args.fetch(:branch),
29
+ :node_total => args.fetch(:node_total),
30
+ :node_index => args.fetch(:node_index),
31
+ }
32
+ )
33
+ end
21
34
  end
22
35
  end
23
36
  end