Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
G
gitlab-ce
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Boxiang Sun
gitlab-ce
Commits
2f048df4
Commit
2f048df4
authored
Nov 18, 2015
by
Zeger-Jan van de Weg
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
API support, incorporated feedback
parent
63b23470
Changes
15
Show whitespace changes
Inline
Side-by-side
Showing
15 changed files
with
157 additions
and
63 deletions
+157
-63
app/controllers/projects/merge_requests_controller.rb
app/controllers/projects/merge_requests_controller.rb
+1
-3
app/models/commit_status.rb
app/models/commit_status.rb
+1
-1
app/models/merge_request.rb
app/models/merge_request.rb
+5
-1
app/services/merge_requests/merge_service.rb
app/services/merge_requests/merge_service.rb
+9
-7
app/services/merge_requests/merge_when_build_succeeds_service.rb
...vices/merge_requests/merge_when_build_succeeds_service.rb
+1
-1
app/services/merge_requests/refresh_service.rb
app/services/merge_requests/refresh_service.rb
+1
-3
app/services/system_note_service.rb
app/services/system_note_service.rb
+1
-1
app/views/projects/merge_requests/widget/open/_accept.html.haml
...ews/projects/merge_requests/widget/open/_accept.html.haml
+1
-1
app/views/projects/merge_requests/widget/open/_merge_when_build_succeeds.html.haml
...requests/widget/open/_merge_when_build_succeeds.html.haml
+4
-4
app/workers/merge_worker.rb
app/workers/merge_worker.rb
+2
-11
config/routes.rb
config/routes.rb
+1
-2
doc/api/merge_requests.md
doc/api/merge_requests.md
+55
-5
lib/api/merge_requests.rb
lib/api/merge_requests.rb
+46
-22
spec/models/merge_request_spec.rb
spec/models/merge_request_spec.rb
+13
-1
spec/services/system_note_service_spec.rb
spec/services/system_note_service_spec.rb
+16
-0
No files found.
app/controllers/projects/merge_requests_controller.rb
View file @
2f048df4
...
@@ -171,9 +171,7 @@ class Projects::MergeRequestsController < Projects::ApplicationController
...
@@ -171,9 +171,7 @@ class Projects::MergeRequestsController < Projects::ApplicationController
@merge_request
.
update
(
merge_error:
nil
)
@merge_request
.
update
(
merge_error:
nil
)
if
params
[
:merge_when_build_succeeds
]
&&
@merge_request
.
ci_commit
.
active?
if
params
[
:merge_when_build_succeeds
]
&&
@merge_request
.
ci_commit
.
active?
MergeRequests
::
MergeWhenBuildSucceedsService
.
new
(
@project
,
MergeRequests
::
MergeWhenBuildSucceedsService
.
new
(
@project
,
current_user
,
merge_params
)
current_user
,
merge_params:
merge_params
)
.
execute
(
@merge_request
)
.
execute
(
@merge_request
)
@status
=
:merge_when_build_succeeds
@status
=
:merge_when_build_succeeds
else
else
...
...
app/models/commit_status.rb
View file @
2f048df4
...
@@ -75,7 +75,7 @@ class CommitStatus < ActiveRecord::Base
...
@@ -75,7 +75,7 @@ class CommitStatus < ActiveRecord::Base
build
.
update_attributes
finished_at:
Time
.
now
build
.
update_attributes
finished_at:
Time
.
now
end
end
after_transition
running:
:success
do
|
build
,
transition
|
after_transition
[
:pending
,
:running
]
=>
:success
do
|
build
,
transition
|
MergeRequests
::
MergeWhenBuildSucceedsService
.
new
(
build
.
commit
.
gl_project
,
nil
).
trigger
(
build
)
MergeRequests
::
MergeWhenBuildSucceedsService
.
new
(
build
.
commit
.
gl_project
,
nil
).
trigger
(
build
)
end
end
...
...
app/models/merge_request.rb
View file @
2f048df4
...
@@ -253,6 +253,10 @@ class MergeRequest < ActiveRecord::Base
...
@@ -253,6 +253,10 @@ class MergeRequest < ActiveRecord::Base
end
end
end
end
def
mergeable_by_or_author
(
user
)
self
.
can_be_merged_by?
(
user
)
||
self
.
author
==
user
end
def
mr_and_commit_notes
def
mr_and_commit_notes
# Fetch comments only from last 100 commits
# Fetch comments only from last 100 commits
commits_for_notes_limit
=
100
commits_for_notes_limit
=
100
...
...
app/services/merge_requests/merge_service.rb
View file @
2f048df4
...
@@ -6,15 +6,12 @@ module MergeRequests
...
@@ -6,15 +6,12 @@ module MergeRequests
# Executed when you do merge via GitLab UI
# Executed when you do merge via GitLab UI
#
#
class
MergeService
<
MergeRequests
::
BaseService
class
MergeService
<
MergeRequests
::
BaseService
attr_reader
:merge_request
,
:commit_message
attr_reader
:merge_request
def
execute
(
merge_request
,
commit_message
)
def
execute
(
merge_request
)
@commit_message
=
commit_message
@merge_request
=
merge_request
@merge_request
=
merge_request
unless
@merge_request
.
mergeable?
return
error
(
'Merge request is not mergeable'
)
unless
@merge_request
.
mergeable?
return
error
(
'Merge request is not mergeable'
)
end
merge_request
.
in_locked_state
do
merge_request
.
in_locked_state
do
if
commit
if
commit
...
@@ -32,7 +29,7 @@ module MergeRequests
...
@@ -32,7 +29,7 @@ module MergeRequests
committer
=
repository
.
user_to_committer
(
current_user
)
committer
=
repository
.
user_to_committer
(
current_user
)
options
=
{
options
=
{
message:
commit_message
,
message:
params
[
:commit_message
]
||
merge_request
.
merge_
commit_message
,
author:
committer
,
author:
committer
,
committer:
committer
committer:
committer
}
}
...
@@ -46,6 +43,11 @@ module MergeRequests
...
@@ -46,6 +43,11 @@ module MergeRequests
def
after_merge
def
after_merge
MergeRequests
::
PostMergeService
.
new
(
project
,
current_user
).
execute
(
merge_request
)
MergeRequests
::
PostMergeService
.
new
(
project
,
current_user
).
execute
(
merge_request
)
if
params
[
:should_remove_source_branch
]
DeleteBranchService
.
new
(
@merge_request
.
source_project
,
current_user
).
execute
(
merge_request
.
source_branch
)
end
end
end
end
end
end
end
app/services/merge_requests/merge_when_build_succeeds_service.rb
View file @
2f048df4
module
MergeRequests
module
MergeRequests
class
MergeWhenBuildSucceedsService
<
MergeRequests
::
BaseService
class
MergeWhenBuildSucceedsService
<
MergeRequests
::
BaseService
def
execute
(
merge_request
)
def
execute
(
merge_request
)
merge_request
.
merge_params
.
merge!
(
params
[
:merge_params
]
)
merge_request
.
merge_params
.
merge!
(
params
)
# The service is also called when the merge params are updated.
# The service is also called when the merge params are updated.
already_approved
=
merge_request
.
merge_when_build_succeeds?
already_approved
=
merge_request
.
merge_when_build_succeeds?
...
...
app/services/merge_requests/refresh_service.rb
View file @
2f048df4
...
@@ -77,9 +77,7 @@ module MergeRequests
...
@@ -77,9 +77,7 @@ module MergeRequests
end
end
def
reset_merge_when_build_succeeds
def
reset_merge_when_build_succeeds
merge_requests_for_source_branch
.
each
do
|
merge_request
|
merge_requests_for_source_branch
.
each
(
&
:reset_merge_when_build_succeeds
)
merge_request
.
reset_merge_when_build_succeeds
end
end
end
def
find_new_commits
def
find_new_commits
...
...
app/services/system_note_service.rb
View file @
2f048df4
...
@@ -132,7 +132,7 @@ class SystemNoteService
...
@@ -132,7 +132,7 @@ class SystemNoteService
# Called when 'merge when build succeeds' is executed
# Called when 'merge when build succeeds' is executed
def
self
.
merge_when_build_succeeds
(
noteable
,
project
,
author
)
def
self
.
merge_when_build_succeeds
(
noteable
,
project
,
author
)
body
=
"
Approved this request to be merged automatically when the build
succeeds"
body
=
"
This merge request will be automatically merged when the build for
#{
noteable
.
ci_commit
.
short_sha
}
succeeds"
create_note
(
noteable:
noteable
,
project:
project
,
author:
author
,
note:
body
)
create_note
(
noteable:
noteable
,
project:
project
,
author:
author
,
note:
body
)
end
end
...
...
app/views/projects/merge_requests/widget/open/_accept.html.haml
View file @
2f048df4
...
@@ -29,5 +29,5 @@
...
@@ -29,5 +29,5 @@
$('.accept_merge_request').on 'click', ->
$('.accept_merge_request').on 'click', ->
btn = $(this)
btn = $(this)
btn.html("<i class='fa fa-spinner fa-spin'></i> Merge in progress")
btn.html("<i class='fa fa-spinner fa-spin'></i> Merge in progress")
$('.accept-mr-form').on 'ajax:sen', ->
$('.accept-mr-form').on 'ajax:sen
d
', ->
$(".accept-mr-form :input").disable()
$(".accept-mr-form :input").disable()
app/views/projects/merge_requests/widget/open/_merge_when_build_succeeds.html.haml
View file @
2f048df4
%h4
%h4
Approved by
#{
link_to_member
(
@project
,
@merge_request
.
merge_user
,
avatar:
true
)
}
Approved by
#{
link_to_member
(
@project
,
@merge_request
.
merge_user
,
avatar:
true
)
}
to be merged automatically when
to be merged automatically when
#{
link_to
"the build"
,
ci_status_path
(
@merge_request
.
ci_commit
)
}
succeeds
#{
link_to
"the build"
,
ci_status_path
(
@merge_request
.
ci_commit
)
}
succeeds
.
%div
%div
-
if
@merge_request
.
merge_params
[
"should_remove_source_branch"
]
-
if
@merge_request
.
merge_params
[
"should_remove_source_branch"
]
.
present?
=
succeed
'.'
do
=
succeed
'.'
do
The changes will be merged into
The changes will be merged into
%span
.label-branch
=
@merge_request
.
target_branch
%span
.label-branch
=
@merge_request
.
target_branch
...
@@ -19,9 +19,9 @@
...
@@ -19,9 +19,9 @@
-
if
remove_source_branch_button
||
@merge_request
.
can_be_merged_by?
(
current_user
)
-
if
remove_source_branch_button
||
@merge_request
.
can_be_merged_by?
(
current_user
)
.clearfix.prepend-top-10
.clearfix.prepend-top-10
-
if
remove_source_branch_button
-
if
remove_source_branch_button
=
link_to
merge_namespace_project_merge_request_path
(
@merge_request
.
source_project
.
namespace
,
@merge_request
.
source
_project
,
@merge_request
,
merge_when_build_succeeds:
true
,
should_remove_source_branch:
true
),
remote:
true
,
method: :post
,
class:
"btn btn-grouped btn-primary btn-sm remove_source_branch"
do
=
link_to
merge_namespace_project_merge_request_path
(
@merge_request
.
target_project
.
namespace
,
@merge_request
.
target
_project
,
@merge_request
,
merge_when_build_succeeds:
true
,
should_remove_source_branch:
true
),
remote:
true
,
method: :post
,
class:
"btn btn-grouped btn-primary btn-sm remove_source_branch"
do
=
icon
(
'times'
)
=
icon
(
'times'
)
Remove Source Branch When Merged
Remove Source Branch When Merged
-
if
@merge_request
.
can_be_merged_by?
(
current_user
)
||
@merge_request
.
author
==
current_user
-
if
@merge_request
.
can_be_merged_by?
(
current_user
)
||
@merge_request
.
author
==
current_user
=
link_to
merge_namespace_project_merge_request_path
(
@merge_request
.
source_project
.
namespace
,
@merge_request
.
source_project
,
@merge_request
),
remote:
true
,
method: :delete
,
class:
"btn btn-grouped btn-warning btn-sm"
do
=
link_to
cancel_merge_when_build_succeeds_namespace_project_merge_request_path
(
@merge_request
.
target_project
.
namespace
,
@merge_request
.
target_project
,
@merge_request
),
remote:
true
,
method: :post
,
class:
"btn btn-grouped btn-warning btn-sm"
do
Cancel Automatic Merge
Cancel Automatic Merge
app/workers/merge_worker.rb
View file @
2f048df4
...
@@ -8,16 +8,7 @@ class MergeWorker
...
@@ -8,16 +8,7 @@ class MergeWorker
current_user
=
User
.
find
(
current_user_id
)
current_user
=
User
.
find
(
current_user_id
)
merge_request
=
MergeRequest
.
find
(
merge_request_id
)
merge_request
=
MergeRequest
.
find
(
merge_request_id
)
result
=
MergeRequests
::
MergeService
.
new
(
merge_request
.
target_project
,
current_user
).
MergeRequests
::
MergeService
.
new
(
merge_request
.
target_project
,
current_user
,
params
).
execute
(
merge_request
,
params
[
:commit_message
])
execute
(
merge_request
)
if
result
[
:status
]
==
:success
&&
params
[
:should_remove_source_branch
].
present?
DeleteBranchService
.
new
(
merge_request
.
source_project
,
current_user
).
execute
(
merge_request
.
source_branch
)
merge_request
.
source_project
.
repository
.
expire_branch_names
end
result
end
end
end
end
config/routes.rb
View file @
2f048df4
...
@@ -556,8 +556,7 @@ Gitlab::Application.routes.draw do
...
@@ -556,8 +556,7 @@ Gitlab::Application.routes.draw do
get
:diffs
get
:diffs
get
:commits
get
:commits
post
:merge
post
:merge
delete
:merge
,
action: :cancel_merge_when_build_succeeds
post
:cancel_merge_when_build_succeeds
get
:merge_check
get
:ci_status
get
:ci_status
post
:toggle_subscription
post
:toggle_subscription
end
end
...
...
doc/api/merge_requests.md
View file @
2f048df4
...
@@ -295,6 +295,56 @@ Parameters:
...
@@ -295,6 +295,56 @@ Parameters:
-
`id`
(required) - The ID of a project
-
`id`
(required) - The ID of a project
-
`merge_request_id`
(required) - ID of MR
-
`merge_request_id`
(required) - ID of MR
-
`merge_commit_message`
(optional) - Custom merge commit message
-
`merge_commit_message`
(optional) - Custom merge commit message
-
`should_remove_source_branch`
(optional) - if
`true`
removes the source branch
-
`merge_when_build_succeeds`
(optional) - if
`true`
the MR is merge when the build succeeds
```
json
{
"id"
:
1
,
"target_branch"
:
"master"
,
"source_branch"
:
"test1"
,
"project_id"
:
3
,
"title"
:
"test1"
,
"state"
:
"merged"
,
"upvotes"
:
0
,
"downvotes"
:
0
,
"author"
:
{
"id"
:
1
,
"username"
:
"admin"
,
"email"
:
"admin@example.com"
,
"name"
:
"Administrator"
,
"state"
:
"active"
,
"created_at"
:
"2012-04-29T08:46:00Z"
},
"assignee"
:
{
"id"
:
1
,
"username"
:
"admin"
,
"email"
:
"admin@example.com"
,
"name"
:
"Administrator"
,
"state"
:
"active"
,
"created_at"
:
"2012-04-29T08:46:00Z"
}
}
```
## Cancel Merge When Build Succeeds
Cancels the merge when build succeeds and reset the merge parameters
If successfull you'll get
`200 OK`
.
If you don't have permissions to accept this merge request - you'll get a 401
If the merge request is already merged or closed - you get 405 and error message 'Method Not Allowed'
In case the merge request is not set to be merged when the build succeeds, you'll also get a 405 with the error message 'Method Not Allowed'
```
PUT /projects/:id/merge_request/:merge_request_id/cancel_merge_when_build_succeeds
```
Parameters:
-
`id`
(required) - The ID of a project
-
`merge_request_id`
(required) - ID of MR
```
json
```
json
{
{
...
...
lib/api/merge_requests.rb
View file @
2f048df4
...
@@ -182,6 +182,7 @@ module API
...
@@ -182,6 +182,7 @@ module API
# id (required) - The ID of a project
# id (required) - The ID of a project
# merge_request_id (required) - ID of MR
# merge_request_id (required) - ID of MR
# merge_commit_message (optional) - Custom merge commit message
# merge_commit_message (optional) - Custom merge commit message
# merge_when_build_succeeds (optional) - truethy when this MR should be merged when the build is succesfull
# Example:
# Example:
# PUT /projects/:id/merge_request/:merge_request_id/merge
# PUT /projects/:id/merge_request/:merge_request_id/merge
#
#
...
@@ -191,34 +192,57 @@ module API
...
@@ -191,34 +192,57 @@ module API
allowed
=
::
Gitlab
::
GitAccess
.
new
(
current_user
,
user_project
).
allowed
=
::
Gitlab
::
GitAccess
.
new
(
current_user
,
user_project
).
can_push_to_branch?
(
merge_request
.
target_branch
)
can_push_to_branch?
(
merge_request
.
target_branch
)
if
allowed
# Merge request can not be merged
if
merge_request
.
unchecked?
# because user dont have permissions to push into target branch
merge_request
.
check_if_can_be_merged
unauthorized!
unless
allowed
end
if
merge_request
.
open?
&&
!
merge_request
.
work_in_progress?
not_allowed!
unless
merge_request
.
open?
if
merge_request
.
can_be_merged?
commit_message
=
params
[
:merge_commit_message
]
||
merge_request
.
merge_commit_message
::
MergeRequests
::
MergeService
.
new
(
merge_request
.
target_project
,
current_user
).
merge_request
.
check_if_can_be_merged
if
merge_request
.
unchecked?
execute
(
merge_request
,
commit_message
)
present
merge_request
,
with:
Entities
::
MergeRequest
merge_params
=
{
commit_message:
params
[
:merge_commit_message
],
should_remove_source_branch:
params
[
:should_remove_source_branch
]
}
if
!
merge_request
.
work_in_progress?
if
parse_boolean
(
params
[
:merge_when_build_succeeds
])
::
MergeRequest
::
MergeWhenBuildSucceedsService
.
new
(
merge_request
.
target_project
,
current_user
,
merge_params
).
execute
(
merge_request
)
else
else
render_api_error!
(
'Branch cannot be merged'
,
405
)
::
MergeRequests
::
MergeService
.
new
(
merge_request
.
target_project
,
current_user
,
merge_params
).
execute
(
merge_request
,
merge_params
)
end
end
else
else
# Merge request can not be merged
render_api_error!
(
'Branch cannot be merged'
,
405
)
# because it is already closed/merged or marked as WIP
not_allowed!
end
end
else
present
merge_request
,
with:
Entities
::
MergeRequest
end
# Cancel Merge if Merge When build succeeds is enabled
# Parameters:
# id (required) - The ID of a project
# merge_request_id (required) - ID of MR
#
post
":id/merge_request/:merge_request_id/cancel_merge_when_build_succeeds"
do
merge_request
=
user_project
.
merge_requests
.
find
(
params
[
:merge_request_id
])
allowed
=
::
Gitlab
::
GitAccess
.
new
(
current_user
,
user_project
).
can_push_to_branch?
(
merge_request
.
target_branch
)
# Merge request can not be merged
# Merge request can not be merged
# because user dont have permissions to push into target branch
# because user dont have permissions to push into target branch
unauthorized!
unauthorized!
unless
allowed
end
if
merge_request
.
merged?
||
!
merge_request
.
open?
||
!
merge_request
.
merge_when_build_succeeds?
not_allowed!
end
end
merge_request
.
reset_merge_when_build_succeeds
present
merge_request
,
with:
Entities
::
MergeRequest
end
# Get a merge request's comments
# Get a merge request's comments
#
#
...
...
spec/models/merge_request_spec.rb
View file @
2f048df4
...
@@ -30,7 +30,7 @@ describe MergeRequest do
...
@@ -30,7 +30,7 @@ describe MergeRequest do
describe
'associations'
do
describe
'associations'
do
it
{
is_expected
.
to
belong_to
(
:target_project
).
with_foreign_key
(
:target_project_id
).
class_name
(
'Project'
)
}
it
{
is_expected
.
to
belong_to
(
:target_project
).
with_foreign_key
(
:target_project_id
).
class_name
(
'Project'
)
}
it
{
is_expected
.
to
belong_to
(
:source_project
).
with_foreign_key
(
:source_project_id
).
class_name
(
'Project'
)
}
it
{
is_expected
.
to
belong_to
(
:source_project
).
with_foreign_key
(
:source_project_id
).
class_name
(
'Project'
)
}
it
{
is_expected
.
to
belong_to
(
:merge_user
).
class_name
(
"User"
)
}
it
{
is_expected
.
to
have_one
(
:merge_request_diff
).
dependent
(
:destroy
)
}
it
{
is_expected
.
to
have_one
(
:merge_request_diff
).
dependent
(
:destroy
)
}
end
end
...
@@ -53,6 +53,8 @@ describe MergeRequest do
...
@@ -53,6 +53,8 @@ describe MergeRequest do
it
{
is_expected
.
to
respond_to
(
:unchecked?
)
}
it
{
is_expected
.
to
respond_to
(
:unchecked?
)
}
it
{
is_expected
.
to
respond_to
(
:can_be_merged?
)
}
it
{
is_expected
.
to
respond_to
(
:can_be_merged?
)
}
it
{
is_expected
.
to
respond_to
(
:cannot_be_merged?
)
}
it
{
is_expected
.
to
respond_to
(
:cannot_be_merged?
)
}
it
{
is_expected
.
to
respond_to
(
:merge_params
)
}
it
{
is_expected
.
to
respond_to
(
:merge_when_build_succeeds
)
}
end
end
describe
'#to_reference'
do
describe
'#to_reference'
do
...
@@ -171,6 +173,16 @@ describe MergeRequest do
...
@@ -171,6 +173,16 @@ describe MergeRequest do
end
end
end
end
describe
"#reset_merge_when_build_succeeds"
do
let
(
:merge_if_green
)
{
create
:merge_request
,
merge_when_build_succeeds:
true
}
it
"sets the item to false"
do
merge_if_green
.
reset_merge_when_build_succeeds
merge_if_green
.
reload
expect
(
merge_if_green
.
merge_when_build_succeeds
).
to
be_falsey
end
end
describe
"#hook_attrs"
do
describe
"#hook_attrs"
do
it
"has all the required keys"
do
it
"has all the required keys"
do
attrs
=
subject
.
hook_attrs
attrs
=
subject
.
hook_attrs
...
...
spec/services/system_note_service_spec.rb
View file @
2f048df4
...
@@ -207,6 +207,22 @@ describe SystemNoteService do
...
@@ -207,6 +207,22 @@ describe SystemNoteService do
end
end
end
end
describe
'.merge_when_build_succeeds'
do
let
(
:ci_commit
)
{
create
:ci_commit
,
gl_project:
project
}
let
(
:merge_request
)
{
create
:merge_request
,
project:
project
}
subject
{
described_class
.
merge_when_build_succeeds
(
merge_request
,
project
,
author
)
}
it_behaves_like
'a system note'
it
"posts the Merge When Build Succeeds system note"
do
allow
(
merge_request
).
to
receive
(
:ci_commit
).
and_return
(
ci_commit
)
allow
(
ci_commit
).
to
receive
(
:short_sha
).
and_return
(
'12345678'
)
expect
(
subject
.
note
).
to
eq
"This merge request will be automatically merged when the build for 12345678 succeeds"
end
end
describe
'.change_title'
do
describe
'.change_title'
do
subject
{
described_class
.
change_title
(
noteable
,
project
,
author
,
'Old title'
)
}
subject
{
described_class
.
change_title
(
noteable
,
project
,
author
,
'Old title'
)
}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment