BUG: Scan and Pipeline Execution Policies do not work correctly when repos have no or blank .gitlab-ci.yaml
Summary
When using a combination of Scan Execution and Pipeline Execution policies, scan jobs do not get run when a Repo has no .gitlab-ci.yaml file
When using a Pipeline Execution policy, pipelines do not get execution when Repo has a blank .gitlab-ci.yaml file
Steps to reproduce
Scenario 1:
- Setup a Repo with no .gitlab-ci.yaml file
- Add a Pipeline Execution policy with inject_ci as it's strategy to the Group
- Add a Scan Execution policy defining some scans to the Group
- Run Pipeline on Repo -> BUG Only jobs in Pipeline Execution Policy get executed
- Add a .gitlab-ci.yaml file to Repo with a "Hello World" job. -> Both Pipeline Execution and Scan Execution policy jobs get run
Scenario 2:
- Setup a Repo with an empty .gitlab-ci.yaml file
- Add a Pipeline Execution policy with inject_ci as it's strategy to the Group
- Run pipeline on Repo -> BUG Pipeline fails with error
Included file.gitlab-ci.ymldoes not have valid YAML syntax!
What is the expected correct behavior?
Scenario 1: Scan Execution jobs appear in pipelines along with Pipeline Execution jobs
Scenario 2: Pipeline Execution jobs should still be run if .gitlab-ci.yml is blank, otherwise users could bypass security controls
Implementation plan
Scenario 1:
We currently clear the whole pipeline with the pipeline source pipeline_execution_policy_forced. This removes also the SEP jobs. Rough patch to address it (we should probably only clear the DUMMY job instead of the .pre stage):
diff --git a/ee/lib/ee/gitlab/ci/pipeline/chain/pipeline_execution_policies/merge_jobs.rb b/ee/lib/ee/gitlab/ci/pipeline/chain/pipeline_execution_policies/merge_jobs.rb
index 306f0fd8c71b..ff6c83fd29a8 100644
--- a/ee/lib/ee/gitlab/ci/pipeline/chain/pipeline_execution_policies/merge_jobs.rb
+++ b/ee/lib/ee/gitlab/ci/pipeline/chain/pipeline_execution_policies/merge_jobs.rb
@@ -44,12 +44,13 @@ def clear_project_pipeline
# the DUMMY job to enforce the pipeline without project CI configuration.
# 2. any policy uses `override_project_ci` strategy.
# It means that we need to ignore the project CI configuration.
- unless pipeline.pipeline_execution_policy_forced? ||
- command.pipeline_policy_context.has_overriding_execution_policy_pipelines?
- return
+ if pipeline.pipeline_execution_policy_forced?
+ pipeline.stages = pipeline.stages.reject do |stage|
+ stage.name == ::Gitlab::Ci::Config::EdgeStagesInjector::PRE_PIPELINE
+ end
+ elsif command.pipeline_policy_context.has_overriding_execution_policy_pipelines?
+ pipeline.stages = []
end
-
- pipeline.stages = []
end
def merge_policy_jobs
diff --git a/ee/spec/services/ci/create_pipeline_service/pipeline_execution_policy_spec.rb b/ee/spec/services/ci/create_pipeline_service/pipeline_execution_policy_spec.rb
index ec87f803094e..7618d6b984e2 100644
--- a/ee/spec/services/ci/create_pipeline_service/pipeline_execution_policy_spec.rb
+++ b/ee/spec/services/ci/create_pipeline_service/pipeline_execution_policy_spec.rb
@@ -569,6 +569,33 @@
expect(stages.find_by(name: 'build').builds.map(&:name)).to contain_exactly('namespace_policy_job')
expect(stages.find_by(name: 'test').builds.map(&:name)).to contain_exactly('project_policy_job')
end
+
+ context 'when both Scan Execution Policy and Pipeline Execution Policy are applied on the project' do
+ let(:scan_execution_policy) do
+ build(:scan_execution_policy, actions: [{ scan: 'secret_detection' }])
+ end
+
+ let(:project_policy_yaml) do
+ build(:orchestration_policy_yaml,
+ pipeline_execution_policy: [project_policy],
+ scan_execution_policy: [scan_execution_policy])
+ end
+
+ it 'persists both pipeline execution policy and scan execution policy jobs', :aggregate_failures do
+ expect { execute }.to change { Ci::Build.count }.from(0).to(3)
+
+ expect(execute).to be_success
+ expect(execute.payload).to be_persisted
+
+ stages = execute.payload.stages
+ expect(stages.map(&:name)).to contain_exactly('build', 'test')
+
+ expect(stages.find_by(name: 'build').builds.map(&:name)).to contain_exactly('namespace_policy_job')
+ expect(stages.find_by(name: 'test').builds.map(&:name))
+ .to contain_exactly('project_policy_job', 'secret-detection-0')
+ end
+ end
end
context 'when commit contains a [ci skip] directive' do
Scenario 2:
This is currently expected, but we can make an enhancement to it.
We have to force the project pipeline to continue if we run in pipeline_context.execution_policy_mode? and the project CI is invalid. The config is processed in lib/gitlab/ci/pipeline/chain/config/process.rb, so we'll need to override it if the validation fails there and there are PEPs to run.