knapsack 0.1.1 → 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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