Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'app/graphql/types')
-rw-r--r--app/graphql/types/base_field.rb31
-rw-r--r--app/graphql/types/branch_protections/base_access_level_type.rb22
-rw-r--r--app/graphql/types/branch_protections/merge_access_level_type.rb11
-rw-r--r--app/graphql/types/branch_protections/push_access_level_type.rb11
-rw-r--r--app/graphql/types/branch_rules/branch_protection_type.rb29
-rw-r--r--app/graphql/types/ci/config_variable_type.rb22
-rw-r--r--app/graphql/types/ci/group_variable_connection_type.rb17
-rw-r--r--app/graphql/types/ci/group_variable_type.rb17
-rw-r--r--app/graphql/types/ci/instance_variable_type.rb28
-rw-r--r--app/graphql/types/ci/job_artifact_type.rb9
-rw-r--r--app/graphql/types/ci/job_type.rb6
-rw-r--r--app/graphql/types/ci/manual_variable_type.rb12
-rw-r--r--app/graphql/types/ci/project_variable_connection_type.rb17
-rw-r--r--app/graphql/types/ci/project_variable_type.rb13
-rw-r--r--app/graphql/types/ci/runner_membership_filter_enum.rb8
-rw-r--r--app/graphql/types/ci/runner_type.rb22
-rw-r--r--app/graphql/types/ci/variable_interface.rb24
-rw-r--r--app/graphql/types/clusters/agent_type.rb2
-rw-r--r--app/graphql/types/customer_relations/contact_sort_enum.rb4
-rw-r--r--app/graphql/types/customer_relations/organization_sort_enum.rb21
-rw-r--r--app/graphql/types/customer_relations/organization_state_counts_type.rb24
-rw-r--r--app/graphql/types/customer_relations/organization_state_enum.rb8
-rw-r--r--app/graphql/types/deployment_details_type.rb15
-rw-r--r--app/graphql/types/deployment_status_enum.rb14
-rw-r--r--app/graphql/types/deployment_tag_type.rb20
-rw-r--r--app/graphql/types/deployment_type.rb69
-rw-r--r--app/graphql/types/deployments_order_by_input_type.rb24
-rw-r--r--app/graphql/types/environment_type.rb41
-rw-r--r--app/graphql/types/group_type.rb14
-rw-r--r--app/graphql/types/member_sort_enum.rb13
-rw-r--r--app/graphql/types/merge_request_type.rb9
-rw-r--r--app/graphql/types/merge_requests/detailed_merge_status_enum.rb3
-rw-r--r--app/graphql/types/mutation_type.rb6
-rw-r--r--app/graphql/types/packages/package_details_type.rb2
-rw-r--r--app/graphql/types/project_type.rb479
-rw-r--r--app/graphql/types/projects/branch_rule_type.rb33
-rw-r--r--app/graphql/types/query_type.rb2
-rw-r--r--app/graphql/types/sort_direction_enum.rb11
-rw-r--r--app/graphql/types/subscription_type.rb7
-rw-r--r--app/graphql/types/timelog_type.rb2
-rw-r--r--app/graphql/types/work_items/widgets/description_type.rb14
41 files changed, 837 insertions, 299 deletions
diff --git a/app/graphql/types/base_field.rb b/app/graphql/types/base_field.rb
index 1c43432594a..6f64e5b5053 100644
--- a/app/graphql/types/base_field.rb
+++ b/app/graphql/types/base_field.rb
@@ -17,8 +17,6 @@ module Types
@requires_argument = !!kwargs.delete(:requires_argument)
@authorize = Array.wrap(kwargs.delete(:authorize))
kwargs[:complexity] = field_complexity(kwargs[:resolver_class], kwargs[:complexity])
- @feature_flag = kwargs[:_deprecated_feature_flag]
- kwargs = check_feature_flag(kwargs)
@deprecation = gitlab_deprecation(kwargs)
after_connection_extensions = kwargs.delete(:late_extensions) || []
@@ -91,16 +89,8 @@ module Types
@constant_complexity
end
- def visible?(context)
- return false if feature_flag.present? && !Feature.enabled?(feature_flag)
-
- super
- end
-
private
- attr_reader :feature_flag
-
def field_authorized?(object, ctx)
object = object.node if object.is_a?(GraphQL::Pagination::Connection::Edge)
@@ -123,27 +113,6 @@ module Types
@authorization ||= ::Gitlab::Graphql::Authorize::ObjectAuthorization.new(@authorize)
end
- def feature_documentation_message(key, description)
- message_parts = ["#{description} Available only when feature flag `#{key}` is enabled."]
-
- message_parts << if Feature::Definition.has_definition?(key) && Feature::Definition.default_enabled?(key)
- "This flag is enabled by default."
- else
- "This flag is disabled by default, because the feature is experimental and is subject to change without notice."
- end
-
- message_parts.join(' ')
- end
-
- def check_feature_flag(args)
- ff = args.delete(:_deprecated_feature_flag)
- return args unless ff.present?
-
- args[:description] = feature_documentation_message(ff, args[:description])
-
- args
- end
-
def field_complexity(resolver_class, current)
return current if current.present? && current > 0
diff --git a/app/graphql/types/branch_protections/base_access_level_type.rb b/app/graphql/types/branch_protections/base_access_level_type.rb
new file mode 100644
index 00000000000..472733a6bc5
--- /dev/null
+++ b/app/graphql/types/branch_protections/base_access_level_type.rb
@@ -0,0 +1,22 @@
+# frozen_string_literal: true
+
+module Types
+ module BranchProtections
+ class BaseAccessLevelType < Types::BaseObject
+ authorize :read_protected_branch
+
+ field :access_level,
+ type: GraphQL::Types::Int,
+ null: false,
+ description: 'GitLab::Access level.'
+
+ field :access_level_description,
+ type: GraphQL::Types::String,
+ null: false,
+ description: 'Human readable representation for this access level.',
+ hash_key: 'humanize'
+ end
+ end
+end
+
+Types::BranchProtections::BaseAccessLevelType.prepend_mod
diff --git a/app/graphql/types/branch_protections/merge_access_level_type.rb b/app/graphql/types/branch_protections/merge_access_level_type.rb
new file mode 100644
index 00000000000..85295e1ba25
--- /dev/null
+++ b/app/graphql/types/branch_protections/merge_access_level_type.rb
@@ -0,0 +1,11 @@
+# frozen_string_literal: true
+
+module Types
+ module BranchProtections
+ class MergeAccessLevelType < BaseAccessLevelType # rubocop:disable Graphql/AuthorizeTypes
+ graphql_name 'MergeAccessLevel'
+ description 'Represents the merge access level of a branch protection.'
+ accepts ::ProtectedBranch::MergeAccessLevel
+ end
+ end
+end
diff --git a/app/graphql/types/branch_protections/push_access_level_type.rb b/app/graphql/types/branch_protections/push_access_level_type.rb
new file mode 100644
index 00000000000..bfbdc4edbea
--- /dev/null
+++ b/app/graphql/types/branch_protections/push_access_level_type.rb
@@ -0,0 +1,11 @@
+# frozen_string_literal: true
+
+module Types
+ module BranchProtections
+ class PushAccessLevelType < BaseAccessLevelType # rubocop:disable Graphql/AuthorizeTypes
+ graphql_name 'PushAccessLevel'
+ description 'Represents the push access level of a branch protection.'
+ accepts ::ProtectedBranch::PushAccessLevel
+ end
+ end
+end
diff --git a/app/graphql/types/branch_rules/branch_protection_type.rb b/app/graphql/types/branch_rules/branch_protection_type.rb
new file mode 100644
index 00000000000..4177a6f92a1
--- /dev/null
+++ b/app/graphql/types/branch_rules/branch_protection_type.rb
@@ -0,0 +1,29 @@
+# frozen_string_literal: true
+
+module Types
+ module BranchRules
+ class BranchProtectionType < BaseObject
+ graphql_name 'BranchProtection'
+ description 'Branch protection details for a branch rule.'
+ accepts ::ProtectedBranch
+ authorize :read_protected_branch
+
+ field :merge_access_levels,
+ type: Types::BranchProtections::MergeAccessLevelType.connection_type,
+ null: true,
+ description: 'Details about who can merge when this branch is the source branch.'
+
+ field :push_access_levels,
+ type: Types::BranchProtections::PushAccessLevelType.connection_type,
+ null: true,
+ description: 'Details about who can push when this branch is the source branch.'
+
+ field :allow_force_push,
+ type: GraphQL::Types::Boolean,
+ null: false,
+ description: 'Toggle force push to the branch for users with write access.'
+ end
+ end
+end
+
+Types::BranchRules::BranchProtectionType.prepend_mod_with('Types::BranchRules::BranchProtectionType')
diff --git a/app/graphql/types/ci/config_variable_type.rb b/app/graphql/types/ci/config_variable_type.rb
new file mode 100644
index 00000000000..87ae026c2c1
--- /dev/null
+++ b/app/graphql/types/ci/config_variable_type.rb
@@ -0,0 +1,22 @@
+# frozen_string_literal: true
+
+module Types
+ module Ci
+ class ConfigVariableType < BaseObject # rubocop:disable Graphql/AuthorizeTypes
+ graphql_name 'CiConfigVariable'
+ description 'CI/CD config variables.'
+
+ field :key, GraphQL::Types::String,
+ null: true,
+ description: 'Name of the variable.'
+
+ field :description, GraphQL::Types::String,
+ null: true,
+ description: 'Description for the CI/CD config variable.'
+
+ field :value, GraphQL::Types::String,
+ null: true,
+ description: 'Value of the variable.'
+ end
+ end
+end
diff --git a/app/graphql/types/ci/group_variable_connection_type.rb b/app/graphql/types/ci/group_variable_connection_type.rb
new file mode 100644
index 00000000000..1f55dde6697
--- /dev/null
+++ b/app/graphql/types/ci/group_variable_connection_type.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+module Types
+ module Ci
+ # rubocop: disable Graphql/AuthorizeTypes
+ class GroupVariableConnectionType < GraphQL::Types::Relay::BaseConnection
+ field :limit, GraphQL::Types::Int,
+ null: false,
+ description: 'Maximum amount of group CI/CD variables.'
+
+ def limit
+ ::Plan.default.actual_limits.group_ci_variables
+ end
+ end
+ # rubocop: enable Graphql/AuthorizeTypes
+ end
+end
diff --git a/app/graphql/types/ci/group_variable_type.rb b/app/graphql/types/ci/group_variable_type.rb
index 3322f741342..f9ed54f0d10 100644
--- a/app/graphql/types/ci/group_variable_type.rb
+++ b/app/graphql/types/ci/group_variable_type.rb
@@ -7,19 +7,20 @@ module Types
graphql_name 'CiGroupVariable'
description 'CI/CD variables for a group.'
+ connection_type_class(Types::Ci::GroupVariableConnectionType)
implements(VariableInterface)
field :environment_scope, GraphQL::Types::String,
- null: true,
- description: 'Scope defining the environments that can use the variable.'
-
- field :protected, GraphQL::Types::Boolean,
- null: true,
- description: 'Indicates whether the variable is protected.'
+ null: true,
+ description: 'Scope defining the environments that can use the variable.'
field :masked, GraphQL::Types::Boolean,
- null: true,
- description: 'Indicates whether the variable is masked.'
+ null: true,
+ description: 'Indicates whether the variable is masked.'
+
+ field :protected, GraphQL::Types::Boolean,
+ null: true,
+ description: 'Indicates whether the variable is protected.'
end
end
end
diff --git a/app/graphql/types/ci/instance_variable_type.rb b/app/graphql/types/ci/instance_variable_type.rb
index f564a2f59a0..7ffc52deb73 100644
--- a/app/graphql/types/ci/instance_variable_type.rb
+++ b/app/graphql/types/ci/instance_variable_type.rb
@@ -9,21 +9,29 @@ module Types
implements(VariableInterface)
+ field :id, GraphQL::Types::ID,
+ null: false,
+ description: 'ID of the variable.'
+
field :environment_scope, GraphQL::Types::String,
- null: true,
- deprecated: {
- reason: 'No longer used, only available for GroupVariableType and ProjectVariableType',
- milestone: '15.3'
- },
- description: 'Scope defining the environments that can use the variable.'
+ null: true,
+ deprecated: {
+ reason: 'No longer used, only available for GroupVariableType and ProjectVariableType',
+ milestone: '15.3'
+ },
+ description: 'Scope defining the environments that can use the variable.'
field :protected, GraphQL::Types::Boolean,
- null: true,
- description: 'Indicates whether the variable is protected.'
+ null: true,
+ description: 'Indicates whether the variable is protected.'
field :masked, GraphQL::Types::Boolean,
- null: true,
- description: 'Indicates whether the variable is masked.'
+ null: true,
+ description: 'Indicates whether the variable is masked.'
+
+ field :raw, GraphQL::Types::Boolean,
+ null: true,
+ description: 'Indicates whether the variable is raw.'
def environment_scope
nil
diff --git a/app/graphql/types/ci/job_artifact_type.rb b/app/graphql/types/ci/job_artifact_type.rb
index a6ab445702c..6346d50de3a 100644
--- a/app/graphql/types/ci/job_artifact_type.rb
+++ b/app/graphql/types/ci/job_artifact_type.rb
@@ -6,6 +6,9 @@ module Types
class JobArtifactType < BaseObject
graphql_name 'CiJobArtifact'
+ field :id, Types::GlobalIDType[::Ci::JobArtifact], null: false,
+ description: 'ID of the artifact.'
+
field :download_path, GraphQL::Types::String, null: true,
description: "URL for downloading the artifact's file."
@@ -16,6 +19,12 @@ module Types
description: 'File name of the artifact.',
method: :filename
+ field :size, GraphQL::Types::Int, null: false,
+ description: 'Size of the artifact in bytes.'
+
+ field :expire_at, Types::TimeType, null: true,
+ description: 'Expiry date of the artifact.'
+
def download_path
::Gitlab::Routing.url_helpers.download_project_job_artifacts_path(
object.project,
diff --git a/app/graphql/types/ci/job_type.rb b/app/graphql/types/ci/job_type.rb
index 4ea9a016e74..ab6103d9469 100644
--- a/app/graphql/types/ci/job_type.rb
+++ b/app/graphql/types/ci/job_type.rb
@@ -92,6 +92,8 @@ module Types
description: 'Indicates the job is stuck.'
field :triggered, GraphQL::Types::Boolean, null: true,
description: 'Whether the job was triggered.'
+ field :web_path, GraphQL::Types::String, null: true,
+ description: 'Web path of the job.'
def kind
return ::Ci::Build unless [::Ci::Build, ::Ci::Bridge].include?(object.class)
@@ -181,6 +183,10 @@ module Types
::Gitlab::Routing.url_helpers.project_commits_path(object.project, ref_name)
end
+ def web_path
+ ::Gitlab::Routing.url_helpers.project_job_path(object.project, object)
+ end
+
def coverage
object&.coverage
end
diff --git a/app/graphql/types/ci/manual_variable_type.rb b/app/graphql/types/ci/manual_variable_type.rb
index d6f59c1d249..ed92a6645b4 100644
--- a/app/graphql/types/ci/manual_variable_type.rb
+++ b/app/graphql/types/ci/manual_variable_type.rb
@@ -10,12 +10,12 @@ module Types
implements(VariableInterface)
field :environment_scope, GraphQL::Types::String,
- null: true,
- deprecated: {
- reason: 'No longer used, only available for GroupVariableType and ProjectVariableType',
- milestone: '15.3'
- },
- description: 'Scope defining the environments that can use the variable.'
+ null: true,
+ deprecated: {
+ reason: 'No longer used, only available for GroupVariableType and ProjectVariableType',
+ milestone: '15.3'
+ },
+ description: 'Scope defining the environments that can use the variable.'
def environment_scope
nil
diff --git a/app/graphql/types/ci/project_variable_connection_type.rb b/app/graphql/types/ci/project_variable_connection_type.rb
new file mode 100644
index 00000000000..c3cdc425f10
--- /dev/null
+++ b/app/graphql/types/ci/project_variable_connection_type.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+module Types
+ module Ci
+ # rubocop: disable Graphql/AuthorizeTypes
+ class ProjectVariableConnectionType < GraphQL::Types::Relay::BaseConnection
+ field :limit, GraphQL::Types::Int,
+ null: false,
+ description: 'Maximum amount of project CI/CD variables.'
+
+ def limit
+ ::Plan.default.actual_limits.project_ci_variables
+ end
+ end
+ # rubocop: enable Graphql/AuthorizeTypes
+ end
+end
diff --git a/app/graphql/types/ci/project_variable_type.rb b/app/graphql/types/ci/project_variable_type.rb
index 625bb7fd4b1..2a5375045e5 100644
--- a/app/graphql/types/ci/project_variable_type.rb
+++ b/app/graphql/types/ci/project_variable_type.rb
@@ -7,19 +7,20 @@ module Types
graphql_name 'CiProjectVariable'
description 'CI/CD variables for a project.'
+ connection_type_class(Types::Ci::ProjectVariableConnectionType)
implements(VariableInterface)
field :environment_scope, GraphQL::Types::String,
- null: true,
- description: 'Scope defining the environments that can use the variable.'
+ null: true,
+ description: 'Scope defining the environments that can use the variable.'
field :protected, GraphQL::Types::Boolean,
- null: true,
- description: 'Indicates whether the variable is protected.'
+ null: true,
+ description: 'Indicates whether the variable is protected.'
field :masked, GraphQL::Types::Boolean,
- null: true,
- description: 'Indicates whether the variable is masked.'
+ null: true,
+ description: 'Indicates whether the variable is masked.'
end
end
end
diff --git a/app/graphql/types/ci/runner_membership_filter_enum.rb b/app/graphql/types/ci/runner_membership_filter_enum.rb
index 2e1051b2151..4fd7e0749b0 100644
--- a/app/graphql/types/ci/runner_membership_filter_enum.rb
+++ b/app/graphql/types/ci/runner_membership_filter_enum.rb
@@ -3,15 +3,17 @@
module Types
module Ci
class RunnerMembershipFilterEnum < BaseEnum
- graphql_name 'RunnerMembershipFilter'
- description 'Values for filtering runners in namespaces.'
+ graphql_name 'CiRunnerMembershipFilter'
+ description 'Values for filtering runners in namespaces. ' \
+ 'The previous type name `RunnerMembershipFilter` was deprecated in 15.4.'
value 'DIRECT',
description: "Include runners that have a direct relationship.",
value: :direct
value 'DESCENDANTS',
- description: "Include runners that have either a direct relationship or a relationship with descendants. These can be project runners or group runners (in the case where group is queried).",
+ description: "Include runners that have either a direct or inherited relationship. " \
+ "These runners can be specific to a project or a group.",
value: :descendants
end
end
diff --git a/app/graphql/types/ci/runner_type.rb b/app/graphql/types/ci/runner_type.rb
index 0afb61d2b64..a9c76974850 100644
--- a/app/graphql/types/ci/runner_type.rb
+++ b/app/graphql/types/ci/runner_type.rb
@@ -52,7 +52,7 @@ module Types
field :job_count, GraphQL::Types::Int, null: true,
description: "Number of jobs processed by the runner (limited to #{JOB_COUNT_LIMIT}, plus one to indicate that more items exist)."
field :jobs, ::Types::Ci::JobType.connection_type, null: true,
- description: 'Jobs assigned to the runner.',
+ description: 'Jobs assigned to the runner. This field can only be resolved for one runner in any single request.',
authorize: :read_builds,
resolver: ::Resolvers::Ci::RunnerJobsResolver
field :locked, GraphQL::Types::Boolean, null: true,
@@ -63,8 +63,11 @@ module Types
description: 'Indicates the runner is paused and not available to run jobs.'
field :project_count, GraphQL::Types::Int, null: true,
description: 'Number of projects that the runner is associated with.'
- field :projects, ::Types::ProjectType.connection_type, null: true,
- description: 'Projects the runner is associated with. For project runners only.'
+ field :projects,
+ ::Types::ProjectType.connection_type,
+ null: true,
+ resolver: ::Resolvers::Ci::RunnerProjectsResolver,
+ description: 'Find projects the runner is associated with. For project runners only.'
field :revision, GraphQL::Types::String, null: true,
description: 'Revision of the runner.'
field :run_untagged, GraphQL::Types::Boolean, null: false,
@@ -131,12 +134,6 @@ module Types
batched_owners(::Ci::RunnerNamespace, Group, :runner_groups, :namespace_id)
end
- def projects
- return unless runner.project_type?
-
- batched_owners(::Ci::RunnerProject, Project, :runner_projects, :project_id)
- end
-
private
def can_admin_runners?
@@ -159,19 +156,12 @@ module Types
owner_ids = runner_owner_ids_by_runner_id.values.flatten.uniq
owners = assoc_type.where(id: owner_ids).index_by(&:id)
- # Preload projects namespaces to avoid N+1 queries when checking the `read_project` policy for each
- preload_projects_namespaces(owners.values) if assoc_type == Project
-
runner_ids.each do |runner_id|
loader.call(runner_id, runner_owner_ids_by_runner_id[runner_id]&.map { |owner_id| owners[owner_id] } || [])
end
end
end
# rubocop: enable CodeReuse/ActiveRecord
-
- def preload_projects_namespaces(_projects)
- # overridden in EE
- end
end
end
end
diff --git a/app/graphql/types/ci/variable_interface.rb b/app/graphql/types/ci/variable_interface.rb
index 82c9ba7121c..ec68d3c987c 100644
--- a/app/graphql/types/ci/variable_interface.rb
+++ b/app/graphql/types/ci/variable_interface.rb
@@ -8,24 +8,24 @@ module Types
graphql_name 'CiVariable'
field :id, GraphQL::Types::ID,
- null: false,
- description: 'ID of the variable.'
+ null: false,
+ description: 'ID of the variable.'
field :key, GraphQL::Types::String,
- null: true,
- description: 'Name of the variable.'
+ null: true,
+ description: 'Name of the variable.'
+
+ field :raw, GraphQL::Types::Boolean,
+ null: true,
+ description: 'Indicates whether the variable is raw.'
field :value, GraphQL::Types::String,
- null: true,
- description: 'Value of the variable.'
+ null: true,
+ description: 'Value of the variable.'
field :variable_type, ::Types::Ci::VariableTypeEnum,
- null: true,
- description: 'Type of the variable.'
-
- field :raw, GraphQL::Types::Boolean,
- null: true,
- description: 'Indicates whether the variable is raw.'
+ null: true,
+ description: 'Type of the variable.'
end
end
end
diff --git a/app/graphql/types/clusters/agent_type.rb b/app/graphql/types/clusters/agent_type.rb
index 546252b2285..5d7b8815cde 100644
--- a/app/graphql/types/clusters/agent_type.rb
+++ b/app/graphql/types/clusters/agent_type.rb
@@ -71,3 +71,5 @@ module Types
end
end
end
+
+Types::Clusters::AgentType.prepend_mod
diff --git a/app/graphql/types/customer_relations/contact_sort_enum.rb b/app/graphql/types/customer_relations/contact_sort_enum.rb
index 221dedacb6a..bb11d741368 100644
--- a/app/graphql/types/customer_relations/contact_sort_enum.rb
+++ b/app/graphql/types/customer_relations/contact_sort_enum.rb
@@ -11,10 +11,10 @@ module Types
sortable_fields.each do |field|
value "#{field.upcase.tr(' ', '_')}_ASC",
value: { field: field.downcase.tr(' ', '_'), direction: :asc },
- description: "#{field} by ascending order."
+ description: "#{field} in ascending order."
value "#{field.upcase.tr(' ', '_')}_DESC",
value: { field: field.downcase.tr(' ', '_'), direction: :desc },
- description: "#{field} by descending order."
+ description: "#{field} in descending order."
end
end
end
diff --git a/app/graphql/types/customer_relations/organization_sort_enum.rb b/app/graphql/types/customer_relations/organization_sort_enum.rb
new file mode 100644
index 00000000000..742a5a4fa99
--- /dev/null
+++ b/app/graphql/types/customer_relations/organization_sort_enum.rb
@@ -0,0 +1,21 @@
+# frozen_string_literal: true
+
+module Types
+ module CustomerRelations
+ class OrganizationSortEnum < SortEnum
+ graphql_name 'OrganizationSort'
+ description 'Values for sorting organizations'
+
+ sortable_fields = ['Name', 'Description', 'Default Rate']
+
+ sortable_fields.each do |field|
+ value "#{field.upcase.tr(' ', '_')}_ASC",
+ value: { field: field.downcase.tr(' ', '_'), direction: :asc },
+ description: "#{field} in ascending order."
+ value "#{field.upcase.tr(' ', '_')}_DESC",
+ value: { field: field.downcase.tr(' ', '_'), direction: :desc },
+ description: "#{field} in descending order."
+ end
+ end
+ end
+end
diff --git a/app/graphql/types/customer_relations/organization_state_counts_type.rb b/app/graphql/types/customer_relations/organization_state_counts_type.rb
new file mode 100644
index 00000000000..7d813209a8e
--- /dev/null
+++ b/app/graphql/types/customer_relations/organization_state_counts_type.rb
@@ -0,0 +1,24 @@
+# frozen_string_literal: true
+
+module Types
+ module CustomerRelations
+ # `object` is a hash. Authorization is performed by OrganizationStateCountsResolver
+ class OrganizationStateCountsType < Types::BaseObject # rubocop:disable Graphql/AuthorizeTypes
+ graphql_name 'OrganizationStateCounts'
+ description 'Represents the total number of organizations for the represented states.'
+
+ AVAILABLE_STATES = ::CustomerRelations::Organization.states.keys.push('all').freeze
+
+ AVAILABLE_STATES.each do |state|
+ field state,
+ GraphQL::Types::Int,
+ null: true,
+ description: "Number of organizations with state `#{state.upcase}`"
+ end
+
+ def all
+ object.values.sum
+ end
+ end
+ end
+end
diff --git a/app/graphql/types/customer_relations/organization_state_enum.rb b/app/graphql/types/customer_relations/organization_state_enum.rb
index ecdd7d092ad..84bbbbc90fc 100644
--- a/app/graphql/types/customer_relations/organization_state_enum.rb
+++ b/app/graphql/types/customer_relations/organization_state_enum.rb
@@ -5,12 +5,16 @@ module Types
class OrganizationStateEnum < BaseEnum
graphql_name 'CustomerRelationsOrganizationState'
+ value 'all',
+ description: "All available organizations.",
+ value: :all
+
value 'active',
- description: "Active organization.",
+ description: "Active organizations.",
value: :active
value 'inactive',
- description: "Inactive organization.",
+ description: "Inactive organizations.",
value: :inactive
end
end
diff --git a/app/graphql/types/deployment_details_type.rb b/app/graphql/types/deployment_details_type.rb
new file mode 100644
index 00000000000..f8ba0cb1b24
--- /dev/null
+++ b/app/graphql/types/deployment_details_type.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+module Types
+ class DeploymentDetailsType < DeploymentType
+ graphql_name 'DeploymentDetails'
+ description 'The details of the deployment'
+ authorize :read_deployment
+ present_using Deployments::DeploymentPresenter
+
+ field :tags,
+ [Types::DeploymentTagType],
+ description: 'Git tags that contain this deployment.',
+ calls_gitaly: true
+ end
+end
diff --git a/app/graphql/types/deployment_status_enum.rb b/app/graphql/types/deployment_status_enum.rb
new file mode 100644
index 00000000000..7ef69d3f1c1
--- /dev/null
+++ b/app/graphql/types/deployment_status_enum.rb
@@ -0,0 +1,14 @@
+# frozen_string_literal: true
+
+module Types
+ class DeploymentStatusEnum < BaseEnum
+ graphql_name 'DeploymentStatus'
+ description 'All deployment statuses.'
+
+ ::Deployment.statuses.each_key do |status|
+ value status.upcase,
+ description: "A deployment that is #{status.tr('_', ' ')}.",
+ value: status
+ end
+ end
+end
diff --git a/app/graphql/types/deployment_tag_type.rb b/app/graphql/types/deployment_tag_type.rb
new file mode 100644
index 00000000000..bc3597404a2
--- /dev/null
+++ b/app/graphql/types/deployment_tag_type.rb
@@ -0,0 +1,20 @@
+# frozen_string_literal: true
+
+module Types
+ # DeploymentTagType is a hash, authorized by the deployment
+ # rubocop:disable Graphql/AuthorizeTypes
+ class DeploymentTagType < BaseObject
+ graphql_name 'DeploymentTag'
+ description 'Tags for a given deployment'
+
+ field :name,
+ GraphQL::Types::String,
+ description: 'Name of this git tag.'
+
+ field :path,
+ GraphQL::Types::String,
+ description: 'Path for this tag.',
+ hash_key: :path
+ end
+ # rubocop:enable Graphql/AuthorizeTypes
+end
diff --git a/app/graphql/types/deployment_type.rb b/app/graphql/types/deployment_type.rb
new file mode 100644
index 00000000000..70a3a4cb574
--- /dev/null
+++ b/app/graphql/types/deployment_type.rb
@@ -0,0 +1,69 @@
+# frozen_string_literal: true
+
+module Types
+ # If you're considering to add a new field in DeploymentType, please follow this guideline:
+ # - If the field is preloadable in batch, define it in DeploymentType.
+ # In this case, you should extend DeploymentsResolver logic to preload the field. Also, add a new test that
+ # fetching the specific field for multiple deployments doesn't cause N+1 query problem.
+ # - If the field is NOT preloadable in batch, define it in DeploymentDetailsType.
+ # This type can be only fetched for a single deployment, so you don't need to take care of the preloading.
+ class DeploymentType < BaseObject
+ graphql_name 'Deployment'
+ description 'The deployment of an environment'
+
+ present_using Deployments::DeploymentPresenter
+
+ authorize :read_deployment
+
+ field :id,
+ GraphQL::Types::ID,
+ description: 'Global ID of the deployment.'
+
+ field :iid,
+ GraphQL::Types::ID,
+ description: 'Project-level internal ID of the deployment.'
+
+ field :ref,
+ GraphQL::Types::String,
+ description: 'Git-Ref that the deployment ran on.'
+
+ field :tag,
+ GraphQL::Types::Boolean,
+ description: 'True or false if the deployment ran on a Git-tag.'
+
+ field :sha,
+ GraphQL::Types::String,
+ description: 'Git-SHA that the deployment ran on.'
+
+ field :created_at,
+ Types::TimeType,
+ description: 'When the deployment record was created.'
+
+ field :updated_at,
+ Types::TimeType,
+ description: 'When the deployment record was updated.'
+
+ field :finished_at,
+ Types::TimeType,
+ description: 'When the deployment finished.'
+
+ field :status,
+ Types::DeploymentStatusEnum,
+ description: 'Status of the deployment.'
+
+ field :commit,
+ Types::CommitType,
+ description: 'Commit details of the deployment.',
+ calls_gitaly: true
+
+ field :job,
+ Types::Ci::JobType,
+ description: 'Pipeline job of the deployment.',
+ method: :build
+
+ field :triggerer,
+ Types::UserType,
+ description: 'User who executed the deployment.',
+ method: :deployed_by
+ end
+end
diff --git a/app/graphql/types/deployments_order_by_input_type.rb b/app/graphql/types/deployments_order_by_input_type.rb
new file mode 100644
index 00000000000..a87fef9fe8a
--- /dev/null
+++ b/app/graphql/types/deployments_order_by_input_type.rb
@@ -0,0 +1,24 @@
+# frozen_string_literal: true
+
+module Types
+ class DeploymentsOrderByInputType < BaseInputObject
+ graphql_name 'DeploymentsOrderByInput'
+ description 'Values for ordering deployments by a specific field'
+
+ argument :created_at,
+ Types::SortDirectionEnum,
+ required: false,
+ description: 'Order by Created time.'
+
+ argument :finished_at,
+ Types::SortDirectionEnum,
+ required: false,
+ description: 'Order by Finished time.'
+
+ def prepare
+ raise GraphQL::ExecutionError, 'orderBy parameter must contain one key-value pair.' unless to_h.size == 1
+
+ super
+ end
+ end
+end
diff --git a/app/graphql/types/environment_type.rb b/app/graphql/types/environment_type.rb
index 2a7076cc3c9..eb4e7b1dabf 100644
--- a/app/graphql/types/environment_type.rb
+++ b/app/graphql/types/environment_type.rb
@@ -21,6 +21,30 @@ module Types
field :path, GraphQL::Types::String, null: false,
description: 'Path to the environment.'
+ field :slug, GraphQL::Types::String,
+ description: 'Slug of the environment.'
+
+ field :external_url, GraphQL::Types::String, null: true,
+ description: 'External URL of the environment.'
+
+ field :created_at, Types::TimeType,
+ description: 'When the environment was created.'
+
+ field :updated_at, Types::TimeType,
+ description: 'When the environment was updated.'
+
+ field :auto_stop_at, Types::TimeType,
+ description: 'When the environment is going to be stopped automatically.'
+
+ field :auto_delete_at, Types::TimeType,
+ description: 'When the environment is going to be deleted automatically.'
+
+ field :tier, Types::DeploymentTierEnum,
+ description: 'Deployment tier of the environment.'
+
+ field :environment_type, GraphQL::Types::String,
+ description: 'Folder name of the environment.'
+
field :metrics_dashboard, Types::Metrics::DashboardType, null: true,
description: 'Metrics dashboard schema for the environment.',
resolver: Resolvers::Metrics::DashboardResolver
@@ -29,5 +53,22 @@ module Types
Types::AlertManagement::AlertType,
null: true,
description: 'Most severe open alert for the environment. If multiple alerts have equal severity, the most recent is returned.'
+
+ field :deployments,
+ Types::DeploymentType.connection_type,
+ null: true,
+ description: 'Deployments of the environment. This field can only be resolved for one project in any single request.',
+ resolver: Resolvers::DeploymentsResolver do
+ extension ::Gitlab::Graphql::Limit::FieldCallCount, limit: 1
+ end
+
+ field :last_deployment,
+ Types::DeploymentType,
+ description: 'Last deployment of the environment.',
+ resolver: Resolvers::Environments::LastDeploymentResolver
+
+ def tier
+ object.tier.to_sym
+ end
end
end
diff --git a/app/graphql/types/group_type.rb b/app/graphql/types/group_type.rb
index 235a2bc2a34..45357de5502 100644
--- a/app/graphql/types/group_type.rb
+++ b/app/graphql/types/group_type.rb
@@ -22,7 +22,7 @@ module Types
type: Types::CustomEmojiType.connection_type,
null: true,
description: 'Custom emoji within this namespace.',
- _deprecated_feature_flag: :custom_emoji
+ alpha: { milestone: '13.6' }
field :share_with_group_lock,
type: GraphQL::Types::Boolean,
@@ -134,7 +134,7 @@ module Types
description: 'Number of container repositories in the group.'
field :packages,
- description: 'Packages of the group.',
+ description: 'Packages of the group. This field can only be resolved for one group in any single request.',
resolver: Resolvers::GroupPackagesResolver
field :dependency_proxy_setting,
@@ -212,6 +212,12 @@ module Types
description: "Find organizations of this group.",
resolver: Resolvers::Crm::OrganizationsResolver
+ field :organization_state_counts,
+ Types::CustomerRelations::OrganizationStateCountsType,
+ null: true,
+ description: 'Counts of organizations by status for the group.',
+ resolver: Resolvers::Crm::OrganizationStateCountsResolver
+
field :contacts, Types::CustomerRelations::ContactType.connection_type,
null: true,
description: "Find contacts of this group.",
@@ -272,6 +278,10 @@ module Types
group.dependency_proxy_setting || group.create_dependency_proxy_setting
end
+ def custom_emoji
+ object.custom_emoji if Feature.enabled?(:custom_emoji)
+ end
+
private
def group
diff --git a/app/graphql/types/member_sort_enum.rb b/app/graphql/types/member_sort_enum.rb
new file mode 100644
index 00000000000..f3291dda13b
--- /dev/null
+++ b/app/graphql/types/member_sort_enum.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+module Types
+ class MemberSortEnum < SortEnum
+ graphql_name 'MemberSort'
+ description 'Values for sorting members'
+
+ value 'ACCESS_LEVEL_ASC', 'Access level ascending order.', value: :access_level_asc
+ value 'ACCESS_LEVEL_DESC', 'Access level descending order.', value: :access_level_desc
+ value 'USER_FULL_NAME_ASC', "User's full name ascending order.", value: :name_asc
+ value 'USER_FULL_NAME_DESC', "User's full name descending order.", value: :name_desc
+ end
+end
diff --git a/app/graphql/types/merge_request_type.rb b/app/graphql/types/merge_request_type.rb
index d88653f2f8c..399dcc8e03d 100644
--- a/app/graphql/types/merge_request_type.rb
+++ b/app/graphql/types/merge_request_type.rb
@@ -94,9 +94,10 @@ module Types
method: :public_merge_status, null: true,
description: 'Merge status of the merge request.'
- field :detailed_merge_status, ::Types::MergeRequests::DetailedMergeStatusEnum, method: :detailed_merge_status, null: true,
+ field :detailed_merge_status, ::Types::MergeRequests::DetailedMergeStatusEnum, null: true,
calls_gitaly: true,
- description: 'Detailed merge status of the merge request.', alpha: { milestone: '15.3' }
+ description: 'Detailed merge status of the merge request.',
+ alpha: { milestone: '15.3' }
field :mergeable_discussions_state, GraphQL::Types::Boolean, null: true,
calls_gitaly: true,
@@ -280,6 +281,10 @@ module Types
def merge_user
object.metrics&.merged_by || object.merge_user
end
+
+ def detailed_merge_status
+ ::MergeRequests::Mergeability::DetailedMergeStatusService.new(merge_request: object).execute
+ end
end
end
diff --git a/app/graphql/types/merge_requests/detailed_merge_status_enum.rb b/app/graphql/types/merge_requests/detailed_merge_status_enum.rb
index 58104159303..3de6296154d 100644
--- a/app/graphql/types/merge_requests/detailed_merge_status_enum.rb
+++ b/app/graphql/types/merge_requests/detailed_merge_status_enum.rb
@@ -21,6 +21,9 @@ module Types
value 'CI_MUST_PASS',
value: :ci_must_pass,
description: 'Pipeline must succeed before merging.'
+ value 'CI_STILL_RUNNING',
+ value: :ci_still_running,
+ description: 'Pipeline is still running.'
value 'DISCUSSIONS_NOT_RESOLVED',
value: :discussions_not_resolved,
description: 'Discussions must be resolved before merging.'
diff --git a/app/graphql/types/mutation_type.rb b/app/graphql/types/mutation_type.rb
index 499c2e786bf..ea833b35085 100644
--- a/app/graphql/types/mutation_type.rb
+++ b/app/graphql/types/mutation_type.rb
@@ -37,8 +37,8 @@ module Types
mount_mutation Mutations::Clusters::AgentTokens::Create
mount_mutation Mutations::Clusters::AgentTokens::Revoke
mount_mutation Mutations::Commits::Create, calls_gitaly: true
- mount_mutation Mutations::CustomEmoji::Create, _deprecated_feature_flag: :custom_emoji
- mount_mutation Mutations::CustomEmoji::Destroy, _deprecated_feature_flag: :custom_emoji
+ mount_mutation Mutations::CustomEmoji::Create, alpha: { milestone: '13.6' }
+ mount_mutation Mutations::CustomEmoji::Destroy, alpha: { milestone: '13.6' }
mount_mutation Mutations::CustomerRelations::Contacts::Create
mount_mutation Mutations::CustomerRelations::Contacts::Update
mount_mutation Mutations::CustomerRelations::Organizations::Create
@@ -120,10 +120,12 @@ module Types
milestone: '15.0'
}
mount_mutation Mutations::Ci::ProjectCiCdSettingsUpdate
+ mount_mutation Mutations::Ci::Job::ArtifactsDestroy
mount_mutation Mutations::Ci::Job::Play
mount_mutation Mutations::Ci::Job::Retry
mount_mutation Mutations::Ci::Job::Cancel
mount_mutation Mutations::Ci::Job::Unschedule
+ mount_mutation Mutations::Ci::JobArtifact::Destroy
mount_mutation Mutations::Ci::JobTokenScope::AddProject
mount_mutation Mutations::Ci::JobTokenScope::RemoveProject
mount_mutation Mutations::Ci::Runner::Update
diff --git a/app/graphql/types/packages/package_details_type.rb b/app/graphql/types/packages/package_details_type.rb
index 0413177ef14..6c0d955ed77 100644
--- a/app/graphql/types/packages/package_details_type.rb
+++ b/app/graphql/types/packages/package_details_type.rb
@@ -26,6 +26,8 @@ module Types
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.'
+ field :last_downloaded_at, Types::TimeType, null: true, description: 'Last time that a file of this package was downloaded.'
+
def versions
object.versions
end
diff --git a/app/graphql/types/project_type.rb b/app/graphql/types/project_type.rb
index ecc6c9d7811..f43f5c27dac 100644
--- a/app/graphql/types/project_type.rb
+++ b/app/graphql/types/project_type.rb
@@ -10,119 +10,204 @@ module Types
expose_permissions Types::PermissionTypes::Project
- field :id, GraphQL::Types::ID, null: false,
- description: 'ID of the project.'
-
- field :ci_config_path_or_default, GraphQL::Types::String, null: false,
- description: 'Path of the CI configuration file.'
- field :full_path, GraphQL::Types::ID, null: false,
- description: 'Full path of the project.'
- field :path, GraphQL::Types::String, null: false,
- description: 'Path of the project.'
-
- field :sast_ci_configuration, Types::CiConfiguration::Sast::Type, null: true,
- calls_gitaly: true,
- description: 'SAST CI configuration for the project.'
-
- field :name, GraphQL::Types::String, null: false,
- description: 'Name of the project (without namespace).'
- field :name_with_namespace, GraphQL::Types::String, null: false,
- description: 'Full name of the project with its namespace.'
-
- field :description, GraphQL::Types::String, null: true,
- description: 'Short description of the project.'
-
- field :tag_list, GraphQL::Types::String, null: true,
- deprecated: { reason: 'Use `topics`', milestone: '13.12' },
- description: 'List of project topics (not Git tags).', method: :topic_list
-
- field :topics, [GraphQL::Types::String], null: true,
- description: 'List of project topics.', method: :topic_list
-
- field :http_url_to_repo, GraphQL::Types::String, null: true,
- description: 'URL to connect to the project via HTTPS.'
- field :ssh_url_to_repo, GraphQL::Types::String, null: true,
- description: 'URL to connect to the project via SSH.'
- field :web_url, GraphQL::Types::String, null: true,
- description: 'Web URL of the project.'
-
- field :forks_count, GraphQL::Types::Int, null: false, calls_gitaly: true, # 4 times
- description: 'Number of times the project has been forked.'
- field :star_count, GraphQL::Types::Int, null: false,
- description: 'Number of times the project has been starred.'
-
- field :created_at, Types::TimeType, null: true,
- description: 'Timestamp of the project creation.'
- field :last_activity_at, Types::TimeType, null: true,
- description: 'Timestamp of the project last activity.'
-
- field :archived, GraphQL::Types::Boolean, null: true,
- description: 'Indicates the archived status of the project.'
-
- field :visibility, GraphQL::Types::String, null: true,
- description: 'Visibility of the project.'
-
- field :lfs_enabled, GraphQL::Types::Boolean, null: true,
- description: 'Indicates if the project has Large File Storage (LFS) enabled.'
- field :merge_requests_ff_only_enabled, GraphQL::Types::Boolean, null: true,
- description: 'Indicates if no merge commits should be created and all merges should instead be fast-forwarded, which means that merging is only allowed if the branch could be fast-forwarded.'
- field :shared_runners_enabled, GraphQL::Types::Boolean, null: true,
- description: 'Indicates if shared runners are enabled for the project.'
-
- field :service_desk_enabled, GraphQL::Types::Boolean, null: true,
- description: 'Indicates if the project has Service Desk enabled.'
-
- field :service_desk_address, GraphQL::Types::String, null: true,
- description: 'E-mail address of the Service Desk.'
-
- field :avatar_url, GraphQL::Types::String, null: true, calls_gitaly: true,
- description: 'URL to avatar image file of the project.'
-
- field :jobs_enabled, GraphQL::Types::Boolean, null: true,
- description: 'Indicates if CI/CD pipeline jobs are enabled for the current user.'
-
- field :public_jobs, GraphQL::Types::Boolean, method: :public_builds, null: true,
- description: 'Indicates if there is public access to pipelines and job details of the project, including output logs and artifacts.'
-
- field :open_issues_count, GraphQL::Types::Int, null: true,
- description: 'Number of open issues for the project.'
-
- field :allow_merge_on_skipped_pipeline, GraphQL::Types::Boolean, null: true,
- description: 'If `only_allow_merge_if_pipeline_succeeds` is true, indicates if merge requests of the project can also be merged with skipped jobs.'
- field :autoclose_referenced_issues, GraphQL::Types::Boolean, null: true,
- description: 'Indicates if issues referenced by merge requests and commits within the default branch are closed automatically.'
- field :import_status, GraphQL::Types::String, null: true,
- description: 'Status of import background job of the project.'
- field :jira_import_status, GraphQL::Types::String, null: true,
- description: 'Status of Jira import background job of the project.'
- field :only_allow_merge_if_all_discussions_are_resolved, GraphQL::Types::Boolean, null: true,
- description: 'Indicates if merge requests of the project can only be merged when all the discussions are resolved.'
- field :only_allow_merge_if_pipeline_succeeds, GraphQL::Types::Boolean, null: true,
- description: 'Indicates if merge requests of the project can only be merged with successful jobs.'
- field :printing_merge_request_link_enabled, GraphQL::Types::Boolean, null: true,
- description: 'Indicates if a link to create or view a merge request should display after a push to Git repositories of the project from the command line.'
- field :remove_source_branch_after_merge, GraphQL::Types::Boolean, null: true,
- description: 'Indicates if `Delete source branch` option should be enabled by default for all new merge requests of the project.'
- field :request_access_enabled, GraphQL::Types::Boolean, null: true,
- description: 'Indicates if users can request member access to the project.'
- field :squash_read_only, GraphQL::Types::Boolean, null: false, method: :squash_readonly?,
- description: 'Indicates if `squashReadOnly` is enabled.'
- field :suggestion_commit_message, GraphQL::Types::String, null: true,
- description: 'Commit message used to apply merge request suggestions.'
+ field :id, GraphQL::Types::ID,
+ null: false,
+ description: 'ID of the project.'
+
+ field :ci_config_path_or_default, GraphQL::Types::String,
+ null: false,
+ description: 'Path of the CI configuration file.'
+
+ field :ci_config_variables, [Types::Ci::ConfigVariableType],
+ null: true,
+ calls_gitaly: true,
+ authorize: :create_pipeline,
+ alpha: { milestone: '15.3' },
+ description: 'CI/CD config variable.' do
+ argument :sha, GraphQL::Types::String,
+ required: true,
+ description: 'Sha.'
+ end
+
+ field :full_path, GraphQL::Types::ID,
+ null: false,
+ description: 'Full path of the project.'
+
+ field :path, GraphQL::Types::String,
+ null: false,
+ description: 'Path of the project.'
+
+ field :sast_ci_configuration, Types::CiConfiguration::Sast::Type,
+ null: true,
+ calls_gitaly: true,
+ description: 'SAST CI configuration for the project.'
+
+ field :name, GraphQL::Types::String,
+ null: false,
+ description: 'Name of the project (without namespace).'
+
+ field :name_with_namespace, GraphQL::Types::String,
+ null: false,
+ description: 'Full name of the project with its namespace.'
+
+ field :description, GraphQL::Types::String,
+ null: true,
+ description: 'Short description of the project.'
+
+ field :tag_list, GraphQL::Types::String,
+ null: true,
+ deprecated: { reason: 'Use `topics`', milestone: '13.12' },
+ description: 'List of project topics (not Git tags).',
+ method: :topic_list
+
+ field :topics, [GraphQL::Types::String],
+ null: true,
+ description: 'List of project topics.',
+ method: :topic_list
+
+ field :http_url_to_repo, GraphQL::Types::String,
+ null: true,
+ description: 'URL to connect to the project via HTTPS.'
+
+ field :ssh_url_to_repo, GraphQL::Types::String,
+ null: true,
+ description: 'URL to connect to the project via SSH.'
+
+ field :web_url, GraphQL::Types::String,
+ null: true,
+ description: 'Web URL of the project.'
+
+ field :forks_count, GraphQL::Types::Int,
+ null: false,
+ calls_gitaly: true, # 4 times
+ description: 'Number of times the project has been forked.'
+
+ field :star_count, GraphQL::Types::Int,
+ null: false,
+ description: 'Number of times the project has been starred.'
+
+ field :created_at, Types::TimeType,
+ null: true,
+ description: 'Timestamp of the project creation.'
+
+ field :last_activity_at, Types::TimeType,
+ null: true,
+ description: 'Timestamp of the project last activity.'
+
+ field :archived, GraphQL::Types::Boolean,
+ null: true,
+ description: 'Indicates the archived status of the project.'
+
+ field :visibility, GraphQL::Types::String,
+ null: true,
+ description: 'Visibility of the project.'
+
+ field :lfs_enabled, GraphQL::Types::Boolean,
+ null: true,
+ description: 'Indicates if the project has Large File Storage (LFS) enabled.'
+
+ field :merge_requests_ff_only_enabled, GraphQL::Types::Boolean,
+ null: true,
+ description: 'Indicates if no merge commits should be created and all merges should instead be ' \
+ 'fast-forwarded, which means that merging is only allowed if the branch could be fast-forwarded.'
+
+ field :shared_runners_enabled, GraphQL::Types::Boolean,
+ null: true,
+ description: 'Indicates if shared runners are enabled for the project.'
+
+ field :service_desk_enabled, GraphQL::Types::Boolean,
+ null: true,
+ description: 'Indicates if the project has Service Desk enabled.'
+
+ field :service_desk_address, GraphQL::Types::String,
+ null: true,
+ description: 'E-mail address of the Service Desk.'
+
+ field :avatar_url, GraphQL::Types::String,
+ null: true,
+ calls_gitaly: true,
+ description: 'URL to avatar image file of the project.'
+
+ field :jobs_enabled, GraphQL::Types::Boolean,
+ null: true,
+ description: 'Indicates if CI/CD pipeline jobs are enabled for the current user.'
+
+ field :public_jobs, GraphQL::Types::Boolean,
+ null: true,
+ description: 'Indicates if there is public access to pipelines and job details of the project, ' \
+ 'including output logs and artifacts.',
+ method: :public_builds
+
+ field :open_issues_count, GraphQL::Types::Int,
+ null: true,
+ description: 'Number of open issues for the project.'
+
+ field :allow_merge_on_skipped_pipeline, GraphQL::Types::Boolean,
+ null: true,
+ description: 'If `only_allow_merge_if_pipeline_succeeds` is true, indicates if merge requests of ' \
+ 'the project can also be merged with skipped jobs.'
+
+ field :autoclose_referenced_issues, GraphQL::Types::Boolean,
+ null: true,
+ description: 'Indicates if issues referenced by merge requests and commits within the default branch ' \
+ 'are closed automatically.'
+
+ field :import_status, GraphQL::Types::String,
+ null: true,
+ description: 'Status of import background job of the project.'
+
+ field :jira_import_status, GraphQL::Types::String,
+ null: true,
+ description: 'Status of Jira import background job of the project.'
+
+ field :only_allow_merge_if_all_discussions_are_resolved, GraphQL::Types::Boolean,
+ null: true,
+ description: 'Indicates if merge requests of the project can only be merged when all the discussions are resolved.'
+
+ field :only_allow_merge_if_pipeline_succeeds, GraphQL::Types::Boolean,
+ null: true,
+ description: 'Indicates if merge requests of the project can only be merged with successful jobs.'
+
+ field :printing_merge_request_link_enabled, GraphQL::Types::Boolean,
+ null: true,
+ description: 'Indicates if a link to create or view a merge request should display after a push to Git ' \
+ 'repositories of the project from the command line.'
+
+ field :remove_source_branch_after_merge, GraphQL::Types::Boolean,
+ null: true,
+ description: 'Indicates if `Delete source branch` option should be enabled by default for all ' \
+ 'new merge requests of the project.'
+
+ field :request_access_enabled, GraphQL::Types::Boolean,
+ null: true,
+ description: 'Indicates if users can request member access to the project.'
+
+ field :squash_read_only, GraphQL::Types::Boolean,
+ null: false,
+ description: 'Indicates if `squashReadOnly` is enabled.',
+ method: :squash_readonly?
+
+ field :suggestion_commit_message, GraphQL::Types::String,
+ null: true,
+ description: 'Commit message used to apply merge request suggestions.'
# No, the quotes are not a typo. Used to get around circular dependencies.
# See https://gitlab.com/gitlab-org/gitlab/-/merge_requests/27536#note_871009675
- field :group, 'Types::GroupType', null: true,
- description: 'Group of the project.'
- field :namespace, Types::NamespaceType, null: true,
- description: 'Namespace of the project.'
+ field :group, 'Types::GroupType',
+ null: true,
+ description: 'Group of the project.'
+
+ field :namespace, Types::NamespaceType,
+ null: true,
+ description: 'Namespace of the project.'
field :statistics, Types::ProjectStatisticsType,
null: true,
description: 'Statistics of the project.'
- field :repository, Types::RepositoryType, null: true,
- description: 'Git repository of the project.'
+ field :repository, Types::RepositoryType,
+ null: true,
+ description: 'Git repository of the project.'
field :merge_requests,
Types::MergeRequestType.connection_type,
@@ -159,9 +244,10 @@ module Types
extras: [:lookahead],
resolver: Resolvers::IssueStatusCountsResolver
- field :milestones, Types::MilestoneType.connection_type, null: true,
- description: 'Milestones of the project.',
- resolver: Resolvers::ProjectMilestonesResolver
+ field :milestones, Types::MilestoneType.connection_type,
+ null: true,
+ description: 'Milestones of the project.',
+ resolver: Resolvers::ProjectMilestonesResolver
field :project_members,
description: 'Members of the project.',
@@ -179,6 +265,12 @@ module Types
description: 'A single environment of the project.',
resolver: Resolvers::EnvironmentsResolver.single
+ field :deployment,
+ Types::DeploymentDetailsType,
+ null: true,
+ description: 'Details of the deployment of the project.',
+ resolver: Resolvers::DeploymentResolver.single
+
field :issue,
Types::IssueType,
null: true,
@@ -201,164 +293,150 @@ module Types
description: 'Jobs of a project. This field can only be resolved for one project in any single request.',
resolver: Resolvers::ProjectJobsResolver
+ field :job,
+ type: Types::Ci::JobType,
+ null: true,
+ authorize: :read_build,
+ description: 'One job belonging to the project, selected by ID.' do
+ argument :id, Types::GlobalIDType[::CommitStatus],
+ required: true,
+ description: 'ID of the job.'
+ end
+
field :pipelines,
null: true,
description: 'Build pipelines of the project.',
extras: [:lookahead],
resolver: Resolvers::ProjectPipelinesResolver
- field :pipeline,
- Types::Ci::PipelineType,
+ field :pipeline, Types::Ci::PipelineType,
null: true,
description: 'Build pipeline of the project.',
extras: [:lookahead],
resolver: Resolvers::ProjectPipelineResolver
- field :pipeline_counts,
- Types::Ci::PipelineCountsType,
+ field :pipeline_counts, Types::Ci::PipelineCountsType,
null: true,
description: 'Build pipeline counts of the project.',
resolver: Resolvers::Ci::ProjectPipelineCountsResolver
- field :ci_variables,
- Types::Ci::ProjectVariableType.connection_type,
+ field :ci_variables, Types::Ci::ProjectVariableType.connection_type,
null: true,
description: "List of the project's CI/CD variables.",
authorize: :admin_build,
method: :variables
- field :ci_cd_settings,
- Types::Ci::CiCdSettingType,
+ field :ci_cd_settings, Types::Ci::CiCdSettingType,
null: true,
description: 'CI/CD settings for the project.'
- field :sentry_detailed_error,
- Types::ErrorTracking::SentryDetailedErrorType,
+ field :sentry_detailed_error, Types::ErrorTracking::SentryDetailedErrorType,
null: true,
description: 'Detailed version of a Sentry error on the project.',
resolver: Resolvers::ErrorTracking::SentryDetailedErrorResolver
- field :grafana_integration,
- Types::GrafanaIntegrationType,
+ field :grafana_integration, Types::GrafanaIntegrationType,
null: true,
description: 'Grafana integration details for the project.',
resolver: Resolvers::Projects::GrafanaIntegrationResolver
- field :snippets,
- Types::SnippetType.connection_type,
+ field :snippets, Types::SnippetType.connection_type,
null: true,
description: 'Snippets of the project.',
resolver: Resolvers::Projects::SnippetsResolver
- field :sentry_errors,
- Types::ErrorTracking::SentryErrorCollectionType,
+ field :sentry_errors, Types::ErrorTracking::SentryErrorCollectionType,
null: true,
description: 'Paginated collection of Sentry errors on the project.',
resolver: Resolvers::ErrorTracking::SentryErrorCollectionResolver
- field :boards,
- Types::BoardType.connection_type,
+ field :boards, Types::BoardType.connection_type,
null: true,
description: 'Boards of the project.',
max_page_size: 2000,
resolver: Resolvers::BoardsResolver
- field :recent_issue_boards,
- Types::BoardType.connection_type,
+ field :recent_issue_boards, Types::BoardType.connection_type,
null: true,
description: 'List of recently visited boards of the project. Maximum size is 4.',
resolver: Resolvers::RecentBoardsResolver
- field :board,
- Types::BoardType,
+ field :board, Types::BoardType,
null: true,
description: 'A single board of the project.',
resolver: Resolvers::BoardResolver
- field :jira_imports,
- Types::JiraImportType.connection_type,
+ field :jira_imports, Types::JiraImportType.connection_type,
null: true,
description: 'Jira imports into the project.'
- field :services,
- Types::Projects::ServiceType.connection_type,
+ field :services, Types::Projects::ServiceType.connection_type,
null: true,
description: 'Project services.',
resolver: Resolvers::Projects::ServicesResolver
- field :alert_management_alerts,
- Types::AlertManagement::AlertType.connection_type,
+ field :alert_management_alerts, Types::AlertManagement::AlertType.connection_type,
null: true,
description: 'Alert Management alerts of the project.',
extras: [:lookahead],
resolver: Resolvers::AlertManagement::AlertResolver
- field :alert_management_alert,
- Types::AlertManagement::AlertType,
+ field :alert_management_alert, Types::AlertManagement::AlertType,
null: true,
description: 'A single Alert Management alert of the project.',
resolver: Resolvers::AlertManagement::AlertResolver.single
- field :alert_management_alert_status_counts,
- Types::AlertManagement::AlertStatusCountsType,
+ field :alert_management_alert_status_counts, Types::AlertManagement::AlertStatusCountsType,
null: true,
description: 'Counts of alerts by status for the project.',
resolver: Resolvers::AlertManagement::AlertStatusCountsResolver
- field :alert_management_integrations,
- Types::AlertManagement::IntegrationType.connection_type,
+ field :alert_management_integrations, Types::AlertManagement::IntegrationType.connection_type,
null: true,
description: 'Integrations which can receive alerts for the project.',
resolver: Resolvers::AlertManagement::IntegrationsResolver
- field :alert_management_http_integrations,
- Types::AlertManagement::HttpIntegrationType.connection_type,
+ field :alert_management_http_integrations, Types::AlertManagement::HttpIntegrationType.connection_type,
null: true,
description: 'HTTP Integrations which can receive alerts for the project.',
resolver: Resolvers::AlertManagement::HttpIntegrationsResolver
- field :incident_management_timeline_events,
- Types::IncidentManagement::TimelineEventType.connection_type,
+ 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,
+ 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,
+ field :releases, Types::ReleaseType.connection_type,
null: true,
description: 'Releases of the project.',
resolver: Resolvers::ReleasesResolver
- field :release,
- Types::ReleaseType,
+ field :release, Types::ReleaseType,
null: true,
description: 'A single release of the project.',
resolver: Resolvers::ReleasesResolver.single,
authorize: :read_release
- field :container_expiration_policy,
- Types::ContainerExpirationPolicyType,
+ field :container_expiration_policy, Types::ContainerExpirationPolicyType,
null: true,
description: 'Container expiration policy of the project.'
- field :container_repositories,
- Types::ContainerRepositoryType.connection_type,
+ field :container_repositories, Types::ContainerRepositoryType.connection_type,
null: true,
description: 'Container repositories of the project.',
resolver: Resolvers::ContainerRepositoriesResolver
- field :container_repositories_count, GraphQL::Types::Int, null: false,
- description: 'Number of container repositories in the project.'
+ field :container_repositories_count, GraphQL::Types::Int,
+ null: false,
+ description: 'Number of container repositories in the project.'
- field :label,
- Types::LabelType,
+ field :label, Types::LabelType,
null: true,
description: 'Label available on this project.' do
argument :title, GraphQL::Types::String,
@@ -366,68 +444,63 @@ module Types
description: 'Title of the label.'
end
- field :terraform_state,
- Types::Terraform::StateType,
+ field :terraform_state, Types::Terraform::StateType,
null: true,
description: 'Find a single Terraform state by name.',
resolver: Resolvers::Terraform::StatesResolver.single
- field :terraform_states,
- Types::Terraform::StateType.connection_type,
+ field :terraform_states, Types::Terraform::StateType.connection_type,
null: true,
description: 'Terraform states associated with the project.',
resolver: Resolvers::Terraform::StatesResolver
- field :pipeline_analytics, Types::Ci::AnalyticsType, null: true,
- description: 'Pipeline analytics.',
- resolver: Resolvers::ProjectPipelineStatisticsResolver
+ field :pipeline_analytics, Types::Ci::AnalyticsType,
+ null: true,
+ description: 'Pipeline analytics.',
+ resolver: Resolvers::ProjectPipelineStatisticsResolver
- field :ci_template, Types::Ci::TemplateType, null: true,
- description: 'Find a single CI/CD template by name.',
- resolver: Resolvers::Ci::TemplateResolver
+ field :ci_template, Types::Ci::TemplateType,
+ null: true,
+ description: 'Find a single CI/CD template by name.',
+ resolver: Resolvers::Ci::TemplateResolver
- field :ci_job_token_scope, Types::Ci::JobTokenScopeType, null: true,
- description: 'The CI Job Tokens scope of access.',
- resolver: Resolvers::Ci::JobTokenScopeResolver
+ field :ci_job_token_scope, Types::Ci::JobTokenScopeType,
+ null: true,
+ description: 'The CI Job Tokens scope of access.',
+ resolver: Resolvers::Ci::JobTokenScopeResolver
- field :timelogs,
- Types::TimelogType.connection_type, null: true,
- description: 'Time logged on issues and merge requests in the project.',
- extras: [:lookahead],
- complexity: 5,
- resolver: ::Resolvers::TimelogResolver
+ field :timelogs, Types::TimelogType.connection_type,
+ null: true,
+ description: 'Time logged on issues and merge requests in the project.',
+ extras: [:lookahead],
+ complexity: 5,
+ resolver: ::Resolvers::TimelogResolver
- field :agent_configurations,
- ::Types::Kas::AgentConfigurationType.connection_type,
+ field :agent_configurations, ::Types::Kas::AgentConfigurationType.connection_type,
null: true,
description: 'Agent configurations defined by the project',
resolver: ::Resolvers::Kas::AgentConfigurationsResolver
- field :cluster_agent,
- ::Types::Clusters::AgentType,
+ field :cluster_agent, ::Types::Clusters::AgentType,
null: true,
description: 'Find a single cluster agent by name.',
resolver: ::Resolvers::Clusters::AgentsResolver.single
- field :cluster_agents,
- ::Types::Clusters::AgentType.connection_type,
+ field :cluster_agents, ::Types::Clusters::AgentType.connection_type,
extras: [:lookahead],
null: true,
description: 'Cluster agents associated with the project.',
resolver: ::Resolvers::Clusters::AgentsResolver
- field :merge_commit_template,
- GraphQL::Types::String,
+ field :merge_commit_template, GraphQL::Types::String,
null: true,
description: 'Template used to create merge commit message in merge requests.'
- field :squash_commit_template,
- GraphQL::Types::String,
+ field :squash_commit_template, GraphQL::Types::String,
null: true,
description: 'Template used to create squash commit message in merge requests.'
- field :labels,
- Types::LabelType.connection_type,
+ field :labels, Types::LabelType.connection_type,
null: true,
description: 'Labels available on this project.',
resolver: Resolvers::LabelsResolver
@@ -438,8 +511,7 @@ module Types
' Returns `null` if `work_items` feature flag is disabled.' \
' This flag is disabled by default, because the feature is experimental and is subject to change without notice.'
- field :timelog_categories,
- Types::TimeTracking::TimelogCategoryType.connection_type,
+ field :timelog_categories, Types::TimeTracking::TimelogCategoryType.connection_type,
null: true,
description: "Timelog categories for the project.",
alpha: { milestone: '15.3' }
@@ -448,6 +520,12 @@ module Types
resolver: Resolvers::Projects::ForkTargetsResolver,
description: 'Namespaces in which the current user can fork the project into.'
+ field :branch_rules,
+ Types::Projects::BranchRuleType.connection_type,
+ null: true,
+ description: "Branch rules configured for the project.",
+ resolver: Resolvers::Projects::BranchRulesResolver
+
def timelog_categories
object.project_namespace.timelog_categories if Feature.enabled?(:timelog_categories)
end
@@ -498,6 +576,21 @@ module Types
project.container_repositories.size
end
+ def ci_config_variables(sha:)
+ result = ::Ci::ListConfigVariablesService.new(object, context[:current_user]).execute(sha)
+
+ return if result.nil?
+
+ result.map do |var_key, var_config|
+ { key: var_key, **var_config }
+ end
+ end
+
+ def job(id:)
+ object.commit_statuses.find(id.model_id)
+ rescue ActiveRecord::RecordNotFound
+ end
+
def sast_ci_configuration
return unless Ability.allowed?(current_user, :download_code, object)
diff --git a/app/graphql/types/projects/branch_rule_type.rb b/app/graphql/types/projects/branch_rule_type.rb
new file mode 100644
index 00000000000..866cff0f439
--- /dev/null
+++ b/app/graphql/types/projects/branch_rule_type.rb
@@ -0,0 +1,33 @@
+# frozen_string_literal: true
+
+module Types
+ module Projects
+ class BranchRuleType < BaseObject
+ graphql_name 'BranchRule'
+ description 'List of branch rules for a project, grouped by branch name.'
+ accepts ::ProtectedBranch
+ authorize :read_protected_branch
+
+ field :name,
+ type: GraphQL::Types::String,
+ null: false,
+ description: 'Branch name, with wildcards, for the branch rules.'
+
+ field :branch_protection,
+ type: Types::BranchRules::BranchProtectionType,
+ null: false,
+ description: 'Branch protections configured for this branch rule.',
+ method: :itself
+
+ field :created_at,
+ Types::TimeType,
+ null: false,
+ description: 'Timestamp of when the branch rule was created.'
+
+ field :updated_at,
+ Types::TimeType,
+ null: false,
+ description: 'Timestamp of when the branch rule was last updated.'
+ end
+ end
+end
diff --git a/app/graphql/types/query_type.rb b/app/graphql/types/query_type.rb
index 84355390ea0..78463a1804a 100644
--- a/app/graphql/types/query_type.rb
+++ b/app/graphql/types/query_type.rb
@@ -67,7 +67,7 @@ module Types
end
field :package,
- description: 'Find a package.',
+ description: 'Find a package. This field can only be resolved for one query in any single request.',
resolver: Resolvers::PackageDetailsResolver
field :user, Types::UserType,
diff --git a/app/graphql/types/sort_direction_enum.rb b/app/graphql/types/sort_direction_enum.rb
new file mode 100644
index 00000000000..28dba1abfb6
--- /dev/null
+++ b/app/graphql/types/sort_direction_enum.rb
@@ -0,0 +1,11 @@
+# frozen_string_literal: true
+
+module Types
+ class SortDirectionEnum < BaseEnum
+ graphql_name 'SortDirectionEnum'
+ description 'Values for sort direction'
+
+ value 'ASC', 'Ascending order.', value: 'asc'
+ value 'DESC', 'Descending order.', value: 'desc'
+ end
+end
diff --git a/app/graphql/types/subscription_type.rb b/app/graphql/types/subscription_type.rb
index 9b5f028a857..ef701bbfc10 100644
--- a/app/graphql/types/subscription_type.rb
+++ b/app/graphql/types/subscription_type.rb
@@ -18,5 +18,12 @@ module Types
field :issuable_dates_updated, subscription: Subscriptions::IssuableUpdated, null: true,
description: 'Triggered when the due date or start date of an issuable is updated.'
+
+ field :merge_request_reviewers_updated,
+ subscription: Subscriptions::IssuableUpdated,
+ null: true,
+ description: 'Triggered when the reviewers of a merge request are updated.'
end
end
+
+Types::SubscriptionType.prepend_mod
diff --git a/app/graphql/types/timelog_type.rb b/app/graphql/types/timelog_type.rb
index c3fb9b77927..3856e1aa3b3 100644
--- a/app/graphql/types/timelog_type.rb
+++ b/app/graphql/types/timelog_type.rb
@@ -4,7 +4,7 @@ module Types
class TimelogType < BaseObject
graphql_name 'Timelog'
- authorize :read_issue
+ authorize :read_issuable
expose_permissions Types::PermissionTypes::Timelog
diff --git a/app/graphql/types/work_items/widgets/description_type.rb b/app/graphql/types/work_items/widgets/description_type.rb
index 4c365a67bfd..4861f7f46d8 100644
--- a/app/graphql/types/work_items/widgets/description_type.rb
+++ b/app/graphql/types/work_items/widgets/description_type.rb
@@ -13,8 +13,18 @@ module Types
implements Types::WorkItems::WidgetInterface
field :description, GraphQL::Types::String,
- null: true,
- description: 'Description of the work item.'
+ null: true,
+ description: 'Description of the work item.'
+ field :edited, GraphQL::Types::Boolean,
+ null: false,
+ description: 'Whether the description has been edited since the work item was created.',
+ method: :edited?
+ field :last_edited_at, Types::TimeType,
+ null: true,
+ description: 'Timestamp of when the work item\'s description was last edited.'
+ field :last_edited_by, Types::UserType,
+ null: true,
+ description: 'User that made the last edit to the work item\'s description.'
markdown_field :description_html, null: true do |resolved_object|
resolved_object.work_item