Commit 58a849e8 authored by Fabio Pitino's avatar Fabio Pitino

Refactor downstream pipeline params

Pass bridge job to pipeline creation

* Take config from bridge job during pipeline creation
  if bridge exist and returns a yaml_for_downstream

* Move Ci::Bridge#yaml_for_downstream to core
parent e73adda2
...@@ -54,6 +54,10 @@ module Ci ...@@ -54,6 +54,10 @@ module Ci
def to_partial_path def to_partial_path
'projects/generic_commit_statuses/generic_commit_status' 'projects/generic_commit_statuses/generic_commit_status'
end end
def yaml_for_downstream
nil
end
end end
end end
......
...@@ -511,10 +511,6 @@ module Ci ...@@ -511,10 +511,6 @@ module Ci
builds.skipped.after_stage(stage_idx).find_each(&:process) builds.skipped.after_stage(stage_idx).find_each(&:process)
end end
def child?
false
end
def latest? def latest?
return false unless git_ref && commit.present? return false unless git_ref && commit.present?
......
...@@ -23,7 +23,7 @@ module Ci ...@@ -23,7 +23,7 @@ module Ci
Gitlab::Ci::Pipeline::Chain::Limit::JobActivity].freeze Gitlab::Ci::Pipeline::Chain::Limit::JobActivity].freeze
# rubocop: disable Metrics/ParameterLists # rubocop: disable Metrics/ParameterLists
def execute(source, ignore_skip_ci: false, save_on_errors: true, trigger_request: nil, schedule: nil, merge_request: nil, external_pull_request: nil, config_content: nil, **options, &block) def execute(source, ignore_skip_ci: false, save_on_errors: true, trigger_request: nil, schedule: nil, merge_request: nil, external_pull_request: nil, bridge: nil, **options, &block)
@pipeline = Ci::Pipeline.new @pipeline = Ci::Pipeline.new
command = Gitlab::Ci::Pipeline::Chain::Command.new( command = Gitlab::Ci::Pipeline::Chain::Command.new(
...@@ -46,7 +46,7 @@ module Ci ...@@ -46,7 +46,7 @@ module Ci
current_user: current_user, current_user: current_user,
push_options: params[:push_options] || {}, push_options: params[:push_options] || {},
chat_data: params[:chat_data], chat_data: params[:chat_data],
config_content: config_content, bridge: bridge,
**extra_options(options)) **extra_options(options))
sequence = Gitlab::Ci::Pipeline::Chain::Sequence sequence = Gitlab::Ci::Pipeline::Chain::Sequence
......
...@@ -4,6 +4,7 @@ module EE ...@@ -4,6 +4,7 @@ module EE
module Ci module Ci
module Bridge module Bridge
extend ActiveSupport::Concern extend ActiveSupport::Concern
extend ::Gitlab::Utils::Override
include ::Gitlab::Utils::StrongMemoize include ::Gitlab::Utils::StrongMemoize
InvalidBridgeTypeError = Class.new(StandardError) InvalidBridgeTypeError = Class.new(StandardError)
...@@ -106,6 +107,14 @@ module EE ...@@ -106,6 +107,14 @@ module EE
yaml_for_downstream.present? yaml_for_downstream.present?
end end
override :yaml_for_downstream
def yaml_for_downstream
strong_memoize(:yaml_for_downstream) do
includes = options&.dig(:trigger, :include)
YAML.dump('include' => includes) if includes
end
end
def downstream_pipeline_params def downstream_pipeline_params
return child_params if triggers_child_pipeline? return child_params if triggers_child_pipeline?
return cross_project_params if downstream_project.present? return cross_project_params if downstream_project.present?
...@@ -123,13 +132,6 @@ module EE ...@@ -123,13 +132,6 @@ module EE
end end
end end
def yaml_for_downstream
strong_memoize(:yaml_for_downstream) do
includes = options&.dig(:trigger, :include)
YAML.dump('include' => includes) if includes
end
end
def upstream_project def upstream_project
strong_memoize(:upstream_project) do strong_memoize(:upstream_project) do
upstream_project_path && ::Project.find_by_full_path(upstream_project_path) upstream_project_path && ::Project.find_by_full_path(upstream_project_path)
...@@ -181,7 +183,8 @@ module EE ...@@ -181,7 +183,8 @@ module EE
source: :cross_project_pipeline, source: :cross_project_pipeline,
target_revision: { target_revision: {
ref: target_ref || downstream_project.default_branch ref: target_ref || downstream_project.default_branch
} },
execute_params: { ignore_skip_ci: true }
} }
end end
...@@ -198,8 +201,9 @@ module EE ...@@ -198,8 +201,9 @@ module EE
source_sha: parent_pipeline.source_sha, source_sha: parent_pipeline.source_sha,
target_sha: parent_pipeline.target_sha target_sha: parent_pipeline.target_sha
}, },
other_execute_params: { execute_params: {
config_content: yaml_for_downstream ignore_skip_ci: true,
bridge: self
} }
} }
end end
......
...@@ -19,8 +19,7 @@ module Ci ...@@ -19,8 +19,7 @@ module Ci
pipeline_params.fetch(:target_revision)) pipeline_params.fetch(:target_revision))
service.execute( service.execute(
pipeline_params.fetch(:source), pipeline_params.fetch(:source), pipeline_params[:execute_params]) do |pipeline|
{ ignore_skip_ci: true }.merge(pipeline_params[:other_execute_params] || {})) do |pipeline|
@bridge.sourced_pipelines.build( @bridge.sourced_pipelines.build(
source_pipeline: @bridge.pipeline, source_pipeline: @bridge.pipeline,
source_project: @bridge.project, source_project: @bridge.project,
......
...@@ -318,4 +318,33 @@ describe Ci::Bridge do ...@@ -318,4 +318,33 @@ describe Ci::Bridge do
it { is_expected.to be_falsey } it { is_expected.to be_falsey }
end end
end end
describe '#yaml_for_downstream' do
subject { bridge.yaml_for_downstream }
context 'when bridge defines a downstream YAML' do
let(:options) do
{
trigger: {
include: 'path/to/child.yml'
}
}
end
let(:yaml) do
<<~EOY
---
include: path/to/child.yml
EOY
end
it { is_expected.to eq yaml }
end
context 'when bridge does not define a downstream YAML' do
let(:options) { {} }
it { is_expected.to be_nil }
end
end
end end
...@@ -86,8 +86,11 @@ describe Ci::CreateCrossProjectPipelineService, '#execute' do ...@@ -86,8 +86,11 @@ describe Ci::CreateCrossProjectPipelineService, '#execute' do
end end
context 'when user can create pipeline in a downstream project' do context 'when user can create pipeline in a downstream project' do
let(:stub_config) { true }
before do before do
downstream_project.add_developer(user) downstream_project.add_developer(user)
stub_ci_pipeline_yaml_file(YAML.dump(rspec: { script: 'rspec' })) if stub_config
end end
it 'creates only one new pipeline' do it 'creates only one new pipeline' do
...@@ -130,10 +133,6 @@ describe Ci::CreateCrossProjectPipelineService, '#execute' do ...@@ -130,10 +133,6 @@ describe Ci::CreateCrossProjectPipelineService, '#execute' do
{ trigger: { project: upstream_project.full_path } } { trigger: { project: upstream_project.full_path } }
end end
before do
downstream_project.add_developer(user)
end
context 'detects a circular dependency' do context 'detects a circular dependency' do
it 'does not create a new pipeline' do it 'does not create a new pipeline' do
expect { service.execute(bridge) } expect { service.execute(bridge) }
...@@ -199,6 +198,8 @@ describe Ci::CreateCrossProjectPipelineService, '#execute' do ...@@ -199,6 +198,8 @@ describe Ci::CreateCrossProjectPipelineService, '#execute' do
upstream_pipeline.update!(sha: upstream_project.commit.id) upstream_pipeline.update!(sha: upstream_project.commit.id)
end end
let(:stub_config) { false }
let(:trigger) do let(:trigger) do
{ {
trigger: { include: 'child-pipeline.yml' } trigger: { include: 'child-pipeline.yml' }
......
...@@ -10,7 +10,7 @@ module Gitlab ...@@ -10,7 +10,7 @@ module Gitlab
:trigger_request, :schedule, :merge_request, :external_pull_request, :trigger_request, :schedule, :merge_request, :external_pull_request,
:ignore_skip_ci, :save_incompleted, :ignore_skip_ci, :save_incompleted,
:seeds_block, :variables_attributes, :push_options, :seeds_block, :variables_attributes, :push_options,
:chat_data, :allow_mirror_update, :chat_data, :allow_mirror_update, :bridge,
# These attributes are set by Chains during processing: # These attributes are set by Chains during processing:
:config_content, :config_processor, :stage_seeds :config_content, :config_processor, :stage_seeds
) do ) do
......
...@@ -6,12 +6,11 @@ module Gitlab ...@@ -6,12 +6,11 @@ module Gitlab
module Chain module Chain
module Config module Config
class Content class Content
# This case represents when a config content is passed in
# as parameter to Ci::CreatePipelineService from the outside.
# For example when creating a child pipeline.
class Bridge < Source class Bridge < Source
def content def content
@command.config_content return unless @command.bridge
@command.bridge.yaml_for_downstream
end end
def source def source
......
...@@ -15,18 +15,39 @@ describe Gitlab::Ci::Pipeline::Chain::Config::Content do ...@@ -15,18 +15,39 @@ describe Gitlab::Ci::Pipeline::Chain::Config::Content do
stub_feature_flags(ci_root_config_content: false) stub_feature_flags(ci_root_config_content: false)
end end
context 'when config is passed in as parameter and already available in command' do context 'when bridge job is passed in as parameter' do
let(:ci_config_path) { nil } let(:ci_config_path) { nil }
let(:bridge) { create(:ci_bridge) }
before do before do
command.config_content = 'the-content' command.bridge = bridge
end end
it 'returns the content already available in command' do context 'when bridge job has downstream yaml' do
subject.perform! before do
allow(bridge).to receive(:yaml_for_downstream).and_return('the-yaml')
end
it 'returns the content already available in command' do
subject.perform!
expect(pipeline.config_source).to eq 'bridge_source' expect(pipeline.config_source).to eq 'bridge_source'
expect(command.config_content).to eq 'the-content' expect(command.config_content).to eq 'the-yaml'
end
end
context 'when bridge job does not have downstream yaml' do
before do
allow(bridge).to receive(:yaml_for_downstream).and_return(nil)
end
it 'returns the next available source' do
subject.perform!
expect(pipeline.config_source).to eq 'auto_devops_source'
template = Gitlab::Template::GitlabCiYmlTemplate.find('Beta/Auto-DevOps')
expect(command.config_content).to eq(template.content)
end
end end
end end
...@@ -150,18 +171,20 @@ describe Gitlab::Ci::Pipeline::Chain::Config::Content do ...@@ -150,18 +171,20 @@ describe Gitlab::Ci::Pipeline::Chain::Config::Content do
end end
end end
context 'when config is passed in as parameter and already available in command' do context 'when bridge job is passed in as parameter' do
let(:ci_config_path) { nil } let(:ci_config_path) { nil }
let(:bridge) { create(:ci_bridge) }
before do before do
command.config_content = 'the-content' command.bridge = bridge
allow(bridge).to receive(:yaml_for_downstream).and_return('the-yaml')
end end
it 'returns the content already available in command' do it 'returns the content already available in command' do
subject.perform! subject.perform!
expect(pipeline.config_source).to eq 'bridge_source' expect(pipeline.config_source).to eq 'bridge_source'
expect(command.config_content).to eq 'the-content' expect(command.config_content).to eq 'the-yaml'
end end
end end
......
...@@ -6,20 +6,24 @@ describe Ci::CreatePipelineService do ...@@ -6,20 +6,24 @@ describe Ci::CreatePipelineService do
let_it_be(:user) { create(:admin) } let_it_be(:user) { create(:admin) }
let(:ref) { 'refs/heads/master' } let(:ref) { 'refs/heads/master' }
let(:service) { described_class.new(project, user, { ref: ref }) } let(:service) { described_class.new(project, user, { ref: ref }) }
let(:pipeline) { service.execute(:push, config_content: config_content) }
context 'custom config content' do context 'custom config content' do
let(:config_content) do let(:bridge) do
YAML.dump( double(:bridge, yaml_for_downstream: <<~YML
rspec: { script: 'rspec' }, rspec:
custom: { script: 'custom' } script: rspec
custom:
script: custom
YML
) )
end end
subject { service.execute(:push, bridge: bridge) }
it 'creates a pipeline using the content passed in as param' do it 'creates a pipeline using the content passed in as param' do
expect(pipeline).to be_persisted expect(subject).to be_persisted
expect(pipeline.builds.map(&:name)).to eq %w[rspec custom] expect(subject.builds.map(&:name)).to eq %w[rspec custom]
expect(pipeline.config_source).to eq 'bridge_source' expect(subject.config_source).to eq 'bridge_source'
end end
end end
end end
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