summaryrefslogtreecommitdiff
path: root/app/services/ci
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2020-02-10 12:08:59 +0000
committerGitLab Bot <gitlab-bot@gitlab.com>2020-02-10 12:08:59 +0000
commit7351a484d79236b7e9d47c86f2fcc970b7ae10b0 (patch)
tree651b5fca7ea0460e3ce7c687cfa9e3a3b37eefc8 /app/services/ci
parentb4ded0ba7b4d2cdbed5b1f331cf2083a25ee4d7c (diff)
downloadgitlab-ce-7351a484d79236b7e9d47c86f2fcc970b7ae10b0.tar.gz
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'app/services/ci')
-rw-r--r--app/services/ci/create_cross_project_pipeline_service.rb88
1 files changed, 88 insertions, 0 deletions
diff --git a/app/services/ci/create_cross_project_pipeline_service.rb b/app/services/ci/create_cross_project_pipeline_service.rb
new file mode 100644
index 00000000000..a60793463b4
--- /dev/null
+++ b/app/services/ci/create_cross_project_pipeline_service.rb
@@ -0,0 +1,88 @@
+# frozen_string_literal: true
+
+module Ci
+ # TODO: rename this (and worker) to CreateDownstreamPipelineService
+ class CreateCrossProjectPipelineService < ::BaseService
+ include Gitlab::Utils::StrongMemoize
+
+ def execute(bridge)
+ @bridge = bridge
+
+ pipeline_params = @bridge.downstream_pipeline_params
+ target_ref = pipeline_params.dig(:target_revision, :ref)
+
+ return unless ensure_preconditions!(target_ref)
+
+ service = ::Ci::CreatePipelineService.new(
+ pipeline_params.fetch(:project),
+ current_user,
+ pipeline_params.fetch(:target_revision))
+
+ downstream_pipeline = service.execute(
+ pipeline_params.fetch(:source), pipeline_params[:execute_params]) do |pipeline|
+ @bridge.sourced_pipelines.build(
+ source_pipeline: @bridge.pipeline,
+ source_project: @bridge.project,
+ project: @bridge.downstream_project,
+ pipeline: pipeline)
+
+ pipeline.variables.build(@bridge.downstream_variables)
+ end
+
+ downstream_pipeline.tap do |pipeline|
+ @bridge.drop!(:downstream_pipeline_creation_failed) if pipeline.has_yaml_errors?
+ end
+ end
+
+ private
+
+ def ensure_preconditions!(target_ref)
+ unless downstream_project_accessible?
+ @bridge.drop!(:downstream_bridge_project_not_found)
+ return false
+ end
+
+ # TODO: Remove this condition if favour of model validation
+ # https://gitlab.com/gitlab-org/gitlab/issues/38338
+ if downstream_project == project && !@bridge.triggers_child_pipeline?
+ @bridge.drop!(:invalid_bridge_trigger)
+ return false
+ end
+
+ # TODO: Remove this condition if favour of model validation
+ # https://gitlab.com/gitlab-org/gitlab/issues/38338
+ if @bridge.triggers_child_pipeline? && @bridge.pipeline.parent_pipeline.present?
+ @bridge.drop!(:bridge_pipeline_is_child_pipeline)
+ return false
+ end
+
+ unless can_create_downstream_pipeline?(target_ref)
+ @bridge.drop!(:insufficient_bridge_permissions)
+ return false
+ end
+
+ true
+ end
+
+ def downstream_project_accessible?
+ downstream_project.present? &&
+ can?(current_user, :read_project, downstream_project)
+ end
+
+ def can_create_downstream_pipeline?(target_ref)
+ can?(current_user, :update_pipeline, project) &&
+ can?(current_user, :create_pipeline, downstream_project) &&
+ can_update_branch?(target_ref)
+ end
+
+ def can_update_branch?(target_ref)
+ ::Gitlab::UserAccess.new(current_user, project: downstream_project).can_update_branch?(target_ref)
+ end
+
+ def downstream_project
+ strong_memoize(:downstream_project) do
+ @bridge.downstream_project
+ end
+ end
+ end
+end