diff options
Diffstat (limited to 'app/graphql/resolvers')
-rw-r--r-- | app/graphql/resolvers/base_issues_resolver.rb | 61 | ||||
-rw-r--r-- | app/graphql/resolvers/ci/pipeline_job_artifacts_resolver.rb | 25 | ||||
-rw-r--r-- | app/graphql/resolvers/concerns/issue_resolver_arguments.rb | 26 | ||||
-rw-r--r-- | app/graphql/resolvers/concerns/resolves_groups.rb | 34 | ||||
-rw-r--r-- | app/graphql/resolvers/concerns/resolves_pipelines.rb | 3 | ||||
-rw-r--r-- | app/graphql/resolvers/group_issues_resolver.rb | 12 | ||||
-rw-r--r-- | app/graphql/resolvers/groups_resolver.rb | 12 | ||||
-rw-r--r-- | app/graphql/resolvers/issue_status_counts_resolver.rb | 1 | ||||
-rw-r--r-- | app/graphql/resolvers/issues_resolver.rb | 59 | ||||
-rw-r--r-- | app/graphql/resolvers/merge_requests_resolver.rb | 6 | ||||
-rw-r--r-- | app/graphql/resolvers/topics_resolver.rb | 19 | ||||
-rw-r--r-- | app/graphql/resolvers/users/groups_resolver.rb | 17 |
12 files changed, 197 insertions, 78 deletions
diff --git a/app/graphql/resolvers/base_issues_resolver.rb b/app/graphql/resolvers/base_issues_resolver.rb new file mode 100644 index 00000000000..54ebb697cb2 --- /dev/null +++ b/app/graphql/resolvers/base_issues_resolver.rb @@ -0,0 +1,61 @@ +# frozen_string_literal: true + +module Resolvers + class BaseIssuesResolver < BaseResolver + prepend IssueResolverArguments + + argument :state, Types::IssuableStateEnum, + required: false, + description: 'Current state of this issue.' + argument :sort, Types::IssueSortEnum, + description: 'Sort issues by this criteria.', + required: false, + default_value: :created_desc + + type Types::IssueType.connection_type, null: true + + NON_STABLE_CURSOR_SORTS = %i[priority_asc priority_desc + popularity_asc popularity_desc + label_priority_asc label_priority_desc + milestone_due_asc milestone_due_desc].freeze + + def continue_issue_resolve(parent, finder, **args) + issues = Gitlab::Graphql::Loaders::IssuableLoader.new(parent, finder).batching_find_all { |q| apply_lookahead(q) } + + if non_stable_cursor_sort?(args[:sort]) + # Certain complex sorts are not supported by the stable cursor pagination yet. + # In these cases, we use offset pagination, so we return the correct connection. + offset_pagination(issues) + else + issues + end + end + + private + + def unconditional_includes + [ + { + project: [:project_feature] + }, + :author + ] + end + + def preloads + { + alert_management_alert: [:alert_management_alert], + labels: [:labels], + assignees: [:assignees], + timelogs: [:timelogs], + customer_relations_contacts: { customer_relations_contacts: [:group] } + } + end + + def non_stable_cursor_sort?(sort) + NON_STABLE_CURSOR_SORTS.include?(sort) + end + end +end + +Resolvers::BaseIssuesResolver.prepend_mod_with('Resolvers::BaseIssuesResolver') diff --git a/app/graphql/resolvers/ci/pipeline_job_artifacts_resolver.rb b/app/graphql/resolvers/ci/pipeline_job_artifacts_resolver.rb new file mode 100644 index 00000000000..35d30827561 --- /dev/null +++ b/app/graphql/resolvers/ci/pipeline_job_artifacts_resolver.rb @@ -0,0 +1,25 @@ +# frozen_string_literal: true + +module Resolvers + module Ci + class PipelineJobArtifactsResolver < BaseResolver + type [Types::Ci::JobArtifactType], null: false + + alias_method :pipeline, :object + + def resolve + find_job_artifacts + end + + private + + def find_job_artifacts + BatchLoader::GraphQL.for(pipeline).batch do |pipelines, loader| + ActiveRecord::Associations::Preloader.new.preload(pipelines, :job_artifacts) # rubocop: disable CodeReuse/ActiveRecord + + pipelines.each { |pl| loader.call(pl, pl.job_artifacts) } + end + end + end + end +end diff --git a/app/graphql/resolvers/concerns/issue_resolver_arguments.rb b/app/graphql/resolvers/concerns/issue_resolver_arguments.rb index 855877110e5..38c79ff52ac 100644 --- a/app/graphql/resolvers/concerns/issue_resolver_arguments.rb +++ b/app/graphql/resolvers/concerns/issue_resolver_arguments.rb @@ -55,8 +55,8 @@ module IssueResolverArguments description: 'Filter issues by the given issue types.', required: false argument :milestone_wildcard_id, ::Types::MilestoneWildcardIdEnum, - required: false, - description: 'Filter issues by milestone ID wildcard.' + required: false, + description: 'Filter issues by milestone ID wildcard.' argument :my_reaction_emoji, GraphQL::Types::String, required: false, description: 'Filter by reaction emoji applied by the current user. Wildcard values "NONE" and "ANY" are supported.' @@ -83,6 +83,7 @@ module IssueResolverArguments args[:attempt_project_search_optimizations] = true if args[:search].present? prepare_assignee_username_params(args) + prepare_release_tag_params(args) finder = IssuesFinder.new(current_user, args) @@ -93,6 +94,7 @@ module IssueResolverArguments params_not_mutually_exclusive(args, mutually_exclusive_assignee_username_args) params_not_mutually_exclusive(args, mutually_exclusive_milestone_args) params_not_mutually_exclusive(args.fetch(:not, {}), mutually_exclusive_milestone_args) + params_not_mutually_exclusive(args, mutually_exclusive_release_tag_args) validate_anonymous_search_access! if args[:search].present? super @@ -105,10 +107,30 @@ module IssueResolverArguments complexity end + + def accept_release_tag + argument :release_tag, [GraphQL::Types::String], + required: false, + description: "Release tag associated with the issue's milestone." + argument :release_tag_wildcard_id, Types::ReleaseTagWildcardIdEnum, + required: false, + description: 'Filter issues by release tag ID wildcard.' + end end private + def prepare_release_tag_params(args) + release_tag_wildcard = args.delete(:release_tag_wildcard_id) + return if release_tag_wildcard.blank? + + args[:release_tag] ||= release_tag_wildcard + end + + def mutually_exclusive_release_tag_args + [:release_tag, :release_tag_wildcard_id] + end + def prepare_assignee_username_params(args) args[:assignee_username] = args.delete(:assignee_usernames) if args[:assignee_usernames].present? args[:not][:assignee_username] = args[:not].delete(:assignee_usernames) if args.dig(:not, :assignee_usernames).present? diff --git a/app/graphql/resolvers/concerns/resolves_groups.rb b/app/graphql/resolvers/concerns/resolves_groups.rb new file mode 100644 index 00000000000..c451d4e7936 --- /dev/null +++ b/app/graphql/resolvers/concerns/resolves_groups.rb @@ -0,0 +1,34 @@ +# frozen_string_literal: true + +# Mixin for all resolver classes for type `Types::GroupType.connection_type`. +module ResolvesGroups + extend ActiveSupport::Concern + include LooksAhead + + def resolve_with_lookahead(**args) + apply_lookahead(resolve_groups(**args)) + end + + private + + # The resolver should implement this method. + def resolve_groups(**args) + raise NotImplementedError + end + + def preloads + { + contacts: [:contacts], + container_repositories_count: [:container_repositories], + custom_emoji: [:custom_emoji], + full_path: [:route], + organizations: [:organizations], + path: [:route], + dependency_proxy_blob_count: [:dependency_proxy_blobs], + dependency_proxy_blobs: [:dependency_proxy_blobs], + dependency_proxy_image_count: [:dependency_proxy_manifests], + dependency_proxy_image_ttl_policy: [:dependency_proxy_image_ttl_policy], + dependency_proxy_setting: [:dependency_proxy_setting] + } + end +end diff --git a/app/graphql/resolvers/concerns/resolves_pipelines.rb b/app/graphql/resolvers/concerns/resolves_pipelines.rb index 7fb0852b11e..1c01e5e0250 100644 --- a/app/graphql/resolvers/concerns/resolves_pipelines.rb +++ b/app/graphql/resolvers/concerns/resolves_pipelines.rb @@ -9,6 +9,9 @@ module ResolvesPipelines Types::Ci::PipelineStatusEnum, required: false, description: "Filter pipelines by their status." + argument :scope, ::Types::Ci::PipelineScopeEnum, + required: false, + description: 'Filter pipelines by scope.' argument :ref, GraphQL::Types::String, required: false, diff --git a/app/graphql/resolvers/group_issues_resolver.rb b/app/graphql/resolvers/group_issues_resolver.rb index 1db0ab08e31..28f9266974f 100644 --- a/app/graphql/resolvers/group_issues_resolver.rb +++ b/app/graphql/resolvers/group_issues_resolver.rb @@ -1,10 +1,18 @@ # frozen_string_literal: true -# rubocop:disable Graphql/ResolverType (inherited from IssuesResolver) +# rubocop:disable Graphql/ResolverType (inherited from BaseIssuesResolver) module Resolvers - class GroupIssuesResolver < IssuesResolver + class GroupIssuesResolver < BaseIssuesResolver include GroupIssuableResolver include_subgroups 'issues' + + def ready?(**args) + if args.dig(:not, :release_tag).present? + raise ::Gitlab::Graphql::Errors::ArgumentError, 'releaseTag filter is not allowed when parent is a group.' + end + + super + end end end diff --git a/app/graphql/resolvers/groups_resolver.rb b/app/graphql/resolvers/groups_resolver.rb index b090fdc49d4..abd3bf9e6e0 100644 --- a/app/graphql/resolvers/groups_resolver.rb +++ b/app/graphql/resolvers/groups_resolver.rb @@ -2,6 +2,8 @@ module Resolvers class GroupsResolver < BaseResolver + include ResolvesGroups + type Types::GroupType, null: true argument :include_parent_descendants, GraphQL::Types::Boolean, @@ -19,16 +21,12 @@ module Resolvers alias_method :parent, :object - def resolve(**args) - return [] unless parent.present? - - find_groups(args) - end - private # rubocop: disable CodeReuse/ActiveRecord - def find_groups(args) + def resolve_groups(args) + return Group.none unless parent.present? + GroupsFinder .new(context[:current_user], args.merge(parent: parent)) .execute diff --git a/app/graphql/resolvers/issue_status_counts_resolver.rb b/app/graphql/resolvers/issue_status_counts_resolver.rb index 58cff559d0d..db5c91daac2 100644 --- a/app/graphql/resolvers/issue_status_counts_resolver.rb +++ b/app/graphql/resolvers/issue_status_counts_resolver.rb @@ -5,6 +5,7 @@ module Resolvers prepend IssueResolverArguments type Types::IssueStatusCountsType, null: true + accept_release_tag extras [:lookahead] diff --git a/app/graphql/resolvers/issues_resolver.rb b/app/graphql/resolvers/issues_resolver.rb index b556964ae0c..4b52ef61d57 100644 --- a/app/graphql/resolvers/issues_resolver.rb +++ b/app/graphql/resolvers/issues_resolver.rb @@ -1,61 +1,8 @@ # frozen_string_literal: true +# rubocop:disable Graphql/ResolverType (inherited from BaseIssuesResolver) module Resolvers - class IssuesResolver < BaseResolver - prepend IssueResolverArguments - - argument :state, Types::IssuableStateEnum, - required: false, - description: 'Current state of this issue.' - argument :sort, Types::IssueSortEnum, - description: 'Sort issues by this criteria.', - required: false, - default_value: :created_desc - - type Types::IssueType.connection_type, null: true - - NON_STABLE_CURSOR_SORTS = %i[priority_asc priority_desc - popularity_asc popularity_desc - label_priority_asc label_priority_desc - milestone_due_asc milestone_due_desc].freeze - - def continue_issue_resolve(parent, finder, **args) - issues = Gitlab::Graphql::Loaders::IssuableLoader.new(parent, finder).batching_find_all { |q| apply_lookahead(q) } - - if non_stable_cursor_sort?(args[:sort]) - # Certain complex sorts are not supported by the stable cursor pagination yet. - # In these cases, we use offset pagination, so we return the correct connection. - offset_pagination(issues) - else - issues - end - end - - private - - def unconditional_includes - [ - { - project: [:project_feature] - }, - :author - ] - end - - def preloads - { - alert_management_alert: [:alert_management_alert], - labels: [:labels], - assignees: [:assignees], - timelogs: [:timelogs], - customer_relations_contacts: { customer_relations_contacts: [:group] } - } - end - - def non_stable_cursor_sort?(sort) - NON_STABLE_CURSOR_SORTS.include?(sort) - end + class IssuesResolver < BaseIssuesResolver + accept_release_tag end end - -Resolvers::IssuesResolver.prepend_mod_with('Resolvers::IssuesResolver') diff --git a/app/graphql/resolvers/merge_requests_resolver.rb b/app/graphql/resolvers/merge_requests_resolver.rb index c0dd61078c6..bd7f1f0774e 100644 --- a/app/graphql/resolvers/merge_requests_resolver.rb +++ b/app/graphql/resolvers/merge_requests_resolver.rb @@ -68,6 +68,12 @@ module Resolvers description: 'Sort merge requests by this criteria.', required: false, default_value: :created_desc + argument :created_after, Types::TimeType, + required: false, + description: 'Merge requests created after this timestamp.' + argument :created_before, Types::TimeType, + required: false, + description: 'Merge requests created before this timestamp.' negated do argument :labels, [GraphQL::Types::String], diff --git a/app/graphql/resolvers/topics_resolver.rb b/app/graphql/resolvers/topics_resolver.rb new file mode 100644 index 00000000000..d8199f3d89b --- /dev/null +++ b/app/graphql/resolvers/topics_resolver.rb @@ -0,0 +1,19 @@ +# frozen_string_literal: true + +module Resolvers + class TopicsResolver < BaseResolver + type Types::Projects::TopicType, null: true + + argument :search, GraphQL::Types::String, + required: false, + description: 'Search query for topic name.' + + def resolve(**args) + if args[:search].present? + ::Projects::Topic.search(args[:search]).order_by_total_projects_count + else + ::Projects::Topic.order_by_total_projects_count + end + end + end +end diff --git a/app/graphql/resolvers/users/groups_resolver.rb b/app/graphql/resolvers/users/groups_resolver.rb index 0899b08e19c..eafb56d8f4c 100644 --- a/app/graphql/resolvers/users/groups_resolver.rb +++ b/app/graphql/resolvers/users/groups_resolver.rb @@ -3,8 +3,8 @@ module Resolvers module Users class GroupsResolver < BaseResolver + include ResolvesGroups include Gitlab::Graphql::Authorize::AuthorizeResource - include LooksAhead type Types::GroupType.connection_type, null: true @@ -20,22 +20,17 @@ module Resolvers description: 'Filter by permissions the user has on groups.' before_connection_authorization do |nodes, current_user| - Preloaders::UserMaxAccessLevelInGroupsPreloader.new(nodes, current_user).execute + Preloaders::GroupPolicyPreloader.new(nodes, current_user).execute end - def resolve_with_lookahead(**args) - return unless Feature.enabled?(:paginatable_namespace_drop_down_for_project_creation, current_user, default_enabled: :yaml) - - apply_lookahead(Groups::UserGroupsFinder.new(current_user, object, args).execute) + def ready?(**args) + Feature.enabled?(:paginatable_namespace_drop_down_for_project_creation, current_user, default_enabled: :yaml) end private - def preloads - { - path: [:route], - full_path: [:route] - } + def resolve_groups(**args) + Groups::UserGroupsFinder.new(current_user, object, args).execute end end end |