Add latest changes from gitlab-org/gitlab@master

This commit is contained in:
GitLab Bot 2020-03-30 21:08:01 +00:00
parent 2c72daf2f1
commit 95ad46159e
74 changed files with 792 additions and 612 deletions

View File

@ -382,3 +382,39 @@ Cop/BanCatchThrow:
Performance/ReadlinesEach:
Enabled: true
# https://gitlab.com/gitlab-org/gitlab/-/issues/212541
RSpec/RepeatedExample:
Exclude:
- 'spec/features/issues/filtered_search/filter_issues_spec.rb'
- 'spec/features/merge_request/user_posts_diff_notes_spec.rb'
- 'spec/features/projects/files/template_type_dropdown_spec.rb'
- 'spec/finders/environments_finder_spec.rb'
- 'spec/frontend/fixtures/merge_requests.rb'
- 'spec/graphql/gitlab_schema_spec.rb'
- 'spec/helpers/users_helper_spec.rb'
- 'spec/lib/banzai/filter/autolink_filter_spec.rb'
- 'spec/lib/banzai/filter/issuable_state_filter_spec.rb'
- 'spec/lib/gitlab/closing_issue_extractor_spec.rb'
- 'spec/lib/gitlab/danger/changelog_spec.rb'
- 'spec/lib/gitlab/git/blob_spec.rb'
- 'spec/lib/gitlab/import_export/project/relation_factory_spec.rb'
- 'spec/models/ability_spec.rb'
- 'spec/models/ci/build_spec.rb'
- 'spec/models/concerns/issuable_spec.rb'
- 'spec/models/concerns/prometheus_adapter_spec.rb'
- 'spec/models/member_spec.rb'
- 'spec/models/project_services/chat_message/pipeline_message_spec.rb'
- 'spec/models/user_spec.rb'
- 'spec/models/wiki_page_spec.rb'
- 'spec/requests/api/merge_requests_spec.rb'
- 'spec/routing/admin_routing_spec.rb'
- 'spec/rubocop/cop/migration/update_large_table_spec.rb'
- 'spec/services/notification_service_spec.rb'
- 'spec/services/web_hook_service_spec.rb'
- 'ee/spec/models/group_spec.rb'
- 'ee/spec/models/user_spec.rb'
- 'ee/spec/requests/api/merge_request_approvals_spec.rb'
- 'ee/spec/services/boards/lists/update_service_spec.rb'
- 'ee/spec/services/geo/repository_verification_primary_service_spec.rb'
- 'ee/spec/workers/geo/file_download_dispatch_worker_spec.rb'

View File

@ -251,10 +251,6 @@ RSpec/LetBeforeExamples:
RSpec/PredicateMatcher:
Enabled: false
# Offense count: 69
RSpec/RepeatedExample:
Enabled: false
# Offense count: 584
# Cop supports --auto-correct.
# Configuration parameters: EnforcedStyle.

View File

@ -39,6 +39,10 @@ export default {
'is-open': this.file.opened,
};
},
textForTitle() {
// don't output a title if we don't have the expanded path
return this.file?.tree?.length ? this.file.tree[0].parentPath : false;
},
},
watch: {
'file.active': function fileActiveWatch(active) {
@ -106,7 +110,7 @@ export default {
<div
v-else
:class="fileClass"
:title="file.name"
:title="textForTitle"
class="file-row"
role="button"
@click="clickFile"

View File

@ -19,7 +19,7 @@ export default {
</script>
<template>
<div class="file-row-header bg-white sticky-top p-2 js-file-row-header">
<div class="file-row-header bg-white sticky-top p-2 js-file-row-header" :title="path">
<span class="bold">{{ truncatedPath }}</span>
</div>
</template>

View File

@ -38,19 +38,14 @@ class IssuableFinder
include CreatedAtFilter
include Gitlab::Utils::StrongMemoize
requires_cross_project_access unless: -> { project? }
# This is used as a common filter for None / Any
FILTER_NONE = 'none'
FILTER_ANY = 'any'
# This is used in unassigning users
NONE = '0'
requires_cross_project_access unless: -> { params.project? }
NEGATABLE_PARAMS_HELPER_KEYS = %i[include_subgroups in].freeze
attr_accessor :current_user, :params
delegate(*%i[assignee milestones], to: :params)
class << self
def scalar_params
@scalar_params ||= %i[
@ -91,9 +86,13 @@ class IssuableFinder
end
end
def params_class
IssuableFinder::Params
end
def initialize(current_user, params = {})
@current_user = current_user
@params = params
@params = params_class.new(params, current_user, klass)
end
def execute
@ -161,7 +160,7 @@ class IssuableFinder
# of a CTE. The CTE will not be used if the sort doesn't support it,
# but will always be used for the counts here as we ignore sorting
# anyway.
labels_count = label_names.any? ? label_names.count : 1
labels_count = params.label_names.any? ? params.label_names.count : 1
labels_count = 1 if use_cte_for_search?
finder.execute.reorder(nil).group(:state_id).count.each do |key, value|
@ -174,192 +173,10 @@ class IssuableFinder
end
# rubocop: enable CodeReuse/ActiveRecord
def group
return @group if defined?(@group)
@group =
if params[:group_id].present?
Group.find(params[:group_id])
else
nil
end
end
def related_groups
if project? && project && project.group && Ability.allowed?(current_user, :read_group, project.group)
project.group.self_and_ancestors
elsif group
[group]
elsif current_user
Gitlab::ObjectHierarchy.new(current_user.authorized_groups, current_user.groups).all_objects
else
[]
end
end
def project?
params[:project_id].present?
end
def project
return @project if defined?(@project)
project = Project.find(params[:project_id])
project = nil unless Ability.allowed?(current_user, :"read_#{klass.to_ability_name}", project)
@project = project
end
def projects
return @projects if defined?(@projects)
return @projects = [project] if project?
projects =
if current_user && params[:authorized_only].presence && !current_user_related?
current_user.authorized_projects(min_access_level)
else
projects_public_or_visible_to_user
end
@projects = projects.with_feature_available_for_user(klass, current_user).reorder(nil) # rubocop: disable CodeReuse/ActiveRecord
end
def projects_public_or_visible_to_user
projects =
if group
if params[:projects]
find_group_projects.id_in(params[:projects])
else
find_group_projects
end
elsif params[:projects]
Project.id_in(params[:projects])
else
Project
end
projects.public_or_visible_to_user(current_user, min_access_level)
end
def find_group_projects
return Project.none unless group
if params[:include_subgroups]
Project.where(namespace_id: group.self_and_descendants) # rubocop: disable CodeReuse/ActiveRecord
else
group.projects
end
end
def search
params[:search].presence
end
def milestones?
params[:milestone_title].present?
end
def milestones
return @milestones if defined?(@milestones)
@milestones =
if milestones?
if project?
group_id = project.group&.id
project_id = project.id
end
group_id = group.id if group
search_params =
{ title: params[:milestone_title], project_ids: project_id, group_ids: group_id }
MilestonesFinder.new(search_params).execute # rubocop: disable CodeReuse/Finder
else
Milestone.none
end
end
def labels?
params[:label_name].present?
end
def filter_by_no_label?
downcased = label_names.map(&:downcase)
downcased.include?(FILTER_NONE)
end
def filter_by_any_label?
label_names.map(&:downcase).include?(FILTER_ANY)
end
def labels
return @labels if defined?(@labels)
@labels =
if labels? && !filter_by_no_label?
LabelsFinder.new(current_user, project_ids: projects, title: label_names).execute(skip_authorization: true) # rubocop: disable CodeReuse/Finder
else
Label.none
end
end
def assignee_id?
params[:assignee_id].present?
end
def assignee_username?
params[:assignee_username].present?
end
def assignee
assignees.first
end
# rubocop: disable CodeReuse/ActiveRecord
def assignees
strong_memoize(:assignees) do
if assignee_id?
User.where(id: params[:assignee_id])
elsif assignee_username?
User.where(username: params[:assignee_username])
else
User.none
end
end
end
# rubocop: enable CodeReuse/ActiveRecord
def author_id?
params[:author_id].present? && params[:author_id] != NONE
end
def author_username?
params[:author_username].present? && params[:author_username] != NONE
end
def no_author?
# author_id takes precedence over author_username
params[:author_id] == NONE || params[:author_username] == NONE
end
# rubocop: disable CodeReuse/ActiveRecord
def author
return @author if defined?(@author)
@author =
if author_id?
User.find_by(id: params[:author_id])
elsif author_username?
User.find_by_username(params[:author_username])
else
nil
end
end
# rubocop: enable CodeReuse/ActiveRecord
def use_cte_for_search?
strong_memoize(:use_cte_for_search) do
next false unless search
@ -370,10 +187,6 @@ class IssuableFinder
end
end
def releases?
params[:release_tag].present?
end
private
def force_cte?
@ -431,7 +244,7 @@ class IssuableFinder
# rubocop: disable CodeReuse/ActiveRecord
def by_scope(items)
return items.none if current_user_related? && !current_user
return items.none if params.current_user_related? && !current_user
case params[:scope]
when 'created_by_me', 'authored'
@ -480,16 +293,13 @@ class IssuableFinder
# rubocop: disable CodeReuse/ActiveRecord
def by_project(items)
items =
if project?
items.of_projects(projects).references_project
elsif projects
items.merge(projects.reorder(nil)).join_project
else
items.none
end
items
if params.project?
items.of_projects(params.projects).references_project
elsif params.projects
items.merge(params.projects.reorder(nil)).join_project
else
items.none
end
end
# rubocop: enable CodeReuse/ActiveRecord
@ -519,42 +329,34 @@ class IssuableFinder
def sort(items)
# Ensure we always have an explicit sort order (instead of inheriting
# multiple orders when combining ActiveRecord::Relation objects).
params[:sort] ? items.sort_by_attribute(params[:sort], excluded_labels: label_names) : items.reorder(id: :desc)
params[:sort] ? items.sort_by_attribute(params[:sort], excluded_labels: params.label_names) : items.reorder(id: :desc)
end
# rubocop: enable CodeReuse/ActiveRecord
def filter_by_no_assignee?
params[:assignee_id].to_s.downcase == FILTER_NONE
end
def filter_by_any_assignee?
params[:assignee_id].to_s.downcase == FILTER_ANY
end
# rubocop: disable CodeReuse/ActiveRecord
def by_author(items)
if author
items = items.where(author_id: author.id)
elsif no_author?
items = items.where(author_id: nil)
elsif author_id? || author_username? # author not found
items = items.none
if params.author
items.where(author_id: params.author.id)
elsif params.no_author?
items.where(author_id: nil)
elsif params.author_id? || params.author_username? # author not found
items.none
else
items
end
items
end
# rubocop: enable CodeReuse/ActiveRecord
def by_assignee(items)
return items.assigned_to(assignees) if not_query? && assignees.any?
return items.assigned_to(params.assignees) if not_query? && params.assignees.any?
if filter_by_no_assignee?
if params.filter_by_no_assignee?
items.unassigned
elsif filter_by_any_assignee?
elsif params.filter_by_any_assignee?
items.assigned
elsif assignee
items.assigned_to(assignee)
elsif assignee_id? || assignee_username? # assignee not found
elsif params.assignee
items.assigned_to(params.assignee)
elsif params.assignee_id? || params.assignee_username? # assignee not found
items.none
else
items
@ -563,106 +365,56 @@ class IssuableFinder
# rubocop: disable CodeReuse/ActiveRecord
def by_milestone(items)
if milestones?
if filter_by_no_milestone?
items = items.left_joins_milestones.where(milestone_id: [-1, nil])
elsif filter_by_any_milestone?
items = items.any_milestone
elsif filter_by_upcoming_milestone?
upcoming_ids = Milestone.upcoming_ids(projects, related_groups)
items = items.left_joins_milestones.where(milestone_id: upcoming_ids)
elsif filter_by_started_milestone?
items = items.left_joins_milestones.merge(Milestone.started)
else
items = items.with_milestone(params[:milestone_title])
end
end
return items unless params.milestones?
items
if params.filter_by_no_milestone?
items.left_joins_milestones.where(milestone_id: [-1, nil])
elsif params.filter_by_any_milestone?
items.any_milestone
elsif params.filter_by_upcoming_milestone?
upcoming_ids = Milestone.upcoming_ids(params.projects, params.related_groups)
items.left_joins_milestones.where(milestone_id: upcoming_ids)
elsif params.filter_by_started_milestone?
items.left_joins_milestones.merge(Milestone.started)
else
items.with_milestone(params[:milestone_title])
end
end
# rubocop: enable CodeReuse/ActiveRecord
def by_release(items)
return items unless releases?
return items unless params.releases?
if filter_by_no_release?
if params.filter_by_no_release?
items.without_release
elsif filter_by_any_release?
elsif params.filter_by_any_release?
items.any_release
else
items.with_release(params[:release_tag], params[:project_id])
end
end
def filter_by_no_milestone?
# Accepts `No Milestone` for compatibility
params[:milestone_title].to_s.downcase == FILTER_NONE || params[:milestone_title] == Milestone::None.title
end
def filter_by_any_milestone?
# Accepts `Any Milestone` for compatibility
params[:milestone_title].to_s.downcase == FILTER_ANY || params[:milestone_title] == Milestone::Any.title
end
def filter_by_upcoming_milestone?
params[:milestone_title] == Milestone::Upcoming.name
end
def filter_by_started_milestone?
params[:milestone_title] == Milestone::Started.name
end
def filter_by_no_release?
params[:release_tag].to_s.downcase == FILTER_NONE
end
def filter_by_any_release?
params[:release_tag].to_s.downcase == FILTER_ANY
end
def by_label(items)
return items unless labels?
return items unless params.labels?
items =
if filter_by_no_label?
items.without_label
elsif filter_by_any_label?
items.any_label
else
items.with_label(label_names, params[:sort], not_query: not_query?)
end
items
if params.filter_by_no_label?
items.without_label
elsif params.filter_by_any_label?
items.any_label
else
items.with_label(params.label_names, params[:sort], not_query: not_query?)
end
end
def by_my_reaction_emoji(items)
if params[:my_reaction_emoji].present? && current_user
items =
if filter_by_no_reaction?
items.not_awarded(current_user)
elsif filter_by_any_reaction?
items.awarded(current_user)
else
items.awarded(current_user, params[:my_reaction_emoji])
end
end
return items unless params[:my_reaction_emoji] && current_user
items
end
def filter_by_no_reaction?
params[:my_reaction_emoji].to_s.downcase == FILTER_NONE
end
def filter_by_any_reaction?
params[:my_reaction_emoji].to_s.downcase == FILTER_ANY
end
def label_names
if labels?
params[:label_name].is_a?(String) ? params[:label_name].split(',') : params[:label_name]
if params.filter_by_no_reaction?
items.not_awarded(current_user)
elsif params.filter_by_any_reaction?
items.awarded(current_user)
else
[]
items.awarded(current_user, params[:my_reaction_emoji])
end
end
@ -670,15 +422,6 @@ class IssuableFinder
params[:non_archived].present? ? items.non_archived : items
end
def current_user_related?
scope = params[:scope]
scope == 'created_by_me' || scope == 'authored' || scope == 'assigned_to_me'
end
def min_access_level
ProjectFeature.required_minimum_access_level(klass)
end
def not_query?
!!params[:not_query]
end

View File

@ -0,0 +1,287 @@
# frozen_string_literal: true
class IssuableFinder
class Params < SimpleDelegator
include Gitlab::Utils::StrongMemoize
# This is used as a common filter for None / Any
FILTER_NONE = 'none'
FILTER_ANY = 'any'
# This is used in unassigning users
NONE = '0'
alias_method :params, :__getobj__
attr_accessor :current_user, :klass
def initialize(params, current_user, klass)
@current_user = current_user
@klass = klass
# We turn the params into a HashWithIndifferentAccess. We must use #to_h first because sometimes
# we get ActionController::Params and IssuableFinder::Params objects here.
super(params.to_h.with_indifferent_access)
end
def present?
params.present?
end
def author_id?
params[:author_id].present? && params[:author_id] != NONE
end
def author_username?
params[:author_username].present? && params[:author_username] != NONE
end
def no_author?
# author_id takes precedence over author_username
params[:author_id] == NONE || params[:author_username] == NONE
end
def filter_by_no_assignee?
params[:assignee_id].to_s.downcase == FILTER_NONE
end
def filter_by_any_assignee?
params[:assignee_id].to_s.downcase == FILTER_ANY
end
def filter_by_no_label?
downcased = label_names.map(&:downcase)
downcased.include?(FILTER_NONE)
end
def filter_by_any_label?
label_names.map(&:downcase).include?(FILTER_ANY)
end
def labels?
params[:label_name].present?
end
def milestones?
params[:milestone_title].present?
end
def filter_by_no_milestone?
# Accepts `No Milestone` for compatibility
params[:milestone_title].to_s.downcase == FILTER_NONE || params[:milestone_title] == Milestone::None.title
end
def filter_by_any_milestone?
# Accepts `Any Milestone` for compatibility
params[:milestone_title].to_s.downcase == FILTER_ANY || params[:milestone_title] == Milestone::Any.title
end
def filter_by_upcoming_milestone?
params[:milestone_title] == Milestone::Upcoming.name
end
def filter_by_started_milestone?
params[:milestone_title] == Milestone::Started.name
end
def filter_by_no_release?
params[:release_tag].to_s.downcase == FILTER_NONE
end
def filter_by_any_release?
params[:release_tag].to_s.downcase == FILTER_ANY
end
def filter_by_no_reaction?
params[:my_reaction_emoji].to_s.downcase == FILTER_NONE
end
def filter_by_any_reaction?
params[:my_reaction_emoji].to_s.downcase == FILTER_ANY
end
def releases?
params[:release_tag].present?
end
def project?
params[:project_id].present?
end
def group
strong_memoize(:group) do
if params[:group_id].present?
Group.find(params[:group_id])
else
nil
end
end
end
def related_groups
if project? && project&.group && Ability.allowed?(current_user, :read_group, project.group)
project.group.self_and_ancestors
elsif group
[group]
elsif current_user
Gitlab::ObjectHierarchy.new(current_user.authorized_groups, current_user.groups).all_objects
else
[]
end
end
def project
strong_memoize(:project) do
project = Project.find(params[:project_id])
project = nil unless Ability.allowed?(current_user, :"read_#{klass.to_ability_name}", project)
project
end
end
def projects
strong_memoize(:projects) do
next [project] if project?
projects =
if current_user && params[:authorized_only].presence && !current_user_related?
current_user.authorized_projects(min_access_level)
else
projects_public_or_visible_to_user
end
projects.with_feature_available_for_user(klass, current_user).reorder(nil) # rubocop: disable CodeReuse/ActiveRecord
end
end
# rubocop: disable CodeReuse/ActiveRecord
def author
strong_memoize(:author) do
if author_id?
User.find_by(id: params[:author_id])
elsif author_username?
User.find_by_username(params[:author_username])
else
nil
end
end
end
# rubocop: enable CodeReuse/ActiveRecord
# rubocop: disable CodeReuse/ActiveRecord
def assignees
strong_memoize(:assignees) do
if assignee_id?
User.where(id: params[:assignee_id])
elsif assignee_username?
User.where(username: params[:assignee_username])
else
User.none
end
end
end
# rubocop: enable CodeReuse/ActiveRecord
def assignee
assignees.first
end
def label_names
if labels?
params[:label_name].is_a?(String) ? params[:label_name].split(',') : params[:label_name]
else
[]
end
end
def labels
strong_memoize(:labels) do
if labels? && !filter_by_no_label?
LabelsFinder.new(current_user, project_ids: projects, title: label_names).execute(skip_authorization: true) # rubocop: disable CodeReuse/Finder
else
Label.none
end
end
end
def milestones
strong_memoize(:milestones) do
if milestones?
if project?
group_id = project.group&.id
project_id = project.id
end
group_id = group.id if group
search_params =
{ title: params[:milestone_title], project_ids: project_id, group_ids: group_id }
MilestonesFinder.new(search_params).execute # rubocop: disable CodeReuse/Finder
else
Milestone.none
end
end
end
def current_user_related?
scope = params[:scope]
scope == 'created_by_me' || scope == 'authored' || scope == 'assigned_to_me'
end
def find_group_projects
return Project.none unless group
if params[:include_subgroups]
Project.where(namespace_id: group.self_and_descendants) # rubocop: disable CodeReuse/ActiveRecord
else
group.projects
end
end
# We use Hash#merge in a few places, so let's support it
def merge(other)
self.class.new(params.merge(other), current_user, klass)
end
# Just for symmetry, and in case someone tries to use it
def merge!(other)
params.merge!(other)
end
private
def projects_public_or_visible_to_user
projects =
if group
if params[:projects]
find_group_projects.id_in(params[:projects])
else
find_group_projects
end
elsif params[:projects]
Project.id_in(params[:projects])
else
Project
end
projects.public_or_visible_to_user(current_user, min_access_level)
end
def min_access_level
ProjectFeature.required_minimum_access_level(klass)
end
def method_missing(method_name, *args, &block)
if method_name[-1] == '?'
params[method_name[0..-2].to_sym].present?
else
super
end
end
def respond_to_missing?(method_name, include_private = false)
method_name[-1] == '?'
end
end
end

View File

@ -38,10 +38,14 @@ class IssuesFinder < IssuableFinder
end
# rubocop: enable CodeReuse/ActiveRecord
def params_class
IssuesFinder::Params
end
# rubocop: disable CodeReuse/ActiveRecord
def with_confidentiality_access_check
return Issue.all if user_can_see_all_confidential_issues?
return Issue.where('issues.confidential IS NOT TRUE') if user_cannot_see_confidential_issues?
return Issue.all if params.user_can_see_all_confidential_issues?
return Issue.where('issues.confidential IS NOT TRUE') if params.user_cannot_see_confidential_issues?
Issue.where('
issues.confidential IS NOT TRUE
@ -57,17 +61,13 @@ class IssuesFinder < IssuableFinder
private
def init_collection
if public_only?
if params.public_only?
Issue.public_only
else
with_confidentiality_access_check
end
end
def public_only?
params.fetch(:public_only, false)
end
def filter_items(items)
issues = super
issues = by_due_date(issues)
@ -82,67 +82,19 @@ class IssuesFinder < IssuableFinder
end
def by_due_date(items)
if due_date?
if filter_by_no_due_date?
items = items.without_due_date
elsif filter_by_overdue?
items = items.due_before(Date.today)
elsif filter_by_due_this_week?
items = items.due_between(Date.today.beginning_of_week, Date.today.end_of_week)
elsif filter_by_due_this_month?
items = items.due_between(Date.today.beginning_of_month, Date.today.end_of_month)
elsif filter_by_due_next_month_and_previous_two_weeks?
items = items.due_between(Date.today - 2.weeks, (Date.today + 1.month).end_of_month)
end
return items unless params.due_date?
if params.filter_by_no_due_date?
items.without_due_date
elsif params.filter_by_overdue?
items.due_before(Date.today)
elsif params.filter_by_due_this_week?
items.due_between(Date.today.beginning_of_week, Date.today.end_of_week)
elsif params.filter_by_due_this_month?
items.due_between(Date.today.beginning_of_month, Date.today.end_of_month)
elsif params.filter_by_due_next_month_and_previous_two_weeks?
items.due_between(Date.today - 2.weeks, (Date.today + 1.month).end_of_month)
end
items
end
def filter_by_no_due_date?
due_date? && params[:due_date] == Issue::NoDueDate.name
end
def filter_by_overdue?
due_date? && params[:due_date] == Issue::Overdue.name
end
def filter_by_due_this_week?
due_date? && params[:due_date] == Issue::DueThisWeek.name
end
def filter_by_due_this_month?
due_date? && params[:due_date] == Issue::DueThisMonth.name
end
def filter_by_due_next_month_and_previous_two_weeks?
due_date? && params[:due_date] == Issue::DueNextMonthAndPreviousTwoWeeks.name
end
def due_date?
params[:due_date].present?
end
def user_can_see_all_confidential_issues?
return @user_can_see_all_confidential_issues if defined?(@user_can_see_all_confidential_issues)
return @user_can_see_all_confidential_issues = false if current_user.blank?
return @user_can_see_all_confidential_issues = true if current_user.can_read_all_resources?
@user_can_see_all_confidential_issues =
if project? && project
project.team.max_member_access(current_user.id) >= CONFIDENTIAL_ACCESS_LEVEL
elsif group
group.max_member_access_for_user(current_user) >= CONFIDENTIAL_ACCESS_LEVEL
else
false
end
end
def user_cannot_see_confidential_issues?
return false if user_can_see_all_confidential_issues?
current_user.blank?
end
end

View File

@ -0,0 +1,53 @@
# frozen_string_literal: true
class IssuesFinder
class Params < IssuableFinder::Params
def public_only?
params.fetch(:public_only, false)
end
def filter_by_no_due_date?
due_date? && params[:due_date] == Issue::NoDueDate.name
end
def filter_by_overdue?
due_date? && params[:due_date] == Issue::Overdue.name
end
def filter_by_due_this_week?
due_date? && params[:due_date] == Issue::DueThisWeek.name
end
def filter_by_due_this_month?
due_date? && params[:due_date] == Issue::DueThisMonth.name
end
def filter_by_due_next_month_and_previous_two_weeks?
due_date? && params[:due_date] == Issue::DueNextMonthAndPreviousTwoWeeks.name
end
def user_can_see_all_confidential_issues?
return @user_can_see_all_confidential_issues if defined?(@user_can_see_all_confidential_issues)
return @user_can_see_all_confidential_issues = false if current_user.blank?
return @user_can_see_all_confidential_issues = true if current_user.can_read_all_resources?
@user_can_see_all_confidential_issues =
if project? && project
project.team.max_member_access(current_user.id) >= CONFIDENTIAL_ACCESS_LEVEL
elsif group
group.max_member_access_for_user(current_user) >= CONFIDENTIAL_ACCESS_LEVEL
else
false
end
end
def user_cannot_see_confidential_issues?
return false if user_can_see_all_confidential_issues?
current_user.blank?
end
end
end
IssuableFinder::Params.prepend_if_ee('EE::IssuesFinder::Params')

View File

@ -189,7 +189,7 @@ class MergeRequest < ApplicationRecord
end
# rubocop: disable CodeReuse/ServiceClass
after_transition [:unchecked, :checking] => :cannot_be_merged do |merge_request, transition|
after_transition unchecked: :cannot_be_merged do |merge_request, transition|
if merge_request.notify_conflict?
NotificationService.new.merge_request_unmergeable(merge_request)
TodoService.new.merge_request_became_unmergeable(merge_request)

View File

@ -21,7 +21,7 @@ module Issuable
params.delete(key) unless params[key].present?
end
if params[:assignee_ids] == [IssuableFinder::NONE.to_s]
if params[:assignee_ids] == [IssuableFinder::Params::NONE.to_s]
params[:assignee_ids] = []
end

View File

@ -46,7 +46,7 @@ class IssuableBaseService < BaseService
assignee_ids = params[:assignee_ids].select { |assignee_id| assignee_can_read?(issuable, assignee_id) }
if params[:assignee_ids].map(&:to_s) == [IssuableFinder::NONE]
if params[:assignee_ids].map(&:to_s) == [IssuableFinder::Params::NONE]
params[:assignee_ids] = []
elsif assignee_ids.any?
params[:assignee_ids] = assignee_ids
@ -70,7 +70,7 @@ class IssuableBaseService < BaseService
milestone_id = params[:milestone_id]
return unless milestone_id
params[:milestone_id] = '' if milestone_id == IssuableFinder::NONE
params[:milestone_id] = '' if milestone_id == IssuableFinder::Params::NONE
groups = project.group&.self_and_ancestors&.select(:id)
milestone =

View File

@ -1,6 +1,6 @@
- page_title "Service Templates"
%h3.page-title Service templates
%p.light Service template allows you to set default values for project services
%p.light= s_('AdminSettings|Service template allows you to set default values for integrations')
.table-holder
%table.table

View File

@ -13,7 +13,7 @@
%thead
%tr
%th
%th= s_("ProjectService|Service")
%th= _('Integration')
%th.d-none.d-sm-block= _("Description")
%th= s_("ProjectService|Last edit")
- @services.sort_by(&:title).each do |service|

View File

@ -1,6 +1,6 @@
- breadcrumb_title @service.title
- add_to_breadcrumbs _('Integration Settings'), project_settings_integrations_path(@project)
- page_title @service.title, s_("ProjectService|Services")
- page_title @service.title, _('Integrations')
= render 'deprecated_message' if @service.deprecation_message

View File

@ -0,0 +1,5 @@
---
title: Rename "Project Services" to "Integrations" in frontend and docs
merge_request: 26244
author:
type: changed

View File

@ -0,0 +1,5 @@
---
title: Add tooltips with full path to file headers on file tree
merge_request: 27437
author:
type: fixed

View File

@ -211,7 +211,7 @@ The following documentation relates to the DevOps **Create** stage:
| [GitLab Integration](integration/README.md) | Integrate with multiple third-party services with GitLab to allow external issue trackers and external authentication. |
| [GitLab Webhooks](user/project/integrations/webhooks.md) | Let GitLab notify you when new code has been pushed to your project. |
| [Jira Development Panel](integration/jira_development_panel.md) **(PREMIUM)** | See GitLab information in the Jira Development Panel. |
| [Project Services](user/project/integrations/project_services.md) | Integrate a project with external services, such as CI and chat. |
| [Integrations](user/project/integrations/overview.md) | Integrate a project with external services, such as CI and chat. |
| [Trello Power-Up](integration/trello_power_up.md) | Integrate with GitLab's Trello Power-Up. |
<div align="right">

View File

@ -196,7 +196,7 @@ than the specified limit, hooks won't be executed.
More information can be found in these docs:
- [Webhooks push events](../user/project/integrations/webhooks.md#push-events)
- [Project services push hooks limit](../user/project/integrations/project_services.md#push-hooks-limit)
- [Project services push hooks limit](../user/project/integrations/overview.md#push-hooks-limit)
### Activities

View File

@ -228,7 +228,7 @@ This file lives in `/var/log/gitlab/gitlab-rails/integrations_json.log` for
Omnibus GitLab packages or in `/home/git/gitlab/log/integrations_json.log` for
installations from source.
It contains information about [integrations](../user/project/integrations/project_services.md) activities such as Jira, Asana, and Irker services. It uses JSON format like the example below:
It contains information about [integrations](../user/project/integrations/overview.md) activities such as Jira, Asana, and Irker services. It uses JSON format like the example below:
```json
{

View File

@ -30,7 +30,7 @@ either:
NOTE: **Note:**
This only applies to pipelines run as part of GitLab CI/CD. This will not enable or disable
pipelines that are run from an [external integration](../user/project/integrations/project_services.md#services).
pipelines that are run from an [external integration](../user/project/integrations/overview.md#integrations-listing).
## Per-project user setting

View File

@ -435,13 +435,13 @@ To learn more about about scoping environments, see [Scoping environments with s
> Introduced in GitLab 8.15.
[Project services](../../user/project/integrations/project_services.md) that are
[Integrations](../../user/project/integrations/overview.md) that are
responsible for deployment configuration may define their own variables that
are set in the build environment. These variables are only defined for
[deployment jobs](../environments.md). Please consult the documentation of
the project services that you are using to learn which variables they define.
the integrations that you are using to learn which variables they define.
An example project service that defines deployment variables is the
An example integration that defines deployment variables is the
[Kubernetes integration](../../user/project/clusters/index.md#deployment-variables).
### Auto DevOps environment variables

View File

@ -90,3 +90,22 @@ To activate the Jenkins service you must have a Starter subscription or higher.
## Test your setup
Make a change in your repository and open an MR. In your Jenkins project it should have triggered a new build and on your MR, there should be a widget saying "Pipeline #NUMBER passed". It will also include a link to your Jenkins build.
### Run QA test
The [jenkins_build_status_spec](https://gitlab.com/gitlab-org/gitlab/-/blob/v12.9.0-ee/qa/qa/specs/features/ee/browser_ui/3_create/jenkins/jenkins_build_status_spec.rb) performs an end-to-end test of the Jenkins setup using [GitLab QA](https://gitlab.com/gitlab-org/gitlab-qa).
To run the test against your GDK, follow the [run QA tests against your GDK setup](https://gitlab.com/gitlab-org/gitlab-qa/-/blob/master/docs/run_qa_against_gdk.md#run-qa-tests-against-your-gdk-setup) instructions.
The following environment variables are required to run the test:
- `GITLAB_USERNAME`
- `GITLAB_PASSWORD`
- `GITLAB_ADMIN_USERNAME`
- `GITLAB_ADMIN_PASSWORD`
Run the test in the **qa** directory using:
```shell
bundle exec bin/qa Test::Instance::All http://<your_network_ip_address>:3000 -- qa/specs/features/ee/browser_ui/3_create/jenkins/jenkins_build_status_spec.rb --tag quarantine
```

View File

@ -57,9 +57,9 @@ GitLab can be integrated with the following enhancements:
- Attach merge requests to [Trello](trello_power_up.md) cards.
- Enable integrated code intelligence powered by [Sourcegraph](sourcegraph.md).
## Project services
## Integrations
Integration with services such as Campfire, Flowdock, HipChat, Pivotal Tracker, and Slack are available as [Project Services](../user/project/integrations/project_services.md).
Integration with services such as Campfire, Flowdock, HipChat, Pivotal Tracker, and Slack are available as [Integrations](../user/project/integrations/overview.md).
## Troubleshooting

View File

@ -15,11 +15,11 @@ GitLab menu always opens the internal issue tracker. When disabled, the link is
## Configuration
The configuration is done via a project's **Services**.
The configuration is done via a project's **Integrations**.
### Project Service
### Integration
To enable an external issue tracker you must configure the appropriate **Service**.
To enable an external issue tracker you must configure the appropriate **Integration**.
Visit the links below for details:
- [Redmine](../user/project/integrations/redmine.md)

View File

@ -6,8 +6,8 @@ In GitLab 8.3, Jenkins integration using the
was deprecated in favor of the
[GitLab Plugin](https://wiki.jenkins.io/display/JENKINS/GitLab+Plugin).
The deprecated integration has been renamed to [Jenkins CI (Deprecated)](jenkins_deprecated.md) in the
project service settings. We may remove this in a future release and recommend
using the new 'Jenkins CI' project service instead which is described in this
integration settings. We may remove this in a future release and recommend
using the new 'Jenkins CI' integration instead which is described in this
document.
## Overview
@ -138,7 +138,7 @@ configured or there was an error reporting the status via the API.
### Merge Request event does not trigger a Jenkins Pipeline
Check [service hook logs](../user/project/integrations/project_services.md#troubleshooting-project-services) for request failures or check the `/var/log/gitlab/gitlab-rails/production.log` file for messages like:
Check [service hook logs](../user/project/integrations/overview.md#troubleshooting-integrations) for request failures or check the `/var/log/gitlab/gitlab-rails/production.log` file for messages like:
```plaintext
WebHook Error => Net::ReadTimeout

View File

@ -2,7 +2,7 @@
> The `run` command was [introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/4466) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 10.6. [Moved](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/24780) to [GitLab Core](https://about.gitlab.com/pricing/) in 11.9.
Slash commands in Mattermost and Slack allow you to control GitLab and view GitLab content right inside your chat client, without having to leave it. For Slack, this requires a [project service configuration](../user/project/integrations/slack_slash_commands.md). Simply type the command as a message in your chat client to activate it.
Slash commands in Mattermost and Slack allow you to control GitLab and view GitLab content right inside your chat client, without having to leave it. For Slack, this requires an [integration configuration](../user/project/integrations/slack_slash_commands.md). Simply type the command as a message in your chat client to activate it.
Commands are scoped to a project, with a trigger term that is specified during configuration.

View File

@ -1,5 +1,5 @@
---
redirect_to: '../user/project/integrations/project_services.md'
redirect_to: '../user/project/integrations/overview.md'
---
This document was moved to [another location](../user/project/integrations/project_services.md).
This document was moved to [another location](../user/project/integrations/overview.md).

View File

@ -66,7 +66,7 @@ With GitLab Enterprise Edition, you can also:
- Leverage continuous delivery method with [Canary Deployments](project/canary_deployments.md).
- Scan your code for vulnerabilities and [display them in merge requests](application_security/sast/index.md).
You can also [integrate](project/integrations/project_services.md) GitLab with numerous third-party applications, such as Mattermost, Microsoft Teams, HipChat, Trello, Slack, Bamboo CI, Jira, and a lot more.
You can also [integrate](project/integrations/overview.md) GitLab with numerous third-party applications, such as Mattermost, Microsoft Teams, HipChat, Trello, Slack, Bamboo CI, Jira, and a lot more.
## Projects

View File

@ -78,7 +78,7 @@ Kubernetes clusters can be used without Auto DevOps.
> Introduced in GitLab 8.15.
When enabled, the Kubernetes service adds [web terminal](../../../ci/environments.md#web-terminals)
When enabled, the Kubernetes integration adds [web terminal](../../../ci/environments.md#web-terminals)
support to your [environments](../../../ci/environments.md). This is based on the `exec` functionality found in
Docker and Kubernetes, so you get a new shell session within your existing
containers. To use this integration, you should deploy to Kubernetes using

View File

@ -72,7 +72,7 @@ To display the Deploy Boards for a specific [environment] you should:
1. [Configure GitLab Runner][runners] with the [Docker][docker-exec] or
[Kubernetes][kube-exec] executor.
1. Configure the [Kubernetes service][kube-service] in your project for the
1. Configure the [Kubernetes integration][kube-integration] in your project for the
cluster. The Kubernetes namespace is of particular note as you will need it
for your deployment scripts (exposed by the `KUBE_NAMESPACE` env variable).
1. Ensure Kubernetes annotations of `app.gitlab.com/env: $CI_ENVIRONMENT_SLUG`
@ -151,7 +151,7 @@ version of your application.
[environment]: ../../ci/environments.md "Environments and deployments documentation"
[docker-exec]: https://docs.gitlab.com/runner/executors/docker.html "GitLab Runner Docker executor"
[kube-exec]: https://docs.gitlab.com/runner/executors/kubernetes.html "GitLab Runner Kubernetes executor"
[kube-service]: integrations/kubernetes.md "Kubernetes project service"
[kube-integration]: clusters/index.md "Kubernetes integration"
[review apps]: ../../ci/review_apps/index.md "Review Apps documentation"
[variables]: ../../ci/variables/README.md "GitLab CI/CD variables"
[autodeploy]: ../../topics/autodevops/index.md#auto-deploy "GitLab Autodeploy"

View File

@ -37,7 +37,7 @@ service in GitLab.
### Complete these steps in GitLab
1. Navigate to the project you want to configure to trigger builds.
1. Navigate to the [Integrations page](project_services.md#accessing-the-project-services)
1. Navigate to the [Integrations page](overview.md#accessing-integrations)
1. Click 'Atlassian Bamboo CI'
1. Select the 'Active' checkbox.
1. Enter the base URL of your Bamboo server. `https://bamboo.example.com`
@ -55,7 +55,7 @@ service in GitLab.
## Troubleshooting
If builds are not triggered, ensure you entered the right GitLab IP address in
Bamboo under 'Trigger IP addresses'. Also check [service hook logs](project_services.md#troubleshooting-project-services) for request failures.
Bamboo under 'Trigger IP addresses'. Also check [service hook logs](overview.md#troubleshooting-integrations) for request failures.
NOTE: **Note:**
Starting with GitLab 8.14.0, builds are triggered on push events.

View File

@ -1,6 +1,6 @@
# Bugzilla Service
Navigate to the [Integrations page](project_services.md#accessing-the-project-services),
Navigate to the [Integrations page](overview.md#accessing-integrations),
select the **Bugzilla** service and fill in the required details as described
in the table below.
@ -29,4 +29,4 @@ address specified in `issues_url`.
## Troubleshooting
To see recent service hook deliveries, check [service hook logs](project_services.md#troubleshooting-project-services).
To see recent service hook deliveries, check [service hook logs](overview.md#troubleshooting-integrations).

View File

@ -1,7 +1,7 @@
# Custom Issue Tracker Service
To enable the Custom Issue Tracker integration in a project, navigate to the
[Integrations page](project_services.md#accessing-the-project-services), click
[Integrations page](overview.md#accessing-integrations), click
the **Customer Issue Tracker** service, and fill in the required details on the page as described
in the table below. You will be able to edit the title and description later as well.

View File

@ -19,8 +19,8 @@ To send GitLab event notifications to a Discord channel, create a webhook in Dis
With the webhook URL created in the Discord channel, you can set up the Discord Notifications service in GitLab.
1. Navigate to the [Integrations page](project_services.md#accessing-the-project-services) in your project's settings. That is, **Project > Settings > Integrations**.
1. Select the **Discord Notifications** project service to configure it.
1. Navigate to the [Integrations page](overview.md#accessing-integrations) in your project's settings. That is, **Project > Settings > Integrations**.
1. Select the **Discord Notifications** integration to configure it.
1. Check the **Active** checkbox to turn on the service.
1. Check the checkboxes corresponding to the GitLab events for which you want to send notifications to Discord.
1. Paste the webhook URL that you copied from the create Discord webhook step.

View File

@ -3,7 +3,7 @@
By enabling this service, you will receive email notifications for every change
that is pushed to your project.
From the [Integrations page](project_services.md#accessing-the-project-services)
From the [Integrations page](overview.md#accessing-integrations)
select **Emails on push** service to activate and configure it.
In the _Recipients_ area, provide a list of emails separated by spaces or newlines.

View File

@ -25,7 +25,7 @@ with `repo:status` access granted:
### Complete these steps on GitLab
1. Navigate to the project you want to configure.
1. Navigate to the [Integrations page](project_services.md#accessing-the-project-services)
1. Navigate to the [Integrations page](overview.md#accessing-integrations)
1. Click "GitHub".
1. Select the "Active" checkbox.
1. Paste the token you've generated on GitHub

View File

@ -17,8 +17,8 @@ See also [the Hangouts Chat documentation for configuring incoming webhooks](htt
When you have the **Webhook URL** for your Hangouts Chat room webhook, you can set up the GitLab service.
1. Navigate to the [Integrations page](project_services.md#accessing-the-project-services) in your project's settings, i.e. **Project > Settings > Integrations**.
1. Select the **Hangouts Chat** project service to configure it.
1. Navigate to the [Integrations page](overview.md#accessing-integrations) in your project's settings, i.e. **Project > Settings > Integrations**.
1. Select the **Hangouts Chat** integration to configure it.
1. Check the **Active** checkbox to turn on the service.
1. Check the checkboxes corresponding to the GitLab events you want to receive.
1. Paste the **Webhook URL** that you copied from the Hangouts Chat configuration step.

View File

@ -35,7 +35,7 @@ service in GitLab.
### Complete these steps in GitLab
1. Navigate to the project you want to configure for notifications.
1. Navigate to the [Integrations page](project_services.md#accessing-the-project-services)
1. Navigate to the [Integrations page](overview.md#accessing-integrations)
1. Click "HipChat".
1. Select the "Active" checkbox.
1. Insert the `token` field from the URL into the `Token` field on the Web page.

View File

@ -4,13 +4,13 @@ You can find the available integrations under your project's
**Settings ➔ Integrations** page. You need to have at least
[maintainer permission][permissions] on the project.
## Project services
## Integrations
Project services allow you to integrate GitLab with other applications.
Integrations allow you to integrate GitLab with other applications.
They are a bit like plugins in that they allow a lot of freedom in
adding functionality to GitLab.
[Learn more about project services.](project_services.md)
[Learn more about integrations.](overview.md)
## Project webhooks

View File

@ -26,7 +26,7 @@ need to follow the firsts steps of the next section.
## Complete these steps in GitLab
1. Navigate to the project you want to configure for notifications.
1. Navigate to the [Integrations page](project_services.md#accessing-the-project-services)
1. Navigate to the [Integrations page](overview.md#accessing-integrations)
1. Click "Irker".
1. Select the "Active" checkbox.
1. Enter the server host address where `irkerd` runs (defaults to `localhost`)

View File

@ -65,7 +65,7 @@ In order to enable the Jira service in GitLab, you need to first configure the p
> a value of `fromDialog`.
To enable the Jira integration in a project, navigate to the
[Integrations page](project_services.md#accessing-the-project-services), click
[Integrations page](overview.md#accessing-integrations), click
the **Jira** service, and fill in the required details on the page as described
in the table below.
@ -101,7 +101,7 @@ When you reference a Jira issue, it will always link back to the source commit/M
To disable the automated commenting on Jira issues:
1. Open the [Integrations page](project_services.md#accessing-the-project-services) and select **Jira**.
1. Open the [Integrations page](overview.md#accessing-integrations) and select **Jira**.
1. In the **Event Action** section, uncheck **Comment**.
## Jira issues

View File

@ -27,7 +27,7 @@ Display name override is not enabled by default, you need to ask your admin to e
After you set up Mattermost, it's time to set up GitLab.
Navigate to the [Integrations page](project_services.md#accessing-the-project-services)
Navigate to the [Integrations page](overview.md#accessing-integrations)
and select the **Mattermost notifications** service to configure it.
There, you will see a checkbox with the following events that can be triggered:

View File

@ -53,7 +53,7 @@ the administrator console.
### Step 2. Open the Mattermost slash commands service in GitLab
1. Open a new tab for GitLab, go to your project's
[Integrations page](project_services.md#accessing-the-project-services)
[Integrations page](overview.md#accessing-integrations)
and select the **Mattermost command** service to configure it.
A screen will appear with all the values you need to copy in Mattermost as
described in the next step. Leave the window open.

View File

@ -9,7 +9,7 @@ Teams by following the steps described in [Sending messages to Connectors and We
After you set up Microsoft Teams, it's time to set up GitLab.
Navigate to the [Integrations page](project_services.md#accessing-the-project-services)
Navigate to the [Integrations page](overview.md#accessing-integrations)
and select the **Microsoft Teams Notification** service to configure it.
There, you will see a checkbox with the following events that can be triggered:

View File

@ -0,0 +1,108 @@
# Integrations
Integrations allow you to integrate GitLab with other applications. They
are a bit like plugins in that they allow a lot of freedom in adding
functionality to GitLab.
## Accessing integrations
You can find the available integrations under your project's
**Settings ➔ Integrations** page.
There are more than 20 integrations to integrate with. Click on the one that you
want to configure.
![Integrations list](img/project_services.png)
Below, you will find a list of the currently supported ones accompanied with comprehensive documentation.
## Integrations listing
Click on the service links to see further configuration instructions and details.
| Service | Description | Service Hooks |
| ------- | ----------- | ------------- |
| Asana | Asana - Teamwork without email | No |
| Assembla | Project Management Software (Source Commits Endpoint) | No |
| [Atlassian Bamboo CI](bamboo.md) | A continuous integration and build server | Yes |
| Buildkite | Continuous integration and deployments | Yes |
| [Bugzilla](bugzilla.md) | Bugzilla issue tracker | No |
| Campfire | Simple web-based real-time group chat | No |
| Custom Issue Tracker | Custom issue tracker | No |
| [Discord Notifications](discord_notifications.md) | Receive event notifications in Discord | No |
| Drone CI | Continuous Integration platform built on Docker, written in Go | Yes |
| [Emails on push](emails_on_push.md) | Email the commits and diff of each push to a list of recipients | No |
| External Wiki | Replaces the link to the internal wiki with a link to an external wiki | No |
| Flowdock | Flowdock is a collaboration web app for technical teams | No |
| [Generic alerts](generic_alerts.md) **(ULTIMATE)** | Receive alerts on GitLab from any source | No |
| [GitHub](github.md) **(PREMIUM)** | Sends pipeline notifications to GitHub | No |
| [Hangouts Chat](hangouts_chat.md) | Receive events notifications in Google Hangouts Chat | No |
| [HipChat](hipchat.md) | Private group chat and IM | No |
| [Irker (IRC gateway)](irker.md) | Send IRC messages, on update, to a list of recipients through an Irker gateway | No |
| [Jira](jira.md) | Jira issue tracker | No |
| [Jenkins](../../../integration/jenkins.md) **(STARTER)** | An extendable open source continuous integration server | Yes |
| JetBrains TeamCity CI | A continuous integration and build server | Yes |
| [Mattermost slash commands](mattermost_slash_commands.md) | Mattermost chat and ChatOps slash commands | No |
| [Mattermost Notifications](mattermost.md) | Receive event notifications in Mattermost | No |
| [Microsoft teams](microsoft_teams.md) | Receive notifications for actions that happen on GitLab into a room on Microsoft Teams using Office 365 Connectors | No |
| Packagist | Update your project on Packagist, the main Composer repository | Yes |
| Pipelines emails | Email the pipeline status to a list of recipients | No |
| [Slack Notifications](slack.md) | Send GitLab events (e.g. issue created) to Slack as notifications | No |
| [Slack slash commands](slack_slash_commands.md) **(CORE ONLY)** | Use slash commands in Slack to control GitLab | No |
| [GitLab Slack application](gitlab_slack_application.md) **(FREE ONLY)** | Use Slack's official application | No |
| PivotalTracker | Project Management Software (Source Commits Endpoint) | No |
| [Prometheus](prometheus.md) | Monitor the performance of your deployed apps | No |
| Pushover | Pushover makes it easy to get real-time notifications on your Android device, iPhone, iPad, and Desktop | No |
| [Redmine](redmine.md) | Redmine issue tracker | No |
| [Unify Circuit](unify_circuit.md) | Receive events notifications in Unify Circuit | No |
| [YouTrack](youtrack.md) | YouTrack issue tracker | No |
## Push hooks limit
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/17874) in GitLab 12.4.
If a single push includes changes to more than three branches or tags, services
supported by `push_hooks` and `tag_push_hooks` events won't be executed.
The number of branches or tags supported can be changed via
[`push_event_hooks_limit` application setting](../../../api/settings.md#list-of-settings-that-can-be-accessed-via-api-calls).
## Services templates
Services templates is a way to set some predefined values in the Service of
your liking which will then be pre-filled on each project's Service.
Read more about [Services templates in this document](services_templates.md).
## Troubleshooting integrations
Some integrations use service hooks for integration with external applications. To confirm which ones use service hooks, see the [integrations listing](#integrations-listing). GitLab stores details of service hook requests made within the last 2 days. To view details of the requests, go to the service's configuration page.
The **Recent Deliveries** section lists the details of each request made within the last 2 days:
- HTTP status code (green for 200-299 codes, red for the others, `internal error` for failed deliveries)
- Triggered event
- URL to which the request was sent
- Elapsed time of the request
- Relative time in which the request was made
To view more information about the request's execution, click the respective **View details** link.
On the details page, you can see the data sent by GitLab (request headers and body) and the data received by GitLab (response headers and body).
From this page, you can repeat delivery with the same data by clicking **Resend Request**.
![Recent deliveries](img/webhook_logs.png)
## Contributing to integrations
Because GitLab is open source we can ship with the code and tests for all
plugins. This allows the community to keep the plugins up to date so that they
always work in newer GitLab versions.
For an overview of what integrations are available, please see the
[project_services source directory][projects-code].
Contributions are welcome!
[projects-code]: https://gitlab.com/gitlab-org/gitlab-foss/tree/master/app/models/project_services
[permissions]: ../../permissions.md

View File

@ -1,108 +1 @@
# Project services
Project services allow you to integrate GitLab with other applications. They
are a bit like plugins in that they allow a lot of freedom in adding
functionality to GitLab.
## Accessing the project services
You can find the available services under your project's
**Settings ➔ Integrations** page.
There are more than 20 services to integrate with. Click on the one that you
want to configure.
![Project services list](img/project_services.png)
Below, you will find a list of the currently supported ones accompanied with comprehensive documentation.
## Services
Click on the service links to see further configuration instructions and details.
| Service | Description | Service Hooks |
| ------- | ----------- | ------------- |
| Asana | Asana - Teamwork without email | No |
| Assembla | Project Management Software (Source Commits Endpoint) | No |
| [Atlassian Bamboo CI](bamboo.md) | A continuous integration and build server | Yes |
| Buildkite | Continuous integration and deployments | Yes |
| [Bugzilla](bugzilla.md) | Bugzilla issue tracker | No |
| Campfire | Simple web-based real-time group chat | No |
| Custom Issue Tracker | Custom issue tracker | No |
| [Discord Notifications](discord_notifications.md) | Receive event notifications in Discord | No |
| Drone CI | Continuous Integration platform built on Docker, written in Go | Yes |
| [Emails on push](emails_on_push.md) | Email the commits and diff of each push to a list of recipients | No |
| External Wiki | Replaces the link to the internal wiki with a link to an external wiki | No |
| Flowdock | Flowdock is a collaboration web app for technical teams | No |
| [Generic alerts](generic_alerts.md) **(ULTIMATE)** | Receive alerts on GitLab from any source | No |
| [GitHub](github.md) **(PREMIUM)** | Sends pipeline notifications to GitHub | No |
| [Hangouts Chat](hangouts_chat.md) | Receive events notifications in Google Hangouts Chat | No |
| [HipChat](hipchat.md) | Private group chat and IM | No |
| [Irker (IRC gateway)](irker.md) | Send IRC messages, on update, to a list of recipients through an Irker gateway | No |
| [Jira](jira.md) | Jira issue tracker | No |
| [Jenkins](../../../integration/jenkins.md) **(STARTER)** | An extendable open source continuous integration server | Yes |
| JetBrains TeamCity CI | A continuous integration and build server | Yes |
| [Mattermost slash commands](mattermost_slash_commands.md) | Mattermost chat and ChatOps slash commands | No |
| [Mattermost Notifications](mattermost.md) | Receive event notifications in Mattermost | No |
| [Microsoft teams](microsoft_teams.md) | Receive notifications for actions that happen on GitLab into a room on Microsoft Teams using Office 365 Connectors | No |
| Packagist | Update your project on Packagist, the main Composer repository | Yes |
| Pipelines emails | Email the pipeline status to a list of recipients | No |
| [Slack Notifications](slack.md) | Send GitLab events (e.g. issue created) to Slack as notifications | No |
| [Slack slash commands](slack_slash_commands.md) **(CORE ONLY)** | Use slash commands in Slack to control GitLab | No |
| [GitLab Slack application](gitlab_slack_application.md) **(FREE ONLY)** | Use Slack's official application | No |
| PivotalTracker | Project Management Software (Source Commits Endpoint) | No |
| [Prometheus](prometheus.md) | Monitor the performance of your deployed apps | No |
| Pushover | Pushover makes it easy to get real-time notifications on your Android device, iPhone, iPad, and Desktop | No |
| [Redmine](redmine.md) | Redmine issue tracker | No |
| [Unify Circuit](unify_circuit.md) | Receive events notifications in Unify Circuit | No |
| [YouTrack](youtrack.md) | YouTrack issue tracker | No |
## Push hooks limit
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/17874) in GitLab 12.4.
If a single push includes changes to more than three branches or tags, services
supported by `push_hooks` and `tag_push_hooks` events won't be executed.
The number of branches or tags supported can be changed via
[`push_event_hooks_limit` application setting](../../../api/settings.md#list-of-settings-that-can-be-accessed-via-api-calls).
## Services templates
Services templates is a way to set some predefined values in the Service of
your liking which will then be pre-filled on each project's Service.
Read more about [Services templates in this document](services_templates.md).
## Troubleshooting project services
Some project services use service hooks for integration with external applications. To confirm which ones use service hooks, see the [services table](#services). GitLab stores details of service hook requests made within the last 2 days. To view details of the requests, go to the service's configuration page.
The **Recent Deliveries** section lists the details of each request made within the last 2 days:
- HTTP status code (green for 200-299 codes, red for the others, `internal error` for failed deliveries)
- Triggered event
- URL to which the request was sent
- Elapsed time of the request
- Relative time in which the request was made
To view more information about the request's execution, click the respective **View details** link.
On the details page, you can see the data sent by GitLab (request headers and body) and the data received by GitLab (response headers and body).
From this page, you can repeat delivery with the same data by clicking **Resend Request**.
![Recent deliveries](img/webhook_logs.png)
## Contributing to project services
Because GitLab is open source we can ship with the code and tests for all
plugins. This allows the community to keep the plugins up to date so that they
always work in newer GitLab versions.
For an overview of what projects services are available, please see the
[project_services source directory][projects-code].
Contributions are welcome!
[projects-code]: https://gitlab.com/gitlab-org/gitlab-foss/tree/master/app/models/project_services
[permissions]: ../../permissions.md
This document was moved to [Integrations](overview.md).

View File

@ -105,7 +105,7 @@ The actual configuration of Prometheus integration within GitLab is very simple.
All you will need is the domain name or IP address of the Prometheus server you'd like
to integrate with.
1. Navigate to the [Integrations page](project_services.md#accessing-the-project-services).
1. Navigate to the [Integrations page](overview.md#accessing-integrations).
1. Click the **Prometheus** service.
1. Provide the domain name or IP address of your server, for example `http://prometheus.example.com/` or `http://192.0.2.1/`.
1. Click **Save changes**.
@ -118,7 +118,7 @@ You can configure [Thanos](https://thanos.io/) as a drop-in replacement for Prom
with GitLab. You will need the domain name or IP address of the Thanos server you'd like
to integrate with.
1. Navigate to the [Integrations page](project_services.md#accessing-the-project-services).
1. Navigate to the [Integrations page](overview.md#accessing-integrations).
1. Click the **Prometheus** service.
1. Provide the domain name or IP address of your server, for example `http://thanos.example.com/` or `http://192.0.2.1/`.
1. Click **Save changes**.

View File

@ -1,7 +1,7 @@
# Redmine Service
1. To enable the Redmine integration in a project, navigate to the
[Integrations page](project_services.md#accessing-the-project-services), click
[Integrations page](overview.md#accessing-integrations), click
the **Redmine** service, and fill in the required details on the page as described
in the table below.

View File

@ -12,8 +12,8 @@ The Slack Notifications Service allows your GitLab project to send events (e.g.
## GitLab Configuration
1. Navigate to the [Integrations page](project_services.md#accessing-the-project-services) in your project's settings, i.e. **Project > Settings > Integrations**.
1. Select the **Slack notifications** project service to configure it.
1. Navigate to the [Integrations page](overview.md#accessing-integrations) in your project's settings, i.e. **Project > Settings > Integrations**.
1. Select the **Slack notifications** integration to configure it.
1. Check the **Active** checkbox to turn on the service.
1. Check the checkboxes corresponding to the GitLab events you want to send to Slack as a notification.
1. For each event, optionally enter the Slack channel names where you want to send the event, separated by a comma. If left empty, the event will be sent to the default channel that you configured in the Slack Configuration step. **Note:** Usernames and private channels are not supported. To send direct messages, use the Member ID found under user's Slack profile.

View File

@ -13,8 +13,8 @@ For GitLab.com, use the [Slack app](gitlab_slack_application.md) instead.
## Configuration
1. Slack slash commands are scoped to a project. Navigate to the [Integrations page](project_services.md#accessing-the-project-services) in your project's settings, i.e. **Project > Settings > Integrations**.
1. Select the **Slack slash commands** project service to configure it. This page contains required information to complete the configuration in Slack. Leave this browser tab open.
1. Slack slash commands are scoped to a project. Navigate to the [Integrations page](overview.md#accessing-integrations) in your project's settings, i.e. **Project > Settings > Integrations**.
1. Select the **Slack slash commands** integration to configure it. This page contains required information to complete the configuration in Slack. Leave this browser tab open.
1. Open a new browser tab and sign in to your Slack team. [Start a new Slash Commands integration](https://my.slack.com/services/new/slash-commands).
1. Enter a trigger term. We suggest you use the project name. Click **Add Slash Command Integration**.
1. Complete the rest of the fields in the Slack configuration page using information from the GitLab browser tab. In particular, the URL needs to be copied and pasted. Click **Save Integration** to complete the configuration in Slack.

View File

@ -15,8 +15,8 @@ For more information, see the [Unify Circuit documentation for configuring incom
When you have the **Webhook URL** for your Unify Circuit conversation webhook, you can set up the GitLab service.
1. Navigate to the [Integrations page](project_services.md#accessing-the-project-services) in your project's settings, i.e. **Project > Settings > Integrations**.
1. Select the **Unify Circuit** project service to configure it.
1. Navigate to the [Integrations page](overview.md#accessing-integrations) in your project's settings, i.e. **Project > Settings > Integrations**.
1. Select the **Unify Circuit** integration to configure it.
1. Check the **Active** checkbox to turn on the service.
1. Check the checkboxes corresponding to the GitLab events you want to receive in Unify Circuit.
1. Paste the **Webhook URL** that you copied from the Unify Circuit configuration step.

View File

@ -8,7 +8,7 @@ You can configure YouTrack as an [External Issue Tracker](../../../integration/e
To enable YouTrack integration in a project:
1. Navigate to the project's **Settings > [Integrations](project_services.md#accessing-the-project-services)** page.
1. Navigate to the project's **Settings > [Integrations](overview.md#accessing-integrations)** page.
1. Click the **YouTrack** service, ensure it's active, and enter the required details on the page as described in the table below.
| Field | Description |

View File

@ -39,7 +39,7 @@ You can prevent merge requests from being merged if their pipeline did not succe
or if there are threads to be resolved. This works for both:
- GitLab CI/CD pipelines
- Pipelines run from an [external CI integration](../integrations/project_services.md#services)
- Pipelines run from an [external CI integration](../integrations/overview.md#integrations-listing)
As a result, [disabling GitLab CI/CD pipelines](../../../ci/enable_or_disable_ci.md)
will not disable this feature, as it will still be possible to use pipelines from external

View File

@ -124,7 +124,7 @@ When you click the **Create branch** button in an empty
repository project, GitLab automatically creates a `master` branch, commits
a blank `README.md` file to it, and creates and redirects you to a new branch
based on the issue title.
If your [project is already configured with a deployment service](../integrations/project_services.md),
If your [project is already configured with a deployment service](../integrations/overview.md),
such as Kubernetes, GitLab takes one step further and prompts you to set up
[auto deploy](../../../topics/autodevops/index.md#auto-deploy)
by helping you create a `.gitlab-ci.yml` file.

View File

@ -38,7 +38,7 @@ module API
value = params[attr_name]
return if value.is_a?(Integer) ||
[IssuableFinder::FILTER_NONE, IssuableFinder::FILTER_ANY].include?(value.to_s.downcase)
[IssuableFinder::Params::FILTER_NONE, IssuableFinder::Params::FILTER_ANY].include?(value.to_s.downcase)
raise Grape::Exceptions::Validation, params: [@scope.full_name(attr_name)],
message: "should be an integer, 'None' or 'Any'"
@ -50,7 +50,7 @@ module API
value = params[attr_name]
return if value.is_a?(Array) ||
[IssuableFinder::FILTER_NONE, IssuableFinder::FILTER_ANY].include?(value.to_s.downcase)
[IssuableFinder::Params::FILTER_NONE, IssuableFinder::Params::FILTER_ANY].include?(value.to_s.downcase)
raise Grape::Exceptions::Validation, params: [@scope.full_name(attr_name)],
message: "should be an array, 'None' or 'Any'"

View File

@ -944,6 +944,10 @@ module Gitlab
Gitlab::GitalyClient::ConflictsService.new(self, our_commit_oid, their_commit_oid)
end
def praefect_info_client
@praefect_info_client ||= Gitlab::GitalyClient::PraefectInfoService.new(self)
end
def clean_stale_repository_files
wrapped_gitaly_errors do
gitaly_repository_client.cleanup if exists?
@ -1019,6 +1023,12 @@ module Gitlab
raise NoRepository # Guard against data races.
end
def replicas
wrapped_gitaly_errors do
praefect_info_client.replicas
end
end
private
def empty_diff_stats

View File

@ -0,0 +1,19 @@
# frozen_string_literal: true
module Gitlab
module GitalyClient
class PraefectInfoService
def initialize(repository)
@repository = repository
@gitaly_repo = repository.gitaly_repository
@storage = repository.storage
end
def replicas
request = Gitaly::RepositoryReplicasRequest.new(repository: @gitaly_repo)
GitalyClient.call(@storage, :praefect_info_service, :repository_replicas, request, timeout: GitalyClient.fast_timeout)
end
end
end
end

View File

@ -1384,6 +1384,9 @@ msgstr ""
msgid "AdminSettings|Select a template"
msgstr ""
msgid "AdminSettings|Service template allows you to set default values for integrations"
msgstr ""
msgid "AdminSettings|Set an instance-wide auto included %{link_start}pipeline configuration%{link_end}. This pipeline configuration will be run after the project's own configuration."
msgstr ""
@ -15537,12 +15540,6 @@ msgstr ""
msgid "ProjectService|Perform common operations on GitLab project: %{project_name}"
msgstr ""
msgid "ProjectService|Service"
msgstr ""
msgid "ProjectService|Services"
msgstr ""
msgid "ProjectService|To set up this service:"
msgstr ""

View File

@ -39,8 +39,8 @@
"@babel/plugin-syntax-import-meta": "^7.8.3",
"@babel/preset-env": "^7.8.4",
"@gitlab/at.js": "^1.5.5",
"@gitlab/svgs": "^1.115.0",
"@gitlab/ui": "^10.0.1",
"@gitlab/svgs": "^1.116.0",
"@gitlab/ui": "^10.1.2",
"@gitlab/visual-review-tools": "1.5.1",
"@sentry/browser": "^5.10.2",
"@sourcegraph/code-host-integration": "0.0.34",

View File

@ -24,7 +24,7 @@ describe 'User filters issues' do
let(:issue) { @issue }
it 'allows filtering by issues with no specified assignee' do
visit project_issues_path(project, assignee_id: IssuableFinder::FILTER_NONE)
visit project_issues_path(project, assignee_id: IssuableFinder::Params::FILTER_NONE)
expect(page).to have_content 'foobar'
expect(page).not_to have_content 'barbaz'

View File

@ -35,7 +35,7 @@ describe 'Merge requests > User lists merge requests' do
end
it 'filters on no assignee' do
visit_merge_requests(project, assignee_id: IssuableFinder::FILTER_NONE)
visit_merge_requests(project, assignee_id: IssuableFinder::Params::FILTER_NONE)
expect(current_path).to eq(project_merge_requests_path(project))
expect(page).to have_content 'merge-test'

View File

@ -429,7 +429,7 @@ describe IssuesFinder do
end
context 'filtering by no label' do
let(:params) { { label_name: described_class::FILTER_NONE } }
let(:params) { { label_name: described_class::Params::FILTER_NONE } }
it 'returns issues with no labels' do
expect(issues).to contain_exactly(issue1, issue4)
@ -437,7 +437,7 @@ describe IssuesFinder do
end
context 'filtering by any label' do
let(:params) { { label_name: described_class::FILTER_ANY } }
let(:params) { { label_name: described_class::Params::FILTER_ANY } }
it 'returns issues that have one or more label' do
create_list(:label_link, 2, label: create(:label, project: project2), target: issue3)

View File

@ -3,6 +3,7 @@
exports[`File row header component adds multiple ellipsises after 40 characters 1`] = `
<div
class="file-row-header bg-white sticky-top p-2 js-file-row-header"
title="app/assets/javascripts/merge_requests/widget/diffs/notes"
>
<span
class="bold"
@ -15,6 +16,7 @@ exports[`File row header component adds multiple ellipsises after 40 characters
exports[`File row header component renders file path 1`] = `
<div
class="file-row-header bg-white sticky-top p-2 js-file-row-header"
title="app/assets"
>
<span
class="bold"
@ -27,6 +29,7 @@ exports[`File row header component renders file path 1`] = `
exports[`File row header component trucates path after 40 characters 1`] = `
<div
class="file-row-header bg-white sticky-top p-2 js-file-row-header"
title="app/assets/javascripts/merge_requests"
>
<span
class="bold"

View File

@ -33,6 +33,35 @@ describe('File row component', () => {
expect(name.text().trim()).toEqual(fileName);
});
it('renders the full path as title', () => {
const filePath = 'path/to/file/with a very long folder name/';
const fileName = 'foo.txt';
createComponent({
file: {
name: fileName,
isHeader: false,
tree: [
{
parentPath: filePath,
},
],
},
level: 1,
});
expect(wrapper.element.title.trim()).toEqual('path/to/file/with a very long folder name/');
});
it('does not render a title attribute if no tree present', () => {
createComponent({
file: file('f1.txt'),
level: 0,
});
expect(wrapper.element.title.trim()).toEqual('');
});
it('emits toggleTreeOpen on click', () => {
const fileName = 't3';
createComponent({

View File

@ -51,11 +51,11 @@ describe Resolvers::IssuesResolver do
end
it 'filters by any assignee' do
expect(resolve_issues(assignee_id: IssuableFinder::FILTER_ANY)).to contain_exactly(issue2)
expect(resolve_issues(assignee_id: IssuableFinder::Params::FILTER_ANY)).to contain_exactly(issue2)
end
it 'filters by no assignee' do
expect(resolve_issues(assignee_id: IssuableFinder::FILTER_NONE)).to contain_exactly(issue1)
expect(resolve_issues(assignee_id: IssuableFinder::Params::FILTER_NONE)).to contain_exactly(issue1)
end
it 'filters by labels' do

View File

@ -1919,6 +1919,15 @@ describe Gitlab::Git::Repository, :seed_helper do
end
end
describe '#replicas', :praefect do
it 'gets the replica checksum through praefect' do
resp = repository.replicas
expect(resp.replicas).to be_empty
expect(resp.primary.checksum).to eq(repository.checksum)
end
end
describe '#clean_stale_repository_files' do
let(:worktree_id) { 'rebase-1' }
let(:gitlab_worktree_path) { File.join(repository_path, 'gitlab-worktree', worktree_id) }

View File

@ -0,0 +1,20 @@
# frozen_string_literal: true
require 'spec_helper'
describe Gitlab::GitalyClient::PraefectInfoService do
let(:project) { create(:project, :repository) }
let(:repository) { project.repository }
let(:gitaly_repository) { repository.gitaly_repository }
let(:client) { described_class.new(repository) }
describe '#repository_replicas', :praefect do
it 'sends an RPC request' do
request = Gitaly::RepositoryReplicasRequest.new(repository: gitaly_repository)
expect_any_instance_of(Gitaly::PraefectInfoService::Stub).to receive(:repository_replicas).with(request, kind_of(Hash))
client.replicas
end
end
end

View File

@ -3223,14 +3223,6 @@ describe MergeRequest do
subject.mark_as_unmergeable
end
it 'notifies conflict, with enabled async mergability check' do
expect(notification_service).to receive(:merge_request_unmergeable).with(subject).once
expect(todo_service).to receive(:merge_request_became_unmergeable).with(subject).once
subject.mark_as_checking
subject.mark_as_unmergeable
end
it 'does not notify whenever merge request is newly unmergeable due to other reasons' do
allow(subject.project.repository).to receive(:can_be_merged?).and_return(true)

View File

@ -475,27 +475,27 @@ describe API::Issues do
end
it 'returns an array of group issues with any label' do
get api(base_url, user), params: { labels: IssuesFinder::FILTER_ANY }
get api(base_url, user), params: { labels: IssuableFinder::Params::FILTER_ANY }
expect_paginated_array_response(group_issue.id)
expect(json_response.first['id']).to eq(group_issue.id)
end
it 'returns an array of group issues with any label with labels param as array' do
get api(base_url, user), params: { labels: [IssuesFinder::FILTER_ANY] }
get api(base_url, user), params: { labels: [IssuableFinder::Params::FILTER_ANY] }
expect_paginated_array_response(group_issue.id)
expect(json_response.first['id']).to eq(group_issue.id)
end
it 'returns an array of group issues with no label' do
get api(base_url, user), params: { labels: IssuesFinder::FILTER_NONE }
get api(base_url, user), params: { labels: IssuableFinder::Params::FILTER_NONE }
expect_paginated_array_response([group_closed_issue.id, group_confidential_issue.id])
end
it 'returns an array of group issues with no label with labels param as array' do
get api(base_url, user), params: { labels: [IssuesFinder::FILTER_NONE] }
get api(base_url, user), params: { labels: [IssuableFinder::Params::FILTER_NONE] }
expect_paginated_array_response([group_closed_issue.id, group_confidential_issue.id])
end

View File

@ -350,25 +350,25 @@ describe API::Issues do
end
it 'returns an array of project issues with any label' do
get api("#{base_url}/issues", user), params: { labels: IssuesFinder::FILTER_ANY }
get api("#{base_url}/issues", user), params: { labels: IssuableFinder::Params::FILTER_ANY }
expect_paginated_array_response(issue.id)
end
it 'returns an array of project issues with any label with labels param as array' do
get api("#{base_url}/issues", user), params: { labels: [IssuesFinder::FILTER_ANY] }
get api("#{base_url}/issues", user), params: { labels: [IssuableFinder::Params::FILTER_ANY] }
expect_paginated_array_response(issue.id)
end
it 'returns an array of project issues with no label' do
get api("#{base_url}/issues", user), params: { labels: IssuesFinder::FILTER_NONE }
get api("#{base_url}/issues", user), params: { labels: IssuableFinder::Params::FILTER_NONE }
expect_paginated_array_response([confidential_issue.id, closed_issue.id])
end
it 'returns an array of project issues with no label with labels param as array' do
get api("#{base_url}/issues", user), params: { labels: [IssuesFinder::FILTER_NONE] }
get api("#{base_url}/issues", user), params: { labels: [IssuableFinder::Params::FILTER_NONE] }
expect_paginated_array_response([confidential_issue.id, closed_issue.id])
end

View File

@ -476,25 +476,25 @@ describe API::Issues do
end
it 'returns an array of issues with any label' do
get api('/issues', user), params: { labels: IssuesFinder::FILTER_ANY }
get api('/issues', user), params: { labels: IssuableFinder::Params::FILTER_ANY }
expect_paginated_array_response(issue.id)
end
it 'returns an array of issues with any label with labels param as array' do
get api('/issues', user), params: { labels: [IssuesFinder::FILTER_ANY] }
get api('/issues', user), params: { labels: [IssuableFinder::Params::FILTER_ANY] }
expect_paginated_array_response(issue.id)
end
it 'returns an array of issues with no label' do
get api('/issues', user), params: { labels: IssuesFinder::FILTER_NONE }
get api('/issues', user), params: { labels: IssuableFinder::Params::FILTER_NONE }
expect_paginated_array_response(closed_issue.id)
end
it 'returns an array of issues with no label with labels param as array' do
get api('/issues', user), params: { labels: [IssuesFinder::FILTER_NONE] }
get api('/issues', user), params: { labels: [IssuableFinder::Params::FILTER_NONE] }
expect_paginated_array_response(closed_issue.id)
end

View File

@ -281,14 +281,14 @@ describe API::MergeRequests do
end
it 'returns an array of merge requests with any label when filtering by any label' do
get api(endpoint_path, user), params: { labels: IssuesFinder::FILTER_ANY }
get api(endpoint_path, user), params: { labels: IssuableFinder::Params::FILTER_ANY }
expect_paginated_array_response([merge_request.id])
expect(json_response.first['id']).to eq(merge_request.id)
end
it 'returns an array of merge requests without a label when filtering by no label' do
get api(endpoint_path, user), params: { labels: IssuesFinder::FILTER_NONE }
get api(endpoint_path, user), params: { labels: IssuableFinder::Params::FILTER_NONE }
expect_response_contain_exactly(
merge_request_merged.id, merge_request_locked.id, merge_request_closed.id

View File

@ -245,9 +245,9 @@ describe Issuable::BulkUpdateService do
end
end
context "when the new assignee ID is #{IssuableFinder::NONE}" do
context "when the new assignee ID is #{IssuableFinder::Params::NONE}" do
it 'unassigns the issues' do
expect { bulk_update(merge_request, assignee_ids: [IssuableFinder::NONE]) }
expect { bulk_update(merge_request, assignee_ids: [IssuableFinder::Params::NONE]) }
.to change { merge_request.reload.assignee_ids }.to([])
end
end
@ -282,9 +282,9 @@ describe Issuable::BulkUpdateService do
end
end
context "when the new assignee ID is #{IssuableFinder::NONE}" do
context "when the new assignee ID is #{IssuableFinder::Params::NONE}" do
it "unassigns the issues" do
expect { bulk_update(issue, assignee_ids: [IssuableFinder::NONE.to_s]) }
expect { bulk_update(issue, assignee_ids: [IssuableFinder::Params::NONE.to_s]) }
.to change { issue.reload.assignees.count }.from(1).to(0)
end
end

View File

@ -781,15 +781,15 @@
eslint-plugin-vue "^6.2.1"
vue-eslint-parser "^7.0.0"
"@gitlab/svgs@^1.115.0":
version "1.115.0"
resolved "https://registry.yarnpkg.com/@gitlab/svgs/-/svgs-1.115.0.tgz#2762ad045d5a2bd728f74fcb4c00caa9bd6dbc22"
integrity sha512-jlmNGqCTpSiPFrNbLaW6GGXNbvIShLdrpeYTtSEz/yFJMClQfPjHc8Zm9bl/PqAM5d/yGQqk8e+rBc4LeAhEfg==
"@gitlab/svgs@^1.116.0":
version "1.116.0"
resolved "https://registry.yarnpkg.com/@gitlab/svgs/-/svgs-1.116.0.tgz#a3c89f950bb256c2e109444c9a85fecdd261292c"
integrity sha512-sZLn3acu0IyrSnZRU1rE3UjxF6FlwvBNfjKQgn0qclxdbe8Ya6cGNVq4aGdCEkHwvb9rFpKbfHBujVgVKNkxSA==
"@gitlab/ui@^10.0.1":
version "10.0.1"
resolved "https://registry.yarnpkg.com/@gitlab/ui/-/ui-10.0.1.tgz#65deee8ded3b8d003dfd74cd93c7eb0549e11b37"
integrity sha512-RMOJjpZjmWJnu0ebfGJsPOn6/ko+HlfHYbBXBImpTIk6Xsr5AaRjT4yCYEoefZ55jK/SJ2nxHytqrMe26wjfDA==
"@gitlab/ui@^10.1.2":
version "10.1.2"
resolved "https://registry.yarnpkg.com/@gitlab/ui/-/ui-10.1.2.tgz#027f86f69ef08fb90cab5c69545adf37e20c6ceb"
integrity sha512-xTvLIHrBqvvvHLVPMGdktBv3hNL7FPGPSFbAC3IURrVa/9FIJbzkIYFGlUIbLu/QX1i0CJN+MLmyHhLtzhKgtA==
dependencies:
"@babel/standalone" "^7.0.0"
"@gitlab/vue-toasted" "^1.3.0"