diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2021-03-16 18:18:33 +0000 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2021-03-16 18:18:33 +0000 |
commit | f64a639bcfa1fc2bc89ca7db268f594306edfd7c (patch) | |
tree | a2c3c2ebcc3b45e596949db485d6ed18ffaacfa1 /app/graphql | |
parent | bfbc3e0d6583ea1a91f627528bedc3d65ba4b10f (diff) | |
download | gitlab-ce-f64a639bcfa1fc2bc89ca7db268f594306edfd7c.tar.gz |
Add latest changes from gitlab-org/gitlab@13-10-stable-eev13.10.0-rc40
Diffstat (limited to 'app/graphql')
118 files changed, 790 insertions, 370 deletions
diff --git a/app/graphql/gitlab_schema.rb b/app/graphql/gitlab_schema.rb index d66a2333d11..7ab5dc36e4a 100644 --- a/app/graphql/gitlab_schema.rb +++ b/app/graphql/gitlab_schema.rb @@ -13,8 +13,6 @@ class GitlabSchema < GraphQL::Schema use GraphQL::Pagination::Connections use BatchLoader::GraphQL use Gitlab::Graphql::Authorize - use Gitlab::Graphql::Present - use Gitlab::Graphql::CallsGitaly use Gitlab::Graphql::Pagination::Connections use Gitlab::Graphql::GenericTracing use Gitlab::Graphql::Timeout, max_seconds: Gitlab.config.gitlab.graphql_timeout diff --git a/app/graphql/mutations/boards/create.rb b/app/graphql/mutations/boards/create.rb index 92bce557446..003c4f7761b 100644 --- a/app/graphql/mutations/boards/create.rb +++ b/app/graphql/mutations/boards/create.rb @@ -14,7 +14,7 @@ module Mutations null: true, description: 'The board after mutation.' - authorize :admin_board + authorize :admin_issue_board def resolve(args) board_parent = authorized_resource_parent_find!(args) @@ -22,7 +22,7 @@ module Mutations response = ::Boards::CreateService.new(board_parent, current_user, args).execute { - board: response.payload, + board: response.success? ? response.payload : nil, errors: response.errors } end diff --git a/app/graphql/mutations/boards/destroy.rb b/app/graphql/mutations/boards/destroy.rb index 8ec13b885d5..4a0068edee2 100644 --- a/app/graphql/mutations/boards/destroy.rb +++ b/app/graphql/mutations/boards/destroy.rb @@ -14,7 +14,7 @@ module Mutations required: true, description: 'The global ID of the board to destroy.' - authorize :admin_board + authorize :admin_issue_board def resolve(id:) board = authorized_find!(id: id) diff --git a/app/graphql/mutations/boards/issues/issue_move_list.rb b/app/graphql/mutations/boards/issues/issue_move_list.rb index 91dfd9fc3e9..096ac89db1c 100644 --- a/app/graphql/mutations/boards/issues/issue_move_list.rb +++ b/app/graphql/mutations/boards/issues/issue_move_list.rb @@ -5,35 +5,38 @@ module Mutations module Issues class IssueMoveList < Mutations::Issues::Base graphql_name 'IssueMoveList' + BoardGID = ::Types::GlobalIDType[::Board] + ListID = ::GraphQL::ID_TYPE + IssueID = ::GraphQL::ID_TYPE - argument :board_id, GraphQL::ID_TYPE, - required: true, - loads: Types::BoardType, - description: 'Global ID of the board that the issue is in.' + argument :board_id, BoardGID, + required: true, + loads: Types::BoardType, + description: 'Global ID of the board that the issue is in.' argument :project_path, GraphQL::ID_TYPE, - required: true, - description: 'Project the issue to mutate is in.' + required: true, + description: 'Project the issue to mutate is in.' argument :iid, GraphQL::STRING_TYPE, - required: true, - description: 'IID of the issue to mutate.' + required: true, + description: 'IID of the issue to mutate.' - argument :from_list_id, GraphQL::ID_TYPE, - required: false, - description: 'ID of the board list that the issue will be moved from.' + argument :from_list_id, ListID, + required: false, + description: 'ID of the board list that the issue will be moved from.' - argument :to_list_id, GraphQL::ID_TYPE, - required: false, - description: 'ID of the board list that the issue will be moved to.' + argument :to_list_id, ListID, + required: false, + description: 'ID of the board list that the issue will be moved to.' - argument :move_before_id, GraphQL::ID_TYPE, - required: false, - description: 'ID of issue that should be placed before the current issue.' + argument :move_before_id, IssueID, + required: false, + description: 'ID of issue that should be placed before the current issue.' - argument :move_after_id, GraphQL::ID_TYPE, - required: false, - description: 'ID of issue that should be placed after the current issue.' + argument :move_after_id, IssueID, + required: false, + description: 'ID of issue that should be placed after the current issue.' def ready?(**args) if move_arguments(args).blank? @@ -83,7 +86,7 @@ module Mutations end def authorize_board!(board) - return if Ability.allowed?(current_user, :read_board, board.resource_parent) + return if Ability.allowed?(current_user, :read_issue_board, board.resource_parent) raise_resource_not_available_error! end diff --git a/app/graphql/mutations/boards/lists/create.rb b/app/graphql/mutations/boards/lists/create.rb index f3aae9ac9c8..673fa95fc56 100644 --- a/app/graphql/mutations/boards/lists/create.rb +++ b/app/graphql/mutations/boards/lists/create.rb @@ -15,7 +15,7 @@ module Mutations null: true, description: 'Issue list in the issue board.' - authorize :admin_list + authorize :admin_issue_board_list private diff --git a/app/graphql/mutations/boards/lists/destroy.rb b/app/graphql/mutations/boards/lists/destroy.rb index 61ffae7c047..a50b5f73455 100644 --- a/app/graphql/mutations/boards/lists/destroy.rb +++ b/app/graphql/mutations/boards/lists/destroy.rb @@ -33,7 +33,7 @@ module Mutations def can_admin_list?(list) return false unless list.present? - Ability.allowed?(current_user, :admin_list, list.board) + Ability.allowed?(current_user, :admin_issue_board_list, list.board) end end end diff --git a/app/graphql/mutations/boards/lists/update.rb b/app/graphql/mutations/boards/lists/update.rb index d30d1d89bb2..504082ec22c 100644 --- a/app/graphql/mutations/boards/lists/update.rb +++ b/app/graphql/mutations/boards/lists/update.rb @@ -17,7 +17,7 @@ module Mutations argument :collapsed, GraphQL::BOOLEAN_TYPE, required: false, - description: 'Indicates if list is collapsed for this user.' + description: 'Indicates if the list is collapsed for this user.' field :list, Types::BoardListType, @@ -44,7 +44,7 @@ module Mutations def can_read_list?(list) return false unless list.present? - Ability.allowed?(current_user, :read_list, list.board) + Ability.allowed?(current_user, :read_issue_board_list, list.board) end end end diff --git a/app/graphql/mutations/boards/update.rb b/app/graphql/mutations/boards/update.rb index b4f8179829e..628b3a3fadb 100644 --- a/app/graphql/mutations/boards/update.rb +++ b/app/graphql/mutations/boards/update.rb @@ -17,7 +17,7 @@ module Mutations null: true, description: 'The board after mutation.' - authorize :admin_board + authorize :admin_issue_board def resolve(id:, **args) board = authorized_find!(id: id) diff --git a/app/graphql/mutations/branches/create.rb b/app/graphql/mutations/branches/create.rb index 6354976f1ea..a94d3966258 100644 --- a/app/graphql/mutations/branches/create.rb +++ b/app/graphql/mutations/branches/create.rb @@ -30,8 +30,6 @@ module Mutations def resolve(project_path:, name:, ref:) project = authorized_find!(project_path) - context.scoped_set!(:branch_project, project) - result = ::Branches::CreateService.new(project, current_user) .execute(name, ref) diff --git a/app/graphql/mutations/concerns/mutations/can_mutate_spammable.rb b/app/graphql/mutations/concerns/mutations/can_mutate_spammable.rb index 2d4983f0d6e..ba644eff36c 100644 --- a/app/graphql/mutations/concerns/mutations/can_mutate_spammable.rb +++ b/app/graphql/mutations/concerns/mutations/can_mutate_spammable.rb @@ -5,6 +5,7 @@ module Mutations # and optionally support the workflow to allow clients to display and solve CAPTCHAs. module CanMutateSpammable extend ActiveSupport::Concern + include Spam::Concerns::HasSpamActionResponseFields # NOTE: The arguments and fields are intentionally named with 'captcha' instead of 'recaptcha', # so that they can be applied to future alternative CAPTCHA implementations other than @@ -59,25 +60,5 @@ module Mutations request: context[:request] } end - - # with_spam_action_fields(spammable) { {other_fields: true} } -> hash - # - # Takes a Spammable and a block as arguments. - # - # The block passed should be a hash, which the spam action fields will be merged into. - def with_spam_action_fields(spammable) - spam_action_fields = { - spam: spammable.spam?, - # NOTE: These fields are intentionally named with 'captcha' instead of 'recaptcha', so - # that they can be applied to future alternative CAPTCHA implementations other than - # reCAPTCHA (such as FriendlyCaptcha) without having to change the response field name - # in the API. - needs_captcha_response: spammable.render_recaptcha?, - spam_log_id: spammable.spam_log&.id, - captcha_site_key: Gitlab::CurrentSettings.recaptcha_site_key - } - - yield.merge(spam_action_fields) - end end end diff --git a/app/graphql/mutations/custom_emoji/create.rb b/app/graphql/mutations/custom_emoji/create.rb index 9ec96be0f26..5cf54f8f877 100644 --- a/app/graphql/mutations/custom_emoji/create.rb +++ b/app/graphql/mutations/custom_emoji/create.rb @@ -31,6 +31,7 @@ module Mutations group = authorized_find!(group_path: group_path) # See https://gitlab.com/gitlab-org/gitlab/-/merge_requests/37911#note_444682238 args[:external] = true + args[:creator] = current_user custom_emoji = group.custom_emoji.create(args) diff --git a/app/graphql/mutations/merge_requests/accept.rb b/app/graphql/mutations/merge_requests/accept.rb new file mode 100644 index 00000000000..540be7098ac --- /dev/null +++ b/app/graphql/mutations/merge_requests/accept.rb @@ -0,0 +1,88 @@ +# frozen_string_literal: true + +module Mutations + module MergeRequests + class Accept < Base + NOT_MERGEABLE = 'This branch cannot be merged' + HOOKS_VALIDATION_ERROR = 'Pre-merge hooks failed' + SHA_MISMATCH = 'The merge-head is not at the anticipated SHA' + MERGE_FAILED = 'The merge failed' + ALREADY_SCHEDULED = 'The merge request is already scheduled to be merged' + + graphql_name 'MergeRequestAccept' + authorize :accept_merge_request + description <<~DESC + Accepts a merge request. + When accepted, the source branch will be merged into the target branch, either + immediately if possible, or using one of the automatic merge strategies. + DESC + + argument :strategy, + ::Types::MergeStrategyEnum, + required: false, + as: :auto_merge_strategy, + description: 'How to merge this merge request.' + + argument :commit_message, ::GraphQL::STRING_TYPE, + required: false, + description: 'Custom merge commit message.' + argument :squash_commit_message, ::GraphQL::STRING_TYPE, + required: false, + description: 'Custom squash commit message (if squash is true).' + argument :sha, ::GraphQL::STRING_TYPE, + required: true, + description: 'The HEAD SHA at the time when this merge was requested.' + + argument :should_remove_source_branch, ::GraphQL::BOOLEAN_TYPE, + required: false, + description: 'Should the source branch be removed.' + argument :squash, ::GraphQL::BOOLEAN_TYPE, + required: false, + default_value: false, + description: 'Squash commits on the source branch before merge.' + + def resolve(project_path:, iid:, **args) + Gitlab::QueryLimiting.whitelist('https://gitlab.com/gitlab-org/gitlab-foss/issues/42317') + merge_request = authorized_find!(project_path: project_path, iid: iid) + project = merge_request.target_project + merge_params = args.compact.with_indifferent_access + merge_service = ::MergeRequests::MergeService.new(project, current_user, merge_params) + + if error = validate(merge_request, merge_service, merge_params) + return { merge_request: merge_request, errors: [error] } + end + + merge_request.update(merge_error: nil, squash: merge_params[:squash]) + + result = if merge_params.key?(:auto_merge_strategy) + service = AutoMergeService.new(project, current_user, merge_params) + service.execute(merge_request, merge_params[:auto_merge_strategy]) + else + merge_service.execute(merge_request) + end + + { + merge_request: merge_request, + errors: result == :failed ? [MERGE_FAILED] : [] + } + rescue ::MergeRequests::MergeBaseService::MergeError => e + { + merge_request: merge_request, + errors: [e.message] + } + end + + def validate(merge_request, merge_service, merge_params) + if merge_request.auto_merge_enabled? + ALREADY_SCHEDULED + elsif !merge_request.mergeable?(skip_ci_check: merge_params.key?(:auto_merge_strategy)) + NOT_MERGEABLE + elsif !merge_service.hooks_validation_pass?(merge_request) + HOOKS_VALIDATION_ERROR + elsif merge_params[:sha] != merge_request.diff_head_sha + SHA_MISMATCH + end + end + end + end +end diff --git a/app/graphql/mutations/merge_requests/set_wip.rb b/app/graphql/mutations/merge_requests/set_wip.rb index 0b5c20de377..beb042ce93f 100644 --- a/app/graphql/mutations/merge_requests/set_wip.rb +++ b/app/graphql/mutations/merge_requests/set_wip.rb @@ -9,7 +9,7 @@ module Mutations GraphQL::BOOLEAN_TYPE, required: true, description: <<~DESC - Whether or not to set the merge request as a WIP. + Whether or not to set the merge request as a draft. DESC def resolve(project_path:, iid:, wip: nil) diff --git a/app/graphql/mutations/notes/create/diff_note.rb b/app/graphql/mutations/notes/create/diff_note.rb index 9b5f3092006..019e7cb8623 100644 --- a/app/graphql/mutations/notes/create/diff_note.rb +++ b/app/graphql/mutations/notes/create/diff_note.rb @@ -11,6 +11,22 @@ module Mutations required: true, description: copy_field_description(Types::Notes::NoteType, :position) + def ready?(**args) + # As both arguments are optional, validate here that one of the + # arguments are present. + # + # This may be able to be done using InputUnions in the future + # if this RFC is merged: + # https://github.com/graphql/graphql-spec/blob/master/rfcs/InputUnion.md + + if args[:position].to_hash.values_at(:old_line, :new_line).compact.blank? + raise Gitlab::Graphql::Errors::ArgumentError, + 'position oldLine or newLine arguments are required' + end + + super(**args) + end + private def create_note_params(noteable, args) diff --git a/app/graphql/mutations/notes/update/base.rb b/app/graphql/mutations/notes/update/base.rb index 4edb7429b97..571001981a4 100644 --- a/app/graphql/mutations/notes/update/base.rb +++ b/app/graphql/mutations/notes/update/base.rb @@ -6,12 +6,18 @@ module Mutations # This is a Base class for the Note update mutations and is not # mounted as a GraphQL mutation itself. class Base < Mutations::Notes::Base + QUICK_ACTION_ONLY_WARNING = <<~NB + If the body of the Note contains only quick actions, + the Note will be destroyed during the update, and no Note will be + returned. + NB + authorize :admin_note argument :id, - ::Types::GlobalIDType[::Note], - required: true, - description: 'The global ID of the note to update.' + ::Types::GlobalIDType[::Note], + required: true, + description: 'The global ID of the note to update.' def resolve(args) note = authorized_find!(id: args[:id]) diff --git a/app/graphql/mutations/notes/update/image_diff_note.rb b/app/graphql/mutations/notes/update/image_diff_note.rb index f4533cd9edb..6160ee03f4e 100644 --- a/app/graphql/mutations/notes/update/image_diff_note.rb +++ b/app/graphql/mutations/notes/update/image_diff_note.rb @@ -5,16 +5,20 @@ module Mutations module Update class ImageDiffNote < Mutations::Notes::Update::Base graphql_name 'UpdateImageDiffNote' + description <<~DESC + Updates a DiffNote on an image (a `Note` where the `position.positionType` is `"image"`). + #{QUICK_ACTION_ONLY_WARNING} + DESC argument :body, - GraphQL::STRING_TYPE, - required: false, - description: copy_field_description(Types::Notes::NoteType, :body) + GraphQL::STRING_TYPE, + required: false, + description: copy_field_description(Types::Notes::NoteType, :body) argument :position, - Types::Notes::UpdateDiffImagePositionInputType, - required: false, - description: copy_field_description(Types::Notes::NoteType, :position) + Types::Notes::UpdateDiffImagePositionInputType, + required: false, + description: copy_field_description(Types::Notes::NoteType, :position) def ready?(**args) # As both arguments are optional, validate here that one of the @@ -34,10 +38,9 @@ module Mutations private def pre_update_checks!(note, _args) - unless note.is_a?(DiffNote) && note.position.on_image? - raise Gitlab::Graphql::Errors::ResourceNotAvailable, - 'Resource is not an ImageDiffNote' - end + return if note.is_a?(DiffNote) && note.position.on_image? + + raise Gitlab::Graphql::Errors::ResourceNotAvailable, 'Resource is not an ImageDiffNote' end def note_params(note, args) diff --git a/app/graphql/mutations/notes/update/note.rb b/app/graphql/mutations/notes/update/note.rb index 73b9b9bc49a..11d8c6e2cb9 100644 --- a/app/graphql/mutations/notes/update/note.rb +++ b/app/graphql/mutations/notes/update/note.rb @@ -5,16 +5,17 @@ module Mutations module Update class Note < Mutations::Notes::Update::Base graphql_name 'UpdateNote' + description "Updates a Note.\n#{QUICK_ACTION_ONLY_WARNING}" argument :body, - GraphQL::STRING_TYPE, - required: false, - description: copy_field_description(Types::Notes::NoteType, :body) + GraphQL::STRING_TYPE, + required: false, + description: copy_field_description(Types::Notes::NoteType, :body) argument :confidential, - GraphQL::BOOLEAN_TYPE, - required: false, - description: 'The confidentiality flag of a note. Default is false.' + GraphQL::BOOLEAN_TYPE, + required: false, + description: 'The confidentiality flag of a note. Default is false.' private diff --git a/app/graphql/mutations/release_asset_links/create.rb b/app/graphql/mutations/release_asset_links/create.rb new file mode 100644 index 00000000000..02704efb47c --- /dev/null +++ b/app/graphql/mutations/release_asset_links/create.rb @@ -0,0 +1,46 @@ +# frozen_string_literal: true + +module Mutations + module ReleaseAssetLinks + class Create < BaseMutation + include FindsProject + + graphql_name 'ReleaseAssetLinkCreate' + + authorize :create_release + + include Types::ReleaseAssetLinkSharedInputArguments + + argument :project_path, GraphQL::ID_TYPE, + required: true, + description: 'Full path of the project the asset link is associated with.' + + argument :tag_name, GraphQL::STRING_TYPE, + required: true, as: :tag, + description: "Name of the associated release's tag." + + field :link, + Types::ReleaseAssetLinkType, + null: true, + description: 'The asset link after mutation.' + + def resolve(project_path:, tag:, **link_attrs) + project = authorized_find!(project_path) + release = project.releases.find_by_tag(tag) + + if release.nil? + message = _('Release with tag "%{tag}" was not found') % { tag: tag } + return { link: nil, errors: [message] } + end + + new_link = release.links.create(link_attrs) + + unless new_link.persisted? + return { link: nil, errors: new_link.errors.full_messages } + end + + { link: new_link, errors: [] } + end + end + end +end diff --git a/app/graphql/mutations/release_asset_links/update.rb b/app/graphql/mutations/release_asset_links/update.rb new file mode 100644 index 00000000000..1d9460bde78 --- /dev/null +++ b/app/graphql/mutations/release_asset_links/update.rb @@ -0,0 +1,65 @@ +# frozen_string_literal: true + +module Mutations + module ReleaseAssetLinks + class Update < BaseMutation + graphql_name 'ReleaseAssetLinkUpdate' + + authorize :update_release + + ReleaseAssetLinkID = ::Types::GlobalIDType[::Releases::Link] + + argument :id, ReleaseAssetLinkID, + required: true, + description: 'ID of the release asset link to update.' + + argument :name, GraphQL::STRING_TYPE, + required: false, + description: 'Name of the asset link.' + + argument :url, GraphQL::STRING_TYPE, + required: false, + description: 'URL of the asset link.' + + argument :direct_asset_path, GraphQL::STRING_TYPE, + required: false, as: :filepath, + description: 'Relative path for a direct asset link.' + + argument :link_type, Types::ReleaseAssetLinkTypeEnum, + required: false, + description: 'The type of the asset link.' + + field :link, + Types::ReleaseAssetLinkType, + null: true, + description: 'The asset link after mutation.' + + def ready?(**args) + if args.key?(:link_type) && args[:link_type].nil? + raise Gitlab::Graphql::Errors::ArgumentError, + 'if the linkType argument is provided, it cannot be null' + end + + super + end + + def resolve(id:, **link_attrs) + link = authorized_find!(id) + + unless link.update(link_attrs) + return { link: nil, errors: link.errors.full_messages } + end + + { link: link, errors: [] } + end + + def find_object(id) + # TODO: remove this line when the compatibility layer is removed + # See: https://gitlab.com/gitlab-org/gitlab/-/issues/257883 + id = ReleaseAssetLinkID.coerce_isolated_input(id) + + GitlabSchema.find_by_gid(id) + end + end + end +end diff --git a/app/graphql/mutations/snippets/create.rb b/app/graphql/mutations/snippets/create.rb index 73eac9f0f3b..7f2dd448b8b 100644 --- a/app/graphql/mutations/snippets/create.rb +++ b/app/graphql/mutations/snippets/create.rb @@ -56,7 +56,7 @@ module Mutations end snippet = service_response.payload[:snippet] - with_spam_action_fields(snippet) do + with_spam_action_response_fields(snippet) do { snippet: service_response.success? ? snippet : nil, errors: errors_on_object(snippet) diff --git a/app/graphql/mutations/snippets/update.rb b/app/graphql/mutations/snippets/update.rb index af8e6f384b7..9f9f8bca848 100644 --- a/app/graphql/mutations/snippets/update.rb +++ b/app/graphql/mutations/snippets/update.rb @@ -45,7 +45,7 @@ module Mutations end snippet = service_response.payload[:snippet] - with_spam_action_fields(snippet) do + with_spam_action_response_fields(snippet) do { snippet: service_response.success? ? snippet : snippet.reset, errors: errors_on_object(snippet) diff --git a/app/graphql/mutations/todos/restore_many.rb b/app/graphql/mutations/todos/restore_many.rb index dc02ffadada..41ccbd77aa6 100644 --- a/app/graphql/mutations/todos/restore_many.rb +++ b/app/graphql/mutations/todos/restore_many.rb @@ -60,7 +60,7 @@ module Mutations def authorized_find_all_pending_by_current_user(ids) return Todo.none if ids.blank? || current_user.nil? - Todo.for_ids(ids).for_user(current_user).done + Todo.id_in(ids).for_user(current_user).done end def restore(todos) diff --git a/app/graphql/mutations/user_callouts/create.rb b/app/graphql/mutations/user_callouts/create.rb new file mode 100644 index 00000000000..0d3dcacda41 --- /dev/null +++ b/app/graphql/mutations/user_callouts/create.rb @@ -0,0 +1,30 @@ +# frozen_string_literal: true + +module Mutations + module UserCallouts + class Create < ::Mutations::BaseMutation + graphql_name 'UserCalloutCreate' + + argument :feature_name, + GraphQL::STRING_TYPE, + required: true, + description: "The feature name you want to dismiss the callout for." + + field :user_callout, Types::UserCalloutType, + null: false, + description: 'The user callout dismissed.' + + def resolve(feature_name:) + callout = Users::DismissUserCalloutService.new( + container: nil, current_user: current_user, params: { feature_name: feature_name } + ).execute + errors = errors_on_object(callout) + + { + user_callout: callout, + errors: errors + } + end + end + end +end diff --git a/app/graphql/resolvers/admin/analytics/instance_statistics/measurements_resolver.rb b/app/graphql/resolvers/admin/analytics/usage_trends/measurements_resolver.rb index 9df07df24d8..a5f81149d4e 100644 --- a/app/graphql/resolvers/admin/analytics/instance_statistics/measurements_resolver.rb +++ b/app/graphql/resolvers/admin/analytics/usage_trends/measurements_resolver.rb @@ -3,13 +3,13 @@ module Resolvers module Admin module Analytics - module InstanceStatistics + module UsageTrends class MeasurementsResolver < BaseResolver include Gitlab::Graphql::Authorize::AuthorizeResource - type Types::Admin::Analytics::InstanceStatistics::MeasurementType, null: true + type Types::Admin::Analytics::UsageTrends::MeasurementType, null: true - argument :identifier, Types::Admin::Analytics::InstanceStatistics::MeasurementIdentifierEnum, + argument :identifier, Types::Admin::Analytics::UsageTrends::MeasurementIdentifierEnum, required: true, description: 'The type of measurement/statistics to retrieve.' @@ -24,7 +24,7 @@ module Resolvers def resolve(identifier:, recorded_before: nil, recorded_after: nil) authorize! - ::Analytics::InstanceStatistics::Measurement + ::Analytics::UsageTrends::Measurement .recorded_after(recorded_after) .recorded_before(recorded_before) .with_identifier(identifier) diff --git a/app/graphql/resolvers/alert_management/alert_resolver.rb b/app/graphql/resolvers/alert_management/alert_resolver.rb index d60cabde62b..008641ed88a 100644 --- a/app/graphql/resolvers/alert_management/alert_resolver.rb +++ b/app/graphql/resolvers/alert_management/alert_resolver.rb @@ -43,7 +43,8 @@ module Resolvers def preloads { assignees: [:assignees], - notes: [:ordered_notes, { ordered_notes: [:system_note_metadata, :project, :noteable] }] + notes: [:ordered_notes, { ordered_notes: [:system_note_metadata, :project, :noteable] }], + issue: [:issue] } end end diff --git a/app/graphql/resolvers/alert_management/http_integrations_resolver.rb b/app/graphql/resolvers/alert_management/http_integrations_resolver.rb new file mode 100644 index 00000000000..94a72bca7c7 --- /dev/null +++ b/app/graphql/resolvers/alert_management/http_integrations_resolver.rb @@ -0,0 +1,23 @@ +# frozen_string_literal: true + +module Resolvers + module AlertManagement + class HttpIntegrationsResolver < BaseResolver + alias_method :project, :synchronized_object + + type Types::AlertManagement::HttpIntegrationType.connection_type, null: true + + def resolve(**args) + http_integrations + end + + private + + def http_integrations + return [] unless Ability.allowed?(current_user, :admin_operations, project) + + ::AlertManagement::HttpIntegrationsFinder.new(project, {}).execute + end + end + end +end diff --git a/app/graphql/resolvers/base_resolver.rb b/app/graphql/resolvers/base_resolver.rb index 5db618254cb..67bba079512 100644 --- a/app/graphql/resolvers/base_resolver.rb +++ b/app/graphql/resolvers/base_resolver.rb @@ -12,8 +12,17 @@ module Resolvers @requires_argument = true end + def self.calls_gitaly! + @calls_gitaly = true + end + def self.field_options - super.merge(requires_argument: @requires_argument) + extra_options = { + requires_argument: @requires_argument, + calls_gitaly: @calls_gitaly + }.compact + + super.merge(extra_options) end def self.singular_type diff --git a/app/graphql/resolvers/board_lists_resolver.rb b/app/graphql/resolvers/board_lists_resolver.rb index a97ac3220d5..e66f7b97b40 100644 --- a/app/graphql/resolvers/board_lists_resolver.rb +++ b/app/graphql/resolvers/board_lists_resolver.rb @@ -9,7 +9,7 @@ module Resolvers type Types::BoardListType, null: true extras [:lookahead] - authorize :read_list + authorize :read_issue_board_list argument :id, Types::GlobalIDType[List], required: false, diff --git a/app/graphql/resolvers/board_resolver.rb b/app/graphql/resolvers/board_resolver.rb index 2c2922c3fbf..637d690e4cd 100644 --- a/app/graphql/resolvers/board_resolver.rb +++ b/app/graphql/resolvers/board_resolver.rb @@ -13,7 +13,7 @@ module Resolvers def resolve(id: nil) return unless parent - ::Boards::ListService.new(parent, context[:current_user], board_id: extract_board_id(id)).execute.first + ::Boards::BoardsFinder.new(parent, context[:current_user], board_id: extract_board_id(id)).execute.first rescue ActiveRecord::RecordNotFound nil end diff --git a/app/graphql/resolvers/boards_resolver.rb b/app/graphql/resolvers/boards_resolver.rb index be2f22175dc..679f2b4cceb 100644 --- a/app/graphql/resolvers/boards_resolver.rb +++ b/app/graphql/resolvers/boards_resolver.rb @@ -16,7 +16,7 @@ module Resolvers return Board.none unless parent - ::Boards::ListService.new(parent, context[:current_user], board_id: extract_board_id(id)).execute + ::Boards::BoardsFinder.new(parent, context[:current_user], board_id: extract_board_id(id)).execute rescue ActiveRecord::RecordNotFound Board.none end diff --git a/app/graphql/resolvers/branch_commit_resolver.rb b/app/graphql/resolvers/branch_commit_resolver.rb index 11c49e17bc5..ba235251950 100644 --- a/app/graphql/resolvers/branch_commit_resolver.rb +++ b/app/graphql/resolvers/branch_commit_resolver.rb @@ -7,11 +7,16 @@ module Resolvers alias_method :branch, :object def resolve(**args) - return unless branch + commit = branch&.dereferenced_target + return unless commit - commit = branch.dereferenced_target + lazy_project = BatchLoader::GraphQL.for(commit.repository.gl_project_path).batch do |paths, loader| + paths.each { |path| loader.call(path, Project.find_by_full_path(path)) } + end - ::Commit.new(commit, context[:branch_project]) if commit + ::Gitlab::Graphql::Lazy.with_value(lazy_project) do |project| + ::Commit.new(commit, project) if project + end end end end diff --git a/app/graphql/resolvers/ci/config_resolver.rb b/app/graphql/resolvers/ci/config_resolver.rb index 852bb47e215..f8670649e48 100644 --- a/app/graphql/resolvers/ci/config_resolver.rb +++ b/app/graphql/resolvers/ci/config_resolver.rb @@ -16,7 +16,7 @@ module Resolvers argument :content, GraphQL::STRING_TYPE, required: true, - description: "Contents of '.gitlab-ci.yml'." + description: "Contents of `.gitlab-ci.yml`." argument :dry_run, GraphQL::BOOLEAN_TYPE, required: false, diff --git a/app/graphql/resolvers/concerns/resolves_snippets.rb b/app/graphql/resolvers/concerns/resolves_snippets.rb index 0bc38188b9a..445f3567b1d 100644 --- a/app/graphql/resolvers/concerns/resolves_snippets.rb +++ b/app/graphql/resolvers/concerns/resolves_snippets.rb @@ -8,7 +8,7 @@ module ResolvesSnippets argument :ids, [::Types::GlobalIDType[::Snippet]], required: false, - description: 'Array of global snippet ids, e.g., "gid://gitlab/ProjectSnippet/1".' + description: 'Array of global snippet IDs. For example, `gid://gitlab/ProjectSnippet/1`.' argument :visibility, Types::Snippets::VisibilityScopesEnum, required: false, diff --git a/app/graphql/resolvers/full_path_resolver.rb b/app/graphql/resolvers/full_path_resolver.rb index d01cdf749a1..b5e90da78b2 100644 --- a/app/graphql/resolvers/full_path_resolver.rb +++ b/app/graphql/resolvers/full_path_resolver.rb @@ -7,7 +7,7 @@ module Resolvers prepended do argument :full_path, GraphQL::ID_TYPE, required: true, - description: 'The full path of the project, group or namespace, e.g., "gitlab-org/gitlab-foss".' + description: 'The full path of the project, group or namespace, e.g., `gitlab-org/gitlab-foss`.' end def model_by_full_path(model, full_path) diff --git a/app/graphql/resolvers/group_packages_resolver.rb b/app/graphql/resolvers/group_packages_resolver.rb new file mode 100644 index 00000000000..d441cd80249 --- /dev/null +++ b/app/graphql/resolvers/group_packages_resolver.rb @@ -0,0 +1,27 @@ +# frozen_string_literal: true + +module Resolvers + class GroupPackagesResolver < BaseResolver + type Types::Packages::PackageType.connection_type, null: true + + def ready?(**args) + context[self.class] ||= { executions: 0 } + context[self.class][:executions] += 1 + raise GraphQL::ExecutionError, "Packages can be requested only for one group at a time" if context[self.class][:executions] > 1 + + super + end + + def resolve(**args) + return unless packages_available? + + ::Packages::GroupPackagesFinder.new(current_user, object).execute + end + + private + + def packages_available? + ::Gitlab.config.packages.enabled + end + end +end diff --git a/app/graphql/resolvers/last_commit_resolver.rb b/app/graphql/resolvers/last_commit_resolver.rb index dd89c322617..00c43bdfee6 100644 --- a/app/graphql/resolvers/last_commit_resolver.rb +++ b/app/graphql/resolvers/last_commit_resolver.rb @@ -4,6 +4,8 @@ module Resolvers class LastCommitResolver < BaseResolver type Types::CommitType, null: true + calls_gitaly! + alias_method :tree, :object def resolve(**args) diff --git a/app/graphql/resolvers/metrics/dashboard_resolver.rb b/app/graphql/resolvers/metrics/dashboard_resolver.rb index f569cb0b2c3..a82a4a95254 100644 --- a/app/graphql/resolvers/metrics/dashboard_resolver.rb +++ b/app/graphql/resolvers/metrics/dashboard_resolver.rb @@ -3,19 +3,30 @@ module Resolvers module Metrics class DashboardResolver < Resolvers::BaseResolver + type Types::Metrics::DashboardType, null: true + calls_gitaly! + argument :path, GraphQL::STRING_TYPE, required: true, - description: "Path to a file which defines metrics dashboard eg: 'config/prometheus/common_metrics.yml'." - - type Types::Metrics::DashboardType, null: true + description: "Path to a file which defines metrics dashboard " \ + "eg: 'config/prometheus/common_metrics.yml'." alias_method :environment, :object def resolve(**args) return unless environment - ::PerformanceMonitoring::PrometheusDashboard - .find_for(project: environment.project, user: context[:current_user], path: args[:path], options: { environment: environment }) + ::PerformanceMonitoring::PrometheusDashboard.find_for(**args, **service_params) + end + + private + + def service_params + { + project: environment.project, + user: current_user, + options: { environment: environment } + } end end end diff --git a/app/graphql/resolvers/namespace_projects_resolver.rb b/app/graphql/resolvers/namespace_projects_resolver.rb index da44b9b5623..7320c3ce141 100644 --- a/app/graphql/resolvers/namespace_projects_resolver.rb +++ b/app/graphql/resolvers/namespace_projects_resolver.rb @@ -17,23 +17,23 @@ module Resolvers default_value: nil, description: 'Sort projects by this criteria.' + argument :ids, [GraphQL::ID_TYPE], + required: false, + default_value: nil, + description: 'Filter projects by IDs.' + type Types::ProjectType, null: true - def resolve(include_subgroups:, sort:, search:) + def resolve(args) # The namespace could have been loaded in batch by `BatchLoader`. # At this point we need the `id` or the `full_path` of the namespace # to query for projects, so make sure it's loaded and not `nil` before continuing. - return Project.none if namespace.nil? - - query = include_subgroups ? namespace.all_projects.with_route : namespace.projects.with_route - return query unless search.present? - - if sort == :similarity - query.sorted_by_similarity_desc(search, include_in_select: true).merge(Project.search(search)) - else - query.merge(Project.search(search)) - end + ::Namespaces::ProjectsFinder.new( + namespace: namespace, + current_user: current_user, + params: finder_params(args) + ).execute end def self.resolver_complexity(args, child_complexity:) @@ -48,6 +48,19 @@ module Resolvers object.respond_to?(:sync) ? object.sync : object end end + + def finder_params(args) + { + include_subgroups: args.dig(:include_subgroups), + sort: args.dig(:sort), + search: args.dig(:search), + ids: parse_gids(args.dig(:ids)) + } + end + + def parse_gids(gids) + gids&.map { |gid| GitlabSchema.parse_gid(gid, expected_type: ::Project).model_id } + end end end diff --git a/app/graphql/resolvers/project_merge_requests_resolver.rb b/app/graphql/resolvers/project_merge_requests_resolver.rb index 9628a6dfd7a..66c020a0c14 100644 --- a/app/graphql/resolvers/project_merge_requests_resolver.rb +++ b/app/graphql/resolvers/project_merge_requests_resolver.rb @@ -10,7 +10,7 @@ module Resolvers def resolve(**args) scope = super - if only_count_is_selected_with_merged_at_filter?(args) && Feature.enabled?(:optimized_merge_request_count_with_merged_at_filter, default_enabled: :yaml) + if only_count_is_selected_with_merged_at_filter?(args) MergeRequest::MetricsFinder .new(current_user, args.merge(target_project: project)) .execute diff --git a/app/graphql/resolvers/packages_resolver.rb b/app/graphql/resolvers/project_packages_resolver.rb index 3eeed48ff7e..288e14b41d0 100644 --- a/app/graphql/resolvers/packages_resolver.rb +++ b/app/graphql/resolvers/project_packages_resolver.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true module Resolvers - class PackagesResolver < BaseResolver + class ProjectPackagesResolver < BaseResolver type Types::Packages::PackageType.connection_type, null: true def resolve(**args) diff --git a/app/graphql/resolvers/project_pipeline_resolver.rb b/app/graphql/resolvers/project_pipeline_resolver.rb index b604a408928..8fca6b829c0 100644 --- a/app/graphql/resolvers/project_pipeline_resolver.rb +++ b/app/graphql/resolvers/project_pipeline_resolver.rb @@ -7,14 +7,34 @@ module Resolvers alias_method :project, :object argument :iid, GraphQL::ID_TYPE, - required: true, - description: 'IID of the Pipeline, e.g., "1".' + required: false, + description: 'IID of the Pipeline. For example, "1".' - def resolve(iid:) - BatchLoader::GraphQL.for(iid).batch(key: project) do |iids, loader, args| - finder = ::Ci::PipelinesFinder.new(project, context[:current_user], iids: iids) + argument :sha, GraphQL::STRING_TYPE, + required: false, + description: 'SHA of the Pipeline. For example, "dyd0f15ay83993f5ab66k927w28673882x99100b".' - finder.execute.each { |pipeline| loader.call(pipeline.iid.to_s, pipeline) } + def ready?(iid: nil, sha: nil) + unless iid.present? ^ sha.present? + raise Gitlab::Graphql::Errors::ArgumentError, 'Provide one of an IID or SHA' + end + + super + end + + def resolve(iid: nil, sha: nil) + if iid + BatchLoader::GraphQL.for(iid).batch(key: project) do |iids, loader, args| + finder = ::Ci::PipelinesFinder.new(project, current_user, iids: iids) + + finder.execute.each { |pipeline| loader.call(pipeline.iid.to_s, pipeline) } + end + else + BatchLoader::GraphQL.for(sha).batch(key: project) do |shas, loader, args| + finder = ::Ci::PipelinesFinder.new(project, current_user, shas: shas) + + finder.execute.each { |pipeline| loader.call(pipeline.sha.to_s, pipeline) } + end end end end diff --git a/app/graphql/resolvers/snippets/blobs_resolver.rb b/app/graphql/resolvers/snippets/blobs_resolver.rb index 672214df7d5..569b82149d3 100644 --- a/app/graphql/resolvers/snippets/blobs_resolver.rb +++ b/app/graphql/resolvers/snippets/blobs_resolver.rb @@ -8,6 +8,7 @@ module Resolvers type Types::Snippets::BlobType.connection_type, null: true authorize :read_snippet + calls_gitaly! alias_method :snippet, :object diff --git a/app/graphql/resolvers/tree_resolver.rb b/app/graphql/resolvers/tree_resolver.rb index 7a70c35897d..c07d9187d4d 100644 --- a/app/graphql/resolvers/tree_resolver.rb +++ b/app/graphql/resolvers/tree_resolver.rb @@ -4,6 +4,8 @@ module Resolvers class TreeResolver < BaseResolver type Types::Tree::TreeType, null: true + calls_gitaly! + argument :path, GraphQL::STRING_TYPE, required: false, default_value: '', diff --git a/app/graphql/types/access_level_enum.rb b/app/graphql/types/access_level_enum.rb index 6754d3d28ce..b7eb35ddfc9 100644 --- a/app/graphql/types/access_level_enum.rb +++ b/app/graphql/types/access_level_enum.rb @@ -5,11 +5,12 @@ module Types graphql_name 'AccessLevelEnum' description 'Access level to a resource' - value 'NO_ACCESS', value: Gitlab::Access::NO_ACCESS - value 'GUEST', value: Gitlab::Access::GUEST - value 'REPORTER', value: Gitlab::Access::REPORTER - value 'DEVELOPER', value: Gitlab::Access::DEVELOPER - value 'MAINTAINER', value: Gitlab::Access::MAINTAINER - value 'OWNER', value: Gitlab::Access::OWNER + value 'NO_ACCESS', value: Gitlab::Access::NO_ACCESS, description: 'No access' + value 'MINIMAL_ACCESS', value: Gitlab::Access::MINIMAL_ACCESS, description: 'Minimal access' + value 'GUEST', value: Gitlab::Access::GUEST, description: 'Guest access' + value 'REPORTER', value: Gitlab::Access::REPORTER, description: 'Reporter access' + value 'DEVELOPER', value: Gitlab::Access::DEVELOPER, description: 'Developer access' + value 'MAINTAINER', value: Gitlab::Access::MAINTAINER, description: 'Maintainer access' + value 'OWNER', value: Gitlab::Access::OWNER, description: 'Owner access' end end 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 deleted file mode 100644 index c6ca5963588..00000000000 --- a/app/graphql/types/admin/analytics/instance_statistics/measurement_identifier_enum.rb +++ /dev/null @@ -1,25 +0,0 @@ -# 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' - value 'PIPELINES_SUCCEEDED', 'Pipeline count with success status', value: 'pipelines_succeeded' - value 'PIPELINES_FAILED', 'Pipeline count with failed status', value: 'pipelines_failed' - value 'PIPELINES_CANCELED', 'Pipeline count with canceled status', value: 'pipelines_canceled' - value 'PIPELINES_SKIPPED', 'Pipeline count with skipped status', value: 'pipelines_skipped' - end - end - end - end -end diff --git a/app/graphql/types/admin/analytics/usage_trends/measurement_identifier_enum.rb b/app/graphql/types/admin/analytics/usage_trends/measurement_identifier_enum.rb new file mode 100644 index 00000000000..33bec5278fe --- /dev/null +++ b/app/graphql/types/admin/analytics/usage_trends/measurement_identifier_enum.rb @@ -0,0 +1,25 @@ +# frozen_string_literal: true + +module Types + module Admin + module Analytics + module UsageTrends + 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' + value 'PIPELINES_SUCCEEDED', 'Pipeline count with success status.', value: 'pipelines_succeeded' + value 'PIPELINES_FAILED', 'Pipeline count with failed status.', value: 'pipelines_failed' + value 'PIPELINES_CANCELED', 'Pipeline count with canceled status.', value: 'pipelines_canceled' + value 'PIPELINES_SKIPPED', 'Pipeline count with skipped status.', value: 'pipelines_skipped' + end + end + end + end +end diff --git a/app/graphql/types/admin/analytics/instance_statistics/measurement_type.rb b/app/graphql/types/admin/analytics/usage_trends/measurement_type.rb index 17a5af8d36b..c8ca702706f 100644 --- a/app/graphql/types/admin/analytics/instance_statistics/measurement_type.rb +++ b/app/graphql/types/admin/analytics/usage_trends/measurement_type.rb @@ -3,13 +3,13 @@ module Types module Admin module Analytics - module InstanceStatistics + module UsageTrends class MeasurementType < BaseObject include Gitlab::Graphql::Authorize::AuthorizeResource - graphql_name 'InstanceStatisticsMeasurement' + graphql_name 'UsageTrendsMeasurement' description 'Represents a recorded measurement (object count) for the Admins' - authorize :read_instance_statistics_measurements + authorize :read_usage_trends_measurement field :recorded_at, Types::TimeType, null: true, description: 'The time the measurement was recorded.' @@ -17,7 +17,7 @@ module Types field :count, GraphQL::INT_TYPE, null: false, description: 'Object count.' - field :identifier, Types::Admin::Analytics::InstanceStatistics::MeasurementIdentifierEnum, null: false, + field :identifier, Types::Admin::Analytics::UsageTrends::MeasurementIdentifierEnum, null: false, description: 'The type of objects being measured.' end end diff --git a/app/graphql/types/alert_management/alert_sort_enum.rb b/app/graphql/types/alert_management/alert_sort_enum.rb index 51e7bef0a7f..11a5cb95722 100644 --- a/app/graphql/types/alert_management/alert_sort_enum.rb +++ b/app/graphql/types/alert_management/alert_sort_enum.rb @@ -6,20 +6,20 @@ module Types graphql_name 'AlertManagementAlertSort' description 'Values for sorting alerts' - value 'STARTED_AT_ASC', 'Start time by ascending order', value: :started_at_asc - value 'STARTED_AT_DESC', 'Start time by descending order', value: :started_at_desc - value 'ENDED_AT_ASC', 'End time by ascending order', value: :ended_at_asc - value 'ENDED_AT_DESC', 'End time by descending order', value: :ended_at_desc - value 'CREATED_TIME_ASC', 'Created time by ascending order', value: :created_at_asc - value 'CREATED_TIME_DESC', 'Created time by descending order', value: :created_at_desc - value 'UPDATED_TIME_ASC', 'Created time by ascending order', value: :updated_at_asc - value 'UPDATED_TIME_DESC', 'Created time by descending order', value: :updated_at_desc - value 'EVENT_COUNT_ASC', 'Events count by ascending order', value: :event_count_asc - value 'EVENT_COUNT_DESC', 'Events count by descending order', value: :event_count_desc - value 'SEVERITY_ASC', 'Severity from less critical to more critical', value: :severity_asc - value 'SEVERITY_DESC', 'Severity from more critical to less critical', value: :severity_desc - value 'STATUS_ASC', 'Status by order: Ignored > Resolved > Acknowledged > Triggered', value: :status_asc - value 'STATUS_DESC', 'Status by order: Triggered > Acknowledged > Resolved > Ignored', value: :status_desc + value 'STARTED_AT_ASC', 'Start time by ascending order.', value: :started_at_asc + value 'STARTED_AT_DESC', 'Start time by descending order.', value: :started_at_desc + value 'ENDED_AT_ASC', 'End time by ascending order.', value: :ended_at_asc + value 'ENDED_AT_DESC', 'End time by descending order.', value: :ended_at_desc + value 'CREATED_TIME_ASC', 'Created time by ascending order.', value: :created_at_asc + value 'CREATED_TIME_DESC', 'Created time by descending order.', value: :created_at_desc + value 'UPDATED_TIME_ASC', 'Created time by ascending order.', value: :updated_at_asc + value 'UPDATED_TIME_DESC', 'Created time by descending order.', value: :updated_at_desc + value 'EVENT_COUNT_ASC', 'Events count by ascending order.', value: :event_count_asc + value 'EVENT_COUNT_DESC', 'Events count by descending order.', value: :event_count_desc + value 'SEVERITY_ASC', 'Severity from less critical to more critical.', value: :severity_asc + value 'SEVERITY_DESC', 'Severity from more critical to less critical.', value: :severity_desc + value 'STATUS_ASC', 'Status by order: Ignored > Resolved > Acknowledged > Triggered.', value: :status_asc + value 'STATUS_DESC', 'Status by order: Triggered > Acknowledged > Resolved > Ignored.', value: :status_desc end end end diff --git a/app/graphql/types/alert_management/alert_type.rb b/app/graphql/types/alert_management/alert_type.rb index 6b7e7030c1f..5a2a5c68c8d 100644 --- a/app/graphql/types/alert_management/alert_type.rb +++ b/app/graphql/types/alert_management/alert_type.rb @@ -20,8 +20,14 @@ module Types field :issue_iid, GraphQL::ID_TYPE, null: true, + deprecated: { reason: 'Use issue field', milestone: '13.10' }, description: 'Internal ID of the GitLab issue attached to the alert.' + field :issue, + Types::IssueType, + null: true, + description: 'Issue attached to the alert.' + field :title, GraphQL::STRING_TYPE, null: true, diff --git a/app/graphql/types/alert_management/domain_filter_enum.rb b/app/graphql/types/alert_management/domain_filter_enum.rb index a798cfb9ee9..3ee01e4c391 100644 --- a/app/graphql/types/alert_management/domain_filter_enum.rb +++ b/app/graphql/types/alert_management/domain_filter_enum.rb @@ -6,8 +6,8 @@ module Types graphql_name 'AlertManagementDomainFilter' description 'Filters the alerts based on given domain' - value 'operations', description: 'Alerts for operations domain' - value 'threat_monitoring', description: 'Alerts for threat monitoring domain' + value 'operations', description: 'Alerts for operations domain.' + value 'threat_monitoring', description: 'Alerts for threat monitoring domain.' end end end diff --git a/app/graphql/types/alert_management/http_integration_type.rb b/app/graphql/types/alert_management/http_integration_type.rb index 88782050b94..0d5bb50a77c 100644 --- a/app/graphql/types/alert_management/http_integration_type.rb +++ b/app/graphql/types/alert_management/http_integration_type.rb @@ -20,3 +20,5 @@ module Types end end end + +Types::AlertManagement::HttpIntegrationType.prepend_ee_mod diff --git a/app/graphql/types/alert_management/integration_type_enum.rb b/app/graphql/types/alert_management/integration_type_enum.rb index 2f9be549e58..94f38e03409 100644 --- a/app/graphql/types/alert_management/integration_type_enum.rb +++ b/app/graphql/types/alert_management/integration_type_enum.rb @@ -6,8 +6,8 @@ module Types graphql_name 'AlertManagementIntegrationType' description 'Values of types of integrations' - value 'PROMETHEUS', 'Prometheus integration', value: :prometheus - value 'HTTP', 'Integration with any monitoring tool', value: :http + value 'PROMETHEUS', 'Prometheus integration.', value: :prometheus + value 'HTTP', 'Integration with any monitoring tool.', value: :http end end end diff --git a/app/graphql/types/base_argument.rb b/app/graphql/types/base_argument.rb index 11774d0b59d..4ad9e8c0e40 100644 --- a/app/graphql/types/base_argument.rb +++ b/app/graphql/types/base_argument.rb @@ -6,7 +6,6 @@ module Types def initialize(*args, **kwargs, &block) kwargs = gitlab_deprecation(kwargs) - kwargs.delete(:deprecation_reason) super(*args, **kwargs, &block) end diff --git a/app/graphql/types/base_field.rb b/app/graphql/types/base_field.rb index f145b9d45c3..78ab6890923 100644 --- a/app/graphql/types/base_field.rb +++ b/app/graphql/types/base_field.rb @@ -9,48 +9,29 @@ module Types DEFAULT_COMPLEXITY = 1 - def initialize(*args, **kwargs, &block) + def initialize(**kwargs, &block) @calls_gitaly = !!kwargs.delete(:calls_gitaly) - @constant_complexity = !!kwargs[:complexity] + @constant_complexity = kwargs[:complexity].is_a?(Integer) && kwargs[:complexity] > 0 @requires_argument = !!kwargs.delete(:requires_argument) kwargs[:complexity] = field_complexity(kwargs[:resolver_class], kwargs[:complexity]) @feature_flag = kwargs[:feature_flag] kwargs = check_feature_flag(kwargs) kwargs = gitlab_deprecation(kwargs) - super(*args, **kwargs, &block) + super(**kwargs, &block) + + # We want to avoid the overhead of this in prod + extension ::Gitlab::Graphql::CallsGitaly::FieldExtension if Gitlab.dev_or_test_env? + + extension ::Gitlab::Graphql::Present::FieldExtension end - def requires_argument? - @requires_argument || arguments.values.any? { |argument| argument.type.non_null? } + def may_call_gitaly? + @constant_complexity || @calls_gitaly 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&.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 + def requires_argument? + @requires_argument || arguments.values.any? { |argument| argument.type.non_null? } end def base_complexity @@ -82,8 +63,10 @@ module Types end def check_feature_flag(args) - args[:description] = feature_documentation_message(args[:feature_flag], args[:description]) if args[:feature_flag].present? - args.delete(:feature_flag) + ff = args.delete(:feature_flag) + return args unless ff.present? + + args[:description] = feature_documentation_message(ff, args[:description]) args end @@ -106,7 +89,9 @@ module Types # items which can be loaded. proc do |ctx, args, child_complexity| # Resolvers may add extra complexity depending on used arguments - complexity = child_complexity + self.resolver&.try(:resolver_complexity, args, child_complexity: child_complexity).to_i + complexity = child_complexity + resolver&.try( + :resolver_complexity, args, child_complexity: child_complexity + ).to_i complexity += 1 if calls_gitaly? complexity += complexity * connection_complexity_multiplier(ctx, args) @@ -121,7 +106,7 @@ module Types page_size = field_defn.connection_max_page_size || ctx.schema.default_max_page_size limit_value = [args[:first], args[:last], page_size].compact.min - multiplier = self.resolver&.try(:complexity_multiplier, args).to_f + multiplier = resolver&.try(:complexity_multiplier, args).to_f limit_value * multiplier end end diff --git a/app/graphql/types/blob_viewers/type_enum.rb b/app/graphql/types/blob_viewers/type_enum.rb index 35e659197e5..3cb5c76d881 100644 --- a/app/graphql/types/blob_viewers/type_enum.rb +++ b/app/graphql/types/blob_viewers/type_enum.rb @@ -6,9 +6,9 @@ module Types graphql_name 'BlobViewersType' description 'Types of blob viewers' - value 'rich', value: :rich - value 'simple', value: :simple - value 'auxiliary', value: :auxiliary + value 'rich', value: :rich, description: 'Rich blob viewers type.' + value 'simple', value: :simple, description: 'Simple blob viewers type.' + value 'auxiliary', value: :auxiliary, description: 'Auxiliary blob viewers type.' end end end diff --git a/app/graphql/types/board_list_type.rb b/app/graphql/types/board_list_type.rb index 46b49c5d8a4..f215aa255de 100644 --- a/app/graphql/types/board_list_type.rb +++ b/app/graphql/types/board_list_type.rb @@ -8,6 +8,8 @@ module Types graphql_name 'BoardList' description 'Represents a list for an issue board' + alias_method :list, :object + field :id, GraphQL::ID_TYPE, null: false, description: 'ID (global ID) of the list.' field :title, GraphQL::STRING_TYPE, null: false, @@ -19,7 +21,7 @@ module Types field :label, Types::LabelType, null: true, description: 'Label of the list.' field :collapsed, GraphQL::BOOLEAN_TYPE, null: true, - description: 'Indicates if list is collapsed for this user.' + description: 'Indicates if the list is collapsed for this user.' field :issues_count, GraphQL::INT_TYPE, null: true, description: 'Count of issues in the list.' @@ -37,12 +39,10 @@ module Types def metadata strong_memoize(:metadata) do - list = self.object - user = context[:current_user] params = (context[:issue_filters] || {}).merge(board_id: list.board_id, id: list.id) ::Boards::Issues::ListService - .new(list.board.resource_parent, user, params) + .new(list.board.resource_parent, current_user, params) .metadata end end diff --git a/app/graphql/types/board_type.rb b/app/graphql/types/board_type.rb index f8bd31d5fa0..f33f3f5e537 100644 --- a/app/graphql/types/board_type.rb +++ b/app/graphql/types/board_type.rb @@ -3,9 +3,9 @@ module Types class BoardType < BaseObject graphql_name 'Board' - description 'Represents a project or group board' + description 'Represents a project or group issue board' accepts ::Board - authorize :read_board + authorize :read_issue_board present_using BoardPresenter diff --git a/app/graphql/types/boards/board_issue_input_base_type.rb b/app/graphql/types/boards/board_issue_input_base_type.rb index dab1414760b..b762cef6e58 100644 --- a/app/graphql/types/boards/board_issue_input_base_type.rb +++ b/app/graphql/types/boards/board_issue_input_base_type.rb @@ -2,7 +2,6 @@ module Types module Boards - # rubocop: disable Graphql/AuthorizeTypes class BoardIssueInputBaseType < BaseInputObject argument :label_name, GraphQL::STRING_TYPE.to_list_type, required: false, @@ -28,7 +27,6 @@ module Types required: false, description: 'Filter by reaction emoji.' end - # rubocop: enable Graphql/AuthorizeTypes end end diff --git a/app/graphql/types/boards/board_issue_input_type.rb b/app/graphql/types/boards/board_issue_input_type.rb index 62a402ee724..9cc0f484a16 100644 --- a/app/graphql/types/boards/board_issue_input_type.rb +++ b/app/graphql/types/boards/board_issue_input_type.rb @@ -2,7 +2,6 @@ module Types module Boards - # rubocop: disable Graphql/AuthorizeTypes class NegatedBoardIssueInputType < BoardIssueInputBaseType end @@ -17,7 +16,6 @@ module Types required: false, description: 'Search query for issue title or description.' end - # rubocop: enable Graphql/AuthorizeTypes end end diff --git a/app/graphql/types/ci/config/status_enum.rb b/app/graphql/types/ci/config/status_enum.rb index 92b04c61679..1ba207531b8 100644 --- a/app/graphql/types/ci/config/status_enum.rb +++ b/app/graphql/types/ci/config/status_enum.rb @@ -7,8 +7,8 @@ module Types graphql_name 'CiConfigStatus' description 'Values for YAML processor result' - value 'VALID', 'The configuration file is valid', value: :valid - value 'INVALID', 'The configuration file is not valid', value: :invalid + value 'VALID', 'The configuration file is valid.', value: :valid + value 'INVALID', 'The configuration file is not valid.', value: :invalid end end end diff --git a/app/graphql/types/ci/job_artifact_file_type_enum.rb b/app/graphql/types/ci/job_artifact_file_type_enum.rb index 4b484dec590..5099b0d4850 100644 --- a/app/graphql/types/ci/job_artifact_file_type_enum.rb +++ b/app/graphql/types/ci/job_artifact_file_type_enum.rb @@ -6,7 +6,8 @@ module Types graphql_name 'JobArtifactFileType' ::Ci::JobArtifact::TYPE_AND_FORMAT_PAIRS.keys.each do |file_type| - value file_type.to_s.upcase, value: file_type.to_s + description = file_type == :codequality ? "CODE QUALITY" : file_type.to_s.titleize.upcase # This is needed as doc lint will not allow codequality as one word + value file_type.to_s.upcase, value: file_type.to_s, description: "#{description} job artifact file type." end end end diff --git a/app/graphql/types/ci/job_type.rb b/app/graphql/types/ci/job_type.rb index ba463cdd9c1..c86337eea89 100644 --- a/app/graphql/types/ci/job_type.rb +++ b/app/graphql/types/ci/job_type.rb @@ -18,6 +18,10 @@ module Types description: 'Schedule for the build.' field :artifacts, Types::Ci::JobArtifactType.connection_type, null: true, description: 'Artifacts generated by the job.' + field :finished_at, Types::TimeType, null: true, + description: 'When a job has finished running.' + field :duration, GraphQL::INT_TYPE, null: true, + description: 'Duration of the job in seconds.' def pipeline Gitlab::Graphql::Loaders::BatchModelLoader.new(::Ci::Pipeline, object.pipeline_id).find diff --git a/app/graphql/types/ci/pipeline_type.rb b/app/graphql/types/ci/pipeline_type.rb index 2c386c9b564..49be200a788 100644 --- a/app/graphql/types/ci/pipeline_type.rb +++ b/app/graphql/types/ci/pipeline_type.rb @@ -95,6 +95,9 @@ module Types field :path, GraphQL::STRING_TYPE, null: true, description: "Relative path to the pipeline's page." + field :commit_path, GraphQL::STRING_TYPE, null: true, + description: 'Path to the commit that triggered the pipeline.' + field :project, Types::ProjectType, null: true, description: 'Project the pipeline belongs to.' @@ -109,6 +112,10 @@ module Types Gitlab::Graphql::Loaders::BatchModelLoader.new(User, object.user_id).find end + def commit_path + ::Gitlab::Routing.url_helpers.project_commit_path(object.project, object.sha) + end + def path ::Gitlab::Routing.url_helpers.project_pipeline_path(object.project, object) end diff --git a/app/graphql/types/ci_configuration/sast/analyzers_entity_input_type.rb b/app/graphql/types/ci_configuration/sast/analyzers_entity_input_type.rb index 9835a7ef208..ccb72283cf6 100644 --- a/app/graphql/types/ci_configuration/sast/analyzers_entity_input_type.rb +++ b/app/graphql/types/ci_configuration/sast/analyzers_entity_input_type.rb @@ -3,7 +3,6 @@ module Types module CiConfiguration module Sast - # rubocop: disable Graphql/AuthorizeTypes class AnalyzersEntityInputType < BaseInputObject graphql_name 'SastCiConfigurationAnalyzersEntityInput' description 'Represents the analyzers entity in SAST CI configuration' diff --git a/app/graphql/types/ci_configuration/sast/entity_input_type.rb b/app/graphql/types/ci_configuration/sast/entity_input_type.rb index 39b3efb3db8..9fce120889b 100644 --- a/app/graphql/types/ci_configuration/sast/entity_input_type.rb +++ b/app/graphql/types/ci_configuration/sast/entity_input_type.rb @@ -3,7 +3,6 @@ module Types module CiConfiguration module Sast - # rubocop: disable Graphql/AuthorizeTypes class EntityInputType < BaseInputObject graphql_name 'SastCiConfigurationEntityInput' description 'Represents an entity in SAST CI configuration' diff --git a/app/graphql/types/ci_configuration/sast/input_type.rb b/app/graphql/types/ci_configuration/sast/input_type.rb index 615436683f6..a86bdfca4da 100644 --- a/app/graphql/types/ci_configuration/sast/input_type.rb +++ b/app/graphql/types/ci_configuration/sast/input_type.rb @@ -3,7 +3,7 @@ module Types module CiConfiguration module Sast - class InputType < BaseInputObject # rubocop:disable Graphql/AuthorizeTypes + class InputType < BaseInputObject graphql_name 'SastCiConfigurationInput' description 'Represents a CI configuration of SAST' diff --git a/app/graphql/types/ci_configuration/sast/ui_component_size_enum.rb b/app/graphql/types/ci_configuration/sast/ui_component_size_enum.rb index 3a208f9d3e4..76d2a314c13 100644 --- a/app/graphql/types/ci_configuration/sast/ui_component_size_enum.rb +++ b/app/graphql/types/ci_configuration/sast/ui_component_size_enum.rb @@ -7,9 +7,9 @@ module Types graphql_name 'SastUiComponentSize' description 'Size of UI component in SAST configuration page' - value 'SMALL' - value 'MEDIUM' - value 'LARGE' + value 'SMALL', description: "The size of UI component in SAST configuration page is small." + value 'MEDIUM', description: "The size of UI component in SAST configuration page is medium." + value 'LARGE', description: "The size of UI component in SAST configuration page is large." end end end diff --git a/app/graphql/types/commit_action_mode_enum.rb b/app/graphql/types/commit_action_mode_enum.rb index 77658a85b51..ea3d49c9822 100644 --- a/app/graphql/types/commit_action_mode_enum.rb +++ b/app/graphql/types/commit_action_mode_enum.rb @@ -5,10 +5,10 @@ module Types graphql_name 'CommitActionMode' description 'Mode of a commit action' - value 'CREATE', description: 'Create command', value: :create - value 'DELETE', description: 'Delete command', value: :delete - value 'MOVE', description: 'Move command', value: :move - value 'UPDATE', description: 'Update command', value: :update - value 'CHMOD', description: 'Chmod command', value: :chmod + value 'CREATE', description: 'Create command.', value: :create + value 'DELETE', description: 'Delete command.', value: :delete + value 'MOVE', description: 'Move command.', value: :move + value 'UPDATE', description: 'Update command.', value: :update + value 'CHMOD', description: 'Chmod command.', value: :chmod end end diff --git a/app/graphql/types/commit_action_type.rb b/app/graphql/types/commit_action_type.rb index e14e7157752..cc1f45478e4 100644 --- a/app/graphql/types/commit_action_type.rb +++ b/app/graphql/types/commit_action_type.rb @@ -1,7 +1,6 @@ # frozen_string_literal: true module Types - # rubocop: disable Graphql/AuthorizeTypes class CommitActionType < BaseInputObject argument :action, type: Types::CommitActionModeEnum, required: true, description: 'The action to perform, create, delete, move, update, chmod.' @@ -18,5 +17,4 @@ module Types argument :encoding, type: Types::CommitEncodingEnum, required: false, description: 'Encoding of the file. Default is text.' end - # rubocop: enable Graphql/AuthorizeTypes end diff --git a/app/graphql/types/commit_encoding_enum.rb b/app/graphql/types/commit_encoding_enum.rb index 0ea89b82db7..c51c1e864fb 100644 --- a/app/graphql/types/commit_encoding_enum.rb +++ b/app/graphql/types/commit_encoding_enum.rb @@ -4,7 +4,7 @@ module Types class CommitEncodingEnum < BaseEnum graphql_name 'CommitEncoding' - value 'TEXT', description: 'Text encoding', value: :text - value 'BASE64', description: 'Base64 encoding', value: :base64 + value 'TEXT', description: 'Text encoding.', value: :text + value 'BASE64', description: 'Base64 encoding.', value: :base64 end end diff --git a/app/graphql/types/concerns/gitlab_style_deprecations.rb b/app/graphql/types/concerns/gitlab_style_deprecations.rb index 9f087f3812d..ad195354930 100644 --- a/app/graphql/types/concerns/gitlab_style_deprecations.rb +++ b/app/graphql/types/concerns/gitlab_style_deprecations.rb @@ -10,7 +10,7 @@ module GitlabStyleDeprecations 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' + 'See https://docs.gitlab.com/ee/development/api_graphql_styleguide.html#deprecating-fields-arguments-and-enum-values' end deprecation = kwargs.delete(:deprecated) diff --git a/app/graphql/types/container_repository_sort_enum.rb b/app/graphql/types/container_repository_sort_enum.rb index 96210c0546b..4f2e15fd32f 100644 --- a/app/graphql/types/container_repository_sort_enum.rb +++ b/app/graphql/types/container_repository_sort_enum.rb @@ -5,7 +5,7 @@ module Types graphql_name 'ContainerRepositorySort' description 'Values for sorting container repositories' - value 'NAME_ASC', 'Name by ascending order', value: :name_asc - value 'NAME_DESC', 'Name by descending order', value: :name_desc + value 'NAME_ASC', 'Name by ascending order.', value: :name_asc + value 'NAME_DESC', 'Name by descending order.', value: :name_desc end end diff --git a/app/graphql/types/current_user_todos.rb b/app/graphql/types/current_user_todos.rb index 79a430af1d7..2551db875b0 100644 --- a/app/graphql/types/current_user_todos.rb +++ b/app/graphql/types/current_user_todos.rb @@ -16,9 +16,10 @@ module Types end def current_user_todos(state: nil) - state ||= %i(done pending) # TodosFinder treats a `nil` state param as `pending` + state ||= %i[done pending] # TodosFinder treats a `nil` state param as `pending` + klass = unpresented.class - TodosFinder.new(current_user, state: state, type: object.class.name, target_id: object.id).execute + TodosFinder.new(current_user, state: state, type: klass.name, target_id: object.id).execute end end end diff --git a/app/graphql/types/design_management/design_version_event_enum.rb b/app/graphql/types/design_management/design_version_event_enum.rb index ea4bc1ffbfa..354b34c9f9f 100644 --- a/app/graphql/types/design_management/design_version_event_enum.rb +++ b/app/graphql/types/design_management/design_version_event_enum.rb @@ -8,7 +8,7 @@ module Types NONE = 'NONE' - value NONE, 'No change' + value NONE, 'No change.' ::DesignManagement::Action.events.keys.each do |event_name| value event_name.upcase, value: event_name, description: "A #{event_name} event" diff --git a/app/graphql/types/diff_paths_input_type.rb b/app/graphql/types/diff_paths_input_type.rb index 864cec1ab07..d148b7656eb 100644 --- a/app/graphql/types/diff_paths_input_type.rb +++ b/app/graphql/types/diff_paths_input_type.rb @@ -1,12 +1,10 @@ # frozen_string_literal: true module Types - # rubocop: disable Graphql/AuthorizeTypes class DiffPathsInputType < BaseInputObject argument :old_path, GraphQL::STRING_TYPE, required: false, description: 'The path of the file on the start sha.' argument :new_path, GraphQL::STRING_TYPE, required: false, description: 'The path of the file on the head sha.' end - # rubocop: enable Graphql/AuthorizeTypes end diff --git a/app/graphql/types/error_tracking/sentry_error_status_enum.rb b/app/graphql/types/error_tracking/sentry_error_status_enum.rb index df68eef4f3c..10579bcbfb1 100644 --- a/app/graphql/types/error_tracking/sentry_error_status_enum.rb +++ b/app/graphql/types/error_tracking/sentry_error_status_enum.rb @@ -6,10 +6,10 @@ module Types graphql_name 'SentryErrorStatus' description 'State of a Sentry error' - value 'RESOLVED', value: 'resolved', description: 'Error has been resolved' - value 'RESOLVED_IN_NEXT_RELEASE', value: 'resolvedInNextRelease', description: 'Error has been ignored until next release' - value 'UNRESOLVED', value: 'unresolved', description: 'Error is unresolved' - value 'IGNORED', value: 'ignored', description: 'Error has been ignored' + value 'RESOLVED', value: 'resolved', description: 'Error has been resolved.' + value 'RESOLVED_IN_NEXT_RELEASE', value: 'resolvedInNextRelease', description: 'Error has been ignored until next release.' + value 'UNRESOLVED', value: 'unresolved', description: 'Error is unresolved.' + value 'IGNORED', value: 'ignored', description: 'Error has been ignored.' end end end diff --git a/app/graphql/types/global_id_type.rb b/app/graphql/types/global_id_type.rb index ed28c3ffd7e..750bd1bfe8d 100644 --- a/app/graphql/types/global_id_type.rb +++ b/app/graphql/types/global_id_type.rb @@ -19,7 +19,14 @@ end module Types class GlobalIDType < BaseScalar graphql_name 'GlobalID' - description 'A global identifier' + description <<~DESC + A global identifier. + + A global identifier represents an object uniquely across the application. + An example of such an identifier is "gid://gitlab/User/1". + + Global identifiers are encoded as strings. + DESC # @param value [GID] # @return [String] @@ -46,35 +53,40 @@ module Types @id_types[model_class] ||= Class.new(self) do graphql_name "#{model_class.name.gsub(/::/, '')}ID" - description "Identifier of #{model_class.name}." + description <<~MD + A `#{graphql_name}` is a global ID. It is encoded as a string. + + An example `#{graphql_name}` is: `"#{::Gitlab::GlobalId.build(model_name: model_class.name, id: 1)}"`. + MD - self.define_singleton_method(:to_s) do + define_singleton_method(:to_s) do graphql_name end - self.define_singleton_method(:inspect) do + define_singleton_method(:inspect) do graphql_name end - self.define_singleton_method(:coerce_result) do |gid, ctx| + define_singleton_method(:coerce_result) do |gid, ctx| global_id = ::Gitlab::GlobalId.as_global_id(gid, model_name: model_class.name) - if suitable?(global_id) - global_id.to_s - else - raise GraphQL::CoercionError, "Expected a #{model_class.name} ID, got #{global_id}" - end + next global_id.to_s if suitable?(global_id) + + raise GraphQL::CoercionError, "Expected a #{model_class.name} ID, got #{global_id}" end - self.define_singleton_method(:suitable?) do |gid| - gid&.model_class&.ancestors&.include?(model_class) + define_singleton_method(:suitable?) do |gid| + next false if gid.nil? + + gid.model_name.safe_constantize.present? && + gid.model_class.ancestors.include?(model_class) end - self.define_singleton_method(:coerce_input) do |string, ctx| + define_singleton_method(:coerce_input) do |string, ctx| gid = super(string, ctx) - raise GraphQL::CoercionError, "#{string.inspect} does not represent an instance of #{model_class.name}" unless suitable?(gid) + next gid if suitable?(gid) - gid + raise GraphQL::CoercionError, "#{string.inspect} does not represent an instance of #{model_class.name}" end end end diff --git a/app/graphql/types/group_type.rb b/app/graphql/types/group_type.rb index 0aaeb8d20df..7a84e76657b 100644 --- a/app/graphql/types/group_type.rb +++ b/app/graphql/types/group_type.rb @@ -95,6 +95,10 @@ module Types field :container_repositories_count, GraphQL::INT_TYPE, null: false, description: 'Number of container repositories in the group.' + field :packages, + description: 'Packages of the group.', + resolver: Resolvers::GroupPackagesResolver + def label(title:) BatchLoader::GraphQL.for(title).batch(key: group) do |titles, loader, args| LabelsFinder diff --git a/app/graphql/types/issuable_sort_enum.rb b/app/graphql/types/issuable_sort_enum.rb index a6d52124d99..f6e17d8988e 100644 --- a/app/graphql/types/issuable_sort_enum.rb +++ b/app/graphql/types/issuable_sort_enum.rb @@ -5,11 +5,11 @@ module Types graphql_name 'IssuableSort' description 'Values for sorting issuables' - value 'PRIORITY_ASC', 'Priority by ascending order', value: :priority_asc - value 'PRIORITY_DESC', 'Priority by descending order', value: :priority_desc - value 'LABEL_PRIORITY_ASC', 'Label priority by ascending order', value: :label_priority_asc - value 'LABEL_PRIORITY_DESC', 'Label priority by descending order', value: :label_priority_desc - value 'MILESTONE_DUE_ASC', 'Milestone due date by ascending order', value: :milestone_due_asc - value 'MILESTONE_DUE_DESC', 'Milestone due date by descending order', value: :milestone_due_desc + value 'PRIORITY_ASC', 'Priority by ascending order.', value: :priority_asc + value 'PRIORITY_DESC', 'Priority by descending order.', value: :priority_desc + value 'LABEL_PRIORITY_ASC', 'Label priority by ascending order.', value: :label_priority_asc + value 'LABEL_PRIORITY_DESC', 'Label priority by descending order.', value: :label_priority_desc + value 'MILESTONE_DUE_ASC', 'Milestone due date by ascending order.', value: :milestone_due_asc + value 'MILESTONE_DUE_DESC', 'Milestone due date by descending order.', value: :milestone_due_desc end end diff --git a/app/graphql/types/issuable_state_enum.rb b/app/graphql/types/issuable_state_enum.rb index 543b7f8e5b2..5a1b11b3bdc 100644 --- a/app/graphql/types/issuable_state_enum.rb +++ b/app/graphql/types/issuable_state_enum.rb @@ -5,9 +5,9 @@ module Types graphql_name 'IssuableState' description 'State of a GitLab issue or merge request' - value 'opened' - value 'closed' - value 'locked' - value 'all' + value 'opened', description: 'In open state.' + value 'closed', description: 'In closed state.' + value 'locked', description: 'Discussion has been locked.' + value 'all', description: 'All available.' end end diff --git a/app/graphql/types/issue_sort_enum.rb b/app/graphql/types/issue_sort_enum.rb index 08762264b1b..bf900fe3525 100644 --- a/app/graphql/types/issue_sort_enum.rb +++ b/app/graphql/types/issue_sort_enum.rb @@ -5,11 +5,11 @@ module Types graphql_name 'IssueSort' description 'Values for sorting issues' - value 'DUE_DATE_ASC', 'Due date by ascending order', value: :due_date_asc - value 'DUE_DATE_DESC', 'Due date by descending order', value: :due_date_desc - value 'RELATIVE_POSITION_ASC', 'Relative position by ascending order', value: :relative_position_asc - value 'SEVERITY_ASC', 'Severity from less critical to more critical', value: :severity_asc - value 'SEVERITY_DESC', 'Severity from more critical to less critical', value: :severity_desc + value 'DUE_DATE_ASC', 'Due date by ascending order.', value: :due_date_asc + value 'DUE_DATE_DESC', 'Due date by descending order.', value: :due_date_desc + value 'RELATIVE_POSITION_ASC', 'Relative position by ascending order.', value: :relative_position_asc + value 'SEVERITY_ASC', 'Severity from less critical to more critical.', value: :severity_asc + value 'SEVERITY_DESC', 'Severity from more critical to less critical.', value: :severity_desc end end diff --git a/app/graphql/types/issue_state_event_enum.rb b/app/graphql/types/issue_state_event_enum.rb index 6a9d840831d..165b9c28367 100644 --- a/app/graphql/types/issue_state_event_enum.rb +++ b/app/graphql/types/issue_state_event_enum.rb @@ -5,7 +5,7 @@ module Types graphql_name 'IssueStateEvent' description 'Values for issue state events' - value 'REOPEN', 'Reopens the issue', value: 'reopen' - value 'CLOSE', 'Closes the issue', value: 'close' + value 'REOPEN', 'Reopens the issue.', value: 'reopen' + value 'CLOSE', 'Closes the issue.', value: 'close' end end diff --git a/app/graphql/types/jira_users_mapping_input_type.rb b/app/graphql/types/jira_users_mapping_input_type.rb index 0c26ea87df2..61e3240ecf3 100644 --- a/app/graphql/types/jira_users_mapping_input_type.rb +++ b/app/graphql/types/jira_users_mapping_input_type.rb @@ -1,7 +1,6 @@ # frozen_string_literal: true module Types - # rubocop: disable Graphql/AuthorizeTypes class JiraUsersMappingInputType < BaseInputObject graphql_name 'JiraUsersMappingInputType' @@ -14,5 +13,4 @@ module Types required: false, description: 'Id of the GitLab user.' end - # rubocop: enable Graphql/AuthorizeTypes end diff --git a/app/graphql/types/label_type.rb b/app/graphql/types/label_type.rb index 94fd15e075c..4e8718a80da 100644 --- a/app/graphql/types/label_type.rb +++ b/app/graphql/types/label_type.rb @@ -19,5 +19,9 @@ module Types description: 'Background color of the label.' field :text_color, GraphQL::STRING_TYPE, null: false, description: 'Text color of the label.' + field :created_at, Types::TimeType, null: false, + description: 'When this label was created.' + field :updated_at, Types::TimeType, null: false, + description: 'When this label was last updated.' end end diff --git a/app/graphql/types/merge_request_sort_enum.rb b/app/graphql/types/merge_request_sort_enum.rb index c64ae367a76..92a71998d91 100644 --- a/app/graphql/types/merge_request_sort_enum.rb +++ b/app/graphql/types/merge_request_sort_enum.rb @@ -5,7 +5,7 @@ module Types 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 + 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_state_enum.rb b/app/graphql/types/merge_request_state_enum.rb index c14b9f80a53..a2d7bd0306c 100644 --- a/app/graphql/types/merge_request_state_enum.rb +++ b/app/graphql/types/merge_request_state_enum.rb @@ -5,6 +5,6 @@ module Types graphql_name 'MergeRequestState' description 'State of a GitLab merge request' - value 'merged', description: "Merge Request has been merged" + value 'merged', description: "Merge Request has been merged." end end diff --git a/app/graphql/types/merge_request_type.rb b/app/graphql/types/merge_request_type.rb index 10f324e901a..449286915f2 100644 --- a/app/graphql/types/merge_request_type.rb +++ b/app/graphql/types/merge_request_type.rb @@ -54,7 +54,7 @@ module Types field :target_branch, GraphQL::STRING_TYPE, null: false, description: 'Target branch of the merge request.' field :work_in_progress, GraphQL::BOOLEAN_TYPE, method: :work_in_progress?, null: false, - description: 'Indicates if the merge request is a work in progress (WIP).' + description: 'Indicates if the merge request is a draft.' field :merge_when_pipeline_succeeds, GraphQL::BOOLEAN_TYPE, null: true, description: 'Indicates if the merge has been set to be merged when its pipeline succeeds (MWPS).' field :diff_head_sha, GraphQL::STRING_TYPE, null: true, @@ -108,6 +108,10 @@ module Types null: false, calls_gitaly: true, method: :target_branch_exists?, description: 'Indicates if the target branch of the merge request exists.' + field :diverged_from_target_branch, GraphQL::BOOLEAN_TYPE, + null: false, calls_gitaly: true, + method: :diverged_from_target_branch?, + description: 'Indicates if the source branch is behind the target branch.' field :mergeable_discussions_state, GraphQL::BOOLEAN_TYPE, null: true, description: 'Indicates if all discussions in the merge request have been resolved, allowing the merge request to be merged.' field :web_url, GraphQL::STRING_TYPE, null: true, diff --git a/app/graphql/types/merge_strategy_enum.rb b/app/graphql/types/merge_strategy_enum.rb new file mode 100644 index 00000000000..2120dc576eb --- /dev/null +++ b/app/graphql/types/merge_strategy_enum.rb @@ -0,0 +1,9 @@ +# frozen_string_literal: true + +module Types + class MergeStrategyEnum < BaseEnum + AutoMergeService.all_strategies_ordered_by_preference.each do |strat| + value strat.upcase, value: strat, description: "Use the #{strat} merge strategy." + end + end +end diff --git a/app/graphql/types/milestone_state_enum.rb b/app/graphql/types/milestone_state_enum.rb index e3b60395c9b..f3797f8f9e5 100644 --- a/app/graphql/types/milestone_state_enum.rb +++ b/app/graphql/types/milestone_state_enum.rb @@ -5,7 +5,7 @@ module Types graphql_name 'MilestoneStateEnum' description 'Current state of milestone' - value 'active', description: 'Milestone is currently active' - value 'closed', description: 'Milestone is closed' + value 'active', description: 'Milestone is currently active.' + value 'closed', description: 'Milestone is closed.' end end diff --git a/app/graphql/types/mutation_operation_mode_enum.rb b/app/graphql/types/mutation_operation_mode_enum.rb index 37e83e7a2e1..75c1d7cd4a6 100644 --- a/app/graphql/types/mutation_operation_mode_enum.rb +++ b/app/graphql/types/mutation_operation_mode_enum.rb @@ -7,8 +7,8 @@ module Types # Suggested param name for the enum: `operation_mode` - value 'REPLACE', 'Performs a replace operation' - value 'APPEND', 'Performs an append operation' - value 'REMOVE', 'Performs a removal operation' + value 'REPLACE', 'Performs a replace operation.' + value 'APPEND', 'Performs an append operation.' + value 'REMOVE', 'Performs a removal operation.' end end diff --git a/app/graphql/types/mutation_type.rb b/app/graphql/types/mutation_type.rb index 166f5617da2..76ffddf416f 100644 --- a/app/graphql/types/mutation_type.rb +++ b/app/graphql/types/mutation_type.rb @@ -24,6 +24,7 @@ module Types mount_mutation Mutations::AwardEmojis::Toggle mount_mutation Mutations::Boards::Create mount_mutation Mutations::Boards::Destroy + mount_mutation Mutations::Boards::Update mount_mutation Mutations::Boards::Issues::IssueMoveList mount_mutation Mutations::Boards::Lists::Create mount_mutation Mutations::Boards::Lists::Update @@ -43,6 +44,7 @@ module Types mount_mutation Mutations::Issues::Update mount_mutation Mutations::Issues::Move mount_mutation Mutations::Labels::Create + mount_mutation Mutations::MergeRequests::Accept mount_mutation Mutations::MergeRequests::Create mount_mutation Mutations::MergeRequests::Update mount_mutation Mutations::MergeRequests::SetLabels @@ -57,19 +59,15 @@ module Types mount_mutation Mutations::Notes::Create::Note, calls_gitaly: true mount_mutation Mutations::Notes::Create::DiffNote, calls_gitaly: true mount_mutation Mutations::Notes::Create::ImageDiffNote, calls_gitaly: true - mount_mutation Mutations::Notes::Update::Note, - description: 'Updates a Note. If the body of the Note contains only quick actions, ' \ - 'the Note will be destroyed during the update, and no Note will be ' \ - 'returned' - mount_mutation Mutations::Notes::Update::ImageDiffNote, - description: 'Updates a DiffNote on an image (a `Note` where the `position.positionType` is `"image"`). ' \ - 'If the body of the Note contains only quick actions, the Note will be ' \ - 'destroyed during the update, and no Note will be returned' + mount_mutation Mutations::Notes::Update::Note + mount_mutation Mutations::Notes::Update::ImageDiffNote mount_mutation Mutations::Notes::RepositionImageDiffNote mount_mutation Mutations::Notes::Destroy mount_mutation Mutations::Releases::Create mount_mutation Mutations::Releases::Update mount_mutation Mutations::Releases::Delete + mount_mutation Mutations::ReleaseAssetLinks::Create + mount_mutation Mutations::ReleaseAssetLinks::Update mount_mutation Mutations::Terraform::State::Delete mount_mutation Mutations::Terraform::State::Lock mount_mutation Mutations::Terraform::State::Unlock @@ -95,6 +93,7 @@ module Types mount_mutation Mutations::Ci::Pipeline::Retry mount_mutation Mutations::Ci::CiCdSettingsUpdate mount_mutation Mutations::Namespace::PackageSettings::Update + mount_mutation Mutations::UserCallouts::Create end end diff --git a/app/graphql/types/notes/diff_image_position_input_type.rb b/app/graphql/types/notes/diff_image_position_input_type.rb index 23b53b20815..dd5c8f20cc3 100644 --- a/app/graphql/types/notes/diff_image_position_input_type.rb +++ b/app/graphql/types/notes/diff_image_position_input_type.rb @@ -2,7 +2,6 @@ module Types module Notes - # rubocop: disable Graphql/AuthorizeTypes class DiffImagePositionInputType < DiffPositionBaseInputType graphql_name 'DiffImagePositionInput' @@ -15,6 +14,5 @@ module Types argument :height, GraphQL::INT_TYPE, required: true, description: copy_field_description(Types::Notes::DiffPositionType, :height) end - # rubocop: enable Graphql/AuthorizeTypes end end diff --git a/app/graphql/types/notes/diff_position_base_input_type.rb b/app/graphql/types/notes/diff_position_base_input_type.rb index a9b4e1a8948..c8f9f9028cc 100644 --- a/app/graphql/types/notes/diff_position_base_input_type.rb +++ b/app/graphql/types/notes/diff_position_base_input_type.rb @@ -2,7 +2,6 @@ module Types module Notes - # rubocop: disable Graphql/AuthorizeTypes class DiffPositionBaseInputType < BaseInputObject argument :head_sha, GraphQL::STRING_TYPE, required: true, description: copy_field_description(Types::DiffRefsType, :head_sha) @@ -17,6 +16,5 @@ module Types description: 'The paths of the file that was changed. ' \ 'Both of the properties of this input are optional, but at least one of them is required' end - # rubocop: enable Graphql/AuthorizeTypes end end diff --git a/app/graphql/types/notes/diff_position_input_type.rb b/app/graphql/types/notes/diff_position_input_type.rb index 02c91e173cb..7ec5fd9e086 100644 --- a/app/graphql/types/notes/diff_position_input_type.rb +++ b/app/graphql/types/notes/diff_position_input_type.rb @@ -2,15 +2,13 @@ module Types module Notes - # rubocop: disable Graphql/AuthorizeTypes class DiffPositionInputType < DiffPositionBaseInputType graphql_name 'DiffPositionInput' argument :old_line, GraphQL::INT_TYPE, required: false, description: copy_field_description(Types::Notes::DiffPositionType, :old_line) - argument :new_line, GraphQL::INT_TYPE, required: true, + argument :new_line, GraphQL::INT_TYPE, required: false, description: copy_field_description(Types::Notes::DiffPositionType, :new_line) end - # rubocop: enable Graphql/AuthorizeTypes end end diff --git a/app/graphql/types/notes/position_type_enum.rb b/app/graphql/types/notes/position_type_enum.rb index abdb2cfc804..9939f6511ce 100644 --- a/app/graphql/types/notes/position_type_enum.rb +++ b/app/graphql/types/notes/position_type_enum.rb @@ -6,8 +6,8 @@ module Types graphql_name 'DiffPositionType' description 'Type of file the position refers to' - value 'text' - value 'image' + value 'text', description: "A text file" + value 'image', description: "An image" end end end diff --git a/app/graphql/types/notes/update_diff_image_position_input_type.rb b/app/graphql/types/notes/update_diff_image_position_input_type.rb index 1b915b65ae9..ab27f6b9ad3 100644 --- a/app/graphql/types/notes/update_diff_image_position_input_type.rb +++ b/app/graphql/types/notes/update_diff_image_position_input_type.rb @@ -3,8 +3,6 @@ module Types module Notes # InputType used for updateImageDiffNote mutation. - # - # rubocop: disable Graphql/AuthorizeTypes class UpdateDiffImagePositionInputType < BaseInputObject graphql_name 'UpdateDiffImagePositionInput' @@ -32,6 +30,5 @@ module Types end end end - # rubocop: enable Graphql/AuthorizeTypes end end diff --git a/app/graphql/types/project_type.rb b/app/graphql/types/project_type.rb index 7205c615271..9a3f2e311e6 100644 --- a/app/graphql/types/project_type.rb +++ b/app/graphql/types/project_type.rb @@ -181,7 +181,7 @@ module Types field :packages, description: 'Packages of the project.', - resolver: Resolvers::PackagesResolver + resolver: Resolvers::ProjectPackagesResolver field :pipelines, null: true, @@ -273,6 +273,12 @@ module Types description: 'Integrations which can receive alerts for the project.', resolver: Resolvers::AlertManagement::IntegrationsResolver + field :alert_management_http_integrations, + Types::AlertManagement::HttpIntegrationType.connection_type, + null: true, + description: 'HTTP Integrations which can receive alerts for the project.', + resolver: Resolvers::AlertManagement::HttpIntegrationsResolver + field :releases, Types::ReleaseType.connection_type, null: true, diff --git a/app/graphql/types/projects/namespace_project_sort_enum.rb b/app/graphql/types/projects/namespace_project_sort_enum.rb index ede29748beb..bd7058196dd 100644 --- a/app/graphql/types/projects/namespace_project_sort_enum.rb +++ b/app/graphql/types/projects/namespace_project_sort_enum.rb @@ -6,8 +6,8 @@ module Types graphql_name 'NamespaceProjectSort' description 'Values for sorting projects' - value 'SIMILARITY', 'Most similar to the search query', value: :similarity - value 'STORAGE', 'Sort by storage size', value: :storage + value 'SIMILARITY', 'Most similar to the search query.', value: :similarity + value 'STORAGE', 'Sort by storage size.', value: :storage end end end diff --git a/app/graphql/types/query_type.rb b/app/graphql/types/query_type.rb index 1d1ab4f2e17..74818bfcd42 100644 --- a/app/graphql/types/query_type.rb +++ b/app/graphql/types/query_type.rb @@ -78,14 +78,20 @@ module Types field :issue, Types::IssueType, null: true, - description: 'Find an issue.' do + 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, + field :instance_statistics_measurements, Types::Admin::Analytics::UsageTrends::MeasurementType.connection_type, null: true, description: 'Get statistics on the instance.', - resolver: Resolvers::Admin::Analytics::InstanceStatistics::MeasurementsResolver + deprecated: { reason: 'This field was renamed. Use the `usageTrendsMeasurements` field instead', milestone: '13.10' }, + resolver: Resolvers::Admin::Analytics::UsageTrends::MeasurementsResolver + + field :usage_trends_measurements, Types::Admin::Analytics::UsageTrends::MeasurementType.connection_type, + null: true, + description: 'Get statistics on the instance.', + resolver: Resolvers::Admin::Analytics::UsageTrends::MeasurementsResolver field :ci_application_settings, Types::Ci::ApplicationSettingType, null: true, diff --git a/app/graphql/types/range_input_type.rb b/app/graphql/types/range_input_type.rb index b75c3669fbf..e31b8ecd811 100644 --- a/app/graphql/types/range_input_type.rb +++ b/app/graphql/types/range_input_type.rb @@ -1,7 +1,6 @@ # frozen_string_literal: true module Types - # rubocop: disable Graphql/AuthorizeTypes class RangeInputType < BaseInputObject def self.[](type, closed = true) @subtypes ||= {} @@ -25,5 +24,4 @@ module Types to_h end end - # rubocop: enable Graphql/AuthorizeTypes end diff --git a/app/graphql/types/release_asset_link_input_type.rb b/app/graphql/types/release_asset_link_input_type.rb index 242d19b683f..17d05a73797 100644 --- a/app/graphql/types/release_asset_link_input_type.rb +++ b/app/graphql/types/release_asset_link_input_type.rb @@ -1,25 +1,10 @@ # frozen_string_literal: true module Types - # rubocop: disable Graphql/AuthorizeTypes class ReleaseAssetLinkInputType < BaseInputObject graphql_name 'ReleaseAssetLinkInput' description 'Fields that are available when modifying a release asset link' - argument :name, GraphQL::STRING_TYPE, - required: true, - description: 'Name of the asset link.' - - argument :url, GraphQL::STRING_TYPE, - required: true, - description: 'URL of the asset link.' - - argument :direct_asset_path, GraphQL::STRING_TYPE, - required: false, as: :filepath, - description: 'Relative path for a direct asset link.' - - argument :link_type, Types::ReleaseAssetLinkTypeEnum, - required: false, default_value: 'other', - description: 'The type of the asset link.' + include Types::ReleaseAssetLinkSharedInputArguments end end diff --git a/app/graphql/types/release_asset_link_shared_input_arguments.rb b/app/graphql/types/release_asset_link_shared_input_arguments.rb new file mode 100644 index 00000000000..4aa247e47cc --- /dev/null +++ b/app/graphql/types/release_asset_link_shared_input_arguments.rb @@ -0,0 +1,25 @@ +# frozen_string_literal: true + +module Types + module ReleaseAssetLinkSharedInputArguments + extend ActiveSupport::Concern + + included do + argument :name, GraphQL::STRING_TYPE, + required: true, + description: 'Name of the asset link.' + + argument :url, GraphQL::STRING_TYPE, + required: true, + description: 'URL of the asset link.' + + argument :direct_asset_path, GraphQL::STRING_TYPE, + required: false, as: :filepath, + description: 'Relative path for a direct asset link.' + + argument :link_type, Types::ReleaseAssetLinkTypeEnum, + required: false, default_value: 'other', + description: 'The type of the asset link.' + end + end +end diff --git a/app/graphql/types/release_assets_input_type.rb b/app/graphql/types/release_assets_input_type.rb index f50be89d43f..2c8d3de3495 100644 --- a/app/graphql/types/release_assets_input_type.rb +++ b/app/graphql/types/release_assets_input_type.rb @@ -1,7 +1,6 @@ # frozen_string_literal: true module Types - # rubocop: disable Graphql/AuthorizeTypes class ReleaseAssetsInputType < BaseInputObject graphql_name 'ReleaseAssetsInput' description 'Fields that are available when modifying release assets' diff --git a/app/graphql/types/release_sort_enum.rb b/app/graphql/types/release_sort_enum.rb index 2f9af1bced9..f51b73d89f1 100644 --- a/app/graphql/types/release_sort_enum.rb +++ b/app/graphql/types/release_sort_enum.rb @@ -9,10 +9,10 @@ module Types # Borrowed from Types::SortEnum # These values/descriptions should stay in-sync as much as possible. - value 'CREATED_DESC', 'Created at descending order', value: :created_desc - value 'CREATED_ASC', 'Created at ascending order', value: :created_asc + value 'CREATED_DESC', 'Created at descending order.', value: :created_desc + value 'CREATED_ASC', 'Created at ascending order.', value: :created_asc - value 'RELEASED_AT_DESC', 'Released at by descending order', value: :released_at_desc - value 'RELEASED_AT_ASC', 'Released at by ascending order', value: :released_at_asc + value 'RELEASED_AT_DESC', 'Released at by descending order.', value: :released_at_desc + value 'RELEASED_AT_ASC', 'Released at by ascending order.', value: :released_at_asc end end diff --git a/app/graphql/types/snippets/blob_action_input_type.rb b/app/graphql/types/snippets/blob_action_input_type.rb index c4289375f6b..13eade3dcc4 100644 --- a/app/graphql/types/snippets/blob_action_input_type.rb +++ b/app/graphql/types/snippets/blob_action_input_type.rb @@ -2,7 +2,7 @@ module Types module Snippets - class BlobActionInputType < BaseInputObject # rubocop:disable Graphql/AuthorizeTypes + class BlobActionInputType < BaseInputObject graphql_name 'SnippetBlobActionInputType' description 'Represents an action to perform over a snippet file' diff --git a/app/graphql/types/snippets/blob_type.rb b/app/graphql/types/snippets/blob_type.rb index fb0c1d9409b..fb9ee380705 100644 --- a/app/graphql/types/snippets/blob_type.rb +++ b/app/graphql/types/snippets/blob_type.rb @@ -14,7 +14,6 @@ module Types field :plain_data, GraphQL::STRING_TYPE, description: 'Blob plain highlighted data.', - calls_gitaly: true, null: true field :raw_path, GraphQL::STRING_TYPE, diff --git a/app/graphql/types/sort_enum.rb b/app/graphql/types/sort_enum.rb index c3a76330fe9..ff994039b6d 100644 --- a/app/graphql/types/sort_enum.rb +++ b/app/graphql/types/sort_enum.rb @@ -7,14 +7,14 @@ module Types # Deprecated, as we prefer uppercase enums # https://gitlab.com/groups/gitlab-org/-/epics/1838 - value 'updated_desc', 'Updated at descending order', value: :updated_desc, deprecated: { reason: 'Use UPDATED_DESC', milestone: '13.5' } - value 'updated_asc', 'Updated at ascending order', value: :updated_asc, deprecated: { reason: 'Use UPDATED_ASC', milestone: '13.5' } - value 'created_desc', 'Created at descending order', value: :created_desc, deprecated: { reason: 'Use CREATED_DESC', milestone: '13.5' } - value 'created_asc', 'Created at ascending order', value: :created_asc, deprecated: { reason: 'Use CREATED_ASC', milestone: '13.5' } + value 'updated_desc', 'Updated at descending order.', value: :updated_desc, deprecated: { reason: 'Use UPDATED_DESC', milestone: '13.5' } + value 'updated_asc', 'Updated at ascending order.', value: :updated_asc, deprecated: { reason: 'Use UPDATED_ASC', milestone: '13.5' } + value 'created_desc', 'Created at descending order.', value: :created_desc, deprecated: { reason: 'Use CREATED_DESC', milestone: '13.5' } + value 'created_asc', 'Created at ascending order.', value: :created_asc, deprecated: { reason: 'Use CREATED_ASC', milestone: '13.5' } - value 'UPDATED_DESC', 'Updated at descending order', value: :updated_desc - value 'UPDATED_ASC', 'Updated at ascending order', value: :updated_asc - value 'CREATED_DESC', 'Created at descending order', value: :created_desc - value 'CREATED_ASC', 'Created at ascending order', value: :created_asc + value 'UPDATED_DESC', 'Updated at descending order.', value: :updated_desc + value 'UPDATED_ASC', 'Updated at ascending order.', value: :updated_asc + value 'CREATED_DESC', 'Created at descending order.', value: :created_desc + value 'CREATED_ASC', 'Created at ascending order.', value: :created_asc end end diff --git a/app/graphql/types/time_type.rb b/app/graphql/types/time_type.rb index c31e4873df0..2db14953308 100644 --- a/app/graphql/types/time_type.rb +++ b/app/graphql/types/time_type.rb @@ -3,7 +3,13 @@ module Types class TimeType < BaseScalar graphql_name 'Time' - description 'Time represented in ISO 8601' + description <<~DESC + Time represented in ISO 8601. + + For example: "2021-03-09T14:58:50+00:00". + + See `https://www.iso.org/iso-8601-date-and-time-format.html`. + DESC def self.coerce_input(value, ctx) Time.parse(value) diff --git a/app/graphql/types/timeframe_input_type.rb b/app/graphql/types/timeframe_input_type.rb index 79c1bc5cf01..02a0ec7df7a 100644 --- a/app/graphql/types/timeframe_input_type.rb +++ b/app/graphql/types/timeframe_input_type.rb @@ -1,10 +1,8 @@ # frozen_string_literal: true module Types - # rubocop: disable Graphql/AuthorizeTypes class TimeframeInputType < RangeInputType[::Types::DateType] graphql_name 'Timeframe' description 'A time-frame defined as a closed inclusive range of two dates' end - # rubocop: enable Graphql/AuthorizeTypes end diff --git a/app/graphql/types/todo_action_enum.rb b/app/graphql/types/todo_action_enum.rb index 0e538838474..ef43b6eb464 100644 --- a/app/graphql/types/todo_action_enum.rb +++ b/app/graphql/types/todo_action_enum.rb @@ -2,12 +2,14 @@ module Types class TodoActionEnum < BaseEnum - value 'assigned', value: 1 - value 'mentioned', value: 2 - value 'build_failed', value: 3 - value 'marked', value: 4 - value 'approval_required', value: 5 - value 'unmergeable', value: 6 - value 'directly_addressed', value: 7 + value 'assigned', value: 1, description: 'User was assigned.' + value 'mentioned', value: 2, description: 'User was mentioned.' + value 'build_failed', value: 3, description: 'Build triggered by the user failed.' + value 'marked', value: 4, description: 'User added a TODO.' + value 'approval_required', value: 5, description: 'User was set as an approver.' + value 'unmergeable', value: 6, description: 'Merge request authored by the user could not be merged.' + value 'directly_addressed', value: 7, description: 'User was directly addressed.' + value 'merge_train_removed', value: 8, description: 'Merge request authored by the user was removed from the merge train.' + value 'review_requested', value: 9, description: 'Review was requested from the user.' end end diff --git a/app/graphql/types/todo_state_enum.rb b/app/graphql/types/todo_state_enum.rb index 29a28b5208d..604e2a62f70 100644 --- a/app/graphql/types/todo_state_enum.rb +++ b/app/graphql/types/todo_state_enum.rb @@ -2,7 +2,7 @@ module Types class TodoStateEnum < BaseEnum - value 'pending' - value 'done' + value 'pending', description: "The state of the todo is pending." + value 'done', description: "The state of the todo is done." end end diff --git a/app/graphql/types/todo_target_enum.rb b/app/graphql/types/todo_target_enum.rb index b797722fef8..ebf65e99936 100644 --- a/app/graphql/types/todo_target_enum.rb +++ b/app/graphql/types/todo_target_enum.rb @@ -2,11 +2,11 @@ module Types class TodoTargetEnum < BaseEnum - value 'COMMIT', value: 'Commit', description: 'A Commit' - value 'ISSUE', value: 'Issue', description: 'An Issue' - value 'MERGEREQUEST', value: 'MergeRequest', description: 'A MergeRequest' - value 'DESIGN', value: 'DesignManagement::Design', description: 'A Design' - value 'ALERT', value: 'AlertManagement::Alert', description: 'An Alert' + value 'COMMIT', value: 'Commit', description: 'A Commit.' + value 'ISSUE', value: 'Issue', description: 'An Issue.' + value 'MERGEREQUEST', value: 'MergeRequest', description: 'A MergeRequest.' + value 'DESIGN', value: 'DesignManagement::Design', description: 'A Design.' + value 'ALERT', value: 'AlertManagement::Alert', description: 'An Alert.' end end diff --git a/app/graphql/types/tree/blob_type.rb b/app/graphql/types/tree/blob_type.rb index 3823bd94083..d192c8d3c57 100644 --- a/app/graphql/types/tree/blob_type.rb +++ b/app/graphql/types/tree/blob_type.rb @@ -15,6 +15,7 @@ module Types field :web_path, GraphQL::STRING_TYPE, null: true, description: 'Web path of the blob.' field :lfs_oid, GraphQL::STRING_TYPE, null: true, + calls_gitaly: true, description: 'LFS ID of the blob.' field :mode, GraphQL::STRING_TYPE, null: true, description: 'Blob mode in numeric format.' diff --git a/app/graphql/types/user_callout_feature_name_enum.rb b/app/graphql/types/user_callout_feature_name_enum.rb new file mode 100644 index 00000000000..410ca5e1c95 --- /dev/null +++ b/app/graphql/types/user_callout_feature_name_enum.rb @@ -0,0 +1,12 @@ +# frozen_string_literal: true + +module Types + class UserCalloutFeatureNameEnum < BaseEnum + graphql_name 'UserCalloutFeatureNameEnum' + description 'Name of the feature that the callout is for.' + + ::UserCallout.feature_names.keys.each do |feature_name| + value feature_name.upcase, value: feature_name, description: "Callout feature name for #{feature_name}." + end + end +end diff --git a/app/graphql/types/user_callout_type.rb b/app/graphql/types/user_callout_type.rb new file mode 100644 index 00000000000..12f4fdea878 --- /dev/null +++ b/app/graphql/types/user_callout_type.rb @@ -0,0 +1,12 @@ +# frozen_string_literal: true + +module Types + class UserCalloutType < BaseObject # rubocop:disable Graphql/AuthorizeTypes + graphql_name 'UserCallout' + + field :feature_name, UserCalloutFeatureNameEnum, null: false, + description: 'Name of the feature that the callout is for.' + field :dismissed_at, Types::TimeType, null: true, + description: 'Date when the callout was dismissed.' + end +end diff --git a/app/graphql/types/user_state_enum.rb b/app/graphql/types/user_state_enum.rb index d34936b4c48..5adec17672e 100644 --- a/app/graphql/types/user_state_enum.rb +++ b/app/graphql/types/user_state_enum.rb @@ -5,8 +5,8 @@ module Types graphql_name 'UserState' description 'Possible states of a user' - value 'active', 'The user is active and is able to use the system', value: 'active' - value 'blocked', 'The user has been blocked and is prevented from using the system', value: 'blocked' - value 'deactivated', 'The user is no longer active and is unable to use the system', value: 'deactivated' + value 'active', 'The user is active and is able to use the system.', value: 'active' + value 'blocked', 'The user has been blocked and is prevented from using the system.', value: 'blocked' + value 'deactivated', 'The user is no longer active and is unable to use the system.', value: 'deactivated' end end diff --git a/app/graphql/types/user_type.rb b/app/graphql/types/user_type.rb index 0cefc84633d..2cc7d379240 100644 --- a/app/graphql/types/user_type.rb +++ b/app/graphql/types/user_type.rb @@ -67,5 +67,9 @@ module Types null: true, description: 'Snippets authored by the user.', resolver: Resolvers::Users::SnippetsResolver + field :callouts, + Types::UserCalloutType.connection_type, + null: true, + description: 'User callouts that belong to the user.' end end diff --git a/app/graphql/types/visibility_levels_enum.rb b/app/graphql/types/visibility_levels_enum.rb index d5ace24455e..07718679bef 100644 --- a/app/graphql/types/visibility_levels_enum.rb +++ b/app/graphql/types/visibility_levels_enum.rb @@ -3,7 +3,7 @@ module Types class VisibilityLevelsEnum < BaseEnum Gitlab::VisibilityLevel.string_options.each do |name, int_value| - value name.downcase, value: int_value + value name.downcase, value: int_value, description: "#{name.titleize} visibility level." end end end |