diff options
Diffstat (limited to 'app/graphql')
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, |