Revert "Revert "Merge branch '18193-developers-can-merge' into 'master'
This reverts commit 530f5158e2
.
See !4892.
Signed-off-by: Rémy Coutable <remy@rymai.me>
This commit is contained in:
parent
1266e2664e
commit
2cf7f09b1e
35 changed files with 512 additions and 308 deletions
|
@ -53,6 +53,7 @@ v 8.10.0 (unreleased)
|
|||
- Add "Enabled Git access protocols" to Application Settings
|
||||
- Diffs will create button/diff form on demand no on server side
|
||||
- Reduce size of HTML used by diff comment forms
|
||||
- Protected branches have a "Developers can Merge" setting. !4892 (original implementation by Mathias Vestergaard)
|
||||
- Fix user creation with stronger minimum password requirements !4054 (nathan-pmt)
|
||||
- Only show New Snippet button to users that can create snippets.
|
||||
- PipelinesFinder uses git cache data
|
||||
|
|
|
@ -1,18 +1,18 @@
|
|||
$ ->
|
||||
$(".protected-branches-list :checkbox").change (e) ->
|
||||
name = $(this).attr("name")
|
||||
if name == "developers_can_push"
|
||||
if name == "developers_can_push" || name == "developers_can_merge"
|
||||
id = $(this).val()
|
||||
checked = $(this).is(":checked")
|
||||
can_push = $(this).is(":checked")
|
||||
url = $(this).data("url")
|
||||
$.ajax
|
||||
type: "PUT"
|
||||
type: "PATCH"
|
||||
url: url
|
||||
dataType: "json"
|
||||
data:
|
||||
id: id
|
||||
protected_branch:
|
||||
developers_can_push: checked
|
||||
"#{name}": can_push
|
||||
|
||||
success: ->
|
||||
row = $(e.target)
|
||||
|
|
|
@ -50,6 +50,6 @@ class Projects::ProtectedBranchesController < Projects::ApplicationController
|
|||
end
|
||||
|
||||
def protected_branch_params
|
||||
params.require(:protected_branch).permit(:name, :developers_can_push)
|
||||
params.require(:protected_branch).permit(:name, :developers_can_push, :developers_can_merge)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -12,7 +12,7 @@ module BranchesHelper
|
|||
def can_push_branch?(project, branch_name)
|
||||
return false unless project.repository.branch_exists?(branch_name)
|
||||
|
||||
::Gitlab::GitAccess.new(current_user, project, 'web').can_push_to_branch?(branch_name)
|
||||
::Gitlab::UserAccess.new(current_user, project: project).can_push_to_branch?(branch_name)
|
||||
end
|
||||
|
||||
def project_branches
|
||||
|
|
|
@ -552,7 +552,13 @@ class MergeRequest < ActiveRecord::Base
|
|||
end
|
||||
|
||||
def can_be_merged_by?(user)
|
||||
::Gitlab::GitAccess.new(user, project, 'web').can_push_to_branch?(target_branch)
|
||||
access = ::Gitlab::UserAccess.new(user, project: project)
|
||||
access.can_push_to_branch?(target_branch) || access.can_merge_to_branch?(target_branch)
|
||||
end
|
||||
|
||||
def can_be_merged_via_command_line_by?(user)
|
||||
access = ::Gitlab::UserAccess.new(user, project: project)
|
||||
access.can_push_to_branch?(target_branch)
|
||||
end
|
||||
|
||||
def mergeable_ci_state?
|
||||
|
|
|
@ -838,6 +838,10 @@ class Project < ActiveRecord::Base
|
|||
protected_branches.matching(branch_name).any?(&:developers_can_push)
|
||||
end
|
||||
|
||||
def developers_can_merge_to_protected_branch?(branch_name)
|
||||
protected_branches.matching(branch_name).any?(&:developers_can_merge)
|
||||
end
|
||||
|
||||
def forked?
|
||||
!(forked_project_link.nil? || forked_project_link.forked_from_project.nil?)
|
||||
end
|
||||
|
|
|
@ -769,9 +769,9 @@ class Repository
|
|||
end
|
||||
end
|
||||
|
||||
def merge(user, source_sha, target_branch, options = {})
|
||||
our_commit = rugged.branches[target_branch].target
|
||||
their_commit = rugged.lookup(source_sha)
|
||||
def merge(user, merge_request, options = {})
|
||||
our_commit = rugged.branches[merge_request.target_branch].target
|
||||
their_commit = rugged.lookup(merge_request.diff_head_sha)
|
||||
|
||||
raise "Invalid merge target" if our_commit.nil?
|
||||
raise "Invalid merge source" if their_commit.nil?
|
||||
|
@ -779,14 +779,16 @@ class Repository
|
|||
merge_index = rugged.merge_commits(our_commit, their_commit)
|
||||
return false if merge_index.conflicts?
|
||||
|
||||
commit_with_hooks(user, target_branch) do |ref|
|
||||
commit_with_hooks(user, merge_request.target_branch) do |tmp_ref|
|
||||
actual_options = options.merge(
|
||||
parents: [our_commit, their_commit],
|
||||
tree: merge_index.write_tree(rugged),
|
||||
update_ref: ref
|
||||
update_ref: tmp_ref
|
||||
)
|
||||
|
||||
Rugged::Commit.create(rugged, actual_options)
|
||||
commit_id = Rugged::Commit.create(rugged, actual_options)
|
||||
merge_request.update(in_progress_merge_commit_sha: commit_id)
|
||||
commit_id
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -23,7 +23,7 @@ module Commits
|
|||
private
|
||||
|
||||
def check_push_permissions
|
||||
allowed = ::Gitlab::GitAccess.new(current_user, project, 'web').can_push_to_branch?(@target_branch)
|
||||
allowed = ::Gitlab::UserAccess.new(current_user, project: project).can_push_to_branch?(@target_branch)
|
||||
|
||||
unless allowed
|
||||
raise ValidationError.new('You are not allowed to push into this branch')
|
||||
|
@ -31,7 +31,7 @@ module Commits
|
|||
|
||||
true
|
||||
end
|
||||
|
||||
|
||||
def create_target_branch(new_branch)
|
||||
# Temporary branch exists and contains the change commit
|
||||
return success if repository.find_branch(new_branch)
|
||||
|
|
|
@ -42,7 +42,7 @@ module Files
|
|||
end
|
||||
|
||||
def validate
|
||||
allowed = ::Gitlab::GitAccess.new(current_user, project, 'web').can_push_to_branch?(@target_branch)
|
||||
allowed = ::Gitlab::UserAccess.new(current_user, project: project).can_push_to_branch?(@target_branch)
|
||||
|
||||
unless allowed
|
||||
raise_error("You are not allowed to push into this branch")
|
||||
|
|
|
@ -89,7 +89,8 @@ class GitPushService < BaseService
|
|||
# Set protection on the default branch if configured
|
||||
if current_application_settings.default_branch_protection != PROTECTION_NONE
|
||||
developers_can_push = current_application_settings.default_branch_protection == PROTECTION_DEV_CAN_PUSH ? true : false
|
||||
@project.protected_branches.create({ name: @project.default_branch, developers_can_push: developers_can_push })
|
||||
developers_can_merge = current_application_settings.default_branch_protection == PROTECTION_DEV_CAN_MERGE ? true : false
|
||||
@project.protected_branches.create({ name: @project.default_branch, developers_can_push: developers_can_push, developers_can_merge: developers_can_merge })
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -34,7 +34,7 @@ module MergeRequests
|
|||
committer: committer
|
||||
}
|
||||
|
||||
commit_id = repository.merge(current_user, merge_request.diff_head_sha, merge_request.target_branch, options)
|
||||
commit_id = repository.merge(current_user, merge_request, options)
|
||||
merge_request.update(merge_commit_sha: commit_id)
|
||||
rescue GitHooksService::PreReceiveError => e
|
||||
merge_request.update(merge_error: e.message)
|
||||
|
@ -43,6 +43,8 @@ module MergeRequests
|
|||
merge_request.update(merge_error: "Something went wrong during merge")
|
||||
Rails.logger.error(e.message)
|
||||
false
|
||||
ensure
|
||||
merge_request.update(in_progress_merge_commit_sha: nil)
|
||||
end
|
||||
|
||||
def after_merge
|
||||
|
|
|
@ -48,7 +48,7 @@ module MergeRequests
|
|||
end
|
||||
|
||||
def force_push?
|
||||
Gitlab::ForcePushCheck.force_push?(@project, @oldrev, @newrev)
|
||||
Gitlab::Checks::ForcePush.force_push?(@project, @oldrev, @newrev)
|
||||
end
|
||||
|
||||
# Refresh merge request diff if we push to source or target branch of merge request
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
%p
|
||||
Please resolve these conflicts or
|
||||
- if @merge_request.can_be_merged_by?(current_user)
|
||||
- if @merge_request.can_be_merged_via_command_line_by?(current_user)
|
||||
#{link_to "merge this request manually", "#modal_merge_info", class: "how_to_merge_link vlink", "data-toggle" => "modal"}.
|
||||
- else
|
||||
ask someone with write access to this repository to merge this request manually.
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
.table-responsive
|
||||
%table.table.protected-branches-list
|
||||
%colgroup
|
||||
%col{ width: "20%" }
|
||||
%col{ width: "30%" }
|
||||
%col{ width: "25%" }
|
||||
%col{ width: "25%" }
|
||||
|
@ -18,6 +19,7 @@
|
|||
%th Protected Branch
|
||||
%th Commit
|
||||
%th Developers Can Push
|
||||
%th Developers Can Merge
|
||||
- if can_admin_project
|
||||
%th
|
||||
%tbody
|
||||
|
|
|
@ -16,6 +16,8 @@
|
|||
(branch was removed from repository)
|
||||
%td
|
||||
= check_box_tag("developers_can_push", protected_branch.id, protected_branch.developers_can_push, data: { url: url })
|
||||
%td
|
||||
= check_box_tag("developers_can_merge", protected_branch.id, protected_branch.developers_can_merge, data: { url: url })
|
||||
- if can_admin_project
|
||||
%td
|
||||
= link_to 'Unprotect', [@project.namespace.becomes(Namespace), @project, protected_branch], data: { confirm: 'Branch will be writable for developers. Are you sure?' }, method: :delete, class: "btn btn-warning btn-sm pull-right"
|
||||
|
|
|
@ -36,6 +36,14 @@
|
|||
= f.label :developers_can_push, "Developers can push", class: "label-light append-bottom-0"
|
||||
%p.light.append-bottom-0
|
||||
Allow developers to push to this branch
|
||||
|
||||
.form-group
|
||||
= f.check_box :developers_can_merge, class: "pull-left"
|
||||
.prepend-left-20
|
||||
= f.label :developers_can_merge, "Developers can merge", class: "label-light append-bottom-0"
|
||||
%p.light.append-bottom-0
|
||||
Allow developers to accept merge requests to this branch
|
||||
= f.submit "Protect", class: "btn-create btn protect-branch-btn", disabled: true
|
||||
|
||||
%hr
|
||||
= render "branches_list"
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
class AddDevelopersCanMergeToProtectedBranches < ActiveRecord::Migration
|
||||
include Gitlab::Database::MigrationHelpers
|
||||
|
||||
disable_ddl_transaction!
|
||||
|
||||
def change
|
||||
add_column_with_default :protected_branches, :developers_can_merge, :boolean, default: false, allow_null: false
|
||||
end
|
||||
end
|
|
@ -0,0 +1,8 @@
|
|||
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
|
||||
# for more information on how to write migrations for GitLab.
|
||||
|
||||
class AddColumnInProgressMergeCommitShaToMergeRequests < ActiveRecord::Migration
|
||||
def change
|
||||
add_column :merge_requests, :in_progress_merge_commit_sha, :string
|
||||
end
|
||||
end
|
10
db/schema.rb
10
db/schema.rb
|
@ -624,8 +624,9 @@ ActiveRecord::Schema.define(version: 20160712171823) do
|
|||
t.integer "merge_user_id"
|
||||
t.string "merge_commit_sha"
|
||||
t.datetime "deleted_at"
|
||||
t.integer "lock_version", default: 0, null: false
|
||||
t.string "in_progress_merge_commit_sha"
|
||||
end
|
||||
|
||||
add_index "merge_requests", ["assignee_id"], name: "index_merge_requests_on_assignee_id", using: :btree
|
||||
add_index "merge_requests", ["author_id"], name: "index_merge_requests_on_author_id", using: :btree
|
||||
add_index "merge_requests", ["created_at", "id"], name: "index_merge_requests_on_created_at_and_id", using: :btree
|
||||
|
@ -858,11 +859,12 @@ ActiveRecord::Schema.define(version: 20160712171823) do
|
|||
add_index "projects", ["visibility_level"], name: "index_projects_on_visibility_level", using: :btree
|
||||
|
||||
create_table "protected_branches", force: :cascade do |t|
|
||||
t.integer "project_id", null: false
|
||||
t.string "name", null: false
|
||||
t.integer "project_id", null: false
|
||||
t.string "name", null: false
|
||||
t.datetime "created_at"
|
||||
t.datetime "updated_at"
|
||||
t.boolean "developers_can_push", default: false, null: false
|
||||
t.boolean "developers_can_push", default: false, null: false
|
||||
t.boolean "developers_can_merge", default: false, null: false
|
||||
end
|
||||
|
||||
add_index "protected_branches", ["project_id"], name: "index_protected_branches_on_project_id", using: :btree
|
||||
|
|
|
@ -17,7 +17,7 @@ module API
|
|||
def current_user
|
||||
@current_user ||= (find_user_by_private_token || doorkeeper_guard)
|
||||
|
||||
unless @current_user && Gitlab::UserAccess.allowed?(@current_user)
|
||||
unless @current_user && Gitlab::UserAccess.new(@current_user).allowed?
|
||||
return nil
|
||||
end
|
||||
|
||||
|
|
|
@ -14,9 +14,10 @@ module Gitlab
|
|||
OWNER = 50
|
||||
|
||||
# Branch protection settings
|
||||
PROTECTION_NONE = 0
|
||||
PROTECTION_DEV_CAN_PUSH = 1
|
||||
PROTECTION_FULL = 2
|
||||
PROTECTION_NONE = 0
|
||||
PROTECTION_DEV_CAN_PUSH = 1
|
||||
PROTECTION_FULL = 2
|
||||
PROTECTION_DEV_CAN_MERGE = 3
|
||||
|
||||
class << self
|
||||
def values
|
||||
|
@ -54,6 +55,7 @@ module Gitlab
|
|||
def protection_options
|
||||
{
|
||||
"Not protected: Both developers and masters can push new commits, force push, or delete the branch." => PROTECTION_NONE,
|
||||
"Protected against pushes: Developers cannot push new commits, but are allowed to accept merge requests to the branch." => PROTECTION_DEV_CAN_MERGE,
|
||||
"Partially protected: Developers can push new commits, but cannot force push or delete the branch. Masters can do all of those." => PROTECTION_DEV_CAN_PUSH,
|
||||
"Fully protected: Developers cannot push new commits, force push, or delete the branch. Only masters can do any of those." => PROTECTION_FULL,
|
||||
}
|
||||
|
|
96
lib/gitlab/checks/change_access.rb
Normal file
96
lib/gitlab/checks/change_access.rb
Normal file
|
@ -0,0 +1,96 @@
|
|||
module Gitlab
|
||||
module Checks
|
||||
class ChangeAccess
|
||||
attr_reader :user_access, :project
|
||||
|
||||
def initialize(change, user_access:, project:)
|
||||
@oldrev, @newrev, @ref = change.split(' ')
|
||||
@branch_name = branch_name(@ref)
|
||||
@user_access = user_access
|
||||
@project = project
|
||||
end
|
||||
|
||||
def exec
|
||||
error = protected_branch_checks || tag_checks || push_checks
|
||||
|
||||
if error
|
||||
GitAccessStatus.new(false, error)
|
||||
else
|
||||
GitAccessStatus.new(true)
|
||||
end
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
def protected_branch_checks
|
||||
return unless project.protected_branch?(@branch_name)
|
||||
|
||||
if forced_push? && user_access.cannot_do_action?(:force_push_code_to_protected_branches)
|
||||
return "You are not allowed to force push code to a protected branch on this project."
|
||||
elsif Gitlab::Git.blank_ref?(@newrev) && user_access.cannot_do_action?(:remove_protected_branches)
|
||||
return "You are not allowed to delete protected branches from this project."
|
||||
end
|
||||
|
||||
if matching_merge_request?
|
||||
if user_access.can_merge_to_branch?(@branch_name) || user_access.can_push_to_branch?(@branch_name)
|
||||
return
|
||||
else
|
||||
"You are not allowed to merge code into protected branches on this project."
|
||||
end
|
||||
else
|
||||
if user_access.can_push_to_branch?(@branch_name)
|
||||
return
|
||||
else
|
||||
"You are not allowed to push code to protected branches on this project."
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def tag_checks
|
||||
tag_ref = tag_name(@ref)
|
||||
|
||||
if tag_ref && protected_tag?(tag_ref) && user_access.cannot_do_action?(:admin_project)
|
||||
"You are not allowed to change existing tags on this project."
|
||||
end
|
||||
end
|
||||
|
||||
def push_checks
|
||||
if user_access.cannot_do_action?(:push_code)
|
||||
"You are not allowed to push code to this project."
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def protected_tag?(tag_name)
|
||||
project.repository.tag_exists?(tag_name)
|
||||
end
|
||||
|
||||
def forced_push?
|
||||
Gitlab::Checks::ForcePush.force_push?(@project, @oldrev, @newrev)
|
||||
end
|
||||
|
||||
def matching_merge_request?
|
||||
Checks::MatchingMergeRequest.new(@newrev, @branch_name, @project).match?
|
||||
end
|
||||
|
||||
def branch_name(ref)
|
||||
ref = @ref.to_s
|
||||
if Gitlab::Git.branch_ref?(ref)
|
||||
Gitlab::Git.ref_name(ref)
|
||||
else
|
||||
nil
|
||||
end
|
||||
end
|
||||
|
||||
def tag_name(ref)
|
||||
ref = @ref.to_s
|
||||
if Gitlab::Git.tag_ref?(ref)
|
||||
Gitlab::Git.ref_name(ref)
|
||||
else
|
||||
nil
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
17
lib/gitlab/checks/force_push.rb
Normal file
17
lib/gitlab/checks/force_push.rb
Normal file
|
@ -0,0 +1,17 @@
|
|||
module Gitlab
|
||||
module Checks
|
||||
class ForcePush
|
||||
def self.force_push?(project, oldrev, newrev)
|
||||
return false if project.empty_repo?
|
||||
|
||||
# Created or deleted branch
|
||||
if Gitlab::Git.blank_ref?(oldrev) || Gitlab::Git.blank_ref?(newrev)
|
||||
false
|
||||
else
|
||||
missed_refs, _ = Gitlab::Popen.popen(%W(#{Gitlab.config.git.bin_path} --git-dir=#{project.repository.path_to_repo} rev-list #{oldrev} ^#{newrev}))
|
||||
missed_refs.split("\n").size > 0
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
18
lib/gitlab/checks/matching_merge_request.rb
Normal file
18
lib/gitlab/checks/matching_merge_request.rb
Normal file
|
@ -0,0 +1,18 @@
|
|||
module Gitlab
|
||||
module Checks
|
||||
class MatchingMergeRequest
|
||||
def initialize(newrev, branch_name, project)
|
||||
@newrev = newrev
|
||||
@branch_name = branch_name
|
||||
@project = project
|
||||
end
|
||||
|
||||
def match?
|
||||
@project.merge_requests
|
||||
.with_state(:locked)
|
||||
.where(in_progress_merge_commit_sha: @newrev, target_branch: @branch_name)
|
||||
.exists?
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,15 +0,0 @@
|
|||
module Gitlab
|
||||
class ForcePushCheck
|
||||
def self.force_push?(project, oldrev, newrev)
|
||||
return false if project.empty_repo?
|
||||
|
||||
# Created or deleted branch
|
||||
if Gitlab::Git.blank_ref?(oldrev) || Gitlab::Git.blank_ref?(newrev)
|
||||
false
|
||||
else
|
||||
missed_refs, _ = Gitlab::Popen.popen(%W(#{Gitlab.config.git.bin_path} --git-dir=#{project.repository.path_to_repo} rev-list #{oldrev} ^#{newrev}))
|
||||
missed_refs.split("\n").size > 0
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,52 +1,17 @@
|
|||
# Check a user's access to perform a git action. All public methods in this
|
||||
# class return an instance of `GitlabAccessStatus`
|
||||
module Gitlab
|
||||
class GitAccess
|
||||
DOWNLOAD_COMMANDS = %w{ git-upload-pack git-upload-archive }
|
||||
PUSH_COMMANDS = %w{ git-receive-pack }
|
||||
|
||||
attr_reader :actor, :project, :protocol
|
||||
attr_reader :actor, :project, :protocol, :user_access
|
||||
|
||||
def initialize(actor, project, protocol)
|
||||
@actor = actor
|
||||
@project = project
|
||||
@protocol = protocol
|
||||
end
|
||||
|
||||
def user
|
||||
return @user if defined?(@user)
|
||||
|
||||
@user =
|
||||
case actor
|
||||
when User
|
||||
actor
|
||||
when DeployKey
|
||||
nil
|
||||
when Key
|
||||
actor.user
|
||||
end
|
||||
end
|
||||
|
||||
def deploy_key
|
||||
actor if actor.is_a?(DeployKey)
|
||||
end
|
||||
|
||||
def can_push_to_branch?(ref)
|
||||
return false unless user
|
||||
|
||||
if project.protected_branch?(ref) && !project.developers_can_push_to_protected_branch?(ref)
|
||||
user.can?(:push_code_to_protected_branches, project)
|
||||
else
|
||||
user.can?(:push_code, project)
|
||||
end
|
||||
end
|
||||
|
||||
def can_read_project?
|
||||
if user
|
||||
user.can?(:read_project, project)
|
||||
elsif deploy_key
|
||||
deploy_key.projects.include?(project)
|
||||
else
|
||||
false
|
||||
end
|
||||
@user_access = UserAccess.new(user, project: project)
|
||||
end
|
||||
|
||||
def check(cmd, changes = nil)
|
||||
|
@ -56,11 +21,11 @@ module Gitlab
|
|||
return build_status_object(false, "No user or key was provided.")
|
||||
end
|
||||
|
||||
if user && !user_allowed?
|
||||
if user && !user_access.allowed?
|
||||
return build_status_object(false, "Your account has been blocked.")
|
||||
end
|
||||
|
||||
unless project && can_read_project?
|
||||
unless project && (user_access.can_read_project? || deploy_key_can_read_project?)
|
||||
return build_status_object(false, 'The project you were looking for could not be found.')
|
||||
end
|
||||
|
||||
|
@ -95,7 +60,7 @@ module Gitlab
|
|||
end
|
||||
|
||||
def user_download_access_check
|
||||
unless user.can?(:download_code, project)
|
||||
unless user_access.can_do_action?(:download_code)
|
||||
return build_status_object(false, "You are not allowed to download code from this project.")
|
||||
end
|
||||
|
||||
|
@ -125,46 +90,8 @@ module Gitlab
|
|||
build_status_object(true)
|
||||
end
|
||||
|
||||
def can_user_do_action?(action)
|
||||
@permission_cache ||= {}
|
||||
@permission_cache[action] ||= user.can?(action, project)
|
||||
end
|
||||
|
||||
def change_access_check(change)
|
||||
oldrev, newrev, ref = change.split(' ')
|
||||
|
||||
action =
|
||||
if project.protected_branch?(branch_name(ref))
|
||||
protected_branch_action(oldrev, newrev, branch_name(ref))
|
||||
elsif (tag_ref = tag_name(ref)) && protected_tag?(tag_ref)
|
||||
# Prevent any changes to existing git tag unless user has permissions
|
||||
:admin_project
|
||||
else
|
||||
:push_code
|
||||
end
|
||||
|
||||
unless can_user_do_action?(action)
|
||||
status =
|
||||
case action
|
||||
when :force_push_code_to_protected_branches
|
||||
build_status_object(false, "You are not allowed to force push code to a protected branch on this project.")
|
||||
when :remove_protected_branches
|
||||
build_status_object(false, "You are not allowed to deleted protected branches from this project.")
|
||||
when :push_code_to_protected_branches
|
||||
build_status_object(false, "You are not allowed to push code to protected branches on this project.")
|
||||
when :admin_project
|
||||
build_status_object(false, "You are not allowed to change existing tags on this project.")
|
||||
else # :push_code
|
||||
build_status_object(false, "You are not allowed to push code to this project.")
|
||||
end
|
||||
return status
|
||||
end
|
||||
|
||||
build_status_object(true)
|
||||
end
|
||||
|
||||
def forced_push?(oldrev, newrev)
|
||||
Gitlab::ForcePushCheck.force_push?(project, oldrev, newrev)
|
||||
Checks::ChangeAccess.new(change, user_access: user_access, project: project).exec
|
||||
end
|
||||
|
||||
def protocol_allowed?
|
||||
|
@ -173,48 +100,38 @@ module Gitlab
|
|||
|
||||
private
|
||||
|
||||
def protected_branch_action(oldrev, newrev, branch_name)
|
||||
# we dont allow force push to protected branch
|
||||
if forced_push?(oldrev, newrev)
|
||||
:force_push_code_to_protected_branches
|
||||
elsif Gitlab::Git.blank_ref?(newrev)
|
||||
# and we dont allow remove of protected branch
|
||||
:remove_protected_branches
|
||||
elsif project.developers_can_push_to_protected_branch?(branch_name)
|
||||
:push_code
|
||||
def matching_merge_request?(newrev, branch_name)
|
||||
Checks::MatchingMergeRequest.new(newrev, branch_name, project).match?
|
||||
end
|
||||
|
||||
def deploy_key
|
||||
actor if actor.is_a?(DeployKey)
|
||||
end
|
||||
|
||||
def deploy_key_can_read_project?
|
||||
if deploy_key
|
||||
deploy_key.projects.include?(project)
|
||||
else
|
||||
:push_code_to_protected_branches
|
||||
end
|
||||
end
|
||||
|
||||
def protected_tag?(tag_name)
|
||||
project.repository.tag_exists?(tag_name)
|
||||
end
|
||||
|
||||
def user_allowed?
|
||||
Gitlab::UserAccess.allowed?(user)
|
||||
end
|
||||
|
||||
def branch_name(ref)
|
||||
ref = ref.to_s
|
||||
if Gitlab::Git.branch_ref?(ref)
|
||||
Gitlab::Git.ref_name(ref)
|
||||
else
|
||||
nil
|
||||
end
|
||||
end
|
||||
|
||||
def tag_name(ref)
|
||||
ref = ref.to_s
|
||||
if Gitlab::Git.tag_ref?(ref)
|
||||
Gitlab::Git.ref_name(ref)
|
||||
else
|
||||
nil
|
||||
false
|
||||
end
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
def user
|
||||
return @user if defined?(@user)
|
||||
|
||||
@user =
|
||||
case actor
|
||||
when User
|
||||
actor
|
||||
when DeployKey
|
||||
nil
|
||||
when Key
|
||||
actor.user
|
||||
end
|
||||
end
|
||||
|
||||
def build_status_object(status, message = '')
|
||||
GitAccessStatus.new(status, message)
|
||||
end
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
module Gitlab
|
||||
class GitAccessWiki < GitAccess
|
||||
def change_access_check(change)
|
||||
if user.can?(:create_wiki, project)
|
||||
if user_access.can_do_action?(:create_wiki)
|
||||
build_status_object(true)
|
||||
else
|
||||
build_status_object(false, "You are not allowed to write to this project's wiki.")
|
||||
|
|
|
@ -1,7 +1,23 @@
|
|||
module Gitlab
|
||||
module UserAccess
|
||||
def self.allowed?(user)
|
||||
return false if user.blocked?
|
||||
class UserAccess
|
||||
attr_reader :user, :project
|
||||
|
||||
def initialize(user, project: nil)
|
||||
@user = user
|
||||
@project = project
|
||||
end
|
||||
|
||||
def can_do_action?(action)
|
||||
@permission_cache ||= {}
|
||||
@permission_cache[action] ||= user.can?(action, project)
|
||||
end
|
||||
|
||||
def cannot_do_action?(action)
|
||||
!can_do_action?(action)
|
||||
end
|
||||
|
||||
def allowed?
|
||||
return false if user.blank? || user.blocked?
|
||||
|
||||
if user.requires_ldap_check? && user.try_obtain_ldap_lease
|
||||
return false unless Gitlab::LDAP::Access.allowed?(user)
|
||||
|
@ -9,5 +25,31 @@ module Gitlab
|
|||
|
||||
true
|
||||
end
|
||||
|
||||
def can_push_to_branch?(ref)
|
||||
return false unless user
|
||||
|
||||
if project.protected_branch?(ref) && !project.developers_can_push_to_protected_branch?(ref)
|
||||
user.can?(:push_code_to_protected_branches, project)
|
||||
else
|
||||
user.can?(:push_code, project)
|
||||
end
|
||||
end
|
||||
|
||||
def can_merge_to_branch?(ref)
|
||||
return false unless user
|
||||
|
||||
if project.protected_branch?(ref) && !project.developers_can_merge_to_protected_branch?(ref)
|
||||
user.can?(:push_code_to_protected_branches, project)
|
||||
else
|
||||
user.can?(:push_code, project)
|
||||
end
|
||||
end
|
||||
|
||||
def can_read_project?
|
||||
return false unless user
|
||||
|
||||
user.can?(:read_project, project)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1639,7 +1639,8 @@ describe Gitlab::Diff::PositionTracer, lib: true do
|
|||
committer: committer
|
||||
}
|
||||
|
||||
repository.merge(current_user, second_create_file_commit.sha, branch_name, options)
|
||||
merge_request = create(:merge_request, source_branch: second_create_file_commit.sha, target_branch: branch_name, source_project: project)
|
||||
repository.merge(current_user, merge_request, options)
|
||||
project.commit(branch_name)
|
||||
end
|
||||
|
||||
|
|
|
@ -6,67 +6,6 @@ describe Gitlab::GitAccess, lib: true do
|
|||
let(:user) { create(:user) }
|
||||
let(:actor) { user }
|
||||
|
||||
describe 'can_push_to_branch?' do
|
||||
describe 'push to none protected branch' do
|
||||
it "returns true if user is a master" do
|
||||
project.team << [user, :master]
|
||||
expect(access.can_push_to_branch?("random_branch")).to be_truthy
|
||||
end
|
||||
|
||||
it "returns true if user is a developer" do
|
||||
project.team << [user, :developer]
|
||||
expect(access.can_push_to_branch?("random_branch")).to be_truthy
|
||||
end
|
||||
|
||||
it "returns false if user is a reporter" do
|
||||
project.team << [user, :reporter]
|
||||
expect(access.can_push_to_branch?("random_branch")).to be_falsey
|
||||
end
|
||||
end
|
||||
|
||||
describe 'push to protected branch' do
|
||||
before do
|
||||
@branch = create :protected_branch, project: project
|
||||
end
|
||||
|
||||
it "returns true if user is a master" do
|
||||
project.team << [user, :master]
|
||||
expect(access.can_push_to_branch?(@branch.name)).to be_truthy
|
||||
end
|
||||
|
||||
it "returns false if user is a developer" do
|
||||
project.team << [user, :developer]
|
||||
expect(access.can_push_to_branch?(@branch.name)).to be_falsey
|
||||
end
|
||||
|
||||
it "returns false if user is a reporter" do
|
||||
project.team << [user, :reporter]
|
||||
expect(access.can_push_to_branch?(@branch.name)).to be_falsey
|
||||
end
|
||||
end
|
||||
|
||||
describe 'push to protected branch if allowed for developers' do
|
||||
before do
|
||||
@branch = create :protected_branch, project: project, developers_can_push: true
|
||||
end
|
||||
|
||||
it "returns true if user is a master" do
|
||||
project.team << [user, :master]
|
||||
expect(access.can_push_to_branch?(@branch.name)).to be_truthy
|
||||
end
|
||||
|
||||
it "returns true if user is a developer" do
|
||||
project.team << [user, :developer]
|
||||
expect(access.can_push_to_branch?(@branch.name)).to be_truthy
|
||||
end
|
||||
|
||||
it "returns false if user is a reporter" do
|
||||
project.team << [user, :reporter]
|
||||
expect(access.can_push_to_branch?(@branch.name)).to be_falsey
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#check with single protocols allowed' do
|
||||
def disable_protocol(protocol)
|
||||
settings = ::ApplicationSetting.create_from_defaults
|
||||
|
@ -160,96 +99,46 @@ describe Gitlab::GitAccess, lib: true do
|
|||
end
|
||||
|
||||
describe 'push_access_check' do
|
||||
def protect_feature_branch
|
||||
create(:protected_branch, name: 'feature', project: project)
|
||||
end
|
||||
before { merge_into_protected_branch }
|
||||
let(:unprotected_branch) { FFaker::Internet.user_name }
|
||||
|
||||
def changes
|
||||
{
|
||||
push_new_branch: "#{Gitlab::Git::BLANK_SHA} 570e7b2ab refs/heads/wow",
|
||||
let(:changes) do
|
||||
{ push_new_branch: "#{Gitlab::Git::BLANK_SHA} 570e7b2ab refs/heads/wow",
|
||||
push_master: '6f6d7e7ed 570e7b2ab refs/heads/master',
|
||||
push_protected_branch: '6f6d7e7ed 570e7b2ab refs/heads/feature',
|
||||
push_remove_protected_branch: "570e7b2ab #{Gitlab::Git::BLANK_SHA} "\
|
||||
'refs/heads/feature',
|
||||
push_tag: '6f6d7e7ed 570e7b2ab refs/tags/v1.0.0',
|
||||
push_new_tag: "#{Gitlab::Git::BLANK_SHA} 570e7b2ab refs/tags/v7.8.9",
|
||||
push_all: ['6f6d7e7ed 570e7b2ab refs/heads/master', '6f6d7e7ed 570e7b2ab refs/heads/feature']
|
||||
}
|
||||
push_all: ['6f6d7e7ed 570e7b2ab refs/heads/master', '6f6d7e7ed 570e7b2ab refs/heads/feature'],
|
||||
merge_into_protected_branch: "0b4bc9a #{merge_into_protected_branch} refs/heads/feature" }
|
||||
end
|
||||
|
||||
def self.permissions_matrix
|
||||
{
|
||||
master: {
|
||||
push_new_branch: true,
|
||||
push_master: true,
|
||||
push_protected_branch: true,
|
||||
push_remove_protected_branch: false,
|
||||
push_tag: true,
|
||||
push_new_tag: true,
|
||||
push_all: true,
|
||||
},
|
||||
|
||||
developer: {
|
||||
push_new_branch: true,
|
||||
push_master: true,
|
||||
push_protected_branch: false,
|
||||
push_remove_protected_branch: false,
|
||||
push_tag: false,
|
||||
push_new_tag: true,
|
||||
push_all: false,
|
||||
},
|
||||
|
||||
reporter: {
|
||||
push_new_branch: false,
|
||||
push_master: false,
|
||||
push_protected_branch: false,
|
||||
push_remove_protected_branch: false,
|
||||
push_tag: false,
|
||||
push_new_tag: false,
|
||||
push_all: false,
|
||||
},
|
||||
|
||||
guest: {
|
||||
push_new_branch: false,
|
||||
push_master: false,
|
||||
push_protected_branch: false,
|
||||
push_remove_protected_branch: false,
|
||||
push_tag: false,
|
||||
push_new_tag: false,
|
||||
push_all: false,
|
||||
}
|
||||
}
|
||||
def stub_git_hooks
|
||||
# Running the `pre-receive` hook is expensive, and not necessary for this test.
|
||||
allow_any_instance_of(GitHooksService).to receive(:execute).and_yield
|
||||
end
|
||||
|
||||
def self.updated_permissions_matrix
|
||||
updated_permissions_matrix = permissions_matrix.dup
|
||||
updated_permissions_matrix[:developer][:push_protected_branch] = true
|
||||
updated_permissions_matrix[:developer][:push_all] = true
|
||||
updated_permissions_matrix
|
||||
end
|
||||
def merge_into_protected_branch
|
||||
@protected_branch_merge_commit ||= begin
|
||||
stub_git_hooks
|
||||
project.repository.add_branch(user, unprotected_branch, 'feature')
|
||||
target_branch = project.repository.lookup('feature')
|
||||
source_branch = project.repository.commit_file(user, FFaker::InternetSE.login_user_name, FFaker::HipsterIpsum.paragraph, FFaker::HipsterIpsum.sentence, unprotected_branch, false)
|
||||
rugged = project.repository.rugged
|
||||
author = { email: "email@example.com", time: Time.now, name: "Example Git User" }
|
||||
|
||||
permissions_matrix.keys.each do |role|
|
||||
describe "#{role} access" do
|
||||
before { protect_feature_branch }
|
||||
before { project.team << [user, role] }
|
||||
|
||||
permissions_matrix[role].each do |action, allowed|
|
||||
context action do
|
||||
subject { access.push_access_check(changes[action]) }
|
||||
|
||||
it { expect(subject.allowed?).to allowed ? be_truthy : be_falsey }
|
||||
end
|
||||
end
|
||||
merge_index = rugged.merge_commits(target_branch, source_branch)
|
||||
Rugged::Commit.create(rugged, author: author, committer: author, message: "commit message", parents: [target_branch, source_branch], tree: merge_index.write_tree(rugged))
|
||||
end
|
||||
end
|
||||
|
||||
context "with enabled developers push to protected branches " do
|
||||
updated_permissions_matrix.keys.each do |role|
|
||||
def self.run_permission_checks(permissions_matrix)
|
||||
permissions_matrix.keys.each do |role|
|
||||
describe "#{role} access" do
|
||||
before { create(:protected_branch, name: 'feature', developers_can_push: true, project: project) }
|
||||
before { project.team << [user, role] }
|
||||
|
||||
updated_permissions_matrix[role].each do |action, allowed|
|
||||
permissions_matrix[role].each do |action, allowed|
|
||||
context action do
|
||||
subject { access.push_access_check(changes[action]) }
|
||||
|
||||
|
@ -259,5 +148,97 @@ describe Gitlab::GitAccess, lib: true do
|
|||
end
|
||||
end
|
||||
end
|
||||
|
||||
permissions_matrix = {
|
||||
master: {
|
||||
push_new_branch: true,
|
||||
push_master: true,
|
||||
push_protected_branch: true,
|
||||
push_remove_protected_branch: false,
|
||||
push_tag: true,
|
||||
push_new_tag: true,
|
||||
push_all: true,
|
||||
merge_into_protected_branch: true
|
||||
},
|
||||
|
||||
developer: {
|
||||
push_new_branch: true,
|
||||
push_master: true,
|
||||
push_protected_branch: false,
|
||||
push_remove_protected_branch: false,
|
||||
push_tag: false,
|
||||
push_new_tag: true,
|
||||
push_all: false,
|
||||
merge_into_protected_branch: false
|
||||
},
|
||||
|
||||
reporter: {
|
||||
push_new_branch: false,
|
||||
push_master: false,
|
||||
push_protected_branch: false,
|
||||
push_remove_protected_branch: false,
|
||||
push_tag: false,
|
||||
push_new_tag: false,
|
||||
push_all: false,
|
||||
merge_into_protected_branch: false
|
||||
},
|
||||
|
||||
guest: {
|
||||
push_new_branch: false,
|
||||
push_master: false,
|
||||
push_protected_branch: false,
|
||||
push_remove_protected_branch: false,
|
||||
push_tag: false,
|
||||
push_new_tag: false,
|
||||
push_all: false,
|
||||
merge_into_protected_branch: false
|
||||
}
|
||||
}
|
||||
|
||||
[['feature', 'exact'], ['feat*', 'wildcard']].each do |protected_branch_name, protected_branch_type|
|
||||
context do
|
||||
before { create(:protected_branch, name: protected_branch_name, project: project) }
|
||||
|
||||
run_permission_checks(permissions_matrix)
|
||||
end
|
||||
|
||||
context "when 'developers can push' is turned on for the #{protected_branch_type} protected branch" do
|
||||
before { create(:protected_branch, name: protected_branch_name, developers_can_push: true, project: project) }
|
||||
|
||||
run_permission_checks(permissions_matrix.deep_merge(developer: { push_protected_branch: true, push_all: true, merge_into_protected_branch: true }))
|
||||
end
|
||||
|
||||
context "when 'developers can merge' is turned on for the #{protected_branch_type} protected branch" do
|
||||
before { create(:protected_branch, name: protected_branch_name, developers_can_merge: true, project: project) }
|
||||
|
||||
context "when a merge request exists for the given source/target branch" do
|
||||
context "when the merge request is in progress" do
|
||||
before do
|
||||
create(:merge_request, source_project: project, source_branch: unprotected_branch, target_branch: 'feature', state: 'locked', in_progress_merge_commit_sha: merge_into_protected_branch)
|
||||
end
|
||||
|
||||
run_permission_checks(permissions_matrix.deep_merge(developer: { merge_into_protected_branch: true }))
|
||||
end
|
||||
|
||||
context "when the merge request is not in progress" do
|
||||
before do
|
||||
create(:merge_request, source_project: project, source_branch: unprotected_branch, target_branch: 'feature', in_progress_merge_commit_sha: nil)
|
||||
end
|
||||
|
||||
run_permission_checks(permissions_matrix.deep_merge(developer: { merge_into_protected_branch: false }))
|
||||
end
|
||||
end
|
||||
|
||||
context "when a merge request does not exist for the given source/target branch" do
|
||||
run_permission_checks(permissions_matrix.deep_merge(developer: { merge_into_protected_branch: false }))
|
||||
end
|
||||
end
|
||||
|
||||
context "when 'developers can merge' and 'developers can push' are turned on for the #{protected_branch_type} protected branch" do
|
||||
before { create(:protected_branch, name: protected_branch_name, developers_can_merge: true, developers_can_push: true, project: project) }
|
||||
|
||||
run_permission_checks(permissions_matrix.deep_merge(developer: { push_protected_branch: true, push_all: true, merge_into_protected_branch: true }))
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
88
spec/lib/gitlab/user_access_spec.rb
Normal file
88
spec/lib/gitlab/user_access_spec.rb
Normal file
|
@ -0,0 +1,88 @@
|
|||
require 'spec_helper'
|
||||
|
||||
describe Gitlab::UserAccess, lib: true do
|
||||
let(:access) { Gitlab::UserAccess.new(user, project: project) }
|
||||
let(:project) { create(:project) }
|
||||
let(:user) { create(:user) }
|
||||
|
||||
describe 'can_push_to_branch?' do
|
||||
describe 'push to none protected branch' do
|
||||
it 'returns true if user is a master' do
|
||||
project.team << [user, :master]
|
||||
expect(access.can_push_to_branch?('random_branch')).to be_truthy
|
||||
end
|
||||
|
||||
it 'returns true if user is a developer' do
|
||||
project.team << [user, :developer]
|
||||
expect(access.can_push_to_branch?('random_branch')).to be_truthy
|
||||
end
|
||||
|
||||
it 'returns false if user is a reporter' do
|
||||
project.team << [user, :reporter]
|
||||
expect(access.can_push_to_branch?('random_branch')).to be_falsey
|
||||
end
|
||||
end
|
||||
|
||||
describe 'push to protected branch' do
|
||||
let(:branch) { create :protected_branch, project: project }
|
||||
|
||||
it 'returns true if user is a master' do
|
||||
project.team << [user, :master]
|
||||
expect(access.can_push_to_branch?(branch.name)).to be_truthy
|
||||
end
|
||||
|
||||
it 'returns false if user is a developer' do
|
||||
project.team << [user, :developer]
|
||||
expect(access.can_push_to_branch?(branch.name)).to be_falsey
|
||||
end
|
||||
|
||||
it 'returns false if user is a reporter' do
|
||||
project.team << [user, :reporter]
|
||||
expect(access.can_push_to_branch?(branch.name)).to be_falsey
|
||||
end
|
||||
end
|
||||
|
||||
describe 'push to protected branch if allowed for developers' do
|
||||
before do
|
||||
@branch = create :protected_branch, project: project, developers_can_push: true
|
||||
end
|
||||
|
||||
it 'returns true if user is a master' do
|
||||
project.team << [user, :master]
|
||||
expect(access.can_push_to_branch?(@branch.name)).to be_truthy
|
||||
end
|
||||
|
||||
it 'returns true if user is a developer' do
|
||||
project.team << [user, :developer]
|
||||
expect(access.can_push_to_branch?(@branch.name)).to be_truthy
|
||||
end
|
||||
|
||||
it 'returns false if user is a reporter' do
|
||||
project.team << [user, :reporter]
|
||||
expect(access.can_push_to_branch?(@branch.name)).to be_falsey
|
||||
end
|
||||
end
|
||||
|
||||
describe 'merge to protected branch if allowed for developers' do
|
||||
before do
|
||||
@branch = create :protected_branch, project: project, developers_can_merge: true
|
||||
end
|
||||
|
||||
it 'returns true if user is a master' do
|
||||
project.team << [user, :master]
|
||||
expect(access.can_merge_to_branch?(@branch.name)).to be_truthy
|
||||
end
|
||||
|
||||
it 'returns true if user is a developer' do
|
||||
project.team << [user, :developer]
|
||||
expect(access.can_merge_to_branch?(@branch.name)).to be_truthy
|
||||
end
|
||||
|
||||
it 'returns false if user is a reporter' do
|
||||
project.team << [user, :reporter]
|
||||
expect(access.can_merge_to_branch?(@branch.name)).to be_falsey
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
end
|
|
@ -4,16 +4,17 @@ describe Repository, models: true do
|
|||
include RepoHelpers
|
||||
TestBlob = Struct.new(:name)
|
||||
|
||||
let(:repository) { create(:project).repository }
|
||||
let(:project) { create(:project) }
|
||||
let(:repository) { project.repository }
|
||||
let(:user) { create(:user) }
|
||||
let(:commit_options) do
|
||||
author = repository.user_to_committer(user)
|
||||
{ message: 'Test message', committer: author, author: author }
|
||||
end
|
||||
let(:merge_commit) do
|
||||
source_sha = repository.find_branch('feature').target
|
||||
merge_commit_sha = repository.merge(user, source_sha, 'master', commit_options)
|
||||
repository.commit(merge_commit_sha)
|
||||
merge_request = create(:merge_request, source_branch: 'feature', target_branch: 'master', source_project: project)
|
||||
merge_commit_id = repository.merge(user, merge_request, commit_options)
|
||||
repository.commit(merge_commit_id)
|
||||
end
|
||||
|
||||
describe '#branch_names_contains' do
|
||||
|
|
|
@ -49,7 +49,7 @@ describe API::Helpers, api: true do
|
|||
|
||||
it "should return nil for a user without access" do
|
||||
env[API::Helpers::PRIVATE_TOKEN_HEADER] = user.private_token
|
||||
allow(Gitlab::UserAccess).to receive(:allowed?).and_return(false)
|
||||
allow_any_instance_of(Gitlab::UserAccess).to receive(:allowed?).and_return(false)
|
||||
expect(current_user).to be_nil
|
||||
end
|
||||
|
||||
|
@ -73,7 +73,7 @@ describe API::Helpers, api: true do
|
|||
|
||||
it "should return nil for a user without access" do
|
||||
env[API::Helpers::PRIVATE_TOKEN_HEADER] = personal_access_token.token
|
||||
allow(Gitlab::UserAccess).to receive(:allowed?).and_return(false)
|
||||
allow_any_instance_of(Gitlab::UserAccess).to receive(:allowed?).and_return(false)
|
||||
expect(current_user).to be_nil
|
||||
end
|
||||
|
||||
|
|
|
@ -224,7 +224,7 @@ describe GitPushService, services: true do
|
|||
it "when pushing a branch for the first time" do
|
||||
expect(project).to receive(:execute_hooks)
|
||||
expect(project.default_branch).to eq("master")
|
||||
expect(project.protected_branches).to receive(:create).with({ name: "master", developers_can_push: false })
|
||||
expect(project.protected_branches).to receive(:create).with({ name: "master", developers_can_push: false, developers_can_merge: false })
|
||||
execute_service(project, user, @blankrev, 'newrev', 'refs/heads/master' )
|
||||
end
|
||||
|
||||
|
@ -242,7 +242,17 @@ describe GitPushService, services: true do
|
|||
|
||||
expect(project).to receive(:execute_hooks)
|
||||
expect(project.default_branch).to eq("master")
|
||||
expect(project.protected_branches).to receive(:create).with({ name: "master", developers_can_push: true })
|
||||
expect(project.protected_branches).to receive(:create).with({ name: "master", developers_can_push: true, developers_can_merge: false })
|
||||
|
||||
execute_service(project, user, @blankrev, 'newrev', 'refs/heads/master')
|
||||
end
|
||||
|
||||
it "when pushing a branch for the first time with default branch protection set to 'developers can merge'" do
|
||||
stub_application_setting(default_branch_protection: Gitlab::Access::PROTECTION_DEV_CAN_MERGE)
|
||||
|
||||
expect(project).to receive(:execute_hooks)
|
||||
expect(project.default_branch).to eq("master")
|
||||
expect(project.protected_branches).to receive(:create).with({ name: "master", developers_can_push: false, developers_can_merge: true })
|
||||
execute_service(project, user, @blankrev, 'newrev', 'refs/heads/master' )
|
||||
end
|
||||
|
||||
|
|
|
@ -88,8 +88,7 @@ describe MergeRequests::RefreshService, services: true do
|
|||
# Merge master -> feature branch
|
||||
author = { email: 'test@gitlab.com', time: Time.now, name: "Me" }
|
||||
commit_options = { message: 'Test message', committer: author, author: author }
|
||||
master_commit = @project.repository.commit('master')
|
||||
@project.repository.merge(@user, master_commit.id, 'feature', commit_options)
|
||||
@project.repository.merge(@user, @merge_request, commit_options)
|
||||
commit = @project.repository.commit('feature')
|
||||
service.new(@project, @user).execute(@oldrev, commit.id, 'refs/heads/feature')
|
||||
reload_mrs
|
||||
|
|
Loading…
Reference in a new issue