Add latest changes from gitlab-org/gitlab@master

This commit is contained in:
GitLab Bot 2024-04-15 09:13:39 +00:00
parent d9dc7ffa36
commit f3b97b325b
31 changed files with 346 additions and 92 deletions

View File

@ -1235,8 +1235,18 @@ class MergeRequest < ApplicationRecord
alias_method :wip_title, :draft_title
def skipped_mergeable_checks(options = {})
merge_when_checks_pass_strat = options[:auto_merge_strategy] == ::AutoMergeService::STRATEGY_MERGE_WHEN_CHECKS_PASS
skip_additional_checks = merge_when_checks_pass_strat &&
::Feature.enabled?(:additional_merge_when_checks_ready, project)
{
skip_ci_check: options.fetch(:auto_merge_requested, false)
skip_ci_check: options.fetch(:auto_merge_requested, false),
skip_approved_check: merge_when_checks_pass_strat,
skip_draft_check: skip_additional_checks,
skip_blocked_check: skip_additional_checks,
skip_discussions_check: skip_additional_checks,
skip_external_status_check: skip_additional_checks
}
end
@ -1285,31 +1295,28 @@ class MergeRequest < ApplicationRecord
# skip_approved_check
# skip_blocked_check
# skip_external_status_check
def mergeable_state?(**mergeable_state_check_params)
additional_checks = execute_merge_checks(
self.class.mergeable_state_checks,
params: mergeable_state_check_params
)
additional_checks.success?
def mergeable_state?(**params)
results = check_mergeability_states(checks: self.class.mergeable_state_checks, **params)
results.success?
end
def mergeable_git_state?(skip_rebase_check: false)
checks = execute_merge_checks(
self.class.mergeable_git_state_checks,
params: {
skip_rebase_check: skip_rebase_check
}
)
# This runs only git related checks
def mergeable_git_state?(**params)
results = check_mergeability_states(checks: self.class.mergeable_git_state_checks, **params)
checks.success?
results.success?
end
# This runs all the checks
def mergeability_checks_pass?(**params)
results = check_mergeability_states(checks: self.class.all_mergeability_checks, **params)
results.success?
end
def all_mergeability_checks_results
execute_merge_checks(
self.class.all_mergeability_checks,
params: {},
execute_all: true
).payload[:results]
check_mergeability_states(checks: self.class.all_mergeability_checks, execute_all: true).payload[:results]
end
def ff_merge_possible?
@ -2241,6 +2248,14 @@ class MergeRequest < ApplicationRecord
)
end
def check_mergeability_states(checks:, execute_all: false, **params)
execute_merge_checks(
checks,
params: params,
execute_all: execute_all
)
end
def merge_base_pipelines
return ::Ci::Pipeline.none unless diff_head_pipeline&.target_sha

View File

@ -58,16 +58,29 @@ module AutoMerge
def available_for?(merge_request)
strong_memoize("available_for_#{merge_request.id}") do
merge_request.can_be_merged_by?(current_user) &&
merge_request.open? &&
!merge_request.broken? &&
overrideable_available_for_checks(merge_request) &&
yield
if Feature.enabled?(:refactor_auto_merge, merge_request.project, type: :gitlab_com_derisk)
merge_request.can_be_merged_by?(current_user) &&
merge_request.mergeability_checks_pass?(**skippable_available_for_checks(merge_request)) &&
yield
else
merge_request.can_be_merged_by?(current_user) &&
merge_request.open? &&
!merge_request.broken? &&
overrideable_available_for_checks(merge_request) &&
yield
end
end
end
private
def skippable_available_for_checks(merge_request)
merge_request.skipped_mergeable_checks(
auto_merge_requested: true,
auto_merge_strategy: strategy
)
end
def overrideable_available_for_checks(merge_request)
!merge_request.draft? &&
merge_request.mergeable_discussions_state? &&

View File

@ -34,7 +34,7 @@ module AutoMerge
def available_for?(merge_request)
super do
check_availability(merge_request)
merge_request.auto_merge_available_when_pipeline_succeeds?
end
end
@ -44,10 +44,6 @@ module AutoMerge
SystemNoteService.merge_when_pipeline_succeeds(merge_request, project, current_user, merge_request.diff_head_pipeline.sha) if merge_request.saved_change_to_auto_merge_enabled?
end
def check_availability(merge_request)
merge_request.auto_merge_available_when_pipeline_succeeds?
end
def notify(merge_request)
notification_service.async.merge_when_pipeline_succeeds(merge_request, current_user) if merge_request.saved_change_to_auto_merge_enabled?
end

View File

@ -4,6 +4,8 @@ class AutoMergeService < BaseService
include Gitlab::Utils::StrongMemoize
STRATEGY_MERGE_WHEN_PIPELINE_SUCCEEDS = 'merge_when_pipeline_succeeds'
# Currently only EE but will be moved to CE in (https://gitlab.com/gitlab-org/gitlab/-/merge_requests/146730)
STRATEGY_MERGE_WHEN_CHECKS_PASS = 'merge_when_checks_pass'
STRATEGIES = [STRATEGY_MERGE_WHEN_PIPELINE_SUCCEEDS].freeze
class << self

View File

@ -7,16 +7,16 @@
= yield
- else
- grouped_emojis = awardable.grouped_awards(with_thumbs: inline)
.awards.js-awards-block{ class: ("hidden" if !inline && grouped_emojis.empty?), data: { award_url: toggle_award_url(awardable) } }
.awards.js-awards-block.gl-gap-3.gl-py-2{ class: ("hidden" if !inline && grouped_emojis.empty?), data: { award_url: toggle_award_url(awardable) } }
- awards_sort(grouped_emojis).each do |emoji, awards|
= render Pajamas::ButtonComponent.new(button_options: { class: (award_state_class(awardable, awards, current_user) + ' award-control js-emoji-btn has-tooltip'), data: { title: award_user_list(awards, current_user) } }) do
= render Pajamas::ButtonComponent.new(button_options: { class: (award_state_class(awardable, awards, current_user) + ' js-emoji-btn has-tooltip'), data: { title: award_user_list(awards, current_user) } }) do
= emoji_icon(emoji)
%span.award-control-text.js-counter
= awards.count
- if can?(current_user, :award_emoji, awardable)
.award-menu-holder.js-award-holder
= render Pajamas::ButtonComponent.new(button_options: { class: 'add-reaction-button award-control has-tooltip js-add-award btn-icon gl-relative', data: { title: _('Add reaction') }, aria: { label: _('Add reaction') } }) do
= render Pajamas::ButtonComponent.new(button_options: { class: 'add-reaction-button has-tooltip js-add-award btn-icon gl-relative', data: { title: _('Add reaction') }, aria: { label: _('Add reaction') } }) do
= sprite_icon('slight-smile', css_class: 'reaction-control-icon-neutral award-control-icon-neutral gl-button-icon gl-icon')
= sprite_icon('smiley', css_class: 'reaction-control-icon-positive award-control-icon-positive gl-button-icon gl-icon !gl-left-3')
= sprite_icon('smile', css_class: 'reaction-control-icon-super-positive award-control-icon-super-positive gl-button-icon gl-icon !gl-left-3')

View File

@ -0,0 +1,9 @@
---
name: refactor_auto_merge
feature_issue_url: https://gitlab.com/groups/gitlab-org/-/epics/10874
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/146153
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/443872
milestone: '16.11'
group: group::code review
type: gitlab_com_derisk
default_enabled: false

View File

@ -1,6 +1,6 @@
---
migration_job_name: BackfillArchivedAndTraversalIdsToVulnerabilityReads
description: Backfill project.archived and project.namespace.traversal_ids values to the denormalized columns of the same name on vulnerability_reads
description: Backfill project.archived and project.namespace.traversal_ids values to the denormalized columns of the same name on vulnerability_reads. No-oped and requeued in job RequeueBackfillArchivedAndTraversalIdsToVulnerabilityReads.
feature_category: vulnerability_management
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/144765
milestone: '16.10'

View File

@ -0,0 +1,9 @@
---
migration_job_name: RequeueBackfillArchivedAndTraversalIdsToVulnerabilityReads
description: Backfill project.archived and project.namespace.traversal_ids values to the denormalized columns of the same name on vulnerability_reads.
feature_category: vulnerability_management
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/144765
milestone: '16.11'
queued_migration_version: 20240409140739
finalize_after: '2024-03-15'
finalized_by: # version of the migration that finalized this BBM

View File

@ -11,17 +11,10 @@ class QueueBackfillArchivedAndTraversalIdsToVulnerabilityReads < Gitlab::Databas
SUB_BATCH_SIZE = 100
def up
queue_batched_background_migration(
MIGRATION,
:vulnerability_reads,
:id,
job_interval: DELAY_INTERVAL,
batch_size: BATCH_SIZE,
sub_batch_size: SUB_BATCH_SIZE
)
# no-op
end
def down
delete_batched_background_migration(MIGRATION, :vulnerability_reads, :id, [])
# no-op
end
end

View File

@ -0,0 +1,30 @@
# frozen_string_literal: true
class RequeueBackfillArchivedAndTraversalIdsToVulnerabilityReads < Gitlab::Database::Migration[2.2]
milestone '16.11'
restrict_gitlab_migration gitlab_schema: :gitlab_main
MIGRATION = "BackfillArchivedAndTraversalIdsToVulnerabilityReads"
DELAY_INTERVAL = 2.minutes
BATCH_SIZE = 10_000
SUB_BATCH_SIZE = 100
def up
# Clear previous background migration execution from QueueBackfillArchivedAndTraversalIdsToVulnerabilityReads
delete_batched_background_migration(MIGRATION, :vulnerability_reads, :id, [])
queue_batched_background_migration(
MIGRATION,
:vulnerability_reads,
:id,
job_interval: DELAY_INTERVAL,
batch_size: BATCH_SIZE,
sub_batch_size: SUB_BATCH_SIZE
)
end
def down
delete_batched_background_migration(MIGRATION, :vulnerability_reads, :id, [])
end
end

View File

@ -0,0 +1 @@
70e1cc677a0f2548bced6a430437e961e4e75ea6965a434427c4c653a50ffd0c

View File

@ -1740,6 +1740,15 @@ For status, choose one:
Generally available features should not have a status.
##### GitLab Duo Pro add-on
The add-on belongs with other subscription tiers. Document it by using the phrase `with GitLab Duo Pro`.
For example:
```markdown
**Tier:** Premium or Ultimate with GitLab Duo Pro
```
##### Duplicating tier, offering, or status on subheadings
If a subheading has the same tier, offering, or status as its parent

View File

@ -71,8 +71,8 @@ To enable Beta and Experimental AI-powered features for GitLab versions where Gi
- To use an HTTP/S proxy, both `gitLab_workhorse` and `gitLab_rails` must have the necessary
[web proxy environment variables](https://docs.gitlab.com/omnibus/settings/environment-variables.html) set.
- Check for restrictions on WebSocket (`wss://`) traffic to `wss://gitlab.com/-/cable` and other `.com` domains.
Network policy restrictions on `wss://` traffic can cause issues with some GitLab Duo
chat services. Consider policy updates to allow these services.
Network policy restrictions on `wss://` traffic can cause issues with some GitLab Duo Chat
services. Consider policy updates to allow these services.
### Disable GitLab Duo features for specific groups or projects or an entire instance

View File

@ -7,8 +7,8 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# Code Suggestions data usage
DETAILS:
**Tier:** Premium, Ultimate
**Offering:** GitLab.com, Self-managed, GitLab Dedicated. GitLab Duo Pro required.
**Tier:** Premium or Ultimate with GitLab Duo Pro
**Offering:** GitLab.com, Self-managed, GitLab Dedicated
Code Suggestions is powered by a generative AI model.

View File

@ -7,8 +7,8 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# Code Suggestions
DETAILS:
**Tier:** Premium, Ultimate
**Offering:** GitLab.com, Self-managed, GitLab Dedicated. GitLab Duo Pro required.
**Tier:** Premium or Ultimate with GitLab Duo Pro
**Offering:** GitLab.com, Self-managed, GitLab Dedicated
> - [Introduced support for Google Vertex AI Codey APIs](https://gitlab.com/groups/gitlab-org/-/epics/10562) in GitLab 16.1.
> - [Removed support for GitLab native model](https://gitlab.com/groups/gitlab-org/-/epics/10752) in GitLab 16.2.

View File

@ -7,8 +7,8 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# Supported extensions and languages
DETAILS:
**Tier:** Premium, Ultimate
**Offering:** GitLab.com, Self-managed, GitLab Dedicated. GitLab Duo Pro required.
**Tier:** Premium or Ultimate with GitLab Duo Pro
**Offering:** GitLab.com, Self-managed, GitLab Dedicated
Code Suggestions is available in the following editor extensions and
for the following languages.

View File

@ -7,8 +7,8 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# Troubleshooting Code Suggestions
DETAILS:
**Tier:** Premium, Ultimate
**Offering:** GitLab.com, Self-managed, GitLab Dedicated. GitLab Duo Pro required.
**Tier:** Premium or Ultimate with GitLab Duo Pro
**Offering:** GitLab.com, Self-managed, GitLab Dedicated
When working with GitLab Duo Code Suggestions, you might encounter the following issues.

View File

@ -14,7 +14,7 @@ module Gitlab
token = audit_event.details[:runner_registration_token]
name = "Registration token: #{token}"
else
raise ArgumentError, 'Runner token missing'
name = "Token not available"
end
super(id: -1, name: name)

View File

@ -15,7 +15,7 @@ module QA
# this file path deliberately includes a subdirectory which matches the file name to verify file/dir matching logic
let(:file_path) { CGI.escape("føo/#{file_name}/føo/#{file_name}") }
it 'user creates a project with a file and deletes them afterwards', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347745' do
it 'user creates a project with a file and deletes them afterwards', :blocking, testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347745' do
create_project_request = Runtime::API::Request.new(@api_client, '/projects')
post create_project_request.url, path: project_name, name: project_name

View File

@ -11,7 +11,7 @@ module QA
end
context 'when branch name contains slash, hash, double dash, and capital letter' do
it 'renders repository file tree correctly', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347715' do
it 'renders repository file tree correctly', :blocking, testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347715' do
create(:commit,
project: project,
branch: branch_name,

View File

@ -2,7 +2,7 @@
module QA
RSpec.describe 'Create', product_group: :source_code do
describe 'Snippet index page' do
describe 'Snippet index page', :blocking do
let(:personal_snippet_with_single_file) do
create(:snippet, title: "Personal snippet with one file-#{SecureRandom.hex(8)}")
end

View File

@ -10,7 +10,7 @@ module QA
Flow::Login.sign_in
end
it 'can preview markdown side-by-side while editing',
it 'can preview markdown side-by-side while editing', :blocking,
testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/367749' do
project.visit!
Page::Project::Show.perform do |project|

View File

@ -30,10 +30,12 @@ RSpec.describe 'Merge request > User resolves Draft', :js, feature_category: :co
end
context 'when there is active pipeline for merge request' do
before do
create(:ci_build, pipeline: pipeline)
let(:feature_flags_state) { true }
stub_feature_flags(merge_blocked_component: false)
before do
stub_feature_flags(merge_when_checks_pass: feature_flags_state, merge_blocked_component: feature_flags_state)
create(:ci_build, pipeline: pipeline)
sign_in(user)
visit project_merge_request_path(project, merge_request)
@ -41,8 +43,17 @@ RSpec.describe 'Merge request > User resolves Draft', :js, feature_category: :co
end
it 'retains merge request data after clicking Resolve WIP status' do
# rubocop:disable RSpec/AvoidConditionalStatements -- remove when Auto merge goes to Foss
# https://gitlab.com/gitlab-org/gitlab/-/merge_requests/146730
expected_message = if Gitlab.ee?
"Set to auto-merge"
else
"Merge blocked:"
end
# rubocop:enable RSpec/AvoidConditionalStatements
expect(page.find('.ci-widget-content')).to have_content("Pipeline ##{pipeline.id}")
expect(page).to have_content "Merge blocked: Select Mark as ready to remove it from Draft status."
expect(page).to have_content expected_message
page.within('.mr-state-widget') do
click_button('Mark as ready')
@ -54,7 +65,28 @@ RSpec.describe 'Merge request > User resolves Draft', :js, feature_category: :co
# merge request widget refreshes, which masks missing elements
# that should already be present.
expect(page.find('.ci-widget-content', wait: 0)).to have_content("Pipeline ##{pipeline.id}")
expect(page).not_to have_content("Merge blocked: Select Mark as ready to remove it from Draft status.")
expect(page).to have_content("Set to auto-merge")
end
context 'when the new merge_when_checks_pass and merge blocked components are disabled' do
let(:feature_flags_state) { false }
it 'retains merge request data after clicking Resolve WIP status' do
expect(page.find('.ci-widget-content')).to have_content("Pipeline ##{pipeline.id}")
expect(page).to have_content "Merge blocked: Select Mark as ready to remove it from Draft status."
page.within('.mr-state-widget') do
click_button('Mark as ready')
end
wait_for_requests
# If we don't disable the wait here, the test will wait until the
# merge request widget refreshes, which masks missing elements
# that should already be present.
expect(page.find('.ci-widget-content', wait: 0)).to have_content("Pipeline ##{pipeline.id}")
expect(page).not_to have_content("Merge blocked")
end
end
end
end

View File

@ -331,12 +331,31 @@ RSpec.describe 'Merge request > User sees merge widget', :js, feature_category:
visit project_merge_request_path(project_only_mwps, merge_request_in_only_mwps_project)
end
it 'is allowed to merge' do
# Wait for the `ci_status` and `merge_check` requests
wait_for_requests
context 'when using merge when pipeline succeeds' do
before do
stub_feature_flags(merge_when_checks_pass: false)
end
expect(page).not_to have_selector('.accept-merge-request')
it 'is not allowed to merge' do
# Wait for the `ci_status` and `merge_check` requests
wait_for_requests
expect(page).not_to have_selector('.accept-merge-request')
end
end
# TODO When moving merge when checks pass to FOSS
# context 'when using merge when checks pass' do
# before do
# stub_feature_flags(merge_when_checks_pass: true)
# end
#
# it 'is not allowed to set auto merge' do
# # Wait for the `ci_status` and `merge_check` requests
# wait_for_requests
#
# expect(page).to have_selector('.accept-merge-request')
# end
# end
end
context 'view merge request with MWPS enabled but automatically merge fails' do

View File

@ -34,8 +34,8 @@ RSpec.describe Gitlab::Audit::CiRunnerTokenAuthor do
{}
end
it 'raises ArgumentError' do
expect { subject }.to raise_error ArgumentError, 'Runner token missing'
it 'returns token not available' do
is_expected.to have_attributes(id: -1, name: 'Token not available')
end
end
end

View File

@ -6,20 +6,14 @@ require_migration!
RSpec.describe QueueBackfillArchivedAndTraversalIdsToVulnerabilityReads, feature_category: :vulnerability_management do
let!(:batched_migration) { described_class::MIGRATION }
it 'schedules a new batched migration' do
it 'does not schedule a new batched migration' do
reversible_migration do |migration|
migration.before -> {
expect(batched_migration).not_to have_scheduled_batched_migration
}
migration.after -> {
expect(batched_migration).to have_scheduled_batched_migration(
table_name: :vulnerability_reads,
column_name: :id,
interval: described_class::DELAY_INTERVAL,
batch_size: described_class::BATCH_SIZE,
sub_batch_size: described_class::SUB_BATCH_SIZE
)
expect(batched_migration).not_to have_scheduled_batched_migration
}
end
end

View File

@ -0,0 +1,26 @@
# frozen_string_literal: true
require 'spec_helper'
require_migration!
RSpec.describe RequeueBackfillArchivedAndTraversalIdsToVulnerabilityReads, feature_category: :vulnerability_management do
let!(:batched_migration) { described_class::MIGRATION }
it 'schedules a new batched migration' do
reversible_migration do |migration|
migration.before -> {
expect(batched_migration).not_to have_scheduled_batched_migration
}
migration.after -> {
expect(batched_migration).to have_scheduled_batched_migration(
table_name: :vulnerability_reads,
column_name: :id,
interval: described_class::DELAY_INTERVAL,
batch_size: described_class::BATCH_SIZE,
sub_batch_size: described_class::SUB_BATCH_SIZE
)
}
end
end
end

View File

@ -3660,15 +3660,40 @@ RSpec.describe MergeRequest, factory_default: :keep, feature_category: :code_rev
describe '#skipped_mergeable_checks' do
subject { build_stubbed(:merge_request).skipped_mergeable_checks(options) }
let(:feature_flag) { true }
before do
stub_feature_flags(additional_merge_when_checks_ready: feature_flag)
end
where(:options, :skip_ci_check) do
{} | false
{ auto_merge_requested: false } | false
{ auto_merge_requested: true } | true
end
with_them do
it { is_expected.to include(skip_ci_check: skip_ci_check) }
end
context 'when auto_merge_requested is true' do
let(:options) { { auto_merge_requested: true, auto_merge_strategy: auto_merge_strategy } }
where(:auto_merge_strategy, :skip_approved_check, :skip_draft_check, :skip_blocked_check,
:skip_discussions_check, :skip_external_status_check, :feature_flag) do
'' | false | false | false | false | false | true
AutoMergeService::STRATEGY_MERGE_WHEN_PIPELINE_SUCCEEDS | false | false | false | false | false | true
AutoMergeService::STRATEGY_MERGE_WHEN_CHECKS_PASS | true | true | true | true | true | true
AutoMergeService::STRATEGY_MERGE_WHEN_CHECKS_PASS | true | false | false | false | false | false
end
with_them do
it do
is_expected.to include(skip_approved_check: skip_approved_check, skip_draft_check: skip_draft_check,
skip_blocked_check: skip_blocked_check, skip_discussions_check: skip_discussions_check,
skip_external_status_check: skip_external_status_check)
end
end
end
end
describe '#check_mergeability' do
@ -6285,6 +6310,26 @@ RSpec.describe MergeRequest, factory_default: :keep, feature_category: :code_rev
end
end
describe '#mergeability_checks_pass?' do
let(:merge_request) { build_stubbed(:merge_request) }
let(:result) { instance_double(ServiceResponse, success?: { results: ['result'] }) }
it 'executes MergeRequests::Mergeability::RunChecksService with all mergeability checks and returns a boolean' do
expect_next_instance_of(
MergeRequests::Mergeability::RunChecksService,
merge_request: merge_request,
params: {}
) do |svc|
expect(svc)
.to receive(:execute)
.with(described_class.all_mergeability_checks, execute_all: false)
.and_return(result)
end
expect(merge_request.mergeability_checks_pass?).to be_truthy
end
end
describe '#only_allow_merge_if_pipeline_succeeds?' do
let(:merge_request) { build_stubbed(:merge_request) }

View File

@ -305,22 +305,65 @@ RSpec.describe AutoMerge::BaseService, feature_category: :code_review_workflow d
describe '#available_for?' do
using RSpec::Parameterized::TableSyntax
subject(:available_for) { service.available_for?(merge_request) { true } }
subject(:available_for) { service.available_for?(merge_request) { yield_result } }
let(:merge_request) { create(:merge_request) }
let(:yield_result) { true }
let(:checks_pass) { true }
let(:can_be_merged) { true }
where(:can_be_merged, :open, :broken, :discussions, :blocked, :draft, :result) do
true | true | false | true | false | false | true
false | true | false | true | false | false | false
true | false | false | true | false | false | false
true | true | true | true | false | false | false
true | true | false | false | false | false | false
true | true | false | true | true | false | false
true | true | false | true | false | true | false
context 'when can_be_merged is true' do
before do
allow(merge_request).to receive(:can_be_merged_by?).and_return(can_be_merged)
allow(merge_request).to receive(:mergeability_checks_pass?).and_return(checks_pass)
end
context 'when the mergeabilty checks pass is true' do
context 'when the yield is true' do
it 'returns true' do
expect(available_for).to be_truthy
end
end
context 'when the yield is false' do
let(:yield_result) { false }
it 'returns false' do
expect(available_for).to be_falsey
end
end
end
context 'when the mergeabilty checks pass is false' do
let(:checks_pass) { false }
context 'when the yield is true' do
it 'returns false' do
expect(available_for).to be_falsey
end
end
context 'when the yield is false' do
let(:yield_result) { false }
it 'returns false' do
expect(available_for).to be_falsey
end
end
end
end
with_them do
context 'when can_be_merged is false' do
let(:can_be_merged) { false }
it 'returns false' do
expect(available_for).to be_falsey
end
end
context 'when refactor_auto_merge is disabled' do
before do
stub_feature_flags(refactor_auto_merge: false)
allow(merge_request).to receive(:can_be_merged_by?).and_return(can_be_merged)
allow(merge_request).to receive(:open?).and_return(open)
allow(merge_request).to receive(:broken?).and_return(broken)
@ -329,8 +372,20 @@ RSpec.describe AutoMerge::BaseService, feature_category: :code_review_workflow d
allow(merge_request).to receive(:merge_blocked_by_other_mrs?).and_return(blocked)
end
it 'returns the expected results' do
expect(available_for).to eq(result)
where(:can_be_merged, :open, :broken, :discussions, :blocked, :draft, :result) do
true | true | false | true | false | false | true
false | true | false | true | false | false | false
true | false | false | true | false | false | false
true | true | true | true | false | false | false
true | true | false | false | false | false | false
true | true | false | true | true | false | false
true | true | false | true | false | true | false
end
with_them do
it 'returns the expected results' do
expect(available_for).to eq(result)
end
end
end
end

View File

@ -102,7 +102,7 @@ RSpec.describe MergeRequests::MergeOrchestrationService, feature_category: :code
context 'when merge request is not mergeable' do
before do
allow(merge_request).to receive(:mergeable?) { false }
merge_request.update!(merge_status: 'cannot_be_merged')
end
it { is_expected.to eq(false) }

View File

@ -553,7 +553,13 @@ RSpec.describe MergeRequests::UpdateService, :mailer, feature_category: :code_re
head_pipeline_of: merge_request
)
expect(AutoMerge::MergeWhenPipelineSucceedsService).to receive(:new).with(project, user, { sha: merge_request.diff_head_sha })
expected_class = if Gitlab.ee?
AutoMerge::MergeWhenChecksPassService
else
AutoMerge::MergeWhenPipelineSucceedsService
end
expect(expected_class).to receive(:new).with(project, user, { sha: merge_request.diff_head_sha })
.and_return(service_mock)
allow(service_mock).to receive(:available_for?) { true }
expect(service_mock).to receive(:execute).with(merge_request)