diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2023-03-10 09:15:47 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2023-03-10 09:15:47 +0300 |
commit | a46f64e06d98c745c4e7ceee705022273924cb78 (patch) | |
tree | a0f4336e110f2f24cc276836e88d1e34dab082e1 | |
parent | d5954a6879517e10e80ffe9b2a200730a748e3ac (diff) |
Add latest changes from gitlab-org/gitlab@master
30 files changed, 115 insertions, 326 deletions
diff --git a/.gitlab/ci/as-if-jh.gitlab-ci.yml b/.gitlab/ci/as-if-jh.gitlab-ci.yml index 73247984589..6bd46bee770 100644 --- a/.gitlab/ci/as-if-jh.gitlab-ci.yml +++ b/.gitlab/ci/as-if-jh.gitlab-ci.yml @@ -35,11 +35,12 @@ prepare-as-if-jh-branch: - .shared-as-if-jh - .as-if-jh:rules:prepare-as-if-jh stage: prepare - variables: - GIT_DEPTH: "0" # clone the full history so we can push needs: - add-jh-files script: + # Fetch for the history of the branch so it does not cause the following error: + # ! [remote rejected] ref -> ref (shallow update not allowed) + - git fetch --unshallow --filter=tree:0 origin "${CI_COMMIT_SHA}" - git checkout -b "${AS_IF_JH_BRANCH}" - git add ${JH_FILES_TO_COMMIT} - git commit -m 'Add JH files' # TODO: Mark which SHA we add diff --git a/app/assets/stylesheets/framework/tables.scss b/app/assets/stylesheets/framework/tables.scss index 8b2a494527b..a288701595e 100644 --- a/app/assets/stylesheets/framework/tables.scss +++ b/app/assets/stylesheets/framework/tables.scss @@ -41,7 +41,7 @@ table { } th { - @include gl-bg-gray-50; + @include gl-bg-gray-10; border-bottom: 0; &.wide { diff --git a/app/assets/stylesheets/framework/wells.scss b/app/assets/stylesheets/framework/wells.scss index cb9c623c8fc..1434c16b68f 100644 --- a/app/assets/stylesheets/framework/wells.scss +++ b/app/assets/stylesheets/framework/wells.scss @@ -1,7 +1,7 @@ .info-well { - background: $gray-light; + background: $gray-10; color: $gl-text-color; - border: 1px solid $border-color; + border: 1px solid $gray-100; border-radius: $border-radius-default; .card.card-body-segment { diff --git a/app/assets/stylesheets/page_bundles/tree.scss b/app/assets/stylesheets/page_bundles/tree.scss index 50d9684c7d2..4fa3f4f63f1 100644 --- a/app/assets/stylesheets/page_bundles/tree.scss +++ b/app/assets/stylesheets/page_bundles/tree.scss @@ -103,7 +103,6 @@ tr { border-bottom: 1px solid var(--gray-50, $gray-50); - border-top: 1px solid var(--gray-50, $gray-50); &:last-of-type { border-bottom-color: transparent; diff --git a/app/controllers/concerns/renders_projects_list.rb b/app/controllers/concerns/renders_projects_list.rb index 05bd9972ee7..739b2be3fe9 100644 --- a/app/controllers/concerns/renders_projects_list.rb +++ b/app/controllers/concerns/renders_projects_list.rb @@ -8,6 +8,7 @@ module RendersProjectsList # once when the entities are rendered projects.each(&:forks_count) projects.each(&:open_issues_count) + projects.each(&:open_merge_requests_count) projects end diff --git a/app/helpers/sidebars_helper.rb b/app/helpers/sidebars_helper.rb index 84d552c15ec..b4657fce467 100644 --- a/app/helpers/sidebars_helper.rb +++ b/app/helpers/sidebars_helper.rb @@ -34,6 +34,12 @@ module SidebarsHelper Sidebars::Groups::Context.new(**context_data, **args) end + def your_work_sidebar_context(user, **args) + context_data = your_work_context_data(user) + + Sidebars::Context.new(**context_data, **args) + end + def super_sidebar_context(user, group:, project:, panel:) { current_menu_items: panel.super_sidebar_menu_items, @@ -94,7 +100,8 @@ module SidebarsHelper context = group_sidebar_context(group, user, **context_adds) Sidebars::Groups::SuperSidebarPanel.new(context) else - Sidebars::YourWork::Panel.new(Sidebars::Context.new(current_user: user, container: nil, **context_adds)) + context = your_work_sidebar_context(user, **context_adds) + Sidebars::YourWork::Panel.new(context) end end @@ -203,6 +210,14 @@ module SidebarsHelper container: group } end + + def your_work_context_data(user) + { + current_user: user, + container: user, + show_security_dashboard: false + } + end end SidebarsHelper.prepend_mod_with('SidebarsHelper') diff --git a/app/models/members/member_role.rb b/app/models/members/member_role.rb deleted file mode 100644 index 77e97a35b6d..00000000000 --- a/app/models/members/member_role.rb +++ /dev/null @@ -1,60 +0,0 @@ -# frozen_string_literal: true - -class MemberRole < ApplicationRecord # rubocop:disable Gitlab/NamespacedClass - include IgnorableColumns - ignore_column :download_code, remove_with: '15.9', remove_after: '2023-01-22' - - MAX_COUNT_PER_GROUP_HIERARCHY = 10 - - has_many :members - belongs_to :namespace - - validates :namespace, presence: true - validates :base_access_level, presence: true - validate :belongs_to_top_level_namespace - validate :max_count_per_group_hierarchy, on: :create - validate :validate_namespace_locked, on: :update - validate :attributes_locked_after_member_associated, on: :update - - validates_associated :members - - before_destroy :prevent_delete_after_member_associated - - private - - def belongs_to_top_level_namespace - return if !namespace || namespace.root? - - errors.add(:namespace, s_("MemberRole|must be top-level namespace")) - end - - def max_count_per_group_hierarchy - return unless namespace - return if namespace.member_roles.count < MAX_COUNT_PER_GROUP_HIERARCHY - - errors.add(:namespace, s_("MemberRole|maximum number of Member Roles are already in use by the group hierarchy. "\ - "Please delete an existing Member Role.")) - end - - def validate_namespace_locked - return unless namespace_id_changed? - - errors.add(:namespace, s_("MemberRole|can't be changed")) - end - - def attributes_locked_after_member_associated - return unless members.present? - - errors.add(:base, s_("MemberRole|cannot be changed because it is already assigned to a user. "\ - "Please create a new Member Role instead")) - end - - def prevent_delete_after_member_associated - return unless members.present? - - errors.add(:base, s_("MemberRole|cannot be deleted because it is already assigned to a user. "\ - "Please disassociate the member role from all users before deletion.")) - - throw :abort # rubocop:disable Cop/BanCatchThrow - end -end diff --git a/app/models/namespace.rb b/app/models/namespace.rb index 13466f147bd..2d264e40f33 100644 --- a/app/models/namespace.rb +++ b/app/models/namespace.rb @@ -52,7 +52,6 @@ class Namespace < ApplicationRecord has_one :namespace_statistics has_one :namespace_route, foreign_key: :namespace_id, autosave: false, inverse_of: :namespace, class_name: 'Route' has_many :namespace_members, foreign_key: :member_namespace_id, inverse_of: :member_namespace, class_name: 'Member' - has_many :member_roles has_one :namespace_ldap_settings, inverse_of: :namespace, class_name: 'Namespaces::LdapSetting', autosave: true diff --git a/app/models/project.rb b/app/models/project.rb index f96cff89221..dba14f92e4d 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -2082,7 +2082,11 @@ class Project < ApplicationRecord # rubocop: disable CodeReuse/ServiceClass def open_merge_requests_count(_current_user = nil) - Projects::OpenMergeRequestsCountService.new(self).count + BatchLoader.for(self).batch do |projects, loader| + ::Projects::BatchOpenMergeRequestsCountService.new(projects) + .refresh_cache_and_retrieve_data + .each { |project, count| loader.call(project, count) } + end end # rubocop: enable CodeReuse/ServiceClass diff --git a/app/services/projects/batch_open_merge_requests_count_service.rb b/app/services/projects/batch_open_merge_requests_count_service.rb new file mode 100644 index 00000000000..62d1b018a55 --- /dev/null +++ b/app/services/projects/batch_open_merge_requests_count_service.rb @@ -0,0 +1,18 @@ +# frozen_string_literal: true + +# Service class for getting and caching the number of merge requests of several projects +# Warning: do not user this service with a really large set of projects +# because the service use maps to retrieve the project ids +module Projects + class BatchOpenMergeRequestsCountService < Projects::BatchCountService + # rubocop: disable CodeReuse/ActiveRecord + def global_count + @global_count ||= count_service.query(project_ids).group(:project_id).count + end + # rubocop: enable CodeReuse/ActiveRecord + + def count_service + ::Projects::OpenMergeRequestsCountService + end + end +end diff --git a/app/services/projects/open_merge_requests_count_service.rb b/app/services/projects/open_merge_requests_count_service.rb index 76ec13952ab..c67ebf2f26a 100644 --- a/app/services/projects/open_merge_requests_count_service.rb +++ b/app/services/projects/open_merge_requests_count_service.rb @@ -4,12 +4,12 @@ module Projects # Service class for counting and caching the number of open merge requests of # a project. class OpenMergeRequestsCountService < Projects::CountService - def relation_for_count - @project.merge_requests.opened - end - def cache_key_name 'open_merge_requests_count' end + + def self.query(project_ids) + MergeRequest.opened.of_projects(project_ids) + end end end diff --git a/app/views/layouts/nav/sidebar/_your_work.html.haml b/app/views/layouts/nav/sidebar/_your_work.html.haml index 0eba5045ab1..0da66c2e14e 100644 --- a/app/views/layouts/nav/sidebar/_your_work.html.haml +++ b/app/views/layouts/nav/sidebar/_your_work.html.haml @@ -1 +1 @@ -= render partial: 'shared/nav/sidebar', object: Sidebars::YourWork::Panel.new(Sidebars::Context.new(current_user: current_user, container: nil)) += render partial: 'shared/nav/sidebar', object: Sidebars::YourWork::Panel.new(your_work_sidebar_context(current_user)) diff --git a/doc/topics/your_work.md b/doc/topics/your_work.md index a73838ae8e3..268a6c4df5b 100644 --- a/doc/topics/your_work.md +++ b/doc/topics/your_work.md @@ -18,3 +18,6 @@ The **Your work** left sidebar provides access to your: - [Milestones](../user/project/milestones/index.md) - [Snippets](../user/snippets.md#snippets) - [Activity](../user/profile/index.md#view-your-activity) +- [Environments dashboard](../ci/environments/environments_dashboard.md) +- [Operations dashboard](../user/operations_dashboard/index.md) +- [Security center](../user/application_security/security_dashboard/index.md#security-center) diff --git a/doc/user/application_security/security_dashboard/img/security_center_dashboard_v13_4.png b/doc/user/application_security/security_dashboard/img/security_center_dashboard_v13_4.png Binary files differdeleted file mode 100644 index 5379b5c6e5d..00000000000 --- a/doc/user/application_security/security_dashboard/img/security_center_dashboard_v13_4.png +++ /dev/null diff --git a/doc/user/application_security/security_dashboard/img/security_center_dashboard_v15_10.png b/doc/user/application_security/security_dashboard/img/security_center_dashboard_v15_10.png Binary files differnew file mode 100644 index 00000000000..106b0a13063 --- /dev/null +++ b/doc/user/application_security/security_dashboard/img/security_center_dashboard_v15_10.png diff --git a/doc/user/application_security/security_dashboard/index.md b/doc/user/application_security/security_dashboard/index.md index 4b9aeefcfe9..1a8b4dac10e 100644 --- a/doc/user/application_security/security_dashboard/index.md +++ b/doc/user/application_security/security_dashboard/index.md @@ -133,7 +133,7 @@ The Security Center includes: - A [vulnerability report](../vulnerability_report/index.md). - A settings area to configure which projects to display. -![Security Center Dashboard with projects](img/security_center_dashboard_v13_4.png) +![Security Center Dashboard with projects](img/security_center_dashboard_v15_10.png) ### View the Security Center diff --git a/lib/banzai/reference_parser/commit_parser.rb b/lib/banzai/reference_parser/commit_parser.rb index c51f4976c28..88896970bc6 100644 --- a/lib/banzai/reference_parser/commit_parser.rb +++ b/lib/banzai/reference_parser/commit_parser.rb @@ -32,13 +32,6 @@ module Banzai commits end - def nodes_visible_to_user(user, nodes) - projects = lazy { projects_for_nodes(nodes) } - user.preloaded_member_roles_for_projects(projects.values) if user - - super - end - private def can_read_reference?(user, ref_project, node) diff --git a/lib/banzai/reference_parser/commit_range_parser.rb b/lib/banzai/reference_parser/commit_range_parser.rb index 3d09bc83151..fb4a392105f 100644 --- a/lib/banzai/reference_parser/commit_range_parser.rb +++ b/lib/banzai/reference_parser/commit_range_parser.rb @@ -38,13 +38,6 @@ module Banzai range.valid_commits? ? range : nil end - def nodes_visible_to_user(user, nodes) - projects = lazy { projects_for_nodes(nodes) } - user.preloaded_member_roles_for_projects(projects.values) if user - - super - end - private def can_read_reference?(user, ref_project, node) diff --git a/locale/gitlab.pot b/locale/gitlab.pot index bdd8d4f258f..757c8102e31 100644 --- a/locale/gitlab.pot +++ b/locale/gitlab.pot @@ -38558,9 +38558,6 @@ msgstr "" msgid "Security dashboard" msgstr "" -msgid "Security navigation" -msgstr "" - msgid "Security report is out of date. Please update your branch with the latest changes from the target branch (%{targetBranchName})" msgstr "" @@ -50647,6 +50644,9 @@ msgstr "" msgid "can only have one escalation policy" msgstr "" +msgid "can't be blank" +msgstr "" + msgid "can't be enabled when delayed group deletion is disabled" msgstr "" diff --git a/spec/features/dashboard/projects_spec.rb b/spec/features/dashboard/projects_spec.rb index 8761d8291f8..099a7b14cd8 100644 --- a/spec/features/dashboard/projects_spec.rb +++ b/spec/features/dashboard/projects_spec.rb @@ -248,7 +248,6 @@ RSpec.describe 'Dashboard Projects', feature_category: :projects do ActiveRecord::QueryRecorder.new { visit dashboard_projects_path }.count # There are a few known N+1 queries: https://gitlab.com/gitlab-org/gitlab/-/issues/214037 - # - Project#open_merge_requests_count # - User#max_member_access_for_project_ids # - ProjectsHelper#load_pipeline_status / Ci::CommitWithPipeline#last_pipeline # - Ci::Pipeline#detailed_status diff --git a/spec/models/member_spec.rb b/spec/models/member_spec.rb index 6a52f12553f..781da6d07df 100644 --- a/spec/models/member_spec.rb +++ b/spec/models/member_spec.rb @@ -16,7 +16,6 @@ RSpec.describe Member, feature_category: :subgroups do describe 'Associations' do it { is_expected.to belong_to(:user) } it { is_expected.to belong_to(:member_namespace) } - it { is_expected.to belong_to(:member_role) } it { is_expected.to have_one(:member_task) } end @@ -173,96 +172,6 @@ RSpec.describe Member, feature_category: :subgroups do end end end - - context 'member role access level' do - let_it_be_with_reload(:member) { create(:group_member, access_level: Gitlab::Access::DEVELOPER) } - - context 'when no member role is associated' do - it 'is valid' do - expect(member).to be_valid - end - end - - context 'when member role is associated' do - let!(:member_role) do - create( - :member_role, - members: [member], - base_access_level: Gitlab::Access::DEVELOPER, - namespace: member.member_namespace - ) - end - - context 'when member role matches access level' do - it 'is valid' do - expect(member).to be_valid - end - end - - context 'when member role does not match access level' do - it 'is invalid' do - member_role.base_access_level = Gitlab::Access::MAINTAINER - - expect(member).not_to be_valid - end - end - - context 'when access_level is changed' do - it 'is invalid' do - member.access_level = Gitlab::Access::MAINTAINER - - expect(member).not_to be_valid - expect(member.errors[:access_level]).to include( - _("cannot be changed since member is associated with a custom role") - ) - end - end - end - end - - context 'member role namespace' do - let_it_be_with_reload(:member) { create(:group_member) } - - context 'when no member role is associated' do - it 'is valid' do - expect(member).to be_valid - end - end - - context 'when member role is associated' do - let_it_be(:member_role) do - create(:member_role, members: [member], namespace: member.group, base_access_level: member.access_level) - end - - context 'when member#member_namespace is a group within hierarchy of member_role#namespace' do - it 'is valid' do - member.member_namespace = create(:group, parent: member_role.namespace) - - expect(member).to be_valid - end - end - - context 'when member#member_namespace is a project within hierarchy of member_role#namespace' do - it 'is valid' do - project = create(:project, group: member_role.namespace) - member.member_namespace = Namespace.find(project.parent_id) - - expect(member).to be_valid - end - end - - context 'when member#member_namespace is outside hierarchy of member_role#namespace' do - it 'is invalid' do - member.member_namespace = create(:group) - - expect(member).not_to be_valid - expect(member.errors[:member_namespace]).to include( - _("must be in same hierarchy as custom role's namespace") - ) - end - end - end - end end describe 'Scopes & finders' do diff --git a/spec/models/members/member_role_spec.rb b/spec/models/members/member_role_spec.rb deleted file mode 100644 index 69d164e1942..00000000000 --- a/spec/models/members/member_role_spec.rb +++ /dev/null @@ -1,131 +0,0 @@ -# frozen_string_literal: true - -require 'spec_helper' - -RSpec.describe MemberRole, feature_category: :system_access do - describe 'associations' do - it { is_expected.to belong_to(:namespace) } - it { is_expected.to have_many(:members) } - end - - describe 'validation' do - subject(:member_role) { build(:member_role) } - - it { is_expected.to validate_presence_of(:namespace) } - it { is_expected.to validate_presence_of(:base_access_level) } - - context 'for attributes_locked_after_member_associated' do - context 'when assigned to member' do - it 'cannot be changed' do - member_role.save! - member_role.members << create(:project_member) - - expect(member_role).not_to be_valid - expect(member_role.errors.messages[:base]).to include( - s_("MemberRole|cannot be changed because it is already assigned to a user. "\ - "Please create a new Member Role instead") - ) - end - end - - context 'when not assigned to member' do - it 'can be changed' do - expect(member_role).to be_valid - end - end - end - - context 'for max_count_per_group_hierarchy' do - let_it_be(:group) { create(:group) } - - subject(:member_role) { build(:member_role, namespace: group) } - - context 'when number of member roles is below limit' do - it 'is valid' do - is_expected.to be_valid - end - end - - context 'when number of member roles is above limit' do - before do - stub_const('MemberRole::MAX_COUNT_PER_GROUP_HIERARCHY', 1) - create(:member_role, namespace: group) - group.reload - end - - it 'is invalid' do - is_expected.to be_invalid - end - end - end - - context 'when for namespace' do - let_it_be(:root_group) { create(:group) } - - context 'when namespace is a subgroup' do - it 'is invalid' do - subgroup = create(:group, parent: root_group) - member_role.namespace = subgroup - - expect(member_role).to be_invalid - expect(member_role.errors[:namespace]).to include( - s_("MemberRole|must be top-level namespace") - ) - end - end - - context 'when namespace is a root group' do - it 'is valid' do - member_role.namespace = root_group - - expect(member_role).to be_valid - end - end - - context 'when namespace is not present' do - it 'is invalid with a different error message' do - member_role.namespace = nil - - expect(member_role).to be_invalid - expect(member_role.errors[:namespace]).to include(_("can't be blank")) - end - end - - context 'when namespace is outside hierarchy of member' do - it 'creates a validation error' do - member_role.save! - member_role.namespace = create(:group) - - expect(member_role).not_to be_valid - expect(member_role.errors[:namespace]).to include(s_("MemberRole|can't be changed")) - end - end - end - end - - describe 'callbacks' do - context 'for preventing deletion after member is associated' do - let_it_be(:member_role) { create(:member_role) } - - subject(:destroy_member_role) { member_role.destroy } # rubocop: disable Rails/SaveBang - - it 'allows deletion without any member associated' do - expect(destroy_member_role).to be_truthy - end - - it 'prevent deletion when member is associated' do - create(:group_member, { group: member_role.namespace, - access_level: Gitlab::Access::DEVELOPER, - member_role: member_role }) - member_role.members.reload - - expect(destroy_member_role).to be_falsey - expect(member_role.errors.messages[:base]) - .to( - include(s_("MemberRole|cannot be deleted because it is already assigned to a user. "\ - "Please disassociate the member role from all users before deletion.")) - ) - end - end - end -end diff --git a/spec/models/merge_request_spec.rb b/spec/models/merge_request_spec.rb index 3932a925086..e7d815414a8 100644 --- a/spec/models/merge_request_spec.rb +++ b/spec/models/merge_request_spec.rb @@ -4291,8 +4291,11 @@ RSpec.describe MergeRequest, factory_default: :keep, feature_category: :code_rev it 'refreshes the number of open merge requests of the target project' do project = subject.target_project - expect { subject.destroy! } - .to change { project.open_merge_requests_count }.from(1).to(0) + expect do + subject.destroy! + + BatchLoader::Executor.clear_current + end.to change { project.open_merge_requests_count }.from(1).to(0) end end diff --git a/spec/models/namespace_spec.rb b/spec/models/namespace_spec.rb index 0553a7d7152..60338d42bfa 100644 --- a/spec/models/namespace_spec.rb +++ b/spec/models/namespace_spec.rb @@ -31,7 +31,6 @@ RSpec.describe Namespace, feature_category: :subgroups do it { is_expected.to have_many :pending_builds } it { is_expected.to have_one :namespace_route } it { is_expected.to have_many :namespace_members } - it { is_expected.to have_many :member_roles } it { is_expected.to have_one :cluster_enabled_grant } it { is_expected.to have_many(:work_items) } it { is_expected.to have_many :achievements } diff --git a/spec/services/merge_requests/close_service_spec.rb b/spec/services/merge_requests/close_service_spec.rb index 2c0817550c6..25c75ae7244 100644 --- a/spec/services/merge_requests/close_service_spec.rb +++ b/spec/services/merge_requests/close_service_spec.rb @@ -88,7 +88,11 @@ RSpec.describe MergeRequests::CloseService, feature_category: :code_review_workf end it 'refreshes the number of open merge requests for a valid MR', :use_clean_rails_memory_store_caching do - expect { execute } + expect do + execute + + BatchLoader::Executor.clear_current + end .to change { project.open_merge_requests_count }.from(1).to(0) end diff --git a/spec/services/merge_requests/create_service_spec.rb b/spec/services/merge_requests/create_service_spec.rb index 394fc269ac3..7e20af32985 100644 --- a/spec/services/merge_requests/create_service_spec.rb +++ b/spec/services/merge_requests/create_service_spec.rb @@ -43,8 +43,11 @@ RSpec.describe MergeRequests::CreateService, :clean_gitlab_redis_shared_state, f end it 'refreshes the number of open merge requests', :use_clean_rails_memory_store_caching do - expect { service.execute } - .to change { project.open_merge_requests_count }.from(0).to(1) + expect do + service.execute + + BatchLoader::Executor.clear_current + end.to change { project.open_merge_requests_count }.from(0).to(1) end it 'creates exactly 1 create MR event', :sidekiq_might_not_need_inline do diff --git a/spec/services/merge_requests/post_merge_service_spec.rb b/spec/services/merge_requests/post_merge_service_spec.rb index d89bfba5129..f7526c169bd 100644 --- a/spec/services/merge_requests/post_merge_service_spec.rb +++ b/spec/services/merge_requests/post_merge_service_spec.rb @@ -23,7 +23,11 @@ RSpec.describe MergeRequests::PostMergeService, feature_category: :code_review_w # Cache the counter before the MR changed state. project.open_merge_requests_count - expect { subject }.to change { project.open_merge_requests_count }.from(1).to(0) + expect do + subject + + BatchLoader::Executor.clear_current + end.to change { project.open_merge_requests_count }.from(1).to(0) end it 'updates metrics' do diff --git a/spec/services/merge_requests/reopen_service_spec.rb b/spec/services/merge_requests/reopen_service_spec.rb index 6d30dd39293..7399b29d06e 100644 --- a/spec/services/merge_requests/reopen_service_spec.rb +++ b/spec/services/merge_requests/reopen_service_spec.rb @@ -92,7 +92,11 @@ RSpec.describe MergeRequests::ReopenService, feature_category: :code_review_work it 'refreshes the number of open merge requests for a valid MR' do service = described_class.new(project: project, current_user: user) - expect { service.execute(merge_request) } + expect do + service.execute(merge_request) + + BatchLoader::Executor.clear_current + end .to change { project.open_merge_requests_count }.from(0).to(1) end diff --git a/spec/services/projects/batch_open_merge_requests_count_service_spec.rb b/spec/services/projects/batch_open_merge_requests_count_service_spec.rb new file mode 100644 index 00000000000..96fc6c5e9dd --- /dev/null +++ b/spec/services/projects/batch_open_merge_requests_count_service_spec.rb @@ -0,0 +1,32 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Projects::BatchOpenMergeRequestsCountService, feature_category: :code_review_workflow do + subject { described_class.new([project_1, project_2]) } + + let_it_be(:project_1) { create(:project) } + let_it_be(:project_2) { create(:project) } + + describe '#refresh_cache_and_retrieve_data', :use_clean_rails_memory_store_caching do + before do + create(:merge_request, source_project: project_1, target_project: project_1) + create(:merge_request, source_project: project_2, target_project: project_2) + end + + it 'refreshes cache keys correctly when cache is clean', :aggregate_failures do + subject.refresh_cache_and_retrieve_data + + expect(Rails.cache.read(get_cache_key(subject, project_1))).to eq(1) + expect(Rails.cache.read(get_cache_key(subject, project_2))).to eq(1) + + expect { subject.refresh_cache_and_retrieve_data }.not_to exceed_query_limit(0) + end + end + + def get_cache_key(subject, project) + subject.count_service + .new(project) + .cache_key + end +end diff --git a/spec/support/db_cleaner.rb b/spec/support/db_cleaner.rb index 223862c17a9..b9a99eff413 100644 --- a/spec/support/db_cleaner.rb +++ b/spec/support/db_cleaner.rb @@ -75,9 +75,6 @@ module DbCleaner Gitlab::Database::Partitioning.sync_partitions_ignore_db_error - # Restore write locks - Gitlab::Database::TablesLocker.new.lock_writes - puts "Databases re-creation done in #{Gitlab::Metrics::System.monotonic_time - start}" end |