Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
		
							parent
							
								
									a0d18c1c5c
								
							
						
					
					
						commit
						ea8c112615
					
				|  | @ -18,6 +18,10 @@ module Types | ||||||
|             description: 'Schedule for the build.' |             description: 'Schedule for the build.' | ||||||
|       field :artifacts, Types::Ci::JobArtifactType.connection_type, null: true, |       field :artifacts, Types::Ci::JobArtifactType.connection_type, null: true, | ||||||
|             description: 'Artifacts generated by the job.' |             description: 'Artifacts generated by the job.' | ||||||
|  |       field :finished_at, Types::TimeType, null: true, | ||||||
|  |             description: 'When a job has finished running.' | ||||||
|  |       field :duration, GraphQL::INT_TYPE, null: true, | ||||||
|  |             description: 'Duration of the job in seconds.' | ||||||
| 
 | 
 | ||||||
|       def pipeline |       def pipeline | ||||||
|         Gitlab::Graphql::Loaders::BatchModelLoader.new(::Ci::Pipeline, object.pipeline_id).find |         Gitlab::Graphql::Loaders::BatchModelLoader.new(::Ci::Pipeline, object.pipeline_id).find | ||||||
|  |  | ||||||
|  | @ -1165,6 +1165,10 @@ module Ci | ||||||
|       end |       end | ||||||
|     end |     end | ||||||
| 
 | 
 | ||||||
|  |     def for_merged_result? | ||||||
|  |       merge_request_event_type == :merged_result | ||||||
|  |     end | ||||||
|  | 
 | ||||||
|     def persistent_ref |     def persistent_ref | ||||||
|       @persistent_ref ||= PersistentRef.new(pipeline: self) |       @persistent_ref ||= PersistentRef.new(pipeline: self) | ||||||
|     end |     end | ||||||
|  |  | ||||||
|  | @ -36,6 +36,10 @@ class MergeRequest < ApplicationRecord | ||||||
| 
 | 
 | ||||||
|   SORTING_PREFERENCE_FIELD = :merge_requests_sort |   SORTING_PREFERENCE_FIELD = :merge_requests_sort | ||||||
| 
 | 
 | ||||||
|  |   ALLOWED_TO_USE_MERGE_BASE_PIPELINE_FOR_COMPARISON = { | ||||||
|  |     'Ci::CompareCodequalityReportsService' => ->(project) { ::Gitlab::Ci::Features.display_codequality_backend_comparison?(project) } | ||||||
|  |   }.freeze | ||||||
|  | 
 | ||||||
|   belongs_to :target_project, class_name: "Project" |   belongs_to :target_project, class_name: "Project" | ||||||
|   belongs_to :source_project, class_name: "Project" |   belongs_to :source_project, class_name: "Project" | ||||||
|   belongs_to :merge_user, class_name: "User" |   belongs_to :merge_user, class_name: "User" | ||||||
|  | @ -1564,7 +1568,7 @@ class MergeRequest < ApplicationRecord | ||||||
|   def compare_reports(service_class, current_user = nil, report_type = nil ) |   def compare_reports(service_class, current_user = nil, report_type = nil ) | ||||||
|     with_reactive_cache(service_class.name, current_user&.id, report_type) do |data| |     with_reactive_cache(service_class.name, current_user&.id, report_type) do |data| | ||||||
|       unless service_class.new(project, current_user, id: id, report_type: report_type) |       unless service_class.new(project, current_user, id: id, report_type: report_type) | ||||||
|         .latest?(base_pipeline, actual_head_pipeline, data) |         .latest?(comparison_base_pipeline(service_class.name), actual_head_pipeline, data) | ||||||
|         raise InvalidateReactiveCache |         raise InvalidateReactiveCache | ||||||
|       end |       end | ||||||
| 
 | 
 | ||||||
|  | @ -1600,7 +1604,7 @@ class MergeRequest < ApplicationRecord | ||||||
|     raise NameError, service_class unless service_class < Ci::CompareReportsBaseService |     raise NameError, service_class unless service_class < Ci::CompareReportsBaseService | ||||||
| 
 | 
 | ||||||
|     current_user = User.find_by(id: current_user_id) |     current_user = User.find_by(id: current_user_id) | ||||||
|     service_class.new(project, current_user, id: id, report_type: report_type).execute(base_pipeline, actual_head_pipeline) |     service_class.new(project, current_user, id: id, report_type: report_type).execute(comparison_base_pipeline(identifier), actual_head_pipeline) | ||||||
|   end |   end | ||||||
| 
 | 
 | ||||||
|   def all_commits |   def all_commits | ||||||
|  | @ -1724,6 +1728,14 @@ class MergeRequest < ApplicationRecord | ||||||
|     end |     end | ||||||
|   end |   end | ||||||
| 
 | 
 | ||||||
|  |   def use_merge_base_pipeline_for_comparison?(service_class) | ||||||
|  |     ALLOWED_TO_USE_MERGE_BASE_PIPELINE_FOR_COMPARISON[service_class]&.call(project) | ||||||
|  |   end | ||||||
|  | 
 | ||||||
|  |   def comparison_base_pipeline(service_class) | ||||||
|  |     (use_merge_base_pipeline_for_comparison?(service_class) && merge_base_pipeline) || base_pipeline | ||||||
|  |   end | ||||||
|  | 
 | ||||||
|   def base_pipeline |   def base_pipeline | ||||||
|     @base_pipeline ||= project.ci_pipelines |     @base_pipeline ||= project.ci_pipelines | ||||||
|       .order(id: :desc) |       .order(id: :desc) | ||||||
|  |  | ||||||
|  | @ -157,7 +157,7 @@ class MergeRequestWidgetEntity < Grape::Entity | ||||||
|   end |   end | ||||||
| 
 | 
 | ||||||
|   def use_merge_base_with_merged_results? |   def use_merge_base_with_merged_results? | ||||||
|     object.actual_head_pipeline&.merge_request_event_type == :merged_result |     object.actual_head_pipeline&.for_merged_result? | ||||||
|   end |   end | ||||||
| 
 | 
 | ||||||
|   def head_pipeline_downloadable_path_for_report_type(file_type) |   def head_pipeline_downloadable_path_for_report_type(file_type) | ||||||
|  |  | ||||||
|  | @ -0,0 +1,5 @@ | ||||||
|  | --- | ||||||
|  | title: Add duration and finishedAt GraphQL fields to jobType in the CI namespace | ||||||
|  | merge_request: 54358 | ||||||
|  | author: | ||||||
|  | type: changed | ||||||
|  | @ -0,0 +1,8 @@ | ||||||
|  | --- | ||||||
|  | name: api_v3_repos_events_optimization | ||||||
|  | introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/54618 | ||||||
|  | rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/322059 | ||||||
|  | milestone: '13.10' | ||||||
|  | type: development | ||||||
|  | group: group::ecosystem | ||||||
|  | default_enabled: false | ||||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							|  | @ -813,6 +813,8 @@ Autogenerated return type of CiCdSettingsUpdate. | ||||||
| | ----- | ---- | ----------- | | | ----- | ---- | ----------- | | ||||||
| | `artifacts` | CiJobArtifactConnection | Artifacts generated by the job. | | | `artifacts` | CiJobArtifactConnection | Artifacts generated by the job. | | ||||||
| | `detailedStatus` | DetailedStatus | Detailed status of the job. | | | `detailedStatus` | DetailedStatus | Detailed status of the job. | | ||||||
|  | | `duration` | Int | Duration of the job in seconds. | | ||||||
|  | | `finishedAt` | Time | When a job has finished running. | | ||||||
| | `name` | String | Name of the job. | | | `name` | String | Name of the job. | | ||||||
| | `needs` | CiBuildNeedConnection | References to builds that must complete before the jobs run. | | | `needs` | CiBuildNeedConnection | References to builds that must complete before the jobs run. | | ||||||
| | `pipeline` | Pipeline | Pipeline the job belongs to. | | | `pipeline` | Pipeline | Pipeline the job belongs to. | | ||||||
|  |  | ||||||
|  | @ -29,7 +29,7 @@ To change the default branch protection: | ||||||
| 
 | 
 | ||||||
| For more details, see [Protected branches](../../project/protected_branches.md). | For more details, see [Protected branches](../../project/protected_branches.md). | ||||||
| 
 | 
 | ||||||
| To change this setting for a specific group, see [Default branch protection for groups](../../group/index.md#changing-the-default-branch-protection-of-a-group) | To change this setting for a specific group, see [Default branch protection for groups](../../group/index.md#change-the-default-branch-protection-of-a-group) | ||||||
| 
 | 
 | ||||||
| ### Disable group owners from updating default branch protection **(PREMIUM SELF)** | ### Disable group owners from updating default branch protection **(PREMIUM SELF)** | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
										
											Binary file not shown.
										
									
								
							| Before Width: | Height: | Size: 38 KiB | 
										
											Binary file not shown.
										
									
								
							| Before Width: | Height: | Size: 40 KiB | 
										
											Binary file not shown.
										
									
								
							| Before Width: | Height: | Size: 40 KiB | 
										
											Binary file not shown.
										
									
								
							| Before Width: | Height: | Size: 42 KiB | 
										
											Binary file not shown.
										
									
								
							| Before Width: | Height: | Size: 28 KiB | 
										
											Binary file not shown.
										
									
								
							| Before Width: | Height: | Size: 41 KiB | 
|  | @ -148,54 +148,35 @@ To remove a member from a group: | ||||||
| > - [Improved](https://gitlab.com/gitlab-org/gitlab/-/issues/228675) in GitLab 13.7. | > - [Improved](https://gitlab.com/gitlab-org/gitlab/-/issues/228675) in GitLab 13.7. | ||||||
| > - [Feature flag removed](https://gitlab.com/gitlab-org/gitlab/-/issues/289911) in GitLab 13.8. | > - [Feature flag removed](https://gitlab.com/gitlab-org/gitlab/-/issues/289911) in GitLab 13.8. | ||||||
| 
 | 
 | ||||||
| The following sections illustrate how you can filter and sort members in a group. To view these options, | To find members in a group, you can sort, filter, or search. | ||||||
| navigate to your desired group, go to **Members**, and include the noted search terms. |  | ||||||
| 
 | 
 | ||||||
| ### Membership filter | ### Filter a group | ||||||
| 
 | 
 | ||||||
| By default, inherited and direct members are displayed. The [membership](subgroups/index.md#membership) filter can be used to display only inherited or only direct members. | Filter a group to find members. By default, all members in the group and subgroups are displayed. | ||||||
| 
 | 
 | ||||||
| #### Only display inherited members | 1. Go to the group and select **Members** (**{users}**). | ||||||
|  | 1. Above the list of members, in the **Filter members** box, enter filter criteria. | ||||||
|  |    - To view members in the group only, select **Membership = Direct**. | ||||||
|  |    - To view members of the group and its subgroups, select **Membership = Inherited**. | ||||||
|  |    - To view members with two-factor authentication enabled or disabled, select **2FA = Enabled** or **Disabled**. | ||||||
| 
 | 
 | ||||||
| Include `Membership` `=` `Inherited` in the search text box. | ### Search a group | ||||||
| 
 |  | ||||||
|  |  | ||||||
| 
 |  | ||||||
| #### Only display direct members |  | ||||||
| 
 |  | ||||||
| Include `Membership` `=` `Direct` in the search text box. |  | ||||||
| 
 |  | ||||||
|  |  | ||||||
| 
 |  | ||||||
| ### 2FA filter |  | ||||||
| 
 |  | ||||||
| [Owner](../permissions.md#group-members-permissions) permissions required. |  | ||||||
| 
 |  | ||||||
| By default, members with 2FA enabled and disabled are displayed. The 2FA filter can be used to display only members with 2FA enabled or only members with 2FA disabled. |  | ||||||
| 
 |  | ||||||
| #### Only display members with 2FA enabled |  | ||||||
| 
 |  | ||||||
| Include `2FA` `=` `Enabled` in the search text box. |  | ||||||
| 
 |  | ||||||
|  |  | ||||||
| 
 |  | ||||||
| #### Only display members with 2FA disabled |  | ||||||
| 
 |  | ||||||
| Include `2FA` `=` `Disabled` in the search text box. |  | ||||||
| 
 |  | ||||||
|  |  | ||||||
| 
 |  | ||||||
| ### Search |  | ||||||
| 
 | 
 | ||||||
| You can search for members by name, username, or email. | You can search for members by name, username, or email. | ||||||
| 
 | 
 | ||||||
|  | 1. Go to the group and select **Members** (**{users}**). | ||||||
|  | 1. Above the list of members, in the **Filter members** box, enter search criteria. | ||||||
|  | 1. To the right of the **Filter members** box, select the magnifying glass (**{search}**). | ||||||
| 
 | 
 | ||||||
| ### Sort | ### Sort members in a group | ||||||
| 
 | 
 | ||||||
| You can sort members by **Account**, **Access granted**, **Max role**, or **Last sign-in** in ascending or descending order. | You can sort members by **Account**, **Access granted**, **Max role**, or **Last sign-in**. | ||||||
| 
 | 
 | ||||||
|  | 1. Go to the group and select **Members** (**{users}**). | ||||||
|  | 1. Above the list of members, on the top right, from the **Account** list, select | ||||||
|  |    the criteria to filter by. | ||||||
|  | 1. To switch the sort between ascending and descending, to the right of the **Account** list, select the | ||||||
|  |    arrow (**{sort-lowest}** or **{sort-highest}**). | ||||||
| 
 | 
 | ||||||
| ## Mention a group in an issue or merge request | ## Mention a group in an issue or merge request | ||||||
| 
 | 
 | ||||||
|  | @ -209,7 +190,7 @@ added to their To-do list. | ||||||
| 
 | 
 | ||||||
| A to-do item is created for all the group and subgroup members. | A to-do item is created for all the group and subgroup members. | ||||||
| 
 | 
 | ||||||
| ## Changing the default branch protection of a group | ## Change the default branch protection of a group | ||||||
| 
 | 
 | ||||||
| > [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/7583) in GitLab 12.9. | > [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/7583) in GitLab 12.9. | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -147,7 +147,7 @@ From the image above, we can deduce the following things: | ||||||
| - Administrator is the Owner and member of **all** subgroups and for that reason, | - Administrator is the Owner and member of **all** subgroups and for that reason, | ||||||
|   as with User 3, the **Source** column indicates **Direct member**. |   as with User 3, the **Source** column indicates **Direct member**. | ||||||
| 
 | 
 | ||||||
| Members can be [filtered by inherited or direct membership](../index.md#membership-filter). | Members can be [filtered by inherited or direct membership](../index.md#filter-a-group). | ||||||
| 
 | 
 | ||||||
| ### Overriding the ancestor group membership | ### Overriding the ancestor group membership | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -303,7 +303,7 @@ group. | ||||||
|    - The [instance level](admin_area/settings/visibility_and_access_controls.md#default-project-creation-protection). |    - The [instance level](admin_area/settings/visibility_and_access_controls.md#default-project-creation-protection). | ||||||
|    - The [group level](group/index.md#default-project-creation-level). |    - The [group level](group/index.md#default-project-creation-level). | ||||||
| 1. Does not apply to subgroups. | 1. Does not apply to subgroups. | ||||||
| 1. Developers can push commits to the default branch of a new project only if the [default branch protection](group/index.md#changing-the-default-branch-protection-of-a-group) is set to "Partially protected" or "Not protected". | 1. Developers can push commits to the default branch of a new project only if the [default branch protection](group/index.md#change-the-default-branch-protection-of-a-group) is set to "Partially protected" or "Not protected". | ||||||
| 1. In addition, if your group is public or internal, all users who can see the group can also see group wiki pages. | 1. In addition, if your group is public or internal, all users who can see the group can also see group wiki pages. | ||||||
| 1. Users can only view events based on their individual actions. | 1. Users can only view events based on their individual actions. | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -194,13 +194,19 @@ module API | ||||||
| 
 | 
 | ||||||
|         # Self-hosted Jira (tested on 7.11.1) requests this endpoint right |         # Self-hosted Jira (tested on 7.11.1) requests this endpoint right | ||||||
|         # after fetching branches. |         # after fetching branches. | ||||||
|  |         # rubocop: disable CodeReuse/ActiveRecord | ||||||
|         get ':namespace/:project/events' do |         get ':namespace/:project/events' do | ||||||
|           user_project = find_project_with_access(params) |           user_project = find_project_with_access(params) | ||||||
| 
 | 
 | ||||||
|           merge_requests = authorized_merge_requests_for_project(user_project) |           merge_requests = authorized_merge_requests_for_project(user_project) | ||||||
| 
 | 
 | ||||||
|  |           if Feature.enabled?(:api_v3_repos_events_optimization, user_project) | ||||||
|  |             merge_requests = merge_requests.preload(:author, :assignees, :metrics, source_project: :namespace, target_project: :namespace) | ||||||
|  |           end | ||||||
|  | 
 | ||||||
|           present paginate(merge_requests), with: ::API::Github::Entities::PullRequestEvent |           present paginate(merge_requests), with: ::API::Github::Entities::PullRequestEvent | ||||||
|         end |         end | ||||||
|  |         # rubocop: enable CodeReuse/ActiveRecord | ||||||
| 
 | 
 | ||||||
|         params do |         params do | ||||||
|           use :project_full_path |           use :project_full_path | ||||||
|  |  | ||||||
|  | @ -14,6 +14,8 @@ RSpec.describe Types::Ci::JobType do | ||||||
|       detailedStatus |       detailedStatus | ||||||
|       scheduledAt |       scheduledAt | ||||||
|       artifacts |       artifacts | ||||||
|  |       finished_at | ||||||
|  |       duration | ||||||
|     ] |     ] | ||||||
| 
 | 
 | ||||||
|     expect(described_class).to have_graphql_fields(*expected_fields) |     expect(described_class).to have_graphql_fields(*expected_fields) | ||||||
|  |  | ||||||
|  | @ -412,6 +412,24 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do | ||||||
|     end |     end | ||||||
|   end |   end | ||||||
| 
 | 
 | ||||||
|  |   describe '#for_merged_result?' do | ||||||
|  |     subject { pipeline.for_merged_result? } | ||||||
|  | 
 | ||||||
|  |     let(:pipeline) { merge_request.all_pipelines.last } | ||||||
|  | 
 | ||||||
|  |     context 'when pipeline is merge request pipeline' do | ||||||
|  |       let(:merge_request) { create(:merge_request, :with_merge_request_pipeline) } | ||||||
|  | 
 | ||||||
|  |       it { is_expected.to be_truthy } | ||||||
|  |     end | ||||||
|  | 
 | ||||||
|  |     context 'when pipeline is detached merge request pipeline' do | ||||||
|  |       let(:merge_request) { create(:merge_request, :with_detached_merge_request_pipeline) } | ||||||
|  | 
 | ||||||
|  |       it { is_expected.to be_falsey } | ||||||
|  |     end | ||||||
|  |   end | ||||||
|  | 
 | ||||||
|   describe '#legacy_detached_merge_request_pipeline?' do |   describe '#legacy_detached_merge_request_pipeline?' do | ||||||
|     subject { pipeline.legacy_detached_merge_request_pipeline? } |     subject { pipeline.legacy_detached_merge_request_pipeline? } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -3839,6 +3839,87 @@ RSpec.describe MergeRequest, factory_default: :keep do | ||||||
|     end |     end | ||||||
|   end |   end | ||||||
| 
 | 
 | ||||||
|  |   describe '#use_merge_base_pipeline_for_comparison?' do | ||||||
|  |     let(:project) { create(:project, :public, :repository) } | ||||||
|  |     let(:merge_request) { create(:merge_request, :with_codequality_reports, source_project: project) } | ||||||
|  | 
 | ||||||
|  |     subject { merge_request.use_merge_base_pipeline_for_comparison?(service_class) } | ||||||
|  | 
 | ||||||
|  |     context 'when service class is Ci::CompareCodequalityReportsService' do | ||||||
|  |       let(:service_class) { 'Ci::CompareCodequalityReportsService' } | ||||||
|  | 
 | ||||||
|  |       context 'when feature flag is enabled' do | ||||||
|  |         it { is_expected.to be_truthy } | ||||||
|  |       end | ||||||
|  | 
 | ||||||
|  |       context 'when feature flag is disabled' do | ||||||
|  |         before do | ||||||
|  |           stub_feature_flags(codequality_backend_comparison: false) | ||||||
|  |         end | ||||||
|  | 
 | ||||||
|  |         it { is_expected.to be_falsey } | ||||||
|  |       end | ||||||
|  |     end | ||||||
|  | 
 | ||||||
|  |     context 'when service class is different' do | ||||||
|  |       let(:service_class) { 'Ci::GenerateCoverageReportsService' } | ||||||
|  | 
 | ||||||
|  |       it { is_expected.to be_falsey } | ||||||
|  |     end | ||||||
|  |   end | ||||||
|  | 
 | ||||||
|  |   describe '#comparison_base_pipeline' do | ||||||
|  |     subject(:pipeline) { merge_request.comparison_base_pipeline(service_class) } | ||||||
|  | 
 | ||||||
|  |     let(:project) { create(:project, :public, :repository) } | ||||||
|  |     let(:merge_request) { create(:merge_request, :with_codequality_reports, source_project: project) } | ||||||
|  |     let!(:base_pipeline) do | ||||||
|  |       create(:ci_pipeline, | ||||||
|  |         :with_test_reports, | ||||||
|  |         project: project, | ||||||
|  |         ref: merge_request.target_branch, | ||||||
|  |         sha: merge_request.diff_base_sha | ||||||
|  |       ) | ||||||
|  |     end | ||||||
|  | 
 | ||||||
|  |     context 'when service class is Ci::CompareCodequalityReportsService' do | ||||||
|  |       let(:service_class) { 'Ci::CompareCodequalityReportsService' } | ||||||
|  | 
 | ||||||
|  |       context 'when merge request has a merge request pipeline' do | ||||||
|  |         let(:merge_request) do | ||||||
|  |           create(:merge_request, :with_merge_request_pipeline) | ||||||
|  |         end | ||||||
|  | 
 | ||||||
|  |         let(:merge_base_pipeline) do | ||||||
|  |           create(:ci_pipeline, ref: merge_request.target_branch, sha: merge_request.target_branch_sha) | ||||||
|  |         end | ||||||
|  | 
 | ||||||
|  |         before do | ||||||
|  |           merge_base_pipeline | ||||||
|  |           merge_request.update_head_pipeline | ||||||
|  |         end | ||||||
|  | 
 | ||||||
|  |         it 'returns the merge_base_pipeline' do | ||||||
|  |           expect(pipeline).to eq(merge_base_pipeline) | ||||||
|  |         end | ||||||
|  |       end | ||||||
|  | 
 | ||||||
|  |       context 'when merge does not have a merge request pipeline' do | ||||||
|  |         it 'returns the base_pipeline' do | ||||||
|  |           expect(pipeline).to eq(base_pipeline) | ||||||
|  |         end | ||||||
|  |       end | ||||||
|  |     end | ||||||
|  | 
 | ||||||
|  |     context 'when service_class is different' do | ||||||
|  |       let(:service_class) { 'Ci::GenerateCoverageReportsService' } | ||||||
|  | 
 | ||||||
|  |       it 'returns the base_pipeline' do | ||||||
|  |         expect(pipeline).to eq(base_pipeline) | ||||||
|  |       end | ||||||
|  |     end | ||||||
|  |   end | ||||||
|  | 
 | ||||||
|   describe '#base_pipeline' do |   describe '#base_pipeline' do | ||||||
|     let(:pipeline_arguments) do |     let(:pipeline_arguments) do | ||||||
|       { |       { | ||||||
|  |  | ||||||
|  | @ -149,6 +149,8 @@ RSpec.describe API::V3::Github do | ||||||
|     end |     end | ||||||
| 
 | 
 | ||||||
|     describe 'GET events' do |     describe 'GET events' do | ||||||
|  |       include ProjectForksHelper | ||||||
|  | 
 | ||||||
|       let(:group) { create(:group) } |       let(:group) { create(:group) } | ||||||
|       let(:project) { create(:project, :empty_repo, path: 'project.with.dot', group: group) } |       let(:project) { create(:project, :empty_repo, path: 'project.with.dot', group: group) } | ||||||
|       let(:events_path) { "/repos/#{group.path}/#{project.path}/events" } |       let(:events_path) { "/repos/#{group.path}/#{project.path}/events" } | ||||||
|  | @ -174,6 +176,34 @@ RSpec.describe API::V3::Github do | ||||||
|         end |         end | ||||||
|       end |       end | ||||||
| 
 | 
 | ||||||
|  |       it 'avoids N+1 queries' do | ||||||
|  |         create(:merge_request, source_project: project) | ||||||
|  |         source_project = fork_project(project, nil, repository: true) | ||||||
|  | 
 | ||||||
|  |         control_count = ActiveRecord::QueryRecorder.new(skip_cached: false) { jira_get v3_api(events_path, user) }.count | ||||||
|  | 
 | ||||||
|  |         create_list(:merge_request, 2, :unique_branches, source_project: source_project, target_project: project) | ||||||
|  | 
 | ||||||
|  |         expect { jira_get v3_api(events_path, user) }.not_to exceed_all_query_limit(control_count) | ||||||
|  |       end | ||||||
|  | 
 | ||||||
|  |       context 'with `api_v3_repos_events_optimization` feature flag disabled' do | ||||||
|  |         before do | ||||||
|  |           stub_feature_flags(api_v3_repos_events_optimization: false) | ||||||
|  |         end | ||||||
|  | 
 | ||||||
|  |         it 'falls back to less optimal query performance' do | ||||||
|  |           create(:merge_request, source_project: project) | ||||||
|  |           source_project = fork_project(project, nil, repository: true) | ||||||
|  | 
 | ||||||
|  |           control_count = ActiveRecord::QueryRecorder.new(skip_cached: false) { jira_get v3_api(events_path, user) }.count | ||||||
|  | 
 | ||||||
|  |           create_list(:merge_request, 2, :unique_branches, source_project: source_project, target_project: project) | ||||||
|  | 
 | ||||||
|  |           expect { jira_get v3_api(events_path, user) }.to exceed_all_query_limit(control_count) | ||||||
|  |         end | ||||||
|  |       end | ||||||
|  | 
 | ||||||
|       context 'if there are more merge requests' do |       context 'if there are more merge requests' do | ||||||
|         let!(:merge_request) { create(:merge_request, id: 10000, source_project: project, target_project: project, author: user) } |         let!(:merge_request) { create(:merge_request, id: 10000, source_project: project, target_project: project, author: user) } | ||||||
|         let!(:merge_request2) { create(:merge_request, id: 10001, source_project: project, source_branch: generate(:branch), target_project: project, author: user) } |         let!(:merge_request2) { create(:merge_request, id: 10001, source_project: project, source_branch: generate(:branch), target_project: project, author: user) } | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue