knapsack_pro 1.20.0 → 1.22.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +45 -0
- data/README.md +42 -17
- data/lib/knapsack_pro.rb +6 -0
- data/lib/knapsack_pro/adapters/base_adapter.rb +16 -0
- data/lib/knapsack_pro/adapters/rspec_adapter.rb +11 -9
- data/lib/knapsack_pro/allocator.rb +7 -5
- data/lib/knapsack_pro/allocator_builder.rb +2 -1
- data/lib/knapsack_pro/base_allocator_builder.rb +41 -10
- data/lib/knapsack_pro/build_distribution_fetcher.rb +57 -0
- data/lib/knapsack_pro/client/api/v1/build_distributions.rb +13 -0
- data/lib/knapsack_pro/client/connection.rb +33 -15
- data/lib/knapsack_pro/config/env.rb +4 -0
- data/lib/knapsack_pro/formatters/rspec_json_formatter.rb +1 -1
- data/lib/knapsack_pro/queue_allocator.rb +7 -5
- data/lib/knapsack_pro/queue_allocator_builder.rb +2 -1
- data/lib/knapsack_pro/report.rb +1 -1
- data/lib/knapsack_pro/runners/queue/cucumber_runner.rb +10 -1
- data/lib/knapsack_pro/runners/queue/rspec_runner.rb +7 -0
- data/lib/knapsack_pro/runners/rspec_runner.rb +5 -2
- data/lib/knapsack_pro/slow_test_file_determiner.rb +33 -0
- data/lib/knapsack_pro/slow_test_file_finder.rb +27 -0
- data/lib/knapsack_pro/test_case_detectors/rspec_test_example_detector.rb +26 -7
- data/lib/knapsack_pro/test_case_mergers/base_merger.rb +29 -0
- data/lib/knapsack_pro/test_case_mergers/rspec_merger.rb +34 -0
- data/lib/knapsack_pro/test_file_finder.rb +43 -5
- data/lib/knapsack_pro/test_files_with_test_cases_composer.rb +22 -0
- data/lib/knapsack_pro/version.rb +1 -1
- data/spec/knapsack_pro/adapters/base_adapter_spec.rb +55 -0
- data/spec/knapsack_pro/adapters/rspec_adapter_spec.rb +61 -25
- data/spec/knapsack_pro/allocator_builder_spec.rb +7 -3
- data/spec/knapsack_pro/allocator_spec.rb +7 -5
- data/spec/knapsack_pro/base_allocator_builder_spec.rb +79 -27
- data/spec/knapsack_pro/build_distribution_fetcher_spec.rb +89 -0
- data/spec/knapsack_pro/client/api/v1/build_distributions_spec.rb +31 -0
- data/spec/knapsack_pro/client/connection_spec.rb +202 -104
- data/spec/knapsack_pro/config/env_spec.rb +14 -0
- data/spec/knapsack_pro/queue_allocator_builder_spec.rb +7 -3
- data/spec/knapsack_pro/queue_allocator_spec.rb +7 -5
- data/spec/knapsack_pro/report_spec.rb +1 -1
- data/spec/knapsack_pro/runners/queue/cucumber_runner_spec.rb +38 -25
- data/spec/knapsack_pro/runners/rspec_runner_spec.rb +4 -4
- data/spec/knapsack_pro/slow_test_file_determiner_spec.rb +74 -0
- data/spec/knapsack_pro/slow_test_file_finder_spec.rb +43 -0
- data/spec/knapsack_pro/test_case_detectors/rspec_test_example_detector_spec.rb +83 -37
- data/spec/knapsack_pro/test_case_mergers/base_merger_spec.rb +27 -0
- data/spec/knapsack_pro/test_case_mergers/rspec_merger_spec.rb +59 -0
- data/spec/knapsack_pro/test_file_finder_spec.rb +105 -29
- data/spec/knapsack_pro/test_files_with_test_cases_composer_spec.rb +41 -0
- metadata +20 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1ff5e0f88a008abb13c1ca010f4b430be290ecf4e349719cac39611eebc575a4
|
4
|
+
data.tar.gz: 83650913e5d6cd21201ebce5ae48c731d61a0bc27bb37f566fcdc3d96a9b0598
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3b3d2dc24c6592040f559f77f59168502bb949b135406a06f59c836494902412e202a28bc781760e0862f416ccaa2d2c9a246269fee87e9fd3d9120ba803f4ab
|
7
|
+
data.tar.gz: 9d4005922f963d765b494ab2b35642fa3be85787a6deb8b490ed3e1f64e5055d474d4cdae5b1bba4d4668b4c63fd59d9063102baf7036830e53d409ba8cf016a
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,50 @@
|
|
1
1
|
# Change Log
|
2
2
|
|
3
|
+
### 1.22.1
|
4
|
+
|
5
|
+
* 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.
|
6
|
+
|
7
|
+
https://github.com/KnapsackPro/knapsack_pro-ruby/pull/113
|
8
|
+
|
9
|
+
https://github.com/KnapsackPro/knapsack_pro-ruby/compare/v1.22.0...v1.22.1
|
10
|
+
|
11
|
+
### 1.22.0
|
12
|
+
|
13
|
+
* 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
|
14
|
+
* 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.
|
15
|
+
|
16
|
+
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).
|
17
|
+
|
18
|
+
https://github.com/KnapsackPro/knapsack_pro-ruby/pull/112
|
19
|
+
|
20
|
+
https://github.com/KnapsackPro/knapsack_pro-ruby/compare/v1.21.0...v1.22.0
|
21
|
+
|
22
|
+
### 1.21.0
|
23
|
+
|
24
|
+
* Automatically detect slow test files for RSpec and split them by test examples when `KNAPSACK_PRO_RSPEC_SPLIT_BY_TEST_EXAMPLES=true`
|
25
|
+
* Add slow test file pattern `KNAPSACK_PRO_SLOW_TEST_FILE_PATTERN` to define RSpec slow test files that should be split by test examples
|
26
|
+
* Start sending API token in header `KNAPSACK-PRO-TEST-SUITE-TOKEN` instead of a key `test_suite_token` in JSON payload.
|
27
|
+
|
28
|
+
https://github.com/KnapsackPro/knapsack_pro-ruby/pull/106
|
29
|
+
|
30
|
+
https://github.com/KnapsackPro/knapsack_pro-ruby/compare/v1.20.2...v1.21.0
|
31
|
+
|
32
|
+
### 1.20.2
|
33
|
+
|
34
|
+
* 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)
|
35
|
+
|
36
|
+
https://github.com/KnapsackPro/knapsack_pro-ruby/pull/111
|
37
|
+
|
38
|
+
https://github.com/KnapsackPro/knapsack_pro-ruby/compare/v1.20.1...v1.20.2
|
39
|
+
|
40
|
+
### 1.20.1
|
41
|
+
|
42
|
+
* Fix bug in RSpec split by test examples in < RSpec 3.6.0 (related to custom json formatter)
|
43
|
+
|
44
|
+
https://github.com/KnapsackPro/knapsack_pro-ruby/pull/105
|
45
|
+
|
46
|
+
https://github.com/KnapsackPro/knapsack_pro-ruby/compare/v1.20.0...v1.20.1
|
47
|
+
|
3
48
|
### 1.20.0
|
4
49
|
|
5
50
|
* Add support for tests split by test examples to RSpec older than 3.6.0
|
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-
|
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
|
-
|
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.
|
601
602
|
|
602
|
-
|
603
|
-
https://knapsackpro.com/contact
|
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
|
-
|
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
|
-
|
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
|
-
|
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
620
|
|
621
|
-
|
621
|
+
### How to manually define a list of slow test files to be split by test cases
|
622
|
+
|
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
|
-
|
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
|
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
|
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
|
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
|
data/lib/knapsack_pro.rb
CHANGED
@@ -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
|
-
|
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
|
-
@
|
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 :
|
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(
|
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(
|
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(
|
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
|
-
|
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
|
-
|
25
|
-
|
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
|
-
|
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
|
-
|
41
|
+
slow_test_files = get_slow_test_files
|
31
42
|
|
32
|
-
|
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
|
-
|
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
|