Draft: VAC: find-only default context in ingestion (durable fix for #612930)
What does this MR do and why?
This is the durable fix for #612930, where the first pipeline on a project's default branch drops the entire SAST slice on ingestion. It makes the ingest phase resolve the tracked default context find-only, mirroring the store phase, so both phases agree on which UUID scheme to use. Tracked under #613547.
Draft while I self-review, then over to Ryan (@ryaanwells) for review. No reviewers assigned yet.
Root cause
There's a store/ingest asymmetry.
The store phase resolves the tracked context find-only. EE::Gitlab::Ci::Reports::Security::Report#tracked_context does ProjectTrackedContext.for_pipeline(pipeline).tracked.first, which is nil when a project has no tracked default context. Findings are stored with context-unaware (v1) UUIDs.
The async ingest phase then lazily find-or-creates a v2 default context mid-pipeline (via TrackedContextFinder#find_or_create_from_pipeline) and re-parses, producing context-aware (v2) UUIDs.
The stored-v1 versus reparsed-v2 UUID mismatch makes the ingestion join miss, so the whole SAST slice is dropped.
The fix
Permissive legacy fallback. Make the ingest phase find-only too, so it matches the store phase. A project without a tracked default context resolves to nil in both phases, both produce v1 UUIDs, the join hits, and nothing is dropped.
The default branch stays legacy v1/NULL-context until it is legitimately tracked, either via CreateOrUpdateDefaultTrackedContextWorker or explicit tracking.
Implementation changes:
- Added
find_from_pipeline/find_from_projecttoTrackedContextFinder(find-only,nilwhen absent). The existingfind_or_create_*methods stay for the advisory scanner caller. FindingMapCollection#tracked_contextandIngestReportsService#tracked_contextswitch to find-only under the FF.log_ingestionis nil-guarded (tracked_context&.is_default?).MarkAsResolvedServiceroutes aniltracked_context to the context-less path, same as when VAC is disabled.
Feature flag
vac_find_only_default_context_ingestion (development, default_enabled: false). Off preserves the existing find-or-create behavior. On switches the ingest phase to find-only.
Test coverage
Added and extended specs in ee/spec/services/security/ingestion/:
tracked_context_finder_specfinding_map_collection_specingest_reports_service_specmark_as_resolved_service_spec
They cover: a first default-branch pipeline with no pre-existing context ingests as v1 when the FF is on; a legacy no-context project doesn't raise ArgumentError and passes nil context through; FF-off preserves current behavior.
Note: mark_as_resolved_service_spec is :elastic-tagged and requires a running Elasticsearch, which wasn't available in the local dev environment; the other three spec files were run locally and pass. CI will exercise the full set.
Related
- Interim safety-net (dual-key join): !250066 (closed)
- Longer-horizon UUID simplification: #613600
- Rollout issue: #613547