Commit ca09a858 authored by Nick Thomas's avatar Nick Thomas

Add namespace license checks for squash before merge

parent ad8e7eb1
......@@ -18,7 +18,8 @@ export default class MergeRequestStore extends CEMergeRequestStore {
initSquashBeforeMerge(data) {
this.squashBeforeMergeHelpPath = this.squashBeforeMergeHelpPath
|| data.squash_before_merge_help_path;
this.enableSquashBeforeMerge = true;
this.enableSquashBeforeMerge = this.enableSquashBeforeMerge
|| data.enable_squash_before_merge;
}
initRebase(data) {
......
......@@ -69,7 +69,10 @@ module EE
end
def merge_params_attributes
super + [:squash]
attrs = super
attrs << :squash if project.feature_available?(:merge_request_squash)
attrs
end
def merge_request_params
......@@ -77,12 +80,14 @@ module EE
end
def merge_request_params_attributes
super + %i[
approvals_before_merge
approver_group_ids
approver_ids
squash
]
attrs = super.push(
:approvals_before_merge,
:approver_group_ids,
:approver_ids
)
attrs << :squash if project.feature_available?(:merge_request_squash)
attrs
end
# If the number of approvals is not greater than the project default, set to
......
......@@ -45,5 +45,10 @@ module EE
true
end
end
def squash
super && project.feature_available?(:merge_request_squash)
end
alias_method :squash?, :squash
end
end
......@@ -11,6 +11,7 @@ class License < ActiveRecord::Base
RELATED_ISSUES_FEATURE = 'RelatedIssues'.freeze
EXPORT_ISSUES_FEATURE = 'GitLab_ExportIssues'.freeze
MERGE_REQUEST_REBASE_FEATURE = 'GitLab_MergeRequestRebase'.freeze
MERGE_REQUEST_SQUASH_FEATURE = 'GitLab_MergeRequestSquash'.freeze
FEATURE_CODES = {
geo: GEO_FEATURE,
......@@ -23,7 +24,8 @@ class License < ActiveRecord::Base
deploy_board: DEPLOY_BOARD_FEATURE,
file_lock: FILE_LOCK_FEATURE,
export_issues: EXPORT_ISSUES_FEATURE,
merge_request_rebase: MERGE_REQUEST_REBASE_FEATURE
merge_request_rebase: MERGE_REQUEST_REBASE_FEATURE,
merge_request_squash: MERGE_REQUEST_SQUASH_FEATURE
}.freeze
STARTER_PLAN = 'starter'.freeze
......@@ -35,7 +37,8 @@ class License < ActiveRecord::Base
{ ELASTIC_SEARCH_FEATURE => 1 },
{ RELATED_ISSUES_FEATURE => 1 },
{ EXPORT_ISSUES_FEATURE => 1 },
{ MERGE_REQUEST_REBASE_FEATURE => 1 }
{ MERGE_REQUEST_REBASE_FEATURE => 1 },
{ MERGE_REQUEST_SQUASH_FEATURE => 1 }
].freeze
EEP_FEATURES = [
......@@ -69,7 +72,8 @@ class License < ActiveRecord::Base
{ SERVICE_DESK_FEATURE => 1 },
{ OBJECT_STORAGE_FEATURE => 1 },
{ EXPORT_ISSUES_FEATURE => 1 },
{ MERGE_REQUEST_REBASE_FEATURE => 1 }
{ MERGE_REQUEST_REBASE_FEATURE => 1 },
{ MERGE_REQUEST_SQUASH_FEATURE => 1 }
].freeze
FEATURES_BY_PLAN = {
......
......@@ -17,6 +17,10 @@ module MergeRequests
return success(squash_sha: merge_request.diff_head_sha)
end
unless project.feature_available?(:merge_request_squash)
return error('License does not allow squashing')
end
if merge_request.squash_in_progress?
return error('Squash task canceled: another squash is already in progress.')
end
......
......@@ -23,6 +23,7 @@
// Object.assign would be useful here, but it blows up Phantom.js in tests
window.gl.mrWidgetData.is_geo_secondary_node = '#{Gitlab::Geo.secondary?}' === 'true';
window.gl.mrWidgetData.geo_secondary_help_path = '#{help_page_path("/gitlab-geo/configuration.md")}';
window.gl.mrWidgetData.enable_squash_before_merge = '#{@merge_request.project.feature_available?(:merge_request_squash)}' === 'true';
window.gl.mrWidgetData.squash_before_merge_help_path = '#{help_page_path("user/project/merge_requests/squash_and_merge")}';
#js-vue-mr-widget.mr-widget
......
- issuable = local_assigns.fetch(:issuable)
- return unless issuable.project.feature_available?(:merge_request_squash)
.form-group
.col-sm-10.col-sm-offset-2
.checkbox
......
---
title: Add namespace license checks for squash before merge
merge_request: 2249
author:
......@@ -363,7 +363,8 @@ module API
expose :approvals_before_merge
expose :should_remove_source_branch?, as: :should_remove_source_branch
expose :force_remove_source_branch?, as: :force_remove_source_branch
expose :squash
expose :squash, if: -> (mr, _) { mr.project.feature_available?(:merge_request_squash) }
expose :web_url do |merge_request, options|
Gitlab::UrlBuilder.build(merge_request)
......
......@@ -232,7 +232,7 @@ module API
render_api_error!("SHA does not match HEAD of source branch: #{merge_request.diff_head_sha}", 409)
end
if params[:squash]
if params[:squash] && merge_request.project.feature_available?(:merge_request_squash)
merge_request.update(squash: params[:squash])
end
......
......@@ -160,7 +160,8 @@ module API
expose :approvals_before_merge
expose :should_remove_source_branch?, as: :should_remove_source_branch
expose :force_remove_source_branch?, as: :force_remove_source_branch
expose :squash
expose :squash, if: ->(mr, _) { mr.project.feature_available?(:merge_request_squash) }
expose :web_url do |merge_request, options|
Gitlab::UrlBuilder.build(merge_request)
......
......@@ -209,7 +209,7 @@ module API
render_api_error!("SHA does not match HEAD of source branch: #{merge_request.diff_head_sha}", 409)
end
if params[:squash]
if params[:squash] && merge_request.project.feature_available?(:merge_request_squash)
merge_request.update(squash: params[:squash])
end
......
......@@ -121,4 +121,24 @@ feature 'Squashing merge requests', js: true, feature: true do
include_examples 'no squash'
end
end
context 'squash is unlicensed' do
let(:merge_request) { create(:merge_request, source_project: project, target_project: project, source_branch: source_branch, target_branch: 'master', squash: true) }
before do
stub_licensed_features(merge_request_squash: false)
end
it 'does not show squash option when creating MR' do
visit new_namespace_project_merge_request_path(project.namespace, project, merge_request: { target_branch: 'master', source_branch: source_branch })
expect(page).to have_no_field('merge_request[squash]')
end
it 'does not show squash option when viewing MR' do
visit namespace_project_merge_request_path(project.namespace, project, merge_request)
expect(page).to have_no_field('squash')
end
end
end
......@@ -90,4 +90,41 @@ describe MergeRequest, models: true do
expect(subject.squash_in_progress?).to be_falsey
end
end
describe '#squash?' do
let(:merge_request) { build(:merge_request, squash: squash) }
subject { merge_request.squash? }
context 'unlicensed' do
before do
stub_licensed_features(merge_request_squash: false)
end
context 'disabled in database' do
let(:squash) { false }
it { is_expected.to be_falsy }
end
context 'enabled in database' do
let(:squash) { true }
it { is_expected.to be_falsy }
end
end
context 'licensed' do
context 'disabled in database' do
let(:squash) { false }
it { is_expected.to be_falsy }
end
context 'licensed' do
let(:squash) { true }
it { is_expected.to be_truthy }
end
end
end
end
......@@ -96,6 +96,16 @@ describe MergeRequests::SquashService do
include_examples 'the squash succeeds'
end
context 'squashing is unlicensed' do
before do
stub_licensed_features(merge_request_squash: false)
end
subject { service.execute(merge_request_with_only_new_files) }
it { is_expected.to match(status: :error, message: a_string_including('License')) }
end
stages = {
'add worktree for squash' => 'worktree',
'configure sparse checkout' => 'config',
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment