Commit bd60ee82 authored by Kamil Trzciński's avatar Kamil Trzciński

Merge branch 'revert-53801134' into 'master'

Revert "Merge branch 'validate-dynamic-pipeline-dependencies' into 'master'"

See merge request gitlab-org/gitlab!28904
parents f634a675 3e7d7f08
---
title: Validate dependency on job generating a CI config when using dynamic child pipelines
merge_request: 27916
author:
type: added
...@@ -136,11 +136,12 @@ your own script to generate a YAML file, which is then [used to trigger a child ...@@ -136,11 +136,12 @@ your own script to generate a YAML file, which is then [used to trigger a child
This technique can be very powerful in generating pipelines targeting content that changed or to This technique can be very powerful in generating pipelines targeting content that changed or to
build a matrix of targets and architectures. build a matrix of targets and architectures.
In GitLab 12.9, the child pipeline could fail to be created in certain cases, causing the parent pipeline to fail.
This is [resolved in GitLab 12.10](https://gitlab.com/gitlab-org/gitlab/-/issues/209070).
## Limitations ## Limitations
A parent pipeline can trigger many child pipelines, but a child pipeline cannot trigger A parent pipeline can trigger many child pipelines, but a child pipeline cannot trigger
further child pipelines. See the [related issue](https://gitlab.com/gitlab-org/gitlab/issues/29651) further child pipelines. See the [related issue](https://gitlab.com/gitlab-org/gitlab/issues/29651)
for discussion on possible future improvements. for discussion on possible future improvements.
When triggering dynamic child pipelines, if the job containing the CI config artifact is not a predecessor of the
trigger job, the child pipeline will fail to be created, causing also the parent pipeline to fail.
In the future we want to validate the trigger job's dependencies [at the time the parent pipeline is created](https://gitlab.com/gitlab-org/gitlab/-/issues/209070) rather than when the child pipeline is created.
...@@ -15,11 +15,6 @@ module Gitlab ...@@ -15,11 +15,6 @@ module Gitlab
validations do validations do
validates :config, hash_or_string: true validates :config, hash_or_string: true
validates :config, allowed_keys: ALLOWED_KEYS validates :config, allowed_keys: ALLOWED_KEYS
validate do
if config[:artifact] && config[:job].blank?
errors.add(:config, "must specify the job where to fetch the artifact from")
end
end
end end
end end
end end
......
...@@ -142,7 +142,6 @@ module Gitlab ...@@ -142,7 +142,6 @@ module Gitlab
validate_job_stage!(name, job) validate_job_stage!(name, job)
validate_job_dependencies!(name, job) validate_job_dependencies!(name, job)
validate_job_needs!(name, job) validate_job_needs!(name, job)
validate_dynamic_child_pipeline_dependencies!(name, job)
validate_job_environment!(name, job) validate_job_environment!(name, job)
end end
end end
...@@ -164,50 +163,35 @@ module Gitlab ...@@ -164,50 +163,35 @@ module Gitlab
def validate_job_dependencies!(name, job) def validate_job_dependencies!(name, job)
return unless job[:dependencies] return unless job[:dependencies]
job[:dependencies].each do |dependency| stage_index = @stages.index(job[:stage])
validate_job_dependency!(name, dependency)
end
end
def validate_dynamic_child_pipeline_dependencies!(name, job) job[:dependencies].each do |dependency|
return unless includes = job.dig(:trigger, :include) raise ValidationError, "#{name} job: undefined dependency: #{dependency}" unless @jobs[dependency.to_sym]
includes.each do |included| dependency_stage_index = @stages.index(@jobs[dependency.to_sym][:stage])
next unless dependency = included[:job]
validate_job_dependency!(name, dependency) unless dependency_stage_index.present? && dependency_stage_index < stage_index
raise ValidationError, "#{name} job: dependency #{dependency} is not defined in prior stages"
end
end end
end end
def validate_job_needs!(name, job) def validate_job_needs!(name, job)
return unless needs = job.dig(:needs, :job) return unless job.dig(:needs, :job)
needs.each do |need| stage_index = @stages.index(job[:stage])
dependency = need[:name]
validate_job_dependency!(name, dependency, 'need')
end
end
def validate_job_dependency!(name, dependency, dependency_type = 'dependency') job.dig(:needs, :job).each do |need|
unless @jobs[dependency.to_sym] need_job_name = need[:name]
raise ValidationError, "#{name} job: undefined #{dependency_type}: #{dependency}"
end
job_stage_index = stage_index(name) raise ValidationError, "#{name} job: undefined need: #{need_job_name}" unless @jobs[need_job_name.to_sym]
dependency_stage_index = stage_index(dependency)
# A dependency might be defined later in the configuration needs_stage_index = @stages.index(@jobs[need_job_name.to_sym][:stage])
# with a stage that does not exist
unless dependency_stage_index.present? && dependency_stage_index < job_stage_index
raise ValidationError, "#{name} job: #{dependency_type} #{dependency} is not defined in prior stages"
end
end
def stage_index(name) unless needs_stage_index.present? && needs_stage_index < stage_index
job = @jobs[name.to_sym] raise ValidationError, "#{name} job: need #{need_job_name} is not defined in prior stages"
return unless job end
end
@stages.index(job[:stage])
end end
def validate_job_environment!(name, job) def validate_job_environment!(name, job)
......
...@@ -1647,48 +1647,6 @@ module Gitlab ...@@ -1647,48 +1647,6 @@ module Gitlab
it { expect { subject }.to raise_error(Gitlab::Ci::YamlProcessor::ValidationError, /is not defined in prior stages/) } it { expect { subject }.to raise_error(Gitlab::Ci::YamlProcessor::ValidationError, /is not defined in prior stages/) }
end end
context 'when trigger job includes artifact generated by a dependency' do
context 'when dependency is defined in previous stages' do
let(:config) do
{
build1: { stage: 'build', script: 'test' },
test1: { stage: 'test', trigger: {
include: [{ job: 'build1', artifact: 'generated.yml' }]
} }
}
end
it { expect { subject }.not_to raise_error }
end
context 'when dependency is defined in later stages' do
let(:config) do
{
build1: { stage: 'build', script: 'test' },
test1: { stage: 'test', trigger: {
include: [{ job: 'deploy1', artifact: 'generated.yml' }]
} },
deploy1: { stage: 'deploy', script: 'test' }
}
end
it { expect { subject }.to raise_error(Gitlab::Ci::YamlProcessor::ValidationError, /is not defined in prior stages/) }
end
context 'when dependency is not defined' do
let(:config) do
{
build1: { stage: 'build', script: 'test' },
test1: { stage: 'test', trigger: {
include: [{ job: 'non-existent', artifact: 'generated.yml' }]
} }
}
end
it { expect { subject }.to raise_error(Gitlab::Ci::YamlProcessor::ValidationError, /undefined dependency: non-existent/) }
end
end
end end
describe "Job Needs" do describe "Job Needs" do
...@@ -2094,34 +2052,6 @@ module Gitlab ...@@ -2094,34 +2052,6 @@ module Gitlab
end end
end end
describe 'with trigger:include' do
context 'when artifact and job are specified' do
let(:config) do
YAML.dump({
build1: { stage: 'build', script: 'test' },
test1: { stage: 'test', trigger: {
include: [{ artifact: 'generated.yml', job: 'build1' }]
} }
})
end
it { expect { subject }.not_to raise_error }
end
context 'when artifact is specified without job' do
let(:config) do
YAML.dump({
build1: { stage: 'build', script: 'test' },
test1: { stage: 'test', trigger: {
include: [{ artifact: 'generated.yml' }]
} }
})
end
it { expect { subject }.to raise_error(Gitlab::Ci::YamlProcessor::ValidationError, /must specify the job where to fetch the artifact from/) }
end
end
describe "Error handling" do describe "Error handling" do
it "fails to parse YAML" do it "fails to parse YAML" do
expect do expect do
......
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