2019-12-26 22:10:19 +05:30
# frozen_string_literal: true
2014-09-02 18:07:02 +05:30
require 'spec_helper'
require 'mime/types'
2020-07-28 23:09:34 +05:30
RSpec . describe API :: Commits do
2019-09-04 21:01:54 +05:30
include ProjectForksHelper
2014-09-02 18:07:02 +05:30
let ( :user ) { create ( :user ) }
2017-09-10 17:25:29 +05:30
let ( :guest ) { create ( :user ) . tap { | u | project . add_guest ( u ) } }
2020-02-01 01:16:34 +05:30
let ( :developer ) { create ( :user ) . tap { | u | project . add_developer ( u ) } }
2017-09-10 17:25:29 +05:30
let ( :project ) { create ( :project , :repository , creator : user , path : 'my.project' ) }
let ( :branch_with_dot ) { project . repository . find_branch ( 'ends-with.json' ) }
let ( :branch_with_slash ) { project . repository . find_branch ( 'improve/awesome' ) }
let ( :project_id ) { project . id }
let ( :current_user ) { nil }
2014-09-02 18:07:02 +05:30
2017-09-10 17:25:29 +05:30
before do
2018-11-18 11:00:15 +05:30
project . add_maintainer ( user )
2017-09-10 17:25:29 +05:30
end
2014-09-02 18:07:02 +05:30
2017-09-10 17:25:29 +05:30
describe 'GET /projects/:id/repository/commits' do
2018-03-17 18:26:18 +05:30
let ( :route ) { " /projects/ #{ project_id } /repository/commits " }
2018-11-08 19:23:39 +05:30
shared_examples_for 'project commits' do | schema : 'public_api/v4/commits' |
2016-09-13 17:45:13 +05:30
it " returns project commits " do
2017-08-17 22:00:37 +05:30
commit = project . repository . commit
2018-03-17 18:26:18 +05:30
get api ( route , current_user )
2014-09-02 18:07:02 +05:30
2020-04-08 14:13:33 +05:30
expect ( response ) . to have_gitlab_http_status ( :ok )
2018-11-08 19:23:39 +05:30
expect ( response ) . to match_response_schema ( schema )
2017-08-17 22:00:37 +05:30
expect ( json_response . first [ 'id' ] ) . to eq ( commit . id )
expect ( json_response . first [ 'committer_name' ] ) . to eq ( commit . committer_name )
expect ( json_response . first [ 'committer_email' ] ) . to eq ( commit . committer_email )
end
it 'include correct pagination headers' do
2018-03-17 18:26:18 +05:30
get api ( route , current_user )
2017-08-17 22:00:37 +05:30
2021-01-03 14:25:43 +05:30
expect ( response ) . to include_limited_pagination_headers
2014-09-02 18:07:02 +05:30
end
end
2018-03-17 18:26:18 +05:30
context 'when unauthenticated' , 'and project is public' do
let ( :project ) { create ( :project , :public , :repository ) }
2017-09-10 17:25:29 +05:30
2018-03-17 18:26:18 +05:30
it_behaves_like 'project commits'
end
context 'when unauthenticated' , 'and project is private' do
it_behaves_like '404 response' do
let ( :request ) { get api ( route ) }
let ( :message ) { '404 Project Not Found' }
2014-09-02 18:07:02 +05:30
end
end
2016-06-02 11:05:42 +05:30
2018-11-18 11:00:15 +05:30
context 'when authenticated' , 'as a maintainer' do
2018-03-17 18:26:18 +05:30
let ( :current_user ) { user }
2016-06-02 11:05:42 +05:30
2018-03-17 18:26:18 +05:30
it_behaves_like 'project commits'
2016-06-02 11:05:42 +05:30
2018-03-17 18:26:18 +05:30
context " since optional parameter " do
it " returns project commits since provided parameter " do
commits = project . repository . commits ( " master " , limit : 2 )
after = commits . second . created_at
2017-08-17 22:00:37 +05:30
2018-03-17 18:26:18 +05:30
get api ( " /projects/ #{ project_id } /repository/commits?since= #{ after . utc . iso8601 } " , user )
2017-08-17 22:00:37 +05:30
2018-03-17 18:26:18 +05:30
expect ( json_response . size ) . to eq 2
expect ( json_response . first [ " id " ] ) . to eq ( commits . first . id )
expect ( json_response . second [ " id " ] ) . to eq ( commits . second . id )
end
2017-08-17 22:00:37 +05:30
2018-03-17 18:26:18 +05:30
it 'include correct pagination headers' do
commits = project . repository . commits ( " master " , limit : 2 )
after = commits . second . created_at
get api ( " /projects/ #{ project_id } /repository/commits?since= #{ after . utc . iso8601 } " , user )
2021-01-03 14:25:43 +05:30
expect ( response ) . to include_limited_pagination_headers
2018-03-17 18:26:18 +05:30
expect ( response . headers [ 'X-Page' ] ) . to eql ( '1' )
end
2017-08-17 22:00:37 +05:30
end
2016-06-02 11:05:42 +05:30
2018-03-17 18:26:18 +05:30
context " until optional parameter " do
it " returns project commits until provided parameter " do
commits = project . repository . commits ( " master " , limit : 20 )
before = commits . second . created_at
2016-06-02 11:05:42 +05:30
2018-03-17 18:26:18 +05:30
get api ( " /projects/ #{ project_id } /repository/commits?until= #{ before . utc . iso8601 } " , user )
2016-06-02 11:05:42 +05:30
2018-03-17 18:26:18 +05:30
if commits . size == 20
expect ( json_response . size ) . to eq ( 20 )
else
expect ( json_response . size ) . to eq ( commits . size - 1 )
end
2016-11-03 12:29:30 +05:30
2018-03-17 18:26:18 +05:30
expect ( json_response . first [ " id " ] ) . to eq ( commits . second . id )
expect ( json_response . second [ " id " ] ) . to eq ( commits . third . id )
end
2017-08-17 22:00:37 +05:30
2018-03-17 18:26:18 +05:30
it 'include correct pagination headers' do
commits = project . repository . commits ( " master " , limit : 2 )
before = commits . second . created_at
2017-08-17 22:00:37 +05:30
2018-03-17 18:26:18 +05:30
get api ( " /projects/ #{ project_id } /repository/commits?until= #{ before . utc . iso8601 } " , user )
2017-08-17 22:00:37 +05:30
2021-01-03 14:25:43 +05:30
expect ( response ) . to include_limited_pagination_headers
2018-03-17 18:26:18 +05:30
expect ( response . headers [ 'X-Page' ] ) . to eql ( '1' )
end
2017-08-17 22:00:37 +05:30
end
2016-06-02 11:05:42 +05:30
2018-03-17 18:26:18 +05:30
context " invalid xmlschema date parameters " do
it " returns an invalid parameter error message " do
get api ( " /projects/ #{ project_id } /repository/commits?since=invalid-date " , user )
2016-06-02 11:05:42 +05:30
2020-04-08 14:13:33 +05:30
expect ( response ) . to have_gitlab_http_status ( :bad_request )
2018-03-17 18:26:18 +05:30
expect ( json_response [ 'error' ] ) . to eq ( 'since is invalid' )
end
2017-08-17 22:00:37 +05:30
end
2019-10-12 21:52:04 +05:30
context " with empty ref_name parameter " do
let ( :route ) { " /projects/ #{ project_id } /repository/commits?ref_name= " }
it_behaves_like 'project commits'
end
2018-03-17 18:26:18 +05:30
context " path optional parameter " do
it " returns project commits matching provided path parameter " do
path = 'files/ruby/popen.rb'
2017-08-17 22:00:37 +05:30
2018-03-17 18:26:18 +05:30
get api ( " /projects/ #{ project_id } /repository/commits?path= #{ path } " , user )
2017-08-17 22:00:37 +05:30
2018-03-17 18:26:18 +05:30
expect ( json_response . size ) . to eq ( 3 )
expect ( json_response . first [ " id " ] ) . to eq ( " 570e7b2abdd848b95f2f578043fc23bd6f6fd24d " )
2021-01-03 14:25:43 +05:30
expect ( response ) . to include_limited_pagination_headers
2018-03-17 18:26:18 +05:30
end
2017-08-17 22:00:37 +05:30
2018-03-17 18:26:18 +05:30
it 'include correct pagination headers' do
path = 'files/ruby/popen.rb'
2017-08-17 22:00:37 +05:30
2018-03-17 18:26:18 +05:30
get api ( " /projects/ #{ project_id } /repository/commits?path= #{ path } " , user )
2017-08-17 22:00:37 +05:30
2021-01-03 14:25:43 +05:30
expect ( response ) . to include_limited_pagination_headers
2018-03-17 18:26:18 +05:30
expect ( response . headers [ 'X-Page' ] ) . to eql ( '1' )
end
2017-08-17 22:00:37 +05:30
end
2018-03-27 19:54:05 +05:30
context 'all optional parameter' do
it 'returns all project commits' do
2021-01-03 14:25:43 +05:30
expected_commit_ids = project . repository . commits ( nil , all : true , limit : 50 ) . map ( & :id )
get api ( " /projects/ #{ project_id } /repository/commits?all=true&per_page=50 " , user )
2018-03-27 19:54:05 +05:30
2021-01-03 14:25:43 +05:30
commit_ids = json_response . map { | c | c [ 'id' ] }
2018-03-27 19:54:05 +05:30
2021-01-03 14:25:43 +05:30
expect ( response ) . to include_limited_pagination_headers
expect ( commit_ids ) . to eq ( expected_commit_ids )
2018-03-27 19:54:05 +05:30
expect ( response . headers [ 'X-Page' ] ) . to eql ( '1' )
end
end
2019-12-21 20:55:43 +05:30
context 'first_parent optional parameter' do
it 'returns all first_parent commits' do
2021-01-03 14:25:43 +05:30
expected_commit_ids = project . repository . commits ( SeedRepo :: Commit :: ID , limit : 50 , first_parent : true ) . map ( & :id )
2019-12-21 20:55:43 +05:30
2021-01-03 14:25:43 +05:30
get api ( " /projects/ #{ project_id } /repository/commits?per_page=50 " , user ) , params : { ref_name : SeedRepo :: Commit :: ID , first_parent : 'true' }
2019-12-21 20:55:43 +05:30
2021-01-03 14:25:43 +05:30
commit_ids = json_response . map { | c | c [ 'id' ] }
expect ( response ) . to include_limited_pagination_headers
expect ( expected_commit_ids . size ) . to eq ( 12 )
expect ( commit_ids ) . to eq ( expected_commit_ids )
2019-12-21 20:55:43 +05:30
end
end
2018-11-08 19:23:39 +05:30
context 'with_stats optional parameter' do
let ( :project ) { create ( :project , :public , :repository ) }
it_behaves_like 'project commits' , schema : 'public_api/v4/commits_with_stats' do
let ( :route ) { " /projects/ #{ project_id } /repository/commits?with_stats=true " }
it 'include commits details' do
commit = project . repository . commit
get api ( route , current_user )
expect ( json_response . first [ 'stats' ] [ 'additions' ] ) . to eq ( commit . stats . additions )
expect ( json_response . first [ 'stats' ] [ 'deletions' ] ) . to eq ( commit . stats . deletions )
expect ( json_response . first [ 'stats' ] [ 'total' ] ) . to eq ( commit . stats . total )
end
end
end
2018-03-17 18:26:18 +05:30
context 'with pagination params' do
let ( :page ) { 1 }
let ( :per_page ) { 5 }
let ( :ref_name ) { 'master' }
let! ( :request ) do
get api ( " /projects/ #{ project_id } /repository/commits?page= #{ page } &per_page= #{ per_page } &ref_name= #{ ref_name } " , user )
end
2017-08-17 22:00:37 +05:30
2018-03-17 18:26:18 +05:30
it 'returns correct headers' do
2021-01-03 14:25:43 +05:30
expect ( response ) . to include_limited_pagination_headers
2018-03-17 18:26:18 +05:30
expect ( response . headers [ 'Link' ] ) . to match ( / page=1&per_page=5 / )
expect ( response . headers [ 'Link' ] ) . to match ( / page=2&per_page=5 / )
end
2017-08-17 22:00:37 +05:30
2018-03-17 18:26:18 +05:30
context 'viewing the first page' do
it 'returns the first 5 commits' do
commit = project . repository . commit
2017-08-17 22:00:37 +05:30
2018-03-17 18:26:18 +05:30
expect ( json_response . size ) . to eq ( per_page )
expect ( json_response . first [ 'id' ] ) . to eq ( commit . id )
expect ( response . headers [ 'X-Page' ] ) . to eq ( '1' )
end
2017-08-17 22:00:37 +05:30
end
2018-03-17 18:26:18 +05:30
context 'viewing the third page' do
let ( :page ) { 3 }
2017-08-17 22:00:37 +05:30
2018-03-17 18:26:18 +05:30
it 'returns the third 5 commits' do
commit = project . repository . commits ( 'HEAD' , limit : per_page , offset : ( page - 1 ) * per_page ) . first
2017-08-17 22:00:37 +05:30
2018-03-17 18:26:18 +05:30
expect ( json_response . size ) . to eq ( per_page )
expect ( json_response . first [ 'id' ] ) . to eq ( commit . id )
expect ( response . headers [ 'X-Page' ] ) . to eq ( '3' )
end
2017-08-17 22:00:37 +05:30
end
2020-03-13 15:44:24 +05:30
end
context 'with order parameter' do
let ( :route ) { " /projects/ #{ project_id } /repository/commits?ref_name=0031876&per_page=6&order= #{ order } " }
context 'set to topo' do
let ( :order ) { 'topo' }
# git log --graph -n 6 --pretty=format:"%h" --topo-order 0031876
# * 0031876
# |\
# | * 48ca272
# | * 335bc94
# * | bf6e164
# * | 9d526f8
# |/
# * 1039376
it 'returns project commits ordered by topo order' do
commits = project . repository . commits ( " 0031876 " , limit : 6 , order : 'topo' )
get api ( route , current_user )
expect ( json_response . size ) . to eq ( 6 )
expect ( json_response . map { | entry | entry [ " id " ] } ) . to eq ( commits . map ( & :id ) )
end
end
context 'set to default' do
let ( :order ) { 'default' }
# git log --graph -n 6 --pretty=format:"%h" --date-order 0031876
# * 0031876
# |\
# * | bf6e164
# | * 48ca272
# * | 9d526f8
# | * 335bc94
# |/
# * 1039376
it 'returns project commits ordered by default order' do
commits = project . repository . commits ( " 0031876 " , limit : 6 , order : 'default' )
get api ( route , current_user )
expect ( json_response . size ) . to eq ( 6 )
expect ( json_response . map { | entry | entry [ " id " ] } ) . to eq ( commits . map ( & :id ) )
end
end
context 'set to an invalid parameter' do
let ( :order ) { 'invalid' }
it_behaves_like '400 response' do
let ( :request ) { get api ( route , current_user ) }
end
end
2016-06-02 11:05:42 +05:30
end
2021-09-04 01:27:46 +05:30
context 'with the optional trailers parameter' do
it 'includes the Git trailers' do
get api ( " /projects/ #{ project_id } /repository/commits?ref_name=6d394385cf567f80a8fd85055db1ab4c5295806f&trailers=true " , current_user )
commit = json_response [ 0 ]
expect ( commit [ 'trailers' ] ) . to eq (
'Signed-off-by' = > 'Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>'
)
end
end
2016-06-02 11:05:42 +05:30
end
2014-09-02 18:07:02 +05:30
end
2017-08-17 22:00:37 +05:30
describe " POST /projects/:id/repository/commits " do
2017-09-10 17:25:29 +05:30
let! ( :url ) { " /projects/ #{ project_id } /repository/commits " }
2016-11-03 12:29:30 +05:30
it 'returns a 403 unauthorized for user without permissions' do
2017-09-10 17:25:29 +05:30
post api ( url , guest )
2016-11-03 12:29:30 +05:30
2020-04-08 14:13:33 +05:30
expect ( response ) . to have_gitlab_http_status ( :forbidden )
2016-11-03 12:29:30 +05:30
end
it 'returns a 400 bad request if no params are given' do
post api ( url , user )
2020-04-08 14:13:33 +05:30
expect ( response ) . to have_gitlab_http_status ( :bad_request )
2016-11-03 12:29:30 +05:30
end
2017-08-17 22:00:37 +05:30
describe 'create' do
2019-07-07 11:18:12 +05:30
let ( :message ) { 'Created a new file with a very very looooooooooooooooooooooooooooooooooooooooooooooong commit message' }
2018-12-05 23:21:45 +05:30
let ( :invalid_c_params ) do
2016-11-03 12:29:30 +05:30
{
2017-08-17 22:00:37 +05:30
branch : 'master' ,
2016-11-03 12:29:30 +05:30
commit_message : message ,
actions : [
{
action : 'create' ,
file_path : 'files/ruby/popen.rb' ,
content : 'puts 8'
}
]
}
end
2020-10-24 23:57:45 +05:30
2018-12-05 23:21:45 +05:30
let ( :valid_c_params ) do
2016-11-03 12:29:30 +05:30
{
2017-08-17 22:00:37 +05:30
branch : 'master' ,
2016-11-03 12:29:30 +05:30
commit_message : message ,
actions : [
{
action : 'create' ,
file_path : 'foo/bar/baz.txt' ,
content : 'puts 8'
}
]
}
end
2020-10-24 23:57:45 +05:30
2018-12-05 23:21:45 +05:30
let ( :valid_utf8_c_params ) do
2018-11-08 19:23:39 +05:30
{
branch : 'master' ,
commit_message : message ,
actions : [
{
action : 'create' ,
file_path : 'foo/bar/baz.txt' ,
content : 'puts 🦊'
}
]
}
end
2016-11-03 12:29:30 +05:30
2020-06-23 00:09:42 +05:30
shared_examples_for " successfully creates the commit " do
it " creates the commit " do
expect ( response ) . to have_gitlab_http_status ( :created )
expect ( json_response [ 'title' ] ) . to eq ( message )
expect ( json_response [ 'committer_name' ] ) . to eq ( user . name )
expect ( json_response [ 'committer_email' ] ) . to eq ( user . email )
end
end
2020-11-24 15:15:51 +05:30
context 'when using access token authentication' do
it 'does not increment the usage counters' do
expect ( :: Gitlab :: UsageDataCounters :: WebIdeCounter ) . not_to receive ( :increment_commits_count )
expect ( :: Gitlab :: UsageDataCounters :: EditorUniqueCounter ) . not_to receive ( :track_web_ide_edit_action )
2018-12-05 23:21:45 +05:30
2020-11-24 15:15:51 +05:30
post api ( url , user ) , params : valid_c_params
end
end
context 'when using warden' do
2022-01-26 12:08:38 +05:30
it 'increments usage counters' , :clean_gitlab_redis_sessions do
2020-11-24 15:15:51 +05:30
session_id = Rack :: Session :: SessionId . new ( '6919a6f1bb119dd7396fadc38fd18d0d' )
session_hash = { 'warden.user.user.key' = > [ [ user . id ] , user . encrypted_password [ 0 , 29 ] ] }
2022-01-26 12:08:38 +05:30
Gitlab :: Redis :: Sessions . with do | redis |
2020-11-24 15:15:51 +05:30
redis . set ( " session:gitlab: #{ session_id . private_id } " , Marshal . dump ( session_hash ) )
end
cookies [ Gitlab :: Application . config . session_options [ :key ] ] = session_id . public_id
expect ( :: Gitlab :: UsageDataCounters :: WebIdeCounter ) . to receive ( :increment_commits_count )
expect ( :: Gitlab :: UsageDataCounters :: EditorUniqueCounter ) . to receive ( :track_web_ide_edit_action )
post api ( url ) , params : valid_c_params
end
2018-12-05 23:21:45 +05:30
end
2020-06-23 00:09:42 +05:30
context 'a new file in project repo' do
before do
post api ( url , user ) , params : valid_c_params
end
2016-11-03 12:29:30 +05:30
2020-06-23 00:09:42 +05:30
it_behaves_like " successfully creates the commit "
2016-11-03 12:29:30 +05:30
end
2020-06-23 00:09:42 +05:30
context 'a new file with utf8 chars in project repo' do
before do
post api ( url , user ) , params : valid_utf8_c_params
end
2018-11-08 19:23:39 +05:30
2020-06-23 00:09:42 +05:30
it_behaves_like " successfully creates the commit "
2018-11-08 19:23:39 +05:30
end
2016-11-03 12:29:30 +05:30
it 'returns a 400 bad request if file exists' do
2019-02-15 15:39:39 +05:30
post api ( url , user ) , params : invalid_c_params
2016-11-03 12:29:30 +05:30
2020-04-08 14:13:33 +05:30
expect ( response ) . to have_gitlab_http_status ( :bad_request )
2016-11-03 12:29:30 +05:30
end
2017-08-17 22:00:37 +05:30
context 'with project path containing a dot in URL' do
let ( :url ) { " /projects/ #{ CGI . escape ( project . full_path ) } /repository/commits " }
it 'a new file in project repo' do
2019-02-15 15:39:39 +05:30
post api ( url , user ) , params : valid_c_params
2017-08-17 22:00:37 +05:30
2020-04-08 14:13:33 +05:30
expect ( response ) . to have_gitlab_http_status ( :created )
2017-08-17 22:00:37 +05:30
end
end
2019-09-04 21:01:54 +05:30
2019-10-12 21:52:04 +05:30
context 'when committing to a new branch' do
2019-09-04 21:01:54 +05:30
def last_commit_id ( project , branch_name )
project . repository . find_branch ( branch_name ) & . dereferenced_target & . id
end
2019-10-12 21:52:04 +05:30
before do
valid_c_params [ :start_branch ] = 'master'
valid_c_params [ :branch ] = 'patch'
end
2019-09-04 21:01:54 +05:30
2019-10-12 21:52:04 +05:30
context 'when the API user is a guest' do
let ( :public_project ) { create ( :project , :public , :repository ) }
let ( :url ) { " /projects/ #{ public_project . id } /repository/commits " }
let ( :guest ) { create ( :user ) . tap { | u | public_project . add_guest ( u ) } }
2019-09-04 21:01:54 +05:30
2019-10-12 21:52:04 +05:30
it 'returns a 403' do
post api ( url , guest ) , params : valid_c_params
2019-09-04 21:01:54 +05:30
2020-04-08 14:13:33 +05:30
expect ( response ) . to have_gitlab_http_status ( :forbidden )
2019-10-12 21:52:04 +05:30
end
2019-09-04 21:01:54 +05:30
2019-10-12 21:52:04 +05:30
context 'when start_project is provided' do
context 'when posting to a forked project the user owns' do
let ( :forked_project ) { fork_project ( public_project , guest , namespace : guest . namespace , repository : true ) }
let ( :url ) { " /projects/ #{ forked_project . id } /repository/commits " }
context 'identified by Integer (id)' do
before do
valid_c_params [ :start_project ] = public_project . id
end
2019-12-26 22:10:19 +05:30
it 'adds a new commit to forked_project and returns a 201' , :sidekiq_might_not_need_inline do
2019-10-12 21:52:04 +05:30
expect_request_with_status ( 201 ) { post api ( url , guest ) , params : valid_c_params }
. to change { last_commit_id ( forked_project , valid_c_params [ :branch ] ) }
. and not_change { last_commit_id ( public_project , valid_c_params [ :start_branch ] ) }
end
end
2019-09-04 21:01:54 +05:30
2019-10-12 21:52:04 +05:30
context 'identified by String (full_path)' do
before do
valid_c_params [ :start_project ] = public_project . full_path
end
2019-12-26 22:10:19 +05:30
it 'adds a new commit to forked_project and returns a 201' , :sidekiq_might_not_need_inline do
2019-10-12 21:52:04 +05:30
expect_request_with_status ( 201 ) { post api ( url , guest ) , params : valid_c_params }
. to change { last_commit_id ( forked_project , valid_c_params [ :branch ] ) }
. and not_change { last_commit_id ( public_project , valid_c_params [ :start_branch ] ) }
end
end
2019-12-26 22:10:19 +05:30
context 'when branch already exists' , :sidekiq_might_not_need_inline do
2019-10-12 21:52:04 +05:30
before do
valid_c_params . delete ( :start_branch )
valid_c_params [ :branch ] = 'master'
valid_c_params [ :start_project ] = public_project . id
end
it 'returns a 400' do
post api ( url , guest ) , params : valid_c_params
2020-04-08 14:13:33 +05:30
expect ( response ) . to have_gitlab_http_status ( :bad_request )
2019-10-12 21:52:04 +05:30
expect ( json_response [ 'message' ] ) . to eq ( " A branch called 'master' already exists. Switch to that branch in order to make changes " )
end
context 'when force is set to true' do
before do
valid_c_params [ :force ] = true
end
it 'adds a new commit to forked_project and returns a 201' do
expect_request_with_status ( 201 ) { post api ( url , guest ) , params : valid_c_params }
. to change { last_commit_id ( forked_project , valid_c_params [ :branch ] ) }
. and not_change { last_commit_id ( public_project , valid_c_params [ :branch ] ) }
end
end
2019-09-04 21:01:54 +05:30
end
2019-10-12 21:52:04 +05:30
context 'when start_sha is also provided' do
let ( :forked_project ) { fork_project ( public_project , guest , namespace : guest . namespace , repository : false ) }
let ( :start_sha ) { public_project . repository . commit . parent . sha }
2019-09-04 21:01:54 +05:30
2019-10-12 21:52:04 +05:30
before do
# initialize an empty repository to force fetching from the original project
forked_project . repository . create_if_not_exists
valid_c_params [ :start_project ] = public_project . id
valid_c_params [ :start_sha ] = start_sha
valid_c_params . delete ( :start_branch )
end
it 'fetches the start_sha from the original project to use as parent commit and returns a 201' do
expect_request_with_status ( 201 ) { post api ( url , guest ) , params : valid_c_params }
. to change { last_commit_id ( forked_project , valid_c_params [ :branch ] ) }
. and not_change { last_commit_id ( forked_project , 'master' ) }
last_commit = forked_project . repository . find_branch ( valid_c_params [ :branch ] ) . dereferenced_target
expect ( last_commit . parent_id ) . to eq ( start_sha )
end
2019-09-04 21:01:54 +05:30
end
end
2019-10-12 21:52:04 +05:30
context 'when the target project is not part of the fork network of start_project' do
let ( :unrelated_project ) { create ( :project , :public , :repository , creator : guest ) }
let ( :url ) { " /projects/ #{ unrelated_project . id } /repository/commits " }
2019-09-04 21:01:54 +05:30
before do
2019-10-12 21:52:04 +05:30
valid_c_params [ :start_branch ] = 'master'
valid_c_params [ :branch ] = 'patch'
valid_c_params [ :start_project ] = public_project . id
2019-09-04 21:01:54 +05:30
end
2019-10-12 21:52:04 +05:30
it 'returns a 403' do
post api ( url , guest ) , params : valid_c_params
2019-09-04 21:01:54 +05:30
2020-04-08 14:13:33 +05:30
expect ( response ) . to have_gitlab_http_status ( :forbidden )
2019-09-04 21:01:54 +05:30
end
end
end
2019-10-12 21:52:04 +05:30
context 'when posting to a forked project the user does not have write access' do
let ( :forked_project ) { fork_project ( public_project , user , namespace : user . namespace , repository : true ) }
let ( :url ) { " /projects/ #{ forked_project . id } /repository/commits " }
2019-09-04 21:01:54 +05:30
before do
2019-10-12 21:52:04 +05:30
valid_c_params [ :start_branch ] = 'master'
valid_c_params [ :branch ] = 'patch'
2019-09-04 21:01:54 +05:30
valid_c_params [ :start_project ] = public_project . id
end
it 'returns a 403' do
post api ( url , guest ) , params : valid_c_params
2020-04-08 14:13:33 +05:30
expect ( response ) . to have_gitlab_http_status ( :forbidden )
2019-09-04 21:01:54 +05:30
end
end
end
2019-10-12 21:52:04 +05:30
context 'when start_sha is provided' do
let ( :start_sha ) { project . repository . commit . parent . sha }
2019-09-04 21:01:54 +05:30
before do
2019-10-12 21:52:04 +05:30
valid_c_params [ :start_sha ] = start_sha
valid_c_params . delete ( :start_branch )
2019-09-04 21:01:54 +05:30
end
2019-10-12 21:52:04 +05:30
it 'returns a 400 if start_branch is also provided' do
valid_c_params [ :start_branch ] = 'master'
post api ( url , user ) , params : valid_c_params
2019-09-04 21:01:54 +05:30
2020-04-08 14:13:33 +05:30
expect ( response ) . to have_gitlab_http_status ( :bad_request )
2019-10-12 21:52:04 +05:30
expect ( json_response [ 'error' ] ) . to eq ( 'start_branch, start_sha are mutually exclusive' )
end
it 'returns a 400 if branch already exists' do
valid_c_params [ :branch ] = 'master'
post api ( url , user ) , params : valid_c_params
2020-04-08 14:13:33 +05:30
expect ( response ) . to have_gitlab_http_status ( :bad_request )
2019-10-12 21:52:04 +05:30
expect ( json_response [ 'message' ] ) . to eq ( " A branch called 'master' already exists. Switch to that branch in order to make changes " )
end
it 'returns a 400 if start_sha does not exist' do
valid_c_params [ :start_sha ] = '1' * 40
post api ( url , user ) , params : valid_c_params
2020-04-08 14:13:33 +05:30
expect ( response ) . to have_gitlab_http_status ( :bad_request )
2019-10-12 21:52:04 +05:30
expect ( json_response [ 'message' ] ) . to eq ( " Cannot find start_sha ' #{ valid_c_params [ :start_sha ] } ' " )
end
it 'returns a 400 if start_sha is not a full SHA' do
valid_c_params [ :start_sha ] = start_sha . slice ( 0 , 7 )
post api ( url , user ) , params : valid_c_params
2020-04-08 14:13:33 +05:30
expect ( response ) . to have_gitlab_http_status ( :bad_request )
2019-10-12 21:52:04 +05:30
expect ( json_response [ 'message' ] ) . to eq ( " Invalid start_sha ' #{ valid_c_params [ :start_sha ] } ' " )
end
it 'uses the start_sha as parent commit and returns a 201' do
expect_request_with_status ( 201 ) { post api ( url , user ) , params : valid_c_params }
. to change { last_commit_id ( project , valid_c_params [ :branch ] ) }
. and not_change { last_commit_id ( project , 'master' ) }
last_commit = project . repository . find_branch ( valid_c_params [ :branch ] ) . dereferenced_target
expect ( last_commit . parent_id ) . to eq ( start_sha )
end
context 'when force is set to true and branch already exists' do
before do
valid_c_params [ :force ] = true
valid_c_params [ :branch ] = 'master'
end
it 'uses the start_sha as parent commit and returns a 201' do
expect_request_with_status ( 201 ) { post api ( url , user ) , params : valid_c_params }
. to change { last_commit_id ( project , valid_c_params [ :branch ] ) }
last_commit = project . repository . find_branch ( valid_c_params [ :branch ] ) . dereferenced_target
expect ( last_commit . parent_id ) . to eq ( start_sha )
end
2019-09-04 21:01:54 +05:30
end
end
end
2016-11-03 12:29:30 +05:30
end
2017-08-17 22:00:37 +05:30
describe 'delete' do
2016-11-03 12:29:30 +05:30
let ( :message ) { 'Deleted file' }
2018-12-05 23:21:45 +05:30
let ( :invalid_d_params ) do
2016-11-03 12:29:30 +05:30
{
2017-08-17 22:00:37 +05:30
branch : 'markdown' ,
2016-11-03 12:29:30 +05:30
commit_message : message ,
actions : [
{
action : 'delete' ,
file_path : 'doc/api/projects.md'
}
]
}
end
2020-10-24 23:57:45 +05:30
2018-12-05 23:21:45 +05:30
let ( :valid_d_params ) do
2016-11-03 12:29:30 +05:30
{
2017-08-17 22:00:37 +05:30
branch : 'markdown' ,
2016-11-03 12:29:30 +05:30
commit_message : message ,
actions : [
{
action : 'delete' ,
file_path : 'doc/api/users.md'
}
]
}
end
it 'an existing file in project repo' do
2019-02-15 15:39:39 +05:30
post api ( url , user ) , params : valid_d_params
2016-11-03 12:29:30 +05:30
2020-04-08 14:13:33 +05:30
expect ( response ) . to have_gitlab_http_status ( :created )
2016-11-03 12:29:30 +05:30
expect ( json_response [ 'title' ] ) . to eq ( message )
end
it 'returns a 400 bad request if file does not exist' do
2019-02-15 15:39:39 +05:30
post api ( url , user ) , params : invalid_d_params
2016-11-03 12:29:30 +05:30
2020-04-08 14:13:33 +05:30
expect ( response ) . to have_gitlab_http_status ( :bad_request )
2016-11-03 12:29:30 +05:30
end
end
2017-08-17 22:00:37 +05:30
describe 'move' do
2016-11-03 12:29:30 +05:30
let ( :message ) { 'Moved file' }
2018-12-05 23:21:45 +05:30
let ( :invalid_m_params ) do
2016-11-03 12:29:30 +05:30
{
2017-08-17 22:00:37 +05:30
branch : 'feature' ,
2016-11-03 12:29:30 +05:30
commit_message : message ,
actions : [
{
action : 'move' ,
file_path : 'CHANGELOG' ,
previous_path : 'VERSION' ,
content : '6.7.0.pre'
}
]
}
end
2020-10-24 23:57:45 +05:30
2018-12-05 23:21:45 +05:30
let ( :valid_m_params ) do
2016-11-03 12:29:30 +05:30
{
2017-08-17 22:00:37 +05:30
branch : 'feature' ,
2016-11-03 12:29:30 +05:30
commit_message : message ,
actions : [
{
action : 'move' ,
file_path : 'VERSION.txt' ,
previous_path : 'VERSION' ,
content : '6.7.0.pre'
}
]
}
end
it 'an existing file in project repo' do
2019-02-15 15:39:39 +05:30
post api ( url , user ) , params : valid_m_params
2016-11-03 12:29:30 +05:30
2020-04-08 14:13:33 +05:30
expect ( response ) . to have_gitlab_http_status ( :created )
2016-11-03 12:29:30 +05:30
expect ( json_response [ 'title' ] ) . to eq ( message )
end
it 'returns a 400 bad request if file does not exist' do
2019-02-15 15:39:39 +05:30
post api ( url , user ) , params : invalid_m_params
2016-11-03 12:29:30 +05:30
2020-04-08 14:13:33 +05:30
expect ( response ) . to have_gitlab_http_status ( :bad_request )
2016-11-03 12:29:30 +05:30
end
end
2017-08-17 22:00:37 +05:30
describe 'update' do
2016-11-03 12:29:30 +05:30
let ( :message ) { 'Updated file' }
2018-12-05 23:21:45 +05:30
let ( :invalid_u_params ) do
2016-11-03 12:29:30 +05:30
{
2017-08-17 22:00:37 +05:30
branch : 'master' ,
2016-11-03 12:29:30 +05:30
commit_message : message ,
actions : [
{
action : 'update' ,
file_path : 'foo/bar.baz' ,
content : 'puts 8'
}
]
}
end
2020-10-24 23:57:45 +05:30
2018-12-05 23:21:45 +05:30
let ( :valid_u_params ) do
2016-11-03 12:29:30 +05:30
{
2017-08-17 22:00:37 +05:30
branch : 'master' ,
2016-11-03 12:29:30 +05:30
commit_message : message ,
actions : [
{
action : 'update' ,
file_path : 'files/ruby/popen.rb' ,
content : 'puts 8'
}
]
}
end
it 'an existing file in project repo' do
2019-02-15 15:39:39 +05:30
post api ( url , user ) , params : valid_u_params
2016-11-03 12:29:30 +05:30
2020-04-08 14:13:33 +05:30
expect ( response ) . to have_gitlab_http_status ( :created )
2016-11-03 12:29:30 +05:30
expect ( json_response [ 'title' ] ) . to eq ( message )
end
it 'returns a 400 bad request if file does not exist' do
2019-02-15 15:39:39 +05:30
post api ( url , user ) , params : invalid_u_params
2016-11-03 12:29:30 +05:30
2020-04-08 14:13:33 +05:30
expect ( response ) . to have_gitlab_http_status ( :bad_request )
2016-11-03 12:29:30 +05:30
end
end
2018-12-05 23:21:45 +05:30
describe 'chmod' do
let ( :message ) { 'Chmod +x file' }
let ( :file_path ) { 'files/ruby/popen.rb' }
let ( :execute_filemode ) { true }
let ( :params ) do
{
branch : 'master' ,
commit_message : message ,
actions : [
{
action : 'chmod' ,
file_path : file_path ,
execute_filemode : execute_filemode
}
]
}
end
it 'responds with success' do
2019-02-15 15:39:39 +05:30
post api ( url , user ) , params : params
2018-12-05 23:21:45 +05:30
2020-04-08 14:13:33 +05:30
expect ( response ) . to have_gitlab_http_status ( :created )
2018-12-05 23:21:45 +05:30
expect ( json_response [ 'title' ] ) . to eq ( message )
end
context 'when execute_filemode is false' do
let ( :execute_filemode ) { false }
it 'responds with success' do
2019-02-15 15:39:39 +05:30
post api ( url , user ) , params : params
2018-12-05 23:21:45 +05:30
2020-04-08 14:13:33 +05:30
expect ( response ) . to have_gitlab_http_status ( :created )
2018-12-05 23:21:45 +05:30
expect ( json_response [ 'title' ] ) . to eq ( message )
end
end
context " when the file doesn't exists " do
let ( :file_path ) { 'foo/bar.baz' }
it " responds with 400 " do
2019-02-15 15:39:39 +05:30
post api ( url , user ) , params : params
2018-12-05 23:21:45 +05:30
2020-04-08 14:13:33 +05:30
expect ( response ) . to have_gitlab_http_status ( :bad_request )
2018-12-05 23:21:45 +05:30
expect ( json_response [ 'message' ] ) . to eq ( " A file with this name doesn't exist " )
end
end
end
2017-08-17 22:00:37 +05:30
describe 'multiple operations' do
2016-11-03 12:29:30 +05:30
let ( :message ) { 'Multiple actions' }
2018-12-05 23:21:45 +05:30
let ( :invalid_mo_params ) do
2016-11-03 12:29:30 +05:30
{
2017-08-17 22:00:37 +05:30
branch : 'master' ,
2016-11-03 12:29:30 +05:30
commit_message : message ,
actions : [
{
action : 'create' ,
file_path : 'files/ruby/popen.rb' ,
content : 'puts 8'
} ,
{
action : 'delete' ,
file_path : 'doc/api/projects.md'
} ,
{
action : 'move' ,
file_path : 'CHANGELOG' ,
previous_path : 'VERSION' ,
content : '6.7.0.pre'
} ,
{
action : 'update' ,
file_path : 'foo/bar.baz' ,
content : 'puts 8'
2018-12-05 23:21:45 +05:30
} ,
{
action : 'chmod' ,
file_path : 'files/ruby/popen.rb' ,
execute_filemode : true
2016-11-03 12:29:30 +05:30
}
]
}
end
2020-10-24 23:57:45 +05:30
2018-12-05 23:21:45 +05:30
let ( :valid_mo_params ) do
2016-11-03 12:29:30 +05:30
{
2017-08-17 22:00:37 +05:30
branch : 'master' ,
2016-11-03 12:29:30 +05:30
commit_message : message ,
actions : [
{
action : 'create' ,
file_path : 'foo/bar/baz.txt' ,
content : 'puts 8'
} ,
{
action : 'delete' ,
file_path : 'Gemfile.zip'
} ,
{
action : 'move' ,
file_path : 'VERSION.txt' ,
previous_path : 'VERSION' ,
content : '6.7.0.pre'
} ,
{
action : 'update' ,
file_path : 'files/ruby/popen.rb' ,
content : 'puts 8'
2018-12-05 23:21:45 +05:30
} ,
{
action : 'chmod' ,
file_path : 'files/ruby/popen.rb' ,
execute_filemode : true
2016-11-03 12:29:30 +05:30
}
]
}
end
2018-12-13 13:39:08 +05:30
it 'are committed as one in project repo' do
2019-02-15 15:39:39 +05:30
post api ( url , user ) , params : valid_mo_params
2016-11-03 12:29:30 +05:30
2020-04-08 14:13:33 +05:30
expect ( response ) . to have_gitlab_http_status ( :created )
2016-11-03 12:29:30 +05:30
expect ( json_response [ 'title' ] ) . to eq ( message )
end
2018-12-05 23:21:45 +05:30
it 'includes the commit stats' do
2019-02-15 15:39:39 +05:30
post api ( url , user ) , params : valid_mo_params
2018-12-05 23:21:45 +05:30
2020-04-08 14:13:33 +05:30
expect ( response ) . to have_gitlab_http_status ( :created )
2018-12-05 23:21:45 +05:30
expect ( json_response ) . to include 'stats'
end
it " doesn't include the commit stats when stats is false " do
2019-02-15 15:39:39 +05:30
post api ( url , user ) , params : valid_mo_params . merge ( stats : false )
2018-12-05 23:21:45 +05:30
2020-04-08 14:13:33 +05:30
expect ( response ) . to have_gitlab_http_status ( :created )
2018-12-05 23:21:45 +05:30
expect ( json_response ) . not_to include 'stats'
end
2016-11-03 12:29:30 +05:30
it 'return a 400 bad request if there are any issues' do
2019-02-15 15:39:39 +05:30
post api ( url , user ) , params : invalid_mo_params
2016-11-03 12:29:30 +05:30
2020-04-08 14:13:33 +05:30
expect ( response ) . to have_gitlab_http_status ( :bad_request )
2016-11-03 12:29:30 +05:30
end
end
2018-11-18 11:00:15 +05:30
context 'when committing into a fork as a maintainer' do
include_context 'merge request allowing collaboration'
let ( :project_id ) { forked_project . id }
def push_params ( branch_name )
{
branch : branch_name ,
commit_message : 'Hello world' ,
actions : [
{
action : 'create' ,
file_path : 'foo/bar/baz.txt' ,
content : 'puts 8'
}
]
}
end
2019-12-26 22:10:19 +05:30
it 'allows pushing to the source branch of the merge request' , :sidekiq_might_not_need_inline do
2019-02-15 15:39:39 +05:30
post api ( url , user ) , params : push_params ( 'feature' )
2018-11-18 11:00:15 +05:30
expect ( response ) . to have_gitlab_http_status ( :created )
end
it 'denies pushing to another branch' do
2019-02-15 15:39:39 +05:30
post api ( url , user ) , params : push_params ( 'other-branch' )
2018-11-18 11:00:15 +05:30
expect ( response ) . to have_gitlab_http_status ( :forbidden )
end
end
2016-11-03 12:29:30 +05:30
end
2018-03-27 19:54:05 +05:30
describe 'GET /projects/:id/repository/commits/:sha/refs' do
let ( :project ) { create ( :project , :public , :repository ) }
let ( :tag ) { project . repository . find_tag ( 'v1.1.0' ) }
let ( :commit_id ) { tag . dereferenced_target . id }
let ( :route ) { " /projects/ #{ project_id } /repository/commits/ #{ commit_id } /refs " }
context 'when ref does not exist' do
let ( :commit_id ) { 'unknown' }
it_behaves_like '404 response' do
let ( :request ) { get api ( route , current_user ) }
let ( :message ) { '404 Commit Not Found' }
end
end
context 'when repository is disabled' do
include_context 'disabled repository'
2019-09-30 21:07:59 +05:30
it_behaves_like '404 response' do
2018-03-27 19:54:05 +05:30
let ( :request ) { get api ( route , current_user ) }
end
end
context 'for a valid commit' do
it 'returns all refs with no scope' do
2019-02-15 15:39:39 +05:30
get api ( route , current_user ) , params : { per_page : 100 }
2018-03-27 19:54:05 +05:30
refs = project . repository . branch_names_contains ( commit_id ) . map { | name | [ 'branch' , name ] }
refs . concat ( project . repository . tag_names_contains ( commit_id ) . map { | name | [ 'tag' , name ] } )
2020-04-08 14:13:33 +05:30
expect ( response ) . to have_gitlab_http_status ( :ok )
2021-01-03 14:25:43 +05:30
expect ( response ) . to include_limited_pagination_headers
2018-03-27 19:54:05 +05:30
expect ( json_response ) . to be_an Array
expect ( json_response . map { | r | [ r [ 'type' ] , r [ 'name' ] ] } . compact ) . to eq ( refs )
end
it 'returns all refs' do
2019-02-15 15:39:39 +05:30
get api ( route , current_user ) , params : { type : 'all' , per_page : 100 }
2018-03-27 19:54:05 +05:30
refs = project . repository . branch_names_contains ( commit_id ) . map { | name | [ 'branch' , name ] }
refs . concat ( project . repository . tag_names_contains ( commit_id ) . map { | name | [ 'tag' , name ] } )
2020-04-08 14:13:33 +05:30
expect ( response ) . to have_gitlab_http_status ( :ok )
2018-03-27 19:54:05 +05:30
expect ( json_response . map { | r | [ r [ 'type' ] , r [ 'name' ] ] } . compact ) . to eq ( refs )
end
it 'returns the branch refs' do
2019-02-15 15:39:39 +05:30
get api ( route , current_user ) , params : { type : 'branch' , per_page : 100 }
2018-03-27 19:54:05 +05:30
refs = project . repository . branch_names_contains ( commit_id ) . map { | name | [ 'branch' , name ] }
2020-04-08 14:13:33 +05:30
expect ( response ) . to have_gitlab_http_status ( :ok )
2018-03-27 19:54:05 +05:30
expect ( json_response . map { | r | [ r [ 'type' ] , r [ 'name' ] ] } . compact ) . to eq ( refs )
end
it 'returns the tag refs' do
2019-02-15 15:39:39 +05:30
get api ( route , current_user ) , params : { type : 'tag' , per_page : 100 }
2018-03-27 19:54:05 +05:30
refs = project . repository . tag_names_contains ( commit_id ) . map { | name | [ 'tag' , name ] }
2020-04-08 14:13:33 +05:30
expect ( response ) . to have_gitlab_http_status ( :ok )
2018-03-27 19:54:05 +05:30
expect ( json_response . map { | r | [ r [ 'type' ] , r [ 'name' ] ] } . compact ) . to eq ( refs )
end
end
end
2017-09-10 17:25:29 +05:30
describe 'GET /projects/:id/repository/commits/:sha' do
let ( :commit ) { project . repository . commit }
let ( :commit_id ) { commit . id }
let ( :route ) { " /projects/ #{ project_id } /repository/commits/ #{ commit_id } " }
2016-09-13 17:45:13 +05:30
2017-09-10 17:25:29 +05:30
shared_examples_for 'ref commit' do
it 'returns the ref last commit' do
get api ( route , current_user )
2020-04-08 14:13:33 +05:30
expect ( response ) . to have_gitlab_http_status ( :ok )
2017-09-10 17:25:29 +05:30
expect ( response ) . to match_response_schema ( 'public_api/v4/commit/detail' )
2017-08-17 22:00:37 +05:30
expect ( json_response [ 'id' ] ) . to eq ( commit . id )
expect ( json_response [ 'short_id' ] ) . to eq ( commit . short_id )
expect ( json_response [ 'title' ] ) . to eq ( commit . title )
expect ( json_response [ 'message' ] ) . to eq ( commit . safe_message )
expect ( json_response [ 'author_name' ] ) . to eq ( commit . author_name )
expect ( json_response [ 'author_email' ] ) . to eq ( commit . author_email )
expect ( json_response [ 'authored_date' ] ) . to eq ( commit . authored_date . iso8601 ( 3 ) )
expect ( json_response [ 'committer_name' ] ) . to eq ( commit . committer_name )
expect ( json_response [ 'committer_email' ] ) . to eq ( commit . committer_email )
expect ( json_response [ 'committed_date' ] ) . to eq ( commit . committed_date . iso8601 ( 3 ) )
expect ( json_response [ 'parent_ids' ] ) . to eq ( commit . parent_ids )
expect ( json_response [ 'stats' ] [ 'additions' ] ) . to eq ( commit . stats . additions )
expect ( json_response [ 'stats' ] [ 'deletions' ] ) . to eq ( commit . stats . deletions )
expect ( json_response [ 'stats' ] [ 'total' ] ) . to eq ( commit . stats . total )
2017-09-10 17:25:29 +05:30
expect ( json_response [ 'status' ] ) . to be_nil
2018-03-17 18:26:18 +05:30
expect ( json_response [ 'last_pipeline' ] ) . to be_nil
2014-09-02 18:07:02 +05:30
end
2017-09-10 17:25:29 +05:30
context 'when ref does not exist' do
let ( :commit_id ) { 'unknown' }
it_behaves_like '404 response' do
let ( :request ) { get api ( route , current_user ) }
let ( :message ) { '404 Commit Not Found' }
end
2014-09-02 18:07:02 +05:30
end
2015-10-24 18:46:33 +05:30
2017-09-10 17:25:29 +05:30
context 'when repository is disabled' do
include_context 'disabled repository'
2016-09-13 17:45:13 +05:30
2019-09-30 21:07:59 +05:30
it_behaves_like '404 response' do
2017-09-10 17:25:29 +05:30
let ( :request ) { get api ( route , current_user ) }
end
2015-10-24 18:46:33 +05:30
end
2017-09-10 17:25:29 +05:30
end
2015-10-24 18:46:33 +05:30
2020-02-01 01:16:34 +05:30
shared_examples_for 'ref with pipeline' do
let! ( :pipeline ) do
project
. ci_pipelines
. create! ( source : :push , ref : 'master' , sha : commit . sha , protected : false )
end
it 'includes status as "created" and a last_pipeline object' do
get api ( route , current_user )
2020-04-08 14:13:33 +05:30
expect ( response ) . to have_gitlab_http_status ( :ok )
2020-02-01 01:16:34 +05:30
expect ( response ) . to match_response_schema ( 'public_api/v4/commit/detail' )
expect ( json_response [ 'status' ] ) . to eq ( 'created' )
expect ( json_response [ 'last_pipeline' ] [ 'id' ] ) . to eq ( pipeline . id )
expect ( json_response [ 'last_pipeline' ] [ 'ref' ] ) . to eq ( pipeline . ref )
expect ( json_response [ 'last_pipeline' ] [ 'sha' ] ) . to eq ( pipeline . sha )
expect ( json_response [ 'last_pipeline' ] [ 'status' ] ) . to eq ( pipeline . status )
end
context 'when pipeline succeeds' do
before do
pipeline . update! ( status : 'success' )
end
it 'includes a "success" status' do
get api ( route , current_user )
2020-04-08 14:13:33 +05:30
expect ( response ) . to have_gitlab_http_status ( :ok )
2020-02-01 01:16:34 +05:30
expect ( response ) . to match_response_schema ( 'public_api/v4/commit/detail' )
expect ( json_response [ 'status' ] ) . to eq ( 'success' )
end
end
end
shared_examples_for 'ref with unaccessible pipeline' do
let! ( :pipeline ) do
project
. ci_pipelines
. create! ( source : :push , ref : 'master' , sha : commit . sha , protected : false )
end
it 'does not include last_pipeline' do
get api ( route , current_user )
expect ( response ) . to match_response_schema ( 'public_api/v4/commit/detail' )
2020-04-08 14:13:33 +05:30
expect ( response ) . to have_gitlab_http_status ( :ok )
2020-02-01 01:16:34 +05:30
expect ( json_response [ 'last_pipeline' ] ) . to be_nil
end
end
2018-03-17 18:26:18 +05:30
context 'when stat param' do
let ( :route ) { " /projects/ #{ project_id } /repository/commits/ #{ commit_id } " }
it 'is not present return stats by default' do
get api ( route , user )
2020-04-08 14:13:33 +05:30
expect ( response ) . to have_gitlab_http_status ( :ok )
2018-03-17 18:26:18 +05:30
expect ( json_response ) . to include 'stats'
end
it " is false it does not include stats " do
2019-02-15 15:39:39 +05:30
get api ( route , user ) , params : { stats : false }
2018-03-17 18:26:18 +05:30
2020-04-08 14:13:33 +05:30
expect ( response ) . to have_gitlab_http_status ( :ok )
2018-03-17 18:26:18 +05:30
expect ( json_response ) . not_to include 'stats'
end
it " is true it includes stats " do
2019-02-15 15:39:39 +05:30
get api ( route , user ) , params : { stats : true }
2018-03-17 18:26:18 +05:30
2020-04-08 14:13:33 +05:30
expect ( response ) . to have_gitlab_http_status ( :ok )
2018-03-17 18:26:18 +05:30
expect ( json_response ) . to include 'stats'
end
end
2017-09-10 17:25:29 +05:30
context 'when unauthenticated' , 'and project is public' do
let ( :project ) { create ( :project , :public , :repository ) }
2016-09-13 17:45:13 +05:30
2017-09-10 17:25:29 +05:30
it_behaves_like 'ref commit'
2020-02-01 01:16:34 +05:30
it_behaves_like 'ref with pipeline'
context 'with private builds' do
before do
project . project_feature . update! ( builds_access_level : ProjectFeature :: PRIVATE )
end
it_behaves_like 'ref with unaccessible pipeline'
end
2017-09-10 17:25:29 +05:30
end
2016-09-13 17:45:13 +05:30
2017-09-10 17:25:29 +05:30
context 'when unauthenticated' , 'and project is private' do
it_behaves_like '404 response' do
let ( :request ) { get api ( route ) }
let ( :message ) { '404 Project Not Found' }
2015-10-24 18:46:33 +05:30
end
2017-09-10 17:25:29 +05:30
end
2016-09-13 17:45:13 +05:30
2018-11-18 11:00:15 +05:30
context 'when authenticated' , 'as a maintainer' do
2017-09-10 17:25:29 +05:30
let ( :current_user ) { user }
2016-09-13 17:45:13 +05:30
2017-09-10 17:25:29 +05:30
it_behaves_like 'ref commit'
2020-02-01 01:16:34 +05:30
it_behaves_like 'ref with pipeline'
context 'when builds are disabled' do
before do
project
. project_feature
. update! ( builds_access_level : ProjectFeature :: DISABLED )
end
it_behaves_like 'ref with unaccessible pipeline'
end
2016-09-13 17:45:13 +05:30
2017-09-10 17:25:29 +05:30
context 'when branch contains a dot' do
let ( :commit ) { project . repository . commit ( branch_with_dot . name ) }
let ( :commit_id ) { branch_with_dot . name }
it_behaves_like 'ref commit'
2016-09-13 17:45:13 +05:30
end
2014-09-02 18:07:02 +05:30
2017-09-10 17:25:29 +05:30
context 'when branch contains a slash' do
let ( :commit_id ) { branch_with_slash . name }
it_behaves_like '404 response' do
let ( :request ) { get api ( route , current_user ) }
end
end
context 'when branch contains an escaped slash' do
let ( :commit ) { project . repository . commit ( branch_with_slash . name ) }
let ( :commit_id ) { CGI . escape ( branch_with_slash . name ) }
it_behaves_like 'ref commit'
end
context 'requesting with the escaped project full path' do
let ( :project_id ) { CGI . escape ( project . full_path ) }
it_behaves_like 'ref commit'
context 'when branch contains a dot' do
let ( :commit ) { project . repository . commit ( branch_with_dot . name ) }
let ( :commit_id ) { branch_with_dot . name }
it_behaves_like 'ref commit'
end
end
2020-02-01 01:16:34 +05:30
end
2017-09-10 17:25:29 +05:30
2020-02-01 01:16:34 +05:30
context 'when authenticated' , 'as a developer' do
let ( :current_user ) { developer }
2017-09-10 17:25:29 +05:30
2020-02-01 01:16:34 +05:30
it_behaves_like 'ref commit'
it_behaves_like 'ref with pipeline'
2017-09-10 17:25:29 +05:30
2020-02-01 01:16:34 +05:30
context 'with private builds' do
before do
project . project_feature . update! ( builds_access_level : ProjectFeature :: PRIVATE )
2017-09-10 17:25:29 +05:30
end
2020-02-01 01:16:34 +05:30
it_behaves_like 'ref with pipeline'
end
end
2017-09-10 17:25:29 +05:30
2020-02-01 01:16:34 +05:30
context 'when authenticated' , 'as a guest' do
let ( :current_user ) { guest }
2017-09-10 17:25:29 +05:30
2020-02-01 01:16:34 +05:30
it_behaves_like '403 response' do
let ( :request ) { get api ( route , guest ) }
let ( :message ) { '403 Forbidden' }
end
end
context 'when authenticated' , 'as a non member' do
let ( :current_user ) { create ( :user ) }
it_behaves_like '403 response' do
let ( :request ) { get api ( route , guest ) }
let ( :message ) { '403 Forbidden' }
end
end
context 'when authenticated' , 'as non_member and project is public' do
let ( :current_user ) { create ( :user ) }
let ( :project ) { create ( :project , :public , :repository ) }
it_behaves_like 'ref with pipeline'
context 'with private builds' do
before do
project . project_feature . update! ( builds_access_level : ProjectFeature :: PRIVATE )
2017-09-10 17:25:29 +05:30
end
2020-02-01 01:16:34 +05:30
it_behaves_like 'ref with unaccessible pipeline'
2014-09-02 18:07:02 +05:30
end
end
end
2017-09-10 17:25:29 +05:30
describe 'GET /projects/:id/repository/commits/:sha/diff' do
let ( :commit ) { project . repository . commit }
let ( :commit_id ) { commit . id }
let ( :route ) { " /projects/ #{ project_id } /repository/commits/ #{ commit_id } /diff " }
2014-09-02 18:07:02 +05:30
2017-09-10 17:25:29 +05:30
shared_examples_for 'ref diff' do
it 'returns the diff of the selected commit' do
get api ( route , current_user )
2014-09-02 18:07:02 +05:30
2020-04-08 14:13:33 +05:30
expect ( response ) . to have_gitlab_http_status ( :ok )
2021-01-03 14:25:43 +05:30
expect ( response ) . to include_limited_pagination_headers
2017-09-10 17:25:29 +05:30
expect ( json_response . size ) . to be > = 1
expect ( json_response . first . keys ) . to include 'diff'
2014-09-02 18:07:02 +05:30
end
2019-12-26 22:10:19 +05:30
context 'when hard limits are lower than the number of files' do
before do
allow ( Commit ) . to receive ( :max_diff_options ) . and_return ( max_files : 1 )
end
it 'respects the limit' do
get api ( route , current_user )
2020-04-08 14:13:33 +05:30
expect ( response ) . to have_gitlab_http_status ( :ok )
2021-01-03 14:25:43 +05:30
expect ( response ) . to include_limited_pagination_headers
2019-12-26 22:10:19 +05:30
expect ( json_response . size ) . to be < = 1
end
end
2017-09-10 17:25:29 +05:30
context 'when ref does not exist' do
let ( :commit_id ) { 'unknown' }
it_behaves_like '404 response' do
let ( :request ) { get api ( route , current_user ) }
let ( :message ) { '404 Commit Not Found' }
end
end
context 'when repository is disabled' do
include_context 'disabled repository'
2019-09-30 21:07:59 +05:30
it_behaves_like '404 response' do
2017-09-10 17:25:29 +05:30
let ( :request ) { get api ( route , current_user ) }
end
2014-09-02 18:07:02 +05:30
end
end
2017-09-10 17:25:29 +05:30
context 'when unauthenticated' , 'and project is public' do
let ( :project ) { create ( :project , :public , :repository ) }
it_behaves_like 'ref diff'
end
context 'when unauthenticated' , 'and project is private' do
it_behaves_like '404 response' do
let ( :request ) { get api ( route ) }
let ( :message ) { '404 Project Not Found' }
end
end
2018-11-18 11:00:15 +05:30
context 'when authenticated' , 'as a maintainer' do
2017-09-10 17:25:29 +05:30
let ( :current_user ) { user }
it_behaves_like 'ref diff'
context 'when branch contains a dot' do
let ( :commit_id ) { branch_with_dot . name }
it_behaves_like 'ref diff'
end
context 'when branch contains a slash' do
let ( :commit_id ) { branch_with_slash . name }
it_behaves_like '404 response' do
let ( :request ) { get api ( route , current_user ) }
end
end
context 'when branch contains an escaped slash' do
let ( :commit_id ) { CGI . escape ( branch_with_slash . name ) }
it_behaves_like 'ref diff'
end
context 'requesting with the escaped project full path' do
let ( :project_id ) { CGI . escape ( project . full_path ) }
it_behaves_like 'ref diff'
context 'when branch contains a dot' do
let ( :commit_id ) { branch_with_dot . name }
it_behaves_like 'ref diff'
end
2015-04-26 12:48:37 +05:30
end
2018-03-17 18:26:18 +05:30
context 'when binary diff are treated as text' do
let ( :commit_id ) { TestEnv :: BRANCH_SHA [ 'add-pdf-text-binary' ] }
it_behaves_like 'ref diff'
end
2015-04-26 12:48:37 +05:30
end
end
2017-09-10 17:25:29 +05:30
describe 'GET /projects/:id/repository/commits/:sha/comments' do
let ( :commit ) { project . repository . commit }
let ( :commit_id ) { commit . id }
let ( :route ) { " /projects/ #{ project_id } /repository/commits/ #{ commit_id } /comments " }
shared_examples_for 'ref comments' do
context 'when ref exists' do
before do
create ( :note_on_commit , author : user , project : project , commit_id : commit . id , note : 'a comment on a commit' )
create ( :note_on_commit , author : user , project : project , commit_id : commit . id , note : 'another comment on a commit' )
end
it 'returns the diff of the selected commit' do
get api ( route , current_user )
2020-04-08 14:13:33 +05:30
expect ( response ) . to have_gitlab_http_status ( :ok )
2017-09-10 17:25:29 +05:30
expect ( response ) . to match_response_schema ( 'public_api/v4/commit_notes' )
expect ( json_response . size ) . to eq ( 2 )
expect ( json_response . first [ 'note' ] ) . to eq ( 'a comment on a commit' )
expect ( json_response . first [ 'author' ] [ 'id' ] ) . to eq ( user . id )
end
2015-04-26 12:48:37 +05:30
end
2017-09-10 17:25:29 +05:30
context 'when ref does not exist' do
let ( :commit_id ) { 'unknown' }
it_behaves_like '404 response' do
let ( :request ) { get api ( route , current_user ) }
let ( :message ) { '404 Commit Not Found' }
end
end
context 'when repository is disabled' do
include_context 'disabled repository'
2019-09-30 21:07:59 +05:30
it_behaves_like '404 response' do
2017-09-10 17:25:29 +05:30
let ( :request ) { get api ( route , current_user ) }
end
end
end
context 'when unauthenticated' , 'and project is public' do
let ( :project ) { create ( :project , :public , :repository ) }
it_behaves_like 'ref comments'
end
context 'when unauthenticated' , 'and project is private' do
it_behaves_like '404 response' do
let ( :request ) { get api ( route ) }
let ( :message ) { '404 Project Not Found' }
2015-04-26 12:48:37 +05:30
end
end
2018-11-18 11:00:15 +05:30
context 'when authenticated' , 'as a maintainer' do
2017-09-10 17:25:29 +05:30
let ( :current_user ) { user }
it_behaves_like 'ref comments'
context 'when branch contains a dot' do
let ( :commit ) { project . repository . commit ( branch_with_dot . name ) }
let ( :commit_id ) { branch_with_dot . name }
it_behaves_like 'ref comments'
end
context 'when branch contains a slash' do
let ( :commit ) { project . repository . commit ( branch_with_slash . name ) }
let ( :commit_id ) { branch_with_slash . name }
it_behaves_like '404 response' do
let ( :request ) { get api ( route , current_user ) }
end
end
context 'when branch contains an escaped slash' do
let ( :commit ) { project . repository . commit ( branch_with_slash . name ) }
let ( :commit_id ) { CGI . escape ( branch_with_slash . name ) }
it_behaves_like 'ref comments'
end
context 'requesting with the escaped project full path' do
let ( :project_id ) { CGI . escape ( project . full_path ) }
it_behaves_like 'ref comments'
context 'when branch contains a dot' do
let ( :commit ) { project . repository . commit ( branch_with_dot . name ) }
let ( :commit_id ) { branch_with_dot . name }
it_behaves_like 'ref comments'
end
2015-04-26 12:48:37 +05:30
end
2021-04-29 21:17:54 +05:30
context 'multiple notes' do
let! ( :note ) { create ( :diff_note_on_commit , project : project ) }
let ( :commit ) { note . commit }
let ( :commit_id ) { note . commit_id }
it 'are returned without N + 1' do
get api ( route , current_user ) # warm up the cache
control_count = ActiveRecord :: QueryRecorder . new { get api ( route , current_user ) } . count
create ( :diff_note_on_commit , project : project , author : create ( :user ) )
expect { get api ( route , current_user ) } . not_to exceed_query_limit ( control_count )
end
end
2015-04-26 12:48:37 +05:30
end
2017-08-17 22:00:37 +05:30
context 'when the commit is present on two projects' do
2017-09-10 17:25:29 +05:30
let ( :forked_project ) { create ( :project , :repository , creator : guest , namespace : guest . namespace ) }
let! ( :forked_project_note ) { create ( :note_on_commit , author : guest , project : forked_project , commit_id : forked_project . repository . commit . id , note : 'a comment on a commit for fork' ) }
let ( :project_id ) { forked_project . id }
let ( :commit_id ) { forked_project . repository . commit . id }
2017-08-17 22:00:37 +05:30
it 'returns the comments for the target project' do
2017-09-10 17:25:29 +05:30
get api ( route , guest )
2017-08-17 22:00:37 +05:30
2020-04-08 14:13:33 +05:30
expect ( response ) . to have_gitlab_http_status ( :ok )
2017-09-10 17:25:29 +05:30
expect ( response ) . to match_response_schema ( 'public_api/v4/commit_notes' )
expect ( json_response . size ) . to eq ( 1 )
2017-08-17 22:00:37 +05:30
expect ( json_response . first [ 'note' ] ) . to eq ( 'a comment on a commit for fork' )
2017-09-10 17:25:29 +05:30
expect ( json_response . first [ 'author' ] [ 'id' ] ) . to eq ( guest . id )
2017-08-17 22:00:37 +05:30
end
end
end
describe 'POST :id/repository/commits/:sha/cherry_pick' do
2017-09-10 17:25:29 +05:30
let ( :commit ) { project . commit ( '7d3b0f7cff5f37573aea97cebfd5692ea1689924' ) }
let ( :commit_id ) { commit . id }
let ( :branch ) { 'master' }
let ( :route ) { " /projects/ #{ project_id } /repository/commits/ #{ commit_id } /cherry_pick " }
shared_examples_for 'ref cherry-pick' do
context 'when ref exists' do
it 'cherry-picks the ref commit' do
2019-02-15 15:39:39 +05:30
post api ( route , current_user ) , params : { branch : branch }
2017-09-10 17:25:29 +05:30
2020-04-08 14:13:33 +05:30
expect ( response ) . to have_gitlab_http_status ( :created )
2017-09-10 17:25:29 +05:30
expect ( response ) . to match_response_schema ( 'public_api/v4/commit/basic' )
expect ( json_response [ 'title' ] ) . to eq ( commit . title )
2018-03-17 18:26:18 +05:30
expect ( json_response [ 'message' ] ) . to eq ( commit . cherry_pick_message ( user ) )
2017-09-10 17:25:29 +05:30
expect ( json_response [ 'author_name' ] ) . to eq ( commit . author_name )
expect ( json_response [ 'committer_name' ] ) . to eq ( user . name )
end
2020-10-24 23:57:45 +05:30
it 'supports dry-run without applying changes' do
head = project . commit ( branch )
post api ( route , current_user ) , params : { branch : branch , dry_run : true }
expect ( response ) . to have_gitlab_http_status ( :ok )
expect ( json_response ) . to eq ( " dry_run " = > " success " )
expect ( project . commit ( branch ) ) . to eq ( head )
end
2021-09-04 01:27:46 +05:30
it 'supports the use of a custom commit message' do
post api ( route , user ) , params : { branch : branch , message : 'foo' }
expect ( response ) . to have_gitlab_http_status ( :created )
expect ( json_response [ " message " ] ) . to eq ( 'foo' )
end
2017-09-10 17:25:29 +05:30
end
2017-08-17 22:00:37 +05:30
2017-09-10 17:25:29 +05:30
context 'when repository is disabled' do
include_context 'disabled repository'
2017-08-17 22:00:37 +05:30
2019-09-30 21:07:59 +05:30
it_behaves_like '404 response' do
2019-02-15 15:39:39 +05:30
let ( :request ) { post api ( route , current_user ) , params : { branch : 'master' } }
2017-09-10 17:25:29 +05:30
end
2017-08-17 22:00:37 +05:30
end
2017-09-10 17:25:29 +05:30
end
2017-08-17 22:00:37 +05:30
2017-09-10 17:25:29 +05:30
context 'when unauthenticated' , 'and project is public' do
let ( :project ) { create ( :project , :public , :repository ) }
2017-08-17 22:00:37 +05:30
2017-09-10 17:25:29 +05:30
it_behaves_like '403 response' do
2019-02-15 15:39:39 +05:30
let ( :request ) { post api ( route ) , params : { branch : 'master' } }
2017-09-10 17:25:29 +05:30
end
end
context 'when unauthenticated' , 'and project is private' do
it_behaves_like '404 response' do
2019-02-15 15:39:39 +05:30
let ( :request ) { post api ( route ) , params : { branch : 'master' } }
2017-09-10 17:25:29 +05:30
let ( :message ) { '404 Project Not Found' }
2017-08-17 22:00:37 +05:30
end
2017-09-10 17:25:29 +05:30
end
2017-08-17 22:00:37 +05:30
2017-09-10 17:25:29 +05:30
context 'when authenticated' , 'as an owner' do
let ( :current_user ) { user }
2017-08-17 22:00:37 +05:30
2017-09-10 17:25:29 +05:30
it_behaves_like 'ref cherry-pick'
2017-08-17 22:00:37 +05:30
2017-09-10 17:25:29 +05:30
context 'when ref does not exist' do
let ( :commit_id ) { 'unknown' }
it_behaves_like '404 response' do
2019-02-15 15:39:39 +05:30
let ( :request ) { post api ( route , current_user ) , params : { branch : 'master' } }
2017-09-10 17:25:29 +05:30
let ( :message ) { '404 Commit Not Found' }
end
2017-08-17 22:00:37 +05:30
end
2017-09-10 17:25:29 +05:30
context 'when branch is missing' do
it_behaves_like '400 response' do
let ( :request ) { post api ( route , current_user ) }
end
end
2017-08-17 22:00:37 +05:30
2018-12-05 23:21:45 +05:30
context 'when branch is empty' do
[ '' , ' ' ] . each do | branch |
it_behaves_like '400 response' do
2019-02-15 15:39:39 +05:30
let ( :request ) { post api ( route , current_user ) , params : { branch : branch } }
2018-12-05 23:21:45 +05:30
end
end
end
2017-09-10 17:25:29 +05:30
context 'when branch does not exist' do
it_behaves_like '404 response' do
2019-02-15 15:39:39 +05:30
let ( :request ) { post api ( route , current_user ) , params : { branch : 'foo' } }
2017-09-10 17:25:29 +05:30
let ( :message ) { '404 Branch Not Found' }
end
end
context 'when commit is already included in the target branch' do
it_behaves_like '400 response' do
2019-02-15 15:39:39 +05:30
let ( :request ) { post api ( route , current_user ) , params : { branch : 'markdown' } }
2017-09-10 17:25:29 +05:30
end
2019-12-26 22:10:19 +05:30
it 'includes an error_code in the response' do
post api ( route , current_user ) , params : { branch : 'markdown' }
expect ( json_response [ 'error_code' ] ) . to eq 'empty'
end
2020-10-24 23:57:45 +05:30
it 'includes an additional dry_run error field when enabled' do
post api ( route , current_user ) , params : { branch : 'markdown' , dry_run : true }
expect ( response ) . to have_gitlab_http_status ( :bad_request )
expect ( json_response [ 'error_code' ] ) . to eq 'empty'
expect ( json_response [ 'dry_run' ] ) . to eq 'error'
end
2017-08-17 22:00:37 +05:30
end
2017-09-10 17:25:29 +05:30
context 'when ref contains a dot' do
let ( :commit ) { project . repository . commit ( branch_with_dot . name ) }
let ( :commit_id ) { branch_with_dot . name }
2017-08-17 22:00:37 +05:30
2017-09-10 17:25:29 +05:30
it_behaves_like 'ref cherry-pick'
2017-08-17 22:00:37 +05:30
end
2017-09-10 17:25:29 +05:30
context 'when ref contains a slash' do
let ( :commit_id ) { branch_with_slash . name }
2017-08-17 22:00:37 +05:30
2017-09-10 17:25:29 +05:30
it_behaves_like '404 response' do
2019-02-15 15:39:39 +05:30
let ( :request ) { post api ( route , current_user ) , params : { branch : 'master' } }
2017-09-10 17:25:29 +05:30
end
2017-08-17 22:00:37 +05:30
end
2017-09-10 17:25:29 +05:30
context 'requesting with the escaped project full path' do
let ( :project_id ) { CGI . escape ( project . full_path ) }
2017-08-17 22:00:37 +05:30
2017-09-10 17:25:29 +05:30
it_behaves_like 'ref cherry-pick'
context 'when ref contains a dot' do
let ( :commit ) { project . repository . commit ( branch_with_dot . name ) }
let ( :commit_id ) { branch_with_dot . name }
it_behaves_like 'ref cherry-pick'
end
2017-08-17 22:00:37 +05:30
end
end
2017-09-10 17:25:29 +05:30
context 'when authenticated' , 'as a developer' do
let ( :current_user ) { guest }
before do
project . add_developer ( guest )
end
context 'when branch is protected' do
before do
create ( :protected_branch , project : project , name : 'feature' )
end
it 'returns 400 if you are not allowed to push to the target branch' do
2019-02-15 15:39:39 +05:30
post api ( route , current_user ) , params : { branch : 'feature' }
2017-08-17 22:00:37 +05:30
2018-11-18 11:00:15 +05:30
expect ( response ) . to have_gitlab_http_status ( :forbidden )
expect ( json_response [ 'message' ] ) . to match ( / You are not allowed to push into this branch / )
2017-09-10 17:25:29 +05:30
end
2017-08-17 22:00:37 +05:30
end
end
2018-11-18 11:00:15 +05:30
context 'when cherry picking to a fork as a maintainer' do
include_context 'merge request allowing collaboration'
let ( :project_id ) { forked_project . id }
2019-12-26 22:10:19 +05:30
it 'allows access from a maintainer that to the source branch' , :sidekiq_might_not_need_inline do
2019-02-15 15:39:39 +05:30
post api ( route , user ) , params : { branch : 'feature' }
2018-11-18 11:00:15 +05:30
expect ( response ) . to have_gitlab_http_status ( :created )
end
it 'denies cherry picking to another branch' do
2019-02-15 15:39:39 +05:30
post api ( route , user ) , params : { branch : 'master' }
2018-11-18 11:00:15 +05:30
expect ( response ) . to have_gitlab_http_status ( :forbidden )
end
end
2015-04-26 12:48:37 +05:30
end
2018-12-13 13:39:08 +05:30
describe 'POST :id/repository/commits/:sha/revert' do
let ( :commit_id ) { 'b83d6e391c22777fca1ed3012fce84f633d7fed0' }
let ( :commit ) { project . commit ( commit_id ) }
let ( :branch ) { 'master' }
let ( :route ) { " /projects/ #{ project_id } /repository/commits/ #{ commit_id } /revert " }
shared_examples_for 'ref revert' do
context 'when ref exists' do
it 'reverts the ref commit' do
2019-02-15 15:39:39 +05:30
post api ( route , current_user ) , params : { branch : branch }
2018-12-13 13:39:08 +05:30
2020-04-08 14:13:33 +05:30
expect ( response ) . to have_gitlab_http_status ( :created )
2018-12-13 13:39:08 +05:30
expect ( response ) . to match_response_schema ( 'public_api/v4/commit/basic' )
expect ( json_response [ 'message' ] ) . to eq ( commit . revert_message ( user ) )
expect ( json_response [ 'author_name' ] ) . to eq ( user . name )
expect ( json_response [ 'committer_name' ] ) . to eq ( user . name )
expect ( json_response [ 'parent_ids' ] ) . to contain_exactly ( commit_id )
end
2020-10-24 23:57:45 +05:30
it 'supports dry-run without applying changes' do
head = project . commit ( branch )
post api ( route , current_user ) , params : { branch : branch , dry_run : true }
expect ( response ) . to have_gitlab_http_status ( :ok )
expect ( json_response ) . to eq ( " dry_run " = > " success " )
expect ( project . commit ( branch ) ) . to eq ( head )
end
2018-12-13 13:39:08 +05:30
end
context 'when repository is disabled' do
include_context 'disabled repository'
2019-09-30 21:07:59 +05:30
it_behaves_like '404 response' do
2019-02-15 15:39:39 +05:30
let ( :request ) { post api ( route , current_user ) , params : { branch : branch } }
2018-12-13 13:39:08 +05:30
end
end
end
context 'when unauthenticated' , 'and project is public' do
let ( :project ) { create ( :project , :public , :repository ) }
it_behaves_like '403 response' do
2019-02-15 15:39:39 +05:30
let ( :request ) { post api ( route ) , params : { branch : branch } }
2018-12-13 13:39:08 +05:30
end
end
context 'when unauthenticated' , 'and project is private' do
it_behaves_like '404 response' do
2019-02-15 15:39:39 +05:30
let ( :request ) { post api ( route ) , params : { branch : branch } }
2018-12-13 13:39:08 +05:30
let ( :message ) { '404 Project Not Found' }
end
end
context 'when authenticated' , 'as an owner' do
let ( :current_user ) { user }
it_behaves_like 'ref revert'
context 'when ref does not exist' do
let ( :commit_id ) { 'unknown' }
it_behaves_like '404 response' do
2019-02-15 15:39:39 +05:30
let ( :request ) { post api ( route , current_user ) , params : { branch : branch } }
2018-12-13 13:39:08 +05:30
let ( :message ) { '404 Commit Not Found' }
end
end
context 'when branch is missing' do
it_behaves_like '400 response' do
let ( :request ) { post api ( route , current_user ) }
end
end
context 'when branch is empty' do
[ '' , ' ' ] . each do | branch |
it_behaves_like '400 response' do
2019-02-15 15:39:39 +05:30
let ( :request ) { post api ( route , current_user ) , params : { branch : branch } }
2018-12-13 13:39:08 +05:30
end
end
end
context 'when branch does not exist' do
it_behaves_like '404 response' do
2019-02-15 15:39:39 +05:30
let ( :request ) { post api ( route , current_user ) , params : { branch : 'foo' } }
2018-12-13 13:39:08 +05:30
let ( :message ) { '404 Branch Not Found' }
end
end
context 'when ref contains a dot' do
let ( :commit_id ) { branch_with_dot . name }
let ( :commit ) { project . repository . commit ( commit_id ) }
it_behaves_like '400 response' do
let ( :request ) { post api ( route , current_user ) }
end
end
2019-12-26 22:10:19 +05:30
context 'when commit is already reverted in the target branch' do
it 'includes an error_code in the response' do
# First one actually reverts
post api ( route , current_user ) , params : { branch : 'markdown' }
# Second one is redundant and should be empty
post api ( route , current_user ) , params : { branch : 'markdown' }
2020-04-08 14:13:33 +05:30
expect ( response ) . to have_gitlab_http_status ( :bad_request )
2019-12-26 22:10:19 +05:30
expect ( json_response [ 'error_code' ] ) . to eq 'empty'
end
2020-10-24 23:57:45 +05:30
it 'includes an additional dry_run error field when enabled' do
# First one actually reverts
post api ( route , current_user ) , params : { branch : 'markdown' }
# Second one is redundant and should be empty
post api ( route , current_user ) , params : { branch : 'markdown' , dry_run : true }
expect ( response ) . to have_gitlab_http_status ( :bad_request )
expect ( json_response [ 'error_code' ] ) . to eq 'empty'
expect ( json_response [ 'dry_run' ] ) . to eq 'error'
end
2019-12-26 22:10:19 +05:30
end
2018-12-13 13:39:08 +05:30
end
context 'when authenticated' , 'as a developer' do
let ( :current_user ) { user }
before do
project . add_developer ( user )
end
context 'when branch is protected' do
before do
create ( :protected_branch , project : project , name : 'feature' )
end
it 'returns 400 if you are not allowed to push to the target branch' do
2019-02-15 15:39:39 +05:30
post api ( route , current_user ) , params : { branch : 'feature' }
2018-12-13 13:39:08 +05:30
expect ( response ) . to have_gitlab_http_status ( :forbidden )
expect ( json_response [ 'message' ] ) . to match ( / You are not allowed to push into this branch / )
end
end
end
end
2017-09-10 17:25:29 +05:30
describe 'POST /projects/:id/repository/commits/:sha/comments' do
let ( :commit ) { project . repository . commit }
let ( :commit_id ) { commit . id }
let ( :note ) { 'My comment' }
let ( :route ) { " /projects/ #{ project_id } /repository/commits/ #{ commit_id } /comments " }
shared_examples_for 'ref new comment' do
context 'when ref exists' do
it 'creates the comment' do
2019-02-15 15:39:39 +05:30
post api ( route , current_user ) , params : { note : note }
2017-09-10 17:25:29 +05:30
2020-04-08 14:13:33 +05:30
expect ( response ) . to have_gitlab_http_status ( :created )
2017-09-10 17:25:29 +05:30
expect ( response ) . to match_response_schema ( 'public_api/v4/commit_note' )
expect ( json_response [ 'note' ] ) . to eq ( 'My comment' )
expect ( json_response [ 'path' ] ) . to be_nil
expect ( json_response [ 'line' ] ) . to be_nil
expect ( json_response [ 'line_type' ] ) . to be_nil
end
2015-04-26 12:48:37 +05:30
end
2017-09-10 17:25:29 +05:30
context 'when repository is disabled' do
include_context 'disabled repository'
2019-09-30 21:07:59 +05:30
it_behaves_like '404 response' do
2019-02-15 15:39:39 +05:30
let ( :request ) { post api ( route , current_user ) , params : { note : 'My comment' } }
2017-09-10 17:25:29 +05:30
end
end
end
context 'when unauthenticated' , 'and project is public' do
let ( :project ) { create ( :project , :public , :repository ) }
it_behaves_like '400 response' do
2019-02-15 15:39:39 +05:30
let ( :request ) { post api ( route ) , params : { note : 'My comment' } }
2017-09-10 17:25:29 +05:30
end
end
context 'when unauthenticated' , 'and project is private' do
it_behaves_like '404 response' do
2019-02-15 15:39:39 +05:30
let ( :request ) { post api ( route ) , params : { note : 'My comment' } }
2017-09-10 17:25:29 +05:30
let ( :message ) { '404 Project Not Found' }
end
end
context 'when authenticated' , 'as an owner' do
let ( :current_user ) { user }
it_behaves_like 'ref new comment'
2016-09-13 17:45:13 +05:30
it 'returns the inline comment' do
2019-02-15 15:39:39 +05:30
post api ( route , current_user ) , params : { note : 'My comment' , path : project . repository . commit . raw_diffs . first . new_path , line : 1 , line_type : 'new' }
2016-11-03 12:29:30 +05:30
2020-04-08 14:13:33 +05:30
expect ( response ) . to have_gitlab_http_status ( :created )
2017-09-10 17:25:29 +05:30
expect ( response ) . to match_response_schema ( 'public_api/v4/commit_note' )
2015-04-26 12:48:37 +05:30
expect ( json_response [ 'note' ] ) . to eq ( 'My comment' )
2016-09-13 17:45:13 +05:30
expect ( json_response [ 'path' ] ) . to eq ( project . repository . commit . raw_diffs . first . new_path )
2016-11-03 12:29:30 +05:30
expect ( json_response [ 'line' ] ) . to eq ( 1 )
2015-04-26 12:48:37 +05:30
expect ( json_response [ 'line_type' ] ) . to eq ( 'new' )
end
2021-11-11 11:23:49 +05:30
it 'correctly adds a note for the "old" line type' do
commit = project . repository . commit ( " markdown " )
commit_id = commit . id
route = " /projects/ #{ project_id } /repository/commits/ #{ commit_id } /comments "
post api ( route , current_user ) , params : {
note : 'My comment' ,
path : commit . raw_diffs . first . old_path ,
line : 4 ,
line_type : 'old'
}
expect ( response ) . to have_gitlab_http_status ( :created )
expect ( response ) . to match_response_schema ( 'public_api/v4/commit_note' )
expect ( json_response [ 'note' ] ) . to eq ( 'My comment' )
expect ( json_response [ 'path' ] ) . to eq ( commit . raw_diffs . first . old_path )
expect ( json_response [ 'line' ] ) . to eq ( 4 )
expect ( json_response [ 'line_type' ] ) . to eq ( 'old' )
end
2017-09-10 17:25:29 +05:30
context 'when ref does not exist' do
let ( :commit_id ) { 'unknown' }
it_behaves_like '404 response' do
2019-02-15 15:39:39 +05:30
let ( :request ) { post api ( route , current_user ) , params : { note : 'My comment' } }
2017-09-10 17:25:29 +05:30
let ( :message ) { '404 Commit Not Found' }
end
end
2016-09-13 17:45:13 +05:30
it 'returns 400 if note is missing' do
2017-09-10 17:25:29 +05:30
post api ( route , current_user )
2020-04-08 14:13:33 +05:30
expect ( response ) . to have_gitlab_http_status ( :bad_request )
2015-04-26 12:48:37 +05:30
end
2017-09-10 17:25:29 +05:30
context 'when ref contains a dot' do
let ( :commit_id ) { branch_with_dot . name }
it_behaves_like 'ref new comment'
2015-04-26 12:48:37 +05:30
end
2017-09-10 17:25:29 +05:30
context 'when ref contains a slash' do
let ( :commit_id ) { branch_with_slash . name }
it_behaves_like '404 response' do
2019-02-15 15:39:39 +05:30
let ( :request ) { post api ( route , current_user ) , params : { note : 'My comment' } }
2017-09-10 17:25:29 +05:30
end
end
context 'when ref contains an escaped slash' do
let ( :commit_id ) { CGI . escape ( branch_with_slash . name ) }
it_behaves_like 'ref new comment'
end
context 'requesting with the escaped project full path' do
let ( :project_id ) { CGI . escape ( project . full_path ) }
it_behaves_like 'ref new comment'
context 'when ref contains a dot' do
let ( :commit_id ) { branch_with_dot . name }
it_behaves_like 'ref new comment'
end
2014-09-02 18:07:02 +05:30
end
end
end
2018-05-09 12:01:36 +05:30
describe 'GET /projects/:id/repository/commits/:sha/merge_requests' do
2019-03-13 22:55:13 +05:30
let ( :project ) { create ( :project , :repository , :private ) }
let ( :merged_mr ) { create ( :merge_request , source_project : project , source_branch : 'master' , target_branch : 'feature' ) }
2018-05-09 12:01:36 +05:30
let ( :commit ) { merged_mr . merge_request_diff . commits . last }
2021-04-29 21:17:54 +05:30
def perform_request ( user )
2018-05-09 12:01:36 +05:30
get api ( " /projects/ #{ project . id } /repository/commits/ #{ commit . id } /merge_requests " , user )
2021-04-29 21:17:54 +05:30
end
it 'returns the correct merge request' do
perform_request ( user )
2018-05-09 12:01:36 +05:30
2020-04-08 14:13:33 +05:30
expect ( response ) . to have_gitlab_http_status ( :ok )
2021-01-03 14:25:43 +05:30
expect ( response ) . to include_limited_pagination_headers
2018-05-09 12:01:36 +05:30
expect ( json_response . length ) . to eq ( 1 )
expect ( json_response [ 0 ] [ 'id' ] ) . to eq ( merged_mr . id )
end
it 'returns 403 for an unauthorized user' do
project . add_guest ( user )
2021-04-29 21:17:54 +05:30
perform_request ( user )
2018-05-09 12:01:36 +05:30
2020-04-08 14:13:33 +05:30
expect ( response ) . to have_gitlab_http_status ( :forbidden )
2018-05-09 12:01:36 +05:30
end
it 'responds 404 when the commit does not exist' do
get api ( " /projects/ #{ project . id } /repository/commits/a7d26f00c35b/merge_requests " , user )
2020-04-08 14:13:33 +05:30
expect ( response ) . to have_gitlab_http_status ( :not_found )
2018-05-09 12:01:36 +05:30
end
2019-03-13 22:55:13 +05:30
context 'public project' do
let ( :project ) { create ( :project , :repository , :public , :merge_requests_private ) }
let ( :non_member ) { create ( :user ) }
it 'responds 403 when only members are allowed to read merge requests' do
2021-04-29 21:17:54 +05:30
perform_request ( non_member )
2019-03-13 22:55:13 +05:30
2020-04-08 14:13:33 +05:30
expect ( response ) . to have_gitlab_http_status ( :forbidden )
2019-03-13 22:55:13 +05:30
end
end
2021-04-29 21:17:54 +05:30
it 'returns multiple merge requests without N + 1' do
perform_request ( user )
control_count = ActiveRecord :: QueryRecorder . new { perform_request ( user ) } . count
create ( :merge_request , :closed , source_project : project , source_branch : 'master' , target_branch : 'feature' )
expect { perform_request ( user ) } . not_to exceed_query_limit ( control_count )
end
2018-05-09 12:01:36 +05:30
end
2019-07-07 11:18:12 +05:30
describe 'GET /projects/:id/repository/commits/:sha/signature' do
let! ( :project ) { create ( :project , :repository , :public ) }
let ( :project_id ) { project . id }
let ( :commit_id ) { project . repository . commit . id }
let ( :route ) { " /projects/ #{ project_id } /repository/commits/ #{ commit_id } /signature " }
context 'when commit does not exist' do
let ( :commit_id ) { 'unknown' }
it_behaves_like '404 response' do
let ( :request ) { get api ( route , current_user ) }
let ( :message ) { '404 Commit Not Found' }
end
end
context 'unsigned commit' do
it_behaves_like '404 response' do
let ( :request ) { get api ( route , current_user ) }
2020-04-22 19:07:51 +05:30
let ( :message ) { '404 Signature Not Found' }
2019-07-07 11:18:12 +05:30
end
end
2020-04-22 19:07:51 +05:30
context 'gpg signed commit' do
2019-07-07 11:18:12 +05:30
let ( :commit ) { project . repository . commit ( GpgHelpers :: SIGNED_COMMIT_SHA ) }
let ( :commit_id ) { commit . id }
it 'returns correct JSON' do
get api ( route , current_user )
2020-04-08 14:13:33 +05:30
expect ( response ) . to have_gitlab_http_status ( :ok )
2020-04-22 19:07:51 +05:30
expect ( json_response [ 'signature_type' ] ) . to eq ( 'PGP' )
2019-07-07 11:18:12 +05:30
expect ( json_response [ 'gpg_key_id' ] ) . to eq ( commit . signature . gpg_key_id )
expect ( json_response [ 'gpg_key_subkey_id' ] ) . to eq ( commit . signature . gpg_key_subkey_id )
expect ( json_response [ 'gpg_key_primary_keyid' ] ) . to eq ( commit . signature . gpg_key_primary_keyid )
expect ( json_response [ 'verification_status' ] ) . to eq ( commit . signature . verification_status )
end
end
2020-04-22 19:07:51 +05:30
context 'x509 signed commit' do
let ( :commit ) { project . repository . commit_by ( oid : '189a6c924013fc3fe40d6f1ec1dc20214183bc97' ) }
let ( :commit_id ) { commit . id }
it 'returns correct JSON' do
get api ( route , current_user )
expect ( response ) . to have_gitlab_http_status ( :ok )
expect ( json_response [ 'signature_type' ] ) . to eq ( 'X509' )
expect ( json_response [ 'verification_status' ] ) . to eq ( commit . signature . verification_status )
expect ( json_response [ 'x509_certificate' ] [ 'id' ] ) . to eq ( commit . signature . x509_certificate . id )
expect ( json_response [ 'x509_certificate' ] [ 'subject' ] ) . to eq ( commit . signature . x509_certificate . subject )
expect ( json_response [ 'x509_certificate' ] [ 'subject_key_identifier' ] ) . to eq ( commit . signature . x509_certificate . subject_key_identifier )
expect ( json_response [ 'x509_certificate' ] [ 'email' ] ) . to eq ( commit . signature . x509_certificate . email )
expect ( json_response [ 'x509_certificate' ] [ 'serial_number' ] ) . to eq ( commit . signature . x509_certificate . serial_number )
expect ( json_response [ 'x509_certificate' ] [ 'certificate_status' ] ) . to eq ( commit . signature . x509_certificate . certificate_status )
expect ( json_response [ 'x509_certificate' ] [ 'x509_issuer' ] [ 'id' ] ) . to eq ( commit . signature . x509_certificate . x509_issuer . id )
expect ( json_response [ 'x509_certificate' ] [ 'x509_issuer' ] [ 'subject' ] ) . to eq ( commit . signature . x509_certificate . x509_issuer . subject )
expect ( json_response [ 'x509_certificate' ] [ 'x509_issuer' ] [ 'subject_key_identifier' ] ) . to eq ( commit . signature . x509_certificate . x509_issuer . subject_key_identifier )
expect ( json_response [ 'x509_certificate' ] [ 'x509_issuer' ] [ 'crl_url' ] ) . to eq ( commit . signature . x509_certificate . x509_issuer . crl_url )
2021-01-29 00:20:46 +05:30
expect ( json_response [ 'commit_source' ] ) . to eq ( 'gitaly' )
end
context 'with Rugged enabled' , :enable_rugged do
it 'returns correct JSON' do
get api ( route , current_user )
expect ( response ) . to have_gitlab_http_status ( :ok )
expect ( json_response [ 'signature_type' ] ) . to eq ( 'PGP' )
expect ( json_response [ 'commit_source' ] ) . to eq ( 'rugged' )
end
2020-04-22 19:07:51 +05:30
end
end
2019-07-07 11:18:12 +05:30
end
2014-09-02 18:07:02 +05:30
end