knapsack 0.2.0 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +4 -0
- data/README.md +72 -5
- data/docs/images/logos/knapsack-@2.png +0 -0
- data/docs/images/logos/knapsack-logo-@2.png +0 -0
- data/docs/images/logos/knapsack-logo.png +0 -0
- data/docs/images/logos/knapsack.png +0 -0
- data/knapsack.gemspec +1 -1
- data/lib/knapsack/config.rb +9 -2
- data/lib/knapsack/distributors/base_distributor.rb +0 -6
- data/lib/knapsack/distributors/leftover_distributor.rb +4 -2
- data/lib/knapsack/distributors/report_distributor.rb +9 -8
- data/lib/knapsack/version.rb +1 -1
- data/spec/knapsack/config_spec.rb +10 -0
- metadata +7 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 181f987c696d1bc19a140cf92e482790f7b1c2ce
|
4
|
+
data.tar.gz: 92a9cb85bb6a341ddd9dd572a8324875fd30ef4d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f9b0a1761048c7c9bd0dcd019e871bf98ac7f0551d10c3b9078f6f6d3dad25748a0450576cb5ae5d7d2be5f2748c8d3f71ab32034b289dddf6e7bc6b6b0b9091
|
7
|
+
data.tar.gz: a976683e07452a987816f8036afdaa97db0254268d2cd503f462da0e2fa91c049553a670412d88e2fcc4d4a0f653f11a0d5ae616e8665ea43603beabd76e22a8
|
data/CHANGELOG.md
CHANGED
data/README.md
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
# Knapsack
|
1
|
+
# ![Knapsack logo](docs/images/logos/knapsack-logo-@2.png)
|
2
2
|
|
3
3
|
[![Gem Version](https://badge.fury.io/rb/knapsack.png)][gem_version]
|
4
4
|
[![Build Status](https://travis-ci.org/ArturT/knapsack.svg?branch=master)][travis]
|
@@ -10,7 +10,7 @@
|
|
10
10
|
[codeclimate]: https://codeclimate.com/github/ArturT/knapsack
|
11
11
|
[coverage]: https://codeclimate.com/github/ArturT/knapsack
|
12
12
|
|
13
|
-
Parallel specs across CI server nodes based on each spec file's time execution. It generates spec time execution report and uses it for
|
13
|
+
Parallel specs across CI server nodes based on each spec file's time execution. It generates a spec time execution report and uses it for future test runs.
|
14
14
|
|
15
15
|
Short [presentation](http://slides.com/arturt/knapsack) about gem.
|
16
16
|
|
@@ -62,13 +62,13 @@ Add in your `Rakefile` this lines:
|
|
62
62
|
require 'knapsack'
|
63
63
|
Knapsack.load_tasks
|
64
64
|
|
65
|
-
Generate time execution report for your spec files. Run
|
65
|
+
Generate time execution report for your spec files. Run below command on one of your CI nodes.
|
66
66
|
|
67
67
|
$ KNAPSACK_GENERATE_REPORT=true bundle exec rspec spec
|
68
68
|
|
69
69
|
Commit generated report `knapsack_report.json` into your repository.
|
70
70
|
|
71
|
-
|
71
|
+
This report should be updated only after you add a lot of new slow tests or you change existing ones which causes a big time execution difference between CI nodes. Either way, you will get time offset warning at the end of the rspec results which reminds you when it’s a good time to regenerate the knapsack report.
|
72
72
|
|
73
73
|
## Setup your CI server
|
74
74
|
|
@@ -94,7 +94,9 @@ You can set `KNAPSACK_REPORT_PATH` if your knapsack report was saved in non defa
|
|
94
94
|
|
95
95
|
If you are using circleci.com you can omit `CI_NODE_TOTAL` and `CI_NODE_INDEX`. Knapsack will use `CIRCLE_NODE_TOTAL` and `CIRCLE_NODE_INDEX` provided by CircleCI.
|
96
96
|
|
97
|
-
Here is example for test configuration in your `circleci.yml` file.
|
97
|
+
Here is an example for test configuration in your `circleci.yml` file.
|
98
|
+
|
99
|
+
#### Step 1
|
98
100
|
|
99
101
|
For the first time run all specs on a single CI node with enabled report generator.
|
100
102
|
|
@@ -104,6 +106,8 @@ For the first time run all specs on a single CI node with enabled report generat
|
|
104
106
|
|
105
107
|
After tests pass on your CircleCI machine your should copy knapsack json report which is rendered at the end of rspec results. Save it into your repository as `knapsack_report.json` file and commit.
|
106
108
|
|
109
|
+
#### Step 2
|
110
|
+
|
107
111
|
Now you should update test command and enable parallel. Please remember to add additional containers for your project in CircleCI settings.
|
108
112
|
|
109
113
|
test:
|
@@ -113,6 +117,65 @@ Now you should update test command and enable parallel. Please remember to add a
|
|
113
117
|
|
114
118
|
Now everything should works. You will get warning at the end of rspec results if time execution will take too much.
|
115
119
|
|
120
|
+
### Info for Travis users
|
121
|
+
|
122
|
+
#### Step 1
|
123
|
+
|
124
|
+
For the first time run all specs at once with enabled report generator. Edit `.travis.yml`
|
125
|
+
|
126
|
+
script: "KNAPSACK_GENERATE_REPORT=true bundle exec rspec spec"
|
127
|
+
|
128
|
+
After tests pass your should copy knapsack json report which is rendered at the end of rspec results. Save it into your repository as `knapsack_report.json` file and commit.
|
129
|
+
|
130
|
+
#### Step 2
|
131
|
+
|
132
|
+
You can parallel your builds across virtual machines with [travis matrix feature](http://docs.travis-ci.com/user/speeding-up-the-build/#Parallelizing-your-builds-across-virtual-machines). Edit `.travis.yml`
|
133
|
+
|
134
|
+
script: "bundle exec rake knapsack:rspec"
|
135
|
+
env:
|
136
|
+
- CI_NODE_TOTAL=2 CI_NODE_INDEX=0
|
137
|
+
- CI_NODE_TOTAL=2 CI_NODE_INDEX=1
|
138
|
+
|
139
|
+
If you want to have some global ENVs and matrix of ENVs then do it like this:
|
140
|
+
|
141
|
+
script: "bundle exec rake knapsack:rspec"
|
142
|
+
env:
|
143
|
+
global:
|
144
|
+
- RAILS_ENV=test
|
145
|
+
- MY_GLOBAL_VAR=123
|
146
|
+
matrix:
|
147
|
+
- CI_NODE_TOTAL=2 CI_NODE_INDEX=0
|
148
|
+
- CI_NODE_TOTAL=2 CI_NODE_INDEX=1
|
149
|
+
|
150
|
+
Such configuration will generate matrix with 2 following ENV rows:
|
151
|
+
|
152
|
+
CI_NODE_TOTAL=2 CI_NODE_INDEX=0 RAILS_ENV=test MY_GLOBAL_VAR=123
|
153
|
+
CI_NODE_TOTAL=2 CI_NODE_INDEX=1 RAILS_ENV=test MY_GLOBAL_VAR=123
|
154
|
+
|
155
|
+
More info about global and matrix ENV configuration in [travis docs](http://docs.travis-ci.com/user/build-configuration/#Environment-variables).
|
156
|
+
|
157
|
+
### Info for semaphoreapp.com users
|
158
|
+
|
159
|
+
#### Step 1
|
160
|
+
|
161
|
+
For the first time run all specs at once with enabled report generator. Set up your build command:
|
162
|
+
|
163
|
+
KNAPSACK_GENERATE_REPORT=true bundle exec rspec spec
|
164
|
+
|
165
|
+
After tests pass your should copy knapsack json report which is rendered at the end of rspec results. Save it into your repository as `knapsack_report.json` file and commit.
|
166
|
+
|
167
|
+
#### Step 2
|
168
|
+
|
169
|
+
Knapsack supports semaphoreapp ENVs `SEMAPHORE_THREAD_COUNT` and `SEMAPHORE_CURRENT_THREAD`. The only thing you need to do is set up knapsack rspec command for as many threads as you need. Here is an example:
|
170
|
+
|
171
|
+
# thread 1
|
172
|
+
bundle exec rake knapsack:rspec
|
173
|
+
|
174
|
+
# thread 2
|
175
|
+
bundle exec rake knapsack:rspec
|
176
|
+
|
177
|
+
Tests will be split across threads.
|
178
|
+
|
116
179
|
## Tests
|
117
180
|
|
118
181
|
### Spec
|
@@ -146,3 +209,7 @@ Specs in `spec_examples/leftover` take more than 3 seconds. This should cause a
|
|
146
209
|
3. Commit your changes (`git commit -am 'Add some feature'`)
|
147
210
|
4. Push to the branch (`git push origin my-new-feature`)
|
148
211
|
5. Create a new Pull Request
|
212
|
+
|
213
|
+
## Acknowledgements
|
214
|
+
|
215
|
+
Many thanks to [Małgorzata Nowak](https://github.com/informatykgosia) for beautiful logo.
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
data/knapsack.gemspec
CHANGED
@@ -9,7 +9,7 @@ Gem::Specification.new do |spec|
|
|
9
9
|
spec.authors = ["ArturT"]
|
10
10
|
spec.email = ["arturtrzop@gmail.com"]
|
11
11
|
spec.summary = %q{Parallel specs across CI server nodes based on each spec file's time execution.}
|
12
|
-
spec.description = %q{Parallel specs across CI server nodes based on each spec file's time execution. It generates spec time execution report and uses it for
|
12
|
+
spec.description = %q{Parallel specs across CI server nodes based on each spec file's time execution. It generates a spec time execution report and uses it for future test runs.}
|
13
13
|
spec.homepage = "https://github.com/ArturT/knapsack"
|
14
14
|
spec.license = "MIT"
|
15
15
|
|
data/lib/knapsack/config.rb
CHANGED
@@ -6,11 +6,11 @@ module Knapsack
|
|
6
6
|
end
|
7
7
|
|
8
8
|
def ci_node_total
|
9
|
-
ENV['CI_NODE_TOTAL'] || ENV['CIRCLE_NODE_TOTAL'] || 1
|
9
|
+
ENV['CI_NODE_TOTAL'] || ENV['CIRCLE_NODE_TOTAL'] || ENV['SEMAPHORE_THREAD_COUNT'] || 1
|
10
10
|
end
|
11
11
|
|
12
12
|
def ci_node_index
|
13
|
-
ENV['CI_NODE_INDEX'] || ENV['CIRCLE_NODE_INDEX'] || 0
|
13
|
+
ENV['CI_NODE_INDEX'] || ENV['CIRCLE_NODE_INDEX'] || semaphore_current_thread || 0
|
14
14
|
end
|
15
15
|
|
16
16
|
def spec_pattern
|
@@ -28,6 +28,13 @@ module Knapsack
|
|
28
28
|
def generate_report
|
29
29
|
ENV['KNAPSACK_GENERATE_REPORT'] || false
|
30
30
|
end
|
31
|
+
|
32
|
+
private
|
33
|
+
|
34
|
+
def semaphore_current_thread
|
35
|
+
index = ENV['SEMAPHORE_CURRENT_THREAD']
|
36
|
+
index.to_i - 1 if index
|
37
|
+
end
|
31
38
|
end
|
32
39
|
end
|
33
40
|
end
|
@@ -29,7 +29,6 @@ module Knapsack
|
|
29
29
|
|
30
30
|
def assign_spec_files_to_node
|
31
31
|
default_node_specs
|
32
|
-
@node_index = 0
|
33
32
|
post_assign_spec_files_to_node
|
34
33
|
end
|
35
34
|
|
@@ -60,11 +59,6 @@ module Knapsack
|
|
60
59
|
def default_report
|
61
60
|
Knapsack.report.open
|
62
61
|
end
|
63
|
-
|
64
|
-
def update_node_index
|
65
|
-
@node_index += 1
|
66
|
-
@node_index = 0 if @node_index == ci_node_total
|
67
|
-
end
|
68
62
|
end
|
69
63
|
end
|
70
64
|
end
|
@@ -12,9 +12,11 @@ module Knapsack
|
|
12
12
|
private
|
13
13
|
|
14
14
|
def post_assign_spec_files_to_node
|
15
|
+
node_index = 0
|
15
16
|
leftover_specs.each do |spec_file|
|
16
|
-
node_specs[
|
17
|
-
|
17
|
+
node_specs[node_index] << spec_file
|
18
|
+
node_index += 1
|
19
|
+
node_index %= ci_node_total
|
18
20
|
end
|
19
21
|
end
|
20
22
|
|
@@ -43,20 +43,21 @@ module Knapsack
|
|
43
43
|
|
44
44
|
def assign_slow_spec_files
|
45
45
|
@not_assigned_spec_files = []
|
46
|
-
|
46
|
+
node_index = 0
|
47
47
|
sorted_report_with_existing_specs.each do |spec_file_with_time|
|
48
|
-
assign_slow_spec_file(spec_file_with_time)
|
49
|
-
|
48
|
+
assign_slow_spec_file(node_index, spec_file_with_time)
|
49
|
+
node_index += 1
|
50
|
+
node_index %= ci_node_total
|
50
51
|
end
|
51
52
|
end
|
52
53
|
|
53
|
-
def assign_slow_spec_file(spec_file_with_time)
|
54
|
+
def assign_slow_spec_file(node_index, spec_file_with_time)
|
54
55
|
time = spec_file_with_time[1]
|
55
|
-
time_left = node_specs[
|
56
|
+
time_left = node_specs[node_index][:time_left] - time
|
56
57
|
|
57
|
-
if time_left >= 0 or node_specs[
|
58
|
-
node_specs[
|
59
|
-
node_specs[
|
58
|
+
if time_left >= 0 or node_specs[node_index][:spec_files_with_time].empty?
|
59
|
+
node_specs[node_index][:time_left] -= time
|
60
|
+
node_specs[node_index][:spec_files_with_time] << spec_file_with_time
|
60
61
|
else
|
61
62
|
@not_assigned_spec_files << spec_file_with_time
|
62
63
|
end
|
data/lib/knapsack/version.rb
CHANGED
@@ -26,6 +26,11 @@ describe Knapsack::Config do
|
|
26
26
|
before { stub_const("ENV", { 'CIRCLE_NODE_TOTAL' => 4 }) }
|
27
27
|
it { should eql 4 }
|
28
28
|
end
|
29
|
+
|
30
|
+
context 'when SEMAPHORE_THREAD_COUNT has value' do
|
31
|
+
before { stub_const("ENV", { 'SEMAPHORE_THREAD_COUNT' => 3 }) }
|
32
|
+
it { should eql 3 }
|
33
|
+
end
|
29
34
|
end
|
30
35
|
|
31
36
|
context "when ENV doesn't exist" do
|
@@ -46,6 +51,11 @@ describe Knapsack::Config do
|
|
46
51
|
before { stub_const("ENV", { 'CIRCLE_NODE_INDEX' => 2 }) }
|
47
52
|
it { should eql 2 }
|
48
53
|
end
|
54
|
+
|
55
|
+
context 'when SEMAPHORE_CURRENT_THREAD has value' do
|
56
|
+
before { stub_const("ENV", { 'SEMAPHORE_CURRENT_THREAD' => 1 }) }
|
57
|
+
it { should eql 0 }
|
58
|
+
end
|
49
59
|
end
|
50
60
|
|
51
61
|
context "when ENV doesn't exist" do
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: knapsack
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- ArturT
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-
|
11
|
+
date: 2014-08-15 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -87,7 +87,7 @@ dependencies:
|
|
87
87
|
- !ruby/object:Gem::Version
|
88
88
|
version: '0'
|
89
89
|
description: Parallel specs across CI server nodes based on each spec file's time
|
90
|
-
execution. It generates spec time execution report and uses it for
|
90
|
+
execution. It generates a spec time execution report and uses it for future test
|
91
91
|
runs.
|
92
92
|
email:
|
93
93
|
- arturtrzop@gmail.com
|
@@ -104,6 +104,10 @@ files:
|
|
104
104
|
- README.md
|
105
105
|
- Rakefile
|
106
106
|
- TODO.md
|
107
|
+
- docs/images/logos/knapsack-@2.png
|
108
|
+
- docs/images/logos/knapsack-logo-@2.png
|
109
|
+
- docs/images/logos/knapsack-logo.png
|
110
|
+
- docs/images/logos/knapsack.png
|
107
111
|
- docs/images/with_knapsack.png
|
108
112
|
- docs/images/without_knapsack.png
|
109
113
|
- knapsack.gemspec
|