diff --git a/GITALY_SERVER_VERSION b/GITALY_SERVER_VERSION index 89e51d5525c..ac663669a67 100644 --- a/GITALY_SERVER_VERSION +++ b/GITALY_SERVER_VERSION @@ -1 +1 @@ -0ae7a0079068ca8ad3a074c87e1b39037bdaed80 +87acab96b9eb16381a49f2c08a2eaa9664a2fa75 diff --git a/app/assets/stylesheets/pages/labels.scss b/app/assets/stylesheets/pages/labels.scss index e37b26187e7..80cb6ec89ce 100644 --- a/app/assets/stylesheets/pages/labels.scss +++ b/app/assets/stylesheets/pages/labels.scss @@ -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; } } } diff --git a/app/controllers/search_controller.rb b/app/controllers/search_controller.rb index ae7aab7ab36..b5e221a8894 100644 --- a/app/controllers/search_controller.rb +++ b/app/controllers/search_controller.rb @@ -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 diff --git a/app/helpers/labels_helper.rb b/app/helpers/labels_helper.rb index 3142d7d7782..bfe1728adad 100644 --- a/app/helpers/labels_helper.rb +++ b/app/helpers/labels_helper.rb @@ -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 diff --git a/app/helpers/search_helper.rb b/app/helpers/search_helper.rb index 8fc9f5ca6fd..36b58be60fc 100644 --- a/app/helpers/search_helper.rb +++ b/app/helpers/search_helper.rb @@ -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 diff --git a/app/models/snippet_repository.rb b/app/models/snippet_repository.rb index 2cfb201191d..fa25a6f8441 100644 --- a/app/models/snippet_repository.rb +++ b/app/models/snippet_repository.rb @@ -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) diff --git a/app/services/namespace_settings/update_service.rb b/app/services/namespace_settings/update_service.rb new file mode 100644 index 00000000000..3c9b7b637ac --- /dev/null +++ b/app/services/namespace_settings/update_service.rb @@ -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') diff --git a/app/services/projects/container_repository/cleanup_tags_service.rb b/app/services/projects/container_repository/cleanup_tags_service.rb index 204a54ff23a..31500043544 100644 --- a/app/services/projects/container_repository/cleanup_tags_service.rb +++ b/app/services/projects/container_repository/cleanup_tags_service.rb @@ -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 diff --git a/app/services/projects/container_repository/delete_tags_service.rb b/app/services/projects/container_repository/delete_tags_service.rb index 2dfe86e4d66..9fc3ec0aafb 100644 --- a/app/services/projects/container_repository/delete_tags_service.rb +++ b/app/services/projects/container_repository/delete_tags_service.rb @@ -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? diff --git a/app/services/search/global_service.rb b/app/services/search/global_service.rb index 68700cff715..5f80b07aa59 100644 --- a/app/services/search/global_service.rb +++ b/app/services/search/global_service.rb @@ -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 diff --git a/app/services/search/project_service.rb b/app/services/search/project_service.rb index 9c18f8e947c..b1142b816d0 100644 --- a/app/services/search/project_service.rb +++ b/app/services/search/project_service.rb @@ -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 diff --git a/app/views/groups/labels/index.html.haml b/app/views/groups/labels/index.html.haml index 3299d127222..debbe95d2aa 100644 --- a/app/views/groups/labels/index.html.haml +++ b/app/views/groups/labels/index.html.haml @@ -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') diff --git a/app/views/layouts/header/_default.html.haml b/app/views/layouts/header/_default.html.haml index bc458e65b0e..328c6031b24 100644 --- a/app/views/layouts/header/_default.html.haml +++ b/app/views/layouts/header/_default.html.haml @@ -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 diff --git a/app/views/layouts/header/_new_dropdown.haml b/app/views/layouts/header/_new_dropdown.haml index 0c989242194..2c5cd7e96c7 100644 --- a/app/views/layouts/header/_new_dropdown.haml +++ b/app/views/layouts/header/_new_dropdown.haml @@ -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? diff --git a/app/views/layouts/nav/_dashboard.html.haml b/app/views/layouts/nav/_dashboard.html.haml index a8b4fee47c4..abaadc89a9e 100644 --- a/app/views/layouts/nav/_dashboard.html.haml +++ b/app/views/layouts/nav/_dashboard.html.haml @@ -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) diff --git a/app/views/projects/labels/index.html.haml b/app/views/projects/labels/index.html.haml index 8d8270847a3..2699192adc9 100644 --- a/app/views/projects/labels/index.html.haml +++ b/app/views/projects/labels/index.html.haml @@ -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') diff --git a/app/views/shared/_label.html.haml b/app/views/shared/_label.html.haml index c4b7ef481fd..9fcb71ec2b9 100644 --- a/app/views/shared/_label.html.haml +++ b/app/views/shared/_label.html.haml @@ -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 } } diff --git a/app/views/shared/_label_row.html.haml b/app/views/shared/_label_row.html.haml index 3d2ae772135..f2b257f9776 100644 --- a/app/views/shared/_label_row.html.haml +++ b/app/views/shared/_label_row.html.haml @@ -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') diff --git a/app/views/shared/milestones/_milestone.html.haml b/app/views/shared/milestones/_milestone.html.haml index 27b771b281b..f28aa406784 100644 --- a/app/views/shared/milestones/_milestone.html.haml +++ b/app/views/shared/milestones/_milestone.html.haml @@ -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 diff --git a/changelogs/unreleased/219915-cleanup-policy-not-working.yml b/changelogs/unreleased/219915-cleanup-policy-not-working.yml new file mode 100644 index 00000000000..7dfe0edeb7e --- /dev/null +++ b/changelogs/unreleased/219915-cleanup-policy-not-working.yml @@ -0,0 +1,5 @@ +--- +title: Fix bug to allow container cleanup policies to properly run +merge_request: 43359 +author: +type: fixed diff --git a/changelogs/unreleased/255322-search-sort-issues-and-mrs.yml b/changelogs/unreleased/255322-search-sort-issues-and-mrs.yml new file mode 100644 index 00000000000..6808844dd9b --- /dev/null +++ b/changelogs/unreleased/255322-search-sort-issues-and-mrs.yml @@ -0,0 +1,5 @@ +--- +title: Add sort parameter to Issue and Merge Request scopes +merge_request: 43295 +author: +type: added diff --git a/changelogs/unreleased/258668-update-icons-in-nav.yml b/changelogs/unreleased/258668-update-icons-in-nav.yml new file mode 100644 index 00000000000..ec630bb34a3 --- /dev/null +++ b/changelogs/unreleased/258668-update-icons-in-nav.yml @@ -0,0 +1,5 @@ +--- +title: Update nav icons to chevron-down +merge_request: 43767 +author: +type: changed diff --git a/config/feature_flags/development/users_search.yml b/config/feature_flags/development/users_search.yml deleted file mode 100644 index 932439af448..00000000000 --- a/config/feature_flags/development/users_search.yml +++ /dev/null @@ -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 diff --git a/lib/api/search.rb b/lib/api/search.rb index b9c6a823f4f..8b6569dd57d 100644 --- a/lib/api/search.rb +++ b/lib/api/search.rb @@ -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 diff --git a/lib/gitlab/git_access_snippet.rb b/lib/gitlab/git_access_snippet.rb index ae83e45f2b3..b4ccca9df07 100644 --- a/lib/gitlab/git_access_snippet.rb +++ b/lib/gitlab/git_access_snippet.rb @@ -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') diff --git a/lib/gitlab/search_results.rb b/lib/gitlab/search_results.rb index 3500af51373..1e78464ddf8 100644 --- a/lib/gitlab/search_results.rb +++ b/lib/gitlab/search_results.rb @@ -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 diff --git a/locale/gitlab.pot b/locale/gitlab.pot index 1c4daa7e3c7..ee042a2a960 100644 --- a/locale/gitlab.pot +++ b/locale/gitlab.pot @@ -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 "" diff --git a/spec/helpers/search_helper_spec.rb b/spec/helpers/search_helper_spec.rb index 110741e5dfd..341606635c0 100644 --- a/spec/helpers/search_helper_spec.rb +++ b/spec/helpers/search_helper_spec.rb @@ -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 diff --git a/spec/lib/gitlab/ci/parsers/test/junit_spec.rb b/spec/lib/gitlab/ci/parsers/test/junit_spec.rb index 1f497dea2bf..5a3a9b53da6 100644 --- a/spec/lib/gitlab/ci/parsers/test/junit_spec.rb +++ b/spec/lib/gitlab/ci/parsers/test/junit_spec.rb @@ -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) } diff --git a/spec/lib/gitlab/git_access_snippet_spec.rb b/spec/lib/gitlab/git_access_snippet_spec.rb index 3b8b5fd82c6..362ea3c006e 100644 --- a/spec/lib/gitlab/git_access_snippet_spec.rb +++ b/spec/lib/gitlab/git_access_snippet_spec.rb @@ -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 } diff --git a/spec/lib/gitlab/search_results_spec.rb b/spec/lib/gitlab/search_results_spec.rb index e41bd86a84c..cdb626778a8 100644 --- a/spec/lib/gitlab/search_results_spec.rb +++ b/spec/lib/gitlab/search_results_spec.rb @@ -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 diff --git a/spec/requests/api/search_spec.rb b/spec/requests/api/search_spec.rb index af6731f3015..523f0f72f11 100644 --- a/spec/requests/api/search_spec.rb +++ b/spec/requests/api/search_spec.rb @@ -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 diff --git a/spec/services/namespace_settings/update_service_spec.rb b/spec/services/namespace_settings/update_service_spec.rb new file mode 100644 index 00000000000..2319bdcd4de --- /dev/null +++ b/spec/services/namespace_settings/update_service_spec.rb @@ -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 diff --git a/spec/services/projects/container_repository/cleanup_tags_service_spec.rb b/spec/services/projects/container_repository/cleanup_tags_service_spec.rb index 2c708e75a25..2f2474f2681 100644 --- a/spec/services/projects/container_repository/cleanup_tags_service_spec.rb +++ b/spec/services/projects/container_repository/cleanup_tags_service_spec.rb @@ -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) diff --git a/spec/services/projects/container_repository/delete_tags_service_spec.rb b/spec/services/projects/container_repository/delete_tags_service_spec.rb index 001c76eb4af..c3ae26b1f05 100644 --- a/spec/services/projects/container_repository/delete_tags_service_spec.rb +++ b/spec/services/projects/container_repository/delete_tags_service_spec.rb @@ -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 diff --git a/spec/support/shared_examples/lib/gitlab/search_results_sorted_shared_examples.rb b/spec/support/shared_examples/lib/gitlab/search_results_sorted_shared_examples.rb new file mode 100644 index 00000000000..765279a78fe --- /dev/null +++ b/spec/support/shared_examples/lib/gitlab/search_results_sorted_shared_examples.rb @@ -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