summaryrefslogtreecommitdiff
path: root/app/graphql
diff options
context:
space:
mode:
Diffstat (limited to 'app/graphql')
-rw-r--r--app/graphql/mutations/clusters/agent_tokens/revoke.rb35
-rw-r--r--app/graphql/mutations/issues/set_crm_contacts.rb9
-rw-r--r--app/graphql/mutations/issues/set_escalation_status.rb46
-rw-r--r--app/graphql/mutations/work_items/create.rb57
-rw-r--r--app/graphql/queries/pipelines/get_pipeline_details.query.graphql21
-rw-r--r--app/graphql/resolvers/base_issues_resolver.rb3
-rw-r--r--app/graphql/resolvers/ci/config_resolver.rb2
-rw-r--r--app/graphql/resolvers/clusters/agent_tokens_resolver.rb9
-rw-r--r--app/graphql/resolvers/concerns/resolves_pipelines.rb4
-rw-r--r--app/graphql/resolvers/design_management/version/designs_at_version_resolver.rb6
-rw-r--r--app/graphql/resolvers/design_management/version_in_collection_resolver.rb6
-rw-r--r--app/graphql/resolvers/group_milestones_resolver.rb6
-rw-r--r--app/graphql/resolvers/merge_requests_resolver.rb4
-rw-r--r--app/graphql/resolvers/users/groups_resolver.rb4
-rw-r--r--app/graphql/resolvers/work_items/types_resolver.rb15
-rw-r--r--app/graphql/types/ci/config/config_type.rb2
-rw-r--r--app/graphql/types/ci/job_type.rb6
-rw-r--r--app/graphql/types/ci/pipeline_message_type.rb16
-rw-r--r--app/graphql/types/ci/pipeline_type.rb23
-rw-r--r--app/graphql/types/ci/runner_type.rb15
-rw-r--r--app/graphql/types/clusters/agent_token_status_enum.rb14
-rw-r--r--app/graphql/types/clusters/agent_token_type.rb5
-rw-r--r--app/graphql/types/commit_type.rb2
-rw-r--r--app/graphql/types/deprecated_mutations.rb3
-rw-r--r--app/graphql/types/group_type.rb5
-rw-r--r--app/graphql/types/incident_management/escalation_status_enum.rb14
-rw-r--r--app/graphql/types/issue_type.rb9
-rw-r--r--app/graphql/types/issue_type_enum.rb2
-rw-r--r--app/graphql/types/merge_request_type.rb22
-rw-r--r--app/graphql/types/mutation_type.rb4
-rw-r--r--app/graphql/types/packages/package_details_type.rb51
-rw-r--r--app/graphql/types/project_type.rb48
-rw-r--r--app/graphql/types/projects/topic_type.rb3
-rw-r--r--app/graphql/types/release_type.rb11
-rw-r--r--app/graphql/types/repository/blob_type.rb19
-rw-r--r--app/graphql/types/sha_format_enum.rb19
-rw-r--r--app/graphql/types/user_interface.rb3
-rw-r--r--app/graphql/types/work_item_type.rb23
-rw-r--r--app/graphql/types/work_items/type_type.rb18
39 files changed, 508 insertions, 56 deletions
diff --git a/app/graphql/mutations/clusters/agent_tokens/revoke.rb b/app/graphql/mutations/clusters/agent_tokens/revoke.rb
new file mode 100644
index 00000000000..ca570792296
--- /dev/null
+++ b/app/graphql/mutations/clusters/agent_tokens/revoke.rb
@@ -0,0 +1,35 @@
+# frozen_string_literal: true
+
+module Mutations
+ module Clusters
+ module AgentTokens
+ class Revoke < BaseMutation
+ graphql_name 'ClusterAgentTokenRevoke'
+
+ authorize :admin_cluster
+
+ TokenID = ::Types::GlobalIDType[::Clusters::AgentToken]
+
+ argument :id, TokenID,
+ required: true,
+ description: 'Global ID of the agent token that will be revoked.'
+
+ def resolve(id:)
+ token = authorized_find!(id: id)
+ token.update(status: token.class.statuses[:revoked])
+
+ { 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/issues/set_crm_contacts.rb b/app/graphql/mutations/issues/set_crm_contacts.rb
index 4e49a45d52a..62990fc67f1 100644
--- a/app/graphql/mutations/issues/set_crm_contacts.rb
+++ b/app/graphql/mutations/issues/set_crm_contacts.rb
@@ -18,7 +18,8 @@ module Mutations
def resolve(project_path:, iid:, contact_ids:, operation_mode: Types::MutationOperationModeEnum.enum[:replace])
issue = authorized_find!(project_path: project_path, iid: iid)
project = issue.project
- raise Gitlab::Graphql::Errors::ResourceNotAvailable, 'Feature disabled' unless Feature.enabled?(:customer_relations, project.group, default_enabled: :yaml)
+
+ raise Gitlab::Graphql::Errors::ResourceNotAvailable, 'Feature disabled' unless feature_enabled?(project)
contact_ids = contact_ids.compact.map do |contact_id|
raise Gitlab::Graphql::Errors::ArgumentError, "Contact #{contact_id} is invalid." unless contact_id.respond_to?(:model_id)
@@ -43,6 +44,12 @@ module Mutations
errors: response.errors
}
end
+
+ private
+
+ def feature_enabled?(project)
+ Feature.enabled?(:customer_relations, project.group, default_enabled: :yaml) && project.group&.crm_enabled?
+ end
end
end
end
diff --git a/app/graphql/mutations/issues/set_escalation_status.rb b/app/graphql/mutations/issues/set_escalation_status.rb
new file mode 100644
index 00000000000..6073b73277b
--- /dev/null
+++ b/app/graphql/mutations/issues/set_escalation_status.rb
@@ -0,0 +1,46 @@
+# frozen_string_literal: true
+
+module Mutations
+ module Issues
+ class SetEscalationStatus < Base
+ graphql_name 'IssueSetEscalationStatus'
+
+ argument :status, Types::IncidentManagement::EscalationStatusEnum,
+ required: true,
+ description: 'Set the escalation status.'
+
+ def resolve(project_path:, iid:, status:)
+ issue = authorized_find!(project_path: project_path, iid: iid)
+ project = issue.project
+
+ authorize_escalation_status!(project)
+ check_feature_availability!(project, issue)
+
+ ::Issues::UpdateService.new(
+ project: project,
+ current_user: current_user,
+ params: { escalation_status: { status: status } }
+ ).execute(issue)
+
+ {
+ issue: issue,
+ errors: errors_on_object(issue)
+ }
+ end
+
+ private
+
+ def authorize_escalation_status!(project)
+ return if Ability.allowed?(current_user, :update_escalation_status, project)
+
+ raise_resource_not_available_error!
+ end
+
+ def check_feature_availability!(project, issue)
+ return if Feature.enabled?(:incident_escalations, project) && issue.supports_escalation?
+
+ raise Gitlab::Graphql::Errors::ResourceNotAvailable, 'Feature unavailable for provided issue'
+ end
+ end
+ end
+end
diff --git a/app/graphql/mutations/work_items/create.rb b/app/graphql/mutations/work_items/create.rb
new file mode 100644
index 00000000000..88b8cefd8d2
--- /dev/null
+++ b/app/graphql/mutations/work_items/create.rb
@@ -0,0 +1,57 @@
+# frozen_string_literal: true
+
+module Mutations
+ module WorkItems
+ class Create < BaseMutation
+ include Mutations::SpamProtection
+ include FindsProject
+
+ graphql_name 'WorkItemCreate'
+
+ authorize :create_work_item
+
+ argument :description, GraphQL::Types::String,
+ required: false,
+ description: copy_field_description(Types::WorkItemType, :description)
+ argument :project_path, GraphQL::Types::ID,
+ required: true,
+ description: 'Full path of the project the work item is associated with.'
+ argument :title, GraphQL::Types::String,
+ required: true,
+ description: copy_field_description(Types::WorkItemType, :title)
+ argument :work_item_type_id, ::Types::GlobalIDType[::WorkItems::Type],
+ required: true,
+ description: 'Global ID of a work item type.'
+
+ field :work_item, Types::WorkItemType,
+ null: true,
+ description: 'Created work item.'
+
+ def resolve(project_path:, **attributes)
+ project = authorized_find!(project_path)
+ params = global_id_compatibility_params(attributes).merge(author_id: current_user.id)
+
+ spam_params = ::Spam::SpamParams.new_from_request(request: context[:request])
+ work_item = ::WorkItems::CreateService.new(project: project, current_user: current_user, params: params, spam_params: spam_params).execute
+
+ check_spam_action_response!(work_item)
+
+ {
+ work_item: work_item.valid? ? work_item : nil,
+ errors: errors_on_object(work_item)
+ }
+ end
+
+ 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
+ end
+ end
+ end
+end
diff --git a/app/graphql/queries/pipelines/get_pipeline_details.query.graphql b/app/graphql/queries/pipelines/get_pipeline_details.query.graphql
index dd5c9e07488..5dece2f81cc 100644
--- a/app/graphql/queries/pipelines/get_pipeline_details.query.graphql
+++ b/app/graphql/queries/pipelines/get_pipeline_details.query.graphql
@@ -1,3 +1,18 @@
+fragment CiNeeds on JobNeedUnion {
+ ...CiBuildNeedFields
+ ...CiJobNeedFields
+}
+
+fragment CiBuildNeedFields on CiBuildNeed {
+ id
+ name
+}
+
+fragment CiJobNeedFields on CiJob {
+ id
+ name
+}
+
fragment LinkedPipelineData on Pipeline {
__typename
id
@@ -91,6 +106,12 @@ query getPipelineDetails($projectPath: ID!, $iid: ID!) {
name
}
}
+ previousStageJobsOrNeeds {
+ __typename
+ nodes {
+ ...CiNeeds
+ }
+ }
status: detailedStatus {
__typename
id
diff --git a/app/graphql/resolvers/base_issues_resolver.rb b/app/graphql/resolvers/base_issues_resolver.rb
index 3983a3697cb..3e7509b4068 100644
--- a/app/graphql/resolvers/base_issues_resolver.rb
+++ b/app/graphql/resolvers/base_issues_resolver.rb
@@ -48,7 +48,8 @@ module Resolvers
labels: [:labels],
assignees: [:assignees],
timelogs: [:timelogs],
- customer_relations_contacts: { customer_relations_contacts: [:group] }
+ customer_relations_contacts: { customer_relations_contacts: [:group] },
+ escalation_status: [:incident_management_issuable_escalation_status]
}
end
diff --git a/app/graphql/resolvers/ci/config_resolver.rb b/app/graphql/resolvers/ci/config_resolver.rb
index 2d74392a84c..387185b5171 100644
--- a/app/graphql/resolvers/ci/config_resolver.rb
+++ b/app/graphql/resolvers/ci/config_resolver.rb
@@ -47,11 +47,13 @@ module Resolvers
{
status: :valid,
errors: [],
+ warnings: result.warnings,
stages: make_stages(result.jobs)
}
else
{
status: :invalid,
+ warnings: result.warnings,
errors: result.errors
}
end
diff --git a/app/graphql/resolvers/clusters/agent_tokens_resolver.rb b/app/graphql/resolvers/clusters/agent_tokens_resolver.rb
index 5ae19700fd5..8208fa56485 100644
--- a/app/graphql/resolvers/clusters/agent_tokens_resolver.rb
+++ b/app/graphql/resolvers/clusters/agent_tokens_resolver.rb
@@ -9,10 +9,17 @@ module Resolvers
delegate :project, to: :agent
+ argument :status, Types::Clusters::AgentTokenStatusEnum,
+ required: false,
+ description: 'Status of the token.'
+
def resolve(**args)
return ::Clusters::AgentToken.none unless can_read_agent_tokens?
- agent.last_used_agent_tokens
+ tokens = agent.last_used_agent_tokens
+ tokens = tokens.with_status(args[:status]) if args[:status].present?
+
+ tokens
end
private
diff --git a/app/graphql/resolvers/concerns/resolves_pipelines.rb b/app/graphql/resolvers/concerns/resolves_pipelines.rb
index 1c01e5e0250..42c4c22a938 100644
--- a/app/graphql/resolvers/concerns/resolves_pipelines.rb
+++ b/app/graphql/resolvers/concerns/resolves_pipelines.rb
@@ -24,7 +24,7 @@ module ResolvesPipelines
argument :source,
GraphQL::Types::String,
required: false,
- description: "Filter pipelines by their source. Will be ignored if `dast_view_scans` feature flag is disabled."
+ description: "Filter pipelines by their source."
end
class_methods do
@@ -38,8 +38,6 @@ module ResolvesPipelines
end
def resolve_pipelines(project, params = {})
- params.delete(:source) unless Feature.enabled?(:dast_view_scans, project, default_enabled: :yaml)
-
Ci::PipelinesFinder.new(project, context[:current_user], params).execute
end
end
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 254f1efa0a5..97cc7554ba8 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
@@ -13,13 +13,13 @@ module Resolvers
DesignID = ::Types::GlobalIDType[::DesignManagement::Design]
- argument :ids, [DesignID],
- required: false,
- description: 'Filters designs by their ID.'
argument :filenames,
[GraphQL::Types::String],
required: false,
description: 'Filters designs by their filename.'
+ argument :ids, [DesignID],
+ required: false,
+ description: 'Filters designs by their ID.'
def self.single
::Resolvers::DesignManagement::Version::DesignAtVersionResolver
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 80db15755d3..2682ce6b3b1 100644
--- a/app/graphql/resolvers/design_management/version_in_collection_resolver.rb
+++ b/app/graphql/resolvers/design_management/version_in_collection_resolver.rb
@@ -15,13 +15,13 @@ module Resolvers
VersionID = ::Types::GlobalIDType[::DesignManagement::Version]
- argument :sha, GraphQL::Types::String,
- required: false,
- description: "SHA256 of a specific version."
argument :id, VersionID,
as: :version_id,
required: false,
description: 'Global ID of the version.'
+ argument :sha, GraphQL::Types::String,
+ required: false,
+ description: "SHA256 of a specific version."
def resolve(version_id: nil, sha: nil)
# TODO: remove this line when the compatibility layer is removed
diff --git a/app/graphql/resolvers/group_milestones_resolver.rb b/app/graphql/resolvers/group_milestones_resolver.rb
index 44192b6f4bf..319ff9f68c4 100644
--- a/app/graphql/resolvers/group_milestones_resolver.rb
+++ b/app/graphql/resolvers/group_milestones_resolver.rb
@@ -2,12 +2,12 @@
module Resolvers
class GroupMilestonesResolver < MilestonesResolver
- argument :include_descendants, GraphQL::Types::Boolean,
- required: false,
- description: 'Include milestones from all subgroups and subprojects.'
argument :include_ancestors, GraphQL::Types::Boolean,
required: false,
description: 'Include milestones from all parent groups.'
+ argument :include_descendants, GraphQL::Types::Boolean,
+ required: false,
+ description: 'Include milestones from all subgroups and subprojects.'
type Types::MilestoneType.connection_type, null: true
diff --git a/app/graphql/resolvers/merge_requests_resolver.rb b/app/graphql/resolvers/merge_requests_resolver.rb
index bd7f1f0774e..6dbcbe0e04d 100644
--- a/app/graphql/resolvers/merge_requests_resolver.rb
+++ b/app/graphql/resolvers/merge_requests_resolver.rb
@@ -51,6 +51,10 @@ module Resolvers
required: false,
description: 'Merge request state. If provided, all resolved merge requests will have this state.'
+ argument :draft, GraphQL::Types::Boolean,
+ required: false,
+ description: 'Limit result to draft merge requests.'
+
argument :labels, [GraphQL::Types::String],
required: false,
as: :label_name,
diff --git a/app/graphql/resolvers/users/groups_resolver.rb b/app/graphql/resolvers/users/groups_resolver.rb
index eafb56d8f4c..d8492a8fcf9 100644
--- a/app/graphql/resolvers/users/groups_resolver.rb
+++ b/app/graphql/resolvers/users/groups_resolver.rb
@@ -23,10 +23,6 @@ module Resolvers
Preloaders::GroupPolicyPreloader.new(nodes, current_user).execute
end
- def ready?(**args)
- Feature.enabled?(:paginatable_namespace_drop_down_for_project_creation, current_user, default_enabled: :yaml)
- end
-
private
def resolve_groups(**args)
diff --git a/app/graphql/resolvers/work_items/types_resolver.rb b/app/graphql/resolvers/work_items/types_resolver.rb
new file mode 100644
index 00000000000..b7a32e13423
--- /dev/null
+++ b/app/graphql/resolvers/work_items/types_resolver.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+module Resolvers
+ module WorkItems
+ class TypesResolver < BaseResolver
+ type Types::WorkItems::TypeType.connection_type, null: true
+
+ def resolve
+ # This will require a finder in the future when groups/projects get their work item types
+ # All groups/projects use the default types for now
+ ::WorkItems::Type.default.order_by_name_asc
+ end
+ end
+ end
+end
diff --git a/app/graphql/types/ci/config/config_type.rb b/app/graphql/types/ci/config/config_type.rb
index 6ac21968bd4..de355c8eacf 100644
--- a/app/graphql/types/ci/config/config_type.rb
+++ b/app/graphql/types/ci/config/config_type.rb
@@ -15,6 +15,8 @@ module Types
description: 'Stages of the pipeline.'
field :status, Types::Ci::Config::StatusEnum, null: true,
description: 'Status of linting, can be either valid or invalid.'
+ field :warnings, [GraphQL::Types::String], null: true,
+ description: 'Linting warnings.'
end
end
end
diff --git a/app/graphql/types/ci/job_type.rb b/app/graphql/types/ci/job_type.rb
index 928ca2f597d..1320b96907e 100644
--- a/app/graphql/types/ci/job_type.rb
+++ b/app/graphql/types/ci/job_type.rb
@@ -50,6 +50,8 @@ module Types
null: true,
description: 'How long the job was enqueued before starting.'
+ field :downstream_pipeline, Types::Ci::PipelineType, null: true,
+ description: 'Downstream pipeline for a bridge.'
field :previous_stage_jobs_or_needs, Types::Ci::JobNeedUnion.connection_type, null: true,
description: 'Jobs that must complete before the job runs. Returns `BuildNeed`, which is the needed jobs if the job uses the `needs` keyword, or the previous stage jobs otherwise.'
field :detailed_status, Types::Ci::DetailedStatusType, null: true,
@@ -89,6 +91,10 @@ module Types
Gitlab::Graphql::Loaders::BatchModelLoader.new(::Ci::Pipeline, object.pipeline_id).find
end
+ def downstream_pipeline
+ object.downstream_pipeline if object.respond_to?(:downstream_pipeline)
+ end
+
def tags
object.tags.map(&:name) if object.is_a?(::Ci::Build)
end
diff --git a/app/graphql/types/ci/pipeline_message_type.rb b/app/graphql/types/ci/pipeline_message_type.rb
new file mode 100644
index 00000000000..7edea1901a1
--- /dev/null
+++ b/app/graphql/types/ci/pipeline_message_type.rb
@@ -0,0 +1,16 @@
+# frozen_string_literal: true
+
+module Types
+ module Ci
+ # rubocop: disable Graphql/AuthorizeTypes
+ class PipelineMessageType < BaseObject
+ graphql_name 'PipelineMessage'
+
+ field :id, GraphQL::Types::ID, null: false,
+ description: 'ID of the pipeline message.'
+
+ field :content, GraphQL::Types::String, null: false,
+ description: 'Content of the pipeline message.'
+ end
+ end
+end
diff --git a/app/graphql/types/ci/pipeline_type.rb b/app/graphql/types/ci/pipeline_type.rb
index c8ac31bce4d..537b8e42ad1 100644
--- a/app/graphql/types/ci/pipeline_type.rb
+++ b/app/graphql/types/ci/pipeline_type.rb
@@ -18,8 +18,14 @@ module Types
field :iid, GraphQL::Types::String, null: false,
description: 'Internal ID of the pipeline.'
- field :sha, GraphQL::Types::String, null: false,
- description: "SHA of the pipeline's commit."
+ field :sha, GraphQL::Types::String, null: true,
+ method: :sha,
+ description: "SHA of the pipeline's commit." do
+ argument :format,
+ type: Types::ShaFormatEnum,
+ required: false,
+ description: 'Format of the SHA.'
+ end
field :before_sha, GraphQL::Types::String, null: true,
description: 'Base SHA of the source branch.'
@@ -162,6 +168,13 @@ module Types
field :ref, GraphQL::Types::String, null: true,
description: 'Reference to the branch from which the pipeline was triggered.'
+ field :ref_path, GraphQL::Types::String, null: true,
+ description: 'Reference path to the branch from which the pipeline was triggered.',
+ method: :source_ref_path
+
+ field :warning_messages, [Types::Ci::PipelineMessageType], null: true,
+ description: 'Pipeline warning messages.'
+
def detailed_status
object.detailed_status(current_user)
end
@@ -189,6 +202,12 @@ module Types
end.take # rubocop: disable CodeReuse/ActiveRecord
end
+ def sha(format: Types::ShaFormatEnum.enum[:long])
+ return pipeline.short_sha if format == Types::ShaFormatEnum.enum[:short]
+
+ pipeline.sha
+ end
+
alias_method :pipeline, :object
end
end
diff --git a/app/graphql/types/ci/runner_type.rb b/app/graphql/types/ci/runner_type.rb
index d37cca0927f..4fe65734911 100644
--- a/app/graphql/types/ci/runner_type.rb
+++ b/app/graphql/types/ci/runner_type.rb
@@ -4,6 +4,7 @@ module Types
module Ci
class RunnerType < BaseObject
edge_type_class(RunnerWebUrlEdge)
+ connection_type_class(Types::CountableConnectionType)
graphql_name 'CiRunner'
authorize :read_runner
present_using ::Ci::RunnerPresenter
@@ -18,8 +19,10 @@ module Types
description: 'ID of the runner.'
field :description, GraphQL::Types::String, null: true,
description: 'Description of the runner.'
+ field :created_at, Types::TimeType, null: true,
+ description: 'Timestamp of creation of this runner.'
field :contacted_at, Types::TimeType, null: true,
- description: 'Last contact from the runner.',
+ description: 'Timestamp of last contact from this runner.',
method: :contacted_at
field :maximum_timeout, GraphQL::Types::Int, null: true,
description: 'Maximum timeout (in seconds) for jobs processed by the runner.'
@@ -54,6 +57,12 @@ module Types
description: "Number of jobs processed by the runner (limited to #{JOB_COUNT_LIMIT}, plus one to indicate that more items exist)."
field :admin_url, GraphQL::Types::String, null: true,
description: 'Admin URL of the runner. Only available for administrators.'
+ field :edit_admin_url, GraphQL::Types::String, null: true,
+ 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
def job_count
# We limit to 1 above the JOB_COUNT_LIMIT to indicate that more items exist after JOB_COUNT_LIMIT
@@ -64,6 +73,10 @@ module Types
Gitlab::Routing.url_helpers.admin_runner_url(runner) if can_admin_runners?
end
+ def edit_admin_url
+ Gitlab::Routing.url_helpers.edit_admin_runner_url(runner) if can_admin_runners?
+ end
+
# rubocop: disable CodeReuse/ActiveRecord
def project_count
BatchLoader::GraphQL.for(runner.id).batch(key: :runner_project_count) do |ids, loader, args|
diff --git a/app/graphql/types/clusters/agent_token_status_enum.rb b/app/graphql/types/clusters/agent_token_status_enum.rb
new file mode 100644
index 00000000000..c00a64d21c1
--- /dev/null
+++ b/app/graphql/types/clusters/agent_token_status_enum.rb
@@ -0,0 +1,14 @@
+# frozen_string_literal: true
+
+module Types
+ module Clusters
+ class AgentTokenStatusEnum < BaseEnum
+ graphql_name 'AgentTokenStatus'
+ description 'Agent token statuses'
+
+ ::Clusters::AgentToken.statuses.keys.each do |status|
+ value status.upcase, value: status, description: "#{status.titleize} agent token."
+ end
+ end
+ end
+end
diff --git a/app/graphql/types/clusters/agent_token_type.rb b/app/graphql/types/clusters/agent_token_type.rb
index 94c5fc46a5d..96fdb5f05c8 100644
--- a/app/graphql/types/clusters/agent_token_type.rb
+++ b/app/graphql/types/clusters/agent_token_type.rb
@@ -44,6 +44,11 @@ module Types
null: true,
description: 'Name given to the token.'
+ field :status,
+ Types::Clusters::AgentTokenStatusEnum,
+ null: true,
+ description: 'Current status of the token.'
+
def cluster_agent
Gitlab::Graphql::Loaders::BatchModelLoader.new(::Clusters::Agent, object.agent_id).find
end
diff --git a/app/graphql/types/commit_type.rb b/app/graphql/types/commit_type.rb
index 7d141bd6daa..2584e15ff0b 100644
--- a/app/graphql/types/commit_type.rb
+++ b/app/graphql/types/commit_type.rb
@@ -39,6 +39,8 @@ module Types
description: 'Rendered HTML of the commit signature.'
field :author_name, type: GraphQL::Types::String, null: true,
description: 'Commit authors name.'
+ field :author_email, type: GraphQL::Types::String, null: true,
+ description: "Commit author's email."
field :author_gravatar, type: GraphQL::Types::String, null: true,
description: 'Commit authors gravatar.'
diff --git a/app/graphql/types/deprecated_mutations.rb b/app/graphql/types/deprecated_mutations.rb
index 49bad56b6f9..70d5fc31cd1 100644
--- a/app/graphql/types/deprecated_mutations.rb
+++ b/app/graphql/types/deprecated_mutations.rb
@@ -5,7 +5,8 @@ module Types
extend ActiveSupport::Concern
prepended do
- # placeholder for any FOSS mutations to be deprecated
+ mount_mutation Mutations::Clusters::AgentTokens::Delete,
+ deprecated: { reason: 'Tokens must be revoked with ClusterAgentTokenRevoke', milestone: '14.7' }
end
end
end
diff --git a/app/graphql/types/group_type.rb b/app/graphql/types/group_type.rb
index 4a20d84f2ab..e02650fd285 100644
--- a/app/graphql/types/group_type.rb
+++ b/app/graphql/types/group_type.rb
@@ -210,6 +210,11 @@ module Types
null: true,
description: "Find contacts of this group."
+ field :work_item_types, Types::WorkItems::TypeType.connection_type,
+ resolver: Resolvers::WorkItems::TypesResolver,
+ description: 'Work item types available to the group.',
+ feature_flag: :work_items
+
def avatar_url
object.avatar_url(only_path: false)
end
diff --git a/app/graphql/types/incident_management/escalation_status_enum.rb b/app/graphql/types/incident_management/escalation_status_enum.rb
new file mode 100644
index 00000000000..bc462f03148
--- /dev/null
+++ b/app/graphql/types/incident_management/escalation_status_enum.rb
@@ -0,0 +1,14 @@
+# frozen_string_literal: true
+
+module Types
+ module IncidentManagement
+ class EscalationStatusEnum < BaseEnum
+ graphql_name 'IssueEscalationStatus'
+ description 'Issue escalation status values'
+
+ ::IncidentManagement::IssuableEscalationStatus.status_names.each do |status|
+ value status.to_s.upcase, value: status, description: "#{::IncidentManagement::IssuableEscalationStatus::STATUS_DESCRIPTIONS[status]}."
+ end
+ end
+ end
+end
diff --git a/app/graphql/types/issue_type.rb b/app/graphql/types/issue_type.rb
index 498569f11ca..46fe91feae4 100644
--- a/app/graphql/types/issue_type.rb
+++ b/app/graphql/types/issue_type.rb
@@ -140,6 +140,9 @@ module Types
field :customer_relations_contacts, Types::CustomerRelations::ContactType.connection_type, null: true,
description: 'Customer relations contacts of the issue.'
+ field :escalation_status, Types::IncidentManagement::EscalationStatusEnum, null: true,
+ description: 'Escalation status of the issue.'
+
def author
Gitlab::Graphql::Loaders::BatchModelLoader.new(User, object.author_id).find
end
@@ -167,6 +170,12 @@ module Types
def hidden?
object.hidden? if Feature.enabled?(:ban_user_feature_flag)
end
+
+ def escalation_status
+ return unless Feature.enabled?(:incident_escalations, object.project) && object.supports_escalation?
+
+ object.escalation_status&.status_name
+ end
end
end
diff --git a/app/graphql/types/issue_type_enum.rb b/app/graphql/types/issue_type_enum.rb
index 0cfba6bbbd0..b18c8b90e96 100644
--- a/app/graphql/types/issue_type_enum.rb
+++ b/app/graphql/types/issue_type_enum.rb
@@ -5,7 +5,7 @@ module Types
graphql_name 'IssueType'
description 'Issue type'
- ::WorkItem::Type.allowed_types_for_issues.each do |issue_type|
+ ::WorkItems::Type.allowed_types_for_issues.each do |issue_type|
value issue_type.upcase, value: issue_type, description: "#{issue_type.titleize} issue type"
end
end
diff --git a/app/graphql/types/merge_request_type.rb b/app/graphql/types/merge_request_type.rb
index 0672ec6f0f8..ea05671c79c 100644
--- a/app/graphql/types/merge_request_type.rb
+++ b/app/graphql/types/merge_request_type.rb
@@ -189,6 +189,8 @@ module Types
description: 'Indicates if the merge request has CI.'
field :mergeable, GraphQL::Types::Boolean, null: false, method: :mergeable?, calls_gitaly: true,
description: 'Indicates if the merge request is mergeable.'
+ field :commits, Types::CommitType.connection_type, null: true,
+ calls_gitaly: true, description: 'Merge request commits.'
field :commits_without_merge_commits, Types::CommitType.connection_type, null: true,
calls_gitaly: true, description: 'Merge request commits excluding merge commits.'
field :security_auto_fix, GraphQL::Types::Boolean, null: true,
@@ -196,7 +198,7 @@ module Types
field :auto_merge_strategy, GraphQL::Types::String, null: true,
description: 'Selected auto merge strategy.'
field :merge_user, Types::UserType, null: true,
- description: 'User who merged this merge request.'
+ description: 'User who merged this merge request or set it to merge when pipeline succeeds.'
field :timelogs, Types::TimelogType.connection_type, null: false,
description: 'Timelogs on the merge request.'
@@ -249,16 +251,28 @@ module Types
!!object.discussion_locked
end
+ def default_merge_commit_message
+ 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
+
def available_auto_merge_strategies
AutoMergeService.new(object.project, current_user).available_strategies(object)
end
+ def commits
+ object.commits.commits
+ end
+
def commits_without_merge_commits
- object.recent_commits.without_merge_commits
+ object.commits.without_merge_commits
end
def security_auto_fix
@@ -268,6 +282,10 @@ module Types
def reviewers
object.reviewers
end
+
+ def merge_user
+ object.metrics&.merged_by || object.merge_user
+ end
end
end
diff --git a/app/graphql/types/mutation_type.rb b/app/graphql/types/mutation_type.rb
index e8a952e9c61..c350f4dd922 100644
--- a/app/graphql/types/mutation_type.rb
+++ b/app/graphql/types/mutation_type.rb
@@ -35,7 +35,7 @@ module Types
mount_mutation Mutations::Clusters::Agents::Create
mount_mutation Mutations::Clusters::Agents::Delete
mount_mutation Mutations::Clusters::AgentTokens::Create
- mount_mutation Mutations::Clusters::AgentTokens::Delete
+ mount_mutation Mutations::Clusters::AgentTokens::Revoke
mount_mutation Mutations::Commits::Create, calls_gitaly: true
mount_mutation Mutations::CustomEmoji::Create, feature_flag: :custom_emoji
mount_mutation Mutations::CustomEmoji::Destroy, feature_flag: :custom_emoji
@@ -55,6 +55,7 @@ module Types
mount_mutation Mutations::Issues::SetDueDate
mount_mutation Mutations::Issues::SetSeverity
mount_mutation Mutations::Issues::SetSubscription
+ mount_mutation Mutations::Issues::SetEscalationStatus
mount_mutation Mutations::Issues::Update
mount_mutation Mutations::Issues::Move
mount_mutation Mutations::Labels::Create
@@ -123,6 +124,7 @@ module Types
mount_mutation Mutations::Packages::Destroy
mount_mutation Mutations::Packages::DestroyFile
mount_mutation Mutations::Echo
+ mount_mutation Mutations::WorkItems::Create, feature_flag: :work_items
end
end
diff --git a/app/graphql/types/packages/package_details_type.rb b/app/graphql/types/packages/package_details_type.rb
index 5ac80860fe2..1d2cf9649d8 100644
--- a/app/graphql/types/packages/package_details_type.rb
+++ b/app/graphql/types/packages/package_details_type.rb
@@ -3,6 +3,8 @@
module Types
module Packages
class PackageDetailsType < PackageType
+ include ::PackagesHelper
+
graphql_name 'PackageDetailsType'
description 'Represents a package details in the Package Registry. Note that this type is in beta and susceptible to changes'
authorize :read_package
@@ -21,9 +23,58 @@ module Types
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.'
+ field :maven_url, GraphQL::Types::String, null: true, description: 'Url of the Maven project endpoint.'
+ field :npm_url, GraphQL::Types::String, null: true, description: 'Url of the NPM project endpoint.'
+ field :nuget_url, GraphQL::Types::String, null: true, description: 'Url of the Nuget project endpoint.'
+ field :pypi_setup_url, GraphQL::Types::String, null: true, description: 'Url of the PyPi project setup endpoint.'
+ field :pypi_url, GraphQL::Types::String, null: true, description: 'Url of the PyPi project endpoint.'
+
def versions
object.versions
end
+
+ def package_files
+ if Feature.enabled?(:packages_installable_package_files, default_enabled: :yaml)
+ object.installable_package_files
+ else
+ object.package_files
+ end
+ end
+
+ def composer_config_repository_url
+ composer_config_repository_name(object.project.group&.id)
+ end
+
+ def composer_url
+ composer_registry_url(object.project.group&.id)
+ end
+
+ def conan_url
+ package_registry_project_url(object.project.id, :conan)
+ end
+
+ def maven_url
+ package_registry_project_url(object.project.id, :maven)
+ end
+
+ def npm_url
+ package_registry_project_url(object.project.id, :npm)
+ end
+
+ def nuget_url
+ nuget_package_registry_url(object.project.id)
+ end
+
+ def pypi_setup_url
+ package_registry_project_url(object.project.id, :pypi)
+ end
+
+ def pypi_url
+ pypi_registry_url(object.project.id)
+ end
end
end
end
diff --git a/app/graphql/types/project_type.rb b/app/graphql/types/project_type.rb
index 3d2ee47a499..f4067552f55 100644
--- a/app/graphql/types/project_type.rb
+++ b/app/graphql/types/project_type.rb
@@ -27,7 +27,6 @@ module Types
field :description, GraphQL::Types::String, null: true,
description: 'Short description of the project.'
- markdown_field :description_html, null: true
field :tag_list, GraphQL::Types::String, null: true,
deprecated: { reason: 'Use `topics`', milestone: '13.12' },
@@ -75,21 +74,6 @@ module Types
field :avatar_url, GraphQL::Types::String, null: true, calls_gitaly: true,
description: 'URL to avatar image file of the project.'
- {
- issues: "Issues are",
- merge_requests: "Merge Requests are",
- wiki: 'Wikis are',
- snippets: 'Snippets are',
- container_registry: 'Container Registry is'
- }.each do |feature, name_string|
- field "#{feature}_enabled", GraphQL::Types::Boolean, null: true,
- description: "Indicates if #{name_string} enabled for the current user"
-
- define_method "#{feature}_enabled" do
- object.feature_available?(feature, context[:current_user])
- end
- end
-
field :jobs_enabled, GraphQL::Types::Boolean, null: true,
description: 'Indicates if CI/CD pipeline jobs are enabled for the current user.'
@@ -391,6 +375,17 @@ module Types
null: true,
description: 'Template used to create squash commit message in merge requests.'
+ field :labels,
+ Types::LabelType.connection_type,
+ null: true,
+ description: 'Labels available on this project.',
+ resolver: Resolvers::LabelsResolver
+
+ field :work_item_types, Types::WorkItems::TypeType.connection_type,
+ resolver: Resolvers::WorkItems::TypesResolver,
+ description: 'Work item types available to the project.',
+ feature_flag: :work_items
+
def label(title:)
BatchLoader::GraphQL.for(title).batch(key: project) do |titles, loader, args|
LabelsFinder
@@ -400,11 +395,22 @@ module Types
end
end
- field :labels,
- Types::LabelType.connection_type,
- null: true,
- description: 'Labels available on this project.',
- resolver: Resolvers::LabelsResolver
+ {
+ issues: "Issues are",
+ merge_requests: "Merge Requests are",
+ wiki: 'Wikis are',
+ snippets: 'Snippets are',
+ container_registry: 'Container Registry is'
+ }.each do |feature, name_string|
+ field "#{feature}_enabled", GraphQL::Types::Boolean, null: true,
+ description: "Indicates if #{name_string} enabled for the current user"
+
+ define_method "#{feature}_enabled" do
+ object.feature_available?(feature, context[:current_user])
+ end
+ end
+
+ markdown_field :description_html, null: true
def avatar_url
object.avatar_url(only_path: false)
diff --git a/app/graphql/types/projects/topic_type.rb b/app/graphql/types/projects/topic_type.rb
index 79ab69e794b..c579f2f2b9d 100644
--- a/app/graphql/types/projects/topic_type.rb
+++ b/app/graphql/types/projects/topic_type.rb
@@ -14,11 +14,12 @@ module Types
field :description, GraphQL::Types::String, null: true,
description: 'Description of the topic.'
- markdown_field :description_html, null: true
field :avatar_url, GraphQL::Types::String, null: true,
description: 'URL to avatar image file of the topic.'
+ markdown_field :description_html, null: true
+
def avatar_url
object.avatar_url(only_path: false)
end
diff --git a/app/graphql/types/release_type.rb b/app/graphql/types/release_type.rb
index fcc9ec49252..fbc3779ea9b 100644
--- a/app/graphql/types/release_type.rb
+++ b/app/graphql/types/release_type.rb
@@ -20,7 +20,6 @@ module Types
authorize: :download_code
field :description, GraphQL::Types::String, null: true,
description: 'Description (also known as "release notes") of the release.'
- markdown_field :description_html, null: true
field :name, GraphQL::Types::String, null: true,
description: 'Name of the release.'
field :created_at, Types::TimeType, null: true,
@@ -42,14 +41,16 @@ module Types
field :author, Types::UserType, null: true,
description: 'User that created the release.'
- def author
- Gitlab::Graphql::Loaders::BatchModelLoader.new(User, release.author_id).find
- end
-
field :commit, Types::CommitType, null: true,
complexity: 10, calls_gitaly: true,
description: 'Commit associated with the release.'
+ markdown_field :description_html, null: true
+
+ def author
+ Gitlab::Graphql::Loaders::BatchModelLoader.new(User, release.author_id).find
+ end
+
def commit
return if release.sha.nil?
diff --git a/app/graphql/types/repository/blob_type.rb b/app/graphql/types/repository/blob_type.rb
index 3265c14bdca..28339093172 100644
--- a/app/graphql/types/repository/blob_type.rb
+++ b/app/graphql/types/repository/blob_type.rb
@@ -56,6 +56,9 @@ module Types
field :stored_externally, GraphQL::Types::Boolean, null: true, method: :stored_externally?,
description: "Whether the blob's content is stored externally (for instance, in LFS)."
+ field :external_storage, GraphQL::Types::String, null: true, method: :external_storage,
+ description: "External storage being used, if enabled (for instance, 'LFS')."
+
field :edit_blob_path, GraphQL::Types::String, null: true,
description: 'Web path to edit the blob in the old-style editor.'
@@ -71,6 +74,19 @@ module Types
field :pipeline_editor_path, GraphQL::Types::String, null: true,
description: 'Web path to edit .gitlab-ci.yml file.'
+ field :find_file_path, GraphQL::Types::String, null: true,
+ description: 'Web path to find file.'
+
+ field :blame_path, GraphQL::Types::String, null: true,
+ description: 'Web path to blob blame page.'
+
+ field :history_path, GraphQL::Types::String, null: true,
+ description: 'Web path to blob history page.'
+
+ field :permalink_path, GraphQL::Types::String, null: true,
+ description: 'Web path to blob permalink.',
+ calls_gitaly: true
+
field :code_owners, [Types::UserType], null: true,
description: 'List of code owners for the blob.',
calls_gitaly: true
@@ -98,6 +114,9 @@ module Types
field :can_current_user_push_to_branch, GraphQL::Types::Boolean, null: true, method: :can_current_user_push_to_branch?,
description: 'Whether the current user can push to the branch.'
+ field :archived, GraphQL::Types::Boolean, null: true, method: :archived?,
+ description: 'Whether the current project is archived.'
+
def raw_text_blob
object.data unless object.binary?
end
diff --git a/app/graphql/types/sha_format_enum.rb b/app/graphql/types/sha_format_enum.rb
new file mode 100644
index 00000000000..2e0e5bb85f3
--- /dev/null
+++ b/app/graphql/types/sha_format_enum.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+module Types
+ class ShaFormatEnum < BaseEnum
+ graphql_name 'ShaFormat'
+ description 'How to format SHA strings.'
+
+ FORMATS_DESCRIPTION = {
+ short: 'Abbreviated format. Short SHAs are typically eight characters long.',
+ long: 'Unabbreviated format.'
+ }.freeze
+
+ FORMATS_DESCRIPTION.each do |format, description|
+ value format.to_s.upcase,
+ description: description,
+ value: format.to_s
+ end
+ end
+end
diff --git a/app/graphql/types/user_interface.rb b/app/graphql/types/user_interface.rb
index 7cc201b6df4..6bb4cb29cdd 100644
--- a/app/graphql/types/user_interface.rb
+++ b/app/graphql/types/user_interface.rb
@@ -64,8 +64,7 @@ module Types
description: 'Group memberships of the user.'
field :groups,
resolver: Resolvers::Users::GroupsResolver,
- description: 'Groups where the user has access. Will always return `null` if ' \
- '`paginatable_namespace_drop_down_for_project_creation` feature flag is disabled.'
+ description: 'Groups where the user has access.'
field :group_count,
resolver: Resolvers::Users::GroupCountResolver,
description: 'Group count for the user.'
diff --git a/app/graphql/types/work_item_type.rb b/app/graphql/types/work_item_type.rb
new file mode 100644
index 00000000000..486c1e52987
--- /dev/null
+++ b/app/graphql/types/work_item_type.rb
@@ -0,0 +1,23 @@
+# frozen_string_literal: true
+
+module Types
+ class WorkItemType < BaseObject
+ graphql_name 'WorkItem'
+
+ authorize :read_issue
+
+ field :description, GraphQL::Types::String, null: true,
+ description: 'Description of the work item.'
+ field :id, Types::GlobalIDType[::WorkItem], null: false,
+ description: 'Global ID of the work item.'
+ field :iid, GraphQL::Types::ID, null: false,
+ description: 'Internal ID of the work item.'
+ field :title, GraphQL::Types::String, null: false,
+ description: 'Title of the work item.'
+ field :work_item_type, Types::WorkItems::TypeType, null: false,
+ description: 'Type assigned to the work item.'
+
+ markdown_field :title_html, null: true
+ markdown_field :description_html, null: true
+ end
+end
diff --git a/app/graphql/types/work_items/type_type.rb b/app/graphql/types/work_items/type_type.rb
new file mode 100644
index 00000000000..f31bd7ee9ba
--- /dev/null
+++ b/app/graphql/types/work_items/type_type.rb
@@ -0,0 +1,18 @@
+# frozen_string_literal: true
+
+module Types
+ module WorkItems
+ class TypeType < BaseObject
+ graphql_name 'WorkItemType'
+
+ authorize :read_work_item_type
+
+ field :icon_name, GraphQL::Types::String, null: true,
+ description: 'Icon name of the work item type.'
+ field :id, Types::GlobalIDType[::WorkItems::Type], null: false,
+ description: 'Global ID of the work item type.'
+ field :name, GraphQL::Types::String, null: false,
+ description: 'Name of the work item type.'
+ end
+ end
+end