1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
|
#!/usr/bin/env ruby
# frozen_string_literal: true
require 'gitlab'
require_relative 'helpers/predictive_tests_helper'
module Tooling
class FindChanges
include Helpers::PredictiveTestsHelper
ALLOWED_FILE_TYPES = ['.js', '.vue', '.md', '.scss'].freeze
def initialize(
from:,
changed_files_pathname: nil,
predictive_tests_pathname: nil,
frontend_fixtures_mapping_pathname: nil,
file_filter: ->(_) { true }
)
raise ArgumentError, ':from can only be :api or :changed_files' unless
%i[api changed_files].include?(from)
@gitlab_token = ENV['PROJECT_TOKEN_FOR_CI_SCRIPTS_API_USAGE'] || ''
@gitlab_endpoint = ENV['CI_API_V4_URL']
@mr_project_path = ENV['CI_MERGE_REQUEST_PROJECT_PATH']
@mr_iid = ENV['CI_MERGE_REQUEST_IID']
@changed_files_pathname = changed_files_pathname
@predictive_tests_pathname = predictive_tests_pathname
@frontend_fixtures_mapping_pathname = frontend_fixtures_mapping_pathname
@from = from
@file_filter = file_filter
end
def execute
if changed_files_pathname.nil?
raise ArgumentError, "A path to the changed files file must be given as :changed_files_pathname"
end
case @from
when :api
write_array_to_file(changed_files_pathname, file_changes + frontend_fixture_files, append: false)
else
write_array_to_file(changed_files_pathname, frontend_fixture_files, append: true)
end
end
def only_allowed_files_changed
file_changes.any? && file_changes.all? { |file| ALLOWED_FILE_TYPES.include?(File.extname(file)) }
end
private
attr_reader :gitlab_token, :gitlab_endpoint, :mr_project_path,
:mr_iid, :changed_files_pathname, :predictive_tests_pathname,
:frontend_fixtures_mapping_pathname, :file_filter
def gitlab
@gitlab ||= begin
Gitlab.configure do |config|
config.endpoint = gitlab_endpoint
config.private_token = gitlab_token
end
Gitlab
end
end
def add_frontend_fixture_files?
predictive_tests_pathname && frontend_fixtures_mapping_pathname
end
def frontend_fixture_files
# If we have a `test file -> JSON frontend fixture` mapping file, we add the files JSON frontend fixtures
# files to the list of changed files so that Jest can automatically run the dependent tests
# using --findRelatedTests flag.
empty = [].freeze
test_files.flat_map do |test_file|
frontend_fixtures_mapping[test_file] || empty
end
end
def file_changes
@file_changes ||=
case @from
when :api
mr_changes.changes.select(&file_filter).flat_map do |change|
change.to_h.values_at('old_path', 'new_path')
end.uniq
else
read_array_from_file(changed_files_pathname)
end
end
def mr_changes
@mr_changes ||= gitlab.merge_request_changes(mr_project_path, mr_iid)
end
def test_files
return [] if !predictive_tests_pathname || !File.exist?(predictive_tests_pathname)
read_array_from_file(predictive_tests_pathname)
end
def frontend_fixtures_mapping
return {} if !frontend_fixtures_mapping_pathname || !File.exist?(frontend_fixtures_mapping_pathname)
JSON.parse(File.read(frontend_fixtures_mapping_pathname)) # rubocop:disable Gitlab/Json
end
end
end
|