summaryrefslogtreecommitdiff
path: root/tooling
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2023-03-29 03:12:19 +0000
committerGitLab Bot <gitlab-bot@gitlab.com>2023-03-29 03:12:19 +0000
commit7d8cc770b14b41fbe40181d447042dccdc45bff8 (patch)
tree4e14a5e236df733f3c0998cd351a72759c48eb46 /tooling
parent8c9cb9bb575b8d9dff39e5b4891fabb1e0f6a687 (diff)
downloadgitlab-ce-7d8cc770b14b41fbe40181d447042dccdc45bff8.tar.gz
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'tooling')
-rwxr-xr-xtooling/bin/graphql_base_type_mappings9
-rw-r--r--tooling/lib/tooling/mappings/graphql_base_type_mappings.rb119
2 files changed, 128 insertions, 0 deletions
diff --git a/tooling/bin/graphql_base_type_mappings b/tooling/bin/graphql_base_type_mappings
new file mode 100755
index 00000000000..2fc06ab639f
--- /dev/null
+++ b/tooling/bin/graphql_base_type_mappings
@@ -0,0 +1,9 @@
+#!/usr/bin/env ruby
+# frozen_string_literal: true
+
+require_relative '../lib/tooling/mappings/graphql_base_type_mappings'
+
+changes_file = ARGV.shift
+matching_tests_paths = ARGV.shift
+
+Tooling::Mappings::GraphqlBaseTypeMappings.new(changes_file, matching_tests_paths).execute
diff --git a/tooling/lib/tooling/mappings/graphql_base_type_mappings.rb b/tooling/lib/tooling/mappings/graphql_base_type_mappings.rb
new file mode 100644
index 00000000000..cd8b55d5820
--- /dev/null
+++ b/tooling/lib/tooling/mappings/graphql_base_type_mappings.rb
@@ -0,0 +1,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