Skip to content

feat: dora table#109

Merged
waltergalvao merged 3 commits intomainfrom
feat/dora-team-table
Apr 23, 2026
Merged

feat: dora table#109
waltergalvao merged 3 commits intomainfrom
feat/dora-team-table

Conversation

@waltergalvao
Copy link
Copy Markdown
Contributor

@waltergalvao waltergalvao commented Apr 23, 2026

Greptile Summary

This PR adds a DORA team overview table that surfaces deployment count, lead time, CFR, and MTTR per team for the selected date range. The backend uses a single CTE-based SQL query (getDoraTeamOverview) that correctly scopes deployments to each team via the TeamMember join, with thorough integration test coverage for edge cases (archived entities, multi-team attribution, deployment-cohort anchoring for incidents).

Confidence Score: 5/5

Safe to merge; all remaining findings are P2 style suggestions.

The backend SQL logic is well-structured and tested (16 integration tests covering archived entities, multi-team attribution, null authors, date range boundaries, and incident-cohort anchoring). The null-sentinel sort ordering issue was flagged in a previous review cycle. Only a minor CFR display formatting nit remains.

apps/web/src/app/metrics-and-insights/dora/components/table-team-overview/table-team-overview.tsx — null sentinel sort order (previous review) and CFR precision formatting.

Important Files Changed

Filename Overview
apps/api/src/app/metrics/services/dora-metrics.service.ts Adds getDoraTeamOverview with a single CTE-based SQL query; correctly strips teamIds from base deployment filters and re-applies team scoping via TeamMember join; lead-time, CFR, and MTTR semantics are consistent with existing per-metric services.
apps/api/src/app/metrics/services/dora-metrics.integration.test.ts Adds comprehensive Team Overview test suite covering team filtering, date ranges, archived entities, multi-team attribution, null-author deployments, and deployment-cohort anchoring for MTTR/CFR. Also adds CFR/MTTR archived-incident tests.
apps/web/src/app/metrics-and-insights/dora/components/table-team-overview/table-team-overview.tsx New sortable table component for DORA team overview; null sentinels (-1) for leadTimeMs and meanTimeToRecoverMs sort null teams to the top under ascending sort (flagged in previous review); CFR formatting is inconsistent.
apps/web/src/app/metrics-and-insights/dora/page.tsx Integrates TeamOverview table below the trends outlet; uses LoadableContent + Skeleton correctly.
apps/web/src/api/dora-metrics.api.ts Adds teamOverview fields to the DoraMetrics GraphQL query; query key and client usage unchanged.
apps/web/src/sandbox/handlers/dora-metrics.ts Adds two realistic mock rows for teamOverview in the MSW sandbox handler; second row correctly uses null for meanTimeToRecoverMs.
apps/api/src/app/metrics/resolvers/dora-metrics.schema.ts Adds TeamDoraOverviewRow type and teamOverview field; outer list nullable is intentional.
apps/api/src/app/metrics/resolvers/queries/dora-metrics.query.ts Wires teamOverview resolver; authorization guard and filter building mirrors existing resolvers.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[DoraPage] -->|teamOverview query| B[teamOverview resolver]
    B --> C[getDoraTeamOverview]
    C --> D{Build CTEs}
    D --> E[all_teams\nfiltered by workspace + teamIds]
    D --> F[deployments_scoped\ndate range + env + app filters]
    D --> G[deployment_lead_times\ndeployments with PRs]
    E --> H[team_deployments\nTeamMember join]
    F --> H
    H --> I[team_lead\nAVG lead time]
    H --> J[team_deploy_count\nCOUNT deployments]
    H --> K[team_cfr\nincidents / deployments x 100]
    H --> L[team_mttr\nAVG resolved incident duration]
    E --> M[Final SELECT\nLEFT JOIN all metrics]
    I --> M
    J --> M
    K --> M
    L --> M
    M --> N[TableTeamOverview\nsortable frontend table]
Loading

Comments Outside Diff (2)

  1. apps/web/src/app/metrics-and-insights/dora/components/table-team-overview/table-team-overview.tsx, line 1147-1151 (link)

    P2 Null values sort to the top under ascending sort

    Rows with null lead time or MTTR are assigned a sentinel value of -1, which puts them at the top under an ascending sort and the bottom under a descending sort. Teams without data appear before teams with data when sorting ascending, which is counterintuitive — usually inactive teams should sort to the bottom regardless of direction. Consider using Infinity for the missing-data sentinel so null rows always land at the end:

  2. apps/web/src/app/metrics-and-insights/dora/components/table-team-overview/table-team-overview.tsx, line 1154-1159 (link)

    P2 Same null sentinel issue for MTTR sorting

    Same problem as leadTimeMs: null MTTR is assigned -1, which sorts those teams above teams with real (positive) MTTR values when sorting ascending.

Reviews (3): Last reviewed commit: "fix: row click" | Re-trigger Greptile

@waltergalvao waltergalvao marked this pull request as ready for review April 23, 2026 07:08
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 23, 2026

Walkthrough

Adds a team-level Dora metrics surface: GraphQL schema and types, a new resolver and service method to compute per-team aggregates, extensive integration tests, frontend query/types updates, a new sortable Team Overview table component, page integration, and sandbox mock data.

Changes

Cohort / File(s) Summary
GraphQL schema & generated types
apps/api/src/app/metrics/resolvers/dora-metrics.schema.ts, packages/graphql-types/api.ts, packages/graphql-types/frontend/gql.ts, packages/graphql-types/frontend/graphql.ts
Adds TeamDoraOverviewRow type and DoraMetrics.teamOverview field; adds DoraMetricsTeamOverviewArgs; updates several KPI change fields from IntFloat; regenerates resolver/type entries.
Backend resolver
apps/api/src/app/metrics/resolvers/queries/dora-metrics.query.ts
Adds teamOverview field resolver that validates workspace context, builds Dora filters, and delegates to service getDoraTeamOverview.
Backend service & types
apps/api/src/app/metrics/services/dora-metrics.service.ts, apps/api/src/app/metrics/services/dora-metrics.types.ts
Adds getDoraTeamOverview(filters) implementation with SQL aggregations (avg lead time, deployment count, change failure rate excluding archived incidents, avg MTTR excluding archived causes); adds DoraTeamOverviewSqlRow type; small formatting change to FailureRateResult.
Backend integration tests
apps/api/src/app/metrics/services/dora-metrics.integration.test.ts
Large test additions covering team overview computations, archived entity exclusion, attribution rules, ordering, filtering (teamIds, date range, production-only), and multi-tenant isolation.
Frontend query & hook
apps/web/src/api/dora-metrics.api.ts, apps/web/src/app/metrics-and-insights/dora/useDoraMetrics.tsx, packages/graphql-types/frontend/gql.ts, packages/graphql-types/frontend/graphql.ts
Includes teamOverview selection in DoraMetrics GraphQL query; updates generated frontend types; useDoraMetrics now returns metrics.teamOverview.
Frontend UI component & integration
apps/web/src/app/metrics-and-insights/dora/components/table-team-overview/table-team-overview.tsx, apps/web/src/app/metrics-and-insights/dora/components/table-team-overview/index.ts, apps/web/src/app/metrics-and-insights/dora/page.tsx
Adds TableTeamOverview component (sortable table, formatting, null handling) plus barrel export and integrates it into the DORA page with loadable skeleton.
Sandbox & mocks
apps/web/src/sandbox/handlers/dora-metrics.ts
Adds teamOverview mock payload with sample team rows (one row with null MTTR).
Other frontend changes
apps/web/src/app/metrics-and-insights/code-review-efficiency/components/table-team-overview/table-team-overview.tsx, apps/web/src/app/metrics-and-insights/pr-flow/components/table-team-overview/table-team-overview.tsx
Removes reading/mutation of URL query params and row click navigation from two existing team-overview components (rows now static).

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

Suggested labels

large

Suggested reviewers

  • sweetrdev
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 inconclusive)

Check name Status Explanation Resolution
Title check ❓ Inconclusive The title 'feat: dora table' is vague and generic, using non-descriptive language that does not clearly convey the main change (adding a team overview table for DORA metrics). Consider using a more descriptive title such as 'feat: add DORA team overview table' or 'feat: add per-team DORA metrics table' to better communicate the primary change.
✅ Passed checks (4 passed)
Check name Status Explanation
Description check ✅ Passed The description provides comprehensive context about the PR, including backend implementation details, test coverage, frontend components, and known issues.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/dora-team-table

Warning

Review ran into problems

🔥 Problems

Git: Failed to clone repository. Please run the @coderabbitai full review command to re-trigger a full review. If the issue persists, set path_filters to include or exclude specific files.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Comment thread apps/api/src/app/metrics/resolvers/dora-metrics.schema.ts
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@apps/api/src/app/metrics/services/dora-metrics.integration.test.ts`:
- Around line 3850-3900: The test and service incorrectly compute
changeFailureRate by counting incidents (which can exceed deployments) resulting
in >100% (see test using getDoraTeamOverview and asserting changeFailureRate),
so update the test expectation to assert 100 instead of 200 and modify the
aggregation logic in getDoraTeamOverview (or the helper that computes CFR) to
count distinct failed deployment IDs (i.e., count unique deploymentId of
deployments that had any incident) divided by total deployments and clamp the
result to 0–100 before converting to percentage; keep MTTR (meanTimeToRecoverMs)
logic unchanged and still derive durations from resolved incidents
(seedIncident/resolvedAt).

In
`@apps/web/src/app/metrics-and-insights/dora/components/table-team-overview/table-team-overview.tsx`:
- Around line 137-140: The table row (<Table.Tr>) is only clickable via mouse,
so make it keyboard-accessible by adding focusability and keyboard activation:
give the row a tabIndex={0} and role="button" (or appropriate role), add an
onKeyDown handler that calls selectTeam(row.teamId) when Enter or Space is
pressed, and ensure any aria-label or aria-describedby uses the team identifier
for clarity; update references in the component where Table.Tr and selectTeam
are defined/used to include these attributes and handler.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: ef38bd3a-d4ea-4f24-808c-dd03c11081a9

📥 Commits

Reviewing files that changed from the base of the PR and between d534500 and ce1f0d3.

📒 Files selected for processing (14)
  • apps/api/src/app/metrics/resolvers/dora-metrics.schema.ts
  • apps/api/src/app/metrics/resolvers/queries/dora-metrics.query.ts
  • apps/api/src/app/metrics/services/dora-metrics.integration.test.ts
  • apps/api/src/app/metrics/services/dora-metrics.service.ts
  • apps/api/src/app/metrics/services/dora-metrics.types.ts
  • apps/web/src/api/dora-metrics.api.ts
  • apps/web/src/app/metrics-and-insights/dora/components/table-team-overview/index.ts
  • apps/web/src/app/metrics-and-insights/dora/components/table-team-overview/table-team-overview.tsx
  • apps/web/src/app/metrics-and-insights/dora/page.tsx
  • apps/web/src/app/metrics-and-insights/dora/useDoraMetrics.tsx
  • apps/web/src/sandbox/handlers/dora-metrics.ts
  • packages/graphql-types/api.ts
  • packages/graphql-types/frontend/gql.ts
  • packages/graphql-types/frontend/graphql.ts

Comment thread apps/api/src/app/metrics/services/dora-metrics.integration.test.ts
Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No issues found across 14 files

Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1 issue found across 4 files (changes from recent commits).

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="apps/web/src/app/metrics-and-insights/pr-flow/components/table-team-overview/table-team-overview.tsx">

<violation number="1" location="apps/web/src/app/metrics-and-insights/pr-flow/components/table-team-overview/table-team-overview.tsx:154">
P2: This change removes team-row click behavior, so users can no longer click a team to set the team filter from the overview table.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

@waltergalvao
Copy link
Copy Markdown
Contributor Author

@coderabbitai review

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 23, 2026

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

coderabbitai[bot]
coderabbitai Bot previously requested changes Apr 23, 2026
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In
`@apps/web/src/app/metrics-and-insights/dora/components/table-team-overview/table-team-overview.tsx`:
- Line 88: The CFR cell currently uses `${row.changeFailureRate}%` which shows
inconsistent decimal places; update the value assigned to `cfr` in the
`TableTeamOverview` rendering logic (the expression using `hasDeploys` and
`row.changeFailureRate`) to format the numeric value to a fixed precision (e.g.,
one decimal) and append '%' (e.g., convert to Number/parseFloat, guard null/NaN,
then call toFixed(1) + '%') so all rows show a consistent "Failure Rate" format.
- Around line 58-71: The comparator for "leadTimeMs" and "meanTimeToRecoverMs"
treats missing values as -1 which causes null rows to sort to the top when
sortDirection === "asc"; update the comparator logic in the table's sort
function (the switch handling "leadTimeMs" and "meanTimeToRecoverMs", using the
dir variable) to explicitly detect missing/null values and push them to the
bottom regardless of sort direction — e.g., if a value is null/undefined treat
it as greater than any real value by returning 1 when a is missing and -1 when b
is missing (and return 0 if both missing), then only apply dir * numeric
difference for two real values.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 12628d0d-3f65-4fd7-92ab-5f431ea4ba28

📥 Commits

Reviewing files that changed from the base of the PR and between ce1f0d3 and 816b478.

📒 Files selected for processing (6)
  • apps/api/src/app/metrics/resolvers/dora-metrics.schema.ts
  • apps/api/src/app/metrics/services/dora-metrics.integration.test.ts
  • apps/api/src/app/metrics/services/dora-metrics.service.ts
  • apps/web/src/app/metrics-and-insights/code-review-efficiency/components/table-team-overview/table-team-overview.tsx
  • apps/web/src/app/metrics-and-insights/dora/components/table-team-overview/table-team-overview.tsx
  • apps/web/src/app/metrics-and-insights/pr-flow/components/table-team-overview/table-team-overview.tsx
🚧 Files skipped from review as they are similar to previous changes (2)
  • apps/api/src/app/metrics/resolvers/dora-metrics.schema.ts
  • apps/api/src/app/metrics/services/dora-metrics.service.ts

Comment on lines +58 to +71
case "leadTimeMs": {
const av = a.leadTimeMs != null ? Number(a.leadTimeMs) : -1;
const bv = b.leadTimeMs != null ? Number(b.leadTimeMs) : -1;
return dir * (av - bv);
}
case "changeFailureRate":
return dir * (a.changeFailureRate - b.changeFailureRate);
case "meanTimeToRecoverMs": {
const av =
a.meanTimeToRecoverMs != null ? Number(a.meanTimeToRecoverMs) : -1;
const bv =
b.meanTimeToRecoverMs != null ? Number(b.meanTimeToRecoverMs) : -1;
return dir * (av - bv);
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Null rows sort to the top under ascending sort.

Using -1 as the sentinel for missing leadTimeMs/meanTimeToRecoverMs means any team without data sorts before every team with data when sortDirection === "asc" (since -1 is less than any real duration). Users sorting "fastest lead time first" will see empty rows at the top, which is the opposite of what they'd expect.

Consider pushing nulls to the bottom regardless of direction (standard spreadsheet-style behavior):

♻️ Proposed fix
         case "leadTimeMs": {
-          const av = a.leadTimeMs != null ? Number(a.leadTimeMs) : -1;
-          const bv = b.leadTimeMs != null ? Number(b.leadTimeMs) : -1;
-          return dir * (av - bv);
+          const av = a.leadTimeMs != null ? Number(a.leadTimeMs) : null;
+          const bv = b.leadTimeMs != null ? Number(b.leadTimeMs) : null;
+          if (av == null && bv == null) return 0;
+          if (av == null) return 1; // nulls always last
+          if (bv == null) return -1;
+          return dir * (av - bv);
         }
         case "changeFailureRate":
           return dir * (a.changeFailureRate - b.changeFailureRate);
         case "meanTimeToRecoverMs": {
-          const av =
-            a.meanTimeToRecoverMs != null ? Number(a.meanTimeToRecoverMs) : -1;
-          const bv =
-            b.meanTimeToRecoverMs != null ? Number(b.meanTimeToRecoverMs) : -1;
-          return dir * (av - bv);
+          const av =
+            a.meanTimeToRecoverMs != null ? Number(a.meanTimeToRecoverMs) : null;
+          const bv =
+            b.meanTimeToRecoverMs != null ? Number(b.meanTimeToRecoverMs) : null;
+          if (av == null && bv == null) return 0;
+          if (av == null) return 1;
+          if (bv == null) return -1;
+          return dir * (av - bv);
         }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@apps/web/src/app/metrics-and-insights/dora/components/table-team-overview/table-team-overview.tsx`
around lines 58 - 71, The comparator for "leadTimeMs" and "meanTimeToRecoverMs"
treats missing values as -1 which causes null rows to sort to the top when
sortDirection === "asc"; update the comparator logic in the table's sort
function (the switch handling "leadTimeMs" and "meanTimeToRecoverMs", using the
dir variable) to explicitly detect missing/null values and push them to the
bottom regardless of sort direction — e.g., if a value is null/undefined treat
it as greater than any real value by returning 1 when a is missing and -1 when b
is missing (and return 0 if both missing), then only apply dir * numeric
difference for two real values.

hasDeploys && row.leadTimeMs != null
? getAbbreviatedDuration(Number(row.leadTimeMs))
: "–",
cfr: hasDeploys ? `${row.changeFailureRate}%` : "–",
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Inconsistent CFR display precision.

${row.changeFailureRate}% will render raw values returned by SQL ROUND(..., 2), producing a mix of "50%", "33.33%", and "16.67%" across rows. Normalize to a fixed precision (e.g. 1 decimal) so the column aligns visually and the "Failure Rate" reads consistently.

♻️ Proposed fix
-      cfr: hasDeploys ? `${row.changeFailureRate}%` : "–",
+      cfr: hasDeploys ? `${row.changeFailureRate.toFixed(1)}%` : "–",
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
cfr: hasDeploys ? `${row.changeFailureRate}%` : "–",
cfr: hasDeploys ? `${row.changeFailureRate.toFixed(1)}%` : "–",
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@apps/web/src/app/metrics-and-insights/dora/components/table-team-overview/table-team-overview.tsx`
at line 88, The CFR cell currently uses `${row.changeFailureRate}%` which shows
inconsistent decimal places; update the value assigned to `cfr` in the
`TableTeamOverview` rendering logic (the expression using `hasDeploys` and
`row.changeFailureRate`) to format the numeric value to a fixed precision (e.g.,
one decimal) and append '%' (e.g., convert to Number/parseFloat, guard null/NaN,
then call toFixed(1) + '%') so all rows show a consistent "Failure Rate" format.

Copy link
Copy Markdown
Contributor

@sweetrdev sweetrdev left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good

@waltergalvao waltergalvao merged commit 3a940d1 into main Apr 23, 2026
10 checks passed
@waltergalvao waltergalvao deleted the feat/dora-team-table branch April 23, 2026 17:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants