Make Security Report UnmarshalJSON forward-compatible by skipping unknown events
Problem
The report.Observability.UnmarshalJSON method fails hard when encountering unregistered event types, forcing all event definitions to be centralized in the report package.
Current behavior:
factory, exists := eventRegistry[baseEvent.Event]
if !exists {
return fmt.Errorf("unknown event type: %s", baseEvent.Name()) // Hard failure
}
Impact:
- Every new analyzer event requires MRs across report package, tracking calculator, and infrastructure before it can be used
- Older post-analyzers crash when processing reports with newer event types, blocking CI pipelines
- Cannot test metrics locally without coordinating releases across multiple repos
Example failure:
Secret Detection registers collect_secret_detection_scan_metrics_from_pipeline in its own observability package. Tracking calculator (using older report version) fails:
[FATA] unknown event type: collect_secret_detection_scan_metrics_from_pipeline
Proposal
Make unmarshaling lenient to support decentralized event registration:
factory, exists := eventRegistry[baseEvent.Event]
if !exists {
log.Debugf("Event type '%s' registered in analyzer, skipping", baseEvent.Name())
continue // Skip analyzer-specific events
}
This allows analyzers to register events in their own packages while maintaining compatibility with older post-analyzer versions.
Benefits
- Decentralized ownership: Analyzers register events in their own packages
- Independent development: Add metrics without cross-repo dependencies
- Version tolerance: Older tools skip newer analyzer events gracefully
- Faster iteration: Test locally without infrastructure updates
- No pipeline breaks: Unknown events don't crash post-analyzers
Trade-offs
- Analyzer-specific events not processed by older post-analyzers (expected - they skip processing but preserve the report)
- Events lost if report is re-serialized (acceptable for tracking calculator's read-modify-write workflow)
Implementation plan
-
Bump tracking-calculator report module to 6.x: https://gitlab.com/gitlab-org/security-products/post-analyzers/tracking-calculator/-/merge_requests/104+ (Preparatory step to ensure a smooth migration) -
Integrate a fallback option into the report module that ensures unregistered events are passed through (post-analyzer use-case): gitlab-org/security-products/analyzers/report!128 and release a new version -
Bump report module versions for secrets, semgrep, GLAS and spotbugs
After these changes we should be able to register new observability events on the consumer side of the report module without the necessity for upstream changes.
Edited by Julian Thome