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.' | ||||
|       field :artifacts, Types::Ci::JobArtifactType.connection_type, null: true, | ||||
|             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 | ||||
|         Gitlab::Graphql::Loaders::BatchModelLoader.new(::Ci::Pipeline, object.pipeline_id).find | ||||
|  |  | |||
|  | @ -1165,6 +1165,10 @@ module Ci | |||
|       end | ||||
|     end | ||||
| 
 | ||||
|     def for_merged_result? | ||||
|       merge_request_event_type == :merged_result | ||||
|     end | ||||
| 
 | ||||
|     def persistent_ref | ||||
|       @persistent_ref ||= PersistentRef.new(pipeline: self) | ||||
|     end | ||||
|  |  | |||
|  | @ -36,6 +36,10 @@ class MergeRequest < ApplicationRecord | |||
| 
 | ||||
|   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 :source_project, class_name: "Project" | ||||
|   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 ) | ||||
|     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) | ||||
|         .latest?(base_pipeline, actual_head_pipeline, data) | ||||
|         .latest?(comparison_base_pipeline(service_class.name), actual_head_pipeline, data) | ||||
|         raise InvalidateReactiveCache | ||||
|       end | ||||
| 
 | ||||
|  | @ -1600,7 +1604,7 @@ class MergeRequest < ApplicationRecord | |||
|     raise NameError, service_class unless service_class < Ci::CompareReportsBaseService | ||||
| 
 | ||||
|     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 | ||||
| 
 | ||||
|   def all_commits | ||||
|  | @ -1724,6 +1728,14 @@ class MergeRequest < ApplicationRecord | |||
|     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 | ||||
|     @base_pipeline ||= project.ci_pipelines | ||||
|       .order(id: :desc) | ||||
|  |  | |||
|  | @ -157,7 +157,7 @@ class MergeRequestWidgetEntity < Grape::Entity | |||
|   end | ||||
| 
 | ||||
|   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 | ||||
| 
 | ||||
|   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. | | ||||
| | `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. | | ||||
| | `needs` | CiBuildNeedConnection | References to builds that must complete before the jobs run. | | ||||
| | `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). | ||||
| 
 | ||||
| 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)** | ||||
| 
 | ||||
|  |  | |||
										
											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. | ||||
| > - [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, | ||||
| navigate to your desired group, go to **Members**, and include the noted search terms. | ||||
| To find members in a group, you can sort, filter, or search. | ||||
| 
 | ||||
| ### 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. | ||||
| 
 | ||||
|  | ||||
| 
 | ||||
| #### 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 | ||||
| ### Search a group | ||||
| 
 | ||||
| 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 | ||||
| 
 | ||||
|  | @ -209,7 +190,7 @@ added to their To-do list. | |||
| 
 | ||||
| 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. | ||||
| 
 | ||||
|  |  | |||
|  | @ -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, | ||||
|   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 | ||||
| 
 | ||||
|  |  | |||
|  | @ -303,7 +303,7 @@ group. | |||
|    - 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). | ||||
| 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. 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 | ||||
|         # after fetching branches. | ||||
|         # rubocop: disable CodeReuse/ActiveRecord | ||||
|         get ':namespace/:project/events' do | ||||
|           user_project = find_project_with_access(params) | ||||
| 
 | ||||
|           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 | ||||
|         end | ||||
|         # rubocop: enable CodeReuse/ActiveRecord | ||||
| 
 | ||||
|         params do | ||||
|           use :project_full_path | ||||
|  |  | |||
|  | @ -14,6 +14,8 @@ RSpec.describe Types::Ci::JobType do | |||
|       detailedStatus | ||||
|       scheduledAt | ||||
|       artifacts | ||||
|       finished_at | ||||
|       duration | ||||
|     ] | ||||
| 
 | ||||
|     expect(described_class).to have_graphql_fields(*expected_fields) | ||||
|  |  | |||
|  | @ -412,6 +412,24 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do | |||
|     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 | ||||
|     subject { pipeline.legacy_detached_merge_request_pipeline? } | ||||
| 
 | ||||
|  |  | |||
|  | @ -3839,6 +3839,87 @@ RSpec.describe MergeRequest, factory_default: :keep do | |||
|     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 | ||||
|     let(:pipeline_arguments) do | ||||
|       { | ||||
|  |  | |||
|  | @ -149,6 +149,8 @@ RSpec.describe API::V3::Github do | |||
|     end | ||||
| 
 | ||||
|     describe 'GET events' do | ||||
|       include ProjectForksHelper | ||||
| 
 | ||||
|       let(:group) { create(:group) } | ||||
|       let(:project) { create(:project, :empty_repo, path: 'project.with.dot', group: group) } | ||||
|       let(:events_path) { "/repos/#{group.path}/#{project.path}/events" } | ||||
|  | @ -174,6 +176,34 @@ RSpec.describe API::V3::Github do | |||
|         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 | ||||
|         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) } | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue