Commit 9c728799 authored by Rémy Coutable's avatar Rémy Coutable

Merge branch '39880-merge-method-api' into 'master'

Resolve "Allow the configuration of a project's merge method via the API"

Closes #39880

See merge request gitlab-org/gitlab-ce!18031
parents c7e0fc76 f6d58310
---
title: 'API: Add parameter merge_method to projects'
merge_request: 18031
author: Jan Beckmann
type: added
...@@ -16,6 +16,21 @@ Values for the project visibility level are: ...@@ -16,6 +16,21 @@ Values for the project visibility level are:
* `public`: * `public`:
The project can be cloned without any authentication. The project can be cloned without any authentication.
## Project merge method
There are currently three options for `merge_method` to choose from:
* `merge`:
A merge commit is created for every merge, and merging is allowed as long as there are no conflicts.
* `rebase_merge`:
A merge commit is created for every merge, but merging is only allowed if fast-forward merge is possible.
This way you could make sure that if this merge request would build, after merging to target branch it would also build.
* `ff`:
No merge commits are created and all merges are fast-forwarded, which means that merging is only allowed if the branch could be fast-forwarded.
## List all projects ## List all projects
Get a list of all visible projects across GitLab for the authenticated user. Get a list of all visible projects across GitLab for the authenticated user.
...@@ -94,6 +109,7 @@ GET /projects ...@@ -94,6 +109,7 @@ GET /projects
"only_allow_merge_if_pipeline_succeeds": false, "only_allow_merge_if_pipeline_succeeds": false,
"only_allow_merge_if_all_discussions_are_resolved": false, "only_allow_merge_if_all_discussions_are_resolved": false,
"request_access_enabled": false, "request_access_enabled": false,
"merge_method": "merge",
"statistics": { "statistics": {
"commit_count": 37, "commit_count": 37,
"storage_size": 1038090, "storage_size": 1038090,
...@@ -173,6 +189,7 @@ GET /projects ...@@ -173,6 +189,7 @@ GET /projects
"only_allow_merge_if_pipeline_succeeds": false, "only_allow_merge_if_pipeline_succeeds": false,
"only_allow_merge_if_all_discussions_are_resolved": false, "only_allow_merge_if_all_discussions_are_resolved": false,
"request_access_enabled": false, "request_access_enabled": false,
"merge_method": "merge",
"statistics": { "statistics": {
"commit_count": 12, "commit_count": 12,
"storage_size": 2066080, "storage_size": 2066080,
...@@ -278,6 +295,7 @@ GET /users/:user_id/projects ...@@ -278,6 +295,7 @@ GET /users/:user_id/projects
"only_allow_merge_if_pipeline_succeeds": false, "only_allow_merge_if_pipeline_succeeds": false,
"only_allow_merge_if_all_discussions_are_resolved": false, "only_allow_merge_if_all_discussions_are_resolved": false,
"request_access_enabled": false, "request_access_enabled": false,
"merge_method": "merge",
"statistics": { "statistics": {
"commit_count": 37, "commit_count": 37,
"storage_size": 1038090, "storage_size": 1038090,
...@@ -357,6 +375,7 @@ GET /users/:user_id/projects ...@@ -357,6 +375,7 @@ GET /users/:user_id/projects
"only_allow_merge_if_pipeline_succeeds": false, "only_allow_merge_if_pipeline_succeeds": false,
"only_allow_merge_if_all_discussions_are_resolved": false, "only_allow_merge_if_all_discussions_are_resolved": false,
"request_access_enabled": false, "request_access_enabled": false,
"merge_method": "merge",
"statistics": { "statistics": {
"commit_count": 12, "commit_count": 12,
"storage_size": 2066080, "storage_size": 2066080,
...@@ -467,6 +486,7 @@ GET /projects/:id ...@@ -467,6 +486,7 @@ GET /projects/:id
"only_allow_merge_if_all_discussions_are_resolved": false, "only_allow_merge_if_all_discussions_are_resolved": false,
"printing_merge_requests_link_enabled": true, "printing_merge_requests_link_enabled": true,
"request_access_enabled": false, "request_access_enabled": false,
"merge_method": "merge",
"statistics": { "statistics": {
"commit_count": 37, "commit_count": 37,
"storage_size": 1038090, "storage_size": 1038090,
...@@ -550,6 +570,7 @@ POST /projects ...@@ -550,6 +570,7 @@ POST /projects
| `public_jobs` | boolean | no | If `true`, jobs can be viewed by non-project-members | | `public_jobs` | boolean | no | If `true`, jobs can be viewed by non-project-members |
| `only_allow_merge_if_pipeline_succeeds` | boolean | no | Set whether merge requests can only be merged with successful jobs | | `only_allow_merge_if_pipeline_succeeds` | boolean | no | Set whether merge requests can only be merged with successful jobs |
| `only_allow_merge_if_all_discussions_are_resolved` | boolean | no | Set whether merge requests can only be merged when all the discussions are resolved | | `only_allow_merge_if_all_discussions_are_resolved` | boolean | no | Set whether merge requests can only be merged when all the discussions are resolved |
| `merge_method` | string | no | Set the merge method used |
| `lfs_enabled` | boolean | no | Enable LFS | | `lfs_enabled` | boolean | no | Enable LFS |
| `request_access_enabled` | boolean | no | Allow users to request member access | | `request_access_enabled` | boolean | no | Allow users to request member access |
| `tag_list` | array | no | The list of tags for a project; put array of tags, that should be finally assigned to a project | | `tag_list` | array | no | The list of tags for a project; put array of tags, that should be finally assigned to a project |
...@@ -586,6 +607,7 @@ POST /projects/user/:user_id ...@@ -586,6 +607,7 @@ POST /projects/user/:user_id
| `public_jobs` | boolean | no | If `true`, jobs can be viewed by non-project-members | | `public_jobs` | boolean | no | If `true`, jobs can be viewed by non-project-members |
| `only_allow_merge_if_pipeline_succeeds` | boolean | no | Set whether merge requests can only be merged with successful jobs | | `only_allow_merge_if_pipeline_succeeds` | boolean | no | Set whether merge requests can only be merged with successful jobs |
| `only_allow_merge_if_all_discussions_are_resolved` | boolean | no | Set whether merge requests can only be merged when all the discussions are resolved | | `only_allow_merge_if_all_discussions_are_resolved` | boolean | no | Set whether merge requests can only be merged when all the discussions are resolved |
| `merge_method` | string | no | Set the merge method used |
| `lfs_enabled` | boolean | no | Enable LFS | | `lfs_enabled` | boolean | no | Enable LFS |
| `request_access_enabled` | boolean | no | Allow users to request member access | | `request_access_enabled` | boolean | no | Allow users to request member access |
| `tag_list` | array | no | The list of tags for a project; put array of tags, that should be finally assigned to a project | | `tag_list` | array | no | The list of tags for a project; put array of tags, that should be finally assigned to a project |
...@@ -621,6 +643,7 @@ PUT /projects/:id ...@@ -621,6 +643,7 @@ PUT /projects/:id
| `public_jobs` | boolean | no | If `true`, jobs can be viewed by non-project-members | | `public_jobs` | boolean | no | If `true`, jobs can be viewed by non-project-members |
| `only_allow_merge_if_pipeline_succeeds` | boolean | no | Set whether merge requests can only be merged with successful jobs | | `only_allow_merge_if_pipeline_succeeds` | boolean | no | Set whether merge requests can only be merged with successful jobs |
| `only_allow_merge_if_all_discussions_are_resolved` | boolean | no | Set whether merge requests can only be merged when all the discussions are resolved | | `only_allow_merge_if_all_discussions_are_resolved` | boolean | no | Set whether merge requests can only be merged when all the discussions are resolved |
| `merge_method` | string | no | Set the merge method used |
| `lfs_enabled` | boolean | no | Enable LFS | | `lfs_enabled` | boolean | no | Enable LFS |
| `request_access_enabled` | boolean | no | Allow users to request member access | | `request_access_enabled` | boolean | no | Allow users to request member access |
| `tag_list` | array | no | The list of tags for a project; put array of tags, that should be finally assigned to a project | | `tag_list` | array | no | The list of tags for a project; put array of tags, that should be finally assigned to a project |
...@@ -724,6 +747,7 @@ Example responses: ...@@ -724,6 +747,7 @@ Example responses:
"only_allow_merge_if_pipeline_succeeds": false, "only_allow_merge_if_pipeline_succeeds": false,
"only_allow_merge_if_all_discussions_are_resolved": false, "only_allow_merge_if_all_discussions_are_resolved": false,
"request_access_enabled": false, "request_access_enabled": false,
"merge_method": "merge",
"_links": { "_links": {
"self": "http://example.com/api/v4/projects", "self": "http://example.com/api/v4/projects",
"issues": "http://example.com/api/v4/projects/1/issues", "issues": "http://example.com/api/v4/projects/1/issues",
...@@ -801,6 +825,7 @@ Example response: ...@@ -801,6 +825,7 @@ Example response:
"only_allow_merge_if_pipeline_succeeds": false, "only_allow_merge_if_pipeline_succeeds": false,
"only_allow_merge_if_all_discussions_are_resolved": false, "only_allow_merge_if_all_discussions_are_resolved": false,
"request_access_enabled": false, "request_access_enabled": false,
"merge_method": "merge",
"_links": { "_links": {
"self": "http://example.com/api/v4/projects", "self": "http://example.com/api/v4/projects",
"issues": "http://example.com/api/v4/projects/1/issues", "issues": "http://example.com/api/v4/projects/1/issues",
...@@ -877,6 +902,7 @@ Example response: ...@@ -877,6 +902,7 @@ Example response:
"only_allow_merge_if_pipeline_succeeds": false, "only_allow_merge_if_pipeline_succeeds": false,
"only_allow_merge_if_all_discussions_are_resolved": false, "only_allow_merge_if_all_discussions_are_resolved": false,
"request_access_enabled": false, "request_access_enabled": false,
"merge_method": "merge",
"_links": { "_links": {
"self": "http://example.com/api/v4/projects", "self": "http://example.com/api/v4/projects",
"issues": "http://example.com/api/v4/projects/1/issues", "issues": "http://example.com/api/v4/projects/1/issues",
...@@ -971,6 +997,7 @@ Example response: ...@@ -971,6 +997,7 @@ Example response:
"only_allow_merge_if_pipeline_succeeds": false, "only_allow_merge_if_pipeline_succeeds": false,
"only_allow_merge_if_all_discussions_are_resolved": false, "only_allow_merge_if_all_discussions_are_resolved": false,
"request_access_enabled": false, "request_access_enabled": false,
"merge_method": "merge",
"_links": { "_links": {
"self": "http://example.com/api/v4/projects", "self": "http://example.com/api/v4/projects",
"issues": "http://example.com/api/v4/projects/1/issues", "issues": "http://example.com/api/v4/projects/1/issues",
...@@ -1065,6 +1092,7 @@ Example response: ...@@ -1065,6 +1092,7 @@ Example response:
"only_allow_merge_if_pipeline_succeeds": false, "only_allow_merge_if_pipeline_succeeds": false,
"only_allow_merge_if_all_discussions_are_resolved": false, "only_allow_merge_if_all_discussions_are_resolved": false,
"request_access_enabled": false, "request_access_enabled": false,
"merge_method": "merge",
"_links": { "_links": {
"self": "http://example.com/api/v4/projects", "self": "http://example.com/api/v4/projects",
"issues": "http://example.com/api/v4/projects/1/issues", "issues": "http://example.com/api/v4/projects/1/issues",
......
...@@ -206,6 +206,7 @@ module API ...@@ -206,6 +206,7 @@ module API
expose :request_access_enabled expose :request_access_enabled
expose :only_allow_merge_if_all_discussions_are_resolved expose :only_allow_merge_if_all_discussions_are_resolved
expose :printing_merge_request_link_enabled expose :printing_merge_request_link_enabled
expose :merge_method
expose :statistics, using: 'API::Entities::ProjectStatistics', if: :statistics expose :statistics, using: 'API::Entities::ProjectStatistics', if: :statistics
......
...@@ -28,6 +28,7 @@ module API ...@@ -28,6 +28,7 @@ module API
optional :tag_list, type: Array[String], desc: 'The list of tags for a project' optional :tag_list, type: Array[String], desc: 'The list of tags for a project'
optional :avatar, type: File, desc: 'Avatar image for project' optional :avatar, type: File, desc: 'Avatar image for project'
optional :printing_merge_request_link_enabled, type: Boolean, desc: 'Show link to create/view merge request when pushing from the command line' optional :printing_merge_request_link_enabled, type: Boolean, desc: 'Show link to create/view merge request when pushing from the command line'
optional :merge_method, type: String, values: %w(ff rebase_merge merge), desc: 'The merge method used when merging merge requests'
end end
params :optional_params do params :optional_params do
...@@ -274,6 +275,7 @@ module API ...@@ -274,6 +275,7 @@ module API
:issues_enabled, :issues_enabled,
:lfs_enabled, :lfs_enabled,
:merge_requests_enabled, :merge_requests_enabled,
:merge_method,
:name, :name,
:only_allow_merge_if_all_discussions_are_resolved, :only_allow_merge_if_all_discussions_are_resolved,
:only_allow_merge_if_pipeline_succeeds, :only_allow_merge_if_pipeline_succeeds,
......
...@@ -452,7 +452,8 @@ describe API::Projects do ...@@ -452,7 +452,8 @@ describe API::Projects do
only_allow_merge_if_pipeline_succeeds: false, only_allow_merge_if_pipeline_succeeds: false,
request_access_enabled: true, request_access_enabled: true,
only_allow_merge_if_all_discussions_are_resolved: false, only_allow_merge_if_all_discussions_are_resolved: false,
ci_config_path: 'a/custom/path' ci_config_path: 'a/custom/path',
merge_method: 'ff'
}) })
post api('/projects', user), project post api('/projects', user), project
...@@ -569,6 +570,22 @@ describe API::Projects do ...@@ -569,6 +570,22 @@ describe API::Projects do
expect(json_response['only_allow_merge_if_all_discussions_are_resolved']).to be_truthy expect(json_response['only_allow_merge_if_all_discussions_are_resolved']).to be_truthy
end end
it 'sets the merge method of a project to rebase merge' do
project = attributes_for(:project, merge_method: 'rebase_merge')
post api('/projects', user), project
expect(json_response['merge_method']).to eq('rebase_merge')
end
it 'rejects invalid values for merge_method' do
project = attributes_for(:project, merge_method: 'totally_not_valid_method')
post api('/projects', user), project
expect(response).to have_gitlab_http_status(400)
end
it 'ignores import_url when it is nil' do it 'ignores import_url when it is nil' do
project = attributes_for(:project, import_url: nil) project = attributes_for(:project, import_url: nil)
...@@ -823,6 +840,7 @@ describe API::Projects do ...@@ -823,6 +840,7 @@ describe API::Projects do
expect(json_response['shared_with_groups'][0]['group_access_level']).to eq(link.group_access) expect(json_response['shared_with_groups'][0]['group_access_level']).to eq(link.group_access)
expect(json_response['only_allow_merge_if_pipeline_succeeds']).to eq(project.only_allow_merge_if_pipeline_succeeds) expect(json_response['only_allow_merge_if_pipeline_succeeds']).to eq(project.only_allow_merge_if_pipeline_succeeds)
expect(json_response['only_allow_merge_if_all_discussions_are_resolved']).to eq(project.only_allow_merge_if_all_discussions_are_resolved) expect(json_response['only_allow_merge_if_all_discussions_are_resolved']).to eq(project.only_allow_merge_if_all_discussions_are_resolved)
expect(json_response['merge_method']).to eq(project.merge_method.to_s)
end end
it 'returns a project by path name' do it 'returns a project by path name' do
...@@ -1474,6 +1492,26 @@ describe API::Projects do ...@@ -1474,6 +1492,26 @@ describe API::Projects do
expect(json_response[k.to_s]).to eq(v) expect(json_response[k.to_s]).to eq(v)
end end
end end
it 'updates merge_method' do
project_param = { merge_method: 'ff' }
put api("/projects/#{project3.id}", user), project_param
expect(response).to have_gitlab_http_status(200)
project_param.each_pair do |k, v|
expect(json_response[k.to_s]).to eq(v)
end
end
it 'rejects to update merge_method when merge_method is invalid' do
project_param = { merge_method: 'invalid' }
put api("/projects/#{project3.id}", user), project_param
expect(response).to have_gitlab_http_status(400)
end
end end
context 'when authenticated as project master' do context 'when authenticated as project master' do
...@@ -1491,6 +1529,7 @@ describe API::Projects do ...@@ -1491,6 +1529,7 @@ describe API::Projects do
wiki_enabled: true, wiki_enabled: true,
snippets_enabled: true, snippets_enabled: true,
merge_requests_enabled: true, merge_requests_enabled: true,
merge_method: 'ff',
description: 'new description' } description: 'new description' }
put api("/projects/#{project3.id}", user4), project_param put api("/projects/#{project3.id}", user4), project_param
......
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