diff --git a/app/helpers/routing/projects_helper.rb b/app/helpers/routing/projects_helper.rb index 9b4aafe49b4..89536b9760d 100644 --- a/app/helpers/routing/projects_helper.rb +++ b/app/helpers/routing/projects_helper.rb @@ -35,6 +35,11 @@ module Routing end def issue_url(entity, *args) + # TODO: we do not have a route to access group level work items yet. + # That is to be done as part of view group level work item issue: + # see https://gitlab.com/gitlab-org/gitlab/-/work_items/393987 + return unless entity.project.present? + if use_work_items_path?(entity) work_item_url(entity, *args) else diff --git a/doc/ci/mobile_devops.md b/doc/ci/mobile_devops.md index 6969b3d4ef4..3c6052d8a3e 100644 --- a/doc/ci/mobile_devops.md +++ b/doc/ci/mobile_devops.md @@ -189,8 +189,7 @@ fastlane init ``` This command creates a `fastlane` folder in the project with an `Appfile` and a stubbed-out `fastfile`. -This process asks you for login credentials to App Store Connect -to generate an app identifier and App Store app if they don't already exist. +During this process, you are prompted for App Store Connect login credentials to generate an app identifier and an App Store app if they don't already exist. The next step sets up fastlane match to manage code signing files for the project. Run the following command to generate a `Matchfile` with the configuration: diff --git a/doc/development/internal_api/index.md b/doc/development/internal_api/index.md index 538b66124ba..b83ed3d49bd 100644 --- a/doc/development/internal_api/index.md +++ b/doc/development/internal_api/index.md @@ -1365,7 +1365,7 @@ Example request: ```shell curl --verbose --request PATCH "https://gitlab.example.com/api/scim/v2/groups/test_group/Users/f0b1d561c-21ff-4092-beab-8154b17f82f2" \ - --data '{ "Operations": [{"op":"Update","path":"name.formatted","value":"New Name"}] }' \ + --data '{ "Operations": [{"op":"replace","path":"id","value":"1234abcd"}] }' \ --header "Authorization: Bearer " --header "Content-Type: application/scim+json" ``` diff --git a/doc/policy/experiment-beta-support.md b/doc/policy/experiment-beta-support.md index 68cc96f118b..a327baa3132 100644 --- a/doc/policy/experiment-beta-support.md +++ b/doc/policy/experiment-beta-support.md @@ -20,7 +20,7 @@ Support is not provided for features listed as "Experimental" or "Alpha" or any - Can be removed at any time. - Data loss may occur. - Documentation may not exist or just be in a blog format. -- Offer an easy way to choose to opt-in to experimental features with minimal friction. For example, needing to flip a feature flag is too much friction, but a group or project-level setting that is in the UI is not. +- Offer a way to opt-in with minimal friction. For example, needing to flip a feature flag is too much friction, but a group or project-level setting in the UI is not. - Link out to the [GitLab Testing Agreement](https://about.gitlab.com/handbook/legal/testing-agreement/) in the opt-in. - Documentation reflects that the feature is subject to the [GitLab Testing Agreement](https://about.gitlab.com/handbook/legal/testing-agreement/). - [UI reflects experiment status](https://design.gitlab.com/usability/feature-management#highlighting-feature-versions). diff --git a/doc/user/project/merge_requests/reviews/img/suggested_reviewers_v15_9.png b/doc/user/project/merge_requests/reviews/img/suggested_reviewers_v15_9.png deleted file mode 100644 index 70db0d79eaf..00000000000 Binary files a/doc/user/project/merge_requests/reviews/img/suggested_reviewers_v15_9.png and /dev/null differ diff --git a/doc/user/project/merge_requests/reviews/img/suggested_reviewers_v16_3.png b/doc/user/project/merge_requests/reviews/img/suggested_reviewers_v16_3.png new file mode 100644 index 00000000000..9c3ecebd395 Binary files /dev/null and b/doc/user/project/merge_requests/reviews/img/suggested_reviewers_v16_3.png differ diff --git a/doc/user/project/merge_requests/reviews/index.md b/doc/user/project/merge_requests/reviews/index.md index e4882134654..0d74108c3b1 100644 --- a/doc/user/project/merge_requests/reviews/index.md +++ b/doc/user/project/merge_requests/reviews/index.md @@ -27,9 +27,16 @@ For an overview, see [Merge request review](https://www.youtube.com/watch?v=2May > - [Enabled on GitLab.com](https://gitlab.com/gitlab-org/gitlab/-/issues/368356) in GitLab 15.6. > - Beta designation [removed from the UI](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/113058) in GitLab 15.10. -GitLab can suggest reviewers. Using the changes in a merge request and a project's contribution graph, machine learning suggestions appear in the reviewer section of the right sidebar. +GitLab uses machine learning to suggest reviewers for your merge request. -![Suggested Reviewers](img/suggested_reviewers_v15_9.png) +To suggest reviewers, GitLab uses: + +- The changes in the merge request +- The project's contribution graph + +Suggested Reviewers also integrates with Code Owners, profile status, and merge request rules, helping you make a more informed decision when choosing reviewers that can meet your review criteria. + +![Suggested Reviewers](img/suggested_reviewers_v16_3.png) For more information, see [Data usage in Suggested Reviewers](data_usage.md). diff --git a/lib/gitlab/content_security_policy/config_loader.rb b/lib/gitlab/content_security_policy/config_loader.rb index 9fb3c7d362f..59a4e425b85 100644 --- a/lib/gitlab/content_security_policy/config_loader.rb +++ b/lib/gitlab/content_security_policy/config_loader.rb @@ -84,7 +84,7 @@ module Gitlab end def allow_lfs(directives) - return unless Gitlab.config.lfs.enabled && LfsObjectUploader.direct_download_enabled? + return unless Gitlab.config.lfs.enabled && LfsObjectUploader.object_store_enabled? && LfsObjectUploader.direct_download_enabled? lfs_url = build_lfs_url return unless lfs_url.present? diff --git a/lib/quality/seeders/issues.rb b/lib/quality/seeders/issues.rb index d43b91167ef..813ff0bf097 100644 --- a/lib/quality/seeders/issues.rb +++ b/lib/quality/seeders/issues.rb @@ -1,7 +1,5 @@ # frozen_string_literal: true -require './spec/support/sidekiq_middleware' - # rubocop:disable CodeReuse/ActiveRecord module Quality module Seeders @@ -85,7 +83,7 @@ module Quality 3.times do |i| params = { project: project, - title: "Sprint #{i}", + title: "Sprint #{i + suffix}", description: FFaker::Lorem.sentence, state: [:active, :closed].sample } diff --git a/spec/factories/issues.rb b/spec/factories/issues.rb index 3f17d4d5a97..b0db17875c5 100644 --- a/spec/factories/issues.rb +++ b/spec/factories/issues.rb @@ -65,6 +65,12 @@ FactoryBot.define do end end + trait :group_level do + project { nil } + association :namespace, factory: :group + association :author, factory: :user + end + trait :issue do association :work_item_type, :default, :issue end diff --git a/spec/lib/gitlab/content_security_policy/config_loader_spec.rb b/spec/lib/gitlab/content_security_policy/config_loader_spec.rb index dd633820ad9..6d24ced138e 100644 --- a/spec/lib/gitlab/content_security_policy/config_loader_spec.rb +++ b/spec/lib/gitlab/content_security_policy/config_loader_spec.rb @@ -205,6 +205,24 @@ RSpec.describe Gitlab::ContentSecurityPolicy::ConfigLoader, feature_category: :s context 'when LFS is enabled' do let(:lfs_enabled) { true } + context 'and object storage is not in use' do + let(:lfs_config) do + { + enabled: false, + remote_directory: 'lfs-objects', + connection: {}, + direct_upload: false, + proxy_download: true, + storage_options: {} + } + end + + it 'is expected to be skipped' do + expect(described_class.send(:allow_lfs, directives)).to be_nil + expect(connect_src).not_to include('lfs-objects') + end + end + context 'and direct downloads are enabled' do let(:provider) { LfsObjectUploader.object_store_options.connection.provider } diff --git a/spec/lib/gitlab/gitaly_client/operation_service_spec.rb b/spec/lib/gitlab/gitaly_client/operation_service_spec.rb index 9055b284119..bd0341d51bf 100644 --- a/spec/lib/gitlab/gitaly_client/operation_service_spec.rb +++ b/spec/lib/gitlab/gitaly_client/operation_service_spec.rb @@ -567,20 +567,58 @@ RSpec.describe Gitlab::GitalyClient::OperationService, feature_category: :source end end - describe '#user_cherry_pick' do + describe '#user_cherry_pick', :freeze_time do let(:response_class) { Gitaly::UserCherryPickResponse } + let(:sha) { '54cec5282aa9f21856362fe321c800c236a61615' } + let(:branch_name) { 'master' } + let(:cherry_pick_message) { 'Cherry-pick message' } + let(:time) { Time.now.utc } + + let(:branch_update) do + Gitaly::OperationBranchUpdate.new( + commit_id: sha, + repo_created: false, + branch_created: false + ) + end + + let(:request) do + Gitaly::UserCherryPickRequest.new( + repository: repository.gitaly_repository, + user: gitaly_user, + commit: repository.commit.to_gitaly_commit, + branch_name: branch_name, + start_branch_name: branch_name, + start_repository: repository.gitaly_repository, + message: cherry_pick_message, + timestamp: Google::Protobuf::Timestamp.new(seconds: time.to_i) + ) + end + + let(:response) { Gitaly::UserCherryPickResponse.new(branch_update: branch_update) } subject do client.user_cherry_pick( user: user, commit: repository.commit, - branch_name: 'master', - message: 'Cherry-pick message', - start_branch_name: 'master', + branch_name: branch_name, + message: cherry_pick_message, + start_branch_name: branch_name, start_repository: repository ) end + it 'sends a user_cherry_pick message and returns a BranchUpdate' do + expect_any_instance_of(Gitaly::OperationService::Stub) + .to receive(:user_cherry_pick).with(request, kind_of(Hash)) + .and_return(response) + + expect(subject).to be_a(Gitlab::Git::OperationService::BranchUpdate) + expect(subject.newrev).to be_present + expect(subject.repo_created).to be(false) + expect(subject.branch_created).to be(false) + end + context 'when AccessCheckError is raised' do let(:raised_error) do new_detailed_error( @@ -641,27 +679,68 @@ RSpec.describe Gitlab::GitalyClient::OperationService, feature_category: :source end end - describe '#user_revert' do - let(:response_class) { Gitaly::UserRevertResponse } + describe '#user_revert', :freeze_time do + let(:sha) { '54cec5282aa9f21856362fe321c800c236a61615' } + let(:branch_name) { 'master' } + let(:revert_message) { 'revert message' } + let(:time) { Time.now.utc } + + let(:branch_update) do + Gitaly::OperationBranchUpdate.new( + commit_id: sha, + repo_created: false, + branch_created: false + ) + end + + let(:request) do + Gitaly::UserRevertRequest.new( + repository: repository.gitaly_repository, + user: gitaly_user, + commit: repository.commit.to_gitaly_commit, + branch_name: branch_name, + start_branch_name: branch_name, + start_repository: repository.gitaly_repository, + message: revert_message, + timestamp: Google::Protobuf::Timestamp.new(seconds: time.to_i) + ) + end + + let(:response) { Gitaly::UserRevertResponse.new(branch_update: branch_update) } subject do client.user_revert( user: user, commit: repository.commit, - branch_name: 'master', - message: 'Revert message', - start_branch_name: 'master', + branch_name: branch_name, + message: revert_message, + start_branch_name: branch_name, start_repository: repository ) end - before do + it 'sends a user_revert message and returns a BranchUpdate' do expect_any_instance_of(Gitaly::OperationService::Stub) - .to receive(:user_revert).with(kind_of(Gitaly::UserRevertRequest), kind_of(Hash)) - .and_return(response) + .to receive(:user_revert).with(request, kind_of(Hash)) + .and_return(response) + + expect(subject).to be_a(Gitlab::Git::OperationService::BranchUpdate) + expect(subject.newrev).to be_present + expect(subject.repo_created).to be(false) + expect(subject.branch_created).to be(false) end - it_behaves_like 'cherry pick and revert errors' + context 'when errors are raised' do + let(:response_class) { Gitaly::UserRevertResponse } + + before do + expect_any_instance_of(Gitaly::OperationService::Stub) + .to receive(:user_revert).with(kind_of(Gitaly::UserRevertRequest), kind_of(Hash)) + .and_return(response) + end + + it_behaves_like 'cherry pick and revert errors' + end end describe '#rebase' do