selective-ruby-core 0.1.6-x86_64-darwin → 0.1.7-x86_64-darwin
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 +4 -4
- data/lib/bin/file_correlation_collector.sh +141 -0
- data/lib/selective/ruby/core/controller.rb +32 -78
- data/lib/selective/ruby/core/file_correlator.rb +38 -0
- data/lib/selective/ruby/core/helper.rb +76 -0
- data/lib/selective/ruby/core/version.rb +1 -1
- data/lib/selective-ruby-core.rb +4 -0
- metadata +5 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0bcee1f0c11ea957dd90a8f41b3c53fe7975117ff67e2e90ef961d1f8658e7a1
|
4
|
+
data.tar.gz: 0e37f18b4198d04bf58855db13b8a4f24a0d9be535938b08543738064e3fec93
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: de3efdfdea2c7fe2f2556c6ae2679f6239a1b8c89ef0b6b081ef7137fc98f0a1a1ef14c1b7da6d286dffd57c1ff30478e7cc7d97475b385e46508ed34a3a3ec0
|
7
|
+
data.tar.gz: 1d9d4d0c260981f3cff61bb1d02e669925c3aa94d2e323a9866d074d4c10c65b2a6fd20472ddce1ca42969081368160e615e837385b7e0988810dff93c45fc48
|
@@ -0,0 +1,141 @@
|
|
1
|
+
#!/bin/bash
|
2
|
+
|
3
|
+
# The first argument is the number of commits to process
|
4
|
+
branch=$1
|
5
|
+
num_commits=$2
|
6
|
+
|
7
|
+
# Initialize an associative array to hold the files to check
|
8
|
+
declare -A files_to_check
|
9
|
+
|
10
|
+
# Populate the array with the script arguments, starting from the second argument
|
11
|
+
for file in "${@:3}"
|
12
|
+
do
|
13
|
+
files_to_check["$file"]=1
|
14
|
+
done
|
15
|
+
|
16
|
+
# Get a list of all commit hashes, in reverse order
|
17
|
+
all_commits=$(git log origin/$branch --no-merges --format=%H --reverse -n $num_commits)
|
18
|
+
|
19
|
+
# Initialize an associative array to store the test files
|
20
|
+
declare -A test_files
|
21
|
+
declare -A uncorrelated_test_files
|
22
|
+
|
23
|
+
# Initialize an array to store the files changed in the previous commit
|
24
|
+
prev_changed_files=()
|
25
|
+
|
26
|
+
# For each commit...
|
27
|
+
for commit in $all_commits
|
28
|
+
do
|
29
|
+
# Get a list of all files that were changed in the current commit
|
30
|
+
files=$(git diff-tree --no-commit-id --name-only -r $commit)
|
31
|
+
|
32
|
+
declare -A correlated_test_files
|
33
|
+
|
34
|
+
# # For each file in the list of files changed in the previous commit...
|
35
|
+
for file in "${prev_changed_files[@]}"
|
36
|
+
do
|
37
|
+
# If the file is in the list of files to check...
|
38
|
+
if [[ ${files_to_check[$file]} ]]; then
|
39
|
+
# For each file...
|
40
|
+
for test_file in $files
|
41
|
+
do
|
42
|
+
# If the file is in the test/ directory and ends with _test.rb...
|
43
|
+
if [[ $test_file == spec/*_spec.rb ]]
|
44
|
+
then
|
45
|
+
# Increment the count in the associative array
|
46
|
+
test_files["$file|$test_file"]=$((test_files["$file|$test_file"]+1))
|
47
|
+
# Add the test file to the correlated_test_files array
|
48
|
+
correlated_test_files["$test_file"]=1
|
49
|
+
fi
|
50
|
+
done
|
51
|
+
fi
|
52
|
+
done
|
53
|
+
|
54
|
+
# For each file in the list of files changed in the current commit...
|
55
|
+
for file in $files
|
56
|
+
do
|
57
|
+
# If the file is in the list of files to check...
|
58
|
+
if [[ ${files_to_check[$file]} ]]; then
|
59
|
+
# For each file...
|
60
|
+
for test_file in $files
|
61
|
+
do
|
62
|
+
# If the file is in the test/ directory and ends with _test.rb...
|
63
|
+
if [[ $test_file == spec/*_spec.rb ]]
|
64
|
+
then
|
65
|
+
# Increment the count in the associative array
|
66
|
+
test_files["$file|$test_file"]=$((test_files["$file|$test_file"]+1))
|
67
|
+
# Add the test file to the correlated_test_files array
|
68
|
+
correlated_test_files["$test_file"]=1
|
69
|
+
fi
|
70
|
+
done
|
71
|
+
fi
|
72
|
+
done
|
73
|
+
|
74
|
+
# For each file...
|
75
|
+
for test_file in $files
|
76
|
+
do
|
77
|
+
# If the file is in the test/ directory and ends with _test.rb...
|
78
|
+
if [[ $test_file == spec/*_spec.rb ]]
|
79
|
+
then
|
80
|
+
# If the test file is not correlated to any of the files to check in the current commit...
|
81
|
+
if [[ -z ${correlated_test_files[$test_file]} ]]
|
82
|
+
then
|
83
|
+
# Increment the count in the associative array
|
84
|
+
uncorrelated_test_files["$test_file"]=$((uncorrelated_test_files["$test_file"]+1))
|
85
|
+
fi
|
86
|
+
fi
|
87
|
+
done
|
88
|
+
|
89
|
+
# Clear the correlated_test_files array for the next commit
|
90
|
+
unset correlated_test_files
|
91
|
+
|
92
|
+
# Store the list of files changed in this commit for the next iteration
|
93
|
+
prev_changed_files=($files)
|
94
|
+
done
|
95
|
+
|
96
|
+
# OUTPUT
|
97
|
+
|
98
|
+
# Initialize an associative array to hold the JSON strings for each file
|
99
|
+
declare -A file_jsons
|
100
|
+
|
101
|
+
# Add the test_files to the file_jsons associative array
|
102
|
+
for key in "${!test_files[@]}"
|
103
|
+
do
|
104
|
+
file=${key%|*}
|
105
|
+
test_file=${key#*|}
|
106
|
+
count=${test_files[$key]}
|
107
|
+
# Append to the JSON string for this file
|
108
|
+
file_jsons["$file"]+="\"$test_file\": $count,"
|
109
|
+
done
|
110
|
+
|
111
|
+
# Initialize an empty string for the test_files JSON
|
112
|
+
correlated_files_json=""
|
113
|
+
|
114
|
+
# Add the file_jsons to the correlated_files_json string
|
115
|
+
for file in "${!file_jsons[@]}"
|
116
|
+
do
|
117
|
+
# Remove the trailing comma from the JSON string for this file
|
118
|
+
file_json=${file_jsons[$file]%?}
|
119
|
+
# Append to the correlated_files_json string
|
120
|
+
correlated_files_json+="\"$file\": { $file_json },"
|
121
|
+
done
|
122
|
+
|
123
|
+
# Remove the trailing comma from the correlated_files_json string
|
124
|
+
correlated_files_json=${correlated_files_json%?}
|
125
|
+
|
126
|
+
# Initialize an empty string for the uncorrelated_test_files JSON
|
127
|
+
uncorrelated_files_json=""
|
128
|
+
|
129
|
+
# Add the uncorrelated_test_files to the uncorrelated_files_json string
|
130
|
+
for key in "${!uncorrelated_test_files[@]}"
|
131
|
+
do
|
132
|
+
count=${uncorrelated_test_files[$key]}
|
133
|
+
# Append to the uncorrelated_files_json string
|
134
|
+
uncorrelated_files_json+="\"$key\": $count,"
|
135
|
+
done
|
136
|
+
|
137
|
+
# Remove the trailing comma from the uncorrelated_files_json string
|
138
|
+
uncorrelated_files_json=${uncorrelated_files_json%?}
|
139
|
+
|
140
|
+
# Output the JSON
|
141
|
+
echo "{ \"correlated_files\": { $correlated_files_json }, \"uncorrelated_files\": { $uncorrelated_files_json } }"
|
@@ -1,13 +1,12 @@
|
|
1
1
|
require "logger"
|
2
2
|
require "uri"
|
3
|
-
require "json"
|
4
3
|
require "fileutils"
|
5
|
-
require "open3"
|
6
4
|
|
7
5
|
module Selective
|
8
6
|
module Ruby
|
9
7
|
module Core
|
10
8
|
class Controller
|
9
|
+
include Helper
|
11
10
|
@@selective_suppress_reporting = false
|
12
11
|
|
13
12
|
def initialize(runner, debug: false, log: false)
|
@@ -51,9 +50,7 @@ module Selective
|
|
51
50
|
|
52
51
|
private
|
53
52
|
|
54
|
-
attr_reader :runner, :pipe, :transport_pid, :retries, :logger, :runner_id
|
55
|
-
|
56
|
-
ROOT_GEM_PATH = Gem.loaded_specs["selective-ruby-core"].full_gem_path
|
53
|
+
attr_reader :runner, :pipe, :transport_pid, :retries, :logger, :runner_id, :diff
|
57
54
|
|
58
55
|
def get_runner_id
|
59
56
|
runner_id = build_env.delete("runner_id")
|
@@ -242,7 +239,11 @@ module Selective
|
|
242
239
|
self.class.restore_reporting!
|
243
240
|
@logger.info("Sending Response: test_manifest")
|
244
241
|
data = {test_cases: runner.manifest["examples"]}
|
245
|
-
|
242
|
+
num_commits = build_env["num_commits"] || 1000
|
243
|
+
if (diff = get_diff(num_commits))
|
244
|
+
data[:modified_test_files] = modified_test_files(diff)
|
245
|
+
data[:correlated_files] = correlated_files(diff, num_commits)
|
246
|
+
end
|
246
247
|
write({type: "test_manifest", data: data})
|
247
248
|
end
|
248
249
|
|
@@ -271,93 +272,46 @@ module Selective
|
|
271
272
|
:break
|
272
273
|
end
|
273
274
|
|
275
|
+
def correlated_files(diff, num_commits)
|
276
|
+
Selective::Ruby::Core::FileCorrelator.new(diff, num_commits, build_env["target_branch"]).correlate
|
277
|
+
end
|
278
|
+
|
274
279
|
def test_case_callback(test_case)
|
275
280
|
@logger.info("Sending Response: test_case_result: #{test_case[:id]}")
|
276
281
|
write({type: "test_case_result", data: test_case})
|
277
282
|
end
|
278
283
|
|
279
|
-
def modified_test_files
|
284
|
+
def modified_test_files(diff)
|
280
285
|
@modified_test_files ||= begin
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
output, status = Open3.capture2e("git diff #{target_branch} --name-only")
|
285
|
-
|
286
|
-
if status.success?
|
287
|
-
output.split("\n").filter do |f|
|
288
|
-
f.match?(/^#{runner.base_test_path}/)
|
289
|
-
end
|
286
|
+
diff.filter do |f|
|
287
|
+
f.match?(/^#{runner.base_test_path}/)
|
290
288
|
end
|
291
289
|
end
|
292
290
|
end
|
293
291
|
|
294
|
-
def
|
295
|
-
|
296
|
-
|
292
|
+
def get_diff(num_commits)
|
293
|
+
target_branch = build_env["target_branch"]
|
294
|
+
return [] if target_branch.nil? || target_branch.empty?
|
297
295
|
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
end
|
304
|
-
|
305
|
-
def with_error_handling(include_header: true)
|
306
|
-
yield
|
307
|
-
rescue => e
|
308
|
-
raise e if debug?
|
309
|
-
header = <<~TEXT
|
310
|
-
An error occurred. Please rerun with --debug
|
311
|
-
and contact support at https://selective.ci/support
|
312
|
-
TEXT
|
313
|
-
|
314
|
-
unless @banner_displayed
|
315
|
-
header = <<~TEXT
|
316
|
-
#{banner}
|
317
|
-
|
318
|
-
#{header}
|
319
|
-
TEXT
|
296
|
+
Open3.capture2e("git fetch origin #{target_branch} --depth=#{num_commits}").then do |output, status|
|
297
|
+
unless status.success?
|
298
|
+
print_warning "Selective was unable to fetch the target branch. This may result in a sub-optimal test order. If the issue persists, please contact support. The output was:\n\n#{output}"
|
299
|
+
return []
|
300
|
+
end
|
320
301
|
end
|
321
302
|
|
322
|
-
|
323
|
-
|
324
|
-
|
325
|
-
|
326
|
-
|
327
|
-
|
328
|
-
|
329
|
-
|
330
|
-
end
|
331
|
-
|
332
|
-
def print_warning(message)
|
333
|
-
puts_indented <<~TEXT
|
334
|
-
\e[33m
|
335
|
-
#{message}
|
336
|
-
\e[0m
|
337
|
-
TEXT
|
338
|
-
end
|
339
|
-
|
340
|
-
def print_notice(message)
|
341
|
-
puts_indented <<~TEXT
|
342
|
-
#{banner}
|
343
|
-
#{message}
|
344
|
-
TEXT
|
345
|
-
end
|
346
|
-
|
347
|
-
def puts_indented(text)
|
348
|
-
puts text.gsub(/^/, " ")
|
303
|
+
Open3.capture2e("git diff origin/#{target_branch} --name-only").then do |output, status|
|
304
|
+
if status.success?
|
305
|
+
output.split("\n")
|
306
|
+
else
|
307
|
+
print_warning "Selective was unable to diff with the target branch. This may result in a sub-optimal test order. If the issue persists, please contact support. The output was:\n\n#{output}"
|
308
|
+
[]
|
309
|
+
end
|
310
|
+
end
|
349
311
|
end
|
350
312
|
|
351
|
-
def
|
352
|
-
@
|
353
|
-
<<~BANNER
|
354
|
-
____ _ _ _
|
355
|
-
/ ___| ___| | ___ ___| |_(_)_ _____
|
356
|
-
\\___ \\ / _ \\ |/ _ \\/ __| __| \\ \\ / / _ \\
|
357
|
-
___) | __/ | __/ (__| |_| |\\ V / __/
|
358
|
-
|____/ \\___|_|\\___|\\___|\\__|_| \\_/ \\___|
|
359
|
-
________________________________________
|
360
|
-
BANNER
|
313
|
+
def debug?
|
314
|
+
@debug
|
361
315
|
end
|
362
316
|
end
|
363
317
|
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
module Selective
|
2
|
+
module Ruby
|
3
|
+
module Core
|
4
|
+
class FileCorrelator
|
5
|
+
include Helper
|
6
|
+
|
7
|
+
class FileCorrelatorError < StandardError; end
|
8
|
+
|
9
|
+
FILE_CORRELATION_COLLECTOR_PATH = File.join(ROOT_GEM_PATH, "lib", "bin", "file_correlation_collector.sh")
|
10
|
+
|
11
|
+
def initialize(diff, num_commits, target_branch)
|
12
|
+
@diff = diff
|
13
|
+
@num_commits = num_commits
|
14
|
+
@target_branch = target_branch
|
15
|
+
end
|
16
|
+
|
17
|
+
def correlate
|
18
|
+
JSON.parse(get_correlated_files, symbolize_names: true)
|
19
|
+
rescue FileCorrelatorError, JSON::ParserError
|
20
|
+
print_warning "Selective was unable to correlate the diff to test files. This may result in a sub-optimal test order. If the issue persists, please contact support."
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
attr_reader :diff, :num_commits, :target_branch
|
26
|
+
|
27
|
+
def get_correlated_files
|
28
|
+
Open3.capture2e("#{FILE_CORRELATION_COLLECTOR_PATH} #{target_branch} #{num_commits} #{diff.join(" ")}").then do |output, status|
|
29
|
+
|
30
|
+
raise FileCorrelatorError unless status.success?
|
31
|
+
|
32
|
+
output
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,76 @@
|
|
1
|
+
module Selective
|
2
|
+
module Ruby
|
3
|
+
module Core
|
4
|
+
module Helper
|
5
|
+
def safe_filename(filename)
|
6
|
+
filename
|
7
|
+
.gsub(/[\/\\:*?"<>|\n\r]+/, '_')
|
8
|
+
.gsub(/^\.+|\.+$/, '')
|
9
|
+
.strip[0, 255]
|
10
|
+
end
|
11
|
+
|
12
|
+
def with_error_handling(include_header: true)
|
13
|
+
yield
|
14
|
+
rescue => e
|
15
|
+
raise e if debug?
|
16
|
+
header = <<~TEXT
|
17
|
+
An error occurred. Please rerun with --debug
|
18
|
+
and contact support at https://selective.ci/support
|
19
|
+
TEXT
|
20
|
+
|
21
|
+
unless $selective_banner_displayed
|
22
|
+
header = <<~TEXT
|
23
|
+
#{banner}
|
24
|
+
|
25
|
+
#{header}
|
26
|
+
TEXT
|
27
|
+
end
|
28
|
+
|
29
|
+
puts_indented <<~TEXT
|
30
|
+
\e[31m
|
31
|
+
#{header if include_header}
|
32
|
+
#{e.message}
|
33
|
+
\e[0m
|
34
|
+
TEXT
|
35
|
+
|
36
|
+
exit 1
|
37
|
+
end
|
38
|
+
|
39
|
+
def print_warning(message)
|
40
|
+
puts_indented <<~TEXT
|
41
|
+
\e[33m
|
42
|
+
#{message}
|
43
|
+
\e[0m
|
44
|
+
TEXT
|
45
|
+
end
|
46
|
+
|
47
|
+
def print_notice(message)
|
48
|
+
puts_indented <<~TEXT
|
49
|
+
#{banner unless $selective_banner_displayed}
|
50
|
+
#{message}
|
51
|
+
TEXT
|
52
|
+
end
|
53
|
+
|
54
|
+
def puts_indented(text)
|
55
|
+
puts text.gsub(/^/, " ")
|
56
|
+
end
|
57
|
+
|
58
|
+
def banner
|
59
|
+
Helper.banner
|
60
|
+
end
|
61
|
+
|
62
|
+
def self.banner
|
63
|
+
$selective_banner_displayed = true
|
64
|
+
<<~BANNER
|
65
|
+
____ _ _ _
|
66
|
+
/ ___| ___| | ___ ___| |_(_)_ _____
|
67
|
+
\\___ \\ / _ \\ |/ _ \\/ __| __| \\ \\ / / _ \\
|
68
|
+
___) | __/ | __/ (__| |_| |\\ V / __/
|
69
|
+
|____/ \\___|_|\\___|\\___|\\__|_| \\_/ \\___|
|
70
|
+
________________________________________
|
71
|
+
BANNER
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
data/lib/selective-ruby-core.rb
CHANGED
@@ -1,6 +1,8 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require "zeitwerk"
|
4
|
+
require "json"
|
5
|
+
require "open3"
|
4
6
|
require "#{__dir__}/selective/ruby/core/version"
|
5
7
|
|
6
8
|
loader = Zeitwerk::Loader.for_gem(warn_on_extra_files: false)
|
@@ -13,6 +15,8 @@ module Selective
|
|
13
15
|
module Core
|
14
16
|
class Error < StandardError; end
|
15
17
|
|
18
|
+
ROOT_GEM_PATH = Gem.loaded_specs["selective-ruby-core"].full_gem_path
|
19
|
+
|
16
20
|
@@available_runners = {}
|
17
21
|
|
18
22
|
def self.register_runner(name, runner_class)
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: selective-ruby-core
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.7
|
5
5
|
platform: x86_64-darwin
|
6
6
|
authors:
|
7
7
|
- Benjamin Wood
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: exe
|
11
11
|
cert_chain: []
|
12
|
-
date: 2024-01-
|
12
|
+
date: 2024-01-05 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: zeitwerk
|
@@ -41,9 +41,12 @@ files:
|
|
41
41
|
- Rakefile
|
42
42
|
- exe/selective
|
43
43
|
- lib/bin/build_env.sh
|
44
|
+
- lib/bin/file_correlation_collector.sh
|
44
45
|
- lib/bin/transport
|
45
46
|
- lib/selective-ruby-core.rb
|
46
47
|
- lib/selective/ruby/core/controller.rb
|
48
|
+
- lib/selective/ruby/core/file_correlator.rb
|
49
|
+
- lib/selective/ruby/core/helper.rb
|
47
50
|
- lib/selective/ruby/core/named_pipe.rb
|
48
51
|
- lib/selective/ruby/core/version.rb
|
49
52
|
homepage: https://www.selective.ci
|