Add security_scan_profiles as a CI job source

What does this MR do and why?

Adds security_scan_profiles: 1003 as a new Ci::BuildSource enum value, wires up the SetBuildSources pipeline chain to tag jobs from profile-triggered pipelines with this source, and introduces a PipelineContext that tracks which specific profile generated each job via the _metadata pattern.

Why: Before profile statuses can be tracked (#591555 (closed)), profile-triggered CI jobs must be identifiable and traceable back to their originating profile. Currently, Ci::BuildSource tracks scan_execution_policy and pipeline_execution_policy but has no value for jobs triggered by security scan profiles. Without this, the status update service (follow-up #593132 (closed)) cannot filter to profile-triggered jobs or determine which profile to update.

This is MR 1 of 4 in the implementation plan. All subsequent MRs depend on being able to filter jobs by source: security_scan_profiles and resolve the originating profile ID.

Implementation details

  • Ci::BuildSource (app/models/ci/build_source.rb): adds security_scan_profiles: 1003 enum value. No migration needed since p_ci_build_sources.source is an integer column and the enum is application-level.
  • SetBuildSources chain (lib/gitlab/ci/pipeline/chain/set_build_sources.rb): adds security_scan_profile_build? check after scan_execution_policy_build? but before the fallback. CE stub returns false.
  • EE override (ee/lib/ee/gitlab/ci/pipeline/chain/set_build_sources.rb): for dedicated profile pipelines (config_source == 'security_scan_profiles_source'), all jobs are tagged. For mixed pipelines, per-job identification uses the PipelineContext.
  • PipelineContext (ee/lib/gitlab/ci/pipeline/security_scan_profiles/pipeline_context.rb): new context object (following the ScanExecutionPolicies::PipelineContext pattern) that wraps PipelineEligibilityService and stores a { job_name => metadata } mapping extracted from _metadata on job configs. Provides job_injected?(name) for source tagging and profile_id_for_job(name) for profile ID resolution.
  • Processor (ee/lib/gitlab/ci/config/security_scan_profiles/processor.rb): passes metadata: { profile_id: trigger.scan_profile.id } when building profile actions. The ScanPipelineService / CiAction::Template chain attaches this as _metadata on each generated job config. The Processor then calls collect_injected_job_names_with_metadata on the PipelineContext (same API as ScanExecutionPolicies::PipelineContext) and strips _metadata before merging into the final config.
  • Plumbing: scan_profile_context is the single entry point on the Command, encapsulating the PipelineEligibilityService. It is passed through Command -> yaml_processor_opts -> ConfigEE -> External::Context so the Processor can populate it and SetBuildSources can read it.

How to set up and validate locally

  1. In GDK, create a group and a project with a repository
  2. Attach a scan profile (e.g., Secret Detection) to the group and apply it to the project
  3. Push a commit to the project's default branch to trigger a pipeline
  4. Verify the profile-injected jobs have the correct source:
pipeline = Ci::Pipeline.last
pipeline.builds.each do |build|
  source = Ci::BuildSource.find_by(build_id: build.id, project_id: pipeline.project_id)
  puts "#{build.name}: #{source&.source}"
end ; nil
# Profile-injected jobs (e.g., secret-detection-0) should show "security_scan_profiles"
# Regular YAML jobs (e.g., build, test) should show the pipeline source

MR acceptance checklist

  • Tests added for CE stub (spec/lib/gitlab/ci/pipeline/chain/set_build_sources_spec.rb)
  • Tests added for EE override (ee/spec/lib/ee/gitlab/ci/pipeline/chain/set_build_sources_spec.rb)
  • Tests added for PipelineContext (ee/spec/lib/gitlab/ci/pipeline/security_scan_profiles/pipeline_context_spec.rb)
  • Tests added for Processor metadata collection and stripping (ee/spec/lib/gitlab/ci/config/security_scan_profiles/processor_spec.rb)
  • Integration tests added (ee/spec/services/ci/create_pipeline_service/set_build_sources_spec.rb)
  • No database migration needed
  • No performance impact (single string comparison in the pipeline chain, lightweight hash lookup for profile mapping)
  • Feature flag: not needed (enum value is inert until consumed by follow-up MRs)

Changelog: added
EE: true

Edited by Nicolae Rotaru

Merge request reports

Loading
Loading