knapsack 0.1.1 → 0.1.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 66e29adad8c5ac42ab419a5b37de9741ff51430c
4
- data.tar.gz: 6dd72187cd1fa6edc33f52d2b22ed0322b34e47a
3
+ metadata.gz: b9c0c3f2c4c9ade9a8b93a9285ae2ec1fef1810f
4
+ data.tar.gz: ba827b1b39aa68a0df7052f579d635dc91331700
5
5
  SHA512:
6
- metadata.gz: 88a2e270d5ad38f0df8a4d989125d533ae0c29aee78d364b07cf6991c8053d9e7602710c1b26551acb54a28311351547cfc1c0106de65a6dd73454b4b76ff629
7
- data.tar.gz: d886bee4e155577ee534d37785a1892361813c24cbfdfc70947325df8083e1bd29c23c69387fc52c08cc8aa3d04a6e6cd2da48ccde964cb84ef309ed4c4321ee
6
+ metadata.gz: 210967c7a39fb22ee932848d362b15356173270e62e58cd427fecc9b4d6e732dfee5a4501d4947440d13a134b9a149e38bb160ebf052ef577dfaf24e978a533a
7
+ data.tar.gz: 76ad4ccb462dd2e732add681a6db6274b300866fe4ef58266e812914c768ced59e88bbac60d1cf6f7e92a8c0c69ebbb9635d0ffca3d83dd3e71718b6eb60f225
@@ -12,21 +12,26 @@ addons:
12
12
  before_install:
13
13
  - "echo 'gem: --no-ri --no-rdoc' > ~/.gemrc"
14
14
  script:
15
+ - echo "Run specs for Knapsack gem"
15
16
  - bundle exec rspec spec
16
17
 
17
- # generate knapsack report
18
+ - echo "Generate knapsack report"
18
19
  - KNAPSACK_GENERATE_REPORT=true bundle exec rspec --default-path spec_examples --tag focus
19
20
 
20
- # run specs with enabled time offset warning
21
+ - echo "Run specs with enabled time offset warning"
21
22
  - bundle exec rspec --default-path spec_examples
22
23
 
23
- # run rake task for the first CI node
24
+ - echo "Run rake task for the first CI node"
24
25
  - CI_NODE_TOTAL=2 CI_NODE_INDEX=0 KNAPSACK_SPEC_PATTERN="spec_examples/**/*_spec.rb" bundle exec rake knapsack:rspec
25
- # run rake task for the second CI node
26
+ - echo "Run rake task for the second CI node"
26
27
  - CI_NODE_TOTAL=2 CI_NODE_INDEX=1 KNAPSACK_SPEC_PATTERN="spec_examples/**/*_spec.rb" bundle exec rake knapsack:rspec
27
28
 
28
- # run specs for custom knapsack report path
29
+ - echo "Run specs for custom knapsack report path"
29
30
  - cp knapsack_report.json custom_knapsack_report.json
30
31
  - KNAPSACK_SPEC_PATTERN="spec_examples/**/*_spec.rb" KNAPSACK_REPORT_PATH="custom_knapsack_report.json" bundle exec rake knapsack:rspec
32
+
33
+ - echo "Run specs when spec file was removed and still exists in knapsack report json"
34
+ - rm spec_examples/fast/1_spec.rb
35
+ - KNAPSACK_SPEC_PATTERN="spec_examples/**/*_spec.rb" bundle exec rake knapsack:rspec
31
36
  notifications:
32
37
  email: false
@@ -1,6 +1,11 @@
1
1
  ### unreleased
2
2
 
3
- * nothing yet
3
+ * TODO
4
+
5
+ ### 0.1.2
6
+
7
+ * Fix case when someone removes spec file which exists in knapsack report.
8
+ * Extract config to separate class and fix wrong node time execution on CI.
4
9
 
5
10
  ### 0.1.1
6
11
 
@@ -1,5 +1,6 @@
1
1
  require 'singleton'
2
2
  require_relative 'knapsack/version'
3
+ require_relative 'knapsack/config'
3
4
  require_relative 'knapsack/tracker'
4
5
  require_relative 'knapsack/presenter'
5
6
  require_relative 'knapsack/report'
@@ -1,9 +1,9 @@
1
1
  module Knapsack
2
2
  class Allocator
3
3
  def initialize(args={})
4
- @config = default_args.merge(args)
5
- @report_distributor = Knapsack::Distributors::ReportDistributor.new(@config)
6
- @leftover_distributor = Knapsack::Distributors::LeftoverDistributor.new(@config)
4
+ @spec_pattern = args[:spec_pattern] || Config.spec_pattern
5
+ @report_distributor = Knapsack::Distributors::ReportDistributor.new(args)
6
+ @leftover_distributor = Knapsack::Distributors::LeftoverDistributor.new(args)
7
7
  end
8
8
 
9
9
  def report_node_specs
@@ -22,44 +22,8 @@ module Knapsack
22
22
  node_specs.join(' ')
23
23
  end
24
24
 
25
- def custom_spec_dir
26
- return unless @config[:spec_pattern]
27
- @config[:spec_pattern].gsub(/^(.*?)\//).first
28
- end
29
-
30
- private
31
-
32
- def default_args
33
- {
34
- ci_node_total: env_ci_node_total,
35
- ci_node_index: env_ci_node_index,
36
- spec_pattern: env_spec_pattern,
37
- report: report
38
- }
39
- end
40
-
41
- def env_ci_node_total
42
- ENV['CI_NODE_TOTAL'] || ENV['CIRCLE_NODE_TOTAL']
43
- end
44
-
45
- def env_ci_node_index
46
- ENV['CI_NODE_INDEX'] || ENV['CIRCLE_NODE_INDEX']
47
- end
48
-
49
- def env_spec_pattern
50
- ENV['KNAPSACK_SPEC_PATTERN']
51
- end
52
-
53
- def env_report_path
54
- ENV['KNAPSACK_REPORT_PATH']
55
- end
56
-
57
- def report
58
- return unless env_report_path
59
- Knapsack.report.config({
60
- report_path: env_report_path
61
- })
62
- Knapsack.report.open
25
+ def spec_dir
26
+ @spec_pattern.gsub(/^(.*?)\//).first
63
27
  end
64
28
  end
65
29
  end
@@ -0,0 +1,33 @@
1
+ module Knapsack
2
+ class Config
3
+ class << self
4
+ def report_path
5
+ ENV['KNAPSACK_REPORT_PATH'] || 'knapsack_report.json'
6
+ end
7
+
8
+ def ci_node_total
9
+ ENV['CI_NODE_TOTAL'] || ENV['CIRCLE_NODE_TOTAL'] || 1
10
+ end
11
+
12
+ def ci_node_index
13
+ ENV['CI_NODE_INDEX'] || ENV['CIRCLE_NODE_INDEX'] || 0
14
+ end
15
+
16
+ def spec_pattern
17
+ ENV['KNAPSACK_SPEC_PATTERN'] || 'spec/**/*_spec.rb'
18
+ end
19
+
20
+ def enable_time_offset_warning
21
+ true
22
+ end
23
+
24
+ def time_offset_in_seconds
25
+ 30
26
+ end
27
+
28
+ def generate_report
29
+ ENV['KNAPSACK_GENERATE_REPORT'] || false
30
+ end
31
+ end
32
+ end
33
+ end
@@ -1,20 +1,13 @@
1
1
  module Knapsack
2
2
  module Distributors
3
3
  class BaseDistributor
4
- attr_reader :report, :node_specs
5
-
6
- DEFAULT_CI_NODE_TOTAL = 1
7
- DEFAULT_CI_NODE_INDEX = 0
4
+ attr_reader :report, :node_specs, :spec_pattern
8
5
 
9
6
  def initialize(args={})
10
7
  @report = args[:report] || default_report
11
- @ci_node_total = args[:ci_node_total] || DEFAULT_CI_NODE_TOTAL
12
- @ci_node_index = args[:ci_node_index] || DEFAULT_CI_NODE_INDEX
13
- post_initialize(args)
14
- end
15
-
16
- def default_report
17
- Knapsack.report.open
8
+ @ci_node_total = args[:ci_node_total] || config.ci_node_total
9
+ @ci_node_index = args[:ci_node_index] || config.ci_node_index
10
+ @spec_pattern = args[:spec_pattern] || config.spec_pattern
18
11
  end
19
12
 
20
13
  def ci_node_total
@@ -40,12 +33,12 @@ module Knapsack
40
33
  post_assign_spec_files_to_node
41
34
  end
42
35
 
43
- protected
44
-
45
- def post_initialize(args)
46
- nil
36
+ def all_specs
37
+ @all_specs ||= Dir[spec_pattern]
47
38
  end
48
39
 
40
+ protected
41
+
49
42
  def post_specs_for_node(node_index)
50
43
  raise NotImplementedError
51
44
  end
@@ -58,6 +51,16 @@ module Knapsack
58
51
  raise NotImplementedError
59
52
  end
60
53
 
54
+ private
55
+
56
+ def config
57
+ Knapsack::Config
58
+ end
59
+
60
+ def default_report
61
+ Knapsack.report.open
62
+ end
63
+
61
64
  def update_node_index
62
65
  @node_index += 1
63
66
  @node_index = 0 if @node_index == ci_node_total
@@ -1,14 +1,8 @@
1
1
  module Knapsack
2
2
  module Distributors
3
3
  class LeftoverDistributor < BaseDistributor
4
- attr_reader :spec_pattern
5
-
6
4
  def report_specs
7
- @report_specs ||= @report.keys
8
- end
9
-
10
- def all_specs
11
- @all_specs ||= Dir[spec_pattern]
5
+ @report_specs ||= report.keys
12
6
  end
13
7
 
14
8
  def leftover_specs
@@ -17,14 +11,6 @@ module Knapsack
17
11
 
18
12
  private
19
13
 
20
- def post_initialize(args={})
21
- @spec_pattern = args[:spec_pattern] || default_spec_pattern
22
- end
23
-
24
- def default_spec_pattern
25
- 'spec/**/*_spec.rb'
26
- end
27
-
28
14
  def post_assign_spec_files_to_node
29
15
  leftover_specs.each do |spec_file|
30
16
  node_specs[@node_index] << spec_file
@@ -2,11 +2,15 @@ module Knapsack
2
2
  module Distributors
3
3
  class ReportDistributor < BaseDistributor
4
4
  def sorted_report
5
- @sorted_report ||= report.sort_by{|k,v| v}.reverse
5
+ @sorted_report ||= report.sort_by { |spec_path, time| time }.reverse
6
+ end
7
+
8
+ def sorted_report_with_existing_specs
9
+ @sorted_report_with_existing_specs ||= sorted_report.select { |spec_path, time| all_specs.include?(spec_path) }
6
10
  end
7
11
 
8
12
  def total_time_execution
9
- @total_time_execution ||= report.values.reduce(0, :+).to_f
13
+ @total_time_execution ||= sorted_report_with_existing_specs.map(&:last).reduce(0, :+).to_f
10
14
  end
11
15
 
12
16
  def node_time_execution
@@ -40,7 +44,7 @@ module Knapsack
40
44
  def assign_slow_spec_files
41
45
  @not_assigned_spec_files = []
42
46
  @node_index = 0
43
- sorted_report.each do |spec_file_with_time|
47
+ sorted_report_with_existing_specs.each do |spec_file_with_time|
44
48
  assign_slow_spec_file(spec_file_with_time)
45
49
  update_node_index
46
50
  end
@@ -24,7 +24,7 @@ module Knapsack
24
24
 
25
25
  def default_config
26
26
  {
27
- report_path: 'knapsack_report.json'
27
+ report_path: Config.report_path
28
28
  }
29
29
  end
30
30
 
@@ -50,16 +50,12 @@ module Knapsack
50
50
 
51
51
  def default_config
52
52
  {
53
- enable_time_offset_warning: true,
54
- time_offset_in_seconds: 30,
55
- generate_report: generate_report
53
+ enable_time_offset_warning: Config.enable_time_offset_warning,
54
+ time_offset_in_seconds: Config.time_offset_in_seconds,
55
+ generate_report: Config.generate_report
56
56
  }
57
57
  end
58
58
 
59
- def generate_report
60
- ENV['KNAPSACK_GENERATE_REPORT'] || false
61
- end
62
-
63
59
  def set_defaults
64
60
  @global_time = 0
65
61
  @spec_files_with_time = {}
@@ -1,3 +1,3 @@
1
1
  module Knapsack
2
- VERSION = "0.1.1"
2
+ VERSION = '0.1.2'
3
3
  end
@@ -12,9 +12,7 @@ namespace :knapsack do
12
12
  puts allocator.leftover_node_specs
13
13
  puts
14
14
 
15
- custom_spec_dir = allocator.custom_spec_dir
16
- default_path = custom_spec_dir ? "--default-path #{custom_spec_dir}" : nil
17
- cmd = %Q[bundle exec rspec #{default_path} -- #{allocator.stringify_node_specs}]
15
+ cmd = %Q[bundle exec rspec --default-path #{allocator.spec_dir} -- #{allocator.stringify_node_specs}]
18
16
 
19
17
  exec(cmd)
20
18
  end
@@ -42,16 +42,16 @@ describe Knapsack::Allocator do
42
42
  it { should eql node_specs.join(' ') }
43
43
  end
44
44
 
45
- describe '#custom_spec_dir' do
46
- subject { allocator.custom_spec_dir }
45
+ describe '#spec_dir' do
46
+ subject { allocator.spec_dir }
47
47
 
48
48
  context 'when spec pattern exists' do
49
- let(:spec_pattern) { "custom_spec_dir/**/*_spec.rb" }
50
- it { should eql 'custom_spec_dir/' }
49
+ let(:spec_pattern) { "spec_dir/**/*_spec.rb" }
50
+ it { should eql 'spec_dir/' }
51
51
  end
52
52
 
53
53
  context "when spec pattern doesn't exist" do
54
- it { should be_nil }
54
+ it { should eql 'spec/' }
55
55
  end
56
56
  end
57
57
  end
@@ -0,0 +1,92 @@
1
+ describe Knapsack::Config do
2
+ describe '.report_path' do
3
+ subject { described_class.report_path }
4
+
5
+ context 'when ENV exists' do
6
+ let(:report_path) { 'custom_knapsack_report.json' }
7
+ before { stub_const("ENV", { 'KNAPSACK_REPORT_PATH' => report_path }) }
8
+ it { should eql report_path }
9
+ end
10
+
11
+ context "when ENV doesn't exist" do
12
+ it { should eql 'knapsack_report.json' }
13
+ end
14
+ end
15
+
16
+ describe '.ci_node_total' do
17
+ subject { described_class.ci_node_total }
18
+
19
+ context 'when ENV exists' do
20
+ context 'when CI_NODE_TOTAL has value' do
21
+ before { stub_const("ENV", { 'CI_NODE_TOTAL' => 5 }) }
22
+ it { should eql 5 }
23
+ end
24
+
25
+ context 'when CIRCLE_NODE_TOTAL has value' do
26
+ before { stub_const("ENV", { 'CIRCLE_NODE_TOTAL' => 4 }) }
27
+ it { should eql 4 }
28
+ end
29
+ end
30
+
31
+ context "when ENV doesn't exist" do
32
+ it { should eql 1 }
33
+ end
34
+ end
35
+
36
+ describe '.ci_node_index' do
37
+ subject { described_class.ci_node_index }
38
+
39
+ context 'when ENV exists' do
40
+ context 'when CI_NODE_INDEX has value' do
41
+ before { stub_const("ENV", { 'CI_NODE_INDEX' => 3 }) }
42
+ it { should eql 3 }
43
+ end
44
+
45
+ context 'when CIRCLE_NODE_INDEX has value' do
46
+ before { stub_const("ENV", { 'CIRCLE_NODE_INDEX' => 2 }) }
47
+ it { should eql 2 }
48
+ end
49
+ end
50
+
51
+ context "when ENV doesn't exist" do
52
+ it { should eql 0 }
53
+ end
54
+ end
55
+
56
+ describe '.spec_pattern' do
57
+ subject { described_class.spec_pattern }
58
+
59
+ context 'when ENV exists' do
60
+ let(:spec_pattern) { 'custom_spec/**/*_spec.rb' }
61
+ before { stub_const("ENV", { 'KNAPSACK_SPEC_PATTERN' => spec_pattern }) }
62
+ it { should eql spec_pattern }
63
+ end
64
+
65
+ context "when ENV doesn't exist" do
66
+ it { should eql 'spec/**/*_spec.rb' }
67
+ end
68
+ end
69
+
70
+ describe '.enable_time_offset_warning' do
71
+ subject { described_class.enable_time_offset_warning }
72
+ it { should be true }
73
+ end
74
+
75
+ describe '.time_offset_in_seconds' do
76
+ subject { described_class.time_offset_in_seconds }
77
+ it { should eql 30 }
78
+ end
79
+
80
+ describe '.generate_report' do
81
+ subject { described_class.generate_report }
82
+
83
+ context 'when ENV exists' do
84
+ before { stub_const("ENV", { 'KNAPSACK_GENERATE_REPORT' => true }) }
85
+ it { should be true }
86
+ end
87
+
88
+ context "when ENV doesn't exist" do
89
+ it { should be false }
90
+ end
91
+ end
92
+ end
@@ -27,12 +27,44 @@ describe Knapsack::Distributors::ReportDistributor do
27
27
 
28
28
  it do
29
29
  should eql([
30
- ["f_spec.rb", 3.5],
31
- ["e_spec.rb", 3.0],
32
- ["d_spec.rb", 2.5],
33
- ["c_spec.rb", 2.0],
34
- ["b_spec.rb", 1.5],
35
- ["a_spec.rb", 1.0],
30
+ ['f_spec.rb', 3.5],
31
+ ['e_spec.rb', 3.0],
32
+ ['d_spec.rb', 2.5],
33
+ ['c_spec.rb', 2.0],
34
+ ['b_spec.rb', 1.5],
35
+ ['a_spec.rb', 1.0],
36
+ ])
37
+ end
38
+ end
39
+
40
+ describe '#sorted_report_with_existing_specs' do
41
+ subject { distributor.sorted_report_with_existing_specs }
42
+
43
+ before do
44
+ expect(distributor).to receive(:all_specs).exactly(6).times.and_return([
45
+ 'b_spec.rb',
46
+ 'd_spec.rb',
47
+ 'f_spec.rb',
48
+ ])
49
+ end
50
+
51
+ let(:report) do
52
+ {
53
+ 'e_spec.rb' => 3.0,
54
+ 'f_spec.rb' => 3.5,
55
+ 'c_spec.rb' => 2.0,
56
+ 'd_spec.rb' => 2.5,
57
+ 'a_spec.rb' => 1.0,
58
+ 'b_spec.rb' => 1.5,
59
+ }
60
+ end
61
+ let(:args) { { report: report } }
62
+
63
+ it do
64
+ should eql([
65
+ ['f_spec.rb', 3.5],
66
+ ['d_spec.rb', 2.5],
67
+ ['b_spec.rb', 1.5],
36
68
  ])
37
69
  end
38
70
  end
@@ -47,6 +79,10 @@ describe Knapsack::Distributors::ReportDistributor do
47
79
  end
48
80
  let(:args) { { report: report } }
49
81
 
82
+ before do
83
+ allow(distributor).to receive(:all_specs).and_return(report.keys)
84
+ end
85
+
50
86
  describe '#total_time_execution' do
51
87
  subject { distributor.total_time_execution }
52
88
 
@@ -93,6 +129,10 @@ describe Knapsack::Distributors::ReportDistributor do
93
129
  }
94
130
  end
95
131
 
132
+ before do
133
+ allow(distributor).to receive(:all_specs).and_return(report.keys)
134
+ end
135
+
96
136
  describe '#assign_spec_files_to_node' do
97
137
  before { distributor.assign_spec_files_to_node }
98
138
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: knapsack
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.1.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - ArturT
@@ -110,6 +110,7 @@ files:
110
110
  - lib/knapsack/adapters/base_adapter.rb
111
111
  - lib/knapsack/adapters/rspec_adapter.rb
112
112
  - lib/knapsack/allocator.rb
113
+ - lib/knapsack/config.rb
113
114
  - lib/knapsack/distributors/base_distributor.rb
114
115
  - lib/knapsack/distributors/leftover_distributor.rb
115
116
  - lib/knapsack/distributors/report_distributor.rb
@@ -122,6 +123,7 @@ files:
122
123
  - spec/knapsack/adapters/base_adapter_spec.rb
123
124
  - spec/knapsack/adapters/rspec_adapter_spec.rb
124
125
  - spec/knapsack/allocator_spec.rb
126
+ - spec/knapsack/config_spec.rb
125
127
  - spec/knapsack/distributors/base_distributor_spec.rb
126
128
  - spec/knapsack/distributors/leftover_distributor_spec.rb
127
129
  - spec/knapsack/distributors/report_distributor_spec.rb
@@ -173,6 +175,7 @@ test_files:
173
175
  - spec/knapsack/adapters/base_adapter_spec.rb
174
176
  - spec/knapsack/adapters/rspec_adapter_spec.rb
175
177
  - spec/knapsack/allocator_spec.rb
178
+ - spec/knapsack/config_spec.rb
176
179
  - spec/knapsack/distributors/base_distributor_spec.rb
177
180
  - spec/knapsack/distributors/leftover_distributor_spec.rb
178
181
  - spec/knapsack/distributors/report_distributor_spec.rb