summaryrefslogtreecommitdiff
path: root/app/graphql
diff options
context:
space:
mode:
Diffstat (limited to 'app/graphql')
-rw-r--r--app/graphql/gitlab_schema.rb8
-rw-r--r--app/graphql/mutations/customer_relations/contacts/create.rb4
-rw-r--r--app/graphql/mutations/customer_relations/contacts/update.rb4
-rw-r--r--app/graphql/mutations/customer_relations/organizations/create.rb4
-rw-r--r--app/graphql/mutations/customer_relations/organizations/update.rb4
-rw-r--r--app/graphql/mutations/issues/create.rb9
-rw-r--r--app/graphql/mutations/issues/set_crm_contacts.rb48
-rw-r--r--app/graphql/mutations/merge_requests/set_wip.rb35
-rw-r--r--app/graphql/mutations/merge_requests/toggle_attention_requested.rb27
-rw-r--r--app/graphql/mutations/security/ci_configuration/configure_sast_iac.rb21
-rw-r--r--app/graphql/queries/epic/epic_children.query.graphql1
-rw-r--r--app/graphql/resolvers/base_issues_resolver.rb61
-rw-r--r--app/graphql/resolvers/ci/pipeline_job_artifacts_resolver.rb25
-rw-r--r--app/graphql/resolvers/concerns/issue_resolver_arguments.rb26
-rw-r--r--app/graphql/resolvers/concerns/resolves_groups.rb34
-rw-r--r--app/graphql/resolvers/concerns/resolves_pipelines.rb3
-rw-r--r--app/graphql/resolvers/group_issues_resolver.rb12
-rw-r--r--app/graphql/resolvers/groups_resolver.rb12
-rw-r--r--app/graphql/resolvers/issue_status_counts_resolver.rb1
-rw-r--r--app/graphql/resolvers/issues_resolver.rb59
-rw-r--r--app/graphql/resolvers/merge_requests_resolver.rb6
-rw-r--r--app/graphql/resolvers/topics_resolver.rb19
-rw-r--r--app/graphql/resolvers/users/groups_resolver.rb17
-rw-r--r--app/graphql/types/ci/job_artifact_type.rb4
-rw-r--r--app/graphql/types/ci/pipeline_scope_enum.rb21
-rw-r--r--app/graphql/types/ci/pipeline_status_enum.rb22
-rw-r--r--app/graphql/types/ci/pipeline_type.rb9
-rw-r--r--app/graphql/types/ci/runner_setup_type.rb2
-rw-r--r--app/graphql/types/commit_type.rb7
-rw-r--r--app/graphql/types/customer_relations/contact_type.rb2
-rw-r--r--app/graphql/types/customer_relations/organization_type.rb2
-rw-r--r--app/graphql/types/dependency_proxy/manifest_type.rb1
-rw-r--r--app/graphql/types/evidence_type.rb2
-rw-r--r--app/graphql/types/group_type.rb10
-rw-r--r--app/graphql/types/issues/negated_issue_filter_input_type.rb3
-rw-r--r--app/graphql/types/merge_request_type.rb6
-rw-r--r--app/graphql/types/mutation_type.rb6
-rw-r--r--app/graphql/types/packages/file_metadata_type.rb5
-rw-r--r--app/graphql/types/packages/helm/dependency_type.rb28
-rw-r--r--app/graphql/types/packages/helm/file_metadatum_type.rb19
-rw-r--r--app/graphql/types/packages/helm/maintainer_type.rb18
-rw-r--r--app/graphql/types/packages/helm/metadata_type.rb32
-rw-r--r--app/graphql/types/packages/package_file_type.rb2
-rw-r--r--app/graphql/types/project_type.rb7
-rw-r--r--app/graphql/types/projects/topic_type.rb28
-rw-r--r--app/graphql/types/query_type.rb5
-rw-r--r--app/graphql/types/release_links_type.rb17
-rw-r--r--app/graphql/types/release_tag_wildcard_id_enum.rb11
-rw-r--r--app/graphql/types/release_type.rb3
-rw-r--r--app/graphql/types/repository/blob_type.rb3
-rw-r--r--app/graphql/types/repository_type.rb3
51 files changed, 558 insertions, 160 deletions
diff --git a/app/graphql/gitlab_schema.rb b/app/graphql/gitlab_schema.rb
index 38ba1611c48..e15a185a743 100644
--- a/app/graphql/gitlab_schema.rb
+++ b/app/graphql/gitlab_schema.rb
@@ -10,11 +10,17 @@ class GitlabSchema < GraphQL::Schema
DEFAULT_MAX_DEPTH = 15
AUTHENTICATED_MAX_DEPTH = 20
+ # Tracers (order is important)
+ use Gitlab::Graphql::Tracers::ApplicationContextTracer
+ use Gitlab::Graphql::Tracers::MetricsTracer
+ use Gitlab::Graphql::Tracers::LoggerTracer
+ use Gitlab::Graphql::GenericTracing # Old tracer which will be removed eventually
+ use Gitlab::Graphql::Tracers::TimerTracer
+
use GraphQL::Subscriptions::ActionCableSubscriptions
use GraphQL::Pagination::Connections
use BatchLoader::GraphQL
use Gitlab::Graphql::Pagination::Connections
- use Gitlab::Graphql::GenericTracing
use Gitlab::Graphql::Timeout, max_seconds: Gitlab.config.gitlab.graphql_timeout
query_analyzer Gitlab::Graphql::QueryAnalyzers::LoggerAnalyzer.new
diff --git a/app/graphql/mutations/customer_relations/contacts/create.rb b/app/graphql/mutations/customer_relations/contacts/create.rb
index 77b4864468b..3495f30f227 100644
--- a/app/graphql/mutations/customer_relations/contacts/create.rb
+++ b/app/graphql/mutations/customer_relations/contacts/create.rb
@@ -42,13 +42,11 @@ module Mutations
required: false,
description: 'Description of or notes for the contact.'
- authorize :admin_contact
+ authorize :admin_crm_contact
def resolve(args)
group = authorized_find!(id: args[:group_id])
- raise Gitlab::Graphql::Errors::ResourceNotAvailable, 'Feature disabled' unless Feature.enabled?(:customer_relations, group, default_enabled: :yaml)
-
set_organization!(args)
result = ::CustomerRelations::Contacts::CreateService.new(group: group, current_user: current_user, params: args).execute
{ contact: result.payload, errors: result.errors }
diff --git a/app/graphql/mutations/customer_relations/contacts/update.rb b/app/graphql/mutations/customer_relations/contacts/update.rb
index e9e7c9b6abd..e2f671058f0 100644
--- a/app/graphql/mutations/customer_relations/contacts/update.rb
+++ b/app/graphql/mutations/customer_relations/contacts/update.rb
@@ -8,7 +8,7 @@ module Mutations
graphql_name 'CustomerRelationsContactUpdate'
- authorize :admin_contact
+ authorize :admin_crm_contact
field :contact,
Types::CustomerRelations::ContactType,
@@ -48,8 +48,6 @@ module Mutations
raise_resource_not_available_error! unless contact
group = contact.group
- raise Gitlab::Graphql::Errors::ResourceNotAvailable, 'Feature disabled' unless Feature.enabled?(:customer_relations, group, default_enabled: :yaml)
-
authorize!(group)
result = ::CustomerRelations::Contacts::UpdateService.new(group: group, current_user: current_user, params: args).execute(contact)
diff --git a/app/graphql/mutations/customer_relations/organizations/create.rb b/app/graphql/mutations/customer_relations/organizations/create.rb
index bb02e1f7346..17e0e9ad459 100644
--- a/app/graphql/mutations/customer_relations/organizations/create.rb
+++ b/app/graphql/mutations/customer_relations/organizations/create.rb
@@ -33,13 +33,11 @@ module Mutations
required: false,
description: 'Description of or notes for the organization.'
- authorize :admin_organization
+ authorize :admin_crm_organization
def resolve(args)
group = authorized_find!(id: args[:group_id])
- raise Gitlab::Graphql::Errors::ResourceNotAvailable, 'Feature disabled' unless Feature.enabled?(:customer_relations, group, default_enabled: :yaml)
-
result = ::CustomerRelations::Organizations::CreateService.new(group: group, current_user: current_user, params: args).execute
{ organization: result.payload, errors: result.errors }
end
diff --git a/app/graphql/mutations/customer_relations/organizations/update.rb b/app/graphql/mutations/customer_relations/organizations/update.rb
index d8eb55d77e9..21fcf565239 100644
--- a/app/graphql/mutations/customer_relations/organizations/update.rb
+++ b/app/graphql/mutations/customer_relations/organizations/update.rb
@@ -8,7 +8,7 @@ module Mutations
graphql_name 'CustomerRelationsOrganizationUpdate'
- authorize :admin_organization
+ authorize :admin_crm_organization
field :organization,
Types::CustomerRelations::OrganizationType,
@@ -39,8 +39,6 @@ module Mutations
raise_resource_not_available_error! unless organization
group = organization.group
- raise Gitlab::Graphql::Errors::ResourceNotAvailable, 'Feature disabled' unless Feature.enabled?(:customer_relations, group, default_enabled: :yaml)
-
authorize!(group)
result = ::CustomerRelations::Organizations::UpdateService.new(group: group, current_user: current_user, params: args).execute(organization)
diff --git a/app/graphql/mutations/issues/create.rb b/app/graphql/mutations/issues/create.rb
index 70a8f539ccf..72b03cc27c2 100644
--- a/app/graphql/mutations/issues/create.rb
+++ b/app/graphql/mutations/issues/create.rb
@@ -3,13 +3,14 @@
module Mutations
module Issues
class Create < BaseMutation
+ include Mutations::SpamProtection
include FindsProject
+ include CommonMutationArguments
+
graphql_name 'CreateIssue'
authorize :create_issue
- include CommonMutationArguments
-
argument :project_path, GraphQL::Types::ID,
required: true,
description: 'Project full path the issue is associated with.'
@@ -76,9 +77,7 @@ module Mutations
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
- if issue.spam?
- issue.errors.add(:base, 'Spam detected.')
- end
+ check_spam_action_response!(issue)
{
issue: issue.valid? ? issue : nil,
diff --git a/app/graphql/mutations/issues/set_crm_contacts.rb b/app/graphql/mutations/issues/set_crm_contacts.rb
new file mode 100644
index 00000000000..7a9e6237eaa
--- /dev/null
+++ b/app/graphql/mutations/issues/set_crm_contacts.rb
@@ -0,0 +1,48 @@
+# frozen_string_literal: true
+
+module Mutations
+ module Issues
+ class SetCrmContacts < Base
+ graphql_name 'IssueSetCrmContacts'
+
+ argument :crm_contact_ids,
+ [::Types::GlobalIDType[::CustomerRelations::Contact]],
+ required: true,
+ description: 'Customer relations contact IDs to set. Replaces existing contacts by default.'
+
+ argument :operation_mode,
+ Types::MutationOperationModeEnum,
+ required: false,
+ description: 'Changes the operation mode. Defaults to REPLACE.'
+
+ def resolve(project_path:, iid:, crm_contact_ids:, operation_mode: Types::MutationOperationModeEnum.enum[:replace])
+ issue = authorized_find!(project_path: project_path, iid: iid)
+ project = issue.project
+ raise Gitlab::Graphql::Errors::ResourceNotAvailable, 'Feature disabled' unless Feature.enabled?(:customer_relations, project.group, default_enabled: :yaml)
+
+ crm_contact_ids = crm_contact_ids.compact.map do |crm_contact_id|
+ raise Gitlab::Graphql::Errors::ArgumentError, "Contact #{crm_contact_id} is invalid." unless crm_contact_id.respond_to?(:model_id)
+
+ crm_contact_id.model_id.to_i
+ end
+
+ attribute_name = case operation_mode
+ when Types::MutationOperationModeEnum.enum[:append]
+ :add_crm_contact_ids
+ when Types::MutationOperationModeEnum.enum[:remove]
+ :remove_crm_contact_ids
+ else
+ :crm_contact_ids
+ end
+
+ response = ::Issues::SetCrmContactsService.new(project: project, current_user: current_user, params: { attribute_name => crm_contact_ids })
+ .execute(issue)
+
+ {
+ issue: issue,
+ errors: response.errors
+ }
+ end
+ end
+ end
+end
diff --git a/app/graphql/mutations/merge_requests/set_wip.rb b/app/graphql/mutations/merge_requests/set_wip.rb
deleted file mode 100644
index 9b6b67d4b4f..00000000000
--- a/app/graphql/mutations/merge_requests/set_wip.rb
+++ /dev/null
@@ -1,35 +0,0 @@
-# frozen_string_literal: true
-
-module Mutations
- module MergeRequests
- class SetWip < Base
- graphql_name 'MergeRequestSetWip'
-
- argument :wip,
- GraphQL::Types::Boolean,
- required: true,
- description: <<~DESC
- Whether or not to set the merge request as a draft.
- DESC
-
- def resolve(project_path:, iid:, wip: nil)
- merge_request = authorized_find!(project_path: project_path, iid: iid)
- project = merge_request.project
-
- ::MergeRequests::UpdateService.new(project: project, current_user: current_user, params: { wip_event: wip_event(merge_request, wip) })
- .execute(merge_request)
-
- {
- merge_request: merge_request,
- errors: errors_on_object(merge_request)
- }
- end
-
- private
-
- def wip_event(merge_request, wip)
- wip ? 'wip' : 'unwip'
- end
- end
- end
-end
diff --git a/app/graphql/mutations/merge_requests/toggle_attention_requested.rb b/app/graphql/mutations/merge_requests/toggle_attention_requested.rb
new file mode 100644
index 00000000000..f316f23fb85
--- /dev/null
+++ b/app/graphql/mutations/merge_requests/toggle_attention_requested.rb
@@ -0,0 +1,27 @@
+# frozen_string_literal: true
+
+module Mutations
+ module MergeRequests
+ class ToggleAttentionRequested < Base
+ graphql_name 'MergeRequestToggleAttentionRequested'
+
+ argument :user_id, ::Types::GlobalIDType[::User],
+ loads: Types::UserType,
+ required: true,
+ description: <<~DESC
+ User ID for the user to toggle attention requested.
+ DESC
+
+ def resolve(project_path:, iid:, user:)
+ merge_request = authorized_find!(project_path: project_path, iid: iid)
+
+ result = ::MergeRequests::ToggleAttentionRequestedService.new(project: merge_request.project, current_user: current_user, merge_request: merge_request, user: user).execute
+
+ {
+ merge_request: merge_request,
+ errors: Array(result[:message])
+ }
+ end
+ end
+ end
+end
diff --git a/app/graphql/mutations/security/ci_configuration/configure_sast_iac.rb b/app/graphql/mutations/security/ci_configuration/configure_sast_iac.rb
new file mode 100644
index 00000000000..a2073f10b1d
--- /dev/null
+++ b/app/graphql/mutations/security/ci_configuration/configure_sast_iac.rb
@@ -0,0 +1,21 @@
+# frozen_string_literal: true
+
+module Mutations
+ module Security
+ module CiConfiguration
+ class ConfigureSastIac < BaseSecurityAnalyzer
+ graphql_name 'ConfigureSastIac'
+ description <<~DESC
+ Enable SAST IaC for a project in a new or
+ modified `.gitlab-ci.yml` file in a new branch. The new
+ branch and a URL to create a merge request are a part of the
+ response.
+ DESC
+
+ def configure_analyzer(project, **_args)
+ ::Security::CiConfiguration::SastIacCreateService.new(project, current_user).execute
+ end
+ end
+ end
+ end
+end
diff --git a/app/graphql/queries/epic/epic_children.query.graphql b/app/graphql/queries/epic/epic_children.query.graphql
index b0e55811b7d..be82813dddb 100644
--- a/app/graphql/queries/epic/epic_children.query.graphql
+++ b/app/graphql/queries/epic/epic_children.query.graphql
@@ -89,6 +89,7 @@ query childItems(
iid
epicIssueId
title
+ blocked
closedAt
state
createdAt
diff --git a/app/graphql/resolvers/base_issues_resolver.rb b/app/graphql/resolvers/base_issues_resolver.rb
new file mode 100644
index 00000000000..54ebb697cb2
--- /dev/null
+++ b/app/graphql/resolvers/base_issues_resolver.rb
@@ -0,0 +1,61 @@
+# frozen_string_literal: true
+
+module Resolvers
+ class BaseIssuesResolver < BaseResolver
+ prepend IssueResolverArguments
+
+ argument :state, Types::IssuableStateEnum,
+ required: false,
+ description: 'Current state of this issue.'
+ argument :sort, Types::IssueSortEnum,
+ description: 'Sort issues by this criteria.',
+ required: false,
+ default_value: :created_desc
+
+ type Types::IssueType.connection_type, null: true
+
+ NON_STABLE_CURSOR_SORTS = %i[priority_asc priority_desc
+ popularity_asc popularity_desc
+ label_priority_asc label_priority_desc
+ milestone_due_asc milestone_due_desc].freeze
+
+ def continue_issue_resolve(parent, finder, **args)
+ issues = Gitlab::Graphql::Loaders::IssuableLoader.new(parent, finder).batching_find_all { |q| apply_lookahead(q) }
+
+ if non_stable_cursor_sort?(args[:sort])
+ # Certain complex sorts are not supported by the stable cursor pagination yet.
+ # In these cases, we use offset pagination, so we return the correct connection.
+ offset_pagination(issues)
+ else
+ issues
+ end
+ end
+
+ private
+
+ def unconditional_includes
+ [
+ {
+ project: [:project_feature]
+ },
+ :author
+ ]
+ end
+
+ def preloads
+ {
+ alert_management_alert: [:alert_management_alert],
+ labels: [:labels],
+ assignees: [:assignees],
+ timelogs: [:timelogs],
+ customer_relations_contacts: { customer_relations_contacts: [:group] }
+ }
+ end
+
+ def non_stable_cursor_sort?(sort)
+ NON_STABLE_CURSOR_SORTS.include?(sort)
+ end
+ end
+end
+
+Resolvers::BaseIssuesResolver.prepend_mod_with('Resolvers::BaseIssuesResolver')
diff --git a/app/graphql/resolvers/ci/pipeline_job_artifacts_resolver.rb b/app/graphql/resolvers/ci/pipeline_job_artifacts_resolver.rb
new file mode 100644
index 00000000000..35d30827561
--- /dev/null
+++ b/app/graphql/resolvers/ci/pipeline_job_artifacts_resolver.rb
@@ -0,0 +1,25 @@
+# frozen_string_literal: true
+
+module Resolvers
+ module Ci
+ class PipelineJobArtifactsResolver < BaseResolver
+ type [Types::Ci::JobArtifactType], null: false
+
+ alias_method :pipeline, :object
+
+ def resolve
+ find_job_artifacts
+ end
+
+ private
+
+ def find_job_artifacts
+ BatchLoader::GraphQL.for(pipeline).batch do |pipelines, loader|
+ ActiveRecord::Associations::Preloader.new.preload(pipelines, :job_artifacts) # rubocop: disable CodeReuse/ActiveRecord
+
+ pipelines.each { |pl| loader.call(pl, pl.job_artifacts) }
+ end
+ end
+ end
+ end
+end
diff --git a/app/graphql/resolvers/concerns/issue_resolver_arguments.rb b/app/graphql/resolvers/concerns/issue_resolver_arguments.rb
index 855877110e5..38c79ff52ac 100644
--- a/app/graphql/resolvers/concerns/issue_resolver_arguments.rb
+++ b/app/graphql/resolvers/concerns/issue_resolver_arguments.rb
@@ -55,8 +55,8 @@ module IssueResolverArguments
description: 'Filter issues by the given issue types.',
required: false
argument :milestone_wildcard_id, ::Types::MilestoneWildcardIdEnum,
- required: false,
- description: 'Filter issues by milestone ID wildcard.'
+ required: false,
+ description: 'Filter issues by milestone ID wildcard.'
argument :my_reaction_emoji, GraphQL::Types::String,
required: false,
description: 'Filter by reaction emoji applied by the current user. Wildcard values "NONE" and "ANY" are supported.'
@@ -83,6 +83,7 @@ module IssueResolverArguments
args[:attempt_project_search_optimizations] = true if args[:search].present?
prepare_assignee_username_params(args)
+ prepare_release_tag_params(args)
finder = IssuesFinder.new(current_user, args)
@@ -93,6 +94,7 @@ module IssueResolverArguments
params_not_mutually_exclusive(args, mutually_exclusive_assignee_username_args)
params_not_mutually_exclusive(args, mutually_exclusive_milestone_args)
params_not_mutually_exclusive(args.fetch(:not, {}), mutually_exclusive_milestone_args)
+ params_not_mutually_exclusive(args, mutually_exclusive_release_tag_args)
validate_anonymous_search_access! if args[:search].present?
super
@@ -105,10 +107,30 @@ module IssueResolverArguments
complexity
end
+
+ def accept_release_tag
+ argument :release_tag, [GraphQL::Types::String],
+ required: false,
+ description: "Release tag associated with the issue's milestone."
+ argument :release_tag_wildcard_id, Types::ReleaseTagWildcardIdEnum,
+ required: false,
+ description: 'Filter issues by release tag ID wildcard.'
+ end
end
private
+ def prepare_release_tag_params(args)
+ release_tag_wildcard = args.delete(:release_tag_wildcard_id)
+ return if release_tag_wildcard.blank?
+
+ args[:release_tag] ||= release_tag_wildcard
+ end
+
+ def mutually_exclusive_release_tag_args
+ [:release_tag, :release_tag_wildcard_id]
+ end
+
def prepare_assignee_username_params(args)
args[:assignee_username] = args.delete(:assignee_usernames) if args[:assignee_usernames].present?
args[:not][:assignee_username] = args[:not].delete(:assignee_usernames) if args.dig(:not, :assignee_usernames).present?
diff --git a/app/graphql/resolvers/concerns/resolves_groups.rb b/app/graphql/resolvers/concerns/resolves_groups.rb
new file mode 100644
index 00000000000..c451d4e7936
--- /dev/null
+++ b/app/graphql/resolvers/concerns/resolves_groups.rb
@@ -0,0 +1,34 @@
+# frozen_string_literal: true
+
+# Mixin for all resolver classes for type `Types::GroupType.connection_type`.
+module ResolvesGroups
+ extend ActiveSupport::Concern
+ include LooksAhead
+
+ def resolve_with_lookahead(**args)
+ apply_lookahead(resolve_groups(**args))
+ end
+
+ private
+
+ # The resolver should implement this method.
+ def resolve_groups(**args)
+ raise NotImplementedError
+ end
+
+ def preloads
+ {
+ contacts: [:contacts],
+ container_repositories_count: [:container_repositories],
+ custom_emoji: [:custom_emoji],
+ full_path: [:route],
+ organizations: [:organizations],
+ path: [:route],
+ dependency_proxy_blob_count: [:dependency_proxy_blobs],
+ dependency_proxy_blobs: [:dependency_proxy_blobs],
+ dependency_proxy_image_count: [:dependency_proxy_manifests],
+ dependency_proxy_image_ttl_policy: [:dependency_proxy_image_ttl_policy],
+ dependency_proxy_setting: [:dependency_proxy_setting]
+ }
+ end
+end
diff --git a/app/graphql/resolvers/concerns/resolves_pipelines.rb b/app/graphql/resolvers/concerns/resolves_pipelines.rb
index 7fb0852b11e..1c01e5e0250 100644
--- a/app/graphql/resolvers/concerns/resolves_pipelines.rb
+++ b/app/graphql/resolvers/concerns/resolves_pipelines.rb
@@ -9,6 +9,9 @@ module ResolvesPipelines
Types::Ci::PipelineStatusEnum,
required: false,
description: "Filter pipelines by their status."
+ argument :scope, ::Types::Ci::PipelineScopeEnum,
+ required: false,
+ description: 'Filter pipelines by scope.'
argument :ref,
GraphQL::Types::String,
required: false,
diff --git a/app/graphql/resolvers/group_issues_resolver.rb b/app/graphql/resolvers/group_issues_resolver.rb
index 1db0ab08e31..28f9266974f 100644
--- a/app/graphql/resolvers/group_issues_resolver.rb
+++ b/app/graphql/resolvers/group_issues_resolver.rb
@@ -1,10 +1,18 @@
# frozen_string_literal: true
-# rubocop:disable Graphql/ResolverType (inherited from IssuesResolver)
+# rubocop:disable Graphql/ResolverType (inherited from BaseIssuesResolver)
module Resolvers
- class GroupIssuesResolver < IssuesResolver
+ class GroupIssuesResolver < BaseIssuesResolver
include GroupIssuableResolver
include_subgroups 'issues'
+
+ def ready?(**args)
+ if args.dig(:not, :release_tag).present?
+ raise ::Gitlab::Graphql::Errors::ArgumentError, 'releaseTag filter is not allowed when parent is a group.'
+ end
+
+ super
+ end
end
end
diff --git a/app/graphql/resolvers/groups_resolver.rb b/app/graphql/resolvers/groups_resolver.rb
index b090fdc49d4..abd3bf9e6e0 100644
--- a/app/graphql/resolvers/groups_resolver.rb
+++ b/app/graphql/resolvers/groups_resolver.rb
@@ -2,6 +2,8 @@
module Resolvers
class GroupsResolver < BaseResolver
+ include ResolvesGroups
+
type Types::GroupType, null: true
argument :include_parent_descendants, GraphQL::Types::Boolean,
@@ -19,16 +21,12 @@ module Resolvers
alias_method :parent, :object
- def resolve(**args)
- return [] unless parent.present?
-
- find_groups(args)
- end
-
private
# rubocop: disable CodeReuse/ActiveRecord
- def find_groups(args)
+ def resolve_groups(args)
+ return Group.none unless parent.present?
+
GroupsFinder
.new(context[:current_user], args.merge(parent: parent))
.execute
diff --git a/app/graphql/resolvers/issue_status_counts_resolver.rb b/app/graphql/resolvers/issue_status_counts_resolver.rb
index 58cff559d0d..db5c91daac2 100644
--- a/app/graphql/resolvers/issue_status_counts_resolver.rb
+++ b/app/graphql/resolvers/issue_status_counts_resolver.rb
@@ -5,6 +5,7 @@ module Resolvers
prepend IssueResolverArguments
type Types::IssueStatusCountsType, null: true
+ accept_release_tag
extras [:lookahead]
diff --git a/app/graphql/resolvers/issues_resolver.rb b/app/graphql/resolvers/issues_resolver.rb
index b556964ae0c..4b52ef61d57 100644
--- a/app/graphql/resolvers/issues_resolver.rb
+++ b/app/graphql/resolvers/issues_resolver.rb
@@ -1,61 +1,8 @@
# frozen_string_literal: true
+# rubocop:disable Graphql/ResolverType (inherited from BaseIssuesResolver)
module Resolvers
- class IssuesResolver < BaseResolver
- prepend IssueResolverArguments
-
- argument :state, Types::IssuableStateEnum,
- required: false,
- description: 'Current state of this issue.'
- argument :sort, Types::IssueSortEnum,
- description: 'Sort issues by this criteria.',
- required: false,
- default_value: :created_desc
-
- type Types::IssueType.connection_type, null: true
-
- NON_STABLE_CURSOR_SORTS = %i[priority_asc priority_desc
- popularity_asc popularity_desc
- label_priority_asc label_priority_desc
- milestone_due_asc milestone_due_desc].freeze
-
- def continue_issue_resolve(parent, finder, **args)
- issues = Gitlab::Graphql::Loaders::IssuableLoader.new(parent, finder).batching_find_all { |q| apply_lookahead(q) }
-
- if non_stable_cursor_sort?(args[:sort])
- # Certain complex sorts are not supported by the stable cursor pagination yet.
- # In these cases, we use offset pagination, so we return the correct connection.
- offset_pagination(issues)
- else
- issues
- end
- end
-
- private
-
- def unconditional_includes
- [
- {
- project: [:project_feature]
- },
- :author
- ]
- end
-
- def preloads
- {
- alert_management_alert: [:alert_management_alert],
- labels: [:labels],
- assignees: [:assignees],
- timelogs: [:timelogs],
- customer_relations_contacts: { customer_relations_contacts: [:group] }
- }
- end
-
- def non_stable_cursor_sort?(sort)
- NON_STABLE_CURSOR_SORTS.include?(sort)
- end
+ class IssuesResolver < BaseIssuesResolver
+ accept_release_tag
end
end
-
-Resolvers::IssuesResolver.prepend_mod_with('Resolvers::IssuesResolver')
diff --git a/app/graphql/resolvers/merge_requests_resolver.rb b/app/graphql/resolvers/merge_requests_resolver.rb
index c0dd61078c6..bd7f1f0774e 100644
--- a/app/graphql/resolvers/merge_requests_resolver.rb
+++ b/app/graphql/resolvers/merge_requests_resolver.rb
@@ -68,6 +68,12 @@ module Resolvers
description: 'Sort merge requests by this criteria.',
required: false,
default_value: :created_desc
+ argument :created_after, Types::TimeType,
+ required: false,
+ description: 'Merge requests created after this timestamp.'
+ argument :created_before, Types::TimeType,
+ required: false,
+ description: 'Merge requests created before this timestamp.'
negated do
argument :labels, [GraphQL::Types::String],
diff --git a/app/graphql/resolvers/topics_resolver.rb b/app/graphql/resolvers/topics_resolver.rb
new file mode 100644
index 00000000000..d8199f3d89b
--- /dev/null
+++ b/app/graphql/resolvers/topics_resolver.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+module Resolvers
+ class TopicsResolver < BaseResolver
+ type Types::Projects::TopicType, null: true
+
+ argument :search, GraphQL::Types::String,
+ required: false,
+ description: 'Search query for topic name.'
+
+ def resolve(**args)
+ if args[:search].present?
+ ::Projects::Topic.search(args[:search]).order_by_total_projects_count
+ else
+ ::Projects::Topic.order_by_total_projects_count
+ end
+ end
+ end
+end
diff --git a/app/graphql/resolvers/users/groups_resolver.rb b/app/graphql/resolvers/users/groups_resolver.rb
index 0899b08e19c..eafb56d8f4c 100644
--- a/app/graphql/resolvers/users/groups_resolver.rb
+++ b/app/graphql/resolvers/users/groups_resolver.rb
@@ -3,8 +3,8 @@
module Resolvers
module Users
class GroupsResolver < BaseResolver
+ include ResolvesGroups
include Gitlab::Graphql::Authorize::AuthorizeResource
- include LooksAhead
type Types::GroupType.connection_type, null: true
@@ -20,22 +20,17 @@ module Resolvers
description: 'Filter by permissions the user has on groups.'
before_connection_authorization do |nodes, current_user|
- Preloaders::UserMaxAccessLevelInGroupsPreloader.new(nodes, current_user).execute
+ Preloaders::GroupPolicyPreloader.new(nodes, current_user).execute
end
- def resolve_with_lookahead(**args)
- return unless Feature.enabled?(:paginatable_namespace_drop_down_for_project_creation, current_user, default_enabled: :yaml)
-
- apply_lookahead(Groups::UserGroupsFinder.new(current_user, object, args).execute)
+ def ready?(**args)
+ Feature.enabled?(:paginatable_namespace_drop_down_for_project_creation, current_user, default_enabled: :yaml)
end
private
- def preloads
- {
- path: [:route],
- full_path: [:route]
- }
+ def resolve_groups(**args)
+ Groups::UserGroupsFinder.new(current_user, object, args).execute
end
end
end
diff --git a/app/graphql/types/ci/job_artifact_type.rb b/app/graphql/types/ci/job_artifact_type.rb
index f80681bcf36..69bb5325dba 100644
--- a/app/graphql/types/ci/job_artifact_type.rb
+++ b/app/graphql/types/ci/job_artifact_type.rb
@@ -12,6 +12,10 @@ module Types
field :file_type, ::Types::Ci::JobArtifactFileTypeEnum, null: true,
description: 'File type of the artifact.'
+ field :name, GraphQL::Types::String, null: true,
+ description: 'File name of the artifact.',
+ method: :filename
+
def download_path
::Gitlab::Routing.url_helpers.download_project_job_artifacts_path(
object.project,
diff --git a/app/graphql/types/ci/pipeline_scope_enum.rb b/app/graphql/types/ci/pipeline_scope_enum.rb
new file mode 100644
index 00000000000..3ce81bc7bf3
--- /dev/null
+++ b/app/graphql/types/ci/pipeline_scope_enum.rb
@@ -0,0 +1,21 @@
+# frozen_string_literal: true
+
+module Types
+ module Ci
+ class PipelineScopeEnum < BaseEnum
+ SCOPES_DESCRIPTION = {
+ running: 'Pipeline is running.',
+ pending: 'Pipeline has not started running yet.',
+ finished: 'Pipeline has completed.',
+ branches: 'Branches.',
+ tags: 'Tags.'
+ }.freeze
+
+ SCOPES_DESCRIPTION.each do |scope, description|
+ value scope.to_s.upcase,
+ description: description,
+ value: scope.to_s
+ end
+ end
+ end
+end
diff --git a/app/graphql/types/ci/pipeline_status_enum.rb b/app/graphql/types/ci/pipeline_status_enum.rb
index 2800454a999..c8e031e18ea 100644
--- a/app/graphql/types/ci/pipeline_status_enum.rb
+++ b/app/graphql/types/ci/pipeline_status_enum.rb
@@ -3,10 +3,24 @@
module Types
module Ci
class PipelineStatusEnum < BaseEnum
- ::Ci::Pipeline.all_state_names.each do |state_symbol|
- value state_symbol.to_s.upcase,
- description: "#{::Ci::Pipeline::STATUSES_DESCRIPTION[state_symbol]}.",
- value: state_symbol.to_s
+ STATUSES_DESCRIPTION = {
+ created: 'Pipeline has been created.',
+ waiting_for_resource: 'A resource (for example, a runner) that the pipeline requires to run is unavailable.',
+ preparing: 'Pipeline is preparing to run.',
+ pending: 'Pipeline has not started running yet.',
+ running: 'Pipeline is running.',
+ failed: 'At least one stage of the pipeline failed.',
+ success: 'Pipeline completed successfully.',
+ canceled: 'Pipeline was canceled before completion.',
+ skipped: 'Pipeline was skipped.',
+ manual: 'Pipeline needs to be manually started.',
+ scheduled: 'Pipeline is scheduled to run.'
+ }.freeze
+
+ STATUSES_DESCRIPTION.each do |state, description|
+ value state.to_s.upcase,
+ description: description,
+ value: state.to_s
end
end
end
diff --git a/app/graphql/types/ci/pipeline_type.rb b/app/graphql/types/ci/pipeline_type.rb
index 493ce188d9b..da2f11be9e2 100644
--- a/app/graphql/types/ci/pipeline_type.rb
+++ b/app/graphql/types/ci/pipeline_type.rb
@@ -108,6 +108,11 @@ module Types
description: 'Name of the job.'
end
+ field :job_artifacts,
+ null: true,
+ description: 'Job artifacts of the pipeline.',
+ resolver: ::Resolvers::Ci::PipelineJobArtifactsResolver
+
field :source_job,
type: Types::Ci::JobType,
null: true,
@@ -125,6 +130,10 @@ module Types
field :path, GraphQL::Types::String, null: true,
description: "Relative path to the pipeline's page."
+ field :commit, Types::CommitType, null: true,
+ description: "Git commit of the pipeline.",
+ calls_gitaly: true
+
field :commit_path, GraphQL::Types::String, null: true,
description: 'Path to the commit that triggered the pipeline.'
diff --git a/app/graphql/types/ci/runner_setup_type.rb b/app/graphql/types/ci/runner_setup_type.rb
index 70f33cef8ad..b6b020db40e 100644
--- a/app/graphql/types/ci/runner_setup_type.rb
+++ b/app/graphql/types/ci/runner_setup_type.rb
@@ -9,7 +9,7 @@ module Types
field :install_instructions, GraphQL::Types::String, null: false,
description: 'Instructions for installing the runner on the specified architecture.'
field :register_instructions, GraphQL::Types::String, null: true,
- description: 'Instructions for registering the runner.'
+ description: 'Instructions for registering the runner. The actual registration tokens are not included in the commands. Instead, a placeholder `$REGISTRATION_TOKEN` is shown.'
end
end
end
diff --git a/app/graphql/types/commit_type.rb b/app/graphql/types/commit_type.rb
index dc1bf6a3101..7d141bd6daa 100644
--- a/app/graphql/types/commit_type.rb
+++ b/app/graphql/types/commit_type.rb
@@ -14,12 +14,19 @@ module Types
description: 'SHA1 ID of the commit.'
field :short_id, type: GraphQL::Types::String, null: false,
description: 'Short SHA1 ID of the commit.'
+
field :title, type: GraphQL::Types::String, null: true, calls_gitaly: true,
description: 'Title of the commit message.'
markdown_field :title_html, null: true
+
+ field :full_title, type: GraphQL::Types::String, null: true, calls_gitaly: true,
+ description: 'Full title of the commit message.'
+ markdown_field :full_title_html, null: true
+
field :description, type: GraphQL::Types::String, null: true,
description: 'Description of the commit message.'
markdown_field :description_html, null: true
+
field :message, type: GraphQL::Types::String, null: true,
description: 'Raw commit message.'
field :authored_date, type: Types::TimeType, null: true,
diff --git a/app/graphql/types/customer_relations/contact_type.rb b/app/graphql/types/customer_relations/contact_type.rb
index b5224a3e239..6a3882c66af 100644
--- a/app/graphql/types/customer_relations/contact_type.rb
+++ b/app/graphql/types/customer_relations/contact_type.rb
@@ -5,7 +5,7 @@ module Types
class ContactType < BaseObject
graphql_name 'CustomerRelationsContact'
- authorize :read_contact
+ authorize :read_crm_contact
field :id,
GraphQL::Types::ID,
diff --git a/app/graphql/types/customer_relations/organization_type.rb b/app/graphql/types/customer_relations/organization_type.rb
index 9b22fa35b11..0f97f0a2433 100644
--- a/app/graphql/types/customer_relations/organization_type.rb
+++ b/app/graphql/types/customer_relations/organization_type.rb
@@ -5,7 +5,7 @@ module Types
class OrganizationType < BaseObject
graphql_name 'CustomerRelationsOrganization'
- authorize :read_organization
+ authorize :read_crm_organization
field :id,
GraphQL::Types::ID,
diff --git a/app/graphql/types/dependency_proxy/manifest_type.rb b/app/graphql/types/dependency_proxy/manifest_type.rb
index 9aa62266ef7..ef9f730df43 100644
--- a/app/graphql/types/dependency_proxy/manifest_type.rb
+++ b/app/graphql/types/dependency_proxy/manifest_type.rb
@@ -8,6 +8,7 @@ module Types
authorize :read_dependency_proxy
+ field :id, ::Types::GlobalIDType[::DependencyProxy::Manifest], null: false, description: 'ID of the manifest.'
field :created_at, Types::TimeType, null: false, description: 'Date of creation.'
field :updated_at, Types::TimeType, null: false, description: 'Date of most recent update.'
field :file_name, GraphQL::Types::String, null: false, description: 'Name of the manifest.'
diff --git a/app/graphql/types/evidence_type.rb b/app/graphql/types/evidence_type.rb
index 26fb64d25d8..33f46c712f1 100644
--- a/app/graphql/types/evidence_type.rb
+++ b/app/graphql/types/evidence_type.rb
@@ -5,7 +5,7 @@ module Types
graphql_name 'ReleaseEvidence'
description 'Evidence for a release'
- authorize :download_code
+ authorize :read_release_evidence
present_using Releases::EvidencePresenter
diff --git a/app/graphql/types/group_type.rb b/app/graphql/types/group_type.rb
index b1bbabcdaed..4a20d84f2ab 100644
--- a/app/graphql/types/group_type.rb
+++ b/app/graphql/types/group_type.rb
@@ -34,6 +34,7 @@ module Types
null: true,
method: :project_creation_level_str,
description: 'Permission level required to create projects in the group.'
+
field :subgroup_creation_level,
type: GraphQL::Types::String,
null: true,
@@ -44,6 +45,7 @@ module Types
type: GraphQL::Types::Boolean,
null: true,
description: 'Indicates if all users in this group are required to set up two-factor authentication.'
+
field :two_factor_grace_period,
type: GraphQL::Types::Int,
null: true,
@@ -220,12 +222,16 @@ module Types
group.container_repositories.size
end
+ def dependency_proxy_manifests
+ group.dependency_proxy_manifests.order_id_desc
+ end
+
def dependency_proxy_image_count
- group.dependency_proxy_manifests.count
+ group.dependency_proxy_manifests.size
end
def dependency_proxy_blob_count
- group.dependency_proxy_blobs.count
+ group.dependency_proxy_blobs.size
end
def dependency_proxy_total_size
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 c8b7cdaa68e..73e090a4802 100644
--- a/app/graphql/types/issues/negated_issue_filter_input_type.rb
+++ b/app/graphql/types/issues/negated_issue_filter_input_type.rb
@@ -14,6 +14,9 @@ module Types
argument :milestone_title, [GraphQL::Types::String],
required: false,
description: 'Milestone not applied to this issue.'
+ argument :release_tag, [GraphQL::Types::String],
+ required: false,
+ description: "Release tag not associated with the issue's milestone. Ignored when parent is a group."
argument :author_username, GraphQL::Types::String,
required: false,
description: "Username of a user who didn't author the issue."
diff --git a/app/graphql/types/merge_request_type.rb b/app/graphql/types/merge_request_type.rb
index 004ac364487..a0f00ddc3c6 100644
--- a/app/graphql/types/merge_request_type.rb
+++ b/app/graphql/types/merge_request_type.rb
@@ -53,9 +53,6 @@ module Types
description: 'Indicates if the source branch is protected.'
field :target_branch, GraphQL::Types::String, null: false,
description: 'Target branch of the merge request.'
- field :work_in_progress, GraphQL::Types::Boolean, method: :work_in_progress?, null: false,
- deprecated: { reason: 'Use `draft`', milestone: '13.12' },
- description: 'Indicates if the merge request is a draft.'
field :draft, GraphQL::Types::Boolean, method: :draft?, null: false,
description: 'Indicates if the merge request is a draft.'
field :merge_when_pipeline_succeeds, GraphQL::Types::Boolean, null: true,
@@ -102,7 +99,8 @@ module Types
field :default_merge_commit_message, GraphQL::Types::String, null: true,
description: 'Default merge commit message of the merge request.'
field :default_merge_commit_message_with_description, GraphQL::Types::String, null: true,
- description: 'Default merge commit message of the merge request with description.'
+ description: 'Default merge commit message of the merge request with description. Will have the same value as `defaultMergeCommitMessage` when project has `mergeCommitTemplate` set.',
+ deprecated: { reason: 'Define merge commit template in project and use `defaultMergeCommitMessage`', milestone: '14.5' }
field :default_squash_commit_message, GraphQL::Types::String, null: true, calls_gitaly: true,
description: 'Default squash commit message of the merge request.'
field :merge_ongoing, GraphQL::Types::Boolean, method: :merge_ongoing?, null: false,
diff --git a/app/graphql/types/mutation_type.rb b/app/graphql/types/mutation_type.rb
index cd4c45d2942..e8a952e9c61 100644
--- a/app/graphql/types/mutation_type.rb
+++ b/app/graphql/types/mutation_type.rb
@@ -16,6 +16,7 @@ module Types
mount_mutation Mutations::AlertManagement::HttpIntegration::ResetToken
mount_mutation Mutations::AlertManagement::HttpIntegration::Destroy
mount_mutation Mutations::Security::CiConfiguration::ConfigureSast
+ mount_mutation Mutations::Security::CiConfiguration::ConfigureSastIac
mount_mutation Mutations::Security::CiConfiguration::ConfigureSecretDetection
mount_mutation Mutations::AlertManagement::PrometheusIntegration::Create
mount_mutation Mutations::AlertManagement::PrometheusIntegration::Update
@@ -48,6 +49,7 @@ module Types
mount_mutation Mutations::Environments::CanaryIngress::Update
mount_mutation Mutations::Issues::Create
mount_mutation Mutations::Issues::SetAssignees
+ mount_mutation Mutations::Issues::SetCrmContacts
mount_mutation Mutations::Issues::SetConfidential
mount_mutation Mutations::Issues::SetLocked
mount_mutation Mutations::Issues::SetDueDate
@@ -63,12 +65,10 @@ module Types
mount_mutation Mutations::MergeRequests::SetLocked
mount_mutation Mutations::MergeRequests::SetMilestone
mount_mutation Mutations::MergeRequests::SetSubscription
- mount_mutation Mutations::MergeRequests::SetWip,
- calls_gitaly: true,
- deprecated: { reason: 'Use mergeRequestSetDraft', milestone: '13.12' }
mount_mutation Mutations::MergeRequests::SetDraft, calls_gitaly: true
mount_mutation Mutations::MergeRequests::SetAssignees
mount_mutation Mutations::MergeRequests::ReviewerRereview
+ mount_mutation Mutations::MergeRequests::ToggleAttentionRequested, feature_flag: :mr_attention_requests
mount_mutation Mutations::Metrics::Dashboard::Annotations::Create
mount_mutation Mutations::Metrics::Dashboard::Annotations::Delete
mount_mutation Mutations::Notes::Create::Note, calls_gitaly: true
diff --git a/app/graphql/types/packages/file_metadata_type.rb b/app/graphql/types/packages/file_metadata_type.rb
index 46ccb424218..0731fc897a2 100644
--- a/app/graphql/types/packages/file_metadata_type.rb
+++ b/app/graphql/types/packages/file_metadata_type.rb
@@ -14,6 +14,8 @@ module Types
case object
when ::Packages::Conan::FileMetadatum
::Types::Packages::Conan::FileMetadatumType
+ when ::Packages::Helm::FileMetadatum
+ ::Types::Packages::Helm::FileMetadatumType
else
# NOTE: This method must be kept in sync with `PackageFileType#file_metadata`,
# which must never produce data that this discriminator cannot handle.
@@ -21,7 +23,8 @@ module Types
end
end
- orphan_types Types::Packages::Conan::FileMetadatumType
+ orphan_types Types::Packages::Conan::FileMetadatumType,
+ Types::Packages::Helm::FileMetadatumType
end
end
end
diff --git a/app/graphql/types/packages/helm/dependency_type.rb b/app/graphql/types/packages/helm/dependency_type.rb
new file mode 100644
index 00000000000..35598c2b1d7
--- /dev/null
+++ b/app/graphql/types/packages/helm/dependency_type.rb
@@ -0,0 +1,28 @@
+# frozen_string_literal: true
+
+module Types
+ module Packages
+ module Helm
+ # rubocop: disable Graphql/AuthorizeTypes
+ class DependencyType < BaseObject
+ graphql_name 'PackageHelmDependencyType'
+ description 'Represents a Helm dependency'
+
+ # Need to be synced with app/validators/json_schemas/helm_metadata.json#dependencies
+ field :name, GraphQL::Types::String, null: true, description: 'Name of the dependency.'
+ field :version, GraphQL::Types::String, null: true, description: 'Version of the dependency.'
+ field :repository, GraphQL::Types::String, null: true, description: 'Repository of the dependency.'
+ field :condition, GraphQL::Types::String, null: true, description: 'Condition of the dependency.'
+ field :tags, [GraphQL::Types::String], null: true, description: 'Tags 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 :alias, GraphQL::Types::String, null: true, description: 'Alias of the dependency.', resolver_method: :resolve_alias
+
+ # field :alias` conflicts with a built-in method
+ def resolve_alias
+ object['alias']
+ end
+ end
+ end
+ end
+end
diff --git a/app/graphql/types/packages/helm/file_metadatum_type.rb b/app/graphql/types/packages/helm/file_metadatum_type.rb
new file mode 100644
index 00000000000..734ed52df40
--- /dev/null
+++ b/app/graphql/types/packages/helm/file_metadatum_type.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+module Types
+ module Packages
+ module Helm
+ class FileMetadatumType < BaseObject
+ graphql_name 'HelmFileMetadata'
+ description 'Helm file metadata'
+
+ implements Types::Packages::FileMetadataType
+
+ authorize :read_package
+
+ field :channel, GraphQL::Types::String, null: false, description: 'Channel of the Helm chart.'
+ field :metadata, Types::Packages::Helm::MetadataType, null: false, description: 'Metadata of the Helm chart.'
+ end
+ end
+ end
+end
diff --git a/app/graphql/types/packages/helm/maintainer_type.rb b/app/graphql/types/packages/helm/maintainer_type.rb
new file mode 100644
index 00000000000..6d25a26c46b
--- /dev/null
+++ b/app/graphql/types/packages/helm/maintainer_type.rb
@@ -0,0 +1,18 @@
+# frozen_string_literal: true
+
+module Types
+ module Packages
+ module Helm
+ # rubocop: disable Graphql/AuthorizeTypes
+ class MaintainerType < BaseObject
+ graphql_name 'PackageHelmMaintainerType'
+ description 'Represents a Helm maintainer'
+
+ # Need to be synced with app/validators/json_schemas/helm_metadata.json#maintainers
+ field :name, GraphQL::Types::String, null: true, description: 'Name of the maintainer.'
+ field :email, GraphQL::Types::String, null: true, description: 'Email of the maintainer.'
+ field :url, GraphQL::Types::String, null: true, description: 'URL of the maintainer.'
+ end
+ end
+ end
+end
diff --git a/app/graphql/types/packages/helm/metadata_type.rb b/app/graphql/types/packages/helm/metadata_type.rb
new file mode 100644
index 00000000000..eeb3e8087a8
--- /dev/null
+++ b/app/graphql/types/packages/helm/metadata_type.rb
@@ -0,0 +1,32 @@
+# frozen_string_literal: true
+
+module Types
+ module Packages
+ module Helm
+ # rubocop: disable Graphql/AuthorizeTypes
+ class MetadataType < BaseObject
+ graphql_name 'PackageHelmMetadataType'
+ description 'Represents the contents of a Helm Chart.yml file'
+
+ # Need to be synced with app/validators/json_schemas/helm_metadata.json
+ field :name, GraphQL::Types::String, null: false, description: 'Name of the chart.'
+ field :home, GraphQL::Types::String, null: true, description: 'URL of the home page.'
+ field :sources, [GraphQL::Types::String], null: true, description: 'URLs of the source code for the chart.'
+ field :version, GraphQL::Types::String, null: false, description: 'Version of the chart.'
+ field :description, GraphQL::Types::String, null: true, description: 'Description of the chart.'
+ field :keywords, [GraphQL::Types::String], null: true, description: 'Keywords for the chart.'
+ field :maintainers, [Types::Packages::Helm::MaintainerType], null: true, description: 'Maintainers of the chart.'
+ field :icon, GraphQL::Types::String, null: true, description: 'URL to an SVG or PNG image for the chart.'
+ field :api_version, GraphQL::Types::String, null: false, description: 'API version of the chart.', hash_key: "apiVersion"
+ field :condition, GraphQL::Types::String, null: true, description: 'Condition for the chart.'
+ field :tags, GraphQL::Types::String, null: true, description: 'Tags for the chart.'
+ field :app_version, GraphQL::Types::String, null: true, description: 'App version of the chart.', hash_key: "appVersion"
+ field :deprecated, GraphQL::Types::Boolean, null: true, description: 'Indicates if the chart is deprecated.'
+ field :annotations, GraphQL::Types::JSON, null: true, description: 'Annotations for the chart.' # rubocop:disable Graphql/JSONType
+ field :kube_version, GraphQL::Types::String, null: true, description: 'Kubernetes versions for the chart.', hash_key: "kubeVersion"
+ field :dependencies, [Types::Packages::Helm::DependencyType], null: true, description: 'Dependencies of the chart.'
+ field :type, GraphQL::Types::String, null: true, description: 'Type of the chart.', hash_key: "appVersion"
+ end
+ end
+ end
+end
diff --git a/app/graphql/types/packages/package_file_type.rb b/app/graphql/types/packages/package_file_type.rb
index 8cc0f9b984a..f90a0992bf8 100644
--- a/app/graphql/types/packages/package_file_type.rb
+++ b/app/graphql/types/packages/package_file_type.rb
@@ -27,6 +27,8 @@ module Types
case object.package.package_type
when 'conan'
object.conan_file_metadatum
+ when 'helm'
+ object.helm_file_metadatum
else
nil
end
diff --git a/app/graphql/types/project_type.rb b/app/graphql/types/project_type.rb
index 791875242df..b6cb9cd3302 100644
--- a/app/graphql/types/project_type.rb
+++ b/app/graphql/types/project_type.rb
@@ -306,7 +306,7 @@ module Types
null: true,
description: 'A single release of the project.',
resolver: Resolvers::ReleasesResolver.single,
- authorize: :download_code
+ authorize: :read_release
field :container_expiration_policy,
Types::ContainerExpirationPolicyType,
@@ -381,6 +381,11 @@ module Types
description: 'Cluster agents associated with the project.',
resolver: ::Resolvers::Clusters::AgentsResolver
+ field :merge_commit_template,
+ GraphQL::Types::String,
+ null: true,
+ description: 'Template used to create merge commit message in merge requests.'
+
def label(title:)
BatchLoader::GraphQL.for(title).batch(key: project) do |titles, loader, args|
LabelsFinder
diff --git a/app/graphql/types/projects/topic_type.rb b/app/graphql/types/projects/topic_type.rb
new file mode 100644
index 00000000000..79ab69e794b
--- /dev/null
+++ b/app/graphql/types/projects/topic_type.rb
@@ -0,0 +1,28 @@
+# frozen_string_literal: true
+
+module Types
+ module Projects
+ # rubocop: disable Graphql/AuthorizeTypes
+ class TopicType < BaseObject
+ graphql_name 'Topic'
+
+ field :id, GraphQL::Types::ID, null: false,
+ description: 'ID of the topic.'
+
+ field :name, GraphQL::Types::String, null: false,
+ description: 'Name of the topic.'
+
+ field :description, GraphQL::Types::String, null: true,
+ description: 'Description of the topic.'
+ markdown_field :description_html, null: true
+
+ field :avatar_url, GraphQL::Types::String, null: true,
+ description: 'URL to avatar image file of the topic.'
+
+ def avatar_url
+ object.avatar_url(only_path: false)
+ end
+ end
+ # rubocop: enable Graphql/AuthorizeTypes
+ end
+end
diff --git a/app/graphql/types/query_type.rb b/app/graphql/types/query_type.rb
index ed4ddbb982b..4a4d6727c3f 100644
--- a/app/graphql/types/query_type.rb
+++ b/app/graphql/types/query_type.rb
@@ -140,6 +140,11 @@ module Types
null: true,
resolver: Resolvers::BoardListResolver
+ field :topics, Types::Projects::TopicType.connection_type,
+ null: true,
+ resolver: Resolvers::TopicsResolver,
+ description: "Find project topics."
+
def design_management
DesignManagementObject.new(nil)
end
diff --git a/app/graphql/types/release_links_type.rb b/app/graphql/types/release_links_type.rb
index 7830e29f3cd..37ad52ce6d0 100644
--- a/app/graphql/types/release_links_type.rb
+++ b/app/graphql/types/release_links_type.rb
@@ -4,7 +4,7 @@ module Types
class ReleaseLinksType < BaseObject
graphql_name 'ReleaseLinks'
- authorize :download_code
+ authorize :read_release
alias_method :release, :object
@@ -16,14 +16,19 @@ module Types
description: "HTTP URL of the release's edit page.",
authorize: :update_release
field :opened_merge_requests_url, GraphQL::Types::String, null: true,
- description: 'HTTP URL of the merge request page, filtered by this release and `state=open`.'
+ description: 'HTTP URL of the merge request page, filtered by this release and `state=open`.',
+ authorize: :download_code
field :merged_merge_requests_url, GraphQL::Types::String, null: true,
- description: 'HTTP URL of the merge request page , filtered by this release and `state=merged`.'
+ description: 'HTTP URL of the merge request page , filtered by this release and `state=merged`.',
+ authorize: :download_code
field :closed_merge_requests_url, GraphQL::Types::String, null: true,
- description: 'HTTP URL of the merge request page , filtered by this release and `state=closed`.'
+ description: 'HTTP URL of the merge request page , filtered by this release and `state=closed`.',
+ authorize: :download_code
field :opened_issues_url, GraphQL::Types::String, null: true,
- description: 'HTTP URL of the issues page, filtered by this release and `state=open`.'
+ description: 'HTTP URL of the issues page, filtered by this release and `state=open`.',
+ authorize: :download_code
field :closed_issues_url, GraphQL::Types::String, null: true,
- description: 'HTTP URL of the issues page, filtered by this release and `state=closed`.'
+ description: 'HTTP URL of the issues page, filtered by this release and `state=closed`.',
+ authorize: :download_code
end
end
diff --git a/app/graphql/types/release_tag_wildcard_id_enum.rb b/app/graphql/types/release_tag_wildcard_id_enum.rb
new file mode 100644
index 00000000000..27765864101
--- /dev/null
+++ b/app/graphql/types/release_tag_wildcard_id_enum.rb
@@ -0,0 +1,11 @@
+# frozen_string_literal: true
+
+module Types
+ class ReleaseTagWildcardIdEnum < BaseEnum
+ graphql_name 'ReleaseTagWildcardId'
+ description 'Release tag ID wildcard values'
+
+ value 'NONE', 'No release tag is assigned.'
+ value 'ANY', 'Release tag is assigned.'
+ end
+end
diff --git a/app/graphql/types/release_type.rb b/app/graphql/types/release_type.rb
index 6dda93c7329..fcc9ec49252 100644
--- a/app/graphql/types/release_type.rb
+++ b/app/graphql/types/release_type.rb
@@ -14,8 +14,7 @@ module Types
present_using ReleasePresenter
field :tag_name, GraphQL::Types::String, null: true, method: :tag,
- description: 'Name of the tag associated with the release.',
- authorize: :download_code
+ description: 'Name of the tag associated with the release.'
field :tag_path, GraphQL::Types::String, null: true,
description: 'Relative web path to the tag associated with the release.',
authorize: :download_code
diff --git a/app/graphql/types/repository/blob_type.rb b/app/graphql/types/repository/blob_type.rb
index ef7f535212f..104171e6772 100644
--- a/app/graphql/types/repository/blob_type.rb
+++ b/app/graphql/types/repository/blob_type.rb
@@ -68,6 +68,9 @@ module Types
field :replace_path, GraphQL::Types::String, null: true,
description: 'Web path to replace the blob content.'
+ field :pipeline_editor_path, GraphQL::Types::String, null: true,
+ description: 'Web path to edit .gitlab-ci.yml file.'
+
field :file_type, GraphQL::Types::String, null: true,
description: 'Expected format of the blob based on the extension.'
diff --git a/app/graphql/types/repository_type.rb b/app/graphql/types/repository_type.rb
index 63d1eef5b59..fc9860900c9 100644
--- a/app/graphql/types/repository_type.rb
+++ b/app/graphql/types/repository_type.rb
@@ -16,8 +16,7 @@ module Types
description: 'Tree of the repository.'
field :paginated_tree, Types::Tree::TreeType.connection_type, null: true, resolver: Resolvers::PaginatedTreeResolver, calls_gitaly: true,
max_page_size: 100,
- description: 'Paginated tree of the repository.',
- feature_flag: :paginated_tree_graphql_query
+ description: 'Paginated tree of the repository.'
field :blobs, Types::Repository::BlobType.connection_type, null: true, resolver: Resolvers::BlobsResolver, calls_gitaly: true,
description: 'Blobs contained within the repository'
field :branch_names, [GraphQL::Types::String], null: true, calls_gitaly: true,