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:
authorGitLab Bot <gitlab-bot@gitlab.com>2023-10-19 15:57:54 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2023-10-19 15:57:54 +0300
commit419c53ec62de6e97a517abd5fdd4cbde3a942a34 (patch)
tree1f43a548b46bca8a5fb8fe0c31cef1883d49c5b6 /app/graphql
parent1da20d9135b3ad9e75e65b028bffc921aaf8deb7 (diff)
Add latest changes from gitlab-org/gitlab@16-5-stable-eev16.5.0-rc42
Diffstat (limited to 'app/graphql')
-rw-r--r--app/graphql/mutations/achievements/update_user_achievement_priorities.rb37
-rw-r--r--app/graphql/mutations/ci/job/retry.rb6
-rw-r--r--app/graphql/mutations/merge_requests/accept.rb4
-rw-r--r--app/graphql/mutations/packages/protection/rule/create.rb60
-rw-r--r--app/graphql/mutations/users/set_namespace_commit_email.rb2
-rw-r--r--app/graphql/mutations/work_items/linked_items/add.rb2
-rw-r--r--app/graphql/mutations/work_items/linked_items/base.rb5
-rw-r--r--app/graphql/mutations/work_items/update.rb12
-rw-r--r--app/graphql/resolvers/achievements/user_achievements_for_user_resolver.rb13
-rw-r--r--app/graphql/resolvers/admin/analytics/usage_trends/measurements_resolver.rb2
-rw-r--r--app/graphql/resolvers/analytics/cycle_analytics/base_issue_resolver.rb2
-rw-r--r--app/graphql/resolvers/base_resolver.rb28
-rw-r--r--app/graphql/resolvers/blobs_resolver.rb2
-rw-r--r--app/graphql/resolvers/ci/config_resolver.rb13
-rw-r--r--app/graphql/resolvers/clusters/agent_tokens_resolver.rb2
-rw-r--r--app/graphql/resolvers/concerns/caching_array_resolver.rb2
-rw-r--r--app/graphql/resolvers/concerns/work_items/look_ahead_preloads.rb6
-rw-r--r--app/graphql/resolvers/error_tracking/sentry_errors_resolver.rb5
-rw-r--r--app/graphql/resolvers/group_issues_resolver.rb8
-rw-r--r--app/graphql/resolvers/issues_resolver.rb8
-rw-r--r--app/graphql/resolvers/kas/agent_configurations_resolver.rb2
-rw-r--r--app/graphql/resolvers/last_commit_resolver.rb2
-rw-r--r--app/graphql/resolvers/merge_request_pipelines_resolver.rb4
-rw-r--r--app/graphql/resolvers/noteable/notes_resolver.rb21
-rw-r--r--app/graphql/resolvers/package_pipelines_resolver.rb11
-rw-r--r--app/graphql/resolvers/paginated_tree_resolver.rb5
-rw-r--r--app/graphql/resolvers/project_packages_protection_rules_resolver.rb15
-rw-r--r--app/graphql/resolvers/projects_resolver.rb2
-rw-r--r--app/graphql/resolvers/user_notes_count_resolver.rb2
-rw-r--r--app/graphql/resolvers/work_items/ancestors_resolver.rb58
-rw-r--r--app/graphql/resolvers/work_items/linked_items_resolver.rb2
-rw-r--r--app/graphql/resolvers/work_items/work_item_discussions_resolver.rb6
-rw-r--r--app/graphql/types/achievements/user_achievement_type.rb5
-rw-r--r--app/graphql/types/base_argument.rb1
-rw-r--r--app/graphql/types/base_enum.rb6
-rw-r--r--app/graphql/types/base_field.rb19
-rw-r--r--app/graphql/types/ci/ci_cd_setting_type.rb6
-rw-r--r--app/graphql/types/ci/detailed_status_type.rb24
-rw-r--r--app/graphql/types/ci/job_trace_type.rb2
-rw-r--r--app/graphql/types/ci/pipeline_type.rb23
-rw-r--r--app/graphql/types/clusters/agent_type.rb2
-rw-r--r--app/graphql/types/custom_emoji_type.rb2
-rw-r--r--app/graphql/types/error_tracking/sentry_error_collection_type.rb3
-rw-r--r--app/graphql/types/issues/negated_issue_filter_input_type.rb2
-rw-r--r--app/graphql/types/merge_request_type.rb6
-rw-r--r--app/graphql/types/merge_requests/mergeability_check_identifier_enum.rb18
-rw-r--r--app/graphql/types/merge_requests/mergeability_check_status_enum.rb22
-rw-r--r--app/graphql/types/merge_requests/mergeability_check_type.rb28
-rw-r--r--app/graphql/types/mutation_type.rb2
-rw-r--r--app/graphql/types/namespace_type.rb2
-rw-r--r--app/graphql/types/notes/note_type.rb2
-rw-r--r--app/graphql/types/packages/helm/dependency_type.rb2
-rw-r--r--app/graphql/types/packages/helm/metadata_type.rb8
-rw-r--r--app/graphql/types/packages/package_base_type.rb1
-rw-r--r--app/graphql/types/packages/package_type.rb1
-rw-r--r--app/graphql/types/packages/protection/rule_access_level_enum.rb17
-rw-r--r--app/graphql/types/packages/protection/rule_package_type_enum.rb17
-rw-r--r--app/graphql/types/packages/protection/rule_type.rb33
-rw-r--r--app/graphql/types/project_type.rb8
-rw-r--r--app/graphql/types/query_type.rb4
-rw-r--r--app/graphql/types/repository_type.rb1
-rw-r--r--app/graphql/types/security/codequality_reports_comparer_type.rb2
-rw-r--r--app/graphql/types/snippet_type.rb5
-rw-r--r--app/graphql/types/todo_action_enum.rb1
-rw-r--r--app/graphql/types/user_interface.rb2
-rw-r--r--app/graphql/types/user_state_enum.rb9
-rw-r--r--app/graphql/types/user_type.rb3
-rw-r--r--app/graphql/types/work_item_type.rb10
-rw-r--r--app/graphql/types/work_items/widgets/hierarchy_type.rb6
-rw-r--r--app/graphql/types/work_items/widgets/notes_type.rb3
70 files changed, 542 insertions, 115 deletions
diff --git a/app/graphql/mutations/achievements/update_user_achievement_priorities.rb b/app/graphql/mutations/achievements/update_user_achievement_priorities.rb
new file mode 100644
index 00000000000..077b4810fdc
--- /dev/null
+++ b/app/graphql/mutations/achievements/update_user_achievement_priorities.rb
@@ -0,0 +1,37 @@
+# frozen_string_literal: true
+
+module Mutations
+ module Achievements
+ class UpdateUserAchievementPriorities < BaseMutation
+ graphql_name 'UserAchievementPrioritiesUpdate'
+
+ field :user_achievements,
+ [::Types::Achievements::UserAchievementType],
+ null: false,
+ description: 'Updated user achievements.'
+
+ argument :user_achievement_ids,
+ [::Types::GlobalIDType[::Achievements::UserAchievement]],
+ required: true,
+ description: 'Global IDs of the user achievements being prioritized, ' \
+ 'ordered from highest to lowest priority.'
+
+ def resolve(args)
+ user_achievements = args.delete(:user_achievement_ids).map { |id| find_object(id) }
+
+ user_achievements.each do |user_achievement|
+ unless Ability.allowed?(current_user, :update_owned_user_achievement, user_achievement)
+ raise_resource_not_available_error!
+ end
+ end
+
+ result = ::Achievements::UpdateUserAchievementPrioritiesService.new(current_user, user_achievements).execute
+ { user_achievements: result.payload, errors: result.errors }
+ end
+
+ def find_object(id)
+ ::Gitlab::Graphql::Lazy.force(GitlabSchema.object_from_id(id, expected_type: ::Achievements::UserAchievement))
+ end
+ end
+ end
+end
diff --git a/app/graphql/mutations/ci/job/retry.rb b/app/graphql/mutations/ci/job/retry.rb
index bfb9b902cc5..5ccc33de33e 100644
--- a/app/graphql/mutations/ci/job/retry.rb
+++ b/app/graphql/mutations/ci/job/retry.rb
@@ -6,6 +6,12 @@ module Mutations
class Retry < Base
graphql_name 'JobRetry'
+ JobID = ::Types::GlobalIDType[::Ci::Processable]
+
+ argument :id, JobID,
+ required: true,
+ description: 'ID of the job to mutate.'
+
field :job,
Types::Ci::JobType,
null: true,
diff --git a/app/graphql/mutations/merge_requests/accept.rb b/app/graphql/mutations/merge_requests/accept.rb
index 64572091379..220ebea22c7 100644
--- a/app/graphql/mutations/merge_requests/accept.rb
+++ b/app/graphql/mutations/merge_requests/accept.rb
@@ -7,7 +7,7 @@ module Mutations
authorize :accept_merge_request
description <<~DESC
Accepts a merge request.
- When accepted, the source branch will be merged into the target branch, either
+ When accepted, the source branch will be scheduled to merge into the target branch, either
immediately if possible, or using one of the automatic merge strategies.
DESC
@@ -59,7 +59,7 @@ module Mutations
service = AutoMergeService.new(project, current_user, merge_params)
service.execute(merge_request, merge_params[:auto_merge_strategy])
else
- merge_service.execute(merge_request)
+ merge_request.merge_async(current_user.id, merge_params)
end
{
diff --git a/app/graphql/mutations/packages/protection/rule/create.rb b/app/graphql/mutations/packages/protection/rule/create.rb
new file mode 100644
index 00000000000..36eaec334d6
--- /dev/null
+++ b/app/graphql/mutations/packages/protection/rule/create.rb
@@ -0,0 +1,60 @@
+# frozen_string_literal: true
+
+module Mutations
+ module Packages
+ module Protection
+ module Rule
+ class Create < ::Mutations::BaseMutation
+ graphql_name 'CreatePackagesProtectionRule'
+ description 'Creates a protection rule to restrict access to project packages. ' \
+ 'Available only when feature flag `packages_protected_packages` is enabled.'
+
+ include FindsProject
+
+ authorize :admin_package
+
+ argument :project_path,
+ GraphQL::Types::ID,
+ required: true,
+ description: 'Full path of the project where a protection rule is located.'
+
+ argument :package_name_pattern,
+ GraphQL::Types::String,
+ required: true,
+ description:
+ 'Package name protected by the protection rule. For example `@my-scope/my-package-*`. ' \
+ 'Wildcard character `*` allowed.'
+
+ argument :package_type,
+ Types::Packages::Protection::RulePackageTypeEnum,
+ required: true,
+ description: 'Package type protected by the protection rule. For example `NPM`.'
+
+ argument :push_protected_up_to_access_level,
+ Types::Packages::Protection::RuleAccessLevelEnum,
+ required: true,
+ description:
+ 'Max GitLab access level unable to push a package. For example `DEVELOPER`, `MAINTAINER`, `OWNER`.'
+
+ field :package_protection_rule,
+ Types::Packages::Protection::RuleType,
+ null: true,
+ description: 'Packages protection rule after mutation.'
+
+ def resolve(project_path:, **kwargs)
+ project = authorized_find!(project_path)
+
+ if Feature.disabled?(:packages_protected_packages, project)
+ raise_resource_not_available_error!("'packages_protected_packages' feature flag is disabled")
+ end
+
+ response = ::Packages::Protection::CreateRuleService.new(project: project, current_user: current_user,
+ params: kwargs).execute
+
+ { package_protection_rule: response.payload[:package_protection_rule], errors: response.errors }
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/app/graphql/mutations/users/set_namespace_commit_email.rb b/app/graphql/mutations/users/set_namespace_commit_email.rb
index 72ef0635bb3..db1c33595f2 100644
--- a/app/graphql/mutations/users/set_namespace_commit_email.rb
+++ b/app/graphql/mutations/users/set_namespace_commit_email.rb
@@ -20,7 +20,7 @@ module Mutations
null: true,
description: 'User namespace commit email after mutation.'
- authorize :read_namespace
+ authorize :read_namespace_via_membership
def resolve(args)
namespace = authorized_find!(args[:namespace_id])
diff --git a/app/graphql/mutations/work_items/linked_items/add.rb b/app/graphql/mutations/work_items/linked_items/add.rb
index e0c17a61205..4029d17d4ac 100644
--- a/app/graphql/mutations/work_items/linked_items/add.rb
+++ b/app/graphql/mutations/work_items/linked_items/add.rb
@@ -16,8 +16,6 @@ module Mutations
private
def update_links(work_item, params)
- Gitlab::QueryLimiting.disable!('https://gitlab.com/gitlab-org/gitlab/-/issues/419555')
-
gids = params.delete(:work_items_ids)
work_items = begin
GitlabSchema.parse_gids(gids, expected_type: ::WorkItem).map(&:find)
diff --git a/app/graphql/mutations/work_items/linked_items/base.rb b/app/graphql/mutations/work_items/linked_items/base.rb
index a1d9bced930..8a6201ffdf7 100644
--- a/app/graphql/mutations/work_items/linked_items/base.rb
+++ b/app/graphql/mutations/work_items/linked_items/base.rb
@@ -5,8 +5,7 @@ module Mutations
module LinkedItems
class Base < BaseMutation
# Limit maximum number of items that can be linked at a time to avoid overloading the DB
- # See https://gitlab.com/gitlab-org/gitlab/-/issues/419555
- MAX_WORK_ITEMS = 3
+ MAX_WORK_ITEMS = 10
argument :id, ::Types::GlobalIDType[::WorkItem],
required: true, description: 'Global ID of the work item.'
@@ -33,7 +32,7 @@ module Mutations
def resolve(**args)
work_item = authorized_find!(id: args.delete(:id))
- raise_resource_not_available_error! unless work_item.project.linked_work_items_feature_flag_enabled?
+ raise_resource_not_available_error! unless work_item.resource_parent.linked_work_items_feature_flag_enabled?
service_response = update_links(work_item, args)
diff --git a/app/graphql/mutations/work_items/update.rb b/app/graphql/mutations/work_items/update.rb
index f22e9bcf393..228a9e52355 100644
--- a/app/graphql/mutations/work_items/update.rb
+++ b/app/graphql/mutations/work_items/update.rb
@@ -10,7 +10,7 @@ module Mutations
include Mutations::WorkItems::UpdateArguments
include Mutations::WorkItems::Widgetable
- authorize :update_work_item
+ authorize :read_work_item
field :work_item, Types::WorkItemType,
null: true,
@@ -22,11 +22,13 @@ module Mutations
work_item = authorized_find!(id: id)
widget_params = extract_widget_params!(work_item.work_item_type, attributes)
-
interpret_quick_actions!(work_item, current_user, widget_params, attributes)
+ # Only checks permissions for base attributes because widgets define their own permissions independently
+ raise_resource_not_available_error! unless attributes.empty? || can_update?(work_item)
+
update_result = ::WorkItems::UpdateService.new(
- container: work_item.project,
+ container: work_item.resource_parent,
current_user: current_user,
params: attributes,
widget_params: widget_params,
@@ -62,6 +64,10 @@ module Mutations
widget_params.merge!(parsed_params[:widgets])
attributes.merge!(parsed_params[:common])
end
+
+ def can_update?(work_item)
+ current_user.can?(:update_work_item, work_item)
+ end
end
end
end
diff --git a/app/graphql/resolvers/achievements/user_achievements_for_user_resolver.rb b/app/graphql/resolvers/achievements/user_achievements_for_user_resolver.rb
new file mode 100644
index 00000000000..673babcf14a
--- /dev/null
+++ b/app/graphql/resolvers/achievements/user_achievements_for_user_resolver.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+module Resolvers
+ module Achievements
+ # rubocop:disable Graphql/ResolverType -- the type is inherited from the parent class
+ class UserAchievementsForUserResolver < UserAchievementsResolver
+ def resolve_with_lookahead
+ super.order_by_priority_asc
+ end
+ end
+ # rubocop:enable Graphql/ResolverType
+ end
+end
diff --git a/app/graphql/resolvers/admin/analytics/usage_trends/measurements_resolver.rb b/app/graphql/resolvers/admin/analytics/usage_trends/measurements_resolver.rb
index b5a19d38b9c..0c9607d9413 100644
--- a/app/graphql/resolvers/admin/analytics/usage_trends/measurements_resolver.rb
+++ b/app/graphql/resolvers/admin/analytics/usage_trends/measurements_resolver.rb
@@ -7,7 +7,7 @@ module Resolvers
class MeasurementsResolver < BaseResolver
include Gitlab::Graphql::Authorize::AuthorizeResource
- type Types::Admin::Analytics::UsageTrends::MeasurementType, null: true
+ type Types::Admin::Analytics::UsageTrends::MeasurementType.connection_type, null: true
argument :identifier, Types::Admin::Analytics::UsageTrends::MeasurementIdentifierEnum,
required: true,
diff --git a/app/graphql/resolvers/analytics/cycle_analytics/base_issue_resolver.rb b/app/graphql/resolvers/analytics/cycle_analytics/base_issue_resolver.rb
index 8128023aecb..768265752d5 100644
--- a/app/graphql/resolvers/analytics/cycle_analytics/base_issue_resolver.rb
+++ b/app/graphql/resolvers/analytics/cycle_analytics/base_issue_resolver.rb
@@ -48,3 +48,5 @@ module Resolvers
end
end
end
+
+Resolvers::Analytics::CycleAnalytics::BaseIssueResolver.prepend_mod
diff --git a/app/graphql/resolvers/base_resolver.rb b/app/graphql/resolvers/base_resolver.rb
index 6f847221f1b..17db91a685f 100644
--- a/app/graphql/resolvers/base_resolver.rb
+++ b/app/graphql/resolvers/base_resolver.rb
@@ -11,26 +11,25 @@ module Resolvers
@requires_argument = true
end
+ def self.requires_argument?
+ !!@requires_argument
+ end
+
def self.calls_gitaly!
@calls_gitaly = true
end
+ def self.calls_gitaly?
+ !!@calls_gitaly
+ end
+
# This is a flag to allow us to use `complexity_multiplier` to compute complexity for connection
# fields(see BaseField#connection_complexity_multiplier) in resolvers that do external connection pagination,
- # thus disabling the default `connection` option(see self.field_options method above).
+ # thus disabling the default `connection` option.
def self.calculate_ext_conn_complexity
false
end
- def self.field_options
- extra_options = {
- requires_argument: @requires_argument,
- calls_gitaly: @calls_gitaly
- }.compact
-
- super.merge(extra_options)
- end
-
def self.singular_type
return unless type
@@ -63,8 +62,13 @@ module Resolvers
type parent.singular_type, null: true
def ready?(**args)
- ready, early_return = super
- [ready, select_result(early_return)]
+ value = super
+
+ if value.is_a?(Array)
+ [value[0], select_result(value[1])]
+ else
+ value
+ end
end
def resolve(**args)
diff --git a/app/graphql/resolvers/blobs_resolver.rb b/app/graphql/resolvers/blobs_resolver.rb
index 546eeb76ff5..27a15381b43 100644
--- a/app/graphql/resolvers/blobs_resolver.rb
+++ b/app/graphql/resolvers/blobs_resolver.rb
@@ -36,7 +36,7 @@ module Resolvers
ref ||= repository.root_ref
validate_ref(ref)
- ref = ExtractsRef.qualify_ref(ref, ref_type)
+ ref = ExtractsRef::RefExtractor.qualify_ref(ref, ref_type)
repository.blobs_at(paths.map { |path| [ref, path] }).tap do |blobs|
blobs.each do |blob|
diff --git a/app/graphql/resolvers/ci/config_resolver.rb b/app/graphql/resolvers/ci/config_resolver.rb
index ec6ede58cf5..8c85a6aebea 100644
--- a/app/graphql/resolvers/ci/config_resolver.rb
+++ b/app/graphql/resolvers/ci/config_resolver.rb
@@ -30,11 +30,20 @@ module Resolvers
required: false,
description: 'Run pipeline creation simulation, or only do static check.'
- def resolve(project_path:, content:, sha: nil, dry_run: false)
+ argument :skip_verify_project_sha, GraphQL::Types::Boolean,
+ required: false,
+ alpha: { milestone: '16.5' },
+ description: "If the provided `sha` is found in the project's repository but is not " \
+ "associated with a Git reference (a detached commit), the verification fails and a " \
+ "validation error is returned. Otherwise, verification passes, even if the `sha` is " \
+ "invalid. Set to `true` to skip this verification process."
+
+ def resolve(project_path:, content:, sha: nil, dry_run: false, skip_verify_project_sha: false)
project = authorized_find!(project_path: project_path)
result = ::Gitlab::Ci::Lint
- .new(project: project, current_user: context[:current_user], sha: sha)
+ .new(project: project, current_user: context[:current_user], sha: sha,
+ verify_project_sha: !skip_verify_project_sha)
.validate(content, dry_run: dry_run)
response(result)
diff --git a/app/graphql/resolvers/clusters/agent_tokens_resolver.rb b/app/graphql/resolvers/clusters/agent_tokens_resolver.rb
index 0b9422db2a9..313d71aa345 100644
--- a/app/graphql/resolvers/clusters/agent_tokens_resolver.rb
+++ b/app/graphql/resolvers/clusters/agent_tokens_resolver.rb
@@ -3,7 +3,7 @@
module Resolvers
module Clusters
class AgentTokensResolver < BaseResolver
- type Types::Clusters::AgentTokenType, null: true
+ type Types::Clusters::AgentTokenType.connection_type, null: true
alias_method :agent, :object
diff --git a/app/graphql/resolvers/concerns/caching_array_resolver.rb b/app/graphql/resolvers/concerns/caching_array_resolver.rb
index 62649518142..15bf9a90e46 100644
--- a/app/graphql/resolvers/concerns/caching_array_resolver.rb
+++ b/app/graphql/resolvers/concerns/caching_array_resolver.rb
@@ -22,7 +22,7 @@
#
# **important**: If the cardinality of your collection is likely to be greater than 100,
# then you will want to pass `max_page_size:` as part of the field definition
-# or (ideally) as part of the resolver `field_options`.
+# or (ideally) set `max_page_size` in the resolver.
#
# How to implement:
# --------------------
diff --git a/app/graphql/resolvers/concerns/work_items/look_ahead_preloads.rb b/app/graphql/resolvers/concerns/work_items/look_ahead_preloads.rb
index 92fb9ec5cef..71833fbd2b9 100644
--- a/app/graphql/resolvers/concerns/work_items/look_ahead_preloads.rb
+++ b/app/graphql/resolvers/concerns/work_items/look_ahead_preloads.rb
@@ -14,7 +14,8 @@ module WorkItems
{
work_item_type: :work_item_type,
web_url: { namespace: :route, project: [:project_namespace, { namespace: :route }] },
- widgets: { work_item_type: :enabled_widget_definitions }
+ widgets: { work_item_type: :enabled_widget_definitions },
+ archived: :project
}
end
@@ -48,7 +49,8 @@ module WorkItems
{
project: [:project_feature, :group]
},
- :author
+ :author,
+ *super
]
end
end
diff --git a/app/graphql/resolvers/error_tracking/sentry_errors_resolver.rb b/app/graphql/resolvers/error_tracking/sentry_errors_resolver.rb
index 793b73342ab..187cb15ccc5 100644
--- a/app/graphql/resolvers/error_tracking/sentry_errors_resolver.rb
+++ b/app/graphql/resolvers/error_tracking/sentry_errors_resolver.rb
@@ -4,7 +4,6 @@ module Resolvers
module ErrorTracking
class SentryErrorsResolver < BaseResolver
type Types::ErrorTracking::SentryErrorType.connection_type, null: true
- extension Gitlab::Graphql::Extensions::ExternallyPaginatedArrayExtension
argument :search_term, ::GraphQL::Types::String,
description: 'Search query for the Sentry error details.',
@@ -31,10 +30,6 @@ module Resolvers
Gitlab::Graphql::ExternallyPaginatedArray.new(previous_cursor, next_cursor, *issues)
end
-
- def self.field_options
- super.merge(connection: false) # we manage the pagination manually, so opt out of the connection field extension
- end
end
end
end
diff --git a/app/graphql/resolvers/group_issues_resolver.rb b/app/graphql/resolvers/group_issues_resolver.rb
index 7bbc662c6c8..5e0fb27bafa 100644
--- a/app/graphql/resolvers/group_issues_resolver.rb
+++ b/app/graphql/resolvers/group_issues_resolver.rb
@@ -11,7 +11,11 @@ module Resolvers
before_connection_authorization do |nodes, _|
projects = nodes.map(&:project)
- ActiveRecord::Associations::Preloader.new(records: projects, associations: :namespace).call
+ ActiveRecord::Associations::Preloader.new(records: projects, associations: project_associations).call
+ end
+
+ def self.project_associations
+ [:namespace]
end
def ready?(**args)
@@ -24,3 +28,5 @@ module Resolvers
end
end
# rubocop:enable Graphql/ResolverType
+
+Resolvers::GroupIssuesResolver.prepend_mod
diff --git a/app/graphql/resolvers/issues_resolver.rb b/app/graphql/resolvers/issues_resolver.rb
index 589366ba26d..34f14eee0e5 100644
--- a/app/graphql/resolvers/issues_resolver.rb
+++ b/app/graphql/resolvers/issues_resolver.rb
@@ -23,7 +23,11 @@ module Resolvers
projects = nodes.map(&:project)
::Preloaders::UserMaxAccessLevelInProjectsPreloader.new(projects, current_user).execute
::Preloaders::GroupPolicyPreloader.new(projects.filter_map(&:group), current_user).execute
- ActiveRecord::Associations::Preloader.new(records: projects, associations: :namespace).call
+ ActiveRecord::Associations::Preloader.new(records: projects, associations: project_associations).call
+ end
+
+ def self.project_associations
+ [:namespace]
end
def ready?(**args)
@@ -62,3 +66,5 @@ module Resolvers
end
end
end
+
+Resolvers::IssuesResolver.prepend_mod
diff --git a/app/graphql/resolvers/kas/agent_configurations_resolver.rb b/app/graphql/resolvers/kas/agent_configurations_resolver.rb
index 74c5cbe55f1..6e35f64c2ee 100644
--- a/app/graphql/resolvers/kas/agent_configurations_resolver.rb
+++ b/app/graphql/resolvers/kas/agent_configurations_resolver.rb
@@ -3,7 +3,7 @@
module Resolvers
module Kas
class AgentConfigurationsResolver < BaseResolver
- type Types::Kas::AgentConfigurationType, null: true
+ type Types::Kas::AgentConfigurationType.connection_type, null: true
# Calls Gitaly via KAS
calls_gitaly!
diff --git a/app/graphql/resolvers/last_commit_resolver.rb b/app/graphql/resolvers/last_commit_resolver.rb
index acf7826ab13..ff5701ede8c 100644
--- a/app/graphql/resolvers/last_commit_resolver.rb
+++ b/app/graphql/resolvers/last_commit_resolver.rb
@@ -12,7 +12,7 @@ module Resolvers
# Ensure merge commits can be returned by sending nil to Gitaly instead of '/'
path = tree.path == '/' ? nil : tree.path
commit = Gitlab::Git::Commit.last_for_path(tree.repository,
- ExtractsRef.qualify_ref(tree.sha, tree.ref_type), path, literal_pathspec: true)
+ ExtractsRef::RefExtractor.qualify_ref(tree.sha, tree.ref_type), path, literal_pathspec: true)
::Commit.new(commit, tree.repository.project) if commit
end
diff --git a/app/graphql/resolvers/merge_request_pipelines_resolver.rb b/app/graphql/resolvers/merge_request_pipelines_resolver.rb
index deb698c63e1..45159e0edd5 100644
--- a/app/graphql/resolvers/merge_request_pipelines_resolver.rb
+++ b/app/graphql/resolvers/merge_request_pipelines_resolver.rb
@@ -11,9 +11,7 @@ module Resolvers
# Return at most 500 pipelines for each MR.
# Merge requests generally have many fewer pipelines than this.
- def self.field_options
- super.merge(max_page_size: 500)
- end
+ max_page_size 500
def resolve(**args)
return unless project
diff --git a/app/graphql/resolvers/noteable/notes_resolver.rb b/app/graphql/resolvers/noteable/notes_resolver.rb
index 0d25c747ffb..b4bd1068723 100644
--- a/app/graphql/resolvers/noteable/notes_resolver.rb
+++ b/app/graphql/resolvers/noteable/notes_resolver.rb
@@ -7,6 +7,11 @@ module Resolvers
type Types::Notes::NoteType.connection_type, null: false
+ argument :filter, Types::WorkItems::NotesFilterTypeEnum,
+ required: false,
+ default_value: ::UserPreference::NOTES_FILTERS[:all_notes],
+ description: 'Type of notes collection: ALL_NOTES, ONLY_COMMENTS, ONLY_ACTIVITY.'
+
before_connection_authorization do |nodes, current_user|
next if nodes.blank?
@@ -16,8 +21,9 @@ module Resolvers
::Preloaders::Projects::NotesPreloader.new(project, current_user).call(nodes)
end
- def resolve_with_lookahead(*)
- apply_lookahead(object.notes.fresh)
+ def resolve_with_lookahead(**args)
+ notes = NotesFinder.new(current_user, build_params(args)).execute
+ apply_lookahead(notes)
end
private
@@ -31,6 +37,17 @@ module Resolvers
award_emoji: [:award_emoji]
}
end
+
+ def build_params(args)
+ params = {
+ project: object.project,
+ target: object
+ }
+
+ params[:notes_filter] = args[:filter] if args[:filter].present?
+
+ params
+ end
end
end
end
diff --git a/app/graphql/resolvers/package_pipelines_resolver.rb b/app/graphql/resolvers/package_pipelines_resolver.rb
index 7f610915489..40e5456164a 100644
--- a/app/graphql/resolvers/package_pipelines_resolver.rb
+++ b/app/graphql/resolvers/package_pipelines_resolver.rb
@@ -5,7 +5,7 @@ module Resolvers
include Gitlab::Graphql::Authorize::AuthorizeResource
type Types::Ci::PipelineType.connection_type, null: true
- extension Gitlab::Graphql::Extensions::ExternallyPaginatedArrayExtension
+ extras [:lookahead]
authorizes_object!
authorize :read_pipeline
@@ -41,14 +41,6 @@ module Resolvers
end
end
- # we manage the pagination manually, so opt out of the connection field extension
- def self.field_options
- super.merge(
- connection: false,
- extras: [:lookahead]
- )
- end
-
private
def lazy_load_pipeline(id)
@@ -59,6 +51,7 @@ module Resolvers
def default_value_for(first:, last:, after:, before:)
Gitlab::Graphql::Pagination::ActiveRecordArrayConnection.new(
[],
+ context: context,
first: first,
last: last,
after: after,
diff --git a/app/graphql/resolvers/paginated_tree_resolver.rb b/app/graphql/resolvers/paginated_tree_resolver.rb
index de48fbafb04..48c94c144dd 100644
--- a/app/graphql/resolvers/paginated_tree_resolver.rb
+++ b/app/graphql/resolvers/paginated_tree_resolver.rb
@@ -3,7 +3,6 @@
module Resolvers
class PaginatedTreeResolver < BaseResolver
type Types::Tree::TreeType.connection_type, null: true
- extension Gitlab::Graphql::Extensions::ExternallyPaginatedArrayExtension
calls_gitaly!
@@ -50,9 +49,5 @@ module Resolvers
extensions: { code: e.code, gitaly_code: e.status, service: e.service }
)
end
-
- def self.field_options
- super.merge(connection: false) # we manage the pagination manually, so opt out of the connection field extension
- end
end
end
diff --git a/app/graphql/resolvers/project_packages_protection_rules_resolver.rb b/app/graphql/resolvers/project_packages_protection_rules_resolver.rb
new file mode 100644
index 00000000000..5d3d0fbf79d
--- /dev/null
+++ b/app/graphql/resolvers/project_packages_protection_rules_resolver.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+module Resolvers
+ class ProjectPackagesProtectionRulesResolver < BaseResolver
+ type Types::Packages::Protection::RuleType.connection_type, null: true
+
+ alias_method :project, :object
+
+ def resolve(**_args)
+ return [] if Feature.disabled?(:packages_protected_packages, project)
+
+ project.package_protection_rules
+ end
+ end
+end
diff --git a/app/graphql/resolvers/projects_resolver.rb b/app/graphql/resolvers/projects_resolver.rb
index 08981f2c441..8dd409a8173 100644
--- a/app/graphql/resolvers/projects_resolver.rb
+++ b/app/graphql/resolvers/projects_resolver.rb
@@ -4,7 +4,7 @@ module Resolvers
class ProjectsResolver < BaseResolver
include ProjectSearchArguments
- type Types::ProjectType, null: true
+ type Types::ProjectType.connection_type, null: true
argument :ids, [GraphQL::Types::ID],
required: false,
diff --git a/app/graphql/resolvers/user_notes_count_resolver.rb b/app/graphql/resolvers/user_notes_count_resolver.rb
index b91815c72f5..ebc54a1c6e8 100644
--- a/app/graphql/resolvers/user_notes_count_resolver.rb
+++ b/app/graphql/resolvers/user_notes_count_resolver.rb
@@ -20,7 +20,7 @@ module Resolvers
def authorized_resource?(object)
ability = "read_#{object.class.name.underscore}".to_sym
- context[:current_user].present? && Ability.allowed?(context[:current_user], ability, object)
+ Ability.allowed?(context[:current_user], ability, object)
end
end
end
diff --git a/app/graphql/resolvers/work_items/ancestors_resolver.rb b/app/graphql/resolvers/work_items/ancestors_resolver.rb
new file mode 100644
index 00000000000..33adbfc9c86
--- /dev/null
+++ b/app/graphql/resolvers/work_items/ancestors_resolver.rb
@@ -0,0 +1,58 @@
+# frozen_string_literal: true
+
+module Resolvers
+ module WorkItems
+ class AncestorsResolver < BaseResolver
+ prepend ::WorkItems::LookAheadPreloads
+
+ type Types::WorkItemType.connection_type, null: true
+
+ def resolve_with_lookahead
+ ancestors = object.ancestors
+ return WorkItem.none unless ancestors
+
+ truncate_ancestors(apply_lookahead(ancestors)).reverse!
+ end
+
+ private
+
+ def truncate_ancestors(ancestors)
+ # Iterate from closest ancestor until root or first missing ancestor
+ authorized = authorized_ancestors(ancestors)
+
+ previous_ancestor = object.work_item
+ authorized.take_while do |ancestor|
+ is_direct_parent = previous_ancestor.work_item_parent.id == ancestor.id
+ previous_ancestor = ancestor
+
+ is_direct_parent
+ end
+ end
+
+ def authorized_ancestors(ancestors)
+ preload_resource_parents(ancestors)
+
+ DeclarativePolicy.user_scope do
+ ancestors.select { |ancestor| Ability.allowed?(current_user, :read_work_item, ancestor) }
+ end
+ end
+
+ def preload_resource_parents(work_items)
+ projects = work_items.filter_map(&:project)
+ namespaces = work_items.filter_map(&:namespace)
+ group_namespaces = namespaces.select { |n| n.type == ::Group.sti_name }
+
+ ::Preloaders::GroupPolicyPreloader.new(group_namespaces, current_user).execute if group_namespaces.any?
+ return unless projects.any?
+
+ ::Preloaders::UserMaxAccessLevelInProjectsPreloader.new(projects, current_user).execute
+ ::Preloaders::GroupPolicyPreloader.new(projects.filter_map(&:namespace), current_user).execute
+ ActiveRecord::Associations::Preloader.new(records: projects, associations: [:namespace]).call
+ end
+
+ def unconditional_includes
+ [:namespace, :work_item_parent, :work_item_type]
+ end
+ end
+ end
+end
diff --git a/app/graphql/resolvers/work_items/linked_items_resolver.rb b/app/graphql/resolvers/work_items/linked_items_resolver.rb
index 35a6974163a..108d5d41b62 100644
--- a/app/graphql/resolvers/work_items/linked_items_resolver.rb
+++ b/app/graphql/resolvers/work_items/linked_items_resolver.rb
@@ -28,7 +28,7 @@ module Resolvers
private
def related_work_items(type)
- return [] unless work_item.project.linked_work_items_feature_flag_enabled?
+ return [] unless work_item.resource_parent.linked_work_items_feature_flag_enabled?
work_item.linked_work_items(current_user, preload: { project: [:project_feature, :group] }, link_type: type)
end
diff --git a/app/graphql/resolvers/work_items/work_item_discussions_resolver.rb b/app/graphql/resolvers/work_items/work_item_discussions_resolver.rb
index b40d85e8003..0bbd51a537e 100644
--- a/app/graphql/resolvers/work_items/work_item_discussions_resolver.rb
+++ b/app/graphql/resolvers/work_items/work_item_discussions_resolver.rb
@@ -4,7 +4,6 @@ module Resolvers
module WorkItems
class WorkItemDiscussionsResolver < BaseResolver
include Gitlab::Graphql::Authorize::AuthorizeResource
- extension Gitlab::Graphql::Extensions::ForwardOnlyExternallyPaginatedArrayExtension
authorize :read_work_item
authorizes_object!
@@ -31,11 +30,6 @@ module Resolvers
)
end
- def self.field_options
- # we manage the pagination manually through external array, so opt out of the connection field extension
- super.merge(connection: false)
- end
-
def self.calculate_ext_conn_complexity
true
end
diff --git a/app/graphql/types/achievements/user_achievement_type.rb b/app/graphql/types/achievements/user_achievement_type.rb
index 7cdcb66576c..b92b2c42bee 100644
--- a/app/graphql/types/achievements/user_achievement_type.rb
+++ b/app/graphql/types/achievements/user_achievement_type.rb
@@ -48,6 +48,11 @@ module Types
Types::TimeType,
null: true,
description: 'Timestamp the achievement was revoked.'
+
+ field :priority,
+ GraphQL::Types::Int,
+ null: true,
+ description: 'Priority of the user achievement.'
end
end
end
diff --git a/app/graphql/types/base_argument.rb b/app/graphql/types/base_argument.rb
index d2bc1d55408..cda7fa4a5df 100644
--- a/app/graphql/types/base_argument.rb
+++ b/app/graphql/types/base_argument.rb
@@ -7,7 +7,6 @@ module Types
attr_reader :doc_reference
def initialize(*args, **kwargs, &block)
- init_gitlab_deprecation(kwargs)
@doc_reference = kwargs.delete(:see)
# our custom addition `nullable` which allows us to declare
diff --git a/app/graphql/types/base_enum.rb b/app/graphql/types/base_enum.rb
index 45e78b330fb..ca86e399f6b 100644
--- a/app/graphql/types/base_enum.rb
+++ b/app/graphql/types/base_enum.rb
@@ -5,12 +5,6 @@ module Types
class BaseEnum < GraphQL::Schema::Enum
class CustomValue < GraphQL::Schema::EnumValue
include Gitlab::Graphql::Deprecations
-
- def initialize(name, desc = nil, **kwargs)
- init_gitlab_deprecation(kwargs)
-
- super(name, desc, **kwargs)
- end
end
enum_value_class(CustomValue)
diff --git a/app/graphql/types/base_field.rb b/app/graphql/types/base_field.rb
index caeb81c95cb..886490ba62f 100644
--- a/app/graphql/types/base_field.rb
+++ b/app/graphql/types/base_field.rb
@@ -11,13 +11,15 @@ module Types
attr_reader :doc_reference
def initialize(**kwargs, &block)
- init_gitlab_deprecation(kwargs)
- @calls_gitaly = !!kwargs.delete(:calls_gitaly)
+ @requires_argument = kwargs.delete(:requires_argument)
+ @calls_gitaly = kwargs.delete(:calls_gitaly)
@doc_reference = kwargs.delete(:see)
- @constant_complexity = kwargs[:complexity].is_a?(Integer) && kwargs[:complexity] > 0
- @requires_argument = !!kwargs.delete(:requires_argument)
+
+ given_complexity = kwargs[:complexity] || kwargs[:resolver_class].try(:complexity)
+ @constant_complexity = given_complexity.is_a?(Integer) && given_complexity > 0
+ kwargs[:complexity] = field_complexity(kwargs[:resolver_class], given_complexity)
+
@authorize = Array.wrap(kwargs.delete(:authorize))
- kwargs[:complexity] = field_complexity(kwargs[:resolver_class], kwargs[:complexity])
after_connection_extensions = kwargs.delete(:late_extensions) || []
super(**kwargs, &block)
@@ -31,11 +33,12 @@ module Types
end
def may_call_gitaly?
- @constant_complexity || @calls_gitaly
+ @constant_complexity || calls_gitaly?
end
def requires_argument?
- @requires_argument || arguments.values.any? { |argument| argument.type.non_null? }
+ value = @requires_argument.nil? ? @resolver_class.try(:requires_argument?) : @requires_argument
+ !!value || arguments.values.any? { |argument| argument.type.non_null? }
end
# By default fields authorize against the current object, but that is not how our
@@ -82,7 +85,7 @@ module Types
end
def calls_gitaly?
- @calls_gitaly
+ !!(@calls_gitaly.nil? ? @resolver_class.try(:calls_gitaly?) : @calls_gitaly)
end
def constant_complexity?
diff --git a/app/graphql/types/ci/ci_cd_setting_type.rb b/app/graphql/types/ci/ci_cd_setting_type.rb
index 8a49c5a6a95..f01c63d717b 100644
--- a/app/graphql/types/ci/ci_cd_setting_type.rb
+++ b/app/graphql/types/ci/ci_cd_setting_type.rb
@@ -29,12 +29,6 @@ module Types
null: true,
description: 'Whether merge pipelines are enabled.',
method: :merge_pipelines_enabled?
- # TODO(Issue 422295): this is EE only and should be moved to the EE file
- field :merge_trains_enabled,
- GraphQL::Types::Boolean,
- null: true,
- description: 'Whether merge trains are enabled.',
- method: :merge_trains_enabled?
field :project,
Types::ProjectType,
null: true,
diff --git a/app/graphql/types/ci/detailed_status_type.rb b/app/graphql/types/ci/detailed_status_type.rb
index e18770c2708..6882a495259 100644
--- a/app/graphql/types/ci/detailed_status_type.rb
+++ b/app/graphql/types/ci/detailed_status_type.rb
@@ -16,20 +16,34 @@ module Types
field :favicon, GraphQL::Types::String, null: true,
description: 'Favicon of the status.'
field :group, GraphQL::Types::String, null: true,
- description: 'Group of the status.'
+ description: 'Group of the status.',
+ deprecated: {
+ reason: 'The `group` attribute is deprecated. Use `name` instead',
+ milestone: '16.4'
+ }
field :has_details, GraphQL::Types::Boolean, null: true,
description: 'Indicates if the status has further details.',
method: :has_details?
field :icon, GraphQL::Types::String, null: true,
- description: 'Icon of the status.'
+ description: 'Icon of the status.',
+ deprecated: {
+ reason: 'The `icon` attribute is deprecated. Use `name` to ' \
+ 'identify the status to display instead',
+ milestone: '16.4'
+ }
field :id, GraphQL::Types::String, null: false,
description: 'ID for a detailed status.',
extras: [:parent]
field :label, GraphQL::Types::String, null: true,
- calls_gitaly: true,
- description: 'Label of the status.'
+ description: 'Human-readable label of the status (e.g. success).'
+ field :name, GraphQL::Types::String, null: true,
+ description: 'Machine-readable status name (e.g. SUCCESS).'
field :text, GraphQL::Types::String, null: true,
- description: 'Text of the status.'
+ description: 'Text of the status.',
+ deprecated: {
+ reason: 'The `text` attribute is being deprecated. Use `label` instead',
+ milestone: '16.4'
+ }
field :tooltip, GraphQL::Types::String, null: true,
description: 'Tooltip associated with the status.',
method: :status_tooltip
diff --git a/app/graphql/types/ci/job_trace_type.rb b/app/graphql/types/ci/job_trace_type.rb
index 405c640115d..62fb9340b53 100644
--- a/app/graphql/types/ci/job_trace_type.rb
+++ b/app/graphql/types/ci/job_trace_type.rb
@@ -21,7 +21,7 @@ module Types
def html_summary(last_lines:)
object.html(
last_lines: last_lines.clamp(1, 100),
- max_size: Feature.enabled?(:graphql_job_trace_html_summary_max_size) ? MAX_SIZE_B : nil
+ max_size: MAX_SIZE_B
).html_safe
end
end
diff --git a/app/graphql/types/ci/pipeline_type.rb b/app/graphql/types/ci/pipeline_type.rb
index ba638d4bc47..dfdc3752916 100644
--- a/app/graphql/types/ci/pipeline_type.rb
+++ b/app/graphql/types/ci/pipeline_type.rb
@@ -18,6 +18,9 @@ module Types
field :iid, GraphQL::Types::String, null: false,
description: 'Internal ID of the pipeline.'
+ field :name, GraphQL::Types::String, null: true,
+ description: 'Name of the pipeline.'
+
field :sha, GraphQL::Types::String, null: true,
method: :sha,
description: "SHA of the pipeline's commit." do
@@ -61,7 +64,7 @@ module Types
description: "Timestamp of the pipeline's last activity."
field :started_at, Types::TimeType, null: true,
- description: 'Timestamp when the pipeline was started.'
+ description: 'Timestamp when the pipeline was started.'
field :finished_at, Types::TimeType, null: true,
description: "Timestamp of the pipeline's completion."
@@ -178,6 +181,24 @@ module Types
field :merge_request_event_type, Types::Ci::PipelineMergeRequestEventTypeEnum, null: true,
description: "Event type of the pipeline associated with a merge request."
+ field :total_jobs, GraphQL::Types::Int, null: false, method: :total_size, description: "The total number of jobs in the pipeline"
+
+ field :failure_reason, GraphQL::Types::String, null: true, description: "The reason why the pipeline failed"
+
+ field :triggered_by_path, GraphQL::Types::String, null: true, description: "The path that triggered this pipeline"
+
+ field :source, GraphQL::Types::String, null: true, method: :source, description: "The source of the pipeline"
+
+ field :child, GraphQL::Types::Boolean, null: false, method: :child?, description: "If the pipeline is a child or not"
+
+ field :latest, GraphQL::Types::Boolean, null: false, method: :latest?, calls_gitaly: true, description: "If the pipeline is the latest one or not"
+
+ field :ref_text, GraphQL::Types::String, null: false, method: :ref_text, description: "The reference text from the presenter", calls_gitaly: true
+
+ field :merge_request, Types::MergeRequestType, null: true, description: "The MR which the Pipeline is attached to"
+
+ field :stuck, GraphQL::Types::Boolean, method: :stuck?, null: false, description: "If the pipeline is stuck."
+
def commit
BatchLoader::GraphQL.wrap(object.commit)
end
diff --git a/app/graphql/types/clusters/agent_type.rb b/app/graphql/types/clusters/agent_type.rb
index c0989796141..04a4a719ba1 100644
--- a/app/graphql/types/clusters/agent_type.rb
+++ b/app/graphql/types/clusters/agent_type.rb
@@ -33,7 +33,7 @@ module Types
null: true,
authorize: :read_project
- field :tokens, Types::Clusters::AgentTokenType.connection_type,
+ field :tokens,
description: 'Tokens associated with the cluster agent.',
null: true,
resolver: ::Resolvers::Clusters::AgentTokensResolver
diff --git a/app/graphql/types/custom_emoji_type.rb b/app/graphql/types/custom_emoji_type.rb
index b02cd56e6df..08ac3172f2c 100644
--- a/app/graphql/types/custom_emoji_type.rb
+++ b/app/graphql/types/custom_emoji_type.rb
@@ -7,7 +7,7 @@ module Types
authorize :read_custom_emoji
- connection_type_class(Types::CountableConnectionType)
+ connection_type_class Types::CountableConnectionType
expose_permissions Types::PermissionTypes::CustomEmoji
diff --git a/app/graphql/types/error_tracking/sentry_error_collection_type.rb b/app/graphql/types/error_tracking/sentry_error_collection_type.rb
index 9790560929b..009da29d9c7 100644
--- a/app/graphql/types/error_tracking/sentry_error_collection_type.rb
+++ b/app/graphql/types/error_tracking/sentry_error_collection_type.rb
@@ -16,7 +16,8 @@ module Types
resolver: Resolvers::ErrorTracking::SentryErrorStackTraceResolver
field :errors,
description: "Collection of Sentry Errors.",
- resolver: Resolvers::ErrorTracking::SentryErrorsResolver
+ resolver: Resolvers::ErrorTracking::SentryErrorsResolver,
+ connection_extension: Gitlab::Graphql::Extensions::ExternallyPaginatedArrayExtension
field :external_url,
GraphQL::Types::String,
null: true,
diff --git a/app/graphql/types/issues/negated_issue_filter_input_type.rb b/app/graphql/types/issues/negated_issue_filter_input_type.rb
index fc39efd2493..12f87509ade 100644
--- a/app/graphql/types/issues/negated_issue_filter_input_type.rb
+++ b/app/graphql/types/issues/negated_issue_filter_input_type.rb
@@ -11,7 +11,7 @@ module Types
argument :assignee_usernames, [GraphQL::Types::String],
required: false,
description: 'Usernames of users not assigned to the issue.'
- argument :author_username, GraphQL::Types::String,
+ argument :author_username, [GraphQL::Types::String],
required: false,
description: "Username of a user who didn't author the issue."
argument :iids, [GraphQL::Types::String],
diff --git a/app/graphql/types/merge_request_type.rb b/app/graphql/types/merge_request_type.rb
index 4fd2b245de9..e6625e44508 100644
--- a/app/graphql/types/merge_request_type.rb
+++ b/app/graphql/types/merge_request_type.rb
@@ -102,6 +102,12 @@ module Types
calls_gitaly: true,
description: 'Detailed merge status of the merge request.'
+ field :mergeability_checks, [::Types::MergeRequests::MergeabilityCheckType],
+ null: false,
+ description: 'Status of all mergeability checks of the merge request.',
+ method: :all_mergeability_checks_results,
+ alpha: { milestone: '16.5' }
+
field :mergeable_discussions_state, GraphQL::Types::Boolean, null: true,
calls_gitaly: true,
description: 'Indicates if all discussions in the merge request have been resolved, allowing the merge request to be merged.'
diff --git a/app/graphql/types/merge_requests/mergeability_check_identifier_enum.rb b/app/graphql/types/merge_requests/mergeability_check_identifier_enum.rb
new file mode 100644
index 00000000000..ac25c98941c
--- /dev/null
+++ b/app/graphql/types/merge_requests/mergeability_check_identifier_enum.rb
@@ -0,0 +1,18 @@
+# frozen_string_literal: true
+
+module Types
+ module MergeRequests
+ class MergeabilityCheckIdentifierEnum < BaseEnum
+ graphql_name 'MergeabilityCheckIdentifier'
+ description 'Representation of mergeability check identifier.'
+
+ MergeRequest.all_mergeability_checks.each do |check_class|
+ identifier = check_class.identifier.to_s
+
+ value identifier.upcase,
+ value: identifier,
+ description: "Mergeability check identifier is #{identifier}."
+ end
+ end
+ end
+end
diff --git a/app/graphql/types/merge_requests/mergeability_check_status_enum.rb b/app/graphql/types/merge_requests/mergeability_check_status_enum.rb
new file mode 100644
index 00000000000..d3b95316b67
--- /dev/null
+++ b/app/graphql/types/merge_requests/mergeability_check_status_enum.rb
@@ -0,0 +1,22 @@
+# frozen_string_literal: true
+
+module Types
+ module MergeRequests
+ class MergeabilityCheckStatusEnum < BaseEnum
+ graphql_name 'MergeabilityCheckStatus'
+ description 'Representation of whether a mergeability check passed, failed or is inactive.'
+
+ value 'SUCCESS',
+ value: 'success',
+ description: 'Mergeability check has passed.'
+
+ value 'FAILED',
+ value: 'failed',
+ description: 'Mergeability check has failed. The merge request cannot be merged.'
+
+ value 'INACTIVE',
+ value: 'inactive',
+ description: 'Mergeability check is disabled via settings.'
+ end
+ end
+end
diff --git a/app/graphql/types/merge_requests/mergeability_check_type.rb b/app/graphql/types/merge_requests/mergeability_check_type.rb
new file mode 100644
index 00000000000..4ef44c4b511
--- /dev/null
+++ b/app/graphql/types/merge_requests/mergeability_check_type.rb
@@ -0,0 +1,28 @@
+# frozen_string_literal: true
+
+module Types
+ module MergeRequests
+ class MergeabilityCheckType < BaseObject # rubocop:disable Graphql/AuthorizeTypes
+ graphql_name 'MergeRequestMergeabilityCheck'
+ description 'Mergeability check of the merge request.'
+
+ field :identifier,
+ ::Types::MergeRequests::MergeabilityCheckIdentifierEnum,
+ null: false,
+ description: 'Identifier of the mergeability check.'
+
+ field :status,
+ ::Types::MergeRequests::MergeabilityCheckStatusEnum,
+ null: false,
+ description: 'Status of the mergeability check.'
+
+ def status
+ object.status.to_s
+ end
+
+ def identifier
+ object.identifier.to_s
+ end
+ end
+ end
+end
diff --git a/app/graphql/types/mutation_type.rb b/app/graphql/types/mutation_type.rb
index 445f26e2fcf..3af7140aed3 100644
--- a/app/graphql/types/mutation_type.rb
+++ b/app/graphql/types/mutation_type.rb
@@ -12,6 +12,7 @@ module Types
mount_mutation Mutations::Achievements::DeleteUserAchievement, alpha: { milestone: '16.1' }
mount_mutation Mutations::Achievements::Revoke, alpha: { milestone: '15.10' }
mount_mutation Mutations::Achievements::Update, alpha: { milestone: '15.11' }
+ mount_mutation Mutations::Achievements::UpdateUserAchievementPriorities, alpha: { milestone: '16.5' }
mount_mutation Mutations::Admin::SidekiqQueues::DeleteJobs
mount_mutation Mutations::AlertManagement::CreateAlertIssue
mount_mutation Mutations::AlertManagement::UpdateAlertStatus
@@ -169,6 +170,7 @@ module Types
mount_mutation Mutations::Packages::BulkDestroy,
extensions: [::Gitlab::Graphql::Limit::FieldCallCount => { limit: 1 }]
mount_mutation Mutations::Packages::DestroyFile
+ mount_mutation Mutations::Packages::Protection::Rule::Create, alpha: { milestone: '16.5' }
mount_mutation Mutations::Packages::DestroyFiles
mount_mutation Mutations::Packages::Cleanup::Policy::Update
mount_mutation Mutations::Echo
diff --git a/app/graphql/types/namespace_type.rb b/app/graphql/types/namespace_type.rb
index 3420f16213f..85bda507ff7 100644
--- a/app/graphql/types/namespace_type.rb
+++ b/app/graphql/types/namespace_type.rb
@@ -4,7 +4,7 @@ module Types
class NamespaceType < BaseObject
graphql_name 'Namespace'
- authorize :read_namespace
+ authorize :read_namespace_via_membership
field :id, GraphQL::Types::ID, null: false,
description: 'ID of the namespace.'
diff --git a/app/graphql/types/notes/note_type.rb b/app/graphql/types/notes/note_type.rb
index e7e032c67c6..ffdaab0a5f6 100644
--- a/app/graphql/types/notes/note_type.rb
+++ b/app/graphql/types/notes/note_type.rb
@@ -5,6 +5,8 @@ module Types
class NoteType < BaseObject
graphql_name 'Note'
+ connection_type_class Types::CountableConnectionType
+
authorize :read_note
expose_permissions Types::PermissionTypes::Note
diff --git a/app/graphql/types/packages/helm/dependency_type.rb b/app/graphql/types/packages/helm/dependency_type.rb
index 72a47d0af51..6ba14145fb5 100644
--- a/app/graphql/types/packages/helm/dependency_type.rb
+++ b/app/graphql/types/packages/helm/dependency_type.rb
@@ -12,7 +12,7 @@ module Types
field :alias, GraphQL::Types::String, null: true, description: 'Alias of the dependency.', resolver_method: :resolve_alias
field :condition, GraphQL::Types::String, null: true, description: 'Condition of the dependency.'
field :enabled, GraphQL::Types::Boolean, null: true, description: 'Indicates the dependency is enabled.'
- field :import_values, [GraphQL::Types::JSON], null: true, description: 'Import-values of the dependency.', hash_key: "import-values" # rubocop:disable Graphql/JSONType
+ field :import_values, [GraphQL::Types::JSON], null: true, description: 'Import-values of the dependency.', hash_key: :'import-values' # rubocop:disable Graphql/JSONType
field :name, GraphQL::Types::String, null: true, description: 'Name of the dependency.'
field :repository, GraphQL::Types::String, null: true, description: 'Repository of the dependency.'
field :tags, [GraphQL::Types::String], null: true, description: 'Tags of the dependency.'
diff --git a/app/graphql/types/packages/helm/metadata_type.rb b/app/graphql/types/packages/helm/metadata_type.rb
index ccc5a3029cd..77062a48bc3 100644
--- a/app/graphql/types/packages/helm/metadata_type.rb
+++ b/app/graphql/types/packages/helm/metadata_type.rb
@@ -10,8 +10,8 @@ module Types
# Need to be synced with app/validators/json_schemas/helm_metadata.json
field :annotations, GraphQL::Types::JSON, null: true, description: 'Annotations for the chart.' # rubocop:disable Graphql/JSONType
- field :api_version, GraphQL::Types::String, null: false, description: 'API version of the chart.', hash_key: "apiVersion"
- field :app_version, GraphQL::Types::String, null: true, description: 'App version of the chart.', hash_key: "appVersion"
+ field :api_version, GraphQL::Types::String, null: false, description: 'API version of the chart.', hash_key: :apiVersion
+ field :app_version, GraphQL::Types::String, null: true, description: 'App version of the chart.', hash_key: :appVersion
field :condition, GraphQL::Types::String, null: true, description: 'Condition for the chart.'
field :dependencies, [Types::Packages::Helm::DependencyType], null: true, description: 'Dependencies of the chart.'
field :deprecated, GraphQL::Types::Boolean, null: true, description: 'Indicates if the chart is deprecated.'
@@ -19,12 +19,12 @@ module Types
field :home, GraphQL::Types::String, null: true, description: 'URL of the home page.'
field :icon, GraphQL::Types::String, null: true, description: 'URL to an SVG or PNG image for the chart.'
field :keywords, [GraphQL::Types::String], null: true, description: 'Keywords for the chart.'
- field :kube_version, GraphQL::Types::String, null: true, description: 'Kubernetes versions for the chart.', hash_key: "kubeVersion"
+ field :kube_version, GraphQL::Types::String, null: true, description: 'Kubernetes versions for the chart.', hash_key: :kubeVersion
field :maintainers, [Types::Packages::Helm::MaintainerType], null: true, description: 'Maintainers of the chart.'
field :name, GraphQL::Types::String, null: false, description: 'Name of the chart.'
field :sources, [GraphQL::Types::String], null: true, description: 'URLs of the source code for the chart.'
field :tags, GraphQL::Types::String, null: true, description: 'Tags for the chart.'
- field :type, GraphQL::Types::String, null: true, description: 'Type of the chart.', hash_key: "appVersion"
+ field :type, GraphQL::Types::String, null: true, description: 'Type of the chart.', hash_key: :appVersion
field :version, GraphQL::Types::String, null: false, description: 'Version of the chart.'
end
end
diff --git a/app/graphql/types/packages/package_base_type.rb b/app/graphql/types/packages/package_base_type.rb
index cc41169bcda..aa580d48709 100644
--- a/app/graphql/types/packages/package_base_type.rb
+++ b/app/graphql/types/packages/package_base_type.rb
@@ -23,6 +23,7 @@ module Types
field :package_type, Types::Packages::PackageTypeEnum, null: false, description: 'Package type.'
field :project, Types::ProjectType, null: false, description: 'Project where the package is stored.'
field :status, Types::Packages::PackageStatusEnum, null: false, description: 'Package status.'
+ field :status_message, GraphQL::Types::String, null: true, description: 'Status message.'
field :tags, Types::Packages::PackageTagType.connection_type, null: true, description: 'Package tags.'
field :updated_at, Types::TimeType, null: false, description: 'Date of most recent update.'
field :version, GraphQL::Types::String, null: true, description: 'Version string.'
diff --git a/app/graphql/types/packages/package_type.rb b/app/graphql/types/packages/package_type.rb
index f6586670c72..4c5b16cc41e 100644
--- a/app/graphql/types/packages/package_type.rb
+++ b/app/graphql/types/packages/package_type.rb
@@ -10,6 +10,7 @@ module Types
field :pipelines,
resolver: Resolvers::PackagePipelinesResolver,
+ connection_extension: Gitlab::Graphql::Extensions::ExternallyPaginatedArrayExtension,
description: <<-DESC
Pipelines that built the package. Max page size #{Resolvers::PackagePipelinesResolver::MAX_PAGE_SIZE}.
DESC
diff --git a/app/graphql/types/packages/protection/rule_access_level_enum.rb b/app/graphql/types/packages/protection/rule_access_level_enum.rb
new file mode 100644
index 00000000000..098a3e48100
--- /dev/null
+++ b/app/graphql/types/packages/protection/rule_access_level_enum.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+module Types
+ module Packages
+ module Protection
+ class RuleAccessLevelEnum < BaseEnum
+ graphql_name 'PackagesProtectionRuleAccessLevel'
+ description 'Access level of a package protection rule resource'
+
+ ::Packages::Protection::Rule.push_protected_up_to_access_levels.each_key do |access_level_key|
+ value access_level_key.upcase, value: access_level_key.to_s,
+ description: "#{access_level_key.capitalize} access."
+ end
+ end
+ end
+ end
+end
diff --git a/app/graphql/types/packages/protection/rule_package_type_enum.rb b/app/graphql/types/packages/protection/rule_package_type_enum.rb
new file mode 100644
index 00000000000..28e9df76adc
--- /dev/null
+++ b/app/graphql/types/packages/protection/rule_package_type_enum.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+module Types
+ module Packages
+ module Protection
+ class RulePackageTypeEnum < BaseEnum
+ graphql_name 'PackagesProtectionRulePackageType'
+ description 'Package type of a package protection rule resource'
+
+ ::Packages::Protection::Rule.package_types.each_key do |package_type|
+ value package_type.upcase, value: package_type,
+ description: "Packages of the #{package_type} format"
+ end
+ end
+ end
+ end
+end
diff --git a/app/graphql/types/packages/protection/rule_type.rb b/app/graphql/types/packages/protection/rule_type.rb
new file mode 100644
index 00000000000..1e969d39ce2
--- /dev/null
+++ b/app/graphql/types/packages/protection/rule_type.rb
@@ -0,0 +1,33 @@
+# frozen_string_literal: true
+
+module Types
+ module Packages
+ module Protection
+ class RuleType < ::Types::BaseObject
+ graphql_name 'PackagesProtectionRule'
+ description 'A packages protection rule designed to protect packages ' \
+ 'from being pushed by users with a certain access level.'
+
+ authorize :admin_package
+
+ field :package_name_pattern,
+ GraphQL::Types::String,
+ null: false,
+ description:
+ 'Package name protected by the protection rule. For example `@my-scope/my-package-*`. ' \
+ 'Wildcard character `*` allowed.'
+
+ field :package_type,
+ Types::Packages::Protection::RulePackageTypeEnum,
+ null: false,
+ description: 'Package type protected by the protection rule. For example `NPM`.'
+
+ field :push_protected_up_to_access_level,
+ Types::Packages::Protection::RuleAccessLevelEnum,
+ null: false,
+ description:
+ 'Max GitLab access level unable to push a package. For example `DEVELOPER`, `MAINTAINER`, `OWNER`.'
+ end
+ end
+ end
+end
diff --git a/app/graphql/types/project_type.rb b/app/graphql/types/project_type.rb
index 2738d4da6c2..95caefc3825 100644
--- a/app/graphql/types/project_type.rb
+++ b/app/graphql/types/project_type.rb
@@ -311,6 +311,12 @@ module Types
null: true,
description: 'Packages cleanup policy for the project.'
+ field :packages_protection_rules,
+ Types::Packages::Protection::RuleType.connection_type,
+ null: true,
+ description: 'Packages protection rules for the project.',
+ resolver: Resolvers::ProjectPackagesProtectionRulesResolver
+
field :jobs,
type: Types::Ci::JobType.connection_type,
null: true,
@@ -524,7 +530,7 @@ module Types
complexity: 5,
resolver: ::Resolvers::TimelogResolver
- field :agent_configurations, ::Types::Kas::AgentConfigurationType.connection_type,
+ field :agent_configurations,
null: true,
description: 'Agent configurations defined by the project',
resolver: ::Resolvers::Kas::AgentConfigurationsResolver
diff --git a/app/graphql/types/query_type.rb b/app/graphql/types/query_type.rb
index d02b3e4136f..d185007f05b 100644
--- a/app/graphql/types/query_type.rb
+++ b/app/graphql/types/query_type.rb
@@ -109,7 +109,7 @@ module Types
null: true,
resolver: Resolvers::ProjectResolver,
description: "Find a project."
- field :projects, Types::ProjectType.connection_type,
+ field :projects,
null: true,
resolver: Resolvers::ProjectsResolver,
description: "Find projects visible to the current user."
@@ -154,7 +154,7 @@ module Types
null: true,
resolver: Resolvers::TopicsResolver,
description: "Find project topics."
- field :usage_trends_measurements, Types::Admin::Analytics::UsageTrends::MeasurementType.connection_type,
+ field :usage_trends_measurements,
null: true,
description: 'Get statistics on the instance.',
resolver: Resolvers::Admin::Analytics::UsageTrends::MeasurementsResolver
diff --git a/app/graphql/types/repository_type.rb b/app/graphql/types/repository_type.rb
index 40eade3a4d1..a012b60b1c6 100644
--- a/app/graphql/types/repository_type.rb
+++ b/app/graphql/types/repository_type.rb
@@ -20,6 +20,7 @@ module Types
field :exists, GraphQL::Types::Boolean, null: false, method: :exists?, calls_gitaly: true,
description: 'Indicates a corresponding Git repository exists on disk.'
field :paginated_tree, Types::Tree::TreeType.connection_type, null: true, resolver: Resolvers::PaginatedTreeResolver, calls_gitaly: true,
+ connection_extension: Gitlab::Graphql::Extensions::ExternallyPaginatedArrayExtension,
max_page_size: 100,
description: 'Paginated tree of the repository.'
field :root_ref, GraphQL::Types::String, null: true, calls_gitaly: true,
diff --git a/app/graphql/types/security/codequality_reports_comparer_type.rb b/app/graphql/types/security/codequality_reports_comparer_type.rb
index 3b0f790af81..8088bf84627 100644
--- a/app/graphql/types/security/codequality_reports_comparer_type.rb
+++ b/app/graphql/types/security/codequality_reports_comparer_type.rb
@@ -11,7 +11,7 @@ module Types
field :report,
type: CodequalityReportsComparer::ReportType,
null: true,
- hash_key: 'data',
+ hash_key: :data,
description: 'Compared codequality report.'
end
# rubocop: enable Graphql/AuthorizeTypes
diff --git a/app/graphql/types/snippet_type.rb b/app/graphql/types/snippet_type.rb
index 6e6d0edbe15..16f01979a43 100644
--- a/app/graphql/types/snippet_type.rb
+++ b/app/graphql/types/snippet_type.rb
@@ -45,6 +45,11 @@ module Types
description: 'Visibility Level of the snippet.',
null: false
+ field :hidden, GraphQL::Types::Boolean,
+ description: 'Indicates the snippet is hidden because the author has been banned.',
+ null: false,
+ method: :hidden_due_to_author_ban?
+
field :created_at, Types::TimeType,
description: 'Timestamp this snippet was created.',
null: false
diff --git a/app/graphql/types/todo_action_enum.rb b/app/graphql/types/todo_action_enum.rb
index 45b83ea1d64..63f96332eab 100644
--- a/app/graphql/types/todo_action_enum.rb
+++ b/app/graphql/types/todo_action_enum.rb
@@ -13,5 +13,6 @@ module Types
value 'review_requested', value: 9, description: 'Review was requested from the user.'
value 'member_access_requested', value: 10, description: 'Group or project access requested from the user.'
value 'review_submitted', value: 11, description: 'Merge request authored by the user received a review.'
+ value 'okr_checkin_requested', value: 12, description: 'An OKR assigned to the user requires an update.'
end
end
diff --git a/app/graphql/types/user_interface.rb b/app/graphql/types/user_interface.rb
index 9e5f6810aca..47d486265b0 100644
--- a/app/graphql/types/user_interface.rb
+++ b/app/graphql/types/user_interface.rb
@@ -160,7 +160,7 @@ module Types
description: "Achievements for the user. " \
"Only returns for namespaces where the `achievements` feature flag is enabled.",
extras: [:lookahead],
- resolver: ::Resolvers::Achievements::UserAchievementsResolver
+ resolver: ::Resolvers::Achievements::UserAchievementsForUserResolver
field :bio,
type: ::GraphQL::Types::String,
diff --git a/app/graphql/types/user_state_enum.rb b/app/graphql/types/user_state_enum.rb
index de15fc19682..72503840bf5 100644
--- a/app/graphql/types/user_state_enum.rb
+++ b/app/graphql/types/user_state_enum.rb
@@ -5,8 +5,11 @@ module Types
graphql_name 'UserState'
description 'Possible states of a user'
- value 'active', 'User is active and is able to use the system.', value: 'active'
- value 'blocked', 'User has been blocked and is prevented from using the system.', value: 'blocked'
- value 'deactivated', 'User is no longer active and is unable to use the system.', value: 'deactivated'
+ value 'active', 'User is active and can use the system.', value: 'active'
+ value 'blocked', 'User has been blocked by an administrator and cannot use the system.', value: 'blocked'
+ value 'deactivated', 'User is no longer active and cannot use the system.', value: 'deactivated'
+ value 'banned', 'User is blocked, and their contributions are hidden.', value: 'banned'
+ value 'ldap_blocked', 'User has been blocked by the system.', value: 'ldap_blocked'
+ value 'blocked_pending_approval', 'User is blocked and pending approval.', value: 'blocked_pending_approval'
end
end
diff --git a/app/graphql/types/user_type.rb b/app/graphql/types/user_type.rb
index 170f28103eb..87ca5fddf14 100644
--- a/app/graphql/types/user_type.rb
+++ b/app/graphql/types/user_type.rb
@@ -4,6 +4,9 @@ module Types
class UserType < ::Types::BaseObject
graphql_name 'UserCore'
description 'Core representation of a GitLab user.'
+
+ connection_type_class Types::CountableConnectionType
+
implements ::Types::UserInterface
authorize :read_user
diff --git a/app/graphql/types/work_item_type.rb b/app/graphql/types/work_item_type.rb
index 05798ba3d2f..103a1c0ec9b 100644
--- a/app/graphql/types/work_item_type.rb
+++ b/app/graphql/types/work_item_type.rb
@@ -58,6 +58,10 @@ module Types
field :work_item_type, Types::WorkItems::TypeType, null: false,
description: 'Type assigned to the work item.'
+ field :archived, GraphQL::Types::Boolean, null: false,
+ description: 'Whether the work item belongs to an archived project. Always false for group level work items.',
+ alpha: { milestone: '16.5' }
+
markdown_field :title_html, null: true
markdown_field :description_html, null: true
@@ -70,5 +74,11 @@ module Types
def create_note_email
object.creatable_note_email_address(context[:current_user])
end
+
+ def archived
+ return false if object.project.blank?
+
+ object.project.archived?
+ end
end
end
diff --git a/app/graphql/types/work_items/widgets/hierarchy_type.rb b/app/graphql/types/work_items/widgets/hierarchy_type.rb
index 4ec8ec84779..41c5af2ce63 100644
--- a/app/graphql/types/work_items/widgets/hierarchy_type.rb
+++ b/app/graphql/types/work_items/widgets/hierarchy_type.rb
@@ -20,6 +20,12 @@ module Types
null: true, complexity: 5,
description: 'Child work items.'
+ field :ancestors, ::Types::WorkItemType.connection_type,
+ null: true, complexity: 5,
+ description: 'Ancestors (parents) of the work item.',
+ extras: [:lookahead],
+ resolver: Resolvers::WorkItems::AncestorsResolver
+
field :has_children, GraphQL::Types::Boolean,
null: false, description: 'Indicates if the work item has children.'
diff --git a/app/graphql/types/work_items/widgets/notes_type.rb b/app/graphql/types/work_items/widgets/notes_type.rb
index 7da2777beee..199001649bb 100644
--- a/app/graphql/types/work_items/widgets/notes_type.rb
+++ b/app/graphql/types/work_items/widgets/notes_type.rb
@@ -18,7 +18,8 @@ module Types
field :discussions, Types::Notes::DiscussionType.connection_type,
null: true,
description: "Notes on this work item.",
- resolver: Resolvers::WorkItems::WorkItemDiscussionsResolver
+ resolver: Resolvers::WorkItems::WorkItemDiscussionsResolver,
+ connection_extension: Gitlab::Graphql::Extensions::ForwardOnlyExternallyPaginatedArrayExtension
end
# rubocop:enable Graphql/AuthorizeTypes
end