Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
186e045e14
commit
4ed4dc08a8
|
|
@ -1 +1 @@
|
|||
0ae7a0079068ca8ad3a074c87e1b39037bdaed80
|
||||
87acab96b9eb16381a49f2c08a2eaa9664a2fa75
|
||||
|
|
|
|||
|
|
@ -134,11 +134,6 @@
|
|||
}
|
||||
}
|
||||
|
||||
.label-description-wrapper {
|
||||
margin-right: 8px;
|
||||
margin-left: 8px;
|
||||
}
|
||||
|
||||
.prioritized-labels {
|
||||
margin-bottom: 30px;
|
||||
|
||||
|
|
@ -201,10 +196,6 @@
|
|||
}
|
||||
}
|
||||
|
||||
.label-options-toggle {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.label-subscription {
|
||||
vertical-align: middle;
|
||||
|
||||
|
|
@ -276,35 +267,6 @@
|
|||
font-size: $label-font-size;
|
||||
}
|
||||
|
||||
.label-badge-blue {
|
||||
background-color: $theme-blue-100;
|
||||
}
|
||||
|
||||
.label-badge-gray {
|
||||
background-color: $gray-50;
|
||||
}
|
||||
|
||||
.label-links {
|
||||
list-style: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.label-link-item {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.label-description {
|
||||
.description-text {
|
||||
margin-bottom: 10px;
|
||||
|
||||
.admin-labels & {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.label-list-item {
|
||||
.content-list &::before,
|
||||
.content-list &::after {
|
||||
|
|
@ -313,21 +275,12 @@
|
|||
|
||||
.label-name {
|
||||
width: 200px;
|
||||
flex-shrink: 0;
|
||||
|
||||
.gl-label {
|
||||
line-height: $gl-line-height;
|
||||
}
|
||||
}
|
||||
|
||||
.label-description {
|
||||
flex-grow: 1;
|
||||
|
||||
a {
|
||||
color: $blue-600;
|
||||
}
|
||||
}
|
||||
|
||||
.label {
|
||||
padding: 4px $grid-size;
|
||||
font-size: $label-font-size;
|
||||
|
|
@ -382,31 +335,8 @@
|
|||
text-align: left;
|
||||
}
|
||||
|
||||
.label-links {
|
||||
white-space: normal;
|
||||
}
|
||||
|
||||
.label-description {
|
||||
order: 3;
|
||||
width: 100%;
|
||||
|
||||
> .label-description-wrapper {
|
||||
margin-left: 0;
|
||||
margin-right: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 910px) {
|
||||
.priority-badge {
|
||||
display: block;
|
||||
width: 100%;
|
||||
margin-left: 0;
|
||||
margin-top: $gl-padding;
|
||||
|
||||
.label-badge {
|
||||
display: inline-block;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -97,8 +97,6 @@ class SearchController < ApplicationController
|
|||
end
|
||||
|
||||
def eager_load_user_status
|
||||
return if Feature.disabled?(:users_search, default_enabled: true)
|
||||
|
||||
@search_objects = @search_objects.eager_load(:status) # rubocop:disable CodeReuse/ActiveRecord
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -36,11 +36,11 @@ module LabelsHelper
|
|||
# link_to_label(label) { "My Custom Label Text" }
|
||||
#
|
||||
# Returns a String
|
||||
def link_to_label(label, type: :issue, tooltip: true, small: false, &block)
|
||||
def link_to_label(label, type: :issue, tooltip: true, small: false, css_class: nil, &block)
|
||||
link = label.filter_path(type: type)
|
||||
|
||||
if block_given?
|
||||
link_to link, &block
|
||||
link_to link, class: css_class, &block
|
||||
else
|
||||
render_label(label, link: link, tooltip: tooltip, small: small)
|
||||
end
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module SearchHelper
|
||||
SEARCH_PERMITTED_PARAMS = [:search, :scope, :project_id, :group_id, :repository_ref, :snippets, :state, :confidential].freeze
|
||||
SEARCH_PERMITTED_PARAMS = [:search, :scope, :project_id, :group_id, :repository_ref, :snippets, :sort, :state, :confidential].freeze
|
||||
|
||||
def search_autocomplete_opts(term)
|
||||
return unless current_user
|
||||
|
|
@ -305,8 +305,6 @@ module SearchHelper
|
|||
end
|
||||
|
||||
def show_user_search_tab?
|
||||
return false if Feature.disabled?(:users_search, default_enabled: true)
|
||||
|
||||
if @project
|
||||
project_search_tabs?(:members)
|
||||
else
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ class SnippetRepository < ApplicationRecord
|
|||
|
||||
belongs_to :snippet, inverse_of: :snippet_repository
|
||||
|
||||
delegate :repository, to: :snippet
|
||||
delegate :repository, :repository_storage, to: :snippet
|
||||
|
||||
class << self
|
||||
def find_snippet(disk_path)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,25 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module NamespaceSettings
|
||||
class UpdateService
|
||||
include ::Gitlab::Allowable
|
||||
|
||||
attr_reader :current_user, :group, :settings_params
|
||||
|
||||
def initialize(current_user, group, settings)
|
||||
@current_user = current_user
|
||||
@group = group
|
||||
@settings_params = settings
|
||||
end
|
||||
|
||||
def execute
|
||||
if group.namespace_settings
|
||||
group.namespace_settings.attributes = settings_params
|
||||
else
|
||||
group.build_namespace_settings(settings_params)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
NamespaceSettings::UpdateService.prepend_if_ee('EE::NamespaceSettings::UpdateService')
|
||||
|
|
@ -25,7 +25,10 @@ module Projects
|
|||
tag_names = tags.map(&:name)
|
||||
|
||||
Projects::ContainerRepository::DeleteTagsService
|
||||
.new(container_repository.project, current_user, tags: tag_names)
|
||||
.new(container_repository.project,
|
||||
current_user,
|
||||
tags: tag_names,
|
||||
container_expiration_policy: params['container_expiration_policy'])
|
||||
.execute(container_repository)
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -7,7 +7,10 @@ module Projects
|
|||
|
||||
def execute(container_repository)
|
||||
@container_repository = container_repository
|
||||
return error('access denied') unless can?(current_user, :destroy_container_image, project)
|
||||
|
||||
unless params[:container_expiration_policy]
|
||||
return error('access denied') unless can?(current_user, :destroy_container_image, project)
|
||||
end
|
||||
|
||||
@tag_names = params[:tags]
|
||||
return error('not tags specified') if @tag_names.blank?
|
||||
|
|
|
|||
|
|
@ -4,6 +4,8 @@ module Search
|
|||
class GlobalService
|
||||
include Gitlab::Utils::StrongMemoize
|
||||
|
||||
ALLOWED_SCOPES = %w(issues merge_requests milestones users).freeze
|
||||
|
||||
attr_accessor :current_user, :params
|
||||
|
||||
def initialize(user, params)
|
||||
|
|
@ -14,6 +16,7 @@ module Search
|
|||
Gitlab::SearchResults.new(current_user,
|
||||
params[:search],
|
||||
projects,
|
||||
sort: params[:sort],
|
||||
filters: { state: params[:state], confidential: params[:confidential] })
|
||||
end
|
||||
|
||||
|
|
@ -22,11 +25,7 @@ module Search
|
|||
end
|
||||
|
||||
def allowed_scopes
|
||||
strong_memoize(:allowed_scopes) do
|
||||
allowed_scopes = %w[issues merge_requests milestones]
|
||||
allowed_scopes << 'users' if Feature.enabled?(:users_search, default_enabled: true)
|
||||
allowed_scopes
|
||||
end
|
||||
ALLOWED_SCOPES
|
||||
end
|
||||
|
||||
def scope
|
||||
|
|
|
|||
|
|
@ -2,6 +2,10 @@
|
|||
|
||||
module Search
|
||||
class ProjectService
|
||||
include Gitlab::Utils::StrongMemoize
|
||||
|
||||
ALLOWED_SCOPES = %w(notes issues merge_requests milestones wiki_blobs commits users).freeze
|
||||
|
||||
attr_accessor :project, :current_user, :params
|
||||
|
||||
def initialize(project, user, params)
|
||||
|
|
@ -17,12 +21,13 @@ module Search
|
|||
)
|
||||
end
|
||||
|
||||
def scope
|
||||
@scope ||= begin
|
||||
allowed_scopes = %w[notes issues merge_requests milestones wiki_blobs commits]
|
||||
allowed_scopes << 'users' if Feature.enabled?(:users_search, default_enabled: true)
|
||||
def allowed_scopes
|
||||
ALLOWED_SCOPES
|
||||
end
|
||||
|
||||
allowed_scopes.delete(params[:scope]) { 'blobs' }
|
||||
def scope
|
||||
strong_memoize(:scope) do
|
||||
allowed_scopes.include?(params[:scope]) ? params[:scope] : 'blobs'
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -27,5 +27,5 @@
|
|||
= render 'shared/empty_states/labels'
|
||||
|
||||
%template#js-badge-item-template
|
||||
%li.label-link-item.js-priority-badge.inline.gl-ml-3
|
||||
.label-badge.label-badge-blue= _('Prioritized label')
|
||||
%li.js-priority-badge.inline.gl-ml-3
|
||||
.label-badge.gl-bg-blue-50= _('Prioritized label')
|
||||
|
|
|
|||
|
|
@ -73,7 +73,7 @@
|
|||
%span.gl-sr-only
|
||||
= s_('Nav|Help')
|
||||
= sprite_icon('question')
|
||||
= sprite_icon('angle-down', css_class: 'caret-down')
|
||||
= sprite_icon('chevron-down', css_class: 'caret-down')
|
||||
.dropdown-menu.dropdown-menu-right
|
||||
= render 'layouts/header/help_dropdown'
|
||||
- if header_link?(:user_dropdown)
|
||||
|
|
@ -81,7 +81,7 @@
|
|||
= link_to current_user, class: user_dropdown_class, data: { toggle: "dropdown" } do
|
||||
= image_tag avatar_icon_for_user(current_user, 23), width: 23, height: 23, class: "header-user-avatar qa-user-avatar", alt: current_user.name
|
||||
= render_if_exists 'layouts/header/user_notification_dot', project: project, namespace: group
|
||||
= sprite_icon('angle-down', css_class: 'caret-down')
|
||||
= sprite_icon('chevron-down', css_class: 'caret-down')
|
||||
.dropdown-menu.dropdown-menu-right
|
||||
= render 'layouts/header/current_user_dropdown'
|
||||
- if has_impersonation_link
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
%li.header-new.dropdown{ data: { track_label: "new_dropdown", track_event: "click_dropdown", track_value: "" } }
|
||||
= link_to new_project_path, class: "header-new-dropdown-toggle has-tooltip qa-new-menu-toggle", id: "js-onboarding-new-project-link", title: _("New..."), ref: 'tooltip', aria: { label: _("New...") }, data: { toggle: 'dropdown', placement: 'bottom', container: 'body', display: 'static' } do
|
||||
= sprite_icon('plus-square')
|
||||
= sprite_icon('angle-down', css_class: 'caret-down')
|
||||
= sprite_icon('chevron-down', css_class: 'caret-down')
|
||||
.dropdown-menu.dropdown-menu-right
|
||||
%ul
|
||||
- if @group&.persisted?
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
= nav_link(path: ['root#index', 'projects#trending', 'projects#starred', 'dashboard/projects#index'], html_options: { id: 'nav-projects-dropdown', class: "home dropdown header-projects qa-projects-dropdown", data: { track_label: "projects_dropdown", track_event: "click_dropdown", track_value: "" } }) do
|
||||
%button{ type: 'button', data: { toggle: "dropdown" } }
|
||||
= _('Projects')
|
||||
= sprite_icon('angle-down', css_class: 'caret-down')
|
||||
= sprite_icon('chevron-down', css_class: 'caret-down')
|
||||
.dropdown-menu.frequent-items-dropdown-menu
|
||||
= render "layouts/nav/projects_dropdown/show"
|
||||
|
||||
|
|
@ -13,7 +13,7 @@
|
|||
= nav_link(controller: ['dashboard/groups', 'explore/groups'], html_options: { id: 'nav-groups-dropdown', class: "d-none d-md-block home dropdown header-groups qa-groups-dropdown", data: { track_label: "groups_dropdown", track_event: "click_dropdown", track_value: "" } }) do
|
||||
%button{ type: 'button', data: { toggle: "dropdown" } }
|
||||
= _('Groups')
|
||||
= sprite_icon('angle-down', css_class: 'caret-down')
|
||||
= sprite_icon('chevron-down', css_class: 'caret-down')
|
||||
.dropdown-menu.frequent-items-dropdown-menu
|
||||
= render "layouts/nav/groups_dropdown/show"
|
||||
|
||||
|
|
@ -21,7 +21,7 @@
|
|||
%li.header-more.dropdown{ **tracking_attrs('main_navigation', 'click_more_link', 'navigation') }
|
||||
%a{ href: "#", data: { toggle: "dropdown", qa_selector: 'more_dropdown' } }
|
||||
= _('More')
|
||||
= sprite_icon('angle-down', css_class: 'caret-down')
|
||||
= sprite_icon('chevron-down', css_class: 'caret-down')
|
||||
.dropdown-menu
|
||||
%ul
|
||||
- if dashboard_nav_link?(:groups)
|
||||
|
|
|
|||
|
|
@ -52,5 +52,5 @@
|
|||
= render 'shared/empty_states/labels'
|
||||
|
||||
%template#js-badge-item-template
|
||||
%li.label-link-item.js-priority-badge.inline.gl-ml-3
|
||||
.label-badge.label-badge-blue= _('Prioritized label')
|
||||
%li.js-priority-badge.inline.gl-ml-3
|
||||
.label-badge.gl-bg-blue-50= _('Prioritized label')
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@
|
|||
%ul.label-actions-list
|
||||
- if @project
|
||||
%li.inline
|
||||
.label-badge.label-badge-gray= label.model_name.human.capitalize
|
||||
.label-badge.gl-bg-gray-50= label.model_name.human.capitalize
|
||||
- if can?(current_user, :admin_label, @project)
|
||||
%li.inline.js-toggle-priority{ data: { url: remove_priority_project_label_path(@project, label),
|
||||
dom_id: dom_id(label), type: label.type } }
|
||||
|
|
|
|||
|
|
@ -3,23 +3,22 @@
|
|||
- show_label_issues_link = subject_or_group_defined && show_label_issuables_link?(label, :issues)
|
||||
- show_label_merge_requests_link = subject_or_group_defined && show_label_issuables_link?(label, :merge_requests)
|
||||
|
||||
.label-name
|
||||
.label-name.gl-flex-shrink-0.gl-mr-3
|
||||
= render_label(label, tooltip: false)
|
||||
.label-description
|
||||
.label-description-wrapper
|
||||
- if label.description.present?
|
||||
.description-text
|
||||
= markdown_field(label, :description)
|
||||
%ul.label-links
|
||||
- if show_label_issues_link
|
||||
%li.label-link-item.inline
|
||||
= link_to_label(label) { _('Issues') }
|
||||
- if show_label_merge_requests_link
|
||||
·
|
||||
%li.label-link-item.inline
|
||||
= link_to_label(label, type: :merge_request) { _('Merge requests') }
|
||||
- if force_priority
|
||||
·
|
||||
%li.label-link-item.priority-badge.js-priority-badge.inline.gl-ml-3
|
||||
.label-badge.label-badge-blue= _('Prioritized label')
|
||||
= render_if_exists 'shared/label_row_epics_link', label: label
|
||||
.label-description.gl-flex-grow-1.gl-mr-3.gl-w-full
|
||||
- if label.description.present?
|
||||
.description-text.gl-mb-3
|
||||
= markdown_field(label, :description)
|
||||
%ul.label-links.gl-m-0.gl-p-0.gl-white-space-nowrap
|
||||
- if show_label_issues_link
|
||||
%li.inline.gl-text-blue-600
|
||||
= link_to_label(label, css_class: 'gl-text-blue-600!') { _('Issues') }
|
||||
- if show_label_merge_requests_link
|
||||
·
|
||||
%li.inline.gl-text-blue-600
|
||||
= link_to_label(label, type: :merge_request, css_class: 'gl-text-blue-600!') { _('Merge requests') }
|
||||
= render_if_exists 'shared/label_row_epics_link', label: label
|
||||
- if force_priority
|
||||
·
|
||||
%li.js-priority-badge.inline.gl-ml-3
|
||||
.label-badge.gl-bg-blue-50= _('Prioritized label')
|
||||
|
|
|
|||
|
|
@ -29,10 +29,10 @@
|
|||
%div
|
||||
= render('shared/milestone_expired', milestone: milestone)
|
||||
- if milestone.group_milestone?
|
||||
.label-badge.label-badge-blue.d-inline-block
|
||||
.label-badge.gl-bg-blue-50.d-inline-block
|
||||
= milestone.group.full_name
|
||||
- if milestone.project_milestone?
|
||||
.label-badge.label-badge-gray.d-inline-block
|
||||
.label-badge.gl-bg-gray-50.d-inline-block
|
||||
= milestone.project.full_name
|
||||
|
||||
.col-sm-4.milestone-progress
|
||||
|
|
|
|||
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Fix bug to allow container cleanup policies to properly run
|
||||
merge_request: 43359
|
||||
author:
|
||||
type: fixed
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Add sort parameter to Issue and Merge Request scopes
|
||||
merge_request: 43295
|
||||
author:
|
||||
type: added
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Update nav icons to chevron-down
|
||||
merge_request: 43767
|
||||
author:
|
||||
type: changed
|
||||
|
|
@ -1,7 +0,0 @@
|
|||
---
|
||||
name: users_search
|
||||
introduced_by_url:
|
||||
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/255282
|
||||
group: group::global search
|
||||
type: development
|
||||
default_enabled: true
|
||||
|
|
@ -62,12 +62,6 @@ module API
|
|||
# Defining this method here as a noop allows us to easily extend it in
|
||||
# EE, without having to modify this file directly.
|
||||
end
|
||||
|
||||
def check_users_search_allowed!
|
||||
if params[:scope].to_sym == :users && Feature.disabled?(:users_search, default_enabled: true)
|
||||
render_api_error!({ error: _("Scope not supported with disabled 'users_search' feature!") }, 400)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
resource :search do
|
||||
|
|
@ -85,7 +79,6 @@ module API
|
|||
end
|
||||
get do
|
||||
verify_search_scope!(resource: nil)
|
||||
check_users_search_allowed!
|
||||
|
||||
present search, with: entity
|
||||
end
|
||||
|
|
@ -107,7 +100,6 @@ module API
|
|||
end
|
||||
get ':id/(-/)search' do
|
||||
verify_search_scope!(resource: user_group)
|
||||
check_users_search_allowed!
|
||||
|
||||
present search(group_id: user_group.id), with: entity
|
||||
end
|
||||
|
|
@ -129,8 +121,6 @@ module API
|
|||
use :pagination
|
||||
end
|
||||
get ':id/(-/)search' do
|
||||
check_users_search_allowed!
|
||||
|
||||
present search({ project_id: user_project.id, repository_ref: params[:ref] }), with: entity
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -60,13 +60,17 @@ module Gitlab
|
|||
def check_valid_actor!
|
||||
# TODO: Investigate if expanding actor/authentication types are needed.
|
||||
# https://gitlab.com/gitlab-org/gitlab/issues/202190
|
||||
if actor && !actor.is_a?(User) && !actor.instance_of?(Key)
|
||||
if actor && !allowed_actor?
|
||||
raise ForbiddenError, ERROR_MESSAGES[:authentication_mechanism]
|
||||
end
|
||||
|
||||
super
|
||||
end
|
||||
|
||||
def allowed_actor?
|
||||
actor.is_a?(User) || actor.instance_of?(Key)
|
||||
end
|
||||
|
||||
def project_snippet?
|
||||
snippet.is_a?(ProjectSnippet)
|
||||
end
|
||||
|
|
@ -138,3 +142,5 @@ module Gitlab
|
|||
end
|
||||
end
|
||||
end
|
||||
|
||||
Gitlab::GitAccessSnippet.prepend_if_ee('EE::Gitlab::GitAccessSnippet')
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ module Gitlab
|
|||
DEFAULT_PAGE = 1
|
||||
DEFAULT_PER_PAGE = 20
|
||||
|
||||
attr_reader :current_user, :query, :filters
|
||||
attr_reader :current_user, :query, :sort, :filters
|
||||
|
||||
# Limit search results by passed projects
|
||||
# It allows us to search only for projects user has access to
|
||||
|
|
@ -19,11 +19,12 @@ module Gitlab
|
|||
# query
|
||||
attr_reader :default_project_filter
|
||||
|
||||
def initialize(current_user, query, limit_projects = nil, default_project_filter: false, filters: {})
|
||||
def initialize(current_user, query, limit_projects = nil, sort: nil, default_project_filter: false, filters: {})
|
||||
@current_user = current_user
|
||||
@query = query
|
||||
@limit_projects = limit_projects || Project.all
|
||||
@default_project_filter = default_project_filter
|
||||
@sort = sort
|
||||
@filters = filters
|
||||
end
|
||||
|
||||
|
|
@ -124,6 +125,19 @@ module Gitlab
|
|||
end
|
||||
end
|
||||
|
||||
# rubocop: disable CodeReuse/ActiveRecord
|
||||
def apply_sort(scope)
|
||||
case sort
|
||||
when 'oldest'
|
||||
scope.reorder('created_at ASC')
|
||||
when 'newest'
|
||||
scope.reorder('created_at DESC')
|
||||
else
|
||||
scope
|
||||
end
|
||||
end
|
||||
# rubocop: enable CodeReuse/ActiveRecord
|
||||
|
||||
def projects
|
||||
limit_projects.search(query)
|
||||
end
|
||||
|
|
@ -135,7 +149,7 @@ module Gitlab
|
|||
issues = issues.where(project_id: project_ids_relation) # rubocop: disable CodeReuse/ActiveRecord
|
||||
end
|
||||
|
||||
issues
|
||||
apply_sort(issues)
|
||||
end
|
||||
|
||||
# rubocop: disable CodeReuse/ActiveRecord
|
||||
|
|
@ -155,7 +169,7 @@ module Gitlab
|
|||
merge_requests = merge_requests.in_projects(project_ids_relation)
|
||||
end
|
||||
|
||||
merge_requests
|
||||
apply_sort(merge_requests)
|
||||
end
|
||||
|
||||
def default_scope
|
||||
|
|
|
|||
|
|
@ -4506,9 +4506,6 @@ msgstr ""
|
|||
msgid "Can't load mermaid module: %{err}"
|
||||
msgstr ""
|
||||
|
||||
msgid "Can't remove group members without group managed account"
|
||||
msgstr ""
|
||||
|
||||
msgid "Can't scan the code?"
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -12649,9 +12646,6 @@ msgstr ""
|
|||
msgid "GroupSAML|Valid SAML Response"
|
||||
msgstr ""
|
||||
|
||||
msgid "GroupSAML|With group managed accounts enabled, all the users without a group managed account will be excluded from the group."
|
||||
msgstr ""
|
||||
|
||||
msgid "GroupSAML|With prohibit outer forks flag enabled group members will be able to fork project only inside your group."
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -22307,9 +22301,6 @@ msgstr ""
|
|||
msgid "Scope"
|
||||
msgstr ""
|
||||
|
||||
msgid "Scope not supported with disabled 'users_search' feature!"
|
||||
msgstr ""
|
||||
|
||||
msgid "Scoped issue boards"
|
||||
msgstr ""
|
||||
|
||||
|
|
|
|||
|
|
@ -357,14 +357,6 @@ RSpec.describe SearchHelper do
|
|||
describe '#show_user_search_tab?' do
|
||||
subject { show_user_search_tab? }
|
||||
|
||||
context 'when users_search feature is disabled' do
|
||||
before do
|
||||
stub_feature_flags(users_search: false)
|
||||
end
|
||||
|
||||
it { is_expected.to eq(false) }
|
||||
end
|
||||
|
||||
context 'when project search' do
|
||||
before do
|
||||
@project = :some_project
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ require 'fast_spec_helper'
|
|||
|
||||
RSpec.describe Gitlab::Ci::Parsers::Test::Junit do
|
||||
describe '#parse!' do
|
||||
subject { described_class.new.parse!(junit, test_suite, args) }
|
||||
subject { described_class.new.parse!(junit, test_suite, **args) }
|
||||
|
||||
let(:test_suite) { Gitlab::Ci::Reports::TestSuite.new('rspec') }
|
||||
let(:test_cases) { flattened_test_cases(test_suite) }
|
||||
|
|
|
|||
|
|
@ -232,29 +232,6 @@ RSpec.describe Gitlab::GitAccessSnippet do
|
|||
end
|
||||
end
|
||||
|
||||
context 'when geo is enabled', if: Gitlab.ee? do
|
||||
let(:user) { snippet.author }
|
||||
let!(:primary_node) { FactoryBot.create(:geo_node, :primary) }
|
||||
|
||||
before do
|
||||
allow(::Gitlab::Database).to receive(:read_only?).and_return(true)
|
||||
allow(::Gitlab::Geo).to receive(:secondary_with_primary?).and_return(true)
|
||||
end
|
||||
|
||||
# Without override, push access would return Gitlab::GitAccessResult::CustomAction
|
||||
it 'skips geo for snippet' do
|
||||
expect { push_access_check }.to raise_forbidden(/You can't push code to a read-only GitLab instance/)
|
||||
end
|
||||
|
||||
context 'when user is migration bot' do
|
||||
let(:user) { migration_bot }
|
||||
|
||||
it 'skips geo for snippet' do
|
||||
expect { push_access_check }.to raise_forbidden(/You can't push code to a read-only GitLab instance/)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'when changes are specific' do
|
||||
let(:changes) { "2d1db523e11e777e49377cfb22d368deec3f0793 ddd0f15ae83993f5cb66a927a28673882e99100b master" }
|
||||
let(:user) { snippet.author }
|
||||
|
|
|
|||
|
|
@ -11,9 +11,11 @@ RSpec.describe Gitlab::SearchResults do
|
|||
let_it_be(:issue) { create(:issue, project: project, title: 'foo') }
|
||||
let_it_be(:milestone) { create(:milestone, project: project, title: 'foo') }
|
||||
let(:merge_request) { create(:merge_request, source_project: project, title: 'foo') }
|
||||
let(:query) { 'foo' }
|
||||
let(:filters) { {} }
|
||||
let(:sort) { nil }
|
||||
|
||||
subject(:results) { described_class.new(user, 'foo', Project.order(:id), filters: filters) }
|
||||
subject(:results) { described_class.new(user, query, Project.order(:id), sort: sort, filters: filters) }
|
||||
|
||||
context 'as a user with access' do
|
||||
before do
|
||||
|
|
@ -137,10 +139,12 @@ RSpec.describe Gitlab::SearchResults do
|
|||
end
|
||||
|
||||
describe '#merge_requests' do
|
||||
let(:scope) { 'merge_requests' }
|
||||
|
||||
it 'includes project filter by default' do
|
||||
expect(results).to receive(:project_ids_relation).and_call_original
|
||||
|
||||
results.objects('merge_requests')
|
||||
results.objects(scope)
|
||||
end
|
||||
|
||||
it 'skips project filter if default project context is used' do
|
||||
|
|
@ -148,24 +152,34 @@ RSpec.describe Gitlab::SearchResults do
|
|||
|
||||
expect(results).not_to receive(:project_ids_relation)
|
||||
|
||||
results.objects('merge_requests')
|
||||
results.objects(scope)
|
||||
end
|
||||
|
||||
context 'filtering' do
|
||||
let!(:opened_result) { create(:merge_request, :opened, source_project: project, title: 'foo opened') }
|
||||
let!(:closed_result) { create(:merge_request, :closed, source_project: project, title: 'foo closed') }
|
||||
let(:scope) { 'merge_requests' }
|
||||
let(:query) { 'foo' }
|
||||
|
||||
include_examples 'search results filtered by state'
|
||||
end
|
||||
|
||||
context 'ordering' do
|
||||
let(:query) { 'sorted' }
|
||||
let!(:old_result) { create(:merge_request, :opened, source_project: project, source_branch: 'old-1', title: 'sorted old', created_at: 1.month.ago) }
|
||||
let!(:new_result) { create(:merge_request, :opened, source_project: project, source_branch: 'new-1', title: 'sorted recent', created_at: 1.day.ago) }
|
||||
let!(:very_old_result) { create(:merge_request, :opened, source_project: project, source_branch: 'very-old-1', title: 'sorted very old', created_at: 1.year.ago) }
|
||||
|
||||
include_examples 'search results sorted'
|
||||
end
|
||||
end
|
||||
|
||||
describe '#issues' do
|
||||
let(:scope) { 'issues' }
|
||||
|
||||
it 'includes project filter by default' do
|
||||
expect(results).to receive(:project_ids_relation).and_call_original
|
||||
|
||||
results.objects('issues')
|
||||
results.objects(scope)
|
||||
end
|
||||
|
||||
it 'skips project filter if default project context is used' do
|
||||
|
|
@ -173,12 +187,10 @@ RSpec.describe Gitlab::SearchResults do
|
|||
|
||||
expect(results).not_to receive(:project_ids_relation)
|
||||
|
||||
results.objects('issues')
|
||||
results.objects(scope)
|
||||
end
|
||||
|
||||
context 'filtering' do
|
||||
let(:scope) { 'issues' }
|
||||
|
||||
let_it_be(:closed_result) { create(:issue, :closed, project: project, title: 'foo closed') }
|
||||
let_it_be(:opened_result) { create(:issue, :opened, project: project, title: 'foo open') }
|
||||
let_it_be(:confidential_result) { create(:issue, :confidential, project: project, title: 'foo confidential') }
|
||||
|
|
@ -186,6 +198,15 @@ RSpec.describe Gitlab::SearchResults do
|
|||
include_examples 'search results filtered by state'
|
||||
include_examples 'search results filtered by confidential'
|
||||
end
|
||||
|
||||
context 'ordering' do
|
||||
let(:query) { 'sorted' }
|
||||
let!(:old_result) { create(:issue, project: project, title: 'sorted old', created_at: 1.month.ago) }
|
||||
let!(:new_result) { create(:issue, project: project, title: 'sorted recent', created_at: 1.day.ago) }
|
||||
let!(:very_old_result) { create(:issue, project: project, title: 'sorted very old', created_at: 1.year.ago) }
|
||||
|
||||
include_examples 'search results sorted'
|
||||
end
|
||||
end
|
||||
|
||||
describe '#users' do
|
||||
|
|
|
|||
|
|
@ -231,18 +231,6 @@ RSpec.describe API::Search do
|
|||
it_behaves_like 'pagination', scope: :users
|
||||
|
||||
it_behaves_like 'ping counters', scope: :users
|
||||
|
||||
context 'when users search feature is disabled' do
|
||||
before do
|
||||
stub_feature_flags(users_search: false)
|
||||
|
||||
get api(endpoint, user), params: { scope: 'users', search: 'billy' }
|
||||
end
|
||||
|
||||
it 'returns 400 error' do
|
||||
expect(response).to have_gitlab_http_status(:bad_request)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'for snippet_titles scope' do
|
||||
|
|
@ -416,18 +404,6 @@ RSpec.describe API::Search do
|
|||
|
||||
include_examples 'pagination', scope: :users
|
||||
end
|
||||
|
||||
context 'when users search feature is disabled' do
|
||||
before do
|
||||
stub_feature_flags(users_search: false)
|
||||
|
||||
get api(endpoint, user), params: { scope: 'users', search: 'billy' }
|
||||
end
|
||||
|
||||
it 'returns 400 error' do
|
||||
expect(response).to have_gitlab_http_status(:bad_request)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'for users scope with group path as id' do
|
||||
|
|
@ -589,18 +565,6 @@ RSpec.describe API::Search do
|
|||
|
||||
include_examples 'pagination', scope: :users
|
||||
end
|
||||
|
||||
context 'when users search feature is disabled' do
|
||||
before do
|
||||
stub_feature_flags(users_search: false)
|
||||
|
||||
get api(endpoint, user), params: { scope: 'users', search: 'billy' }
|
||||
end
|
||||
|
||||
it 'returns 400 error' do
|
||||
expect(response).to have_gitlab_http_status(:bad_request)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'for notes scope' do
|
||||
|
|
|
|||
|
|
@ -0,0 +1,35 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe NamespaceSettings::UpdateService do
|
||||
let(:user) { create(:user) }
|
||||
let(:group) { create(:group) }
|
||||
let(:settings) { {} }
|
||||
|
||||
subject(:service) { described_class.new(user, group, settings) }
|
||||
|
||||
describe "#execute" do
|
||||
context "group has no namespace_settings" do
|
||||
it "builds out a new namespace_settings record" do
|
||||
expect do
|
||||
service.execute
|
||||
end.to change { NamespaceSetting.count }.by(1)
|
||||
end
|
||||
end
|
||||
|
||||
context "group has a namespace_settings" do
|
||||
before do
|
||||
create(:namespace_settings, namespace: group)
|
||||
|
||||
service.execute
|
||||
end
|
||||
|
||||
it "doesn't create a new namespace_setting record" do
|
||||
expect do
|
||||
service.execute
|
||||
end.not_to change { NamespaceSetting.count }
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -245,7 +245,7 @@ RSpec.describe Projects::ContainerRepository::CleanupTagsService do
|
|||
end
|
||||
|
||||
it 'succeeds without a user' do
|
||||
expect_delete(%w(Bb Ba C))
|
||||
expect_delete(%w(Bb Ba C), container_expiration_policy: true)
|
||||
|
||||
is_expected.to include(status: :success, deleted: %w(Bb Ba C))
|
||||
end
|
||||
|
|
@ -287,10 +287,10 @@ RSpec.describe Projects::ContainerRepository::CleanupTagsService do
|
|||
end
|
||||
end
|
||||
|
||||
def expect_delete(tags)
|
||||
def expect_delete(tags, container_expiration_policy: nil)
|
||||
expect(Projects::ContainerRepository::DeleteTagsService)
|
||||
.to receive(:new)
|
||||
.with(repository.project, user, tags: tags)
|
||||
.with(repository.project, user, tags: tags, container_expiration_policy: container_expiration_policy)
|
||||
.and_call_original
|
||||
|
||||
expect_any_instance_of(Projects::ContainerRepository::DeleteTagsService)
|
||||
|
|
|
|||
|
|
@ -85,6 +85,41 @@ RSpec.describe Projects::ContainerRepository::DeleteTagsService do
|
|||
end
|
||||
end
|
||||
|
||||
RSpec.shared_examples 'supporting fast delete' do
|
||||
context 'when the registry supports fast delete' do
|
||||
before do
|
||||
allow(repository.client).to receive(:supports_tag_delete?).and_return(true)
|
||||
end
|
||||
|
||||
it_behaves_like 'calling the correct delete tags service', ::Projects::ContainerRepository::Gitlab::DeleteTagsService
|
||||
|
||||
it_behaves_like 'handling invalid params'
|
||||
|
||||
context 'with the real service' do
|
||||
before do
|
||||
stub_delete_reference_requests(tags)
|
||||
expect_delete_tag_by_names(tags)
|
||||
end
|
||||
|
||||
it { is_expected.to include(status: :success) }
|
||||
|
||||
it_behaves_like 'logging a success response'
|
||||
end
|
||||
|
||||
context 'with a timeout error' do
|
||||
before do
|
||||
expect_next_instance_of(::Projects::ContainerRepository::Gitlab::DeleteTagsService) do |delete_service|
|
||||
expect(delete_service).to receive(:delete_tags).and_raise(::Projects::ContainerRepository::Gitlab::DeleteTagsService::TimeoutError)
|
||||
end
|
||||
end
|
||||
|
||||
it { is_expected.to include(status: :error, message: 'timeout while deleting tags') }
|
||||
|
||||
it_behaves_like 'logging an error response', message: 'timeout while deleting tags'
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#execute' do
|
||||
let(:tags) { %w[A Ba] }
|
||||
|
||||
|
|
@ -103,38 +138,7 @@ RSpec.describe Projects::ContainerRepository::DeleteTagsService do
|
|||
project.add_developer(user)
|
||||
end
|
||||
|
||||
context 'when the registry supports fast delete' do
|
||||
before do
|
||||
allow(repository.client).to receive(:supports_tag_delete?).and_return(true)
|
||||
end
|
||||
|
||||
it_behaves_like 'calling the correct delete tags service', ::Projects::ContainerRepository::Gitlab::DeleteTagsService
|
||||
|
||||
it_behaves_like 'handling invalid params'
|
||||
|
||||
context 'with the real service' do
|
||||
before do
|
||||
stub_delete_reference_requests(tags)
|
||||
expect_delete_tag_by_names(tags)
|
||||
end
|
||||
|
||||
it { is_expected.to include(status: :success) }
|
||||
|
||||
it_behaves_like 'logging a success response'
|
||||
end
|
||||
|
||||
context 'with a timeout error' do
|
||||
before do
|
||||
expect_next_instance_of(::Projects::ContainerRepository::Gitlab::DeleteTagsService) do |delete_service|
|
||||
expect(delete_service).to receive(:delete_tags).and_raise(::Projects::ContainerRepository::Gitlab::DeleteTagsService::TimeoutError)
|
||||
end
|
||||
end
|
||||
|
||||
it { is_expected.to include(status: :error, message: 'timeout while deleting tags') }
|
||||
|
||||
it_behaves_like 'logging an error response', message: 'timeout while deleting tags'
|
||||
end
|
||||
end
|
||||
it_behaves_like 'supporting fast delete'
|
||||
|
||||
context 'when the registry does not support fast delete' do
|
||||
before do
|
||||
|
|
@ -146,5 +150,19 @@ RSpec.describe Projects::ContainerRepository::DeleteTagsService do
|
|||
it_behaves_like 'handling invalid params'
|
||||
end
|
||||
end
|
||||
|
||||
context 'without user' do
|
||||
let_it_be(:user) { nil }
|
||||
|
||||
context 'when not run by a cleanup policy' do
|
||||
it { is_expected.to include(status: :error) }
|
||||
end
|
||||
|
||||
context 'when run by a cleanup policy' do
|
||||
let(:params) { { tags: tags, container_expiration_policy: true } }
|
||||
|
||||
it_behaves_like 'supporting fast delete'
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -0,0 +1,19 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
RSpec.shared_examples 'search results sorted' do
|
||||
context 'sort: newest' do
|
||||
let(:sort) { 'newest' }
|
||||
|
||||
it 'sorts results by created_at' do
|
||||
expect(results.objects(scope).map(&:id)).to eq([new_result.id, old_result.id, very_old_result.id])
|
||||
end
|
||||
end
|
||||
|
||||
context 'sort: oldest' do
|
||||
let(:sort) { 'oldest' }
|
||||
|
||||
it 'sorts results by created_at' do
|
||||
expect(results.objects(scope).map(&:id)).to eq([very_old_result.id, old_result.id, new_result.id])
|
||||
end
|
||||
end
|
||||
end
|
||||
Loading…
Reference in New Issue