CI/CD analytics: Failure rate and Success rate denominator incorrectly includes canceled/skipped pipelines and jobs
## Summary On the project CI/CD analytics page (`<project>/-/pipelines/charts`), the **Failure rate** and **Success rate** in both the Pipelines KPI strip and the Jobs panel use a denominator that includes `canceled` and `skipped` rows. This silently dilutes both rates whenever a project has non-trivial canceled/skipped volume. A real-world example from `gitlab-org/gitlab`: the KPI strip displays **Failure rate 7%** and **Success rate 91%**. The two values should sum to ~100% (±1% due to integer-percent rounding) but instead sum to **98%**. The missing 2% is the canceled/skipped slice being absorbed into the denominator rather than counted as its own bucket. The Status chart on the same page already exposes this slice as a separate "Other (Cancelled, Skipped)" series, so the inconsistency is user-visible. ## What Both rate calculations on `<project>/-/pipelines/charts` currently use: ``` rate = count(status) / total_count ``` where `total_count` includes success + failed + canceled + skipped. The intended behavior is: ``` rate = count(status) / (count(success) + count(failed)) ``` Canceled is a deliberate user action and skipped is a config/dependency artifact — neither indicates job/pipeline health and should not depress the rates. Affected surfaces: | Surface | Component | Calculation layer | |---|---|---| | **Pipelines KPI strip** — Failure rate / Success rate | `app/assets/javascripts/ci/analytics/project_ci_cd_analytics/components/pipelines_stats.vue:57,63` | Frontend (`failedCount/count`, `successCount/count`) | | **Jobs panel table** (EE) — `failedRate` / `successRate` columns + `2 / N` tooltip | `ee/app/assets/javascripts/ci/analytics/project_ci_cd_analytics/components/job_analytics_table.vue:241-246` and the server-side aggregation in `lib/click_house/finders/ci/concerns/finished_builds_aggregations.rb:121-133` | Backend (ClickHouse aggregation) — `query_builder.count` denominator | Not affected: - Duration chart (p50/p95 only — no rate math). - Status chart (raw stacked counts with "Other" as its own bar). ## How (proposed fix) ### 1. Backend — Jobs panel rate aggregation File: `lib/click_house/finders/ci/concerns/finished_builds_aggregations.rb` (used by both `FinishedBuildsFinder` and `FinishedBuildsDeduplicatedFinder`). Change `build_rate_aggregate` so the denominator is `countIf(success) + countIf(failed)`: ```ruby def build_rate_aggregate(status) numerator = build_count_aggregate(status) denominator = query_builder.add( # confirm helper name build_count_aggregate('success'), build_count_aggregate('failed') ) safe_denominator = query_builder.named_func('nullIf', [denominator, 0]) percentage = query_builder.division(numerator, safe_denominator) percentage_value = query_builder.multiply(percentage, 100) round(percentage_value).as("rate_of_#{status}") end ``` Notes: - Confirm the QueryBuilder addition helper name in `lib/click_house/client/query_builder.rb`. - `nullIf(denominator, 0)` guards against `0/0` when a job's only finished outcomes are canceled/skipped — return `null` so the UI renders `-`. ### 2. Frontend — Pipelines KPI strip File: `app/assets/javascripts/ci/analytics/project_ci_cd_analytics/components/pipelines_stats.vue`. The GraphQL query already returns `successCount` and `failedCount`. Compute the denominator client-side: ```js const rateDenominator = (BigInt(successCount ?? 0) + BigInt(failedCount ?? 0)).toString(); // ... value: formatPipelineCountPercentage(failedCount, rateDenominator), value: formatPipelineCountPercentage(successCount, rateDenominator), ``` `Total pipeline runs` KPI continues to use `count` (the true unfiltered total — correct as-is). ### 3. Frontend — Jobs panel tooltip File: `ee/app/assets/javascripts/ci/analytics/project_ci_cd_analytics/components/job_analytics_table.vue:241-246`. Change tooltip from `formatCount(item.failedCount, item.count)` to use `BigInt(item.successCount) + BigInt(item.failedCount)` so the displayed fraction `N / M` matches the displayed rate.
issue