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
113
114
115
116
117
118
119
|
# frozen_string_literal: true
require 'active_support/inflector'
require_relative 'base'
require_relative '../../../../lib/gitlab_edition'
# If a GraphQL type class changed, we try to identify the other GraphQL types that potentially include this type.
module Tooling
module Mappings
class GraphqlBaseTypeMappings < Base
# Checks for the implements keyword, and graphql_base_types the class name
GRAPHQL_IMPLEMENTS_REGEXP = /implements[( ]([\w:]+)[)]?$/
# GraphQL types are a bit scattered in the codebase based on the edition.
#
# Also, a higher edition is able to include lower editions.
# e.g. EE can include FOSS GraphQL types, and JH can include all GraphQL types
GRAPHQL_TYPES_FOLDERS_FOSS = ['app/graphql/types'].freeze
GRAPHQL_TYPES_FOLDERS_EE = GRAPHQL_TYPES_FOLDERS_FOSS + ['ee/app/graphql/types', 'ee/app/graphql/ee/types']
GRAPHQL_TYPES_FOLDERS_JH = GRAPHQL_TYPES_FOLDERS_EE + ['jh/app/graphql/types', 'jh/app/graphql/jh/types']
GRAPHQL_TYPES_FOLDERS = {
nil => GRAPHQL_TYPES_FOLDERS_FOSS,
'ee' => GRAPHQL_TYPES_FOLDERS_EE,
'jh' => GRAPHQL_TYPES_FOLDERS_JH
}.freeze
def initialize(changes_file, matching_tests_paths)
@matching_tests_paths = matching_tests_paths
@changed_files = read_array_from_file(changes_file)
end
def execute
# We go through the available editions when searching for base types
#
# `nil` is the FOSS edition
matching_graphql_tests = ([nil] + ::GitlabEdition.extensions).flat_map do |edition|
hierarchy = types_hierarchies[edition]
filter_files.flat_map do |graphql_file|
children_types = hierarchy[filename_to_class_name(graphql_file)]
next if children_types.empty?
# We find the specs for the children GraphQL types that are implementing the current GraphQL Type
children_types.map { |filename| filename_to_spec_filename(filename) }
end
end.compact.uniq
write_array_to_file(matching_tests_paths, matching_graphql_tests)
end
def filter_files
changed_files.select do |filename|
filename.start_with?(*GRAPHQL_TYPES_FOLDERS.values.flatten.uniq) &&
filename.end_with?('.rb') &&
File.exist?(filename)
end
end
# Regroup all GraphQL types (by edition) that are implementing another GraphQL type.
#
# The key is the type that is being implemented (e.g. NoteableInterface, TodoableInterface below)
# The value is an array of GraphQL type files that are implementing those types.
#
# Example output:
#
# {
# nil => {
# "NoteableInterface" => [
# "app/graphql/types/alert_management/alert_type.rb",
# "app/graphql/types/design_management/design_type.rb"
# , "TodoableInterface" => [...]
# },
# "ee" => {
# "NoteableInterface" => [
# "app/graphql/types/alert_management/alert_type.rb",
# "app/graphql/types/design_management/design_type.rb",
# "ee/app/graphql/types/epic_type.rb"],
# "TodoableInterface"=> [...]
# }
# }
def types_hierarchies
return @types_hierarchies if @types_hierarchies
@types_hierarchies = {}
GRAPHQL_TYPES_FOLDERS.each_key do |edition|
@types_hierarchies[edition] = Hash.new { |h, k| h[k] = [] }
graphql_files_for_edition_glob = File.join("{#{GRAPHQL_TYPES_FOLDERS[edition].join(',')}}", '**', '*.rb')
Dir[graphql_files_for_edition_glob].each do |graphql_file|
graphql_base_types = File.read(graphql_file).scan(GRAPHQL_IMPLEMENTS_REGEXP)
next if graphql_base_types.empty?
graphql_base_classes = graphql_base_types.flatten.map { |class_name| class_name.split('::').last }
graphql_base_classes.each do |graphql_base_class|
@types_hierarchies[edition][graphql_base_class] += [graphql_file]
end
end
end
@types_hierarchies
end
def filename_to_class_name(filename)
File.basename(filename, '.*').camelize
end
def filename_to_spec_filename(filename)
spec_file = filename.sub('app', 'spec').sub('.rb', '_spec.rb')
return spec_file if File.exist?(spec_file)
end
private
attr_reader :changed_files, :matching_tests_paths
end
end
end
|