affected_tests 0.1.0 → 0.4.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: af75eb73948c85a496715e0ea5f27610a1edb9ad9db22ddf1529122bc9129fcf
4
- data.tar.gz: 812ebcd3b665254bfc365e10537896bec4d84bbca4efd17b5de46bfa73ed0346
3
+ metadata.gz: fbb2179c4fffe41e99f31697dc10b161f5d0063776a4e844b88591013c33a97c
4
+ data.tar.gz: 1c4b1596a80fea2d05dc754d4ddc7219843dacb53b022afd0ddab06acc663c31
5
5
  SHA512:
6
- metadata.gz: 90130e1a9102afb5afae71d4b0f14bb024c35ae44f807fd8c3fc75d7f143d14636854c84bb67bebfbd5970bc7326b2968cd2f2997345d86d5be41897ec312ab7
7
- data.tar.gz: e4d4f3879148330499743228daf4facabd030a4cd799c3a92bb95f99886bb86760d5f77385037fd5b3982c5d7e3546462fc1f4def93eb7ec048e047a2dc52f3b
6
+ metadata.gz: 58d176dc48c68f09fa0ff3a610879e1c3c90d6d360eb33cc2b48306810996a7dd762b7490dc47fd63c9bddee22a44005bfbce7262c88043ab4352e41ead236bc
7
+ data.tar.gz: 484bade7034e6ccf3259dd84419b2c80cac33f17a0171f842d59d1cad5d2db252dbaf487ec6082cead83bca000ea2540ee718963d6562c7ba4b8a336f7a5d28b
data/Gemfile.lock CHANGED
@@ -1,17 +1,17 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- affected_tests (0.1.0)
5
- calleree
4
+ affected_tests (0.3.0)
5
+ rotoscope
6
6
 
7
7
  GEM
8
8
  remote: https://rubygems.org/
9
9
  specs:
10
- calleree (0.1.0)
11
10
  rake (13.0.6)
11
+ rotoscope (0.3.0)
12
12
 
13
13
  PLATFORMS
14
- arm64-darwin-21
14
+ ruby
15
15
 
16
16
  DEPENDENCIES
17
17
  affected_tests!
data/README.md CHANGED
@@ -29,10 +29,28 @@ require "affected_tests/rspec"
29
29
  AffectedTests.setup(
30
30
  project_path: File.expand_path("../../", __FILE__),
31
31
  test_dir_path: "spec/",
32
- output_path: "log/affected-tests-map.json"
32
+ output_path: "log/affected-tests-map.json",
33
+ revision: "1cf22fdb86e2b2d6107" # or git rev-parse HEAD > REVISION
33
34
  )
34
35
  ```
35
36
 
37
+ this will write associated test files per file on `log/affected-tests-map.json`:
38
+
39
+ ```json
40
+ {
41
+ "revision": "1cf22fdb86e2b2d6107",
42
+ "map": {
43
+ "app/controllers/comments_controller.rb": [
44
+ "spec/requests/comments_spec.rb"
45
+ ],
46
+ "app/views/comments/index.html.erb": [
47
+ "spec/requests/comments_spec.rb",
48
+ "spec/views/comments/index.html.erb_spec.rb"
49
+ ]
50
+ }
51
+ }
52
+ ```
53
+
36
54
  ### Get Diff
37
55
 
38
56
  #### Schema
@@ -76,6 +94,17 @@ pp target_tests
76
94
 
77
95
  See also: `scripts/calculate-target-tests`
78
96
 
97
+ #### Merge results from parallel test
98
+
99
+ ```
100
+ require "affected_tests/map_merger"
101
+
102
+ AffectedTests::MapMerger.run(
103
+ map_file_paths: %w[node1-result.json node2-result.json node3-result.json],
104
+ output_path: "merged-result.json"
105
+ )
106
+ ```
107
+
79
108
  ## Development
80
109
 
81
110
  After checking out the repo, run `bin/setup` to install dependencies. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
@@ -0,0 +1,41 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "json"
4
+ require "set"
5
+
6
+ module AffectedTests
7
+ module MapMerger
8
+ module_function
9
+
10
+ def run(map_file_paths:, output_path:)
11
+ map_infos = map_file_paths.map do |map_file_path|
12
+ JSON.parse(File.read(map_file_path))
13
+ end
14
+
15
+ revisions = map_infos.map { |map_info| map_info["revision"] }.uniq
16
+ raise "map files weren't generated by same revision" if revisions.size != 1
17
+
18
+ keys = map_infos.flat_map { |map_info| map_info["map"].keys }.uniq
19
+
20
+ result_map = {}
21
+ keys.each do |key|
22
+ map_infos.each do |map_info|
23
+ map = map_info["map"]
24
+ next if map[key].nil?
25
+
26
+ result_map[key] ||= Set.new
27
+ map[key].each do |test_file_path|
28
+ result_map[key] << test_file_path
29
+ end
30
+ end
31
+ end
32
+
33
+ result = {
34
+ revision: revisions.first,
35
+ map: result_map.transform_values(&:to_a)
36
+ }
37
+
38
+ File.write(output_path, JSON.dump(result))
39
+ end
40
+ end
41
+ end
@@ -1,13 +1,14 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  RSpec.configure do |config|
4
- config.before(:suite) do
5
- AffectedTests.start
4
+ config.prepend_before(:each) do
5
+ AffectedTests.start_trace
6
6
  end
7
7
 
8
- config.after(:each) do
8
+ config.append_after(:each) do
9
+ AffectedTests.stop_trace
9
10
  target_spec = self.class.declaration_locations.last[0]
10
- AffectedTests.emit(target_spec)
11
+ AffectedTests.checkpoint(target_spec)
11
12
  end
12
13
 
13
14
  config.after(:suite) do
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module AffectedTests
4
- VERSION = "0.1.0"
4
+ VERSION = "0.4.0"
5
5
  end
@@ -3,61 +3,62 @@
3
3
  require "set"
4
4
  require "json"
5
5
 
6
- require "calleree"
6
+ require "rotoscope"
7
7
 
8
8
  require_relative "affected_tests/version"
9
9
 
10
10
  module AffectedTests
11
11
  module_function
12
12
 
13
- def setup(project_path:, test_dir_path:, output_path:)
13
+ def setup(project_path:, test_dir_path:, output_path:, revision: nil)
14
14
  @project_path = project_path
15
15
  @test_dir_path = test_dir_path
16
16
  @output_path = output_path
17
+ @revision = revision || build_revision
18
+ @rotoscope = Rotoscope.new do |call|
19
+ next if self == call.receiver
20
+
21
+ if call.caller_path && target_path?(call.caller_path)
22
+ buffer << call.caller_path
23
+ end
24
+ end
17
25
  end
18
26
 
19
- def start
20
- Calleree.start
27
+ def start_trace
28
+ @rotoscope.start_trace
21
29
  end
22
30
 
23
- def import_from_calleree(target_test_path, result)
24
- caller_in_project = result.select do |(caller_info, _callee_info, _count)|
25
- caller_path = caller_info.first
26
- target_path?(caller_path)
27
- end.map do |(caller_info, _callee_info, _count)|
28
- format_path(caller_info.first)
29
- end
31
+ def stop_trace
32
+ @rotoscope.stop_trace
33
+ end
30
34
 
31
- called_in_project = result.select do |(_caller_info, callee_info, _count)|
32
- callee_path = callee_info.first
33
- target_path?(callee_path)
34
- end.map do |(_caller_info, callee_info, _count)|
35
- format_path(callee_info.first)
35
+ def import_from_rotoscope(target_test_path, result)
36
+ all_related_paths = result.uniq.map do |caller_path|
37
+ format_path(caller_path)
36
38
  end
37
39
 
38
- all_related_paths = (called_in_project + caller_in_project).uniq
39
-
40
- target_test_file_path = format_path(target_test_path)
40
+ formatted_target_test_path = format_path(target_test_path)
41
41
 
42
42
  all_related_paths.each do |path|
43
43
  next if path.start_with?(@test_dir_path)
44
44
 
45
- if path != target_test_file_path
46
- add(target_test_file_path, path)
45
+ if path != formatted_target_test_path
46
+ add(formatted_target_test_path, path)
47
47
  end
48
48
  end
49
49
  end
50
50
 
51
- def emit(target_test_path)
52
- res = Calleree.result(clear: true)
53
- import_from_calleree(target_test_path, res)
51
+ def checkpoint(target_test_path)
52
+ diff = buffer
53
+ import_from_rotoscope(target_test_path, diff)
54
+ buffer.clear
54
55
  end
55
56
 
56
57
  def dump
57
- data = { revision: revision, map: cache.transform_values(&:to_a) }
58
+ data = { revision: @revision, map: cache.transform_values(&:to_a) }
58
59
  File.write(@output_path, JSON.dump(data))
59
60
  ensure
60
- Calleree.stop
61
+ @rotoscope.stop_trace if @rotoscope.tracing?
61
62
  end
62
63
 
63
64
  def format_path(path)
@@ -73,17 +74,25 @@ module AffectedTests
73
74
  cache[callee].add(caller)
74
75
  end
75
76
 
76
- def revision
77
- revision_path = File.expand_path("../../REVISION", __FILE__)
78
- if File.exist?(revision_path)
79
- File.read(revision_path).strip
77
+ def build_revision
78
+ if defined? Rails
79
+ path = Rails.root.join("REVISION")
80
+ if path.exist?
81
+ path.read.chomp
82
+ else
83
+ "UNKNOWN"
84
+ end
80
85
  else
81
86
  "UNKNOWN"
82
87
  end
83
88
  end
84
89
 
90
+ def buffer
91
+ Thread.current[:buffer] ||= []
92
+ end
93
+
85
94
  def cache
86
- @cache ||= {}
95
+ Thread.current[:cache] ||= {}
87
96
  end
88
97
 
89
98
  def bundler_path
@@ -15,11 +15,23 @@ target_sha = ARGV.shift
15
15
 
16
16
  client = Octokit::Client.new(access_token: ENV["GITHUB_TOKEN"])
17
17
 
18
- targets = client.compare(repository, base_sha, target_sha).files.map do |info|
19
- {
20
- filename: info.filename,
21
- status: info.status
22
- }
18
+ targets = client.compare(repository, base_sha, target_sha).files.each_with_object([]) do |info, arr|
19
+ # https://docs.github.com/en/rest/commits/commits#get-a-commit
20
+ case info.status
21
+ when "modified", "added", "removed"
22
+ arr << { filename: info.filename, status: info.status }
23
+ when "renamed"
24
+ arr << { filename: info.filename, status: "added" }
25
+ arr << { filename: info.previous_filename, status: "removed" }
26
+ when "copied"
27
+ arr << { filename: info.filename, status: "added" }
28
+ when "changed"
29
+ arr << { filename: info.filename, status: "modified" }
30
+ when "unchanged"
31
+ # do nothing
32
+ else
33
+ raise "Unknown status: #{info.status}"
34
+ end
23
35
  end
24
36
 
25
37
  puts JSON.dump(targets)
metadata CHANGED
@@ -1,17 +1,17 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: affected_tests
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Shia
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2022-07-19 00:00:00.000000000 Z
11
+ date: 2022-08-29 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
- name: calleree
14
+ name: rotoscope
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
17
  - - ">="
@@ -39,6 +39,7 @@ files:
39
39
  - Rakefile
40
40
  - lib/affected_tests.rb
41
41
  - lib/affected_tests/differ.rb
42
+ - lib/affected_tests/map_merger.rb
42
43
  - lib/affected_tests/rspec.rb
43
44
  - lib/affected_tests/version.rb
44
45
  - scripts/calculate-target-tests