Factory-heavy RSpec test observability, guardrails, and remediation
### Problem Statement
GitLab's RSpec test suite relies heavily on **factories** — a pattern used to create database records (users, projects, merge requests, etc.) within tests. While convenient, factories are expensive: each one triggers real database writes, and deeply nested factories can create dozens of records to test a single scenario.
As the codebase grows, so does factory usage — and the CI time it consumes. A 2022 profiling run ([MR !98000](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/98000)) gave us a snapshot: the `project` factory alone accounted for **~11.7 hours of CI time per full pipeline run**, and across spec types, we have **16** RSpec test types that **spend more than 40% of their runtime creating factories** (e.g. _model_ specs spent **58% of their runtime in factories**).
We have no live data to know where things stand today. This epic aims to fix that — and to act on it.
### Approach
We tackle this in three pillars, in order:
1. **Observability first** (~"group::development analytics"): Before doing anything else, we need baseline data. We will ingest factory profiling data into ClickHouse and build a dashboard so we can see where time is actually being spent — by factory, by spec type, by team. This data also unlocks threshold calibration for guardrails.
2. **Guardrails second** (~"group::test governance"): With data in hand, we audit and expand existing RuboCop factory cops — calibrating thresholds against real usage rather than guessing. The goal is to block new factory-heavy violations at the MR level, especially as AI-generated tests become more common.
3. **Remediation last** (~"group::test governance"): Once we understand the problem and have guardrails in place, we address the existing backlog. The approach is intentionally open: it may involve distributing work to teams, a centralized one-off effort, AI agent-driven automation, or a mix — to be decided based on what the POC reveals.
### Exit Criteria
- **Observability** (~"group::development analytics"): Factory profiling data is ingested into ClickHouse and a dashboard surfaces factory health metrics by factory name, spec type, and team
- **Guardrails** (~"group::test governance"): RuboCop factory cops are audited, scopes expanded, and thresholds calibrated with real data — blocking new violations at the MR level
- **Remediation** (~"group::test governance"): A POC demonstrates measurable improvement on one factory-heavy spec file, and a plan distributes the remaining work across engineering teams
### Topics
#### Observability (~"group::development analytics")
| Item | Tracking | Status |
|------|----------|--------|
| Ingest factory profiling data into ClickHouse | [#630](https://gitlab.com/gitlab-org/quality/analytics/team/-/work_items/630) | 📋 Planned |
| Factory health dashboard & triage reporting | [#631](https://gitlab.com/gitlab-org/quality/analytics/team/-/work_items/631) | 📋 Planned |
#### Guardrails (~"group::test governance")
| Item | Tracking | Status |
|------|----------|--------|
| Audit & enable RuboCop factory cops, calibrated with data | [#632](https://gitlab.com/gitlab-org/quality/analytics/team/-/work_items/632) | 📋 Planned |
#### Remediation (~"group::test governance")
| Item | Tracking | Status |
|------|----------|--------|
| POC — fix one factory-heavy spec file | [#633](https://gitlab.com/gitlab-org/quality/analytics/team/-/work_items/633) | 📋 Planned |
| Factory remediation plan & team distribution | [#634](https://gitlab.com/gitlab-org/quality/analytics/team/-/work_items/634) | 📋 Planned |
### Development Log
<!-- STATUS NOTE START -->
<!-- STATUS NOTE END -->
epic