diff --git a/app/services/ci/create_pipeline_service.rb b/app/services/ci/create_pipeline_service.rb index 13baa63220d..a54af4749ac 100644 --- a/app/services/ci/create_pipeline_service.rb +++ b/app/services/ci/create_pipeline_service.rb @@ -27,6 +27,12 @@ module Ci return error('Reference not found') end + if tag? + return error("#{ref} is protected") unless access.can_create_tag?(ref) + else + return error("#{ref} is protected") unless access.can_merge_to_branch?(ref) + end + unless commit return error('Commit not found') end @@ -94,6 +100,10 @@ module Ci @commit ||= project.commit(origin_sha || origin_ref) end + def access + @access ||= Gitlab::UserAccess.new(current_user, project: project) + end + def sha commit.try(:id) end diff --git a/spec/services/ci/create_pipeline_service_spec.rb b/spec/services/ci/create_pipeline_service_spec.rb index 597c3947e71..13a1c6a504d 100644 --- a/spec/services/ci/create_pipeline_service_spec.rb +++ b/spec/services/ci/create_pipeline_service_spec.rb @@ -3,13 +3,14 @@ require 'spec_helper' describe Ci::CreatePipelineService, services: true do let(:project) { create(:project, :repository) } let(:user) { create(:admin) } + let(:ref_name) { 'refs/heads/master' } before do stub_ci_pipeline_to_return_yaml_file end describe '#execute' do - def execute_service(source: :push, after: project.commit.id, message: 'Message', ref: 'refs/heads/master') + def execute_service(source: :push, after: project.commit.id, message: 'Message', ref: ref_name) params = { ref: ref, before: '00000000', after: after, @@ -311,5 +312,49 @@ describe Ci::CreatePipelineService, services: true do end.not_to change { Environment.count } end end + + shared_examples 'when ref is protected' do + let(:user) { create(:user) } + + context 'when user is developer' do + before do + project.add_developer(user) + end + + it 'does not create a pipeline' do + expect(execute_service).not_to be_persisted + expect(Ci::Pipeline.count).to eq(0) + end + end + + context 'when user is master' do + before do + project.add_master(user) + end + + it 'creates a pipeline' do + expect(execute_service).to be_persisted + expect(Ci::Pipeline.count).to eq(1) + end + end + end + + context 'when ref is a protected branch' do + before do + create(:protected_branch, project: project, name: 'master') + end + + it_behaves_like 'when ref is protected' + end + + context 'when ref is a protected tag' do + let(:ref_name) { 'refs/tags/v1.0.0' } + + before do + create(:protected_tag, project: project, name: '*') + end + + it_behaves_like 'when ref is protected' + end end end