knapsack_pro 5.1.1 → 5.2.0

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
  SHA256:
3
- metadata.gz: 58063b1846ea84151755a05ad9f4cca8297246b78ff0c47d140576cb0d32e19c
4
- data.tar.gz: bf36f5e4232ae62eb835dea8f6aeb0d767f5bef88e7aabf7fea2508c8017068a
3
+ metadata.gz: f00531028caf0501edea4bf33df1bd81fe7ec9fbc888875797289f488e51851e
4
+ data.tar.gz: dbe2e29cdb257ef772348653e40bcccc0ae4d70e8fc0fdd72fd26193784a60b7
5
5
  SHA512:
6
- metadata.gz: 756a63cd54c3e35e60cd09ba057c026d5ab279dab5bdd295bccfb49c6f235f68835e956171a19d9a8c5ca21db46de204e22867c879dae331fe482ffefe906189
7
- data.tar.gz: 54e7d11084f8eab1ace9e225f0a1455dd9b391f33742cafa475b2ce144024f8509d7afcb0915f663784f0ead5407b7accee33d90acb19c44a6ab845c8507e0b5
6
+ metadata.gz: 8ac1af3bf5eff25233ddb17294c56d9de6c9ec0d94c6412182a69ce2f4c04082eb705b0f204e42a342486c2001862171503d6726012421b336fe25c851e103c8
7
+ data.tar.gz: 52d4b68c5793defaf162659597d63afa7461964c78e6b78385ffe21af5cdf529124a15c9d5d96f2ca7216e175daa8b9aa6d2b04698e23c59b2a71b6603b13318
@@ -0,0 +1,11 @@
1
+ # To get started with Dependabot version updates, you'll need to specify which
2
+ # package ecosystems to update and where the package manifests are located.
3
+ # Please see the documentation for all configuration options:
4
+ # https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates
5
+
6
+ version: 2
7
+ updates:
8
+ - package-ecosystem: "bundler"
9
+ directory: "/"
10
+ schedule:
11
+ interval: "weekly"
data/CHANGELOG.md CHANGED
@@ -1,5 +1,21 @@
1
1
  # Changelog
2
2
 
3
+ ### 5.2.0
4
+
5
+ * Send authors to the API
6
+
7
+ https://github.com/KnapsackPro/knapsack_pro-ruby/pull/208
8
+
9
+ https://github.com/KnapsackPro/knapsack_pro-ruby/compare/v5.1.2...v5.2.0
10
+
11
+ ### 5.1.2
12
+
13
+ * Fix broken RSpec split by test examples feature when `SPEC_OPTS` is set in Queue Mode. Ignore `SPEC_OPTS` when generating test examples report for slow test files.
14
+
15
+ https://github.com/KnapsackPro/knapsack_pro-ruby/pull/191
16
+
17
+ https://github.com/KnapsackPro/knapsack_pro-ruby/compare/v5.1.1...v5.1.2
18
+
3
19
  ### 5.1.1
4
20
 
5
21
  * Use `KNAPSACK_PRO_FIXED_QUEUE_SPLIT=true` as default value in Queue Mode for GitLab CI
@@ -16,6 +16,8 @@ module KnapsackPro
16
16
  :node_index => args.fetch(:node_index),
17
17
  :ci_build_id => KnapsackPro::Config::Env.ci_node_build_id,
18
18
  :user_seat => KnapsackPro::Config::Env.masked_user_seat,
19
+ :build_author => KnapsackPro::RepositoryAdapters::GitAdapter.new.build_author,
20
+ :commit_authors => KnapsackPro::RepositoryAdapters::GitAdapter.new.commit_authors,
19
21
  }
20
22
 
21
23
  unless request_hash[:cache_read_attempt]
@@ -17,6 +17,8 @@ module KnapsackPro
17
17
  :node_index => args.fetch(:node_index),
18
18
  :node_build_id => KnapsackPro::Config::Env.ci_node_build_id,
19
19
  :user_seat => KnapsackPro::Config::Env.masked_user_seat,
20
+ :build_author => KnapsackPro::RepositoryAdapters::GitAdapter.new.build_author,
21
+ :commit_authors => KnapsackPro::RepositoryAdapters::GitAdapter.new.commit_authors,
20
22
  }
21
23
 
22
24
  if request_hash[:can_initialize_queue] && !request_hash[:attempt_connect_to_queue]
@@ -67,7 +67,7 @@ module KnapsackPro
67
67
  def masked_user_seat
68
68
  return unless user_seat
69
69
 
70
- user_seat.gsub(/(?<=\w{2})[a-zA-Z]/, "*")
70
+ KnapsackPro::MaskString.call(user_seat)
71
71
  end
72
72
 
73
73
  def test_file_pattern
@@ -0,0 +1,7 @@
1
+ module KnapsackPro
2
+ class MaskString
3
+ def self.call(string)
4
+ string.gsub(/(?<=\w{2})[a-zA-Z]/, "*")
5
+ end
6
+ end
7
+ end
@@ -14,8 +14,40 @@ module KnapsackPro
14
14
  str_branches.split("\n")
15
15
  end
16
16
 
17
+ def commit_authors
18
+ authors = git_commit_authors
19
+ .split("\n")
20
+ .map { |line| line.strip }
21
+ .map { |line| line.split("\t") }
22
+ .map do |commits, author|
23
+ { commits: commits.to_i, author: KnapsackPro::MaskString.call(author) }
24
+ end
25
+
26
+ raise if authors.empty?
27
+
28
+ authors
29
+ rescue Exception
30
+ []
31
+ end
32
+
33
+ def build_author
34
+ author = KnapsackPro::MaskString.call(git_build_author.strip)
35
+ raise if author.empty?
36
+ author
37
+ rescue Exception
38
+ "no git <no.git@example.com>"
39
+ end
40
+
17
41
  private
18
42
 
43
+ def git_commit_authors
44
+ `git fetch --shallow-since "1 month ago" >/dev/null 2>&1 && git shortlog --summary --email --since "one month ago"`
45
+ end
46
+
47
+ def git_build_author
48
+ `git log --format="%aN <%aE>" -1`
49
+ end
50
+
19
51
  def working_dir
20
52
  dir = KnapsackPro::Config::Env.project_dir
21
53
  File.expand_path(dir)
@@ -87,6 +87,7 @@ module KnapsackPro
87
87
  all_test_file_paths += test_file_paths
88
88
  cli_args = args + test_file_paths
89
89
 
90
+ ensure_spec_opts_have_rspec_queue_summary_formatter
90
91
  options = ::RSpec::Core::ConfigurationOptions.new(cli_args)
91
92
  rspec_runner = ::RSpec::Core::Runner.new(options)
92
93
 
@@ -113,6 +114,15 @@ module KnapsackPro
113
114
  end
114
115
  end
115
116
 
117
+ def self.ensure_spec_opts_have_rspec_queue_summary_formatter
118
+ spec_opts = ENV['SPEC_OPTS']
119
+
120
+ return unless spec_opts
121
+ return if spec_opts.include?(KnapsackPro::Formatters::RSpecQueueSummaryFormatter.to_s)
122
+
123
+ ENV['SPEC_OPTS'] = "#{spec_opts} --format #{KnapsackPro::Formatters::RSpecQueueSummaryFormatter.to_s}"
124
+ end
125
+
116
126
  private
117
127
 
118
128
  def self.adapter_class
@@ -1,3 +1,3 @@
1
1
  module KnapsackPro
2
- VERSION = '5.1.1'
2
+ VERSION = '5.2.0'
3
3
  end
data/lib/knapsack_pro.rb CHANGED
@@ -55,6 +55,7 @@ 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/mask_string'
58
59
  require_relative 'knapsack_pro/test_case_mergers/base_merger'
59
60
  require_relative 'knapsack_pro/test_case_mergers/rspec_merger'
60
61
  require_relative 'knapsack_pro/build_distribution_fetcher'
data/lib/tasks/rspec.rake CHANGED
@@ -7,6 +7,9 @@ namespace :knapsack_pro do
7
7
 
8
8
  desc "Generate JSON report for test suite based on default test pattern or based on defined pattern with ENV vars"
9
9
  task :rspec_test_example_detector do
10
+ # ignore the `SPEC_OPTS` options to not affect RSpec execution within this rake task
11
+ ENV.delete('SPEC_OPTS')
12
+
10
13
  detector = KnapsackPro::TestCaseDetectors::RSpecTestExampleDetector.new
11
14
  detector.generate_json_report
12
15
  end
@@ -8,6 +8,7 @@ describe KnapsackPro::Client::API::V1::BuildDistributions do
8
8
  let(:ci_build_id) { double }
9
9
  let(:masked_user_seat) { double }
10
10
  let(:test_files) { double }
11
+ let(:cache_read_attempt) { [false, true].sample }
11
12
 
12
13
  subject do
13
14
  described_class.subset(
@@ -31,20 +32,9 @@ describe KnapsackPro::Client::API::V1::BuildDistributions do
31
32
 
32
33
  it 'does not send test_files among other params' do
33
34
  action = double
34
- expect(KnapsackPro::Client::API::Action).to receive(:new).with({
35
- endpoint_path: '/v1/build_distributions/subset',
36
- http_method: :post,
37
- request_hash: {
38
- fixed_test_suite_split: fixed_test_suite_split,
39
- cache_read_attempt: cache_read_attempt,
40
- commit_hash: commit_hash,
41
- branch: branch,
42
- node_total: node_total,
43
- node_index: node_index,
44
- ci_build_id: ci_build_id,
45
- user_seat: masked_user_seat,
46
- }
47
- }).and_return(action)
35
+ expect(KnapsackPro::Client::API::Action).to receive(:new).with(
36
+ hash_including(request_hash: hash_excluding(:test_files))
37
+ ).and_return(action)
48
38
  expect(subject).to eq action
49
39
  end
50
40
  end
@@ -54,24 +44,22 @@ describe KnapsackPro::Client::API::V1::BuildDistributions do
54
44
 
55
45
  it 'sends test_files among other params' do
56
46
  action = double
57
- expect(KnapsackPro::Client::API::Action).to receive(:new).with({
58
- endpoint_path: '/v1/build_distributions/subset',
59
- http_method: :post,
60
- request_hash: {
61
- fixed_test_suite_split: fixed_test_suite_split,
62
- cache_read_attempt: cache_read_attempt,
63
- commit_hash: commit_hash,
64
- branch: branch,
65
- node_total: node_total,
66
- node_index: node_index,
67
- ci_build_id: ci_build_id,
68
- user_seat: masked_user_seat,
69
- test_files: test_files
70
- }
71
- }).and_return(action)
47
+ expect(KnapsackPro::Client::API::Action).to receive(:new).with(
48
+ hash_including(request_hash: hash_including(test_files: test_files))
49
+ ).and_return(action)
72
50
  expect(subject).to eq action
73
51
  end
74
52
  end
53
+
54
+ it "sends authors" do
55
+ action = double
56
+
57
+ expect(KnapsackPro::Client::API::Action).to receive(:new).with(
58
+ hash_including(request_hash: hash_including(:build_author, :commit_authors))
59
+ ).and_return(action)
60
+
61
+ expect(subject).to eq action
62
+ end
75
63
  end
76
64
 
77
65
  describe '.last' do
@@ -8,6 +8,8 @@ describe KnapsackPro::Client::API::V1::Queues do
8
8
  let(:test_files) { double }
9
9
  let(:node_build_id) { double }
10
10
  let(:masked_user_seat) { double }
11
+ let(:can_initialize_queue) { [false, true].sample }
12
+ let(:attempt_connect_to_queue) { [false, true].sample }
11
13
 
12
14
  subject do
13
15
  described_class.queue(
@@ -33,21 +35,9 @@ describe KnapsackPro::Client::API::V1::Queues do
33
35
 
34
36
  it 'does not send test_files among other params' do
35
37
  action = double
36
- expect(KnapsackPro::Client::API::Action).to receive(:new).with({
37
- endpoint_path: '/v1/queues/queue',
38
- http_method: :post,
39
- request_hash: {
40
- fixed_queue_split: fixed_queue_split,
41
- can_initialize_queue: can_initialize_queue,
42
- attempt_connect_to_queue: attempt_connect_to_queue,
43
- commit_hash: commit_hash,
44
- branch: branch,
45
- node_total: node_total,
46
- node_index: node_index,
47
- node_build_id: node_build_id,
48
- user_seat: masked_user_seat,
49
- }
50
- }).and_return(action)
38
+ expect(KnapsackPro::Client::API::Action).to receive(:new).with(
39
+ hash_including(request_hash: hash_excluding(:test_files))
40
+ ).and_return(action)
51
41
  expect(subject).to eq action
52
42
  end
53
43
  end
@@ -58,22 +48,9 @@ describe KnapsackPro::Client::API::V1::Queues do
58
48
 
59
49
  it 'sends test_files among other params' do
60
50
  action = double
61
- expect(KnapsackPro::Client::API::Action).to receive(:new).with({
62
- endpoint_path: '/v1/queues/queue',
63
- http_method: :post,
64
- request_hash: {
65
- fixed_queue_split: fixed_queue_split,
66
- can_initialize_queue: can_initialize_queue,
67
- attempt_connect_to_queue: attempt_connect_to_queue,
68
- commit_hash: commit_hash,
69
- branch: branch,
70
- node_total: node_total,
71
- node_index: node_index,
72
- node_build_id: node_build_id,
73
- user_seat: masked_user_seat,
74
- test_files: test_files
75
- }
76
- }).and_return(action)
51
+ expect(KnapsackPro::Client::API::Action).to receive(:new).with(
52
+ hash_including(request_hash: hash_including(test_files: test_files))
53
+ ).and_return(action)
77
54
  expect(subject).to eq action
78
55
  end
79
56
  end
@@ -84,23 +61,21 @@ describe KnapsackPro::Client::API::V1::Queues do
84
61
 
85
62
  it 'does not send test_files among other params' do
86
63
  action = double
87
- expect(KnapsackPro::Client::API::Action).to receive(:new).with({
88
- endpoint_path: '/v1/queues/queue',
89
- http_method: :post,
90
- request_hash: {
91
- fixed_queue_split: fixed_queue_split,
92
- can_initialize_queue: can_initialize_queue,
93
- attempt_connect_to_queue: attempt_connect_to_queue,
94
- commit_hash: commit_hash,
95
- branch: branch,
96
- node_total: node_total,
97
- node_index: node_index,
98
- node_build_id: node_build_id,
99
- user_seat: masked_user_seat,
100
- }
101
- }).and_return(action)
64
+ expect(KnapsackPro::Client::API::Action).to receive(:new).with(
65
+ hash_including(request_hash: hash_excluding(:test_files))
66
+ ).and_return(action)
102
67
  expect(subject).to eq action
103
68
  end
104
69
  end
70
+
71
+ it "sends authors" do
72
+ action = double
73
+
74
+ expect(KnapsackPro::Client::API::Action).to receive(:new).with(
75
+ hash_including(request_hash: hash_including(:build_author, :commit_authors))
76
+ ).and_return(action)
77
+
78
+ expect(subject).to eq action
79
+ end
105
80
  end
106
81
  end
@@ -31,4 +31,76 @@ describe KnapsackPro::RepositoryAdapters::GitAdapter do
31
31
  it { expect(subject.include?('master')).to be true }
32
32
  it { expect(subject.include?(circle_branch)).to be true } if ENV['CIRCLECI']
33
33
  end
34
+
35
+ describe '#build_author' do
36
+ it "returns the masked build author" do
37
+ allow_any_instance_of(KnapsackPro::RepositoryAdapters::GitAdapter).to receive(:git_build_author).and_return(
38
+ "John Doe <john.doe@example.com>" + "\n"
39
+ )
40
+
41
+ subject = KnapsackPro::RepositoryAdapters::GitAdapter.new
42
+
43
+ expect(subject.build_author).to eq 'Jo** Do* <jo**.do*@ex*****.co*>'
44
+ end
45
+
46
+ context "when the command raises an exception" do
47
+ it "returns the no-git author" do
48
+ allow_any_instance_of(KnapsackPro::RepositoryAdapters::GitAdapter).to receive(:git_build_author).and_raise(Exception)
49
+
50
+ subject = KnapsackPro::RepositoryAdapters::GitAdapter.new
51
+
52
+ expect(subject.build_author).to eq "no git <no.git@example.com>"
53
+ end
54
+ end
55
+
56
+ context "when the command returns an empty string" do
57
+ it "returns the no-git author" do
58
+ allow_any_instance_of(KnapsackPro::RepositoryAdapters::GitAdapter).to receive(:git_build_author).and_return("")
59
+
60
+ subject = KnapsackPro::RepositoryAdapters::GitAdapter.new
61
+
62
+ expect(subject.build_author).to eq "no git <no.git@example.com>"
63
+ end
64
+ end
65
+ end
66
+
67
+ describe '#commit_authors' do
68
+ it "returns the masked commit authors" do
69
+ allow_any_instance_of(KnapsackPro::RepositoryAdapters::GitAdapter).to receive(:git_commit_authors).and_return([
70
+ " 5\t3v0k4 <riccardo@example.com>\n",
71
+ " 10\tArtur Nowak <artur@example.com>\n",
72
+ " 2\tRiccardo <riccardo@example.com>\n",
73
+ " 3 \tshadre <shadi@example.com>\n",
74
+ ].join(""))
75
+
76
+ subject = KnapsackPro::RepositoryAdapters::GitAdapter.new
77
+
78
+ expect(subject.commit_authors).to eq([
79
+ { commits: 5, author: "3v0*4 <ri******@ex*****.co*>" },
80
+ { commits: 10, author: "Ar*** No*** <ar***@ex*****.co*>" },
81
+ { commits: 2, author: "Ri****** <ri******@ex*****.co*>" },
82
+ { commits: 3, author: "sh**** <sh***@ex*****.co*>" },
83
+ ])
84
+ end
85
+
86
+ context "when the authors command raises an exception" do
87
+ it "returns []" do
88
+ allow_any_instance_of(KnapsackPro::RepositoryAdapters::GitAdapter).to receive(:git_commit_authors).and_raise(Exception)
89
+
90
+ subject = KnapsackPro::RepositoryAdapters::GitAdapter.new
91
+
92
+ expect(subject.commit_authors).to eq []
93
+ end
94
+ end
95
+
96
+ context "when the authors command returns an empty string" do
97
+ it "returns []" do
98
+ allow_any_instance_of(KnapsackPro::RepositoryAdapters::GitAdapter).to receive(:git_commit_authors).and_return("")
99
+
100
+ subject = KnapsackPro::RepositoryAdapters::GitAdapter.new
101
+
102
+ expect(subject.commit_authors).to eq []
103
+ end
104
+ end
105
+ end
34
106
  end
@@ -212,6 +212,7 @@ describe KnapsackPro::Runners::Queue::RSpecRunner do
212
212
  expect(tracker).to receive(:reset!)
213
213
  expect(tracker).to receive(:set_prerun_tests).with(test_file_paths)
214
214
 
215
+ expect(described_class).to receive(:ensure_spec_opts_have_rspec_queue_summary_formatter)
215
216
  options = double
216
217
  expect(RSpec::Core::ConfigurationOptions).to receive(:new).with([
217
218
  '--no-color',
@@ -339,4 +340,39 @@ describe KnapsackPro::Runners::Queue::RSpecRunner do
339
340
  end
340
341
  end
341
342
  end
343
+
344
+ describe '.ensure_spec_opts_have_rspec_queue_summary_formatter' do
345
+ subject { described_class.ensure_spec_opts_have_rspec_queue_summary_formatter }
346
+
347
+ context 'when `SPEC_OPTS` is set' do
348
+ context 'when `SPEC_OPTS` has RSpec Queue Summary Formatter' do
349
+ before do
350
+ stub_const('ENV', { 'SPEC_OPTS' => '--format json --format KnapsackPro::Formatters::RSpecQueueSummaryFormatter' })
351
+ end
352
+
353
+ it 'does nothing' do
354
+ subject
355
+ expect(ENV['SPEC_OPTS']).to eq '--format json --format KnapsackPro::Formatters::RSpecQueueSummaryFormatter'
356
+ end
357
+ end
358
+
359
+ context 'when `SPEC_OPTS` has no RSpec Queue Summary Formatter' do
360
+ before do
361
+ stub_const('ENV', { 'SPEC_OPTS' => '--format json' })
362
+ end
363
+
364
+ it 'adds RSpec Queue Summary Formatter to `SPEC_OPTS`' do
365
+ subject
366
+ expect(ENV['SPEC_OPTS']).to eq '--format json --format KnapsackPro::Formatters::RSpecQueueSummaryFormatter'
367
+ end
368
+ end
369
+ end
370
+
371
+ context 'when `SPEC_OPTS` is not set' do
372
+ it 'does nothing' do
373
+ subject
374
+ expect(ENV['SPEC_OPTS']).to be_nil
375
+ end
376
+ end
377
+ end
342
378
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: knapsack_pro
3
3
  version: !ruby/object:Gem::Version
4
- version: 5.1.1
4
+ version: 5.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - ArturT
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-06-19 00:00:00.000000000 Z
11
+ date: 2023-07-17 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake
@@ -192,6 +192,7 @@ files:
192
192
  - ".circleci/config.yml"
193
193
  - ".github/assets/install-button.png"
194
194
  - ".github/assets/knapsack-diamonds.png"
195
+ - ".github/dependabot.yml"
195
196
  - ".gitignore"
196
197
  - ".rspec"
197
198
  - CHANGELOG.md
@@ -244,6 +245,7 @@ files:
244
245
  - lib/knapsack_pro/formatters/rspec_queue_summary_formatter.rb
245
246
  - lib/knapsack_pro/hooks/queue.rb
246
247
  - lib/knapsack_pro/logger_wrapper.rb
248
+ - lib/knapsack_pro/mask_string.rb
247
249
  - lib/knapsack_pro/presenter.rb
248
250
  - lib/knapsack_pro/queue_allocator.rb
249
251
  - lib/knapsack_pro/queue_allocator_builder.rb