diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2020-09-19 04:45:44 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2020-09-19 04:45:44 +0300 |
commit | 85dc423f7090da0a52c73eb66faf22ddb20efff9 (patch) | |
tree | 9160f299afd8c80c038f08e1545be119f5e3f1e1 /app/graphql/types | |
parent | 15c2c8c66dbe422588e5411eee7e68f1fa440bb8 (diff) |
Add latest changes from gitlab-org/gitlab@13-4-stable-ee
Diffstat (limited to 'app/graphql/types')
44 files changed, 359 insertions, 59 deletions
diff --git a/app/graphql/types/admin/analytics/instance_statistics/measurement_identifier_enum.rb b/app/graphql/types/admin/analytics/instance_statistics/measurement_identifier_enum.rb new file mode 100644 index 00000000000..13c67442c2e --- /dev/null +++ b/app/graphql/types/admin/analytics/instance_statistics/measurement_identifier_enum.rb @@ -0,0 +1,21 @@ +# frozen_string_literal: true + +module Types + module Admin + module Analytics + module InstanceStatistics + class MeasurementIdentifierEnum < BaseEnum + graphql_name 'MeasurementIdentifier' + description 'Possible identifier types for a measurement' + + value 'PROJECTS', 'Project count', value: :projects + value 'USERS', 'User count', value: :users + value 'ISSUES', 'Issue count', value: :issues + value 'MERGE_REQUESTS', 'Merge request count', value: :merge_requests + value 'GROUPS', 'Group count', value: :groups + value 'PIPELINES', 'Pipeline count', value: :pipelines + end + end + end + end +end diff --git a/app/graphql/types/admin/analytics/instance_statistics/measurement_type.rb b/app/graphql/types/admin/analytics/instance_statistics/measurement_type.rb new file mode 100644 index 00000000000..d45341077a4 --- /dev/null +++ b/app/graphql/types/admin/analytics/instance_statistics/measurement_type.rb @@ -0,0 +1,24 @@ +# frozen_string_literal: true +# rubocop:disable Graphql/AuthorizeTypes + +module Types + module Admin + module Analytics + module InstanceStatistics + class MeasurementType < BaseObject + graphql_name 'InstanceStatisticsMeasurement' + description 'Represents a recorded measurement (object count) for the Admins' + + field :recorded_at, Types::TimeType, null: true, + description: 'The time the measurement was recorded' + + field :count, GraphQL::INT_TYPE, null: false, + description: 'Object count' + + field :identifier, Types::Admin::Analytics::InstanceStatistics::MeasurementIdentifierEnum, null: false, + description: 'The type of objects being measured' + end + end + end + end +end diff --git a/app/graphql/types/admin/sidekiq_queues/delete_jobs_response_type.rb b/app/graphql/types/admin/sidekiq_queues/delete_jobs_response_type.rb index 69af9d463bb..93dd49b3c38 100644 --- a/app/graphql/types/admin/sidekiq_queues/delete_jobs_response_type.rb +++ b/app/graphql/types/admin/sidekiq_queues/delete_jobs_response_type.rb @@ -7,7 +7,7 @@ module Types # a plain hash. class DeleteJobsResponseType < BaseObject # rubocop:disable Graphql/AuthorizeTypes graphql_name 'DeleteJobsResponse' - description 'The response from the AdminSidekiqQueuesDeleteJobs mutation.' + description 'The response from the AdminSidekiqQueuesDeleteJobs mutation' field :completed, GraphQL::BOOLEAN_TYPE, diff --git a/app/graphql/types/alert_management/alert_type.rb b/app/graphql/types/alert_management/alert_type.rb index 1a0b0685ffe..2da97030b88 100644 --- a/app/graphql/types/alert_management/alert_type.rb +++ b/app/graphql/types/alert_management/alert_type.rb @@ -6,6 +6,8 @@ module Types graphql_name 'AlertManagementAlert' description "Describes an alert from the project's Alert Management" + present_using ::AlertManagement::AlertPresenter + implements(Types::Notes::NoteableType) authorize :read_alert_management_alert diff --git a/app/graphql/types/award_emojis/award_emoji_type.rb b/app/graphql/types/award_emojis/award_emoji_type.rb index 0247ec767c8..fe7affa50cc 100644 --- a/app/graphql/types/award_emojis/award_emoji_type.rb +++ b/app/graphql/types/award_emojis/award_emoji_type.rb @@ -4,7 +4,7 @@ module Types module AwardEmojis class AwardEmojiType < BaseObject graphql_name 'AwardEmoji' - description 'An emoji awarded by a user.' + description 'An emoji awarded by a user' authorize :read_emoji diff --git a/app/graphql/types/base_enum.rb b/app/graphql/types/base_enum.rb index 94f6c47e876..159443641bc 100644 --- a/app/graphql/types/base_enum.rb +++ b/app/graphql/types/base_enum.rb @@ -2,9 +2,12 @@ module Types class BaseEnum < GraphQL::Schema::Enum + extend GitlabStyleDeprecations + class << self def value(*args, **kwargs, &block) enum[args[0].downcase] = kwargs[:value] || args[0] + kwargs = gitlab_deprecation(kwargs) super(*args, **kwargs, &block) end diff --git a/app/graphql/types/base_field.rb b/app/graphql/types/base_field.rb index c8ec4b3f897..1e72a4cddf5 100644 --- a/app/graphql/types/base_field.rb +++ b/app/graphql/types/base_field.rb @@ -3,6 +3,7 @@ module Types class BaseField < GraphQL::Schema::Field prepend Gitlab::Graphql::Authorize + include GitlabStyleDeprecations DEFAULT_COMPLEXITY = 1 @@ -12,11 +13,39 @@ module Types kwargs[:complexity] = field_complexity(kwargs[:resolver_class], kwargs[:complexity]) @feature_flag = kwargs[:feature_flag] kwargs = check_feature_flag(kwargs) - kwargs = handle_deprecated(kwargs) + kwargs = gitlab_deprecation(kwargs) super(*args, **kwargs, &block) end + # Based on https://github.com/rmosolgo/graphql-ruby/blob/v1.11.4/lib/graphql/schema/field.rb#L538-L563 + # Modified to fix https://github.com/rmosolgo/graphql-ruby/issues/3113 + def resolve_field(obj, args, ctx) + ctx.schema.after_lazy(obj) do |after_obj| + query_ctx = ctx.query.context + inner_obj = after_obj && after_obj.object + + ctx.schema.after_lazy(to_ruby_args(after_obj, args, ctx)) do |ruby_args| + if authorized?(inner_obj, ruby_args, query_ctx) + if @resolve_proc + # We pass `after_obj` here instead of `inner_obj` because extensions expect a GraphQL::Schema::Object + with_extensions(after_obj, ruby_args, query_ctx) do |extended_obj, extended_args| + # Since `extended_obj` is now a GraphQL::Schema::Object, we need to get the inner object and pass that to `@resolve_proc` + extended_obj = extended_obj.object if extended_obj.is_a?(GraphQL::Schema::Object) + + @resolve_proc.call(extended_obj, args, ctx) + end + else + public_send_field(after_obj, ruby_args, query_ctx) + end + else + err = GraphQL::UnauthorizedFieldError.new(object: inner_obj, type: obj.class, context: ctx, field: self) + query_ctx.schema.unauthorized_field(err) + end + end + end + end + def base_complexity complexity = DEFAULT_COMPLEXITY complexity += 1 if calls_gitaly? @@ -52,28 +81,6 @@ module Types args end - def handle_deprecated(kwargs) - if kwargs[:deprecation_reason].present? - raise ArgumentError, 'Use `deprecated` property instead of `deprecation_reason`. ' \ - 'See https://docs.gitlab.com/ee/development/api_graphql_styleguide.html#deprecating-fields' - end - - deprecation = kwargs.delete(:deprecated) - return kwargs unless deprecation - - milestone, reason = deprecation.values_at(:milestone, :reason).map(&:presence) - - raise ArgumentError, 'Please provide a `milestone` within `deprecated`' unless milestone - raise ArgumentError, 'Please provide a `reason` within `deprecated`' unless reason - raise ArgumentError, '`milestone` must be a `String`' unless milestone.is_a?(String) - - deprecated_in = "Deprecated in #{milestone}" - kwargs[:deprecation_reason] = "#{reason}. #{deprecated_in}" - kwargs[:description] += ". #{deprecated_in}: #{reason}" if kwargs[:description] - - kwargs - end - def field_complexity(resolver_class, current) return current if current.present? && current > 0 diff --git a/app/graphql/types/board_list_type.rb b/app/graphql/types/board_list_type.rb index 70c0794fc90..24faf1fe8bc 100644 --- a/app/graphql/types/board_list_type.rb +++ b/app/graphql/types/board_list_type.rb @@ -41,7 +41,7 @@ module Types list = self.object user = context[:current_user] - Boards::Issues::ListService + ::Boards::Issues::ListService .new(list.board.resource_parent, user, board_id: list.board_id, id: list.id) .metadata end diff --git a/app/graphql/types/boards/board_issue_input_base_type.rb b/app/graphql/types/boards/board_issue_input_base_type.rb new file mode 100644 index 00000000000..1187b3352cd --- /dev/null +++ b/app/graphql/types/boards/board_issue_input_base_type.rb @@ -0,0 +1,35 @@ +# frozen_string_literal: true + +module Types + module Boards + # rubocop: disable Graphql/AuthorizeTypes + class BoardIssueInputBaseType < BaseInputObject + argument :label_name, GraphQL::STRING_TYPE.to_list_type, + required: false, + description: 'Filter by label name' + + argument :milestone_title, GraphQL::STRING_TYPE, + required: false, + description: 'Filter by milestone title' + + argument :assignee_username, GraphQL::STRING_TYPE.to_list_type, + required: false, + description: 'Filter by assignee username' + + argument :author_username, GraphQL::STRING_TYPE, + required: false, + description: 'Filter by author username' + + argument :release_tag, GraphQL::STRING_TYPE, + required: false, + description: 'Filter by release tag' + + argument :my_reaction_emoji, GraphQL::STRING_TYPE, + required: false, + description: 'Filter by reaction emoji' + end + # rubocop: enable Graphql/AuthorizeTypes + end +end + +Types::Boards::BoardIssueInputBaseType.prepend_if_ee('::EE::Types::Boards::BoardIssueInputBaseType') diff --git a/app/graphql/types/boards/board_issue_input_type.rb b/app/graphql/types/boards/board_issue_input_type.rb new file mode 100644 index 00000000000..40d065d8ea9 --- /dev/null +++ b/app/graphql/types/boards/board_issue_input_type.rb @@ -0,0 +1,24 @@ +# frozen_string_literal: true + +module Types + module Boards + # rubocop: disable Graphql/AuthorizeTypes + class NegatedBoardIssueInputType < BoardIssueInputBaseType + end + + class BoardIssueInputType < BoardIssueInputBaseType + graphql_name 'BoardIssueInput' + + argument :not, NegatedBoardIssueInputType, + required: false, + description: 'List of negated params. Warning: this argument is experimental and a subject to change in future' + + argument :search, GraphQL::STRING_TYPE, + required: false, + description: 'Search query for issue title or description' + end + # rubocop: enable Graphql/AuthorizeTypes + end +end + +Types::Boards::BoardIssueInputType.prepend_if_ee('::EE::Types::Boards::BoardIssueInputType') diff --git a/app/graphql/types/ci/pipeline_config_source_enum.rb b/app/graphql/types/ci/pipeline_config_source_enum.rb index 48f88c133b4..e1575cb2f99 100644 --- a/app/graphql/types/ci/pipeline_config_source_enum.rb +++ b/app/graphql/types/ci/pipeline_config_source_enum.rb @@ -3,7 +3,7 @@ module Types module Ci class PipelineConfigSourceEnum < BaseEnum - ::Ci::PipelineEnums.config_sources.keys.each do |state_symbol| + ::Enums::Ci::Pipeline.config_sources.keys.each do |state_symbol| value state_symbol.to_s.upcase, value: state_symbol.to_s end end diff --git a/app/graphql/types/ci/pipeline_type.rb b/app/graphql/types/ci/pipeline_type.rb index 82a9f8495ce..c508b746317 100644 --- a/app/graphql/types/ci/pipeline_type.rb +++ b/app/graphql/types/ci/pipeline_type.rb @@ -26,7 +26,7 @@ module Types description: 'Detailed status of the pipeline', resolve: -> (obj, _args, ctx) { obj.detailed_status(ctx[:current_user]) } field :config_source, PipelineConfigSourceEnum, null: true, - description: "Config source of the pipeline (#{::Ci::PipelineEnums.config_sources.keys.join(', ').upcase})" + description: "Config source of the pipeline (#{::Enums::Ci::Pipeline.config_sources.keys.join(', ').upcase})" field :duration, GraphQL::INT_TYPE, null: true, description: 'Duration of the pipeline in seconds' field :coverage, GraphQL::FLOAT_TYPE, null: true, @@ -48,6 +48,14 @@ module Types field :user, Types::UserType, null: true, description: 'Pipeline user', resolve: -> (pipeline, _args, _context) { Gitlab::Graphql::Loaders::BatchModelLoader.new(User, pipeline.user_id).find } + field :retryable, GraphQL::BOOLEAN_TYPE, + description: 'Specifies if a pipeline can be retried', + method: :retryable?, + null: false + field :cancelable, GraphQL::BOOLEAN_TYPE, + description: 'Specifies if a pipeline can be canceled', + method: :cancelable?, + null: false end end end diff --git a/app/graphql/types/concerns/gitlab_style_deprecations.rb b/app/graphql/types/concerns/gitlab_style_deprecations.rb new file mode 100644 index 00000000000..2c932f4214b --- /dev/null +++ b/app/graphql/types/concerns/gitlab_style_deprecations.rb @@ -0,0 +1,31 @@ +# frozen_string_literal: true + +# Concern for handling deprecation arguments. +# https://docs.gitlab.com/ee/development/api_graphql_styleguide.html#deprecating-fields-and-enum-values +module GitlabStyleDeprecations + extend ActiveSupport::Concern + + private + + def gitlab_deprecation(kwargs) + if kwargs[:deprecation_reason].present? + raise ArgumentError, 'Use `deprecated` property instead of `deprecation_reason`. ' \ + 'See https://docs.gitlab.com/ee/development/api_graphql_styleguide.html#deprecating-fields-and-enum-values' + end + + deprecation = kwargs.delete(:deprecated) + return kwargs unless deprecation + + milestone, reason = deprecation.values_at(:milestone, :reason).map(&:presence) + + raise ArgumentError, 'Please provide a `milestone` within `deprecated`' unless milestone + raise ArgumentError, 'Please provide a `reason` within `deprecated`' unless reason + raise ArgumentError, '`milestone` must be a `String`' unless milestone.is_a?(String) + + deprecated_in = "Deprecated in #{milestone}" + kwargs[:deprecation_reason] = "#{reason}. #{deprecated_in}" + kwargs[:description] += ". #{deprecated_in}: #{reason}" if kwargs[:description] + + kwargs + end +end diff --git a/app/graphql/types/current_user_todos.rb b/app/graphql/types/current_user_todos.rb new file mode 100644 index 00000000000..e610286c1a9 --- /dev/null +++ b/app/graphql/types/current_user_todos.rb @@ -0,0 +1,24 @@ +# frozen_string_literal: true + +# Interface to expose todos for the current_user on the `object` +module Types + module CurrentUserTodos + include BaseInterface + + field_class Types::BaseField + + field :current_user_todos, Types::TodoType.connection_type, + description: 'Todos for the current user', + null: false do + argument :state, Types::TodoStateEnum, + description: 'State of the todos', + required: false + end + + def current_user_todos(state: nil) + state ||= %i(done pending) # TodosFinder treats a `nil` state param as `pending` + + TodosFinder.new(current_user, state: state, type: object.class.name, target_id: object.id).execute + end + end +end diff --git a/app/graphql/types/design_management/design_at_version_type.rb b/app/graphql/types/design_management/design_at_version_type.rb index 343d4cf4ff4..e10a0de1715 100644 --- a/app/graphql/types/design_management/design_at_version_type.rb +++ b/app/graphql/types/design_management/design_at_version_type.rb @@ -6,7 +6,7 @@ module Types graphql_name 'DesignAtVersion' description 'A design pinned to a specific version. ' \ - 'The image field reflects the design as of the associated version.' + 'The image field reflects the design as of the associated version' authorize :read_design @@ -23,7 +23,7 @@ module Types field :design, Types::DesignManagement::DesignType, null: false, - description: 'The underlying design.' + description: 'The underlying design' def cached_stateful_version(_parent) version diff --git a/app/graphql/types/design_management/design_collection_type.rb b/app/graphql/types/design_management/design_collection_type.rb index 194910831c6..904fb270e11 100644 --- a/app/graphql/types/design_management/design_collection_type.rb +++ b/app/graphql/types/design_management/design_collection_type.rb @@ -4,7 +4,7 @@ module Types module DesignManagement class DesignCollectionType < BaseObject graphql_name 'DesignCollection' - description 'A collection of designs.' + description 'A collection of designs' authorize :read_design diff --git a/app/graphql/types/design_management/design_type.rb b/app/graphql/types/design_management/design_type.rb index 3c84dc151bd..4e11a7aaf09 100644 --- a/app/graphql/types/design_management/design_type.rb +++ b/app/graphql/types/design_management/design_type.rb @@ -12,6 +12,7 @@ module Types implements(Types::Notes::NoteableType) implements(Types::DesignManagement::DesignFields) + implements(Types::CurrentUserTodos) field :versions, Types::DesignManagement::VersionType.connection_type, diff --git a/app/graphql/types/error_tracking/sentry_detailed_error_type.rb b/app/graphql/types/error_tracking/sentry_detailed_error_type.rb index 8bdd8afcbff..cfde9fa0d6a 100644 --- a/app/graphql/types/error_tracking/sentry_detailed_error_type.rb +++ b/app/graphql/types/error_tracking/sentry_detailed_error_type.rb @@ -4,7 +4,7 @@ module Types module ErrorTracking class SentryDetailedErrorType < ::Types::BaseObject graphql_name 'SentryDetailedError' - description 'A Sentry error.' + description 'A Sentry error' present_using SentryErrorPresenter diff --git a/app/graphql/types/error_tracking/sentry_error_collection_type.rb b/app/graphql/types/error_tracking/sentry_error_collection_type.rb index f423fcb1b9f..798e0433d06 100644 --- a/app/graphql/types/error_tracking/sentry_error_collection_type.rb +++ b/app/graphql/types/error_tracking/sentry_error_collection_type.rb @@ -4,7 +4,7 @@ module Types module ErrorTracking class SentryErrorCollectionType < ::Types::BaseObject graphql_name 'SentryErrorCollection' - description 'An object containing a collection of Sentry errors, and a detailed error.' + description 'An object containing a collection of Sentry errors, and a detailed error' authorize :read_sentry_issue @@ -21,7 +21,7 @@ module Types required: false argument :sort, String, - description: 'Attribute to sort on. Options are frequency, first_seen, last_seen. last_seen is default.', + description: 'Attribute to sort on. Options are frequency, first_seen, last_seen. last_seen is default', required: false end field :detailed_error, Types::ErrorTracking::SentryDetailedErrorType, diff --git a/app/graphql/types/error_tracking/sentry_error_stack_trace_entry_type.rb b/app/graphql/types/error_tracking/sentry_error_stack_trace_entry_type.rb index 0747e41e9fb..2e6c40b233b 100644 --- a/app/graphql/types/error_tracking/sentry_error_stack_trace_entry_type.rb +++ b/app/graphql/types/error_tracking/sentry_error_stack_trace_entry_type.rb @@ -5,7 +5,7 @@ module Types # rubocop: disable Graphql/AuthorizeTypes class SentryErrorStackTraceEntryType < ::Types::BaseObject graphql_name 'SentryErrorStackTraceEntry' - description 'An object containing a stack trace entry for a Sentry error.' + description 'An object containing a stack trace entry for a Sentry error' field :function, GraphQL::STRING_TYPE, null: true, diff --git a/app/graphql/types/error_tracking/sentry_error_stack_trace_type.rb b/app/graphql/types/error_tracking/sentry_error_stack_trace_type.rb index 0e6105d1ff2..1bbe7e0c77b 100644 --- a/app/graphql/types/error_tracking/sentry_error_stack_trace_type.rb +++ b/app/graphql/types/error_tracking/sentry_error_stack_trace_type.rb @@ -4,7 +4,7 @@ module Types module ErrorTracking class SentryErrorStackTraceType < ::Types::BaseObject graphql_name 'SentryErrorStackTrace' - description 'An object containing a stack trace entry for a Sentry error.' + description 'An object containing a stack trace entry for a Sentry error' authorize :read_sentry_issue diff --git a/app/graphql/types/error_tracking/sentry_error_type.rb b/app/graphql/types/error_tracking/sentry_error_type.rb index 7a842025e45..693ab0c4f8f 100644 --- a/app/graphql/types/error_tracking/sentry_error_type.rb +++ b/app/graphql/types/error_tracking/sentry_error_type.rb @@ -5,7 +5,7 @@ module Types # rubocop: disable Graphql/AuthorizeTypes class SentryErrorType < ::Types::BaseObject graphql_name 'SentryError' - description 'A Sentry error. A simplified version of SentryDetailedError.' + description 'A Sentry error. A simplified version of SentryDetailedError' present_using SentryErrorPresenter diff --git a/app/graphql/types/group_member_type.rb b/app/graphql/types/group_member_type.rb index ffffa3247db..6cca0a50647 100644 --- a/app/graphql/types/group_member_type.rb +++ b/app/graphql/types/group_member_type.rb @@ -8,7 +8,7 @@ module Types implements MemberInterface graphql_name 'GroupMember' - description 'Represents a Group Member' + description 'Represents a Group Membership' field :group, Types::GroupType, null: true, description: 'Group that a User is a member of', diff --git a/app/graphql/types/group_type.rb b/app/graphql/types/group_type.rb index cc8cd7c01f9..60b2e3c7b6e 100644 --- a/app/graphql/types/group_type.rb +++ b/app/graphql/types/group_type.rb @@ -75,6 +75,12 @@ module Types description: 'Title of the label' end + field :group_members, + Types::GroupMemberType.connection_type, + description: 'A membership of a user within this group', + extras: [:lookahead], + resolver: Resolvers::GroupMembersResolver + def label(title:) BatchLoader::GraphQL.for(title).batch(key: group) do |titles, loader, args| LabelsFinder diff --git a/app/graphql/types/issuable_severity_enum.rb b/app/graphql/types/issuable_severity_enum.rb new file mode 100644 index 00000000000..563965d991e --- /dev/null +++ b/app/graphql/types/issuable_severity_enum.rb @@ -0,0 +1,12 @@ +# frozen_string_literal: true + +module Types + class IssuableSeverityEnum < BaseEnum + graphql_name 'IssuableSeverity' + description 'Incident severity' + + ::IssuableSeverity.severities.keys.each do |severity| + value severity.upcase, value: severity, description: "#{severity.titleize} severity" + end + end +end diff --git a/app/graphql/types/issue_status_counts_type.rb b/app/graphql/types/issue_status_counts_type.rb index f2b1ba8e655..77429f9ea12 100644 --- a/app/graphql/types/issue_status_counts_type.rb +++ b/app/graphql/types/issue_status_counts_type.rb @@ -3,7 +3,7 @@ module Types class IssueStatusCountsType < BaseObject graphql_name 'IssueStatusCountsType' - description "Represents total number of issues for the represented statuses." + description 'Represents total number of issues for the represented statuses' authorize :read_issue diff --git a/app/graphql/types/issue_type.rb b/app/graphql/types/issue_type.rb index 0a73ce95424..d6253f74ce5 100644 --- a/app/graphql/types/issue_type.rb +++ b/app/graphql/types/issue_type.rb @@ -7,6 +7,7 @@ module Types connection_type_class(Types::CountableConnectionType) implements(Types::Notes::NoteableType) + implements(Types::CurrentUserTodos) authorize :read_issue @@ -38,12 +39,10 @@ module Types description: 'User that created the issue', resolve: -> (obj, _args, _ctx) { Gitlab::Graphql::Loaders::BatchModelLoader.new(User, obj.author_id).find } - # Remove complexity when BatchLoader is used - field :assignees, Types::UserType.connection_type, null: true, complexity: 5, + field :assignees, Types::UserType.connection_type, null: true, description: 'Assignees of the issue' - # Remove complexity when BatchLoader is used - field :labels, Types::LabelType.connection_type, null: true, complexity: 5, + field :labels, Types::LabelType.connection_type, null: true, description: 'Labels of the issue' field :milestone, Types::MilestoneType, null: true, description: 'Milestone of the issue', @@ -101,6 +100,14 @@ module Types field :type, Types::IssueTypeEnum, null: true, method: :issue_type, description: 'Type of the issue' + + field :alert_management_alert, + Types::AlertManagement::AlertType, + null: true, + description: 'Alert associated to this issue' + + field :severity, Types::IssuableSeverityEnum, null: true, + description: 'Severity level of the incident' end end diff --git a/app/graphql/types/jira_user_type.rb b/app/graphql/types/jira_user_type.rb index 999526a920e..394820d23be 100644 --- a/app/graphql/types/jira_user_type.rb +++ b/app/graphql/types/jira_user_type.rb @@ -7,7 +7,7 @@ module Types graphql_name 'JiraUser' field :jira_account_id, GraphQL::STRING_TYPE, null: false, - description: 'Account id of the Jira user' + description: 'Account ID of the Jira user' field :jira_display_name, GraphQL::STRING_TYPE, null: false, description: 'Display name of the Jira user' field :jira_email, GraphQL::STRING_TYPE, null: true, diff --git a/app/graphql/types/member_interface.rb b/app/graphql/types/member_interface.rb index 976836221bc..615a45413cb 100644 --- a/app/graphql/types/member_interface.rb +++ b/app/graphql/types/member_interface.rb @@ -4,6 +4,9 @@ module Types module MemberInterface include BaseInterface + field :id, GraphQL::ID_TYPE, null: false, + description: 'ID of the member' + field :access_level, Types::AccessLevelType, null: true, description: 'GitLab::Access level' @@ -18,5 +21,21 @@ module Types field :expires_at, Types::TimeType, null: true, description: 'Date and time the membership expires' + + field :user, Types::UserType, null: false, + description: 'User that is associated with the member object' + + definition_methods do + def resolve_type(object, context) + case object + when GroupMember + Types::GroupMemberType + when ProjectMember + Types::ProjectMemberType + else + raise ::Gitlab::Graphql::Errors::BaseError, "Unknown member type #{object.class.name}" + end + end + end end end diff --git a/app/graphql/types/merge_request_sort_enum.rb b/app/graphql/types/merge_request_sort_enum.rb new file mode 100644 index 00000000000..c64ae367a76 --- /dev/null +++ b/app/graphql/types/merge_request_sort_enum.rb @@ -0,0 +1,11 @@ +# frozen_string_literal: true + +module Types + class MergeRequestSortEnum < IssuableSortEnum + graphql_name 'MergeRequestSort' + description 'Values for sorting merge requests' + + value 'MERGED_AT_ASC', 'Merge time by ascending order', value: :merged_at_asc + value 'MERGED_AT_DESC', 'Merge time by descending order', value: :merged_at_desc + end +end diff --git a/app/graphql/types/merge_request_type.rb b/app/graphql/types/merge_request_type.rb index 01b02b7976f..56c88491684 100644 --- a/app/graphql/types/merge_request_type.rb +++ b/app/graphql/types/merge_request_type.rb @@ -7,6 +7,7 @@ module Types connection_type_class(Types::CountableConnectionType) implements(Types::Notes::NoteableType) + implements(Types::CurrentUserTodos) authorize :read_merge_request @@ -79,7 +80,7 @@ module Types description: 'Error message due to a merge error' field :allow_collaboration, GraphQL::BOOLEAN_TYPE, null: true, description: 'Indicates if members of the target project can push to the fork' - field :should_be_rebased, GraphQL::BOOLEAN_TYPE, method: :should_be_rebased?, null: false, + field :should_be_rebased, GraphQL::BOOLEAN_TYPE, method: :should_be_rebased?, null: false, calls_gitaly: true, description: 'Indicates if the merge request will be rebased' field :rebase_commit_sha, GraphQL::STRING_TYPE, null: true, description: 'Rebase commit SHA of the merge request' @@ -112,6 +113,7 @@ module Types field :head_pipeline, Types::Ci::PipelineType, null: true, method: :actual_head_pipeline, description: 'The pipeline running on the branch HEAD of the merge request' field :pipelines, Types::Ci::PipelineType.connection_type, + null: true, description: 'Pipelines for the merge request', resolver: Resolvers::MergeRequestPipelinesResolver @@ -145,6 +147,10 @@ module Types description: Types::TaskCompletionStatus.description field :commit_count, GraphQL::INT_TYPE, null: true, description: 'Number of commits in the merge request' + field :conflicts, GraphQL::BOOLEAN_TYPE, null: false, method: :cannot_be_merged?, + description: 'Indicates if the merge request has conflicts' + field :auto_merge_enabled, GraphQL::BOOLEAN_TYPE, null: false, + description: 'Indicates if auto merge is enabled for the merge request' def diff_stats(path: nil) stats = Array.wrap(object.diff_stats&.to_a) diff --git a/app/graphql/types/metrics/dashboard_type.rb b/app/graphql/types/metrics/dashboard_type.rb index bbcce2d9596..47502356773 100644 --- a/app/graphql/types/metrics/dashboard_type.rb +++ b/app/graphql/types/metrics/dashboard_type.rb @@ -16,6 +16,13 @@ module Types field :annotations, Types::Metrics::Dashboards::AnnotationType.connection_type, null: true, description: 'Annotations added to the dashboard', resolver: Resolvers::Metrics::Dashboards::AnnotationResolver + + # In order to maintain backward compatibility we need to return NULL when there are no warnings + # and dashboard validation returns an empty array when there are no issues. + def schema_validation_warnings + warnings = object.schema_validation_warnings + warnings unless warnings.empty? + end end # rubocop: enable Graphql/AuthorizeTypes end diff --git a/app/graphql/types/milestone_type.rb b/app/graphql/types/milestone_type.rb index ca606c9da44..8603043804e 100644 --- a/app/graphql/types/milestone_type.rb +++ b/app/graphql/types/milestone_type.rb @@ -3,7 +3,7 @@ module Types class MilestoneType < BaseObject graphql_name 'Milestone' - description 'Represents a milestone.' + description 'Represents a milestone' present_using MilestonePresenter @@ -60,3 +60,5 @@ module Types end end end + +Types::MilestoneType.prepend_if_ee('::EE::Types::MilestoneType') diff --git a/app/graphql/types/mutation_operation_mode_enum.rb b/app/graphql/types/mutation_operation_mode_enum.rb index 90a29d2b0e5..37e83e7a2e1 100644 --- a/app/graphql/types/mutation_operation_mode_enum.rb +++ b/app/graphql/types/mutation_operation_mode_enum.rb @@ -3,7 +3,7 @@ module Types class MutationOperationModeEnum < BaseEnum graphql_name 'MutationOperationMode' - description 'Different toggles for changing mutator behavior.' + description 'Different toggles for changing mutator behavior' # Suggested param name for the enum: `operation_mode` diff --git a/app/graphql/types/mutation_type.rb b/app/graphql/types/mutation_type.rb index e143d14676e..b2732d83aac 100644 --- a/app/graphql/types/mutation_type.rb +++ b/app/graphql/types/mutation_type.rb @@ -14,6 +14,7 @@ module Types mount_mutation Mutations::AwardEmojis::Add mount_mutation Mutations::AwardEmojis::Remove mount_mutation Mutations::AwardEmojis::Toggle + mount_mutation Mutations::Boards::Destroy mount_mutation Mutations::Boards::Issues::IssueMoveList mount_mutation Mutations::Boards::Lists::Create mount_mutation Mutations::Boards::Lists::Update @@ -24,6 +25,7 @@ module Types mount_mutation Mutations::Issues::SetConfidential mount_mutation Mutations::Issues::SetLocked mount_mutation Mutations::Issues::SetDueDate + mount_mutation Mutations::Issues::SetSeverity mount_mutation Mutations::Issues::SetSubscription mount_mutation Mutations::Issues::Update mount_mutation Mutations::MergeRequests::Create @@ -62,6 +64,9 @@ module Types mount_mutation Mutations::DesignManagement::Delete, calls_gitaly: true mount_mutation Mutations::DesignManagement::Move mount_mutation Mutations::ContainerExpirationPolicies::Update + mount_mutation Mutations::Ci::PipelineCancel + mount_mutation Mutations::Ci::PipelineDestroy + mount_mutation Mutations::Ci::PipelineRetry end end diff --git a/app/graphql/types/permission_types/merge_request.rb b/app/graphql/types/permission_types/merge_request.rb index 28b7ebd2af6..e9c89b0c92e 100644 --- a/app/graphql/types/permission_types/merge_request.rb +++ b/app/graphql/types/permission_types/merge_request.rb @@ -18,6 +18,10 @@ module Types PERMISSION_FIELDS.each do |field_name| permission_field field_name, method: :"can_#{field_name}?", calls_gitaly: true end + + permission_field :can_merge, calls_gitaly: true, resolve: -> (object, args, context) do + object.can_be_merged_by?(context[:current_user]) + end end end end diff --git a/app/graphql/types/project_member_type.rb b/app/graphql/types/project_member_type.rb index e9ccb51886b..f08781238d0 100644 --- a/app/graphql/types/project_member_type.rb +++ b/app/graphql/types/project_member_type.rb @@ -3,7 +3,7 @@ module Types class ProjectMemberType < BaseObject graphql_name 'ProjectMember' - description 'Represents a Project Member' + description 'Represents a Project Membership' expose_permissions Types::PermissionTypes::Project @@ -11,13 +11,6 @@ module Types authorize :read_project - field :id, GraphQL::ID_TYPE, null: false, - description: 'ID of the member' - - field :user, Types::UserType, null: false, - description: 'User that is associated with the member object', - resolve: -> (obj, _args, _ctx) { Gitlab::Graphql::Loaders::BatchModelLoader.new(User, obj.user_id).find } - field :project, Types::ProjectType, null: true, description: 'Project that User is a member of', resolve: -> (obj, _args, _ctx) { Gitlab::Graphql::Loaders::BatchModelLoader.new(Project, obj.source_id).find } diff --git a/app/graphql/types/project_type.rb b/app/graphql/types/project_type.rb index 5562db69de6..0fd54af1538 100644 --- a/app/graphql/types/project_type.rb +++ b/app/graphql/types/project_type.rb @@ -54,7 +54,7 @@ module Types field :container_registry_enabled, GraphQL::BOOLEAN_TYPE, null: true, description: 'Indicates if the project stores Docker container images in a container registry' field :shared_runners_enabled, GraphQL::BOOLEAN_TYPE, null: true, - description: 'Indicates if Shared Runners are enabled for the project' + description: 'Indicates if shared runners are enabled for the project' field :lfs_enabled, GraphQL::BOOLEAN_TYPE, null: true, description: 'Indicates if the project has Large File Storage (LFS) enabled' field :merge_requests_ff_only_enabled, GraphQL::BOOLEAN_TYPE, null: true, @@ -134,7 +134,7 @@ module Types null: true, description: 'Merge requests of the project', extras: [:lookahead], - resolver: Resolvers::MergeRequestsResolver + resolver: Resolvers::ProjectMergeRequestsResolver field :merge_request, Types::MergeRequestType, @@ -146,12 +146,14 @@ module Types Types::IssueType.connection_type, null: true, description: 'Issues of the project', + extras: [:lookahead], resolver: Resolvers::IssuesResolver field :issue_status_counts, Types::IssueStatusCountsType, null: true, description: 'Counts of issues by status for the project', + extras: [:lookahead], resolver: Resolvers::IssueStatusCountsResolver field :milestones, Types::MilestoneType.connection_type, null: true, @@ -159,7 +161,7 @@ module Types resolver: Resolvers::ProjectMilestonesResolver field :project_members, - Types::ProjectMemberType.connection_type, + Types::MemberInterface.connection_type, description: 'Members of the project', resolver: Resolvers::ProjectMembersResolver diff --git a/app/graphql/types/projects/namespace_project_sort_enum.rb b/app/graphql/types/projects/namespace_project_sort_enum.rb new file mode 100644 index 00000000000..1e13deb6508 --- /dev/null +++ b/app/graphql/types/projects/namespace_project_sort_enum.rb @@ -0,0 +1,12 @@ +# frozen_string_literal: true + +module Types + module Projects + class NamespaceProjectSortEnum < BaseEnum + graphql_name 'NamespaceProjectSort' + description 'Values for sorting projects' + + value 'SIMILARITY', 'Most similar to the search query', value: :similarity + end + end +end diff --git a/app/graphql/types/query_type.rb b/app/graphql/types/query_type.rb index c04f4da70cf..447ac63a294 100644 --- a/app/graphql/types/query_type.rb +++ b/app/graphql/types/query_type.rb @@ -70,9 +70,24 @@ module Types description: 'Text to echo back', resolver: Resolvers::EchoResolver + field :issue, Types::IssueType, + null: true, + description: 'Find an issue' do + argument :id, ::Types::GlobalIDType[::Issue], required: true, description: 'The global ID of the Issue' + end + + field :instance_statistics_measurements, Types::Admin::Analytics::InstanceStatistics::MeasurementType.connection_type, + null: true, + description: 'Get statistics on the instance', + resolver: Resolvers::Admin::Analytics::InstanceStatistics::MeasurementsResolver + def design_management DesignManagementObject.new(nil) end + + def issue(id:) + GitlabSchema.object_from_id(id, expected_type: ::Issue) + end end end diff --git a/app/graphql/types/release_asset_link_type.rb b/app/graphql/types/release_asset_link_type.rb index 21f1bd50cff..0e519ece791 100644 --- a/app/graphql/types/release_asset_link_type.rb +++ b/app/graphql/types/release_asset_link_type.rb @@ -17,5 +17,17 @@ module Types description: 'Type of the link: `other`, `runbook`, `image`, `package`; defaults to `other`' field :external, GraphQL::BOOLEAN_TYPE, null: true, method: :external?, description: 'Indicates the link points to an external resource' + + field :direct_asset_url, GraphQL::STRING_TYPE, null: true, + description: 'Direct asset URL of the link' + + def direct_asset_url + return object.url unless object.filepath + + release = object.release + project = release.project + + Gitlab::Routing.url_helpers.project_release_url(project, release) << object.filepath + end end end diff --git a/app/graphql/types/release_type.rb b/app/graphql/types/release_type.rb index a0703b96a36..b715b981483 100644 --- a/app/graphql/types/release_type.rb +++ b/app/graphql/types/release_type.rb @@ -5,6 +5,8 @@ module Types graphql_name 'Release' description 'Represents a release' + connection_type_class(Types::CountableConnectionType) + authorize :read_release alias_method :release, :object @@ -26,6 +28,8 @@ module Types description: 'Timestamp of when the release was created' field :released_at, Types::TimeType, null: true, description: 'Timestamp of when the release was released' + field :upcoming_release, GraphQL::BOOLEAN_TYPE, null: true, method: :upcoming_release?, + description: 'Indicates the release is an upcoming release' field :assets, Types::ReleaseAssetsType, null: true, method: :itself, description: 'Assets of the release' field :links, Types::ReleaseLinksType, null: true, method: :itself, diff --git a/app/graphql/types/todo_type.rb b/app/graphql/types/todo_type.rb index 08e7fabeb74..4f21da3d897 100644 --- a/app/graphql/types/todo_type.rb +++ b/app/graphql/types/todo_type.rb @@ -26,7 +26,7 @@ module Types resolve: -> (todo, args, context) { Gitlab::Graphql::Loaders::BatchModelLoader.new(Group, todo.group_id).find } field :author, Types::UserType, - description: 'The owner of this todo', + description: 'The author of this todo', null: false, resolve: -> (todo, args, context) { Gitlab::Graphql::Loaders::BatchModelLoader.new(User, todo.author_id).find } diff --git a/app/graphql/types/user_type.rb b/app/graphql/types/user_type.rb index cb3575b41d1..8047708776d 100644 --- a/app/graphql/types/user_type.rb +++ b/app/graphql/types/user_type.rb @@ -37,6 +37,9 @@ module Types field :project_memberships, Types::ProjectMemberType.connection_type, null: true, description: 'Project memberships of the user', method: :project_members + field :starred_projects, Types::ProjectType.connection_type, null: true, + description: 'Projects starred by the user', + resolver: Resolvers::UserStarredProjectsResolver # Merge request field: MRs can be either authored or assigned: field :authored_merge_requests, Types::MergeRequestType.connection_type, null: true, |