API: Ability to cherry-pick a commit
This commit is contained in:
parent
db9e1635d0
commit
1a81fcfbd8
4 changed files with 148 additions and 1 deletions
4
changelogs/unreleased/api-cherry-pick.yml
Normal file
4
changelogs/unreleased/api-cherry-pick.yml
Normal file
|
@ -0,0 +1,4 @@
|
|||
---
|
||||
title: 'API: Ability to cherry pick a commit'
|
||||
merge_request: 8047
|
||||
author: Robert Schilling
|
|
@ -183,6 +183,44 @@ Example response:
|
|||
}
|
||||
```
|
||||
|
||||
## Cherry pick a commit
|
||||
|
||||
> [Introduced][ce-8047] in GitLab 8.15.
|
||||
|
||||
Cherry picks a commit to a given branch.
|
||||
|
||||
```
|
||||
POST /projects/:id/repository/commits/:sha/cherry_pick
|
||||
```
|
||||
|
||||
Parameters:
|
||||
|
||||
| Attribute | Type | Required | Description |
|
||||
| --------- | ---- | -------- | ----------- |
|
||||
| `id` | integer/string | yes | The ID of a project or NAMESPACE/PROJECT_NAME owned by the authenticated user
|
||||
| `sha` | string | yes | The commit hash |
|
||||
| `branch` | string | yes | The name of the branch |
|
||||
|
||||
```bash
|
||||
curl --request POST --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" --form "branch=master" "https://gitlab.example.com/api/v3/projects/5/repository/commits/master/cherry_pick"
|
||||
```
|
||||
|
||||
Example response:
|
||||
|
||||
```json
|
||||
{
|
||||
"id": "8b090c1b79a14f2bd9e8a738f717824ff53aebad",
|
||||
"short_id": "8b090c1b",
|
||||
"title": "Feature added",
|
||||
"author_name": "Dmitriy Zaporozhets",
|
||||
"author_email": "dmitriy.zaporozhets@gmail.com",
|
||||
"created_at": "2016-12-12T20:10:39.000+01:00",
|
||||
"committer_name": "Administrator",
|
||||
"committer_email": "admin@example.com",
|
||||
"message": "Feature added\n\nSigned-off-by: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>\n"
|
||||
}
|
||||
```
|
||||
|
||||
## Get the diff of a commit
|
||||
|
||||
Get the diff of a commit in a project.
|
||||
|
@ -438,3 +476,4 @@ Example response:
|
|||
```
|
||||
|
||||
[ce-6096]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/6096 "Multi-file commit"
|
||||
[ce-8047]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/8047
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
require 'mime/types'
|
||||
|
||||
module API
|
||||
# Projects commits API
|
||||
class Commits < Grape::API
|
||||
include PaginationParams
|
||||
|
||||
|
@ -121,6 +120,41 @@ module API
|
|||
present paginate(notes), with: Entities::CommitNote
|
||||
end
|
||||
|
||||
desc 'Cherry pick commit into a branch' do
|
||||
detail 'This feature was introduced in GitLab 8.15'
|
||||
success Entities::RepoCommit
|
||||
end
|
||||
params do
|
||||
requires :sha, type: String, desc: 'A commit sha to be cherry picked'
|
||||
requires :branch, type: String, desc: 'The name of the branch'
|
||||
end
|
||||
post ':id/repository/commits/:sha/cherry_pick' do
|
||||
authorize! :push_code, user_project
|
||||
|
||||
commit = user_project.commit(params[:sha])
|
||||
not_found!('Commit') unless commit
|
||||
|
||||
branch = user_project.repository.find_branch(params[:branch])
|
||||
not_found!('Branch') unless branch
|
||||
|
||||
commit_params = {
|
||||
commit: commit,
|
||||
create_merge_request: false,
|
||||
source_project: user_project,
|
||||
source_branch: commit.cherry_pick_branch_name,
|
||||
target_branch: params[:branch]
|
||||
}
|
||||
|
||||
result = ::Commits::CherryPickService.new(user_project, current_user, commit_params).execute
|
||||
|
||||
if result[:status] == :success
|
||||
branch = user_project.repository.find_branch(params[:branch])
|
||||
present user_project.repository.commit(branch.dereferenced_target), with: Entities::RepoCommit
|
||||
else
|
||||
render_api_error!(result[:message], 400)
|
||||
end
|
||||
end
|
||||
|
||||
desc 'Post comment to commit' do
|
||||
success Entities::CommitNote
|
||||
end
|
||||
|
|
|
@ -456,6 +456,76 @@ describe API::Commits, api: true do
|
|||
end
|
||||
end
|
||||
|
||||
describe 'POST :id/repository/commits/:sha/cherry_pick' do
|
||||
let(:master_pickable_commit) { project.commit('7d3b0f7cff5f37573aea97cebfd5692ea1689924') }
|
||||
|
||||
context 'authorized user' do
|
||||
it 'cherry picks a commit' do
|
||||
post api("/projects/#{project.id}/repository/commits/#{master_pickable_commit.id}/cherry_pick", user), branch: 'master'
|
||||
|
||||
expect(response).to have_http_status(201)
|
||||
expect(json_response['title']).to eq(master_pickable_commit.title)
|
||||
expect(json_response['message']).to eq(master_pickable_commit.message)
|
||||
expect(json_response['author_name']).to eq(master_pickable_commit.author_name)
|
||||
expect(json_response['committer_name']).to eq(user.name)
|
||||
end
|
||||
|
||||
it 'returns 400 if commit is already included in the target branch' do
|
||||
post api("/projects/#{project.id}/repository/commits/#{master_pickable_commit.id}/cherry_pick", user), branch: 'markdown'
|
||||
|
||||
expect(response).to have_http_status(400)
|
||||
expect(json_response['message']).to eq('Sorry, we cannot cherry-pick this commit automatically.
|
||||
It may have already been cherry-pick, or a more recent commit may have updated some of its content.')
|
||||
end
|
||||
|
||||
it 'returns 400 if you are not allowed to push to the target branch' do
|
||||
project.team << [user2, :developer]
|
||||
protected_branch = create(:protected_branch, project: project, name: 'feature')
|
||||
|
||||
post api("/projects/#{project.id}/repository/commits/#{master_pickable_commit.id}/cherry_pick", user2), branch: 'feature'
|
||||
|
||||
expect(response).to have_http_status(400)
|
||||
expect(json_response['message']).to eq('You are not allowed to push into this branch')
|
||||
end
|
||||
|
||||
it 'returns 400 for missing parameters' do
|
||||
post api("/projects/#{project.id}/repository/commits/#{master_pickable_commit.id}/cherry_pick", user)
|
||||
|
||||
expect(response).to have_http_status(400)
|
||||
expect(json_response['error']).to eq('branch is missing')
|
||||
end
|
||||
|
||||
it 'returns 404 if commit is not found' do
|
||||
post api("/projects/#{project.id}/repository/commits/abcd0123/cherry_pick", user), branch: 'master'
|
||||
|
||||
expect(response).to have_http_status(404)
|
||||
expect(json_response['message']).to eq('404 Commit Not Found')
|
||||
end
|
||||
|
||||
it 'returns 404 if branch is not found' do
|
||||
post api("/projects/#{project.id}/repository/commits/#{master_pickable_commit.id}/cherry_pick", user), branch: 'foo'
|
||||
|
||||
expect(response).to have_http_status(404)
|
||||
expect(json_response['message']).to eq('404 Branch Not Found')
|
||||
end
|
||||
|
||||
it 'returns 400 for missing parameters' do
|
||||
post api("/projects/#{project.id}/repository/commits/#{master_pickable_commit.id}/cherry_pick", user)
|
||||
|
||||
expect(response).to have_http_status(400)
|
||||
expect(json_response['error']).to eq('branch is missing')
|
||||
end
|
||||
end
|
||||
|
||||
context 'unauthorized user' do
|
||||
it 'does not cherry pick the commit' do
|
||||
post api("/projects/#{project.id}/repository/commits/#{master_pickable_commit.id}/cherry_pick"), branch: 'master'
|
||||
|
||||
expect(response).to have_http_status(401)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'Post comment to commit' do
|
||||
context 'authorized user' do
|
||||
it 'returns comment' do
|
||||
|
|
Loading…
Reference in a new issue