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