diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2022-05-19 10:33:21 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2022-05-19 10:33:21 +0300 |
commit | 36a59d088eca61b834191dacea009677a96c052f (patch) | |
tree | e4f33972dab5d8ef79e3944a9f403035fceea43f /app/graphql | |
parent | a1761f15ec2cae7c7f7bbda39a75494add0dfd6f (diff) |
Add latest changes from gitlab-org/gitlab@15-0-stable-eev15.0.0-rc42
Diffstat (limited to 'app/graphql')
138 files changed, 1109 insertions, 611 deletions
diff --git a/app/graphql/mutations/award_emojis/base.rb b/app/graphql/mutations/award_emojis/base.rb index ce73f2083f2..dc2d46269e6 100644 --- a/app/graphql/mutations/award_emojis/base.rb +++ b/app/graphql/mutations/award_emojis/base.rb @@ -26,12 +26,6 @@ module Mutations private - # TODO: remove this method when the compatibility layer is removed - # See: https://gitlab.com/gitlab-org/gitlab/-/issues/257883 - def find_object(id:) - super(id: ::Types::GlobalIDType[::Awardable].coerce_isolated_input(id)) - end - def authorize!(object) super raise_resource_not_available_error!(NOT_EMOJI_AWARDABLE) unless object.emoji_awardable? diff --git a/app/graphql/mutations/base_mutation.rb b/app/graphql/mutations/base_mutation.rb index 5de042f78d6..d57a097a9e2 100644 --- a/app/graphql/mutations/base_mutation.rb +++ b/app/graphql/mutations/base_mutation.rb @@ -4,7 +4,6 @@ module Mutations class BaseMutation < GraphQL::Schema::RelayClassicMutation include Gitlab::Graphql::Authorize::AuthorizeResource prepend Gitlab::Graphql::CopyFieldDescription - prepend ::Gitlab::Graphql::GlobalIDCompatibility ERROR_MESSAGE = 'You cannot perform write operations on a read-only instance' diff --git a/app/graphql/mutations/boards/update.rb b/app/graphql/mutations/boards/update.rb index 40ab5a5ba7d..7cfce9d2d91 100644 --- a/app/graphql/mutations/boards/update.rb +++ b/app/graphql/mutations/boards/update.rb @@ -33,9 +33,6 @@ module Mutations private def find_object(id:) - # TODO: remove this line when the compatibility layer is removed - # See: https://gitlab.com/gitlab-org/gitlab/-/issues/257883 - id = ::Types::GlobalIDType[::Board].coerce_isolated_input(id) GitlabSchema.find_by_gid(id) end end diff --git a/app/graphql/mutations/ci/ci_cd_settings_update.rb b/app/graphql/mutations/ci/ci_cd_settings_update.rb index dec90ced962..98b8e9567e7 100644 --- a/app/graphql/mutations/ci/ci_cd_settings_update.rb +++ b/app/graphql/mutations/ci/ci_cd_settings_update.rb @@ -2,42 +2,9 @@ module Mutations module Ci - class CiCdSettingsUpdate < BaseMutation + # TODO: Remove in 16.0, see https://gitlab.com/gitlab-org/gitlab/-/merge_requests/87002 + class CiCdSettingsUpdate < ProjectCiCdSettingsUpdate graphql_name 'CiCdSettingsUpdate' - - include FindsProject - - authorize :admin_project - - argument :full_path, GraphQL::Types::ID, - required: true, - description: 'Full Path of the project the settings belong to.' - - argument :keep_latest_artifact, GraphQL::Types::Boolean, - required: false, - description: 'Indicates if the latest artifact should be kept for this project.' - - argument :job_token_scope_enabled, GraphQL::Types::Boolean, - required: false, - description: 'Indicates CI job tokens generated in this project have restricted access to resources.' - - field :ci_cd_settings, - Types::Ci::CiCdSettingType, - null: false, - description: 'CI/CD settings after mutation.' - - def resolve(full_path:, **args) - project = authorized_find!(full_path) - settings = project.ci_cd_settings - settings.update(args) - - { - ci_cd_settings: settings, - errors: errors_on_object(settings) - } - end end end end - -Mutations::Ci::CiCdSettingsUpdate.prepend_mod_with('Mutations::Ci::CiCdSettingsUpdate') diff --git a/app/graphql/mutations/ci/job/base.rb b/app/graphql/mutations/ci/job/base.rb index a9fe26226d9..6ea8e25a58d 100644 --- a/app/graphql/mutations/ci/job/base.rb +++ b/app/graphql/mutations/ci/job/base.rb @@ -11,9 +11,6 @@ module Mutations description: 'ID of the job to mutate.' def find_object(id: ) - # TODO: remove this line when the compatibility layer is removed - # See: https://gitlab.com/gitlab-org/gitlab/-/issues/257883 - id = JobID.coerce_isolated_input(id) GlobalID::Locator.locate(id) end end diff --git a/app/graphql/mutations/ci/pipeline/base.rb b/app/graphql/mutations/ci/pipeline/base.rb index aed8035a52a..503cf6c005f 100644 --- a/app/graphql/mutations/ci/pipeline/base.rb +++ b/app/graphql/mutations/ci/pipeline/base.rb @@ -13,9 +13,6 @@ module Mutations private def find_object(id:) - # TODO: remove this line when the compatibility layer is removed - # See: https://gitlab.com/gitlab-org/gitlab/-/issues/257883 - id = PipelineID.coerce_isolated_input(id) GlobalID::Locator.locate(id) end end diff --git a/app/graphql/mutations/ci/project_ci_cd_settings_update.rb b/app/graphql/mutations/ci/project_ci_cd_settings_update.rb new file mode 100644 index 00000000000..b0cffa2c088 --- /dev/null +++ b/app/graphql/mutations/ci/project_ci_cd_settings_update.rb @@ -0,0 +1,43 @@ +# frozen_string_literal: true + +module Mutations + module Ci + class ProjectCiCdSettingsUpdate < BaseMutation + graphql_name 'ProjectCiCdSettingsUpdate' + + include FindsProject + + authorize :admin_project + + argument :full_path, GraphQL::Types::ID, + required: true, + description: 'Full Path of the project the settings belong to.' + + argument :keep_latest_artifact, GraphQL::Types::Boolean, + required: false, + description: 'Indicates if the latest artifact should be kept for this project.' + + argument :job_token_scope_enabled, GraphQL::Types::Boolean, + required: false, + description: 'Indicates CI job tokens generated in this project have restricted access to resources.' + + field :ci_cd_settings, + Types::Ci::CiCdSettingType, + null: false, + description: 'CI/CD settings after mutation.' + + def resolve(full_path:, **args) + project = authorized_find!(full_path) + settings = project.ci_cd_settings + settings.update(args) + + { + ci_cd_settings: settings, + errors: errors_on_object(settings) + } + end + end + end +end + +Mutations::Ci::ProjectCiCdSettingsUpdate.prepend_mod_with('Mutations::Ci::ProjectCiCdSettingsUpdate') diff --git a/app/graphql/mutations/ci/runner/delete.rb b/app/graphql/mutations/ci/runner/delete.rb index 1713ec0bf6d..db68914a4eb 100644 --- a/app/graphql/mutations/ci/runner/delete.rb +++ b/app/graphql/mutations/ci/runner/delete.rb @@ -23,10 +23,6 @@ module Mutations 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 = RunnerID.coerce_isolated_input(id) - GitlabSchema.find_by_gid(id) end end diff --git a/app/graphql/mutations/ci/runner/update.rb b/app/graphql/mutations/ci/runner/update.rb index 3432840f60f..faccd1273e5 100644 --- a/app/graphql/mutations/ci/runner/update.rb +++ b/app/graphql/mutations/ci/runner/update.rb @@ -61,10 +61,6 @@ module Mutations 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 = RunnerID.coerce_isolated_input(id) - GitlabSchema.find_by_gid(id) end end diff --git a/app/graphql/mutations/ci/runners_registration_token/reset.rb b/app/graphql/mutations/ci/runners_registration_token/reset.rb index 29ef7aa2e81..8c49b682ab0 100644 --- a/app/graphql/mutations/ci/runners_registration_token/reset.rb +++ b/app/graphql/mutations/ci/runners_registration_token/reset.rb @@ -23,19 +23,24 @@ module Mutations null: true, description: 'Runner token after mutation.' - def resolve(**args) + def resolve(type:, id: nil) + scope = authorized_find!(type: type, id: id) + new_token = reset_token(scope) + { - token: reset_token(**args), - errors: [] + token: new_token, + errors: errors_on_object(scope) } end private - def find_object(type:, **args) - id = args[:id] - + def find_object(type:, id: nil) case type + when 'instance_type' + raise Gitlab::Graphql::Errors::ArgumentError, "id must not be specified for '#{type}' scope" if id.present? + + ApplicationSetting.current when 'group_type' GitlabSchema.object_from_id(id, expected_type: ::Group) when 'project_type' @@ -43,20 +48,7 @@ module Mutations end end - def reset_token(type:, **args) - id = args[:id] - scope = nil - - case type - when 'instance_type' - raise Gitlab::Graphql::Errors::ArgumentError, "id must not be specified for '#{type}' scope" if id.present? - - scope = ApplicationSetting.current - authorize!(scope) - when 'group_type', 'project_type' - scope = authorized_find!(type: type, id: id) - end - + def reset_token(scope) ::Ci::Runners::ResetRegistrationTokenService.new(scope, current_user).execute if scope end end diff --git a/app/graphql/mutations/clusters/agent_tokens/create.rb b/app/graphql/mutations/clusters/agent_tokens/create.rb index 07bf2536065..a99a54fa5ed 100644 --- a/app/graphql/mutations/clusters/agent_tokens/create.rb +++ b/app/graphql/mutations/clusters/agent_tokens/create.rb @@ -58,9 +58,6 @@ module Mutations private def find_object(id:) - # TODO: remove this line when the compatibility layer is removed - # See: https://gitlab.com/gitlab-org/gitlab/-/issues/257883 - id = ClusterAgentID.coerce_isolated_input(id) GitlabSchema.find_by_gid(id) end end diff --git a/app/graphql/mutations/clusters/agent_tokens/delete.rb b/app/graphql/mutations/clusters/agent_tokens/delete.rb deleted file mode 100644 index 603b6b30910..00000000000 --- a/app/graphql/mutations/clusters/agent_tokens/delete.rb +++ /dev/null @@ -1,35 +0,0 @@ -# frozen_string_literal: true - -module Mutations - module Clusters - module AgentTokens - class Delete < BaseMutation - graphql_name 'ClusterAgentTokenDelete' - - authorize :admin_cluster - - TokenID = ::Types::GlobalIDType[::Clusters::AgentToken] - - argument :id, TokenID, - required: true, - description: 'Global ID of the cluster agent token that will be deleted.' - - def resolve(id:) - token = authorized_find!(id: id) - token.destroy - - { errors: errors_on_object(token) } - end - - private - - def find_object(id:) - # TODO: remove this line when the compatibility layer is removed - # See: https://gitlab.com/gitlab-org/gitlab/-/issues/257883 - id = TokenID.coerce_isolated_input(id) - GitlabSchema.find_by_gid(id) - end - end - end - end -end diff --git a/app/graphql/mutations/clusters/agent_tokens/revoke.rb b/app/graphql/mutations/clusters/agent_tokens/revoke.rb index ca570792296..974db976f1d 100644 --- a/app/graphql/mutations/clusters/agent_tokens/revoke.rb +++ b/app/graphql/mutations/clusters/agent_tokens/revoke.rb @@ -24,9 +24,6 @@ module Mutations private def find_object(id:) - # TODO: remove this line when the compatibility layer is removed - # See: https://gitlab.com/gitlab-org/gitlab/-/issues/257883 - id = TokenID.coerce_isolated_input(id) GitlabSchema.find_by_gid(id) end end diff --git a/app/graphql/mutations/clusters/agents/delete.rb b/app/graphql/mutations/clusters/agents/delete.rb index 9ada1f31f60..fb482e02794 100644 --- a/app/graphql/mutations/clusters/agents/delete.rb +++ b/app/graphql/mutations/clusters/agents/delete.rb @@ -28,9 +28,6 @@ module Mutations private def find_object(id:) - # TODO: remove this line when the compatibility layer is removed - # See: https://gitlab.com/gitlab-org/gitlab/-/issues/257883 - id = AgentID.coerce_isolated_input(id) GitlabSchema.find_by_gid(id) end end diff --git a/app/graphql/mutations/container_expiration_policies/update.rb b/app/graphql/mutations/container_expiration_policies/update.rb index 762058acf3d..c2208e469c5 100644 --- a/app/graphql/mutations/container_expiration_policies/update.rb +++ b/app/graphql/mutations/container_expiration_policies/update.rb @@ -7,7 +7,7 @@ module Mutations include FindsProject - authorize :destroy_container_image + authorize :admin_container_image argument :project_path, GraphQL::Types::ID, diff --git a/app/graphql/mutations/container_repositories/destroy_base.rb b/app/graphql/mutations/container_repositories/destroy_base.rb index ddaa6c52121..1c2c4d87a5f 100644 --- a/app/graphql/mutations/container_repositories/destroy_base.rb +++ b/app/graphql/mutations/container_repositories/destroy_base.rb @@ -8,9 +8,6 @@ module Mutations private def find_object(id:) - # TODO: remove this line when the compatibility layer is removed - # See: https://gitlab.com/gitlab-org/gitlab/-/issues/257883 - id = ::Types::GlobalIDType[::ContainerRepository].coerce_isolated_input(id) GitlabSchema.find_by_gid(id) end end diff --git a/app/graphql/mutations/customer_relations/contacts/base.rb b/app/graphql/mutations/customer_relations/contacts/base.rb new file mode 100644 index 00000000000..5d49d48ebe2 --- /dev/null +++ b/app/graphql/mutations/customer_relations/contacts/base.rb @@ -0,0 +1,25 @@ +# frozen_string_literal: true + +module Mutations + module CustomerRelations + module Contacts + class Base < BaseMutation + include ResolvesIds + include Gitlab::Graphql::Authorize::AuthorizeResource + + field :contact, + Types::CustomerRelations::ContactType, + null: true, + description: 'Contact after the mutation.' + + authorize :admin_crm_contact + + def set_organization!(args) + return unless args[:organization_id] + + args[:organization_id] = args[:organization_id].model_id + end + end + end + end +end diff --git a/app/graphql/mutations/customer_relations/contacts/create.rb b/app/graphql/mutations/customer_relations/contacts/create.rb index 96dc047c3db..5b4063fb89a 100644 --- a/app/graphql/mutations/customer_relations/contacts/create.rb +++ b/app/graphql/mutations/customer_relations/contacts/create.rb @@ -3,17 +3,11 @@ module Mutations module CustomerRelations module Contacts - class Create < BaseMutation + class Create < Base graphql_name 'CustomerRelationsContactCreate' - include ResolvesIds include Gitlab::Graphql::Authorize::AuthorizeResource - field :contact, - Types::CustomerRelations::ContactType, - null: true, - description: 'Contact after the mutation.' - argument :group_id, ::Types::GlobalIDType[::Group], required: true, description: 'Group for the contact.' @@ -42,8 +36,6 @@ module Mutations required: false, description: 'Description of or notes for the contact.' - authorize :admin_crm_contact - def resolve(args) group = authorized_find!(id: args[:group_id]) @@ -55,12 +47,6 @@ module Mutations def find_object(id:) GitlabSchema.object_from_id(id, expected_type: ::Group) end - - def set_organization!(args) - return unless args[:organization_id] - - args[:organization_id] = resolve_ids(args[:organization_id], ::Types::GlobalIDType[::CustomerRelations::Organization])[0] - end end end end diff --git a/app/graphql/mutations/customer_relations/contacts/update.rb b/app/graphql/mutations/customer_relations/contacts/update.rb index a3abf37f21f..1fc4f655464 100644 --- a/app/graphql/mutations/customer_relations/contacts/update.rb +++ b/app/graphql/mutations/customer_relations/contacts/update.rb @@ -3,18 +3,9 @@ module Mutations module CustomerRelations module Contacts - class Update < Mutations::BaseMutation + class Update < Base graphql_name 'CustomerRelationsContactUpdate' - include ResolvesIds - - authorize :admin_crm_contact - - field :contact, - Types::CustomerRelations::ContactType, - null: true, - description: 'Contact after the mutation.' - argument :id, ::Types::GlobalIDType[::CustomerRelations::Contact], required: true, description: 'Global ID of the contact.' @@ -43,6 +34,10 @@ module Mutations required: false, description: 'Description of or notes for the contact.' + argument :active, GraphQL::Types::Boolean, + required: false, + description: 'State of the contact.' + def resolve(args) contact = ::Gitlab::Graphql::Lazy.force(GitlabSchema.object_from_id(args.delete(:id), expected_type: ::CustomerRelations::Contact)) raise_resource_not_available_error! unless contact @@ -50,6 +45,7 @@ module Mutations group = contact.group authorize!(group) + set_organization!(args) result = ::CustomerRelations::Contacts::UpdateService.new(group: group, current_user: current_user, params: args).execute(contact) { contact: result.payload, errors: result.errors } end diff --git a/app/graphql/mutations/customer_relations/organizations/update.rb b/app/graphql/mutations/customer_relations/organizations/update.rb index 0c05541dbd7..b2153b0b102 100644 --- a/app/graphql/mutations/customer_relations/organizations/update.rb +++ b/app/graphql/mutations/customer_relations/organizations/update.rb @@ -34,6 +34,10 @@ module Mutations required: false, description: 'Description of or notes for the organization.' + argument :active, GraphQL::Types::Boolean, + required: false, + description: 'State of the organization.' + def resolve(args) organization = ::Gitlab::Graphql::Lazy.force(GitlabSchema.object_from_id(args.delete(:id), expected_type: ::CustomerRelations::Organization)) raise_resource_not_available_error! unless organization diff --git a/app/graphql/mutations/design_management/move.rb b/app/graphql/mutations/design_management/move.rb index 1ca03f22880..b19d9b4ce61 100644 --- a/app/graphql/mutations/design_management/move.rb +++ b/app/graphql/mutations/design_management/move.rb @@ -35,9 +35,6 @@ module Mutations end def find_design(id) - # TODO: remove this line when the compatibility layer is removed - # See: https://gitlab.com/gitlab-org/gitlab/-/issues/257883 - id = DesignID.coerce_isolated_input(id) GitlabSchema.find_by_gid(id) end diff --git a/app/graphql/mutations/discussions/toggle_resolve.rb b/app/graphql/mutations/discussions/toggle_resolve.rb index 2005c9e54e0..fce6e4f416f 100644 --- a/app/graphql/mutations/discussions/toggle_resolve.rb +++ b/app/graphql/mutations/discussions/toggle_resolve.rb @@ -54,9 +54,6 @@ module Mutations end def find_object(id:) - # TODO: remove explicit coercion once compatibility layer has been removed - # See: https://gitlab.com/gitlab-org/gitlab/-/issues/257883 - id = Types::GlobalIDType[Discussion].coerce_isolated_input(id) GitlabSchema.find_by_gid(id) end diff --git a/app/graphql/mutations/environments/canary_ingress/update.rb b/app/graphql/mutations/environments/canary_ingress/update.rb index ce24b8842c6..1cddfdd815b 100644 --- a/app/graphql/mutations/environments/canary_ingress/update.rb +++ b/app/graphql/mutations/environments/canary_ingress/update.rb @@ -24,7 +24,7 @@ module Mutations 'https://gitlab.com/groups/gitlab-org/configure/-/epics/8' def resolve(id:, **kwargs) - return { errors: [REMOVAL_ERR_MSG] } if cert_based_clusters_ff_disabled? + return { errors: [REMOVAL_ERR_MSG] } unless certificate_based_clusters_enabled? environment = authorized_find!(id: id) @@ -36,15 +36,14 @@ module Mutations end def find_object(id:) - # TODO: remove as part of https://gitlab.com/gitlab-org/gitlab/-/issues/257883 - id = ::Types::GlobalIDType[::Environment].coerce_isolated_input(id) GitlabSchema.find_by_gid(id) end private - def cert_based_clusters_ff_disabled? - Feature.disabled?(:certificate_based_clusters, default_enabled: :yaml, type: :ops) + def certificate_based_clusters_enabled? + instance_cluster = ::Clusters::Instance.new + instance_cluster.certificate_based_clusters_enabled? end end end diff --git a/app/graphql/mutations/incident_management/timeline_event/base.rb b/app/graphql/mutations/incident_management/timeline_event/base.rb new file mode 100644 index 00000000000..742470b4831 --- /dev/null +++ b/app/graphql/mutations/incident_management/timeline_event/base.rb @@ -0,0 +1,29 @@ +# frozen_string_literal: true + +module Mutations + module IncidentManagement + module TimelineEvent + class Base < BaseMutation + field :timeline_event, + ::Types::IncidentManagement::TimelineEventType, + null: true, + description: 'Timeline event.' + + authorize :admin_incident_management_timeline_event + + private + + def response(result) + { + timeline_event: result.payload[:timeline_event], + errors: result.errors + } + end + + def find_object(id:) + GitlabSchema.object_from_id(id, expected_type: ::IncidentManagement::TimelineEvent).sync + end + end + end + end +end diff --git a/app/graphql/mutations/incident_management/timeline_event/create.rb b/app/graphql/mutations/incident_management/timeline_event/create.rb new file mode 100644 index 00000000000..cbc708a2530 --- /dev/null +++ b/app/graphql/mutations/incident_management/timeline_event/create.rb @@ -0,0 +1,37 @@ +# frozen_string_literal: true + +module Mutations + module IncidentManagement + module TimelineEvent + class Create < Base + graphql_name 'TimelineEventCreate' + + argument :incident_id, Types::GlobalIDType[::Issue], + required: true, + description: 'Incident ID of the timeline event.' + + argument :note, GraphQL::Types::String, + required: true, + description: 'Text note of the timeline event.' + + argument :occurred_at, Types::TimeType, + required: true, + description: 'Timestamp of when the event occurred.' + + def resolve(incident_id:, **args) + incident = authorized_find!(id: incident_id) + + authorize!(incident) + + response ::IncidentManagement::TimelineEvents::CreateService.new(incident, current_user, args).execute + end + + private + + def find_object(id:) + GitlabSchema.object_from_id(id, expected_type: ::Issue).sync + end + end + end + end +end diff --git a/app/graphql/mutations/incident_management/timeline_event/destroy.rb b/app/graphql/mutations/incident_management/timeline_event/destroy.rb new file mode 100644 index 00000000000..728a2e7c0d6 --- /dev/null +++ b/app/graphql/mutations/incident_management/timeline_event/destroy.rb @@ -0,0 +1,24 @@ +# frozen_string_literal: true + +module Mutations + module IncidentManagement + module TimelineEvent + class Destroy < Base + graphql_name 'TimelineEventDestroy' + + argument :id, Types::GlobalIDType[::IncidentManagement::TimelineEvent], + required: true, + description: 'Timeline event ID to remove.' + + def resolve(id:) + timeline_event = authorized_find!(id: id) + + response ::IncidentManagement::TimelineEvents::DestroyService.new( + timeline_event, + current_user + ).execute + end + end + end + end +end diff --git a/app/graphql/mutations/incident_management/timeline_event/promote_from_note.rb b/app/graphql/mutations/incident_management/timeline_event/promote_from_note.rb new file mode 100644 index 00000000000..73a20b8a380 --- /dev/null +++ b/app/graphql/mutations/incident_management/timeline_event/promote_from_note.rb @@ -0,0 +1,46 @@ +# frozen_string_literal: true + +module Mutations + module IncidentManagement + module TimelineEvent + class PromoteFromNote < Base + graphql_name 'TimelineEventPromoteFromNote' + + argument :note_id, Types::GlobalIDType[::Note], + required: true, + description: 'Note ID from which the timeline event promoted.' + + def resolve(note_id:) + note = find_object(id: note_id) + incident = note&.noteable + + authorize!(incident) + + response ::IncidentManagement::TimelineEvents::CreateService.new( + incident, + current_user, + promoted_from_note: note, + note: note.note, + occurred_at: note.created_at + ).execute + end + + private + + def find_object(id:) + GitlabSchema.object_from_id(id, expected_type: ::Note).sync + end + + def authorize!(object) + raise_noteable_not_incident! if object && !object.try(:incident?) + + super + end + + def raise_noteable_not_incident! + raise_resource_not_available_error! 'Note does not belong to an incident' + end + end + end + end +end diff --git a/app/graphql/mutations/incident_management/timeline_event/update.rb b/app/graphql/mutations/incident_management/timeline_event/update.rb new file mode 100644 index 00000000000..1f53bdc19cb --- /dev/null +++ b/app/graphql/mutations/incident_management/timeline_event/update.rb @@ -0,0 +1,33 @@ +# frozen_string_literal: true + +module Mutations + module IncidentManagement + module TimelineEvent + class Update < Base + graphql_name 'TimelineEventUpdate' + + argument :id, ::Types::GlobalIDType[::IncidentManagement::TimelineEvent], + required: true, + description: 'ID of the timeline event to update.' + + argument :note, GraphQL::Types::String, + required: false, + description: 'Text note of the timeline event.' + + argument :occurred_at, Types::TimeType, + required: false, + description: 'Timestamp when the event occurred.' + + def resolve(id:, **args) + timeline_event = authorized_find!(id: id) + + response ::IncidentManagement::TimelineEvents::UpdateService.new( + timeline_event, + current_user, + args + ).execute + end + end + end + end +end diff --git a/app/graphql/mutations/issues/set_crm_contacts.rb b/app/graphql/mutations/issues/set_crm_contacts.rb index 62990fc67f1..4df65e4769c 100644 --- a/app/graphql/mutations/issues/set_crm_contacts.rb +++ b/app/graphql/mutations/issues/set_crm_contacts.rb @@ -48,7 +48,7 @@ module Mutations private def feature_enabled?(project) - Feature.enabled?(:customer_relations, project.group, default_enabled: :yaml) && project.group&.crm_enabled? + Feature.enabled?(:customer_relations, project.group) && project.group&.crm_enabled? end end end diff --git a/app/graphql/mutations/merge_requests/remove_attention_request.rb b/app/graphql/mutations/merge_requests/remove_attention_request.rb new file mode 100644 index 00000000000..3b12b09528b --- /dev/null +++ b/app/graphql/mutations/merge_requests/remove_attention_request.rb @@ -0,0 +1,40 @@ +# frozen_string_literal: true + +module Mutations + module MergeRequests + class RemoveAttentionRequest < Base + graphql_name 'MergeRequestRemoveAttentionRequest' + + argument :user_id, ::Types::GlobalIDType[::User], + loads: Types::UserType, + required: true, + description: <<~DESC + User ID of the user for attention request removal. + DESC + + def resolve(project_path:, iid:, user:) + raise Gitlab::Graphql::Errors::ResourceNotAvailable, 'Feature disabled' unless feature_enabled? + + merge_request = authorized_find!(project_path: project_path, iid: iid) + + result = ::MergeRequests::RemoveAttentionRequestedService.new( + project: merge_request.project, + current_user: current_user, + merge_request: merge_request, + user: user + ).execute + + { + merge_request: merge_request, + errors: Array(result[:message]) + } + end + + private + + def feature_enabled? + current_user&.mr_attention_requests_enabled? + end + end + end +end diff --git a/app/graphql/mutations/merge_requests/request_attention.rb b/app/graphql/mutations/merge_requests/request_attention.rb new file mode 100644 index 00000000000..5f5565285f6 --- /dev/null +++ b/app/graphql/mutations/merge_requests/request_attention.rb @@ -0,0 +1,40 @@ +# frozen_string_literal: true + +module Mutations + module MergeRequests + class RequestAttention < Base + graphql_name 'MergeRequestRequestAttention' + + argument :user_id, ::Types::GlobalIDType[::User], + loads: Types::UserType, + required: true, + description: <<~DESC + User ID of the user to request attention. + DESC + + def resolve(project_path:, iid:, user:) + raise Gitlab::Graphql::Errors::ResourceNotAvailable, 'Feature disabled' unless feature_enabled? + + merge_request = authorized_find!(project_path: project_path, iid: iid) + + result = ::MergeRequests::RequestAttentionService.new( + project: merge_request.project, + current_user: current_user, + merge_request: merge_request, + user: user + ).execute + + { + merge_request: merge_request, + errors: Array(result[:message]) + } + end + + private + + def feature_enabled? + current_user&.mr_attention_requests_enabled? + end + end + end +end diff --git a/app/graphql/mutations/merge_requests/set_labels.rb b/app/graphql/mutations/merge_requests/set_labels.rb index 0b40d6c5c5e..f80fcd0f1ac 100644 --- a/app/graphql/mutations/merge_requests/set_labels.rb +++ b/app/graphql/mutations/merge_requests/set_labels.rb @@ -23,9 +23,6 @@ module Mutations merge_request = authorized_find!(project_path: project_path, iid: iid) project = merge_request.project - # TODO: remove this line when the compatibility layer is removed: - # See: https://gitlab.com/gitlab-org/gitlab/-/issues/257883 - label_ids = label_ids.map { |id| ::Types::GlobalIDType[::Label].coerce_isolated_input(id) } # MergeRequests::UpdateService expects integers label_ids = label_ids.compact.map(&:model_id) diff --git a/app/graphql/mutations/merge_requests/toggle_attention_requested.rb b/app/graphql/mutations/merge_requests/toggle_attention_requested.rb index f316f23fb85..8913ca48531 100644 --- a/app/graphql/mutations/merge_requests/toggle_attention_requested.rb +++ b/app/graphql/mutations/merge_requests/toggle_attention_requested.rb @@ -13,6 +13,8 @@ module Mutations DESC def resolve(project_path:, iid:, user:) + raise Gitlab::Graphql::Errors::ResourceNotAvailable, 'Feature disabled' unless current_user&.mr_attention_requests_enabled? + merge_request = authorized_find!(project_path: project_path, iid: iid) result = ::MergeRequests::ToggleAttentionRequestedService.new(project: merge_request.project, current_user: current_user, merge_request: merge_request, user: user).execute diff --git a/app/graphql/mutations/metrics/dashboard/annotations/create.rb b/app/graphql/mutations/metrics/dashboard/annotations/create.rb index 2eb48c9029d..2e7c0c5a2f9 100644 --- a/app/graphql/mutations/metrics/dashboard/annotations/create.rb +++ b/app/graphql/mutations/metrics/dashboard/annotations/create.rb @@ -96,16 +96,7 @@ module Mutations end def annotation_source(args) - # TODO: remove these lines when the compatibility layer is removed - # See: https://gitlab.com/gitlab-org/gitlab/-/issues/257883 - annotation_source_id = if args[:cluster_id] - ::Types::GlobalIDType[::Clusters::Cluster].coerce_isolated_input(args[:cluster_id]) - else - ::Types::GlobalIDType[::Environment].coerce_isolated_input(args[:environment_id]) - end - - # TODO: uncomment following line once lines above are removed - # annotation_source_id = args[:cluster_id] || args[:environment_id] + annotation_source_id = args[:cluster_id] || args[:environment_id] authorized_find!(id: annotation_source_id) end end diff --git a/app/graphql/mutations/namespace/package_settings/update.rb b/app/graphql/mutations/namespace/package_settings/update.rb index 934b75193d7..e499e646781 100644 --- a/app/graphql/mutations/namespace/package_settings/update.rb +++ b/app/graphql/mutations/namespace/package_settings/update.rb @@ -8,7 +8,7 @@ module Mutations include Mutations::ResolvesNamespace - authorize :create_package_settings + authorize :admin_package argument :namespace_path, GraphQL::Types::ID, diff --git a/app/graphql/mutations/notes/base.rb b/app/graphql/mutations/notes/base.rb index 65bb9e4644c..fb74805db17 100644 --- a/app/graphql/mutations/notes/base.rb +++ b/app/graphql/mutations/notes/base.rb @@ -17,9 +17,6 @@ module Mutations private def find_object(id:) - # TODO: remove explicit coercion once compatibility layer has been removed - # See: https://gitlab.com/gitlab-org/gitlab/-/issues/257883 - id = ::Types::GlobalIDType[::Note].coerce_isolated_input(id) GitlabSchema.find_by_gid(id) end end diff --git a/app/graphql/mutations/notes/create/base.rb b/app/graphql/mutations/notes/create/base.rb index e13a51c6862..1b673204213 100644 --- a/app/graphql/mutations/notes/create/base.rb +++ b/app/graphql/mutations/notes/create/base.rb @@ -42,9 +42,6 @@ module Mutations private def find_object(id:) - # TODO: remove explicit coercion once compatibility layer has been removed - # See: https://gitlab.com/gitlab-org/gitlab/-/issues/257883 - id = ::Types::GlobalIDType[::Noteable].coerce_isolated_input(id) GitlabSchema.find_by_gid(id) end diff --git a/app/graphql/mutations/notes/create/note.rb b/app/graphql/mutations/notes/create/note.rb index 1cfc11c6b11..4d6f056de09 100644 --- a/app/graphql/mutations/notes/create/note.rb +++ b/app/graphql/mutations/notes/create/note.rb @@ -22,11 +22,8 @@ module Mutations def create_note_params(noteable, args) discussion_id = nil - if args[:discussion_id] - # TODO: remove this line when the compatibility layer is removed - # See: https://gitlab.com/gitlab-org/gitlab/-/issues/257883 - discussion_gid = ::Types::GlobalIDType[::Discussion].coerce_isolated_input(args[:discussion_id]) - discussion = GitlabSchema.find_by_gid(discussion_gid) + if gid = args[:discussion_id] + discussion = GitlabSchema.find_by_gid(gid) authorize_discussion!(discussion) diff --git a/app/graphql/mutations/notes/reposition_image_diff_note.rb b/app/graphql/mutations/notes/reposition_image_diff_note.rb index ec68f077c84..9c3377b1f96 100644 --- a/app/graphql/mutations/notes/reposition_image_diff_note.rb +++ b/app/graphql/mutations/notes/reposition_image_diff_note.rb @@ -26,6 +26,7 @@ module Mutations def resolve(note:, position:) authorize!(note) + position = position.to_h.compact pre_update_checks!(note, position) updated_note = ::Notes::UpdateService.new( @@ -46,7 +47,7 @@ module Mutations # just a `DiffNote` with a particular kind of `Gitlab::Diff::Position`. # In addition to accepting a `DiffNote` Global ID we also need to # perform this check. - def pre_update_checks!(note, position) + def pre_update_checks!(note, _position) unless note.position&.on_image? raise Gitlab::Graphql::Errors::ResourceNotAvailable, 'Resource is not an ImageDiffNote' diff --git a/app/graphql/mutations/notes/update/image_diff_note.rb b/app/graphql/mutations/notes/update/image_diff_note.rb index 284c0f1bb20..8e4dbb06d46 100644 --- a/app/graphql/mutations/notes/update/image_diff_note.rb +++ b/app/graphql/mutations/notes/update/image_diff_note.rb @@ -54,7 +54,7 @@ module Mutations original_position = note.position.to_h - Gitlab::Diff::Position.new(original_position.merge(args[:position])) + Gitlab::Diff::Position.new(original_position.merge(args[:position].to_h)) end end end diff --git a/app/graphql/mutations/packages/destroy.rb b/app/graphql/mutations/packages/destroy.rb index 81fa53fc116..a398b1ff9dc 100644 --- a/app/graphql/mutations/packages/destroy.rb +++ b/app/graphql/mutations/packages/destroy.rb @@ -27,9 +27,6 @@ module Mutations private def find_object(id:) - # TODO: remove this line when the compatibility layer is removed - # See: https://gitlab.com/gitlab-org/gitlab/-/issues/257883 - id = ::Types::GlobalIDType[::Packages::Package].coerce_isolated_input(id) GitlabSchema.find_by_gid(id) end end diff --git a/app/graphql/mutations/packages/destroy_file.rb b/app/graphql/mutations/packages/destroy_file.rb index 4aa33b3504c..f2a8f2b853a 100644 --- a/app/graphql/mutations/packages/destroy_file.rb +++ b/app/graphql/mutations/packages/destroy_file.rb @@ -25,9 +25,6 @@ module Mutations private def find_object(id:) - # TODO: remove this line when the compatibility layer is removed - # See: https://gitlab.com/gitlab-org/gitlab/-/issues/257883 - id = ::Types::GlobalIDType[::Packages::PackageFile].coerce_isolated_input(id) GitlabSchema.find_by_gid(id) end end diff --git a/app/graphql/mutations/release_asset_links/delete.rb b/app/graphql/mutations/release_asset_links/delete.rb index d8f0946670b..91fa74859f6 100644 --- a/app/graphql/mutations/release_asset_links/delete.rb +++ b/app/graphql/mutations/release_asset_links/delete.rb @@ -29,10 +29,6 @@ module Mutations 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 diff --git a/app/graphql/mutations/release_asset_links/update.rb b/app/graphql/mutations/release_asset_links/update.rb index 18d92cd82ae..f9368927371 100644 --- a/app/graphql/mutations/release_asset_links/update.rb +++ b/app/graphql/mutations/release_asset_links/update.rb @@ -54,10 +54,6 @@ module Mutations 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 diff --git a/app/graphql/mutations/saved_replies/base.rb b/app/graphql/mutations/saved_replies/base.rb index 59871df687f..4923fcb7851 100644 --- a/app/graphql/mutations/saved_replies/base.rb +++ b/app/graphql/mutations/saved_replies/base.rb @@ -24,14 +24,10 @@ module Mutations end def feature_enabled? - Feature.enabled?(:saved_replies, current_user, default_enabled: :yaml) + Feature.enabled?(:saved_replies, current_user) 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 = ::Types::GlobalIDType[::Users::SavedReply].coerce_isolated_input(id) - GitlabSchema.find_by_gid(id) end end diff --git a/app/graphql/mutations/timelogs/delete.rb b/app/graphql/mutations/timelogs/delete.rb new file mode 100644 index 00000000000..8fd41c27b88 --- /dev/null +++ b/app/graphql/mutations/timelogs/delete.rb @@ -0,0 +1,33 @@ +# frozen_string_literal: true + +module Mutations + module Timelogs + class Delete < Mutations::BaseMutation + graphql_name 'TimelogDelete' + + field :timelog, + Types::TimelogType, + null: true, + description: 'Deleted timelog.' + + argument :id, + ::Types::GlobalIDType[::Timelog], + required: true, + description: 'Global ID of the timelog.' + + authorize :admin_timelog + + def resolve(id:) + timelog = authorized_find!(id: id) + result = ::Timelogs::DeleteService.new(timelog, current_user).execute + + # Return the result payload, not the loaded timelog, so that it returns null in case of unauthorized access + { timelog: result.payload, errors: result.errors } + end + + def find_object(id:) + GitlabSchema.find_by_gid(id) + end + end + end +end diff --git a/app/graphql/mutations/todos/base.rb b/app/graphql/mutations/todos/base.rb index 4dab3bbc3f4..9a94c5d1e6d 100644 --- a/app/graphql/mutations/todos/base.rb +++ b/app/graphql/mutations/todos/base.rb @@ -6,9 +6,6 @@ module Mutations private def find_object(id:) - # TODO: remove this line when the compatibility layer is removed - # See: https://gitlab.com/gitlab-org/gitlab/-/issues/257883 - id = ::Types::GlobalIDType[::Todo].coerce_isolated_input(id) GitlabSchema.find_by_gid(id) end end diff --git a/app/graphql/mutations/todos/create.rb b/app/graphql/mutations/todos/create.rb index ccc3d0b61e4..489d2f490ff 100644 --- a/app/graphql/mutations/todos/create.rb +++ b/app/graphql/mutations/todos/create.rb @@ -17,8 +17,7 @@ module Mutations description: 'To-do item created.' def resolve(target_id:) - id = ::Types::GlobalIDType[Todoable].coerce_isolated_input(target_id) - target = authorized_find!(id) + target = authorized_find!(target_id) todo = TodoService.new.mark_todo(target, current_user)&.first errors = errors_on_object(todo) if todo diff --git a/app/graphql/mutations/todos/mark_all_done.rb b/app/graphql/mutations/todos/mark_all_done.rb index 67a822c1067..fe4023515a4 100644 --- a/app/graphql/mutations/todos/mark_all_done.rb +++ b/app/graphql/mutations/todos/mark_all_done.rb @@ -39,7 +39,7 @@ module Mutations if args[:target_id].present? target = Gitlab::Graphql::Lazy.force( - GitlabSchema.find_by_gid(TodoableID.coerce_isolated_input(args[:target_id])) + GitlabSchema.find_by_gid(args[:target_id]) ) raise Gitlab::Graphql::Errors::ResourceNotAvailable, "Resource not available: #{args[:target_id]}" if target.nil? diff --git a/app/graphql/mutations/todos/restore_many.rb b/app/graphql/mutations/todos/restore_many.rb index 3453645000b..fe0ad6df65b 100644 --- a/app/graphql/mutations/todos/restore_many.rb +++ b/app/graphql/mutations/todos/restore_many.rb @@ -33,9 +33,6 @@ module Mutations def model_ids_of(ids) ids.map do |gid| - # TODO: remove this line when the compatibility layer is removed - # See: https://gitlab.com/gitlab-org/gitlab/-/issues/257883 - gid = ::Types::GlobalIDType[::Todo].coerce_isolated_input(gid) gid.model_id.to_i end.compact end diff --git a/app/graphql/mutations/user_preferences/update.rb b/app/graphql/mutations/user_preferences/update.rb index eface536a87..b71c952b0f2 100644 --- a/app/graphql/mutations/user_preferences/update.rb +++ b/app/graphql/mutations/user_preferences/update.rb @@ -38,7 +38,7 @@ module Mutations def disabled_sort_value?(args) return false unless [:escalation_status_asc, :escalation_status_desc].include?(args[:issues_sort]) - Feature.disabled?(:incident_escalations, default_enabled: :yaml) + Feature.disabled?(:incident_escalations) end end end diff --git a/app/graphql/mutations/work_items/create.rb b/app/graphql/mutations/work_items/create.rb index c29dbb899b5..2e136d409ab 100644 --- a/app/graphql/mutations/work_items/create.rb +++ b/app/graphql/mutations/work_items/create.rb @@ -53,9 +53,6 @@ module Mutations private def global_id_compatibility_params(params) - # TODO: remove this line when the compatibility layer is removed - # See: https://gitlab.com/gitlab-org/gitlab/-/issues/257883 - params[:work_item_type_id] = ::Types::GlobalIDType[::WorkItems::Type].coerce_isolated_input(params[:work_item_type_id]) if params[:work_item_type_id] params[:work_item_type_id] = params[:work_item_type_id]&.model_id params diff --git a/app/graphql/mutations/work_items/create_from_task.rb b/app/graphql/mutations/work_items/create_from_task.rb index 278c1bc65a9..4da709401a6 100644 --- a/app/graphql/mutations/work_items/create_from_task.rb +++ b/app/graphql/mutations/work_items/create_from_task.rb @@ -55,8 +55,6 @@ module Mutations private def find_object(id:) - # TODO: Remove coercion when working on https://gitlab.com/gitlab-org/gitlab/-/issues/257883 - id = ::Types::GlobalIDType[::WorkItem].coerce_isolated_input(id) GitlabSchema.find_by_gid(id) end end diff --git a/app/graphql/mutations/work_items/delete.rb b/app/graphql/mutations/work_items/delete.rb index 3d72ebbd95d..1830ab5443c 100644 --- a/app/graphql/mutations/work_items/delete.rb +++ b/app/graphql/mutations/work_items/delete.rb @@ -38,8 +38,6 @@ module Mutations private def find_object(id:) - # TODO: Remove coercion when working on https://gitlab.com/gitlab-org/gitlab/-/issues/257883 - id = ::Types::GlobalIDType[::WorkItem].coerce_isolated_input(id) GitlabSchema.find_by_gid(id) end end diff --git a/app/graphql/mutations/work_items/delete_task.rb b/app/graphql/mutations/work_items/delete_task.rb new file mode 100644 index 00000000000..87620a28fa1 --- /dev/null +++ b/app/graphql/mutations/work_items/delete_task.rb @@ -0,0 +1,69 @@ +# frozen_string_literal: true + +module Mutations + module WorkItems + class DeleteTask < BaseMutation + graphql_name 'WorkItemDeleteTask' + + description "Deletes a task in a work item's description." \ + ' Available only when feature flag `work_items` is enabled. This feature is experimental and' \ + ' is subject to change without notice.' + + authorize :update_work_item + + argument :id, ::Types::GlobalIDType[::WorkItem], + required: true, + description: 'Global ID of the work item.' + argument :lock_version, GraphQL::Types::Int, + required: true, + description: 'Current lock version of the work item containing the task in the description.' + argument :task_data, ::Types::WorkItems::DeletedTaskInputType, + required: true, + description: 'Arguments necessary to delete a task from a work item\'s description.', + prepare: ->(attributes, _ctx) { attributes.to_h } + + field :work_item, Types::WorkItemType, + null: true, + description: 'Updated work item.' + + def resolve(id:, lock_version:, task_data:) + work_item = authorized_find!(id: id) + task_data[:task] = authorized_find_task!(task_data[:id]) + + unless work_item.project.work_items_feature_flag_enabled? + return { errors: ['`work_items` feature flag disabled for this project'] } + end + + result = ::WorkItems::DeleteTaskService.new( + work_item: work_item, + current_user: current_user, + lock_version: lock_version, + task_params: task_data + ).execute + + response = { errors: result.errors } + response[:work_item] = work_item if result.success? + + response + end + + private + + def authorized_find_task!(task_id) + task = ::Gitlab::Graphql::Lazy.force(GitlabSchema.find_by_gid(task_id)) + + if current_user.can?(:delete_work_item, task) + task + else + # Fail early if user cannot delete task + raise_resource_not_available_error! + end + end + + # method used by `authorized_find!(id: id)` + def find_object(id:) + GitlabSchema.find_by_gid(id) + end + end + end +end diff --git a/app/graphql/mutations/work_items/update.rb b/app/graphql/mutations/work_items/update.rb index 091237d6fa0..20319301482 100644 --- a/app/graphql/mutations/work_items/update.rb +++ b/app/graphql/mutations/work_items/update.rb @@ -52,8 +52,6 @@ module Mutations private def find_object(id:) - # TODO: Remove coercion when working on https://gitlab.com/gitlab-org/gitlab/-/issues/257883 - id = ::Types::GlobalIDType[::WorkItem].coerce_isolated_input(id) GitlabSchema.find_by_gid(id) end end diff --git a/app/graphql/queries/burndown_chart/burnup.iteration.query.graphql b/app/graphql/queries/burndown_chart/burnup.iteration.query.graphql new file mode 100644 index 00000000000..ff50c34ade3 --- /dev/null +++ b/app/graphql/queries/burndown_chart/burnup.iteration.query.graphql @@ -0,0 +1,40 @@ +query BurnupTimesSeriesIterationData( + $iterationId: IterationID! + $weight: Boolean = false + $fullPath: String +) { + iteration(id: $iterationId) { + __typename + id + title + report(fullPath: $fullPath) { + __typename + burnupTimeSeries { + __typename + date + completedCount @skip(if: $weight) + scopeCount @skip(if: $weight) + completedWeight @include(if: $weight) + scopeWeight @include(if: $weight) + } + stats { + __typename + total { + __typename + count @skip(if: $weight) + weight @include(if: $weight) + } + complete { + __typename + count @skip(if: $weight) + weight @include(if: $weight) + } + incomplete { + __typename + count @skip(if: $weight) + weight @include(if: $weight) + } + } + } + } +} diff --git a/app/graphql/queries/burndown_chart/burnup.milestone.query.graphql b/app/graphql/queries/burndown_chart/burnup.milestone.query.graphql new file mode 100644 index 00000000000..18e59249500 --- /dev/null +++ b/app/graphql/queries/burndown_chart/burnup.milestone.query.graphql @@ -0,0 +1,36 @@ +query BurnupTimesSeriesMilestoneData($milestoneId: MilestoneID!, $weight: Boolean = false) { + milestone(id: $milestoneId) { + __typename + id + title + report { + __typename + burnupTimeSeries { + __typename + date + completedCount @skip(if: $weight) + scopeCount @skip(if: $weight) + completedWeight @include(if: $weight) + scopeWeight @include(if: $weight) + } + stats { + __typename + total { + __typename + count @skip(if: $weight) + weight @include(if: $weight) + } + complete { + __typename + count @skip(if: $weight) + weight @include(if: $weight) + } + incomplete { + __typename + count @skip(if: $weight) + weight @include(if: $weight) + } + } + } + } +} diff --git a/app/graphql/queries/burndown_chart/burnup.query.graphql b/app/graphql/queries/burndown_chart/burnup.query.graphql deleted file mode 100644 index 0795645f8b7..00000000000 --- a/app/graphql/queries/burndown_chart/burnup.query.graphql +++ /dev/null @@ -1,75 +0,0 @@ -query BurnupTimesSeriesData( - $id: ID! - $isIteration: Boolean = false - $weight: Boolean = false - $fullPath: String -) { - milestone(id: $id) @skip(if: $isIteration) { - __typename - id - title - report { - __typename - burnupTimeSeries { - __typename - date - completedCount @skip(if: $weight) - scopeCount @skip(if: $weight) - completedWeight @include(if: $weight) - scopeWeight @include(if: $weight) - } - stats { - __typename - total { - __typename - count @skip(if: $weight) - weight @include(if: $weight) - } - complete { - __typename - count @skip(if: $weight) - weight @include(if: $weight) - } - incomplete { - __typename - count @skip(if: $weight) - weight @include(if: $weight) - } - } - } - } - iteration(id: $id) @include(if: $isIteration) { - __typename - id - title - report(fullPath: $fullPath) { - __typename - burnupTimeSeries { - __typename - date - completedCount @skip(if: $weight) - scopeCount @skip(if: $weight) - completedWeight @include(if: $weight) - scopeWeight @include(if: $weight) - } - stats { - __typename - total { - __typename - count @skip(if: $weight) - weight @include(if: $weight) - } - complete { - __typename - count @skip(if: $weight) - weight @include(if: $weight) - } - incomplete { - __typename - count @skip(if: $weight) - weight @include(if: $weight) - } - } - } - } -} diff --git a/app/graphql/queries/design_management/get_design_list.query.graphql b/app/graphql/queries/design_management/get_design_list.query.graphql index f0caa7c5b4c..c2100b5fa04 100644 --- a/app/graphql/queries/design_management/get_design_list.query.graphql +++ b/app/graphql/queries/design_management/get_design_list.query.graphql @@ -1,4 +1,4 @@ -query getDesignList($fullPath: ID!, $iid: String!, $atVersion: ID) { +query getDesignList($fullPath: ID!, $iid: String!, $atVersion: DesignManagementVersionID) { project(fullPath: $fullPath) { __typename id diff --git a/app/graphql/queries/pipelines/get_pipeline_details.query.graphql b/app/graphql/queries/pipelines/get_pipeline_details.query.graphql index f4921706f7e..c8353c738a5 100644 --- a/app/graphql/queries/pipelines/get_pipeline_details.query.graphql +++ b/app/graphql/queries/pipelines/get_pipeline_details.query.graphql @@ -18,6 +18,11 @@ fragment LinkedPipelineData on Pipeline { id iid path + cancelable + retryable + userPermissions { + updatePipeline + } status: detailedStatus { __typename id @@ -97,6 +102,7 @@ query getPipelineDetails($projectPath: ID!, $iid: ID!) { __typename id name + kind scheduledAt needs { __typename diff --git a/app/graphql/queries/snippet/snippet_blob_content.query.graphql b/app/graphql/queries/snippet/snippet_blob_content.query.graphql index 4459a5e4316..0ac7d4d23a0 100644 --- a/app/graphql/queries/snippet/snippet_blob_content.query.graphql +++ b/app/graphql/queries/snippet/snippet_blob_content.query.graphql @@ -1,4 +1,4 @@ -query SnippetBlobContent($ids: [ID!], $rich: Boolean!, $paths: [String!]) { +query SnippetBlobContent($ids: [SnippetID!], $rich: Boolean!, $paths: [String!]) { snippets(ids: $ids) { __typename nodes { diff --git a/app/graphql/resolvers/alert_management/http_integrations_resolver.rb b/app/graphql/resolvers/alert_management/http_integrations_resolver.rb index abc54614a59..225e20bab83 100644 --- a/app/graphql/resolvers/alert_management/http_integrations_resolver.rb +++ b/app/graphql/resolvers/alert_management/http_integrations_resolver.rb @@ -26,8 +26,7 @@ module Resolvers private def integrations_by(gid:) - id = Types::GlobalIDType[::AlertManagement::HttpIntegration].coerce_isolated_input(gid) - object = GitlabSchema.find_by_gid(id) + object = GitlabSchema.find_by_gid(gid) defer { object }.then do |integration| ret = integration if project == integration&.project diff --git a/app/graphql/resolvers/base_issues_resolver.rb b/app/graphql/resolvers/base_issues_resolver.rb index 4cae7866a49..a1fda976876 100644 --- a/app/graphql/resolvers/base_issues_resolver.rb +++ b/app/graphql/resolvers/base_issues_resolver.rb @@ -35,7 +35,7 @@ module Resolvers def prepare_params(args, parent) return unless [:escalation_status_asc, :escalation_status_desc].include?(args[:sort]) - return if Feature.enabled?(:incident_escalations, parent, default_enabled: :yaml) + return if Feature.enabled?(:incident_escalations, parent) args[:sort] = :created_desc # default for sort argument end diff --git a/app/graphql/resolvers/base_resolver.rb b/app/graphql/resolvers/base_resolver.rb index dbded8f60a0..2b54a3fdd55 100644 --- a/app/graphql/resolvers/base_resolver.rb +++ b/app/graphql/resolvers/base_resolver.rb @@ -4,7 +4,6 @@ module Resolvers class BaseResolver < GraphQL::Schema::Resolver extend ::Gitlab::Utils::Override include ::Gitlab::Utils::StrongMemoize - include ::Gitlab::Graphql::GlobalIDCompatibility argument_class ::Types::BaseArgument diff --git a/app/graphql/resolvers/boards_resolver.rb b/app/graphql/resolvers/boards_resolver.rb index 679f2b4cceb..91cd15f615d 100644 --- a/app/graphql/resolvers/boards_resolver.rb +++ b/app/graphql/resolvers/boards_resolver.rb @@ -26,9 +26,6 @@ module Resolvers def extract_board_id(id) return unless id.present? - # TODO: remove this line when the compatibility layer is removed - # See: https://gitlab.com/gitlab-org/gitlab/-/issues/257883 - id = Types::GlobalIDType[Board].coerce_isolated_input(id) id.model_id end end diff --git a/app/graphql/resolvers/ci/config_resolver.rb b/app/graphql/resolvers/ci/config_resolver.rb index f9d60650443..6f861012d83 100644 --- a/app/graphql/resolvers/ci/config_resolver.rb +++ b/app/graphql/resolvers/ci/config_resolver.rb @@ -37,7 +37,7 @@ module Resolvers .new(project: project, current_user: context[:current_user], sha: sha) .validate(content, dry_run: dry_run) - response(result).merge(merged_yaml: result.merged_yaml) + response(result) rescue GRPC::InvalidArgument => error Gitlab::ErrorTracking.track_and_raise_exception(error, sha: sha) end @@ -45,20 +45,14 @@ module Resolvers private def response(result) - if result.errors.empty? - { - status: :valid, - errors: [], - warnings: result.warnings, - stages: make_stages(result.jobs) - } - else - { - status: :invalid, - warnings: result.warnings, - errors: result.errors - } - end + { + status: result.status, + errors: result.errors, + warnings: result.warnings, + stages: make_stages(result), + merged_yaml: result.merged_yaml, + includes: result.includes + } end def make_jobs(config_jobs) @@ -90,8 +84,10 @@ module Resolvers end end - def make_stages(jobs) - make_groups(jobs) + def make_stages(result) + return [] unless result.valid? + + make_groups(result.jobs) .group_by { |group| group[:stage] } .map { |name, groups| { name: name, groups: groups } } end diff --git a/app/graphql/resolvers/ci/runner_status_resolver.rb b/app/graphql/resolvers/ci/runner_status_resolver.rb index d916a8a13f0..447ab306ba7 100644 --- a/app/graphql/resolvers/ci/runner_status_resolver.rb +++ b/app/graphql/resolvers/ci/runner_status_resolver.rb @@ -3,7 +3,8 @@ module Resolvers module Ci # NOTE: This class was introduced to allow modifying the meaning of certain values in RunnerStatusEnum - # while preserving backward compatibility. It can be removed in 15.0 once the API has stabilized. + # while preserving backward compatibility. It can be removed in 17.0 after being deprecated + # and made a no-op in %16.0 (legacy_mode will be hard-coded to nil). class RunnerStatusResolver < BaseResolver type Types::Ci::RunnerStatusEnum, null: false @@ -14,7 +15,11 @@ module Resolvers default_value: '14.5', required: false, description: 'Compatibility mode. A null value turns off compatibility mode.', - deprecated: { reason: 'Will be removed in 15.0. From that release onward, the field will behave as if legacyMode is null', milestone: '14.6' } + deprecated: { + reason: 'Will be removed in 17.0. In GitLab 16.0 and later, ' \ + 'the field will act as if `legacyMode` is null', + milestone: '15.0' + } def resolve(legacy_mode:, **args) runner.status(legacy_mode) diff --git a/app/graphql/resolvers/concerns/issue_resolver_arguments.rb b/app/graphql/resolvers/concerns/issue_resolver_arguments.rb index 432d6f48607..de44dbb26d7 100644 --- a/app/graphql/resolvers/concerns/issue_resolver_arguments.rb +++ b/app/graphql/resolvers/concerns/issue_resolver_arguments.rb @@ -68,6 +68,12 @@ module IssueResolverArguments description: 'Negated arguments.', prepare: ->(negated_args, ctx) { negated_args.to_h }, required: false + argument :crm_contact_id, GraphQL::Types::String, + required: false, + description: 'ID of a contact assigned to the issues.' + argument :crm_organization_id, GraphQL::Types::String, + required: false, + description: 'ID of an organization assigned to the issues.' end def resolve_with_lookahead(**args) diff --git a/app/graphql/resolvers/concerns/resolves_ids.rb b/app/graphql/resolvers/concerns/resolves_ids.rb index 8bf2a6b2ac9..3e248c40562 100644 --- a/app/graphql/resolvers/concerns/resolves_ids.rb +++ b/app/graphql/resolvers/concerns/resolves_ids.rb @@ -3,13 +3,10 @@ module ResolvesIds extend ActiveSupport::Concern - def resolve_ids(ids, type) + def resolve_ids(ids) Array.wrap(ids).map do |id| next unless id.present? - # TODO: remove this line when the compatibility layer is removed - # See: https://gitlab.com/gitlab-org/gitlab/-/issues/257883 - id = type.coerce_isolated_input(id) id.model_id end.compact end diff --git a/app/graphql/resolvers/concerns/resolves_snippets.rb b/app/graphql/resolvers/concerns/resolves_snippets.rb index 46d78a6a8c8..8274b5cc49f 100644 --- a/app/graphql/resolvers/concerns/resolves_snippets.rb +++ b/app/graphql/resolvers/concerns/resolves_snippets.rb @@ -28,7 +28,7 @@ module ResolvesSnippets def snippet_finder_params(args) { - ids: resolve_ids(args[:ids], ::Types::GlobalIDType[::Snippet]), + ids: resolve_ids(args[:ids]), scope: args[:visibility] }.merge(options_by_type(args[:type])) end diff --git a/app/graphql/resolvers/concerns/time_frame_arguments.rb b/app/graphql/resolvers/concerns/time_frame_arguments.rb index 0ec3c642f29..87b7a96045c 100644 --- a/app/graphql/resolvers/concerns/time_frame_arguments.rb +++ b/app/graphql/resolvers/concerns/time_frame_arguments.rb @@ -24,10 +24,13 @@ module TimeFrameArguments # TODO: remove when the start_date and end_date arguments are removed def validate_timeframe_params!(args) return unless %i[start_date end_date timeframe].any? { |k| args[k].present? } - return if args[:timeframe] && %i[start_date end_date].all? { |k| args[k].nil? } + + # the timeframe is passed in as a TimeframeInputType + timeframe = args[:timeframe].to_h if args[:timeframe] + return if timeframe && %i[start_date end_date].all? { |k| args[k].nil? } error_message = - if args[:timeframe].present? + if timeframe.present? "startDate and endDate are deprecated in favor of timeframe. Please use only timeframe." elsif args[:start_date].nil? || args[:end_date].nil? "Both startDate and endDate must be present." @@ -42,7 +45,7 @@ module TimeFrameArguments def transform_timeframe_parameters(args) if args[:timeframe] - args[:timeframe].transform_keys { |k| :"#{k}_date" } + args[:timeframe].to_h.transform_keys { |k| :"#{k}_date" } else args.slice(:start_date, :end_date) end diff --git a/app/graphql/resolvers/design_management/design_at_version_resolver.rb b/app/graphql/resolvers/design_management/design_at_version_resolver.rb index c87670bc24c..5ba23b5d1ed 100644 --- a/app/graphql/resolvers/design_management/design_at_version_resolver.rb +++ b/app/graphql/resolvers/design_management/design_at_version_resolver.rb @@ -18,9 +18,6 @@ module Resolvers 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 = ::Types::GlobalIDType[::DesignManagement::DesignAtVersion].coerce_isolated_input(id) dav = GitlabSchema.find_by_gid(id) return unless consistent?(dav) diff --git a/app/graphql/resolvers/design_management/design_resolver.rb b/app/graphql/resolvers/design_management/design_resolver.rb index d9e5203ef0e..eaa11d2fd9d 100644 --- a/app/graphql/resolvers/design_management/design_resolver.rb +++ b/app/graphql/resolvers/design_management/design_resolver.rb @@ -54,10 +54,6 @@ module Resolvers end def parse_gid(gid) - # TODO: remove this line when the compatibility layer is removed - # See: https://gitlab.com/gitlab-org/gitlab/-/issues/257883 - gid = ::Types::GlobalIDType[::DesignManagement::Design].coerce_isolated_input(gid) - gid.model_id end end diff --git a/app/graphql/resolvers/design_management/designs_resolver.rb b/app/graphql/resolvers/design_management/designs_resolver.rb index a62ef6d76e5..429bbba74a5 100644 --- a/app/graphql/resolvers/design_management/designs_resolver.rb +++ b/app/graphql/resolvers/design_management/designs_resolver.rb @@ -24,13 +24,17 @@ module Resolvers end def resolve(ids: nil, filenames: nil, at_version: nil) - ::DesignManagement::DesignsFinder.new( - issue, - current_user, - ids: design_ids(ids), - filenames: filenames, - visible_at_version: version(at_version) - ).execute + context.scoped_set!(:at_version_argument, at_version) if at_version + + ::Gitlab::Graphql::Lazy.with_value(version(at_version)) do |visible_at| + ::DesignManagement::DesignsFinder.new( + issue, + current_user, + ids: design_ids(ids), + filenames: filenames, + visible_at_version: visible_at + ).execute + end end private @@ -38,19 +42,12 @@ module Resolvers def version(at_version) return unless at_version - # TODO: remove this line when the compatibility layer is removed - # See: https://gitlab.com/gitlab-org/gitlab/-/issues/257883 - at_version = VersionID.coerce_isolated_input(at_version) - # TODO: when we get promises use this to make resolve lazy - Gitlab::Graphql::Lazy.force(GitlabSchema.find_by_gid(at_version)) + GitlabSchema.find_by_gid(at_version) end def design_ids(gids) return if gids.nil? - # TODO: remove this line when the compatibility layer is removed - # See: https://gitlab.com/gitlab-org/gitlab/-/issues/257883 - gids = gids.map { |id| DesignID.coerce_isolated_input(id) } gids.map(&:model_id) end diff --git a/app/graphql/resolvers/design_management/version/design_at_version_resolver.rb b/app/graphql/resolvers/design_management/version/design_at_version_resolver.rb index 76e365c40b1..30d2865ae85 100644 --- a/app/graphql/resolvers/design_management/version/design_at_version_resolver.rb +++ b/app/graphql/resolvers/design_management/version/design_at_version_resolver.rb @@ -34,11 +34,6 @@ module Resolvers def resolve(design_id: nil, filename: nil, design_at_version_id: nil) validate_arguments(design_id, filename, design_at_version_id) - # TODO: remove this when the compatibility layer is removed - # See: https://gitlab.com/gitlab-org/gitlab/-/issues/257883 - design_id &&= DesignID.coerce_isolated_input(design_id) - design_at_version_id &&= DesignAtVersionID.coerce_isolated_input(design_at_version_id) - return unless Ability.allowed?(current_user, :read_design, issue) return specific_design_at_version(design_at_version_id) if design_at_version_id diff --git a/app/graphql/resolvers/design_management/version/designs_at_version_resolver.rb b/app/graphql/resolvers/design_management/version/designs_at_version_resolver.rb index 97cc7554ba8..9f98762b519 100644 --- a/app/graphql/resolvers/design_management/version/designs_at_version_resolver.rb +++ b/app/graphql/resolvers/design_management/version/designs_at_version_resolver.rb @@ -41,9 +41,6 @@ module Resolvers def design_ids(gids) return if gids.nil? - # TODO: remove this line when the compatibility layer is removed - # See: https://gitlab.com/gitlab-org/gitlab/-/issues/257883 - gids = gids.map { |id| DesignID.coerce_isolated_input(id) } gids.map(&:model_id) end diff --git a/app/graphql/resolvers/design_management/version_in_collection_resolver.rb b/app/graphql/resolvers/design_management/version_in_collection_resolver.rb index 2682ce6b3b1..f29cd30c36f 100644 --- a/app/graphql/resolvers/design_management/version_in_collection_resolver.rb +++ b/app/graphql/resolvers/design_management/version_in_collection_resolver.rb @@ -24,10 +24,6 @@ module Resolvers description: "SHA256 of a specific version." def resolve(version_id: nil, sha: nil) - # TODO: remove this line when the compatibility layer is removed - # See: https://gitlab.com/gitlab-org/gitlab/-/issues/257883 - version_id &&= VersionID.coerce_isolated_input(version_id) - check_args(version_id, sha) ::DesignManagement::VersionsFinder diff --git a/app/graphql/resolvers/design_management/version_resolver.rb b/app/graphql/resolvers/design_management/version_resolver.rb index a6403fbd69f..7895981d67c 100644 --- a/app/graphql/resolvers/design_management/version_resolver.rb +++ b/app/graphql/resolvers/design_management/version_resolver.rb @@ -18,10 +18,6 @@ module Resolvers 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 = ::Types::GlobalIDType[::DesignManagement::Version].coerce_isolated_input(id) - GitlabSchema.find_by_gid(id) end end diff --git a/app/graphql/resolvers/design_management/versions_resolver.rb b/app/graphql/resolvers/design_management/versions_resolver.rb index 23ba3c86d98..de636655087 100644 --- a/app/graphql/resolvers/design_management/versions_resolver.rb +++ b/app/graphql/resolvers/design_management/versions_resolver.rb @@ -9,8 +9,6 @@ module Resolvers VersionID = ::Types::GlobalIDType[::DesignManagement::Version] - extras [:parent] - argument :earlier_or_equal_to_sha, GraphQL::Types::String, as: :sha, required: false, @@ -26,11 +24,8 @@ module Resolvers ::Resolvers::DesignManagement::VersionInCollectionResolver end - def resolve(parent: nil, id: nil, sha: nil) - # TODO: remove this line when the compatibility layer is removed - # See: https://gitlab.com/gitlab-org/gitlab/-/issues/257883 - id &&= VersionID.coerce_isolated_input(id) - version = cutoff(parent, id, sha) + def resolve(id: nil, sha: nil) + version = cutoff(id, sha) raise ::Gitlab::Graphql::Errors::ResourceNotAvailable, 'cutoff not found' unless version.present? @@ -44,11 +39,11 @@ module Resolvers private # Find the most recent version that the client will accept - def cutoff(parent, id, sha) + def cutoff(id, sha) if sha.present? || id.present? specific_version(id, sha) - elsif at_version = at_version_arg(parent) - by_id(at_version) + elsif at_version = context[:at_version_argument] + by_id(at_version) # See: DesignsResolver else :unconstrained end @@ -68,20 +63,6 @@ module Resolvers def by_id(gid) ::Gitlab::Graphql::Lazy.force(GitlabSchema.find_by_gid(gid)) end - - # Find an `at_version` argument passed to a parent node. - # - # If one is found, then a design collection further up the AST - # has been filtered to reflect designs at that version, and so - # for consistency we should only present versions up to the given - # version here. - def at_version_arg(parent) - # TODO: remove coercion when the compatibility layer is removed - # See: https://gitlab.com/gitlab-org/gitlab/-/issues/257883 - version_id = ::Gitlab::Graphql::FindArgumentInParent.find(parent, :at_version, limit_depth: 4) - version_id &&= VersionID.coerce_isolated_input(version_id) - version_id - end end end end diff --git a/app/graphql/resolvers/error_tracking/sentry_detailed_error_resolver.rb b/app/graphql/resolvers/error_tracking/sentry_detailed_error_resolver.rb index 7032af46221..27bba6c8144 100644 --- a/app/graphql/resolvers/error_tracking/sentry_detailed_error_resolver.rb +++ b/app/graphql/resolvers/error_tracking/sentry_detailed_error_resolver.rb @@ -10,10 +10,6 @@ module Resolvers description: 'ID of the Sentry issue.' def resolve(id:) - # TODO: remove this line when the compatibility layer is removed - # See: https://gitlab.com/gitlab-org/gitlab/-/issues/257883 - id = ::Types::GlobalIDType[::Gitlab::ErrorTracking::DetailedError].coerce_isolated_input(id) - # Get data from Sentry response = ::ErrorTracking::IssueDetailsService.new( project, diff --git a/app/graphql/resolvers/error_tracking/sentry_error_stack_trace_resolver.rb b/app/graphql/resolvers/error_tracking/sentry_error_stack_trace_resolver.rb index 8876f8badcd..3867634dd8b 100644 --- a/app/graphql/resolvers/error_tracking/sentry_error_stack_trace_resolver.rb +++ b/app/graphql/resolvers/error_tracking/sentry_error_stack_trace_resolver.rb @@ -10,10 +10,6 @@ module Resolvers description: 'ID of the Sentry issue.' def resolve(id:) - # TODO: remove this line when the compatibility layer is removed - # See: https://gitlab.com/gitlab-org/gitlab/-/issues/257883 - id = ::Types::GlobalIDType[::Gitlab::ErrorTracking::DetailedError].coerce_isolated_input(id) - # Get data from Sentry response = ::ErrorTracking::IssueLatestEventService.new( project, diff --git a/app/graphql/resolvers/group_members_resolver.rb b/app/graphql/resolvers/group_members_resolver.rb index d3662b08cdf..f787f12e82a 100644 --- a/app/graphql/resolvers/group_members_resolver.rb +++ b/app/graphql/resolvers/group_members_resolver.rb @@ -11,6 +11,10 @@ module Resolvers required: false, default_value: GroupMembersFinder::DEFAULT_RELATIONS + argument :access_levels, [Types::AccessLevelEnum], + description: 'Filter members by the given access levels.', + required: false + private def finder_class diff --git a/app/graphql/resolvers/group_packages_resolver.rb b/app/graphql/resolvers/group_packages_resolver.rb index d91fe84317d..b48e0b75190 100644 --- a/app/graphql/resolvers/group_packages_resolver.rb +++ b/app/graphql/resolvers/group_packages_resolver.rb @@ -26,7 +26,10 @@ module Resolvers def resolve(sort:, **filters) return unless packages_available? - ::Packages::GroupPackagesFinder.new(current_user, object, filters.merge(GROUP_SORT_TO_PARAMS_MAP.fetch(sort))).execute + params = filters.merge(GROUP_SORT_TO_PARAMS_MAP.fetch(sort)) + params[:preload_pipelines] = false + + ::Packages::GroupPackagesFinder.new(current_user, object, params).execute end end end diff --git a/app/graphql/resolvers/incident_management/timeline_events_resolver.rb b/app/graphql/resolvers/incident_management/timeline_events_resolver.rb new file mode 100644 index 00000000000..b9978259e6b --- /dev/null +++ b/app/graphql/resolvers/incident_management/timeline_events_resolver.rb @@ -0,0 +1,32 @@ +# frozen_string_literal: true + +module Resolvers + module IncidentManagement + class TimelineEventsResolver < BaseResolver + include LooksAhead + + alias_method :project, :object + + type ::Types::IncidentManagement::TimelineEventType.connection_type, null: true + + argument :incident_id, + ::Types::GlobalIDType[::Issue], + required: true, + description: 'ID of the incident.' + + when_single do + argument :id, + ::Types::GlobalIDType[::IncidentManagement::TimelineEvent], + required: true, + description: 'ID of the timeline event.', + prepare: ->(id, ctx) { id.model_id } + end + + def resolve(**args) + incident = args[:incident_id].find + + apply_lookahead(::IncidentManagement::TimelineEventsFinder.new(current_user, incident, args).execute) + end + end + end +end diff --git a/app/graphql/resolvers/package_details_resolver.rb b/app/graphql/resolvers/package_details_resolver.rb index 42cb23e701d..705d3900cd2 100644 --- a/app/graphql/resolvers/package_details_resolver.rb +++ b/app/graphql/resolvers/package_details_resolver.rb @@ -17,9 +17,6 @@ module Resolvers end def resolve(id:) - # TODO: remove this line when the compatibility layer is removed - # See: https://gitlab.com/gitlab-org/gitlab/-/issues/257883 - id = ::Types::GlobalIDType[::Packages::Package].coerce_isolated_input(id) GitlabSchema.find_by_gid(id) end end diff --git a/app/graphql/resolvers/package_pipelines_resolver.rb b/app/graphql/resolvers/package_pipelines_resolver.rb index 59a1cd173a4..9ff77f02547 100644 --- a/app/graphql/resolvers/package_pipelines_resolver.rb +++ b/app/graphql/resolvers/package_pipelines_resolver.rb @@ -12,21 +12,33 @@ module Resolvers alias_method :package, :object - def resolve(first: nil, last: nil, after: nil, before: nil, lookahead:) - finder = ::Packages::BuildInfosFinder.new( - package, - first: first, - last: last, - after: decode_cursor(after), - before: decode_cursor(before), - max_page_size: context.schema.default_max_page_size, - support_next_page: lookahead.selects?(:page_info) - ) + # this resolver can be called for 100 packages max and we want to limit the + # number of build infos returned for _each_ package when using the new finder. + MAX_PAGE_SIZE = 20 - build_infos = finder.execute + # This returns a promise for a connection of promises for pipelines: + # Lazy[Connection[Lazy[Pipeline]]] structure + def resolve(first: nil, last: nil, after: nil, before: nil, lookahead:) + default_value = default_value_for(first: first, last: last, after: after, before: before) + BatchLoader::GraphQL.for(package.id) + .batch(default_value: default_value) do |package_ids, loader| + build_infos = ::Packages::BuildInfosFinder.new( + package_ids, + first: first, + last: last, + after: decode_cursor(after), + before: decode_cursor(before), + max_page_size: MAX_PAGE_SIZE, + support_next_page: lookahead.selects?(:page_info) + ).execute - # this .pluck_pipeline_ids can load max 101 pipelines ids - ::Ci::Pipeline.id_in(build_infos.pluck_pipeline_ids) + build_infos.each do |build_info| + loader.call(build_info.package_id) do |connection| + connection.items << lazy_load_pipeline(build_info.pipeline_id) + connection + end + end + end end # we manage the pagination manually, so opt out of the connection field extension @@ -39,6 +51,22 @@ module Resolvers private + def lazy_load_pipeline(id) + ::Gitlab::Graphql::Loaders::BatchModelLoader.new(::Ci::Pipeline, id) + .find + end + + def default_value_for(first:, last:, after:, before:) + Gitlab::Graphql::Pagination::ActiveRecordArrayConnection.new( + [], + first: first, + last: last, + after: after, + before: before, + max_page_size: MAX_PAGE_SIZE + ) + end + def decode_cursor(encoded) return unless encoded diff --git a/app/graphql/resolvers/project_packages_resolver.rb b/app/graphql/resolvers/project_packages_resolver.rb index 6d66c2fe460..284d3c594da 100644 --- a/app/graphql/resolvers/project_packages_resolver.rb +++ b/app/graphql/resolvers/project_packages_resolver.rb @@ -8,7 +8,10 @@ module Resolvers def resolve(sort:, **filters) return unless packages_available? - ::Packages::PackagesFinder.new(object, filters.merge(SORT_TO_PARAMS_MAP.fetch(sort))).execute + params = filters.merge(SORT_TO_PARAMS_MAP.fetch(sort)) + params[:preload_pipelines] = false + + ::Packages::PackagesFinder.new(object, params).execute end end end diff --git a/app/graphql/resolvers/project_pipeline_resolver.rb b/app/graphql/resolvers/project_pipeline_resolver.rb index ea733ab08ad..69327cd17b1 100644 --- a/app/graphql/resolvers/project_pipeline_resolver.rb +++ b/app/graphql/resolvers/project_pipeline_resolver.rb @@ -47,5 +47,10 @@ module Resolvers { statuses: [:needs] } ] end + + def self.resolver_complexity(args, child_complexity:) + complexity = super + complexity - 10 + end end end diff --git a/app/graphql/resolvers/snippets_resolver.rb b/app/graphql/resolvers/snippets_resolver.rb index 149bd8fa1ce..90f5f2cb534 100644 --- a/app/graphql/resolvers/snippets_resolver.rb +++ b/app/graphql/resolvers/snippets_resolver.rb @@ -38,11 +38,9 @@ module Resolvers private def snippet_finder_params(args) - # TODO: remove the type arguments when the compatibility layer is removed - # See: https://gitlab.com/gitlab-org/gitlab/-/issues/257883 super - .merge(author: resolve_ids(args[:author_id], ::Types::GlobalIDType[::User]), - project: resolve_ids(args[:project_id], ::Types::GlobalIDType[::Project]), + .merge(author: resolve_ids(args[:author_id]), + project: resolve_ids(args[:project_id]), explore: args[:explore]) end end diff --git a/app/graphql/resolvers/timelog_resolver.rb b/app/graphql/resolvers/timelog_resolver.rb index 14831a29d90..52c4508003a 100644 --- a/app/graphql/resolvers/timelog_resolver.rb +++ b/app/graphql/resolvers/timelog_resolver.rb @@ -3,7 +3,6 @@ module Resolvers class TimelogResolver < BaseResolver include LooksAhead - include ResolvesIds type ::Types::TimelogType.connection_type, null: false @@ -100,14 +99,13 @@ module Resolvers def apply_project_filter(timelogs, args) return timelogs unless args[:project_id] - project = resolve_ids(args[:project_id], ::Types::GlobalIDType[::Project]) - timelogs.in_project(project) + timelogs.in_project(args[:project_id].model_id) end def apply_group_filter(timelogs, args) return timelogs unless args[:group_id] - group = Group.find_by_id(resolve_ids(args[:group_id], ::Types::GlobalIDType[::Group])) + group = Group.find_by_id(args[:group_id].model_id) timelogs.in_group(group) end diff --git a/app/graphql/resolvers/user_merge_requests_resolver_base.rb b/app/graphql/resolvers/user_merge_requests_resolver_base.rb index e0201e45664..b2d85307c49 100644 --- a/app/graphql/resolvers/user_merge_requests_resolver_base.rb +++ b/app/graphql/resolvers/user_merge_requests_resolver_base.rb @@ -57,9 +57,6 @@ module Resolvers end def load_project(project_path, project_id) - # TODO: remove this line when the compatibility layer is removed - # See: https://gitlab.com/gitlab-org/gitlab/-/issues/257883 - project_id &&= ::Types::GlobalIDType[::Project].coerce_isolated_input(project_id) @project = ::Gitlab::Graphql::Lazy.force(resolve_project(full_path: project_path, project_id: project_id)) end diff --git a/app/graphql/resolvers/work_item_resolver.rb b/app/graphql/resolvers/work_item_resolver.rb index ad510849f31..9eb7d6bc693 100644 --- a/app/graphql/resolvers/work_item_resolver.rb +++ b/app/graphql/resolvers/work_item_resolver.rb @@ -20,9 +20,6 @@ module Resolvers private def find_object(id:) - # TODO: remove this line when the compatibility layer is removed - # See: https://gitlab.com/gitlab-org/gitlab/-/issues/257883 - id = ::Types::GlobalIDType[::WorkItem].coerce_isolated_input(id) GitlabSchema.find_by_gid(id) end end diff --git a/app/graphql/subscriptions/issuable_updated.rb b/app/graphql/subscriptions/issuable_updated.rb index c1d82bfcf9c..ad78fd4b4a1 100644 --- a/app/graphql/subscriptions/issuable_updated.rb +++ b/app/graphql/subscriptions/issuable_updated.rb @@ -15,10 +15,6 @@ module Subscriptions end def authorized?(issuable_id:) - # TODO: remove this check when the compatibility layer is removed - # See: https://gitlab.com/gitlab-org/gitlab/-/issues/257883 - raise Gitlab::Graphql::Errors::ArgumentError, 'Invalid IssuableID' unless issuable_id.is_a?(GlobalID) - issuable = force(GitlabSchema.find_by_gid(issuable_id)) unauthorized! unless issuable && Ability.allowed?(current_user, :"read_#{issuable.to_ability_name}", issuable) diff --git a/app/graphql/types/alert_management/domain_filter_enum.rb b/app/graphql/types/alert_management/domain_filter_enum.rb index 3ee01e4c391..cd70cdd8ecf 100644 --- a/app/graphql/types/alert_management/domain_filter_enum.rb +++ b/app/graphql/types/alert_management/domain_filter_enum.rb @@ -7,7 +7,11 @@ module Types 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 'threat_monitoring', description: 'Alerts for threat monitoring domain.', + deprecated: { + reason: 'Network policies are deprecated and will be removed in GitLab 16.0', + milestone: '15.0' + } end end end diff --git a/app/graphql/types/base_field.rb b/app/graphql/types/base_field.rb index 75909592c6c..b4cd54b1332 100644 --- a/app/graphql/types/base_field.rb +++ b/app/graphql/types/base_field.rb @@ -68,7 +68,7 @@ module Types end def visible?(context) - return false if feature_flag.present? && !Feature.enabled?(feature_flag, default_enabled: :yaml) + return false if feature_flag.present? && !Feature.enabled?(feature_flag) super end diff --git a/app/graphql/types/boards/board_issue_input_type.rb b/app/graphql/types/boards/board_issue_input_type.rb index afa66c1c510..0dd7fbc87da 100644 --- a/app/graphql/types/boards/board_issue_input_type.rb +++ b/app/graphql/types/boards/board_issue_input_type.rb @@ -7,7 +7,6 @@ module Types argument :not, NegatedBoardIssueInputType, required: false, - prepare: ->(negated_args, ctx) { negated_args.to_h }, description: 'List of negated arguments.' argument :search, GraphQL::Types::String, diff --git a/app/graphql/types/ci/config/config_type.rb b/app/graphql/types/ci/config/config_type.rb index de355c8eacf..a7a6927136d 100644 --- a/app/graphql/types/ci/config/config_type.rb +++ b/app/graphql/types/ci/config/config_type.rb @@ -9,6 +9,8 @@ module Types field :errors, [GraphQL::Types::String], null: true, description: 'Linting errors.' + field :includes, [Types::Ci::Config::IncludeType], null: true, + description: 'List of included files.' field :merged_yaml, GraphQL::Types::String, null: true, description: 'Merged CI configuration YAML.' field :stages, Types::Ci::Config::StageType.connection_type, null: true, diff --git a/app/graphql/types/ci/config/include_type.rb b/app/graphql/types/ci/config/include_type.rb new file mode 100644 index 00000000000..71eb8f755ab --- /dev/null +++ b/app/graphql/types/ci/config/include_type.rb @@ -0,0 +1,53 @@ +# frozen_string_literal: true + +module Types + module Ci + # rubocop: disable Graphql/AuthorizeTypes + module Config + class IncludeType < BaseObject + graphql_name 'CiConfigInclude' + + field :type, + Types::Ci::Config::IncludeTypeEnum, + null: true, + description: 'Include type.' + + field :location, + GraphQL::Types::String, + null: true, + description: 'File location. It can be masked if it contains masked variables, e.g., ' \ + '".gitlab/ci/build-images.gitlab-ci.yml".' + + field :blob, + GraphQL::Types::String, + null: true, + description: 'File blob location. It can be masked if it contains masked variables, e.g., ' \ + '"https://gitlab.com/gitlab-org/gitlab/-/blob/e52d6d0246d7375291850e61f0abc101fbda9dc2' \ + '/.gitlab/ci/build-images.gitlab-ci.yml".' + + field :raw, + GraphQL::Types::String, + null: true, + description: 'File raw location. It can be masked if it contains masked variables, e.g., ' \ + '"https://gitlab.com/gitlab-org/gitlab/-/raw/e52d6d0246d7375291850e61f0abc101fbda9dc2' \ + '/.gitlab/ci/build-images.gitlab-ci.yml".' + + field :extra, # rubocop:disable Graphql/JSONType + GraphQL::Types::JSON, + null: true, + description: 'Extra information for the `include`, which can contain `job_name`, `project`, and `ref`. ' \ + 'Values can be masked if they contain masked variables.' + + field :context_project, + GraphQL::Types::String, + null: true, + description: 'Current project scope, e.g., "gitlab-org/gitlab".' + + field :context_sha, + GraphQL::Types::String, + null: true, + description: 'Current sha scope.' + end + end + end +end diff --git a/app/graphql/types/ci/config/include_type_enum.rb b/app/graphql/types/ci/config/include_type_enum.rb new file mode 100644 index 00000000000..328824ae996 --- /dev/null +++ b/app/graphql/types/ci/config/include_type_enum.rb @@ -0,0 +1,17 @@ +# frozen_string_literal: true + +module Types + module Ci + module Config + class IncludeTypeEnum < BaseEnum + graphql_name 'CiConfigIncludeType' + description 'Include type.' + + value 'remote', description: 'Remote include.', value: :remote + value 'local', description: 'Local include.', value: :local + value 'file', description: 'Project file include.', value: :file + value 'template', description: 'Template include.', value: :template + end + end + end +end diff --git a/app/graphql/types/ci/pipeline_type.rb b/app/graphql/types/ci/pipeline_type.rb index 537b8e42ad1..81afc7f0f42 100644 --- a/app/graphql/types/ci/pipeline_type.rb +++ b/app/graphql/types/ci/pipeline_type.rb @@ -195,7 +195,6 @@ module Types raise ::Gitlab::Graphql::Errors::ArgumentError, 'One of id or name is required' unless id || name if id - id = ::Types::GlobalIDType[::CommitStatus].coerce_isolated_input(id) if id pipeline.statuses.id_in(id.model_id) else pipeline.statuses.by_name(name) diff --git a/app/graphql/types/ci/runner_status_enum.rb b/app/graphql/types/ci/runner_status_enum.rb index 2e65e2d4e1e..e8bd3d15a54 100644 --- a/app/graphql/types/ci/runner_status_enum.rb +++ b/app/graphql/types/ci/runner_status_enum.rb @@ -28,21 +28,17 @@ module Types value: :online value 'OFFLINE', - description: "Runner that has not contacted this instance within the last #{::Ci::Runner::ONLINE_CONTACT_TIMEOUT.inspect}.", - deprecated: { reason: 'This field will have a slightly different scope starting in 15.0, with STALE being returned after a certain period offline', milestone: '14.6' }, + description: "Runner that has not contacted this instance within the " \ + "last #{::Ci::Runner::ONLINE_CONTACT_TIMEOUT.inspect}. Will be considered `STALE` if offline for " \ + "more than #{::Ci::Runner::STALE_TIMEOUT.inspect}.", value: :offline value 'STALE', - description: "Runner that has not contacted this instance within the last #{::Ci::Runner::STALE_TIMEOUT.inspect}. Only available if legacyMode is null. Will be a possible return value starting in 15.0.", + description: "Runner that has not contacted this instance within the last #{::Ci::Runner::STALE_TIMEOUT.inspect}.", value: :stale - value 'NOT_CONNECTED', - description: 'Runner that has never contacted this instance.', - deprecated: { reason: "Use NEVER_CONTACTED instead. NEVER_CONTACTED will have a slightly different scope starting in 15.0, with STALE being returned instead after #{::Ci::Runner::STALE_TIMEOUT.inspect} of no contact", milestone: '14.6' }, - value: :not_connected - value 'NEVER_CONTACTED', - description: 'Runner that has never contacted this instance. Set legacyMode to null to utilize this value. Will replace NOT_CONNECTED starting in 15.0.', + description: 'Runner that has never contacted this instance.', value: :never_contacted end end diff --git a/app/graphql/types/ci/runner_type.rb b/app/graphql/types/ci/runner_type.rb index a7f0730f07e..6f957d2511f 100644 --- a/app/graphql/types/ci/runner_type.rb +++ b/app/graphql/types/ci/runner_type.rb @@ -34,8 +34,15 @@ module Types description: 'Admin form URL of the runner. Only available for administrators.' field :executor_name, GraphQL::Types::String, null: true, description: 'Executor last advertised by the runner.', - method: :executor_name, - feature_flag: :graphql_ci_runner_executor + method: :executor_name + field :platform_name, GraphQL::Types::String, null: true, + description: 'Platform provided by the runner.', + method: :platform + field :architecture_name, GraphQL::Types::String, null: true, + description: 'Architecture provided by the the runner.', + method: :architecture + field :maintenance_note, GraphQL::Types::String, null: true, + description: 'Runner\'s maintenance notes.' field :groups, ::Types::GroupType.connection_type, null: true, description: 'Groups the runner is associated with. For group runners only.' field :id, ::Types::GlobalIDType[::Ci::Runner], null: false, @@ -70,7 +77,7 @@ module Types Types::Ci::RunnerStatusEnum, null: false, description: 'Status of the runner.', - resolver: ::Resolvers::Ci::RunnerStatusResolver + resolver: ::Resolvers::Ci::RunnerStatusResolver # TODO: Remove :resolver in %17.0 field :tag_list, [GraphQL::Types::String], null: true, description: 'Tags associated with the runner.' field :token_expires_at, Types::TimeType, null: true, diff --git a/app/graphql/types/ci/runner_upgrade_status_type_enum.rb b/app/graphql/types/ci/runner_upgrade_status_type_enum.rb index e3d77e485bc..02feafe3df9 100644 --- a/app/graphql/types/ci/runner_upgrade_status_type_enum.rb +++ b/app/graphql/types/ci/runner_upgrade_status_type_enum.rb @@ -5,17 +5,11 @@ module Types class RunnerUpgradeStatusTypeEnum < BaseEnum graphql_name 'CiRunnerUpgradeStatusType' - value 'NOT_AVAILABLE', - description: "An update is not available for the runner.", - value: :not_available + value 'UNKNOWN', description: 'Upgrade status is unknown.', value: :unknown - value 'AVAILABLE', - description: "An update is available for the runner.", - value: :available - - value 'RECOMMENDED', - description: "An update is available and recommended for the runner.", - value: :recommended + Gitlab::Ci::RunnerUpgradeCheck::STATUSES.each do |status, description| + value status.to_s.upcase, description: description, value: status + end end end end diff --git a/app/graphql/types/color_type.rb b/app/graphql/types/color_type.rb new file mode 100644 index 00000000000..ee5c0c8737b --- /dev/null +++ b/app/graphql/types/color_type.rb @@ -0,0 +1,25 @@ +# frozen_string_literal: true + +module Types + class ColorType < BaseScalar + graphql_name 'Color' + description <<~DESC + Color represented as a hex code or named color. + + For example: "#fefefe". + DESC + + def self.coerce_input(value, ctx) + color = Gitlab::Color.of(value) + raise GraphQL::CoercionError, 'Not a color' unless color.valid? + + color + rescue ArgumentError => e + raise GraphQL::CoercionError, e.message + end + + def self.coerce_result(value, ctx) + value.to_s + end + end +end diff --git a/app/graphql/types/concerns/gitlab_style_deprecations.rb b/app/graphql/types/concerns/gitlab_style_deprecations.rb index 802562ed958..cd8e393b235 100644 --- a/app/graphql/types/concerns/gitlab_style_deprecations.rb +++ b/app/graphql/types/concerns/gitlab_style_deprecations.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true # Concern for handling deprecation arguments. -# https://docs.gitlab.com/ee/development/api_graphql_styleguide.html#deprecating-fields-and-enum-values +# https://docs.gitlab.com/ee/development/api_graphql_styleguide.html#deprecating-schema-items module GitlabStyleDeprecations extend ActiveSupport::Concern @@ -11,7 +11,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-arguments-and-enum-values' + 'See https://docs.gitlab.com/ee/development/api_graphql_styleguide.html#deprecating-schema-items' end deprecation = ::Gitlab::Graphql::Deprecation.parse(kwargs.delete(:deprecated)) diff --git a/app/graphql/types/container_expiration_policy_type.rb b/app/graphql/types/container_expiration_policy_type.rb index 0e9534be684..22020aff36b 100644 --- a/app/graphql/types/container_expiration_policy_type.rb +++ b/app/graphql/types/container_expiration_policy_type.rb @@ -6,7 +6,7 @@ module Types description 'A tag expiration policy designed to keep only the images that matter most' - authorize :destroy_container_image + authorize :admin_container_image field :cadence, Types::ContainerExpirationPolicyCadenceEnum, null: false, description: 'This container expiration policy schedule.' field :created_at, Types::TimeType, null: false, description: 'Timestamp of when the container expiration policy was created.' diff --git a/app/graphql/types/container_repository_type.rb b/app/graphql/types/container_repository_type.rb index dddf9a3ee97..cb818ac5e92 100644 --- a/app/graphql/types/container_repository_type.rb +++ b/app/graphql/types/container_repository_type.rb @@ -21,6 +21,7 @@ module Types field :status, Types::ContainerRepositoryStatusEnum, null: true, description: 'Status of the container repository.' field :tags_count, GraphQL::Types::Int, null: false, description: 'Number of tags associated with this image.' field :updated_at, Types::TimeType, null: false, description: 'Timestamp when the container repository was updated.' + field :last_cleanup_deleted_tags_count, GraphQL::Types::Int, null: true, description: 'Number of deleted tags from the last cleanup.' def can_delete Ability.allowed?(current_user, :update_container_image, object) diff --git a/app/graphql/types/current_user_todos.rb b/app/graphql/types/current_user_todos.rb index 2551db875b0..4c4cb516979 100644 --- a/app/graphql/types/current_user_todos.rb +++ b/app/graphql/types/current_user_todos.rb @@ -17,9 +17,24 @@ module Types def current_user_todos(state: nil) state ||= %i[done pending] # TodosFinder treats a `nil` state param as `pending` - klass = unpresented.class + key = [state, unpresented.class.name] - TodosFinder.new(current_user, state: state, type: klass.name, target_id: object.id).execute + BatchLoader::GraphQL.for(unpresented).batch(default_value: [], key: key) do |targets, loader, args| + state, klass_name = args[:key] + + targets_by_id = targets.index_by(&:id) + ids = targets_by_id.keys + + results = TodosFinder.new(current_user, state: state, type: klass_name, target_id: ids).execute + + by_target_id = results.group_by(&:target_id) + + by_target_id.each do |target_id, todos| + target = targets_by_id[target_id] + todos.each { _1.target = target } # prevent extra loads + loader.call(target, todos) + end + end end end end diff --git a/app/graphql/types/customer_relations/contact_type.rb b/app/graphql/types/customer_relations/contact_type.rb index 6a3882c66af..c07d2164d14 100644 --- a/app/graphql/types/customer_relations/contact_type.rb +++ b/app/graphql/types/customer_relations/contact_type.rb @@ -50,6 +50,11 @@ module Types Types::TimeType, null: false, description: 'Timestamp the contact was last updated.' + + field :active, + GraphQL::Types::Boolean, + null: false, + description: 'State of the contact.', method: :active? end end end diff --git a/app/graphql/types/customer_relations/organization_type.rb b/app/graphql/types/customer_relations/organization_type.rb index 0f97f0a2433..d7835470795 100644 --- a/app/graphql/types/customer_relations/organization_type.rb +++ b/app/graphql/types/customer_relations/organization_type.rb @@ -36,6 +36,11 @@ module Types Types::TimeType, null: false, description: 'Timestamp the organization was last updated.' + + field :active, + GraphQL::Types::Boolean, + null: false, + description: 'State of the organization.', method: :active? end end end diff --git a/app/graphql/types/dependency_proxy/group_setting_type.rb b/app/graphql/types/dependency_proxy/group_setting_type.rb index 8b8b8572aa9..6c6f848d019 100644 --- a/app/graphql/types/dependency_proxy/group_setting_type.rb +++ b/app/graphql/types/dependency_proxy/group_setting_type.rb @@ -6,7 +6,7 @@ module Types description 'Group-level Dependency Proxy settings' - authorize :read_dependency_proxy + authorize :admin_dependency_proxy field :enabled, GraphQL::Types::Boolean, null: false, description: 'Indicates whether the dependency proxy is enabled for the group.' end diff --git a/app/graphql/types/dependency_proxy/image_ttl_group_policy_type.rb b/app/graphql/types/dependency_proxy/image_ttl_group_policy_type.rb index 9ab7c50998d..b8c178539a0 100644 --- a/app/graphql/types/dependency_proxy/image_ttl_group_policy_type.rb +++ b/app/graphql/types/dependency_proxy/image_ttl_group_policy_type.rb @@ -6,7 +6,7 @@ module Types description 'Group-level Dependency Proxy TTL policy settings' - authorize :read_dependency_proxy + authorize :admin_dependency_proxy field :created_at, Types::TimeType, null: true, description: 'Timestamp of creation.' field :enabled, GraphQL::Types::Boolean, null: false, description: 'Indicates whether the policy is enabled or disabled.' diff --git a/app/graphql/types/deprecated_mutations.rb b/app/graphql/types/deprecated_mutations.rb index 70d5fc31cd1..49bad56b6f9 100644 --- a/app/graphql/types/deprecated_mutations.rb +++ b/app/graphql/types/deprecated_mutations.rb @@ -5,8 +5,7 @@ module Types extend ActiveSupport::Concern prepended do - mount_mutation Mutations::Clusters::AgentTokens::Delete, - deprecated: { reason: 'Tokens must be revoked with ClusterAgentTokenRevoke', milestone: '14.7' } + # placeholder for any FOSS mutations to be deprecated end end end diff --git a/app/graphql/types/design_management/design_fields.rb b/app/graphql/types/design_management/design_fields.rb index 364f72a519f..c3a35cfe1ad 100644 --- a/app/graphql/types/design_management/design_fields.rb +++ b/app/graphql/types/design_management/design_fields.rb @@ -43,13 +43,12 @@ module Types end def image_v432x230(parent:) - version = cached_stateful_version(parent) - action = design.actions.up_to_version(version).most_recent.first - - # A `nil` return value indicates that the image has not been processed - return unless action.image_v432x230.file + Gitlab::Graphql::Lazy.with_value(lazy_action(parent)) do |action| + # A `nil` return value indicates that the image has not been processed + next unless action&.image_v432x230&.file - Gitlab::UrlBuilder.build(design, ref: version.sha, size: :v432x230) + Gitlab::UrlBuilder.build(action.design, ref: action.version.sha, size: :v432x230) + end end def event(parent:) @@ -73,6 +72,25 @@ module Types def issue ::Gitlab::Graphql::Loaders::BatchModelLoader.new(::Issue, design.issue_id).find end + + private + + def lazy_action(parent) + version = cached_stateful_version(parent) + + BatchLoader::GraphQL.for([version, design]).batch do |ids, loader| + by_version = ids.group_by(&:first).transform_values { _1.map(&:second) } + designs_by_id = ids.map(&:second).index_by(&:id) + + by_version.each do |v, designs| + actions = ::DesignManagement::Action.most_recent.up_to_version(v).by_design(designs).with_version + actions.each do |action| + action.design = designs_by_id[action.design_id] # eliminate duplicate load + loader.call([v, action.design], action) + end + end + end + end end end end diff --git a/app/graphql/types/design_management/design_type.rb b/app/graphql/types/design_management/design_type.rb index 4c0b1162306..cc4c0e19ec7 100644 --- a/app/graphql/types/design_management/design_type.rb +++ b/app/graphql/types/design_management/design_type.rb @@ -23,14 +23,13 @@ module Types field :versions, Types::DesignManagement::VersionType.connection_type, resolver: Resolvers::DesignManagement::VersionsResolver, - description: "All versions related to this design ordered newest first.", - extras: [:parent] + description: "All versions related to this design ordered newest first." # Returns a `DesignManagement::Version` for this query based on the # `atVersion` argument passed to a parent node if present, or otherwise # the most recent `Version` for the issue. def cached_stateful_version(parent_node) - version_gid = Gitlab::Graphql::FindArgumentInParent.find(parent_node, :at_version) + version_gid = context[:at_version_argument] # See: DesignsResolver # Caching is scoped to an `issue_id` to allow us to cache the # most recent `Version` for an issue diff --git a/app/graphql/types/global_id_type.rb b/app/graphql/types/global_id_type.rb index 4f92b5e8cc2..6a924c13a3c 100644 --- a/app/graphql/types/global_id_type.rb +++ b/app/graphql/types/global_id_type.rb @@ -1,21 +1,5 @@ # frozen_string_literal: true -module GraphQLExtensions - module ScalarExtensions - # Allow ID to unify with GlobalID Types - def ==(other) - if name == 'ID' && other.is_a?(self.class) && - other.type_class.ancestors.include?(::Types::GlobalIDType) - return true - end - - super - end - end -end - -::GraphQL::ScalarType.prepend(GraphQLExtensions::ScalarExtensions) - module Types class GlobalIDType < BaseScalar graphql_name 'GlobalID' diff --git a/app/graphql/types/incident_management/timeline_event_type.rb b/app/graphql/types/incident_management/timeline_event_type.rb new file mode 100644 index 00000000000..a6d3f57404b --- /dev/null +++ b/app/graphql/types/incident_management/timeline_event_type.rb @@ -0,0 +1,72 @@ +# frozen_string_literal: true + +module Types + module IncidentManagement + class TimelineEventType < BaseObject + graphql_name 'TimelineEventType' + description 'Describes an incident management timeline event' + + authorize :read_incident_management_timeline_event + + field :id, + Types::GlobalIDType[::IncidentManagement::TimelineEvent], + null: false, + description: 'ID of the timeline event.' + + field :author, + Types::UserType, + null: true, + description: 'User that created the timeline event.' + + field :updated_by_user, + Types::UserType, + null: true, + description: 'User that updated the timeline event.' + + field :incident, + Types::IssueType, + null: false, + description: 'Incident of the timeline event.' + + field :note, + GraphQL::Types::String, + null: true, + description: 'Text note of the timeline event.' + + field :note_html, + GraphQL::Types::String, + null: true, + description: 'HTML note of the timeline event.' + + field :promoted_from_note, + Types::Notes::NoteType, + null: true, + description: 'Note from which the timeline event was created.' + + field :editable, + GraphQL::Types::Boolean, + null: false, + description: 'Indicates the timeline event is editable.' + + field :action, + GraphQL::Types::String, + null: false, + description: 'Indicates the timeline event icon.' + + field :occurred_at, + Types::TimeType, + null: false, + description: 'Timestamp when the event occurred.' + + field :created_at, + Types::TimeType, + null: false, + description: 'Timestamp when the event created.' + + field :updated_at, + Types::TimeType, + null: false, + description: 'Timestamp when the event updated.' + end + end +end diff --git a/app/graphql/types/issue_type.rb b/app/graphql/types/issue_type.rb index 07450c38616..c83200bd614 100644 --- a/app/graphql/types/issue_type.rb +++ b/app/graphql/types/issue_type.rb @@ -170,7 +170,7 @@ module Types end def hidden? - object.hidden? if Feature.enabled?(:ban_user_feature_flag, default_enabled: :yaml) + object.hidden? if Feature.enabled?(:ban_user_feature_flag) end def escalation_status diff --git a/app/graphql/types/merge_request_type.rb b/app/graphql/types/merge_request_type.rb index af198d03c3f..cc3df474bef 100644 --- a/app/graphql/types/merge_request_type.rb +++ b/app/graphql/types/merge_request_type.rb @@ -67,9 +67,6 @@ module Types description: 'Indicates if members of the target project can push to the fork.' field :default_merge_commit_message, GraphQL::Types::String, null: true, calls_gitaly: true, description: 'Default merge commit message of the merge request.' - field :default_merge_commit_message_with_description, GraphQL::Types::String, null: true, - description: 'Default merge commit message of the merge request with description. Will have the same value as `defaultMergeCommitMessage` when project has `mergeCommitTemplate` set.', - deprecated: { reason: 'Define merge commit template in project and use `defaultMergeCommitMessage`', milestone: '14.5' } field :default_squash_commit_message, GraphQL::Types::String, null: true, calls_gitaly: true, description: 'Default squash commit message of the merge request.' field :diff_stats_summary, Types::DiffStatsSummaryType, null: true, calls_gitaly: true, @@ -97,6 +94,7 @@ module Types method: :public_merge_status, null: true, description: 'Merge status of the merge request.' field :mergeable_discussions_state, GraphQL::Types::Boolean, null: true, + calls_gitaly: true, description: 'Indicates if all discussions in the merge request have been resolved, allowing the merge request to be merged.' field :rebase_commit_sha, GraphQL::Types::String, null: true, description: 'Rebase commit SHA of the merge request.' @@ -254,10 +252,6 @@ module Types object.default_merge_commit_message(include_description: false, user: current_user) end - def default_merge_commit_message_with_description - object.default_merge_commit_message(include_description: true) - end - def default_squash_commit_message object.default_squash_commit_message(user: current_user) end diff --git a/app/graphql/types/mutation_type.rb b/app/graphql/types/mutation_type.rb index 2297912ac35..7d8ada82d40 100644 --- a/app/graphql/types/mutation_type.rb +++ b/app/graphql/types/mutation_type.rb @@ -47,6 +47,10 @@ module Types mount_mutation Mutations::DependencyProxy::ImageTtlGroupPolicy::Update mount_mutation Mutations::DependencyProxy::GroupSettings::Update mount_mutation Mutations::Environments::CanaryIngress::Update + mount_mutation Mutations::IncidentManagement::TimelineEvent::Create + mount_mutation Mutations::IncidentManagement::TimelineEvent::PromoteFromNote + mount_mutation Mutations::IncidentManagement::TimelineEvent::Update + mount_mutation Mutations::IncidentManagement::TimelineEvent::Destroy mount_mutation Mutations::Issues::Create mount_mutation Mutations::Issues::SetAssignees mount_mutation Mutations::Issues::SetCrmContacts @@ -69,7 +73,9 @@ module Types mount_mutation Mutations::MergeRequests::SetDraft, calls_gitaly: true mount_mutation Mutations::MergeRequests::SetAssignees mount_mutation Mutations::MergeRequests::ReviewerRereview - mount_mutation Mutations::MergeRequests::ToggleAttentionRequested, feature_flag: :mr_attention_requests + mount_mutation Mutations::MergeRequests::RequestAttention + mount_mutation Mutations::MergeRequests::RemoveAttentionRequest + mount_mutation Mutations::MergeRequests::ToggleAttentionRequested mount_mutation Mutations::Metrics::Dashboard::Annotations::Create mount_mutation Mutations::Metrics::Dashboard::Annotations::Delete mount_mutation Mutations::Notes::Create::Note, calls_gitaly: true @@ -88,6 +94,7 @@ module Types mount_mutation Mutations::Terraform::State::Delete mount_mutation Mutations::Terraform::State::Lock mount_mutation Mutations::Terraform::State::Unlock + mount_mutation Mutations::Timelogs::Delete mount_mutation Mutations::Todos::Create mount_mutation Mutations::Todos::MarkDone mount_mutation Mutations::Todos::Restore @@ -108,7 +115,12 @@ module Types mount_mutation Mutations::Ci::Pipeline::Cancel mount_mutation Mutations::Ci::Pipeline::Destroy mount_mutation Mutations::Ci::Pipeline::Retry - mount_mutation Mutations::Ci::CiCdSettingsUpdate + mount_mutation Mutations::Ci::CiCdSettingsUpdate, deprecated: { + reason: :renamed, + replacement: 'ProjectCiCdSettingsUpdate', + milestone: '15.0' + } + mount_mutation Mutations::Ci::ProjectCiCdSettingsUpdate mount_mutation Mutations::Ci::Job::Play mount_mutation Mutations::Ci::Job::Retry mount_mutation Mutations::Ci::Job::Cancel @@ -128,6 +140,7 @@ module Types mount_mutation Mutations::WorkItems::Create mount_mutation Mutations::WorkItems::CreateFromTask mount_mutation Mutations::WorkItems::Delete + mount_mutation Mutations::WorkItems::DeleteTask mount_mutation Mutations::WorkItems::Update mount_mutation Mutations::SavedReplies::Create mount_mutation Mutations::SavedReplies::Update diff --git a/app/graphql/types/namespace/package_settings_type.rb b/app/graphql/types/namespace/package_settings_type.rb index cb546bbf3ec..7a0abe619a5 100644 --- a/app/graphql/types/namespace/package_settings_type.rb +++ b/app/graphql/types/namespace/package_settings_type.rb @@ -6,7 +6,7 @@ module Types description 'Namespace-level Package Registry settings' - authorize :read_package_settings + authorize :admin_package field :generic_duplicate_exception_regex, Types::UntrustedRegexp, null: true, description: 'When generic_duplicates_allowed is false, you can publish duplicate packages with names that match this regex. Otherwise, this setting has no effect.' field :generic_duplicates_allowed, GraphQL::Types::Boolean, null: false, description: 'Indicates whether duplicate generic packages are allowed for this namespace.' 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 0c6e4a16434..913d24cb513 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 @@ -28,6 +28,8 @@ module Types raise GraphQL::ExecutionError, "At least one property of `#{self.class.graphql_name}` must be set" end end + + super end end end diff --git a/app/graphql/types/packages/package_base_type.rb b/app/graphql/types/packages/package_base_type.rb new file mode 100644 index 00000000000..06ccde94cd4 --- /dev/null +++ b/app/graphql/types/packages/package_base_type.rb @@ -0,0 +1,60 @@ +# frozen_string_literal: true + +module Types + module Packages + class PackageBaseType < ::Types::BaseObject + graphql_name 'PackageBase' + description 'Represents a package in the Package Registry' + + connection_type_class(Types::CountableConnectionType) + + authorize :read_package + + field :id, ::Types::GlobalIDType[::Packages::Package], null: false, + description: 'ID of the package.' + + field :can_destroy, GraphQL::Types::Boolean, null: false, description: 'Whether the user can destroy the package.' + field :created_at, Types::TimeType, null: false, description: 'Date of creation.' + field :metadata, Types::Packages::MetadataType, null: true, + description: 'Package metadata.' + field :name, GraphQL::Types::String, null: false, description: 'Name of the package.' + field :package_type, Types::Packages::PackageTypeEnum, null: false, description: 'Package type.' + field :project, Types::ProjectType, null: false, description: 'Project where the package is stored.' + field :status, Types::Packages::PackageStatusEnum, null: false, description: 'Package status.' + field :tags, Types::Packages::PackageTagType.connection_type, null: true, description: 'Package tags.' + field :updated_at, Types::TimeType, null: false, description: 'Date of most recent update.' + field :version, GraphQL::Types::String, null: true, description: 'Version string.' + + def project + Gitlab::Graphql::Loaders::BatchModelLoader.new(Project, object.project_id).find + end + + def can_destroy + Ability.allowed?(current_user, :destroy_package, object) + end + + # NOTE: This method must be kept in sync with the union + # type: `Types::Packages::MetadataType`. + # + # `Types::Packages::MetadataType.resolve_type(metadata, ctx)` must never raise. + # rubocop: disable GraphQL/ResolverMethodLength + def metadata + case object.package_type + when 'composer' + object.composer_metadatum + when 'conan' + object.conan_metadatum + when 'maven' + object.maven_metadatum + when 'nuget' + object.nuget_metadatum + when 'pypi' + object.pypi_metadatum + else + nil + end + end + # rubocop: enable GraphQL/ResolverMethodLength + end + end +end diff --git a/app/graphql/types/packages/package_details_type.rb b/app/graphql/types/packages/package_details_type.rb index 444ecb5e792..ae57e103f40 100644 --- a/app/graphql/types/packages/package_details_type.rb +++ b/app/graphql/types/packages/package_details_type.rb @@ -4,26 +4,19 @@ module Types module Packages class PackageDetailsType < PackageType graphql_name 'PackageDetailsType' - description 'Represents a package details in the Package Registry. Note that this type is in beta and susceptible to changes' + description 'Represents a package details in the Package Registry' include ::PackagesHelper authorize :read_package - field :versions, ::Types::Packages::PackageType.connection_type, null: true, + field :versions, ::Types::Packages::PackageBaseType.connection_type, null: true, description: 'Other versions of the package.' field :package_files, Types::Packages::PackageFileType.connection_type, null: true, method: :installable_package_files, description: 'Package files.' field :dependency_links, Types::Packages::PackageDependencyLinkType.connection_type, null: true, description: 'Dependency link.' - # this is an override of Types::Packages::PackageType.pipelines - # in order to use a custom resolver: Resolvers::PackagePipelinesResolver - field :pipelines, - resolver: Resolvers::PackagePipelinesResolver, - description: 'Pipelines that built the package.', - deprecated: { reason: 'Due to scalability concerns, this field is going to be removed', milestone: '14.6' } - field :composer_config_repository_url, GraphQL::Types::String, null: true, description: 'Url of the Composer setup endpoint.' field :composer_url, GraphQL::Types::String, null: true, description: 'Url of the Composer endpoint.' field :conan_url, GraphQL::Types::String, null: true, description: 'Url of the Conan project endpoint.' diff --git a/app/graphql/types/packages/package_type.rb b/app/graphql/types/packages/package_type.rb index 1155be28e08..f6586670c72 100644 --- a/app/graphql/types/packages/package_type.rb +++ b/app/graphql/types/packages/package_type.rb @@ -2,67 +2,17 @@ module Types module Packages - class PackageType < ::Types::BaseObject + class PackageType < Types::Packages::PackageBaseType graphql_name 'Package' - description 'Represents a package in the Package Registry. Note that this type is in beta and susceptible to changes' - - connection_type_class(Types::CountableConnectionType) + description 'Represents a package with pipelines in the Package Registry' authorize :read_package - field :id, ::Types::GlobalIDType[::Packages::Package], null: false, - description: 'ID of the package.' - - field :can_destroy, GraphQL::Types::Boolean, null: false, description: 'Whether the user can destroy the package.' - field :created_at, Types::TimeType, null: false, description: 'Date of creation.' - field :metadata, Types::Packages::MetadataType, null: true, - description: 'Package metadata.' - field :name, GraphQL::Types::String, null: false, description: 'Name of the package.' - field :package_type, Types::Packages::PackageTypeEnum, null: false, description: 'Package type.' - field :pipelines, Types::Ci::PipelineType.connection_type, null: true, - description: 'Pipelines that built the package.', - deprecated: { reason: 'Due to scalability concerns, this field is going to be removed', milestone: '14.6' } - field :project, Types::ProjectType, null: false, description: 'Project where the package is stored.' - field :status, Types::Packages::PackageStatusEnum, null: false, description: 'Package status.' - field :tags, Types::Packages::PackageTagType.connection_type, null: true, description: 'Package tags.' - field :updated_at, Types::TimeType, null: false, description: 'Date of most recent update.' - field :version, GraphQL::Types::String, null: true, description: 'Version string.' - field :versions, ::Types::Packages::PackageType.connection_type, null: true, - description: 'Other versions of the package.', - deprecated: { reason: 'This field is now only returned in the PackageDetailsType', milestone: '13.11' } - - def project - Gitlab::Graphql::Loaders::BatchModelLoader.new(Project, object.project_id).find - end - - def versions - [] - end - - def can_destroy - Ability.allowed?(current_user, :destroy_package, object) - end - - # NOTE: This method must be kept in sync with the union - # type: `Types::Packages::MetadataType`. - # - # `Types::Packages::MetadataType.resolve_type(metadata, ctx)` must never raise. - def metadata - case object.package_type - when 'composer' - object.composer_metadatum - when 'conan' - object.conan_metadatum - when 'maven' - object.maven_metadatum - when 'nuget' - object.nuget_metadatum - when 'pypi' - object.pypi_metadatum - else - nil - end - end + field :pipelines, + resolver: Resolvers::PackagePipelinesResolver, + description: <<-DESC + Pipelines that built the package. Max page size #{Resolvers::PackagePipelinesResolver::MAX_PAGE_SIZE}. + DESC end end end diff --git a/app/graphql/types/permission_types/timelog.rb b/app/graphql/types/permission_types/timelog.rb new file mode 100644 index 00000000000..c35f3101e39 --- /dev/null +++ b/app/graphql/types/permission_types/timelog.rb @@ -0,0 +1,11 @@ +# frozen_string_literal: true + +module Types + module PermissionTypes + class Timelog < BasePermissionType + graphql_name 'TimelogPermissions' + + abilities :admin_timelog + end + end +end diff --git a/app/graphql/types/permission_types/work_item.rb b/app/graphql/types/permission_types/work_item.rb new file mode 100644 index 00000000000..bae1dae4834 --- /dev/null +++ b/app/graphql/types/permission_types/work_item.rb @@ -0,0 +1,12 @@ +# frozen_string_literal: true + +module Types + module PermissionTypes + class WorkItem < BasePermissionType + graphql_name 'WorkItemPermissions' + description 'Check permissions for the current user on a work item' + + abilities :read_work_item, :update_work_item, :delete_work_item + end + end +end diff --git a/app/graphql/types/project_statistics_type.rb b/app/graphql/types/project_statistics_type.rb index 1146774b43c..5ab3cc33e85 100644 --- a/app/graphql/types/project_statistics_type.rb +++ b/app/graphql/types/project_statistics_type.rb @@ -27,5 +27,7 @@ module Types description: 'Uploads size of the project in bytes.' field :wiki_size, GraphQL::Types::Float, null: true, description: 'Wiki size of the project in bytes.' + field :container_registry_size, GraphQL::Types::Float, null: true, + description: 'Container Registry size of the project in bytes.' end end diff --git a/app/graphql/types/project_type.rb b/app/graphql/types/project_type.rb index 47e9a6c11fc..f1de8e985b3 100644 --- a/app/graphql/types/project_type.rb +++ b/app/graphql/types/project_type.rb @@ -295,6 +295,19 @@ module Types description: 'HTTP Integrations which can receive alerts for the project.', resolver: Resolvers::AlertManagement::HttpIntegrationsResolver + field :incident_management_timeline_events, + Types::IncidentManagement::TimelineEventType.connection_type, + null: true, + description: 'Incident Management Timeline events associated with the incident.', + extras: [:lookahead], + resolver: Resolvers::IncidentManagement::TimelineEventsResolver + + field :incident_management_timeline_event, + Types::IncidentManagement::TimelineEventType, + null: true, + description: 'Incident Management Timeline event associated with the incident.', + resolver: Resolvers::IncidentManagement::TimelineEventsResolver.single + field :releases, Types::ReleaseType.connection_type, null: true, diff --git a/app/graphql/types/projects/topic_type.rb b/app/graphql/types/projects/topic_type.rb index c579f2f2b9d..bde6d79ddbf 100644 --- a/app/graphql/types/projects/topic_type.rb +++ b/app/graphql/types/projects/topic_type.rb @@ -12,6 +12,10 @@ module Types field :name, GraphQL::Types::String, null: false, description: 'Name of the topic.' + field :title, GraphQL::Types::String, null: false, + method: :title_or_name, + description: 'Title of the topic.' + field :description, GraphQL::Types::String, null: true, description: 'Description of the topic.' diff --git a/app/graphql/types/query_type.rb b/app/graphql/types/query_type.rb index cc46c7e86e4..01b1a71896a 100644 --- a/app/graphql/types/query_type.rb +++ b/app/graphql/types/query_type.rb @@ -99,17 +99,6 @@ module Types argument :id, ::Types::GlobalIDType[::MergeRequest], required: true, description: 'Global ID of the merge request.' end - field :instance_statistics_measurements, - type: Types::Admin::Analytics::UsageTrends::MeasurementType.connection_type, - null: true, - description: 'Get statistics on the instance.', - resolver: Resolvers::Admin::Analytics::UsageTrends::MeasurementsResolver, - deprecated: { - reason: :renamed, - replacement: 'Query.usageTrendsMeasurements', - milestone: '13.10' - } - field :usage_trends_measurements, Types::Admin::Analytics::UsageTrends::MeasurementType.connection_type, null: true, description: 'Get statistics on the instance.', @@ -160,30 +149,18 @@ module Types end def issue(id:) - # TODO: remove this line when the compatibility layer is removed - # See: https://gitlab.com/gitlab-org/gitlab/-/issues/257883 - id = ::Types::GlobalIDType[::Issue].coerce_isolated_input(id) GitlabSchema.find_by_gid(id) end def merge_request(id:) - # TODO: remove this line when the compatibility layer is removed - # See: https://gitlab.com/gitlab-org/gitlab/-/issues/257883 - id = ::Types::GlobalIDType[::MergeRequest].coerce_isolated_input(id) GitlabSchema.find_by_gid(id) end def milestone(id:) - # TODO: remove this line when the compatibility layer is removed - # See: https://gitlab.com/gitlab-org/gitlab/-/issues/257883 - id = ::Types::GlobalIDType[Milestone].coerce_isolated_input(id) GitlabSchema.find_by_gid(id) end def container_repository(id:) - # TODO: remove this line when the compatibility layer is removed - # See: https://gitlab.com/gitlab-org/gitlab/-/issues/257883 - id = ::Types::GlobalIDType[::ContainerRepository].coerce_isolated_input(id) GitlabSchema.find_by_gid(id) end diff --git a/app/graphql/types/range_input_type.rb b/app/graphql/types/range_input_type.rb index 9580b37d6c0..15b8121da93 100644 --- a/app/graphql/types/range_input_type.rb +++ b/app/graphql/types/range_input_type.rb @@ -21,7 +21,7 @@ module Types raise ::Gitlab::Graphql::Errors::ArgumentError, 'start must be before end' end - to_h + super end end end diff --git a/app/graphql/types/root_storage_statistics_type.rb b/app/graphql/types/root_storage_statistics_type.rb index 467331c5643..b1b712aab38 100644 --- a/app/graphql/types/root_storage_statistics_type.rb +++ b/app/graphql/types/root_storage_statistics_type.rb @@ -16,5 +16,6 @@ module Types field :storage_size, GraphQL::Types::Float, null: false, description: 'Total storage in bytes.' field :uploads_size, GraphQL::Types::Float, null: false, description: 'Uploads size in bytes.' field :wiki_size, GraphQL::Types::Float, null: false, description: 'Wiki size in bytes.' + field :container_registry_size, GraphQL::Types::Float, null: false, description: 'Container Registry size in bytes.' end end diff --git a/app/graphql/types/timelog_type.rb b/app/graphql/types/timelog_type.rb index d348fa698fa..c3fb9b77927 100644 --- a/app/graphql/types/timelog_type.rb +++ b/app/graphql/types/timelog_type.rb @@ -6,6 +6,13 @@ module Types authorize :read_issue + expose_permissions Types::PermissionTypes::Timelog + + field :id, + GraphQL::Types::ID, + null: false, + description: 'Internal ID of the timelog.' + field :spent_at, Types::TimeType, null: true, diff --git a/app/graphql/types/work_item_type.rb b/app/graphql/types/work_item_type.rb index 512b9ef64d2..cd784d54959 100644 --- a/app/graphql/types/work_item_type.rb +++ b/app/graphql/types/work_item_type.rb @@ -23,5 +23,7 @@ module Types markdown_field :title_html, null: true markdown_field :description_html, null: true + + expose_permissions Types::PermissionTypes::WorkItem end end diff --git a/app/graphql/types/work_items/convert_task_input_type.rb b/app/graphql/types/work_items/convert_task_input_type.rb index 1f142c6815c..2e66c1c1b3f 100644 --- a/app/graphql/types/work_items/convert_task_input_type.rb +++ b/app/graphql/types/work_items/convert_task_input_type.rb @@ -24,10 +24,6 @@ module Types class << self def work_item_type_global_id(global_id) - # TODO: remove this line when the compatibility layer is removed - # See: https://gitlab.com/gitlab-org/gitlab/-/issues/257883 - global_id = ::Types::GlobalIDType[::WorkItems::Type].coerce_isolated_input(global_id) - global_id&.model_id end end diff --git a/app/graphql/types/work_items/deleted_task_input_type.rb b/app/graphql/types/work_items/deleted_task_input_type.rb new file mode 100644 index 00000000000..92297876c89 --- /dev/null +++ b/app/graphql/types/work_items/deleted_task_input_type.rb @@ -0,0 +1,19 @@ +# frozen_string_literal: true + +module Types + module WorkItems + class DeletedTaskInputType < BaseInputObject + graphql_name 'WorkItemDeletedTaskInput' + + argument :id, ::Types::GlobalIDType[::WorkItem], + required: true, + description: 'Global ID of the task referenced in the work item\'s description.' + argument :line_number_end, GraphQL::Types::Int, + required: true, + description: 'Last line in the Markdown source that defines the list item task.' + argument :line_number_start, GraphQL::Types::Int, + required: true, + description: 'First line in the Markdown source that defines the list item task.' + end + end +end |