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>2022-10-20 12:40:42 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2022-10-20 12:40:42 +0300
commitee664acb356f8123f4f6b00b73c1e1cf0866c7fb (patch)
treef8479f94a28f66654c6a4f6fb99bad6b4e86a40e /app/graphql
parent62f7d5c5b69180e82ae8196b7b429eeffc8e7b4f (diff)
Add latest changes from gitlab-org/gitlab@15-5-stable-eev15.5.0-rc42
Diffstat (limited to 'app/graphql')
-rw-r--r--app/graphql/batch_loaders/award_emoji_votes_batch_loader.rb21
-rw-r--r--app/graphql/gitlab_schema.rb13
-rw-r--r--app/graphql/graphql_triggers.rb20
-rw-r--r--app/graphql/mutations/alert_management/create_alert_issue.rb4
-rw-r--r--app/graphql/mutations/ci/job/artifacts_destroy.rb21
-rw-r--r--app/graphql/mutations/ci/pipeline_schedule/base.rb21
-rw-r--r--app/graphql/mutations/ci/pipeline_schedule/delete.rb27
-rw-r--r--app/graphql/mutations/ci/project_ci_cd_settings_update.rb11
-rw-r--r--app/graphql/mutations/ci/runner/update.rb2
-rw-r--r--app/graphql/mutations/concerns/mutations/work_items/update_arguments.rb3
-rw-r--r--app/graphql/mutations/issues/create.rb8
-rw-r--r--app/graphql/mutations/namespace/package_settings/update.rb30
-rw-r--r--app/graphql/mutations/packages/bulk_destroy.rb43
-rw-r--r--app/graphql/mutations/packages/destroy_files.rb4
-rw-r--r--app/graphql/mutations/work_items/update_widgets.rb60
-rw-r--r--app/graphql/resolvers/base_issues_resolver.rb2
-rw-r--r--app/graphql/resolvers/bulk_labels_resolver.rb27
-rw-r--r--app/graphql/resolvers/ci/all_jobs_resolver.rb17
-rw-r--r--app/graphql/resolvers/ci/runner_projects_resolver.rb4
-rw-r--r--app/graphql/resolvers/concerns/looks_ahead.rb27
-rw-r--r--app/graphql/resolvers/concerns/resolves_merge_requests.rb4
-rw-r--r--app/graphql/resolvers/down_votes_count_resolver.rb15
-rw-r--r--app/graphql/resolvers/project_pipeline_schedules_resolver.rb17
-rw-r--r--app/graphql/resolvers/projects/branch_rules_resolver.rb8
-rw-r--r--app/graphql/resolvers/projects_resolver.rb4
-rw-r--r--app/graphql/resolvers/up_votes_count_resolver.rb15
-rw-r--r--app/graphql/resolvers/work_items_resolver.rb26
-rw-r--r--app/graphql/types/ci/ci_cd_setting_type.rb11
-rw-r--r--app/graphql/types/ci/config_variable_type.rb4
-rw-r--r--app/graphql/types/ci/job_type.rb18
-rw-r--r--app/graphql/types/ci/pipeline_schedule_status_enum.rb12
-rw-r--r--app/graphql/types/ci/pipeline_schedule_type.rb45
-rw-r--r--app/graphql/types/ci/runner_membership_filter_enum.rb7
-rw-r--r--app/graphql/types/environment_type.rb4
-rw-r--r--app/graphql/types/issue_type.rb19
-rw-r--r--app/graphql/types/merge_request_type.rb23
-rw-r--r--app/graphql/types/merge_requests/detailed_merge_status_enum.rb3
-rw-r--r--app/graphql/types/mutation_type.rb4
-rw-r--r--app/graphql/types/namespace/package_settings_type.rb49
-rw-r--r--app/graphql/types/notes/note_type.rb2
-rw-r--r--app/graphql/types/permission_types/ci/pipeline_schedules.rb17
-rw-r--r--app/graphql/types/project_type.rb6
-rw-r--r--app/graphql/types/projects/branch_rule_type.rb9
-rw-r--r--app/graphql/types/query_type.rb6
-rw-r--r--app/graphql/types/subscription_type.rb8
-rw-r--r--app/graphql/types/work_items/widget_interface.rb3
-rw-r--r--app/graphql/types/work_items/widgets/labels_update_input_type.rb20
47 files changed, 596 insertions, 128 deletions
diff --git a/app/graphql/batch_loaders/award_emoji_votes_batch_loader.rb b/app/graphql/batch_loaders/award_emoji_votes_batch_loader.rb
new file mode 100644
index 00000000000..c1b35d3eaf7
--- /dev/null
+++ b/app/graphql/batch_loaders/award_emoji_votes_batch_loader.rb
@@ -0,0 +1,21 @@
+# frozen_string_literal: true
+
+module BatchLoaders
+ module AwardEmojiVotesBatchLoader
+ private
+
+ def load_votes(object, vote_type)
+ BatchLoader::GraphQL.for(object.id).batch(key: "#{object.issuing_parent_id}-#{vote_type}") do |ids, loader, args|
+ counts = AwardEmoji.votes_for_collection(ids, object.class.name).named(vote_type).index_by(&:awardable_id)
+
+ ids.each do |id|
+ loader.call(id, counts[id]&.count || 0)
+ end
+ end
+ end
+
+ def authorized_resource?(object)
+ Ability.allowed?(current_user, "read_#{object.to_ability_name}".to_sym, object)
+ end
+ end
+end
diff --git a/app/graphql/gitlab_schema.rb b/app/graphql/gitlab_schema.rb
index c0e063a34d5..37adf4c2d3b 100644
--- a/app/graphql/gitlab_schema.rb
+++ b/app/graphql/gitlab_schema.rb
@@ -137,6 +137,19 @@ class GitlabSchema < GraphQL::Schema
gid
end
+ # Parse an array of strings to an array of GlobalIDs, raising ArgumentError if there are problems
+ # with it.
+ # See #parse_gid
+ #
+ # ```
+ # gids = GitlabSchema.parse_gids(my_array_of_strings, expected_type: ::Project)
+ # project_ids = gids.map(&:model_id)
+ # gids.all? { |gid| gid.model_class == ::Project }
+ # ```
+ def parse_gids(global_ids, ctx = {})
+ global_ids.map { |gid| parse_gid(gid, ctx) }
+ end
+
private
def max_query_complexity(ctx)
diff --git a/app/graphql/graphql_triggers.rb b/app/graphql/graphql_triggers.rb
index 8086d8c02a4..dc4f838ae36 100644
--- a/app/graphql/graphql_triggers.rb
+++ b/app/graphql/graphql_triggers.rb
@@ -13,6 +13,10 @@ module GraphqlTriggers
GitlabSchema.subscriptions.trigger('issuableTitleUpdated', { issuable_id: issuable.to_gid }, issuable)
end
+ def self.issuable_description_updated(issuable)
+ GitlabSchema.subscriptions.trigger('issuableDescriptionUpdated', { issuable_id: issuable.to_gid }, issuable)
+ end
+
def self.issuable_labels_updated(issuable)
GitlabSchema.subscriptions.trigger('issuableLabelsUpdated', { issuable_id: issuable.to_gid }, issuable)
end
@@ -20,6 +24,22 @@ module GraphqlTriggers
def self.issuable_dates_updated(issuable)
GitlabSchema.subscriptions.trigger('issuableDatesUpdated', { issuable_id: issuable.to_gid }, issuable)
end
+
+ def self.merge_request_reviewers_updated(merge_request)
+ GitlabSchema.subscriptions.trigger(
+ 'mergeRequestReviewersUpdated',
+ { issuable_id: merge_request.to_gid },
+ merge_request
+ )
+ end
+
+ def self.merge_request_merge_status_updated(merge_request)
+ GitlabSchema.subscriptions.trigger(
+ 'mergeRequestMergeStatusUpdated',
+ { issuable_id: merge_request.to_gid },
+ merge_request
+ )
+ end
end
GraphqlTriggers.prepend_mod
diff --git a/app/graphql/mutations/alert_management/create_alert_issue.rb b/app/graphql/mutations/alert_management/create_alert_issue.rb
index 2c128e1b339..77a7d7a4147 100644
--- a/app/graphql/mutations/alert_management/create_alert_issue.rb
+++ b/app/graphql/mutations/alert_management/create_alert_issue.rb
@@ -24,8 +24,8 @@ module Mutations
def prepare_response(alert, result)
{
alert: alert,
- issue: result.payload[:issue],
- errors: Array(result.message)
+ issue: result[:issue],
+ errors: result.errors
}
end
end
diff --git a/app/graphql/mutations/ci/job/artifacts_destroy.rb b/app/graphql/mutations/ci/job/artifacts_destroy.rb
index c27ab9c4d89..34c58fc1240 100644
--- a/app/graphql/mutations/ci/job/artifacts_destroy.rb
+++ b/app/graphql/mutations/ci/job/artifacts_destroy.rb
@@ -25,12 +25,21 @@ module Mutations
def resolve(id:)
job = authorized_find!(id: id)
- result = ::Ci::JobArtifacts::DestroyBatchService.new(job.job_artifacts, pick_up_at: Time.current).execute
- {
- job: job,
- destroyed_artifacts_count: result[:destroyed_artifacts_count],
- errors: Array(result[:errors])
- }
+ result = ::Ci::JobArtifacts::DeleteService.new(job).execute
+
+ if result.success?
+ {
+ job: job,
+ destroyed_artifacts_count: result.payload[:destroyed_artifacts_count],
+ errors: Array(result.payload[:errors])
+ }
+ else
+ {
+ job: job,
+ destroyed_artifacts_count: 0,
+ errors: Array(result.message)
+ }
+ end
end
end
end
diff --git a/app/graphql/mutations/ci/pipeline_schedule/base.rb b/app/graphql/mutations/ci/pipeline_schedule/base.rb
new file mode 100644
index 00000000000..a737ccce575
--- /dev/null
+++ b/app/graphql/mutations/ci/pipeline_schedule/base.rb
@@ -0,0 +1,21 @@
+# frozen_string_literal: true
+
+module Mutations
+ module Ci
+ module PipelineSchedule
+ class Base < BaseMutation
+ PipelineScheduleID = ::Types::GlobalIDType[::Ci::PipelineSchedule]
+
+ argument :id, PipelineScheduleID,
+ required: true,
+ description: 'ID of the pipeline schedule to mutate.'
+
+ private
+
+ def find_object(id:)
+ GlobalID::Locator.locate(id)
+ end
+ end
+ end
+ end
+end
diff --git a/app/graphql/mutations/ci/pipeline_schedule/delete.rb b/app/graphql/mutations/ci/pipeline_schedule/delete.rb
new file mode 100644
index 00000000000..ead9a43161d
--- /dev/null
+++ b/app/graphql/mutations/ci/pipeline_schedule/delete.rb
@@ -0,0 +1,27 @@
+# frozen_string_literal: true
+
+module Mutations
+ module Ci
+ module PipelineSchedule
+ class Delete < Base
+ graphql_name 'PipelineScheduleDelete'
+
+ authorize :admin_pipeline_schedule
+
+ def resolve(id:)
+ schedule = authorized_find!(id: id)
+
+ if schedule.destroy
+ {
+ errors: []
+ }
+ else
+ {
+ errors: ['Failed to remove the pipeline schedule']
+ }
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/app/graphql/mutations/ci/project_ci_cd_settings_update.rb b/app/graphql/mutations/ci/project_ci_cd_settings_update.rb
index b0cffa2c088..27b066ffcf6 100644
--- a/app/graphql/mutations/ci/project_ci_cd_settings_update.rb
+++ b/app/graphql/mutations/ci/project_ci_cd_settings_update.rb
@@ -19,7 +19,13 @@ module Mutations
argument :job_token_scope_enabled, GraphQL::Types::Boolean,
required: false,
- description: 'Indicates CI job tokens generated in this project have restricted access to resources.'
+ description: 'Indicates CI/CD job tokens generated in this project ' \
+ 'have restricted access to other projects.'
+
+ argument :inbound_job_token_scope_enabled, GraphQL::Types::Boolean,
+ required: false,
+ description: 'Indicates CI/CD job tokens generated in other projects ' \
+ 'have restricted access to this project.'
field :ci_cd_settings,
Types::Ci::CiCdSettingType,
@@ -28,6 +34,9 @@ module Mutations
def resolve(full_path:, **args)
project = authorized_find!(full_path)
+
+ args.delete(:inbound_job_token_scope_enabled) unless Feature.enabled?(:ci_inbound_job_token_scope, project)
+
settings = project.ci_cd_settings
settings.update(args)
diff --git a/app/graphql/mutations/ci/runner/update.rb b/app/graphql/mutations/ci/runner/update.rb
index f98138646be..2f2c8c4c668 100644
--- a/app/graphql/mutations/ci/runner/update.rb
+++ b/app/graphql/mutations/ci/runner/update.rb
@@ -94,6 +94,7 @@ module Mutations
).execute
return if result.success?
+ response[:runner] = nil
response[:errors] = result.errors
raise ActiveRecord::Rollback
end
@@ -102,6 +103,7 @@ module Mutations
result = ::Ci::Runners::UpdateRunnerService.new(runner).execute(attrs)
return if result.success?
+ response[:runner] = nil
response[:errors] = result.errors
raise ActiveRecord::Rollback
end
diff --git a/app/graphql/mutations/concerns/mutations/work_items/update_arguments.rb b/app/graphql/mutations/concerns/mutations/work_items/update_arguments.rb
index 1f90f394521..e42e59de78f 100644
--- a/app/graphql/mutations/concerns/mutations/work_items/update_arguments.rb
+++ b/app/graphql/mutations/concerns/mutations/work_items/update_arguments.rb
@@ -30,6 +30,9 @@ module Mutations
argument :start_and_due_date_widget, ::Types::WorkItems::Widgets::StartAndDueDateUpdateInputType,
required: false,
description: 'Input for start and due date widget.'
+ argument :labels_widget, ::Types::WorkItems::Widgets::LabelsUpdateInputType,
+ required: false,
+ description: 'Input for labels widget.'
end
end
end
diff --git a/app/graphql/mutations/issues/create.rb b/app/graphql/mutations/issues/create.rb
index 6bf8caf82d7..0389a482822 100644
--- a/app/graphql/mutations/issues/create.rb
+++ b/app/graphql/mutations/issues/create.rb
@@ -83,13 +83,13 @@ module Mutations
params = build_create_issue_params(attributes.merge(author_id: current_user.id), project)
spam_params = ::Spam::SpamParams.new_from_request(request: context[:request])
- issue = ::Issues::CreateService.new(project: project, current_user: current_user, params: params, spam_params: spam_params).execute
+ result = ::Issues::CreateService.new(project: project, current_user: current_user, params: params, spam_params: spam_params).execute
- check_spam_action_response!(issue)
+ check_spam_action_response!(result[:issue]) if result[:issue]
{
- issue: issue.valid? ? issue : nil,
- errors: errors_on_object(issue)
+ issue: result.success? ? result[:issue] : nil,
+ errors: result.errors
}
end
diff --git a/app/graphql/mutations/namespace/package_settings/update.rb b/app/graphql/mutations/namespace/package_settings/update.rb
index e499e646781..ea72b71715c 100644
--- a/app/graphql/mutations/namespace/package_settings/update.rb
+++ b/app/graphql/mutations/namespace/package_settings/update.rb
@@ -35,6 +35,36 @@ module Mutations
required: false,
description: copy_field_description(Types::Namespace::PackageSettingsType, :generic_duplicate_exception_regex)
+ argument :maven_package_requests_forwarding,
+ GraphQL::Types::Boolean,
+ required: false,
+ description: copy_field_description(Types::Namespace::PackageSettingsType, :maven_package_requests_forwarding)
+
+ argument :npm_package_requests_forwarding,
+ GraphQL::Types::Boolean,
+ required: false,
+ description: copy_field_description(Types::Namespace::PackageSettingsType, :npm_package_requests_forwarding)
+
+ argument :pypi_package_requests_forwarding,
+ GraphQL::Types::Boolean,
+ required: false,
+ description: copy_field_description(Types::Namespace::PackageSettingsType, :pypi_package_requests_forwarding)
+
+ argument :lock_maven_package_requests_forwarding,
+ GraphQL::Types::Boolean,
+ required: false,
+ description: copy_field_description(Types::Namespace::PackageSettingsType, :lock_maven_package_requests_forwarding)
+
+ argument :lock_npm_package_requests_forwarding,
+ GraphQL::Types::Boolean,
+ required: false,
+ description: copy_field_description(Types::Namespace::PackageSettingsType, :lock_npm_package_requests_forwarding)
+
+ argument :lock_pypi_package_requests_forwarding,
+ GraphQL::Types::Boolean,
+ required: false,
+ description: copy_field_description(Types::Namespace::PackageSettingsType, :lock_pypi_package_requests_forwarding)
+
field :package_settings,
Types::Namespace::PackageSettingsType,
null: true,
diff --git a/app/graphql/mutations/packages/bulk_destroy.rb b/app/graphql/mutations/packages/bulk_destroy.rb
new file mode 100644
index 00000000000..a0756d0c3f9
--- /dev/null
+++ b/app/graphql/mutations/packages/bulk_destroy.rb
@@ -0,0 +1,43 @@
+# frozen_string_literal: true
+
+module Mutations
+ module Packages
+ class BulkDestroy < ::Mutations::BaseMutation
+ graphql_name 'DestroyPackages'
+
+ MAX_PACKAGES = 20
+ TOO_MANY_IDS_ERROR = "Cannot delete more than #{MAX_PACKAGES} packages"
+
+ argument :ids,
+ [::Types::GlobalIDType[::Packages::Package]],
+ required: true,
+ description: "Global IDs of the Packages. Max #{MAX_PACKAGES}"
+
+ def resolve(ids:)
+ raise_resource_not_available_error!(TOO_MANY_IDS_ERROR) if ids.size > MAX_PACKAGES
+
+ ids = GitlabSchema.parse_gids(ids, expected_type: ::Packages::Package)
+ .map(&:model_id)
+
+ service = ::Packages::MarkPackagesForDestructionService.new(
+ packages: packages_from(ids),
+ current_user: current_user
+ )
+ result = service.execute
+
+ raise_resource_not_available_error! if result.reason == :unauthorized
+
+ errors = result.error? ? Array.wrap(result[:message]) : []
+
+ { errors: errors }
+ end
+
+ private
+
+ def packages_from(ids)
+ ::Packages::Package.displayable
+ .id_in(ids)
+ end
+ end
+ end
+end
diff --git a/app/graphql/mutations/packages/destroy_files.rb b/app/graphql/mutations/packages/destroy_files.rb
index 3900a2c46ae..60a21be20d8 100644
--- a/app/graphql/mutations/packages/destroy_files.rb
+++ b/app/graphql/mutations/packages/destroy_files.rb
@@ -25,7 +25,7 @@ module Mutations
project = authorized_find!(project_path)
raise_resource_not_available_error! "Cannot delete more than #{MAXIMUM_FILES} files" if ids.size > MAXIMUM_FILES
- package_files = ::Packages::PackageFile.where(id: parse_gids(ids)) # rubocop:disable CodeReuse/ActiveRecord
+ package_files = ::Packages::PackageFile.id_in(parse_gids(ids))
ensure_file_access!(project, package_files)
@@ -47,7 +47,7 @@ module Mutations
end
def parse_gids(gids)
- gids.map { |gid| GitlabSchema.parse_gid(gid, expected_type: ::Packages::PackageFile).model_id }
+ GitlabSchema.parse_gids(gids, expected_type: ::Packages::PackageFile).map(&:model_id)
end
end
end
diff --git a/app/graphql/mutations/work_items/update_widgets.rb b/app/graphql/mutations/work_items/update_widgets.rb
deleted file mode 100644
index 7037b7e5a2a..00000000000
--- a/app/graphql/mutations/work_items/update_widgets.rb
+++ /dev/null
@@ -1,60 +0,0 @@
-# frozen_string_literal: true
-
-module Mutations
- module WorkItems
- # TODO: Deprecate in favor of using WorkItemUpdate. See https://gitlab.com/gitlab-org/gitlab/-/issues/366300
- class UpdateWidgets < BaseMutation
- graphql_name 'WorkItemUpdateWidgets'
- description "Updates the attributes of a work item's widgets by global ID." \
- " Available only when feature flag `work_items` is enabled."
-
- include Mutations::SpamProtection
-
- authorize :update_work_item
-
- argument :id, ::Types::GlobalIDType[::WorkItem],
- required: true,
- description: 'Global ID of the work item.'
-
- argument :description_widget, ::Types::WorkItems::Widgets::DescriptionInputType,
- required: false,
- description: 'Input for description widget.'
-
- field :work_item, Types::WorkItemType,
- null: true,
- description: 'Updated work item.'
-
- def resolve(id:, **widget_attributes)
- work_item = authorized_find!(id: id)
-
- unless work_item.project.work_items_feature_flag_enabled?
- return { errors: ['`work_items` feature flag disabled for this project'] }
- end
-
- spam_params = ::Spam::SpamParams.new_from_request(request: context[:request])
-
- ::WorkItems::UpdateService.new(
- project: work_item.project,
- current_user: current_user,
- # Cannot use prepare to use `.to_h` on each input due to
- # https://gitlab.com/gitlab-org/gitlab/-/merge_requests/87472#note_945199865
- widget_params: widget_attributes.transform_values { |values| values.to_h },
- spam_params: spam_params
- ).execute(work_item)
-
- check_spam_action_response!(work_item)
-
- {
- work_item: work_item.valid? ? work_item : nil,
- errors: errors_on_object(work_item)
- }
- end
-
- private
-
- def find_object(id:)
- GitlabSchema.find_by_gid(id)
- end
- end
- end
-end
diff --git a/app/graphql/resolvers/base_issues_resolver.rb b/app/graphql/resolvers/base_issues_resolver.rb
index ec47a8996eb..6357132705e 100644
--- a/app/graphql/resolvers/base_issues_resolver.rb
+++ b/app/graphql/resolvers/base_issues_resolver.rb
@@ -47,8 +47,8 @@ module Resolvers
def preloads
{
alert_management_alert: [:alert_management_alert],
- labels: [:labels],
assignees: [:assignees],
+ participants: Issue.participant_includes,
timelogs: [:timelogs],
customer_relations_contacts: { customer_relations_contacts: [:group] },
escalation_status: [:incident_management_issuable_escalation_status]
diff --git a/app/graphql/resolvers/bulk_labels_resolver.rb b/app/graphql/resolvers/bulk_labels_resolver.rb
new file mode 100644
index 00000000000..7362e257fb6
--- /dev/null
+++ b/app/graphql/resolvers/bulk_labels_resolver.rb
@@ -0,0 +1,27 @@
+# frozen_string_literal: true
+
+module Resolvers
+ class BulkLabelsResolver < BaseResolver
+ include Gitlab::Graphql::Authorize::AuthorizeResource
+
+ type Types::LabelType.connection_type, null: true
+
+ def resolve
+ authorize!(object)
+
+ BatchLoader::GraphQL.for(object.id).batch(cache: false) do |ids, loader, args|
+ labels = Label.for_targets(object.class.id_in(ids)).group_by(&:target_id)
+
+ ids.each do |id|
+ loader.call(id, labels[id] || [])
+ end
+ end
+ end
+
+ private
+
+ def authorized_resource?(object)
+ Ability.allowed?(current_user, :read_label, object.issuing_parent)
+ end
+ end
+end
diff --git a/app/graphql/resolvers/ci/all_jobs_resolver.rb b/app/graphql/resolvers/ci/all_jobs_resolver.rb
new file mode 100644
index 00000000000..d918bed9f57
--- /dev/null
+++ b/app/graphql/resolvers/ci/all_jobs_resolver.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+module Resolvers
+ module Ci
+ class AllJobsResolver < BaseResolver
+ type ::Types::Ci::JobType.connection_type, null: true
+
+ argument :statuses, [::Types::Ci::JobStatusEnum],
+ required: false,
+ description: 'Filter jobs by status.'
+
+ def resolve(statuses: nil)
+ ::Ci::JobsFinder.new(current_user: current_user, params: { scope: statuses }).execute
+ end
+ end
+ end
+end
diff --git a/app/graphql/resolvers/ci/runner_projects_resolver.rb b/app/graphql/resolvers/ci/runner_projects_resolver.rb
index ca3b4ebb797..af9a67acfda 100644
--- a/app/graphql/resolvers/ci/runner_projects_resolver.rb
+++ b/app/graphql/resolvers/ci/runner_projects_resolver.rb
@@ -21,8 +21,8 @@ module Resolvers
'Specify `"id_asc"` if query results\' order is important',
milestone: '15.4'
},
- description: "Sort order of results. Format: '<field_name>_<sort_direction>', " \
- "for example: 'id_desc' or 'name_asc'"
+ description: "Sort order of results. Format: `<field_name>_<sort_direction>`, " \
+ "for example: `id_desc` or `name_asc`"
def resolve_with_lookahead(**args)
return unless runner.project_type?
diff --git a/app/graphql/resolvers/concerns/looks_ahead.rb b/app/graphql/resolvers/concerns/looks_ahead.rb
index b548dc1e175..81099c04e9f 100644
--- a/app/graphql/resolvers/concerns/looks_ahead.rb
+++ b/app/graphql/resolvers/concerns/looks_ahead.rb
@@ -32,16 +32,37 @@ module LooksAhead
{}
end
+ def nested_preloads
+ {}
+ end
+
def filtered_preloads
nodes = node_selection
return [] unless nodes
selected_fields = nodes.selections.map(&:name)
+ root_level_preloads = preloads_from_node_selection(selected_fields, preloads)
- preloads.each.flat_map do |name, requirements|
- selected_fields.include?(name) ? requirements : []
- end
+ root_level_preloads + nested_filtered_preloads(nodes, selected_fields)
+ end
+
+ def nested_filtered_preloads(nodes, selected_root_fields)
+ return [] if nested_preloads.empty?
+
+ nested_preloads.each_with_object([]) do |(root_field, fields), result|
+ next unless selected_root_fields.include?(root_field)
+
+ selected_fields = nodes.selection(root_field).selections.map(&:name)
+
+ result << preloads_from_node_selection(selected_fields, fields)
+ end.flatten
+ end
+
+ def preloads_from_node_selection(selected_fields, fields)
+ fields.each_with_object([]) do |(field, requirements), result|
+ result << requirements if selected_fields.include?(field)
+ end.flatten
end
def node_selection
diff --git a/app/graphql/resolvers/concerns/resolves_merge_requests.rb b/app/graphql/resolvers/concerns/resolves_merge_requests.rb
index 697cc6f5b03..d56951bc821 100644
--- a/app/graphql/resolvers/concerns/resolves_merge_requests.rb
+++ b/app/graphql/resolvers/concerns/resolves_merge_requests.rb
@@ -42,7 +42,6 @@ module ResolvesMergeRequests
assignees: [:assignees],
reviewers: [:reviewers],
participants: MergeRequest.participant_includes,
- labels: [:labels],
author: [:author],
merged_at: [:metrics],
commit_count: [:metrics],
@@ -53,7 +52,8 @@ module ResolvesMergeRequests
head_pipeline: [:merge_request_diff, { head_pipeline: [:merge_request] }],
timelogs: [:timelogs],
pipelines: [:merge_request_diffs], # used by `recent_diff_head_shas` to load pipelines
- committers: [merge_request_diff: [:merge_request_diff_commits]]
+ committers: [merge_request_diff: [:merge_request_diff_commits]],
+ suggested_reviewers: [:predictions]
}
end
end
diff --git a/app/graphql/resolvers/down_votes_count_resolver.rb b/app/graphql/resolvers/down_votes_count_resolver.rb
new file mode 100644
index 00000000000..0e7772f988a
--- /dev/null
+++ b/app/graphql/resolvers/down_votes_count_resolver.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+module Resolvers
+ class DownVotesCountResolver < BaseResolver
+ include Gitlab::Graphql::Authorize::AuthorizeResource
+ include BatchLoaders::AwardEmojiVotesBatchLoader
+
+ type GraphQL::Types::Int, null: true
+
+ def resolve
+ authorize!(object)
+ load_votes(object, AwardEmoji::DOWNVOTE_NAME)
+ end
+ end
+end
diff --git a/app/graphql/resolvers/project_pipeline_schedules_resolver.rb b/app/graphql/resolvers/project_pipeline_schedules_resolver.rb
new file mode 100644
index 00000000000..eb980f72717
--- /dev/null
+++ b/app/graphql/resolvers/project_pipeline_schedules_resolver.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+module Resolvers
+ class ProjectPipelineSchedulesResolver < BaseResolver
+ alias_method :project, :object
+
+ type ::Types::Ci::PipelineScheduleType.connection_type, null: true
+
+ argument :status, ::Types::Ci::PipelineScheduleStatusEnum,
+ required: false,
+ description: 'Filter pipeline schedules by active status.'
+
+ def resolve(status: nil)
+ ::Ci::PipelineSchedulesFinder.new(project).execute(scope: status)
+ end
+ end
+end
diff --git a/app/graphql/resolvers/projects/branch_rules_resolver.rb b/app/graphql/resolvers/projects/branch_rules_resolver.rb
index 6c8b416bcea..e99d7ae4d5f 100644
--- a/app/graphql/resolvers/projects/branch_rules_resolver.rb
+++ b/app/graphql/resolvers/projects/branch_rules_resolver.rb
@@ -3,13 +3,17 @@
module Resolvers
module Projects
class BranchRulesResolver < BaseResolver
+ include LooksAhead
+
type Types::Projects::BranchRuleType.connection_type, null: false
alias_method :project, :object
- def resolve(**args)
- project.protected_branches
+ def resolve_with_lookahead(**args)
+ apply_lookahead(project.protected_branches)
end
end
end
end
+
+Resolvers::Projects::BranchRulesResolver.prepend_mod_with('Resolvers::Projects::BranchRulesResolver')
diff --git a/app/graphql/resolvers/projects_resolver.rb b/app/graphql/resolvers/projects_resolver.rb
index 4d1e1b867da..0bdba53c7af 100644
--- a/app/graphql/resolvers/projects_resolver.rb
+++ b/app/graphql/resolvers/projects_resolver.rb
@@ -12,8 +12,8 @@ module Resolvers
argument :sort, GraphQL::Types::String,
required: false,
- description: "Sort order of results. Format: '<field_name>_<sort_direction>', " \
- "for example: 'id_desc' or 'name_asc'"
+ description: "Sort order of results. Format: `<field_name>_<sort_direction>`, " \
+ "for example: `id_desc` or `name_asc`"
def resolve(**args)
ProjectsFinder
diff --git a/app/graphql/resolvers/up_votes_count_resolver.rb b/app/graphql/resolvers/up_votes_count_resolver.rb
new file mode 100644
index 00000000000..1c78facb694
--- /dev/null
+++ b/app/graphql/resolvers/up_votes_count_resolver.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+module Resolvers
+ class UpVotesCountResolver < BaseResolver
+ include Gitlab::Graphql::Authorize::AuthorizeResource
+ include BatchLoaders::AwardEmojiVotesBatchLoader
+
+ type GraphQL::Types::Int, null: true
+
+ def resolve
+ authorize!(object)
+ load_votes(object, AwardEmoji::UPVOTE_NAME)
+ end
+ end
+end
diff --git a/app/graphql/resolvers/work_items_resolver.rb b/app/graphql/resolvers/work_items_resolver.rb
index a8c0d363325..a4cbcc61ead 100644
--- a/app/graphql/resolvers/work_items_resolver.rb
+++ b/app/graphql/resolvers/work_items_resolver.rb
@@ -37,20 +37,26 @@ module Resolvers
def preloads
{
- last_edited_by: :last_edited_by,
- web_url: { project: { namespace: :route } }
+ work_item_type: :work_item_type,
+ web_url: { project: { namespace: :route } },
+ widgets: :work_item_type
}
end
- # Allows to apply lookahead for fields
- # selected from WidgetInterface
- override :node_selection
- def node_selection
- selected_fields = super
-
- return unless selected_fields
+ def nested_preloads
+ {
+ widgets: widget_preloads,
+ user_permissions: { update_work_item: :assignees }
+ }
+ end
- selected_fields.selection(:widgets)
+ def widget_preloads
+ {
+ last_edited_by: :last_edited_by,
+ assignees: :assignees,
+ parent: :work_item_parent,
+ labels: :labels
+ }
end
def unconditional_includes
diff --git a/app/graphql/types/ci/ci_cd_setting_type.rb b/app/graphql/types/ci/ci_cd_setting_type.rb
index bec8c72e783..574791b79e6 100644
--- a/app/graphql/types/ci/ci_cd_setting_type.rb
+++ b/app/graphql/types/ci/ci_cd_setting_type.rb
@@ -10,8 +10,17 @@ module Types
field :job_token_scope_enabled,
GraphQL::Types::Boolean,
null: true,
- description: 'Indicates CI job tokens generated in this project have restricted access to resources.',
+ description: 'Indicates CI/CD job tokens generated in this project ' \
+ 'have restricted access to other projects.',
method: :job_token_scope_enabled?
+
+ field :inbound_job_token_scope_enabled,
+ GraphQL::Types::Boolean,
+ null: true,
+ description: 'Indicates CI/CD job tokens generated in other projects ' \
+ 'have restricted access to this project.',
+ method: :inbound_job_token_scope_enabled?
+
field :keep_latest_artifact, GraphQL::Types::Boolean, null: true,
description: 'Whether to keep the latest builds artifacts.',
method: :keep_latest_artifacts_available?
diff --git a/app/graphql/types/ci/config_variable_type.rb b/app/graphql/types/ci/config_variable_type.rb
index 87ae026c2c1..5b5890fd5a5 100644
--- a/app/graphql/types/ci/config_variable_type.rb
+++ b/app/graphql/types/ci/config_variable_type.rb
@@ -17,6 +17,10 @@ module Types
field :value, GraphQL::Types::String,
null: true,
description: 'Value of the variable.'
+
+ field :value_options, [GraphQL::Types::String],
+ null: true,
+ description: 'Value options for the variable.'
end
end
end
diff --git a/app/graphql/types/ci/job_type.rb b/app/graphql/types/ci/job_type.rb
index ab6103d9469..4447a10a74e 100644
--- a/app/graphql/types/ci/job_type.rb
+++ b/app/graphql/types/ci/job_type.rb
@@ -56,6 +56,8 @@ module Types
description: 'Indicates the job is active.'
field :artifacts, Types::Ci::JobArtifactType.connection_type, null: true,
description: 'Artifacts generated by the job.'
+ field :browse_artifacts_path, GraphQL::Types::String, null: true,
+ description: "URL for browsing the artifact's archive."
field :cancelable, GraphQL::Types::Boolean, null: false, method: :cancelable?,
description: 'Indicates the job can be canceled.'
field :commit_path, GraphQL::Types::String, null: true,
@@ -148,17 +150,7 @@ module Types
end
def stage
- ::Gitlab::Graphql::Lazy.with_value(pipeline) do |pl|
- BatchLoader::GraphQL.for([pl, object.stage]).batch do |ids, loader|
- by_pipeline = ids
- .group_by(&:first)
- .transform_values { |grp| grp.map(&:second) }
-
- by_pipeline.each do |p, names|
- p.stages.by_name(names).each { |s| loader.call([p, s.name], s) }
- end
- end
- end
+ ::Gitlab::Graphql::Loaders::BatchModelLoader.new(::Ci::Stage, object.stage_id).find
end
# This class is a secret union!
@@ -187,6 +179,10 @@ module Types
::Gitlab::Routing.url_helpers.project_job_path(object.project, object)
end
+ def browse_artifacts_path
+ ::Gitlab::Routing.url_helpers.browse_project_job_artifacts_path(object.project, object)
+ end
+
def coverage
object&.coverage
end
diff --git a/app/graphql/types/ci/pipeline_schedule_status_enum.rb b/app/graphql/types/ci/pipeline_schedule_status_enum.rb
new file mode 100644
index 00000000000..61bae7daff8
--- /dev/null
+++ b/app/graphql/types/ci/pipeline_schedule_status_enum.rb
@@ -0,0 +1,12 @@
+# frozen_string_literal: true
+
+module Types
+ module Ci
+ class PipelineScheduleStatusEnum < BaseEnum
+ graphql_name 'PipelineScheduleStatus'
+
+ value 'ACTIVE', value: "active", description: 'Active pipeline schedules.'
+ value 'INACTIVE', value: "inactive", description: 'Inactive pipeline schedules.'
+ end
+ end
+end
diff --git a/app/graphql/types/ci/pipeline_schedule_type.rb b/app/graphql/types/ci/pipeline_schedule_type.rb
new file mode 100644
index 00000000000..04f9fc78a92
--- /dev/null
+++ b/app/graphql/types/ci/pipeline_schedule_type.rb
@@ -0,0 +1,45 @@
+# frozen_string_literal: true
+
+module Types
+ module Ci
+ class PipelineScheduleType < BaseObject
+ graphql_name 'PipelineSchedule'
+
+ connection_type_class(Types::CountableConnectionType)
+
+ expose_permissions Types::PermissionTypes::Ci::PipelineSchedules
+
+ authorize :read_pipeline_schedule
+
+ field :id, GraphQL::Types::ID, null: false, description: 'ID of the pipeline schedule.'
+
+ field :description, GraphQL::Types::String, null: true, description: 'Description of the pipeline schedule.'
+
+ field :owner, ::Types::UserType, null: false, description: 'Owner of the pipeline schedule.'
+
+ field :active, GraphQL::Types::Boolean, null: false, description: 'Indicates if a pipeline schedule is active.'
+
+ field :next_run_at, Types::TimeType, null: false, description: 'Time when the next pipeline will run.'
+
+ field :real_next_run, Types::TimeType, null: false, description: 'Time when the next pipeline will run.'
+
+ field :last_pipeline, PipelineType, null: true, description: 'Last pipeline object.'
+
+ field :ref_for_display, GraphQL::Types::String,
+ null: true, description: 'Git ref for the pipeline schedule.', method: :ref_for_display
+
+ field :ref_path, GraphQL::Types::String, null: true, description: 'Path to the ref that triggered the pipeline.'
+
+ field :for_tag, GraphQL::Types::Boolean,
+ null: false, description: 'Indicates if a pipelines schedule belongs to a tag.', method: :for_tag?
+
+ field :cron, GraphQL::Types::String, null: false, description: 'Cron notation for the schedule.'
+
+ field :cron_timezone, GraphQL::Types::String, null: false, description: 'Timezone for the pipeline schedule.'
+
+ def ref_path
+ ::Gitlab::Routing.url_helpers.project_commits_path(object.project, object.ref_for_display)
+ end
+ 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 4fd7e0749b0..d59a68b427b 100644
--- a/app/graphql/types/ci/runner_membership_filter_enum.rb
+++ b/app/graphql/types/ci/runner_membership_filter_enum.rb
@@ -15,6 +15,13 @@ module Types
description: "Include runners that have either a direct or inherited relationship. " \
"These runners can be specific to a project or a group.",
value: :descendants
+
+ value 'ALL_AVAILABLE',
+ description:
+ "Include all runners. This list includes runners for all projects in the group " \
+ "and subgroups, as well as for the parent groups and instance.",
+ value: :all_available,
+ deprecated: { milestone: '15.5', reason: :alpha }
end
end
end
diff --git a/app/graphql/types/environment_type.rb b/app/graphql/types/environment_type.rb
index eb4e7b1dabf..dd2286d333d 100644
--- a/app/graphql/types/environment_type.rb
+++ b/app/graphql/types/environment_type.rb
@@ -57,7 +57,7 @@ module Types
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.',
+ description: 'Deployments of the environment. This field can only be resolved for one environment in any single request.',
resolver: Resolvers::DeploymentsResolver do
extension ::Gitlab::Graphql::Limit::FieldCallCount, limit: 1
end
@@ -72,3 +72,5 @@ module Types
end
end
end
+
+Types::EnvironmentType.prepend_mod_with('Types::EnvironmentType')
diff --git a/app/graphql/types/issue_type.rb b/app/graphql/types/issue_type.rb
index d897f3cde48..76fac831199 100644
--- a/app/graphql/types/issue_type.rb
+++ b/app/graphql/types/issue_type.rb
@@ -43,8 +43,10 @@ module Types
field :updated_by, Types::UserType, null: true,
description: 'User that last updated the issue.'
- field :labels, Types::LabelType.connection_type, null: true,
- description: 'Labels of the issue.'
+ field :labels, Types::LabelType.connection_type,
+ null: true,
+ description: 'Labels of the issue.',
+ resolver: Resolvers::BulkLabelsResolver
field :milestone, Types::MilestoneType, null: true,
description: 'Milestone of the issue.'
@@ -58,15 +60,20 @@ module Types
description: 'Indicates the issue is hidden because the author has been banned. ' \
'Will always return `null` if `ban_user_feature_flag` feature flag is disabled.'
- field :downvotes, GraphQL::Types::Int, null: false,
- description: 'Number of downvotes the issue has received.'
+ field :downvotes, GraphQL::Types::Int,
+ null: false,
+ description: 'Number of downvotes the issue has received.',
+ resolver: Resolvers::DownVotesCountResolver
field :merge_requests_count, GraphQL::Types::Int, null: false,
description: 'Number of merge requests that close the issue on merge.',
resolver: Resolvers::MergeRequestsCountResolver
field :relative_position, GraphQL::Types::Int, null: true,
description: 'Relative position of the issue (used for positioning in epic tree and issue boards).'
- field :upvotes, GraphQL::Types::Int, null: false,
- description: 'Number of upvotes the issue has received.'
+ field :upvotes, GraphQL::Types::Int,
+ null: false,
+ description: 'Number of upvotes the issue has received.',
+ resolver: Resolvers::UpVotesCountResolver
+
field :user_discussions_count, GraphQL::Types::Int, null: false,
description: 'Number of user discussions in the issue.',
resolver: Resolvers::UserDiscussionsCountResolver
diff --git a/app/graphql/types/merge_request_type.rb b/app/graphql/types/merge_request_type.rb
index 399dcc8e03d..8cc600fc68e 100644
--- a/app/graphql/types/merge_request_type.rb
+++ b/app/graphql/types/merge_request_type.rb
@@ -75,8 +75,12 @@ module Types
null: false, calls_gitaly: true,
method: :diverged_from_target_branch?,
description: 'Indicates if the source branch is behind the target branch.'
- field :downvotes, GraphQL::Types::Int, null: false,
- description: 'Number of downvotes for the merge request.'
+
+ field :downvotes, GraphQL::Types::Int,
+ null: false,
+ description: 'Number of downvotes for the merge request.',
+ resolver: Resolvers::DownVotesCountResolver
+
field :force_remove_source_branch, GraphQL::Types::Boolean, method: :force_remove_source_branch?, null: true,
description: 'Indicates if the project settings will lead to source branch deletion after merge.'
field :in_progress_merge_commit_sha, GraphQL::Types::String, null: true,
@@ -118,8 +122,12 @@ module Types
null: false, calls_gitaly: true,
method: :target_branch_exists?,
description: 'Indicates if the target branch of the merge request exists.'
- field :upvotes, GraphQL::Types::Int, null: false,
- description: 'Number of upvotes for the merge request.'
+
+ field :upvotes, GraphQL::Types::Int,
+ null: false,
+ description: 'Number of upvotes for the merge request.',
+ resolver: Resolvers::UpVotesCountResolver
+
field :user_discussions_count, GraphQL::Types::Int, null: true,
description: 'Number of user discussions in the merge request.',
resolver: Resolvers::UserDiscussionsCountResolver
@@ -150,8 +158,11 @@ module Types
description: 'Human-readable time estimate of the merge request.'
field :human_total_time_spent, GraphQL::Types::String, null: true,
description: 'Human-readable total time reported as spent on the merge request.'
- field :labels, Types::LabelType.connection_type, null: true, complexity: 5,
- description: 'Labels of the merge request.'
+ field :labels, Types::LabelType.connection_type,
+ null: true, complexity: 5,
+ description: 'Labels of the merge request.',
+ resolver: Resolvers::BulkLabelsResolver
+
field :milestone, Types::MilestoneType, null: true,
description: 'Milestone of the merge request.'
field :participants, Types::MergeRequests::ParticipantType.connection_type, null: true, complexity: 15,
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 3de6296154d..1ba72ae33b5 100644
--- a/app/graphql/types/merge_requests/detailed_merge_status_enum.rb
+++ b/app/graphql/types/merge_requests/detailed_merge_status_enum.rb
@@ -42,6 +42,9 @@ module Types
value 'POLICIES_DENIED',
value: :policies_denied,
description: 'There are denied policies for the merge request.'
+ value 'EXTERNAL_STATUS_CHECKS',
+ value: :status_checks_must_pass,
+ description: 'Status checks must pass.'
end
end
end
diff --git a/app/graphql/types/mutation_type.rb b/app/graphql/types/mutation_type.rb
index ea833b35085..5ffc1aeacad 100644
--- a/app/graphql/types/mutation_type.rb
+++ b/app/graphql/types/mutation_type.rb
@@ -114,6 +114,7 @@ module Types
mount_mutation Mutations::Ci::Pipeline::Cancel
mount_mutation Mutations::Ci::Pipeline::Destroy
mount_mutation Mutations::Ci::Pipeline::Retry
+ mount_mutation Mutations::Ci::PipelineSchedule::Delete
mount_mutation Mutations::Ci::CiCdSettingsUpdate, deprecated: {
reason: :renamed,
replacement: 'ProjectCiCdSettingsUpdate',
@@ -137,6 +138,8 @@ module Types
mount_mutation Mutations::UserCallouts::Create
mount_mutation Mutations::UserPreferences::Update
mount_mutation Mutations::Packages::Destroy
+ mount_mutation Mutations::Packages::BulkDestroy,
+ extensions: [::Gitlab::Graphql::Limit::FieldCallCount => { limit: 1 }]
mount_mutation Mutations::Packages::DestroyFile
mount_mutation Mutations::Packages::DestroyFiles
mount_mutation Mutations::Packages::Cleanup::Policy::Update
@@ -146,7 +149,6 @@ module Types
mount_mutation Mutations::WorkItems::Delete, alpha: { milestone: '15.1' }
mount_mutation Mutations::WorkItems::DeleteTask, alpha: { milestone: '15.1' }
mount_mutation Mutations::WorkItems::Update, alpha: { milestone: '15.1' }
- mount_mutation Mutations::WorkItems::UpdateWidgets, alpha: { milestone: '15.1' }
mount_mutation Mutations::WorkItems::UpdateTask, alpha: { milestone: '15.1' }
mount_mutation Mutations::SavedReplies::Create
mount_mutation Mutations::SavedReplies::Update
diff --git a/app/graphql/types/namespace/package_settings_type.rb b/app/graphql/types/namespace/package_settings_type.rb
index 7a0abe619a5..84becba8001 100644
--- a/app/graphql/types/namespace/package_settings_type.rb
+++ b/app/graphql/types/namespace/package_settings_type.rb
@@ -8,9 +8,50 @@ module Types
authorize :admin_package
- field :generic_duplicate_exception_regex, Types::UntrustedRegexp, null: true, description: 'When generic_duplicates_allowed is false, you can publish duplicate packages with names that match this regex. Otherwise, this setting has no effect.'
- field :generic_duplicates_allowed, GraphQL::Types::Boolean, null: false, description: 'Indicates whether duplicate generic packages are allowed for this namespace.'
- field :maven_duplicate_exception_regex, Types::UntrustedRegexp, null: true, description: 'When maven_duplicates_allowed is false, you can publish duplicate packages with names that match this regex. Otherwise, this setting has no effect.'
- field :maven_duplicates_allowed, GraphQL::Types::Boolean, null: false, description: 'Indicates whether duplicate Maven packages are allowed for this namespace.'
+ field :generic_duplicate_exception_regex, Types::UntrustedRegexp,
+ null: true,
+ description: 'When generic_duplicates_allowed is false, you can publish duplicate packages with names that match this regex. Otherwise, this setting has no effect.'
+ field :generic_duplicates_allowed, GraphQL::Types::Boolean,
+ null: false,
+ description: 'Indicates whether duplicate generic packages are allowed for this namespace.'
+ field :maven_duplicate_exception_regex, Types::UntrustedRegexp,
+ null: true,
+ description: 'When maven_duplicates_allowed is false, you can publish duplicate packages with names that match this regex. Otherwise, this setting has no effect.'
+ field :maven_duplicates_allowed, GraphQL::Types::Boolean,
+ null: false,
+ description: 'Indicates whether duplicate Maven packages are allowed for this namespace.'
+
+ field :maven_package_requests_forwarding, GraphQL::Types::Boolean,
+ null: true,
+ description: 'Indicates whether Maven package forwarding is allowed for this namespace.'
+ field :npm_package_requests_forwarding, GraphQL::Types::Boolean,
+ null: true,
+ description: 'Indicates whether npm package forwarding is allowed for this namespace.'
+ field :pypi_package_requests_forwarding, GraphQL::Types::Boolean,
+ null: true,
+ description: 'Indicates whether PyPI package forwarding is allowed for this namespace.'
+
+ field :lock_maven_package_requests_forwarding, GraphQL::Types::Boolean,
+ null: false,
+ description: 'Indicates whether Maven package forwarding is locked for all descendent namespaces.'
+ field :lock_npm_package_requests_forwarding, GraphQL::Types::Boolean,
+ null: false,
+ description: 'Indicates whether npm package forwarding is locked for all descendent namespaces.'
+ field :lock_pypi_package_requests_forwarding, GraphQL::Types::Boolean,
+ null: false,
+ description: 'Indicates whether PyPI package forwarding is locked for all descendent namespaces.'
+
+ field :maven_package_requests_forwarding_locked, GraphQL::Types::Boolean,
+ null: false,
+ method: :maven_package_requests_forwarding_locked?,
+ description: 'Indicates whether Maven package forwarding settings are locked by a parent namespace.'
+ field :npm_package_requests_forwarding_locked, GraphQL::Types::Boolean,
+ null: false,
+ method: :npm_package_requests_forwarding_locked?,
+ description: 'Indicates whether npm package forwarding settings are locked by a parent namespace.'
+ field :pypi_package_requests_forwarding_locked, GraphQL::Types::Boolean,
+ null: false,
+ method: :pypi_package_requests_forwarding_locked?,
+ description: 'Indicates whether PyPI package forwarding settings are locked by a parent namespace.'
end
end
diff --git a/app/graphql/types/notes/note_type.rb b/app/graphql/types/notes/note_type.rb
index c254460a51f..eef5ce40bde 100644
--- a/app/graphql/types/notes/note_type.rb
+++ b/app/graphql/types/notes/note_type.rb
@@ -41,7 +41,7 @@ module Types
deprecated: {
reason: :renamed,
replacement: 'internal',
- milestone: '15.3'
+ milestone: '15.5'
}
field :internal, GraphQL::Types::Boolean, null: true,
diff --git a/app/graphql/types/permission_types/ci/pipeline_schedules.rb b/app/graphql/types/permission_types/ci/pipeline_schedules.rb
new file mode 100644
index 00000000000..268ac6096d0
--- /dev/null
+++ b/app/graphql/types/permission_types/ci/pipeline_schedules.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+module Types
+ module PermissionTypes
+ module Ci
+ class PipelineSchedules < BasePermissionType
+ graphql_name 'PipelineSchedulePermissions'
+
+ abilities :take_ownership_pipeline_schedule,
+ :update_pipeline_schedule,
+ :admin_pipeline_schedule
+
+ ability_field :play_pipeline_schedule, calls_gitaly: true
+ end
+ end
+ end
+end
diff --git a/app/graphql/types/project_type.rb b/app/graphql/types/project_type.rb
index f43f5c27dac..a41af34ef4c 100644
--- a/app/graphql/types/project_type.rb
+++ b/app/graphql/types/project_type.rb
@@ -309,6 +309,12 @@ module Types
extras: [:lookahead],
resolver: Resolvers::ProjectPipelinesResolver
+ field :pipeline_schedules,
+ type: Types::Ci::PipelineScheduleType.connection_type,
+ null: true,
+ description: 'Pipeline schedules of the project. This field can only be resolved for one project per request.',
+ resolver: Resolvers::ProjectPipelineSchedulesResolver
+
field :pipeline, Types::Ci::PipelineType,
null: true,
description: 'Build pipeline of the project.',
diff --git a/app/graphql/types/projects/branch_rule_type.rb b/app/graphql/types/projects/branch_rule_type.rb
index 866cff0f439..e7632c17cca 100644
--- a/app/graphql/types/projects/branch_rule_type.rb
+++ b/app/graphql/types/projects/branch_rule_type.rb
@@ -13,6 +13,13 @@ module Types
null: false,
description: 'Branch name, with wildcards, for the branch rules.'
+ field :is_default,
+ type: GraphQL::Types::Boolean,
+ null: false,
+ method: :default_branch?,
+ calls_gitaly: true,
+ description: "Check if this branch rule protects the project's default branch."
+
field :branch_protection,
type: Types::BranchRules::BranchProtectionType,
null: false,
@@ -31,3 +38,5 @@ module Types
end
end
end
+
+Types::Projects::BranchRuleType.prepend_mod
diff --git a/app/graphql/types/query_type.rb b/app/graphql/types/query_type.rb
index 78463a1804a..1b39f43659e 100644
--- a/app/graphql/types/query_type.rb
+++ b/app/graphql/types/query_type.rb
@@ -154,6 +154,12 @@ module Types
null: true,
description: "Whether Gitpod is enabled in application settings."
+ field :jobs,
+ ::Types::Ci::JobType.connection_type,
+ null: true,
+ description: 'All jobs on this GitLab instance.',
+ resolver: ::Resolvers::Ci::AllJobsResolver
+
def design_management
DesignManagementObject.new(nil)
end
diff --git a/app/graphql/types/subscription_type.rb b/app/graphql/types/subscription_type.rb
index ef701bbfc10..3b8f5c64beb 100644
--- a/app/graphql/types/subscription_type.rb
+++ b/app/graphql/types/subscription_type.rb
@@ -13,6 +13,9 @@ module Types
field :issuable_title_updated, subscription: Subscriptions::IssuableUpdated, null: true,
description: 'Triggered when the title of an issuable is updated.'
+ field :issuable_description_updated, subscription: Subscriptions::IssuableUpdated, null: true,
+ description: 'Triggered when the description of an issuable is updated.'
+
field :issuable_labels_updated, subscription: Subscriptions::IssuableUpdated, null: true,
description: 'Triggered when the labels of an issuable are updated.'
@@ -23,6 +26,11 @@ module Types
subscription: Subscriptions::IssuableUpdated,
null: true,
description: 'Triggered when the reviewers of a merge request are updated.'
+
+ field :merge_request_merge_status_updated,
+ subscription: Subscriptions::IssuableUpdated,
+ null: true,
+ description: 'Triggered when the merge status of a merge request is updated.'
end
end
diff --git a/app/graphql/types/work_items/widget_interface.rb b/app/graphql/types/work_items/widget_interface.rb
index eca8c8d845a..a3943361114 100644
--- a/app/graphql/types/work_items/widget_interface.rb
+++ b/app/graphql/types/work_items/widget_interface.rb
@@ -23,6 +23,9 @@ module Types
ORPHAN_TYPES
end
+ # Whenever a new widget is added make sure to update the spec to avoid N + 1 queries in
+ # spec/requests/api/graphql/project/work_items_spec.rb and add the necessary preloads
+ # in app/graphql/resolvers/work_items_resolver.rb
def self.resolve_type(object, context)
case object
when ::WorkItems::Widgets::Description
diff --git a/app/graphql/types/work_items/widgets/labels_update_input_type.rb b/app/graphql/types/work_items/widgets/labels_update_input_type.rb
new file mode 100644
index 00000000000..d38b8cefa63
--- /dev/null
+++ b/app/graphql/types/work_items/widgets/labels_update_input_type.rb
@@ -0,0 +1,20 @@
+# frozen_string_literal: true
+
+module Types
+ module WorkItems
+ module Widgets
+ class LabelsUpdateInputType < BaseInputObject
+ graphql_name 'WorkItemWidgetLabelsUpdateInput'
+
+ argument :add_label_ids, [Types::GlobalIDType[::Label]],
+ required: false,
+ description: 'Global IDs of labels to be added to the work item.',
+ prepare: ->(label_ids, _ctx) { label_ids.map(&:model_id) }
+ argument :remove_label_ids, [Types::GlobalIDType[::Label]],
+ required: false,
+ description: 'Global IDs of labels to be removed from the work item.',
+ prepare: ->(label_ids, _ctx) { label_ids.map(&:model_id) }
+ end
+ end
+ end
+end