Commit 609fa45f authored by Grzegorz Bizon's avatar Grzegorz Bizon

Split pipeline chain builder validation class

parent 3e60d62c
...@@ -2,7 +2,9 @@ module Ci ...@@ -2,7 +2,9 @@ module Ci
class CreatePipelineService < BaseService class CreatePipelineService < BaseService
attr_reader :pipeline attr_reader :pipeline
SEQUENCE = [Gitlab::Ci::Pipeline::Chain::Validate, SEQUENCE = [Gitlab::Ci::Pipeline::Chain::ValidateAbilities,
Gitlab::Ci::Pipeline::Chain::ValidateRepository,
Gitlab::Ci::Pipeline::Chain::ValidateConfig,
Gitlab::Ci::Pipeline::Chain::Skip, Gitlab::Ci::Pipeline::Chain::Skip,
Gitlab::Ci::Pipeline::Chain::Create].freeze Gitlab::Ci::Pipeline::Chain::Create].freeze
......
...@@ -3,6 +3,8 @@ module Gitlab ...@@ -3,6 +3,8 @@ module Gitlab
module Pipeline module Pipeline
module Chain module Chain
class Create < Chain::Base class Create < Chain::Base
include Chain::Helpers
def perform! def perform!
::Ci::Pipeline.transaction do ::Ci::Pipeline.transaction do
pipeline.save! pipeline.save!
...@@ -16,7 +18,7 @@ module Gitlab ...@@ -16,7 +18,7 @@ module Gitlab
.execute(pipeline) .execute(pipeline)
end end
rescue ActiveRecord::RecordInvalid => e rescue ActiveRecord::RecordInvalid => e
pipeline.erros.add(:base, "Failed to persist the pipeline: #{e}") error("Failed to persist the pipeline: #{e}")
end end
def break? def break?
......
module Gitlab
module Ci
module Pipeline
module Chain
module Helpers
def branch_exists?
return @is_branch if defined?(@is_branch)
@is_branch = project.repository.branch_exists?(pipeline.ref)
end
def tag_exists?
return @is_tag if defined?(@is_tag)
@is_tag = project.repository.tag_exists?(pipeline.ref)
end
def error(message)
pipeline.errors.add(:base, message)
end
end
end
end
end
end
...@@ -2,15 +2,26 @@ module Gitlab ...@@ -2,15 +2,26 @@ module Gitlab
module Ci module Ci
module Pipeline module Pipeline
module Chain module Chain
class Validate < Chain::Base class ValidateAbilities < Chain::Base
include Gitlab::Allowable include Gitlab::Allowable
include Chain::Helpers
def perform! def perform!
validate_project! || validate_repository! || validate_pipeline! unless project.builds_enabled?
return error('Pipelines are disabled!')
end
unless allowed_to_trigger_pipeline?
if can?(current_user, :create_pipeline, project)
return error("Insufficient permissions for protected ref '#{pipeline.ref}'")
else
return error('Insufficient permissions to create a new pipeline')
end
end
end end
def break? def break?
@pipeline.errors.any? || @pipeline.persisted? @pipeline.errors.any?
end end
def allowed_to_trigger_pipeline? def allowed_to_trigger_pipeline?
...@@ -26,74 +37,14 @@ module Gitlab ...@@ -26,74 +37,14 @@ module Gitlab
access = Gitlab::UserAccess.new(current_user, project: project) access = Gitlab::UserAccess.new(current_user, project: project)
if branch? if branch_exists?
access.can_update_branch?(@pipeline.ref) access.can_update_branch?(@pipeline.ref)
elsif tag? elsif tag_exists?
access.can_create_tag?(@pipeline.ref) access.can_create_tag?(@pipeline.ref)
else else
true # Allow it for now and we'll reject when we check ref existence true # Allow it for now and we'll reject when we check ref existence
end end
end end
private
def validate_project!
unless project.builds_enabled?
return error('Pipeline is disabled')
end
unless allowed_to_trigger_pipeline?
if can?(current_user, :create_pipeline, project)
return error("Insufficient permissions for protected ref '#{pipeline.ref}'")
else
return error('Insufficient permissions to create a new pipeline')
end
end
end
def validate_repository!
unless branch? || tag?
return error('Reference not found')
end
unless pipeline.sha
return error('Commit not found')
end
end
def validate_pipeline!
unless @pipeline.config_processor
unless @pipeline.ci_yaml_file
return error("Missing #{@pipeline.ci_yaml_file_path} file")
end
if @command.save_incompleted && @pipeline.has_yaml_errors?
@pipeline.drop
end
return error(@pipeline.yaml_errors)
end
unless @pipeline.has_stage_seeds?
return error('No stages / jobs for this pipeline.')
end
end
def branch?
return @is_branch if defined?(@is_branch)
@is_branch = project.repository.branch_exists?(pipeline.ref)
end
def tag?
return @is_tag if defined?(@is_tag)
@is_tag = project.repository.tag_exists?(pipeline.ref)
end
def error(message)
pipeline.errors.add(:base, message)
end
end end
end end
end end
......
module Gitlab
module Ci
module Pipeline
module Chain
class ValidateConfig < Chain::Base
include Chain::Helpers
def perform!
unless @pipeline.config_processor
unless @pipeline.ci_yaml_file
return error("Missing #{@pipeline.ci_yaml_file_path} file")
end
if @command.save_incompleted && @pipeline.has_yaml_errors?
@pipeline.drop
end
return error(@pipeline.yaml_errors)
end
unless @pipeline.has_stage_seeds?
return error('No stages / jobs for this pipeline.')
end
end
def break?
@pipeline.errors.any? || @pipeline.persisted?
end
end
end
end
end
end
module Gitlab
module Ci
module Pipeline
module Chain
class ValidateRepository < Chain::Base
include Chain::Helpers
def perform!
unless branch_exists? || tag_exists?
return error('Reference not found')
end
## TODO, we check commit in the service, that is why
# there is no repository access here.
#
# Should we validate repository before building a pipeline?
#
unless pipeline.sha
return error('Commit not found')
end
end
def break?
@pipeline.errors.any?
end
end
end
end
end
end
require 'spec_helper' require 'spec_helper'
describe Gitlab::Ci::Pipeline::Chain::Validate do describe Gitlab::Ci::Pipeline::Chain::ValidateAbilities do
describe '#allowed_to_create?' do describe '#allowed_to_create?' do
let(:user) { create(:user) } let(:user) { create(:user) }
let(:project) { create(:project, :repository) } let(:project) { create(:project, :repository) }
......
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