summaryrefslogtreecommitdiff
path: root/lib/gitlab/ci
diff options
context:
space:
mode:
authorGrzegorz Bizon <grzesiek.bizon@gmail.com>2017-09-25 16:22:00 +0200
committerGrzegorz Bizon <grzesiek.bizon@gmail.com>2017-09-25 16:22:00 +0200
commit8f47d484dab12df982655c3c05305bce7624914d (patch)
treebd4eef75a1714a22377962092f6f0103df49feed /lib/gitlab/ci
parent1209f4f671c290ce6c577c0ff16ad7f9ea8b6271 (diff)
downloadgitlab-ce-8f47d484dab12df982655c3c05305bce7624914d.tar.gz
Extract pipeline chain builder classes from service
Diffstat (limited to 'lib/gitlab/ci')
-rw-r--r--lib/gitlab/ci/pipeline/chain/base.rb27
-rw-r--r--lib/gitlab/ci/pipeline/chain/skip.rb33
-rw-r--r--lib/gitlab/ci/pipeline/chain/validate.rb107
3 files changed, 167 insertions, 0 deletions
diff --git a/lib/gitlab/ci/pipeline/chain/base.rb b/lib/gitlab/ci/pipeline/chain/base.rb
new file mode 100644
index 00000000000..8d82e1b288d
--- /dev/null
+++ b/lib/gitlab/ci/pipeline/chain/base.rb
@@ -0,0 +1,27 @@
+module Gitlab
+ module Ci
+ module Pipeline
+ module Chain
+ class Base
+ attr_reader :pipeline, :project, :current_user
+
+ def initialize(pipeline, command)
+ @pipeline = pipeline
+ @command = command
+
+ @project = command.project
+ @current_user = command.current_user
+ end
+
+ def perform!
+ raise NotImplementedError
+ end
+
+ def break?
+ raise NotImplementedError
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/ci/pipeline/chain/skip.rb b/lib/gitlab/ci/pipeline/chain/skip.rb
new file mode 100644
index 00000000000..3f86275ae15
--- /dev/null
+++ b/lib/gitlab/ci/pipeline/chain/skip.rb
@@ -0,0 +1,33 @@
+module Gitlab
+ module Ci
+ module Pipeline
+ module Chain
+ class Skip < Chain::Base
+ SKIP_PATTERN = /\[(ci[ _-]skip|skip[ _-]ci)\]/i
+
+ def perform!
+ if skipped?
+ @pipeline.skip if @command.save_incompleted
+ end
+ end
+
+ def skipped?
+ !@command.ignore_skip_ci && commit_message_skips_ci?
+ end
+
+ def break?
+ skipped?
+ end
+
+ private
+
+ def commit_message_skips_ci?
+ return false unless @pipeline.git_commit_message
+
+ @skipped ||= @pipeline.git_commit_message =~ SKIP_PATTERN
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/ci/pipeline/chain/validate.rb b/lib/gitlab/ci/pipeline/chain/validate.rb
new file mode 100644
index 00000000000..e7109425d6c
--- /dev/null
+++ b/lib/gitlab/ci/pipeline/chain/validate.rb
@@ -0,0 +1,107 @@
+module Gitlab
+ module Ci
+ module Pipeline
+ module Chain
+ class Validate < Chain::Base
+ include Gitlab::Allowable
+
+ def perform!
+ validate_project! || validate_repository! || validate_pipeline!
+ end
+
+ def break?
+ @pipeline.errors.any? || @pipeline.persisted?
+ end
+
+ def allowed_to_trigger_pipeline?
+ if current_user
+ allowed_to_create?
+ else # legacy triggers don't have a corresponding user
+ !project.protected_for?(@pipeline.ref)
+ end
+ end
+
+ def allowed_to_create?
+ return unless can?(current_user, :create_pipeline, project)
+
+ access = Gitlab::UserAccess.new(current_user, project: project)
+
+ if branch?
+ access.can_update_branch?(@pipeline.ref)
+ elsif tag?
+ access.can_create_tag?(@pipeline.ref)
+ else
+ true # Allow it for now and we'll reject when we check ref existence
+ 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
+
+ ## TODO, move to Pipeline as `branch_exists?`
+ #
+ def branch?
+ return @is_branch if defined?(@is_branch)
+
+ @is_branch = project.repository
+ .ref_exists?(Gitlab::Git::BRANCH_REF_PREFIX + pipeline.ref)
+ end
+
+ ## TODO, move to pipeline as `tag_exists?`
+ #
+ def tag?
+ return @is_tag if defined?(@is_tag)
+
+ @is_tag = project.repository
+ .ref_exists?(Gitlab::Git::TAG_REF_PREFIX + pipeline.ref)
+ end
+
+ def error(message)
+ pipeline.errors.add(:base, message)
+ end
+ end
+ end
+ end
+ end
+end