Follow-up from "Create downstream pipeline inside same project"

The following discussion from !20930 (merged) should be addressed:

  • @dosuken123 started a discussion: (+5 comments)

    If we allow to pass config_content as an argument, I feel we should pass config_source as well. Or should we pass one encapsulated domain object as the argument?

we are assuming that from now on any time Ci::CreatePipelineService gets a content passed in as param it's always because of parent/child pipelines.

I'd say config_content and config_source params should be always paired. For example,

diff --git a/lib/gitlab/ci/config/content.rb b/lib/gitlab/ci/config/content.rb
new file mode 100644
index 00000000000..63dab28737b
--- /dev/null
+++ b/lib/gitlab/ci/config/content.rb
@@ -0,0 +1,52 @@
+# frozen_string_literal: true
+
+module Gitlab
+  module Ci
+    class Config
+      class Content
+        attr_reader :project, :source, :blob
+
+        delegate_missing_to :blob
+
+        def initialize(project)
+          @project = project
+        end
+
+        def generate_for_child_pipeline(bridge:)
+          @blob = @bridge.yaml_in_upstream_for_downstream
+          @source = :parent_pipeline_source
+        end
+
+        def auto_generate(sha:)
+          if @blob = content_from_repo(sha)
+            @source = :repository_source
+          elsif @blob = content_from_auto_devops
+            @source = :auto_devops_source
+          end
+        end
+
+        private
+
+        def content_from_repo(sha)
+          return unless project
+          return unless sha
+          return unless ci_config_path
+
+          project.repository.gitlab_ci_yml_for(sha, ci_config_path)
+        rescue GRPC::NotFound, GRPC::Internal
+          nil
+        end
+
+        def content_from_auto_devops
+          return unless project&.auto_devops_enabled?
+
+          Gitlab::Template::GitlabCiYmlTemplate.find('Auto-DevOps').content
+        end
+
+        def ci_config_path
+          project.ci_config_path.presence || '.gitlab-ci.yml'
+        end
+      end
+    end
+  end
+end
diff --git a/lib/gitlab/ci/pipeline/chain/config/content.rb b/lib/gitlab/ci/pipeline/chain/config/content.rb
index a8cd99b8e92..bd2dfceb7b4 100644
--- a/lib/gitlab/ci/pipeline/chain/config/content.rb
+++ b/lib/gitlab/ci/pipeline/chain/config/content.rb
@@ -9,18 +9,18 @@ module Gitlab
             include Chain::Helpers
 
             def perform!
-              return if @command.config_content
-
-              if content = content_from_repo
-                @command.config_content = content
-                @pipeline.config_source = :repository_source
-                # TODO: we should persist ci_config_path
-                # @pipeline.config_path = ci_config_path
-              elsif content = content_from_auto_devops
-                @command.config_content = content
-                @pipeline.config_source = :auto_devops_source
+              if @command.config_content
+                @pipeline.config_source = @command.config_content.source
+                return
               end
 
+              content = Gitlab::Ci::Config::Content
+                .new(@command.project)
+                .auto_generate(sha: @pipeline.sha)
+
+              @command.config_content = content
+              @pipeline.config_source = content.source
+
               unless @command.config_content
                 return error("Missing #{ci_config_path} file")
               end

and then

def create_child_pipeline!
  config_content = Gitlab::Ci::Config::Content.generate_for_child_pipeline

  ::Ci::CreatePipelineService...
    .execute(:pipeline, ignore_skip_ci: true, config_content: config_content)

This way, it's very clear how the config blob was generated, which would leave some room for us to extend the architecture.

Assignee Loading
Time tracking Loading