Skip to content

fix: Add Trends Line graph on Deployment events page #652

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 9 commits into
base: main
Choose a base branch
from

Conversation

harshit078
Copy link

@harshit078 harshit078 commented May 6, 2025

Linked Issue(s)

#544

Acceptance Criteria fulfillment

  • Divided the existing page into 2 tabs
  • Added deployment Durations
  • Added deployment trends
  • Added deployment Graph

Proposed changes

  • Added tabs support for deployment events and deployment analytics
  • Added deployment duration which calculates Longest and shortest deployment
  • Added Deployment trends which calculates the avg trend

Further comments

Screenshot 2025-05-13 at 6 52 46 PM Screenshot 2025-05-13 at 6 53 28 PM

Summary by CodeRabbit

  • New Features

    • Introduced a tabbed interface in the deployment insights overlay, separating "Deployment Analytics" and "Deployment Events" into distinct views.
    • Added a new analytics dashboard displaying deployment counts, success/failure rates, and visualizations of the longest and shortest deployment durations.
    • Enhanced deployment event details with improved filtering and grouping options.
  • UI Improvements

    • Streamlined navigation between analytics and event details for a clearer and more organized user experience.

Summary by CodeRabbit

  • New Features

    • Introduced a tabbed interface for deployment insights, allowing users to switch between "Deployment Analytics" and "Deployment Events" views.
    • Added visualizations for deployment duration metrics, highlighting the longest and shortest deployments.
    • Implemented deployment trend analysis with charts and trend indicators for deployment duration and pull request counts.
  • Refactor

    • Reorganized deployment analytics and event details into separate tabs for a clearer, more focused user experience.

Copy link

coderabbitai bot commented May 6, 2025

Walkthrough

Two new React components, DoraMetricsDuration and DoraMetricsTrend, are introduced to visualize deployment durations and trends. The DeploymentInsightsOverlay component is refactored to use a tabbed interface, separating analytics (with the new metrics components) from deployment event details. Supporting utility functions and UI elements are included.

Changes

File(s) Change Summary
web-server/src/content/DoraMetrics/DoraMetricsDuration.tsx Added DoraMetricsDuration component displaying longest and shortest deployments with detailed cards and robust date formatting.
web-server/src/content/DoraMetrics/DoraMetricsTrend.tsx Added DoraMetricsTrend component and helper functions to analyze deployment trends, calculate averages and percentage changes, and render a dual-axis bar chart with trend indicators.
web-server/src/content/PullRequests/DeploymentInsightsOverlay.tsx Refactored DeploymentInsightsOverlay to add tabbed interface ("Deployment Analytics" and "Deployment Events"), integrating new metrics components in analytics tab and moving deployment event list and filters to events tab.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant DeploymentInsightsOverlay
    participant DoraMetricsDuration
    participant DoraMetricsTrend

    User->>DeploymentInsightsOverlay: Open overlay
    DeploymentInsightsOverlay->>User: Show tabs (Analytics, Events)
    User->>DeploymentInsightsOverlay: Select "Deployment Analytics" tab
    DeploymentInsightsOverlay->>DoraMetricsDuration: Render with deployments
    DeploymentInsightsOverlay->>DoraMetricsTrend: Render with deployments
    DoraMetricsDuration-->>DeploymentInsightsOverlay: Display duration cards
    DoraMetricsTrend-->>DeploymentInsightsOverlay: Display trend chart
Loading

Suggested reviewers

  • jayantbh

Poem

🐇
In the warren, metrics bloom anew,
With tabs that split the work in two.
Longest, shortest, trends revealed—
Deployments’ secrets, now unsealed!
Charts and cards in colors bright,
Analytics and events—what a sight!
Rabbits cheer for code done right.

✨ Finishing Touches
  • 📝 Generate Docstrings

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
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link

@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

🧹 Nitpick comments (3)
web-server/src/content/PullRequests/DeploymentInsightsOverlay.tsx (2)

1-5: Remove unused icon imports to avoid lint-failures

CodeRounded and AccessTimeRounded are imported but never referenced in this file, which will be flagged by the build/linter and bloats bundle size.

-import { ArrowDownwardRounded, CodeRounded, AccessTimeRounded } from '@mui/icons-material';
+import { ArrowDownwardRounded } from '@mui/icons-material';

225-233: Replace redundant Boolean(deps.length) with truthy test

The explicit cast is unnecessary; deps.length is already coerced to true / false.
This also satisfies the Biome warning reported in the static-analysis hints.

-              {Boolean(deps.length) && (
+              {deps.length > 0 && (
web-server/src/content/DoraMetrics/DoraMetricsDuration.tsx (1)

133-141: Redundant boolean cast

Same as in the overlay file—Boolean(d.conducted_at) can be replaced by truthiness testing:

-      .filter((d): d is Deployment => Boolean(d.conducted_at))
+      .filter((d): d is Deployment => !!d.conducted_at)
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 055bb47 and 2547521.

📒 Files selected for processing (2)
  • web-server/src/content/DoraMetrics/DoraMetricsDuration.tsx (1 hunks)
  • web-server/src/content/PullRequests/DeploymentInsightsOverlay.tsx (6 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (2)
web-server/src/content/DoraMetrics/DoraMetricsDuration.tsx (1)
web-server/src/types/resources.ts (1)
  • Deployment (216-228)
web-server/src/content/PullRequests/DeploymentInsightsOverlay.tsx (4)
web-server/src/hooks/useStateTeamConfig.tsx (2)
  • useSingleTeamConfig (130-154)
  • useBranchesForPrFilters (163-174)
cli/source/store/index.ts (1)
  • useDispatch (30-30)
web-server/src/content/DoraMetrics/DoraMetricsDuration.tsx (1)
  • DoraMetricsDuration (126-180)
web-server/src/components/PRTableMini/PullRequestsTableMini.tsx (1)
  • PullRequestsTableMini (42-378)
🪛 Biome (1.9.4)
web-server/src/content/PullRequests/DeploymentInsightsOverlay.tsx

[error] 310-310: Avoid redundant Boolean call

It is not necessary to use Boolean call when a value will already be coerced to a boolean.
Unsafe fix: Remove redundant Boolean call

(lint/complexity/noExtraBooleanCast)

🔇 Additional comments (1)
web-server/src/content/PullRequests/DeploymentInsightsOverlay.tsx (1)

334-350: Guard against divide-by-zero in success-rate computation

percent(successfulDeps.length, deployments.length) will throw if deployments.length is 0.
Although the surrounding conditional currently prevents an empty list from being rendered, an early return or a defensive check here protects against future refactors.

-                      perc={percent(
-                        successfulDeps.length,
-                        deployments.length
-                      )}
+                      perc={
+                        deployments.length
+                          ? percent(successfulDeps.length, deployments.length)
+                          : 0
+                      }

Comment on lines +63 to +70
const DeploymentCard: FC<DeploymentCardProps> = ({ deployment }) => {
const theme = useTheme();

const handleDeploymentClick = () => {
if (deployment.html_url) {
window.open(deployment.html_url, '_blank', 'noopener,noreferrer');
}
};
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

DeploymentCard crashes when deployment is null

longestDeployment / shortestDeployment can be null, yet the prop is typed as non-nullable.
This causes a TypeScript error and a potential runtime exception when there are no valid deployments.

-interface DeploymentCardProps {
-  deployment: DeploymentWithValidDuration;
+interface DeploymentCardProps {
+  deployment?: DeploymentWithValidDuration | null;

Add an early return inside the component:

-  const theme = useTheme();
+  const theme = useTheme();
+  if (!deployment) {
+    return (
+      <Card elevation={0} sx={{ p: 1.6, flex: 1, textAlign: 'center' }}>
+        <Line white>No data</Line>
+      </Card>
+    );
+  }

And adjust the caller:

-<DeploymentCard deployment={longestDeployment} type="Longest" />
+<DeploymentCard deployment={longestDeployment} type="Longest" />

Copy link

@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: 1

♻️ Duplicate comments (1)
web-server/src/content/DoraMetrics/DoraMetricsDuration.tsx (1)

147-161: ⚠️ Potential issue

DeploymentCard is still called with a possible null value

longestDeployment / shortestDeployment can be null (see the useMemo above) yet the prop is typed as non-nullable and the component never checks for it.
This reproduces the compile/runtime issue flagged in the previous review and will crash or fail the type-check as soon as a repo has no valid deployments.

Suggested fix (same as before):

-interface DeploymentCardProps {
-  deployment: Deployment;
+interface DeploymentCardProps {
+  deployment?: Deployment | null;
   type: DeploymentCardType;
 }
 …
-const DeploymentCard: FC<DeploymentCardProps> = ({ deployment }) => {
+const DeploymentCard: FC<DeploymentCardProps> = ({ deployment }) => {
+  if (!deployment) {
+    return (
+      <Card elevation={0} sx={{ p: 1.6, flex: 1, textAlign: 'center' }}>
+        <Line white>No data</Line>
+      </Card>
+    );
+  }
   const theme = useTheme();

and render the card only when data is present:

-{/* Longest  */}
-<DeploymentCard deployment={longestDeployment} type="Longest" />
+{longestDeployment && (
+  <DeploymentCard deployment={longestDeployment} type="Longest" />
+)}

-{/* Shortest */}
-<DeploymentCard deployment={shortestDeployment} type="Shortest" />
+{shortestDeployment && (
+  <DeploymentCard deployment={shortestDeployment} type="Shortest" />
+)}
🧹 Nitpick comments (7)
web-server/src/content/DoraMetrics/DoraMetricsDuration.tsx (3)

124-126: Redundant Boolean() cast

Boolean(...) is unnecessary—JavaScript already coerces the expression to a boolean in the filter callback.
Removing it also satisfies the Biome warning.

-.filter((d): d is Deployment => Boolean(d.conducted_at && typeof d.run_duration === 'number'))
+.filter(
+  (d): d is Deployment =>
+    d.conducted_at && typeof d.run_duration === 'number'
+)

13-16: Unused type prop

type is declared in DeploymentCardProps and passed by the parent but is never read inside DeploymentCard.
Drop the prop (and its derivations) or surface it in the UI to avoid dead code.


91-97: Minor grammar – plural apostrophe

new PR's should be new PRs (no apostrophe) to indicate plural, not possession.

-  {deployment.pr_count || 0} new PR's
+  {deployment.pr_count || 0} new PRs
web-server/src/content/PullRequests/DeploymentInsightsOverlay.tsx (1)

56-61: Prefer strongly-typed state for tab key

useState<string>(TabKeys.EVENTS) weakens type-safety. Constrain the state to the TabKeys enum so accidental strings are impossible.

-const [activeTab, setActiveTab] = useState<string>(TabKeys.EVENTS);
+const [activeTab, setActiveTab] = useState<TabKeys>(TabKeys.EVENTS);-const handleTabSelect = (item: TabItem) => setActiveTab(item.key as string);
+const handleTabSelect = (item: TabItem) =>
+  setActiveTab(item.key as TabKeys);
web-server/src/content/DoraMetrics/DoraMetricsTrend.tsx (3)

70-74: Remove stray console.log

Left-over debugging statement leaks to the browser console and can expose data in production.

-  console.log(deployments)

15-16: Threshold is probably too low

MEANINGFUL_CHANGE_THRESHOLD = 0.5 is compared against a percentage (e.g., 20, -3.4).
0.5 therefore means “ignore < 0.5 % change”, which is almost noise-level.
Consider raising this to something like 5 or 10 % or make it configurable.


149-155: value prop is unused

DeploymentTrendPill accepts a value (and optional valueFormat) but never uses it, which confuses callers and bloats render cycles.

Either:

  1. Display the value in the pill, or
  2. Remove the prop from the interface and the call-sites.
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between d7168a1 and 9c9b074.

📒 Files selected for processing (3)
  • web-server/src/content/DoraMetrics/DoraMetricsDuration.tsx (1 hunks)
  • web-server/src/content/DoraMetrics/DoraMetricsTrend.tsx (1 hunks)
  • web-server/src/content/PullRequests/DeploymentInsightsOverlay.tsx (5 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (1)
web-server/src/content/DoraMetrics/DoraMetricsDuration.tsx (1)
web-server/src/types/resources.ts (1)
  • Deployment (216-228)
🪛 Biome (1.9.4)
web-server/src/content/PullRequests/DeploymentInsightsOverlay.tsx

[error] 308-308: Avoid redundant Boolean call

It is not necessary to use Boolean call when a value will already be coerced to a boolean.
Unsafe fix: Remove redundant Boolean call

(lint/complexity/noExtraBooleanCast)

Copy link

@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: 0

🧹 Nitpick comments (7)
web-server/src/content/PullRequests/DeploymentInsightsOverlay.tsx (7)

56-62: Consider defaulting to the Analytics tab.

Since the PR introduces new analytics features as a major enhancement, it might make more sense to default to the ANALYTICS tab instead of EVENTS to highlight the new functionality for users.

-  const [activeTab, setActiveTab] = useState<string>(TabKeys.EVENTS);
+  const [activeTab, setActiveTab] = useState<string>(TabKeys.ANALYTICS);

293-293: Fix spacing in style object.

Minor formatting issue with the spacing in the style object.

-                <Box sx={{mb:'10px'}} key={selectedRepo.value}>
+                <Box sx={{ mb: '10px' }} key={selectedRepo.value}>

308-308: Remove redundant Boolean call.

The Boolean wrapper is unnecessary as the expression will already be coerced to a boolean in this context.

-                      {Boolean(failedDeps.length) ? (
+                      {failedDeps.length ? (
🧰 Tools
🪛 Biome (1.9.4)

[error] 308-308: Avoid redundant Boolean call

It is not necessary to use Boolean call when a value will already be coerced to a boolean.
Unsafe fix: Remove redundant Boolean call

(lint/complexity/noExtraBooleanCast)


351-355: Consider adding descriptions for analytics components.

The DoraMetricsDuration and DoraMetricsTrend components are added without any surrounding context or descriptions for users. Consider adding brief explanatory text to help users understand what these visualizations represent.

                <FlexBox>
+                  <Line white medium sx={{ mb: 1 }}>Deployment Duration Analysis</Line>
                  <DoraMetricsDuration deployments={deployments} />
                </FlexBox>
                <FlexBox></FlexBox>
+                <Line white medium sx={{ mb: 1 }}>Deployment Trend Analysis</Line>
                <DoraMetricsTrend />

354-354: Remove empty FlexBox.

There's an empty FlexBox that doesn't serve any purpose and should be removed.

                <FlexBox>
                  <DoraMetricsDuration deployments={deployments} />
                </FlexBox>
-                <FlexBox></FlexBox>
                <DoraMetricsTrend />

290-473: Consider extracting tab content into separate components.

The component is quite large and handles multiple concerns. Consider extracting the Analytics tab and Events tab content into separate components to improve readability and maintainability.

For example:

  • Create a DeploymentAnalyticsTab component
  • Create a DeploymentEventsTab component

This refactoring would make the main component more focused on managing the tab state and layout.

🧰 Tools
🪛 Biome (1.9.4)

[error] 308-308: Avoid redundant Boolean call

It is not necessary to use Boolean call when a value will already be coerced to a boolean.
Unsafe fix: Remove redundant Boolean call

(lint/complexity/noExtraBooleanCast)


349-350: Maintain consistent indentation.

The indentation in the analytics tab doesn't appear to be consistently applied, particularly for the closing tag of FlexBox.

                    />
                  </FlexBox>
-                </Box>
+              </Box>
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
Cache: Disabled due to data retention organization setting
Knowledge Base: Disabled due to data retention organization setting

📥 Commits

Reviewing files that changed from the base of the PR and between 9c9b074 and 9cdb98f.

📒 Files selected for processing (2)
  • web-server/src/content/DoraMetrics/DoraMetricsTrend.tsx (1 hunks)
  • web-server/src/content/PullRequests/DeploymentInsightsOverlay.tsx (5 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • web-server/src/content/DoraMetrics/DoraMetricsTrend.tsx
🧰 Additional context used
🪛 Biome (1.9.4)
web-server/src/content/PullRequests/DeploymentInsightsOverlay.tsx

[error] 308-308: Avoid redundant Boolean call

It is not necessary to use Boolean call when a value will already be coerced to a boolean.
Unsafe fix: Remove redundant Boolean call

(lint/complexity/noExtraBooleanCast)

🔇 Additional comments (3)
web-server/src/content/PullRequests/DeploymentInsightsOverlay.tsx (3)

5-7: Good addition of new imports for tab functionality and analytics components.

The imports for useState and the new DORA metrics components (DoraMetricsTrend and DoraMetricsDuration) are correctly added to support the new tabbed interface and analytics features.


45-48: Good use of enum for tab identification.

Using an enum for tab keys is a clean approach that prevents magic strings and makes the code more maintainable.


285-289: Clean implementation of the Tabs component.

The Tabs component is well integrated with appropriate props for items, selection handling, and active tab checking.

Copy link
Contributor

@jayantbh jayantbh left a comment

Choose a reason for hiding this comment

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

image

  1. Remove white borders from bars
  2. Legends dark text should be brighter and same color as the legends. (you do have access to the source visual no?)
  3. Format the duration instead of just being in hours. Try getDurationString. It's in the webserver codebase.

Additionally, lint issues.
Please run the linter before you push. Or, you could help us by updating the configuration to run it as part of the precommit hook.

@jayantbh
Copy link
Contributor

The code is largely fine tbh. Good job.

@jayantbh
Copy link
Contributor

@harshit078 please update your screenshots after visual changes.

@harshit078
Copy link
Author

@jayantbh sure, I'll add the screen recording along with screenshots by today !

@harshit078
Copy link
Author

Screenshot 2025-05-30 at 12 03 46 PM

Copy link

@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: 0

🧹 Nitpick comments (4)
web-server/src/content/PullRequests/DeploymentInsightsOverlay.tsx (4)

48-51: TabKeys enum & state initialization
The TabKeys enum and the initialization of activeTab with its corresponding tabItems correctly model the two views. For stronger type safety, consider defining the state as useState<TabKeys>(TabKeys.EVENTS) instead of string to eliminate the need for casting in handleTabSelect.

Also applies to: 59-64


361-364: Remove unnecessary empty FlexBox
There’s an unused <FlexBox></FlexBox> wrapper immediately before DoraMetricsTrend. It doesn’t affect layout and can be removed to keep the markup clean.


315-324: Avoid redundant Boolean casts on .length checks
Rather than {Boolean(failedDeps.length) ? …}, you can simplify to {failedDeps.length > 0 ? …} and similarly for the pass branch. This removes extra function calls and improves readability.

Also applies to: 327-335

🧰 Tools
🪛 Biome (1.9.4)

[error] 315-315: Avoid redundant Boolean call

It is not necessary to use Boolean call when a value will already be coerced to a boolean.
Unsafe fix: Remove redundant Boolean call

(lint/complexity/noExtraBooleanCast)


297-378: Analytics tab: layout refinements
The analytics pane correctly presents deployment counts, the progress bar, and conditionally renders metrics or a settings link. A couple of optional tweaks:

  1. Use ROUTES.TEAMS.PATH instead of ROUTES.TEAMS.ROUTE.PATH for brevity.
  2. Add a brief comment on key={selectedRepo.value} for the <Box> to explain the remount-on-repo-change hack.
🧰 Tools
🪛 Biome (1.9.4)

[error] 315-315: Avoid redundant Boolean call

It is not necessary to use Boolean call when a value will already be coerced to a boolean.
Unsafe fix: Remove redundant Boolean call

(lint/complexity/noExtraBooleanCast)

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f9e85d2 and 208faed.

📒 Files selected for processing (1)
  • web-server/src/content/PullRequests/DeploymentInsightsOverlay.tsx (7 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (1)
web-server/src/content/PullRequests/DeploymentInsightsOverlay.tsx (6)
web-server/src/hooks/useStateTeamConfig.tsx (2)
  • useSingleTeamConfig (130-154)
  • useBranchesForPrFilters (163-174)
cli/source/store/index.ts (1)
  • useDispatch (30-30)
web-server/src/content/DoraMetrics/DoraMetricsDuration.tsx (1)
  • DoraMetricsDuration (118-165)
web-server/src/content/DoraMetrics/DoraMetricsTrend.tsx (1)
  • DoraMetricsTrend (243-456)
web-server/src/constants/routes.ts (1)
  • ROUTES (58-73)
web-server/src/components/PRTableMini/PullRequestsTableMini.tsx (1)
  • PullRequestsTableMini (42-378)
🪛 Biome (1.9.4)
web-server/src/content/PullRequests/DeploymentInsightsOverlay.tsx

[error] 315-315: Avoid redundant Boolean call

It is not necessary to use Boolean call when a value will already be coerced to a boolean.
Unsafe fix: Remove redundant Boolean call

(lint/complexity/noExtraBooleanCast)

🔇 Additional comments (5)
web-server/src/content/PullRequests/DeploymentInsightsOverlay.tsx (5)

5-7: Clean introduction of new imports
The new imports for React hooks (FC, useCallback, useEffect, useMemo, useState), DoraMetricsTrend, DoraMetricsDuration, Tabs, Link, ROUTES, and DeploymentSources are all used in this component and correctly referenced.

Also applies to: 14-14, 34-36


229-232: Selected repo styling is applied correctly
The conditional border and fontWeight props on each repo card clearly highlight the selected repo. This dynamic styling is implemented as intended.

Also applies to: 244-246


201-203: Determine PR_MERGE deployment source
Adding currentBaseRepo and isPRMergeSource to gate display of analytics is appropriate. Please verify that the deployment_type property on your repo objects always matches the DeploymentSources enum values (e.g., PR_MERGE).


292-296: Tabs component integration
The Tabs component is correctly wired with items, onSelect, and checkSelected. Users will be able to switch between "Deployment Analytics" and "Deployment Events" seamlessly.


379-380: Events tab content preserved under tabs
The deployment events UI is now properly nested under the "Deployment Events" tab and all existing functionality (filters, grouping, PR details) remains intact.

Copy link

@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: 1

🧹 Nitpick comments (3)
web-server/src/content/PullRequests/DeploymentInsightsOverlay.tsx (3)

319-319: Remove redundant Boolean call.

The Boolean() call is unnecessary since failedDeps.length already evaluates to a truthy/falsy value in this context.

-                      {Boolean(failedDeps.length) ? (
+                      {failedDeps.length ? (
🧰 Tools
🪛 Biome (1.9.4)

[error] 319-319: Avoid redundant Boolean call

It is not necessary to use Boolean call when a value will already be coerced to a boolean.
Unsafe fix: Remove redundant Boolean call

(lint/complexity/noExtraBooleanCast)


359-367: Consider adding deployment trends even for PR_MERGE sources.

The conditional rendering logic is correct, but consider if there are alternative metrics that could be shown for PR_MERGE sources instead of completely hiding the analytics.

The current implementation appropriately hides deployment trends for PR_MERGE sources, but you might consider showing alternative analytics or a more informative message about what metrics are available for this deployment type.


364-364: Remove empty FlexBox element.

This empty FlexBox serves no purpose and should be removed for cleaner code.

-                    <FlexBox></FlexBox>
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 208faed and 1f84876.

📒 Files selected for processing (2)
  • web-server/src/content/DoraMetrics/DoraMetricsDuration.tsx (1 hunks)
  • web-server/src/content/PullRequests/DeploymentInsightsOverlay.tsx (5 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • web-server/src/content/DoraMetrics/DoraMetricsDuration.tsx
🧰 Additional context used
🪛 Biome (1.9.4)
web-server/src/content/PullRequests/DeploymentInsightsOverlay.tsx

[error] 319-319: Avoid redundant Boolean call

It is not necessary to use Boolean call when a value will already be coerced to a boolean.
Unsafe fix: Remove redundant Boolean call

(lint/complexity/noExtraBooleanCast)

🔇 Additional comments (7)
web-server/src/content/PullRequests/DeploymentInsightsOverlay.tsx (7)

3-3: LGTM! Clean import organization for new tabbed functionality.

The new imports are well-organized and properly support the tabbed interface refactoring. All imported components and utilities are used appropriately throughout the component.

Also applies to: 14-14, 16-16, 33-33, 39-40


50-54: Well-structured tab key enumeration.

The TabKeys enum provides a clean and maintainable way to manage tab identifiers, following good TypeScript practices.


61-66: Solid tab state management implementation.

The tab state initialization and handling logic is clean and follows React best practices. The tab items configuration and selection handler are properly structured.


203-208: Good conditional logic for deployment source detection.

The logic to detect PR_MERGE deployment sources is well-implemented and serves the important purpose of conditionally showing deployment trends based on the repository's configuration.


296-300: Clean tab component integration.

The Tabs component integration is properly implemented with appropriate props and selection handling.


368-386: Well-crafted user guidance for unsupported deployment sources.

The informational message and link to settings provides clear guidance to users about why deployment trends aren't available and how to potentially enable them.


388-503: Excellent preservation of existing events functionality.

The events tab maintains all the existing deployment filtering, grouping, and selection functionality while being properly integrated into the new tabbed interface. The layout and user experience are preserved.

Copy link

@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: 1

♻️ Duplicate comments (1)
web-server/src/content/DoraMetrics/DoraMetricsTrend.tsx (1)

338-340: Guard against empty data when computing Math.max (addressing previous review).

This matches the exact issue flagged in the past review comment. When durations is an empty array, Math.max(...durations) returns -Infinity, which would break the y-axis.

The previous review comment is still valid and should be addressed:

-const maxDuration = Math.max(...durations);
-const yAxisMax = Math.ceil(maxDuration);
+const maxDuration =
+  durations.length > 0 ? Math.max(...durations) : 0;
+const yAxisMax = Math.ceil(maxDuration);
🧹 Nitpick comments (4)
web-server/src/content/DoraMetrics/DoraMetricsTrend.tsx (4)

120-120: Remove console.log statement.

Console.log statements should not be left in production code.

-    console.log('prCount', deployments[0]);

184-190: Remove unused props from component interface.

The DeploymentTrendPill component accepts value and valueFormat props but doesn't use them in the implementation.

 export const DeploymentTrendPill: FC<{
   label: string;
   change: number;
   state: 'positive' | 'negative' | 'neutral';
-  value: number;
-  valueFormat?: (val: number) => string;
-}> = ({ label, change, state }) => {
+}> = ({ label, change, state }) => {

67-77: Consider extracting duplicate validation logic.

The deployment validation logic is duplicated between calculateDeploymentTrends and the chartData useMemo. This violates DRY principles and increases maintenance burden.

Consider extracting this into a shared validation function:

+const isValidDeployment = (dep: Deployment): boolean => {
+  const hasValidDates =
+    dep.conducted_at &&
+    new Date(dep.conducted_at).toString() !== 'Invalid Date';
+
+  if (dep.id?.startsWith('WORKFLOW')) {
+    return (
+      hasValidDates &&
+      typeof dep.run_duration === 'number' &&
+      dep.run_duration >= 0
+    );
+  }
+
+  return (
+    hasValidDates &&
+    dep.created_at &&
+    new Date(dep.created_at).toString() !== 'Invalid Date'
+  );
+};

Then use this function in both places to reduce code duplication.

Also applies to: 258-276


392-450: Chart configuration complexity could benefit from extraction.

The chart options configuration is quite complex and embedded within the component. Consider extracting it to improve readability and testability.

Consider creating a separate function to generate chart options:

const createChartOptions = (theme: Theme, yAxisMax: number) => ({
  scales: {
    y: {
      type: 'linear',
      display: true,
      position: 'left',
      title: {
        display: true,
        text: 'Duration (minutes)',
        color: theme.colors.success.main
      },
      ticks: {
        color: theme.colors.success.main,
        callback: (value) => value + 'm'
      },
      max: yAxisMax,
      grid: {
        color: darken(theme.colors.success.lighter, 0.2)
      }
    },
    // ... rest of configuration
  }
});
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 1f84876 and 0ed9d1b.

📒 Files selected for processing (1)
  • web-server/src/content/DoraMetrics/DoraMetricsTrend.tsx (1 hunks)
🔇 Additional comments (1)
web-server/src/content/DoraMetrics/DoraMetricsTrend.tsx (1)

263-263: ⚠️ Potential issue

Add null check for deployment ID.

Similar to line 72, this code assumes dep.id exists without null checking.

-      if (dep.id?.startsWith('WORKFLOW')) {
+      if (dep.id?.startsWith('WORKFLOW')) {

Wait, I see this already has the optional chaining operator. This is actually correct.

Copy link

@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: 1

♻️ Duplicate comments (1)
web-server/src/content/DoraMetrics/DoraMetricsTrend.tsx (1)

72-74: ⚠️ Potential issue

Null-safety missing on dep.id – re-introduces the exact crash flagged earlier

dep.id is still accessed without an optional-chain, so undefined.startsWith will throw when deployments come from sources that omit id.
The same issue was pointed out in a previous review; please address it this time.

-    if (dep.id.startsWith('WORKFLOW')) {
+    if (dep.id?.startsWith('WORKFLOW')) {
🧹 Nitpick comments (2)
web-server/src/content/DoraMetrics/DoraMetricsTrend.tsx (2)

120-123: Left-over debug console.log

The stray console.log('prCount', deployments[0]); leaks implementation details to the browser console and needlessly clutters logs.

-    console.log('prCount', deployments[0]);

18-23: Dead field size in TrendData

size is declared but never referenced anywhere in this file. Drop it until a use-case emerges to keep the type lean.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 0ed9d1b and e90e189.

📒 Files selected for processing (1)
  • web-server/src/content/DoraMetrics/DoraMetricsTrend.tsx (1 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (1)
web-server/src/content/DoraMetrics/DoraMetricsTrend.tsx (2)
web-server/src/types/resources.ts (1)
  • Deployment (216-228)
cli/source/store/index.ts (1)
  • useSelector (28-28)

Comment on lines +184 to +203
export const DeploymentTrendPill: FC<{
label: string;
change: number;
state: 'positive' | 'negative' | 'neutral';
value: number;
valueFormat?: (val: number) => string;
}> = ({ label, change, state }) => {
const theme = useTheme();

const text =
state === 'neutral'
? label
: state === 'positive'
? 'Increasing ' + label
: 'Decreasing ' + label;

const useMultiplierFormat = Math.abs(change) > 100;
const formattedChange = useMultiplierFormat
? `${percentageToMultiplier(Math.abs(change))}`
: `${Math.abs(Math.round(change))}%`;
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

value / valueFormat props are unused – compilation will fail under noUnusedParameters

DeploymentTrendPill’s signature exposes value and valueFormat, yet neither is referenced in the body. Besides misleading API consumers, this breaks builds with stricter TS configs.

Two options:

  1. Remove the unused props:
-export const DeploymentTrendPill: FC<{
-  label: string;
-  change: number;
-  state: 'positive' | 'negative' | 'neutral';
-  value: number;
-  valueFormat?: (val: number) => string;
-}> = ({ label, change, state }) => {
+export const DeploymentTrendPill: FC<{
+  label: string;
+  change: number;
+  state: 'positive' | 'negative' | 'neutral';
+}> = ({ label, change, state }) => {
  1. Or actually surface the value:
   const formattedChange = useMultiplierFormat
     ? `${percentageToMultiplier(Math.abs(change))}`
     : `${Math.abs(Math.round(change))}%`;
 
   const color = darken(
@@
       <FlexBox color={color} alignCenter>
         <Line bold>{formattedChange}</Line>
+        {value !== undefined && (
+          <Line sx={{ ml: 0.5 }}>{valueFormat ? valueFormat(value) : value}</Line>
+        )}
         {icon}
       </FlexBox>

Choose whichever matches your UX intention.

📝 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
export const DeploymentTrendPill: FC<{
label: string;
change: number;
state: 'positive' | 'negative' | 'neutral';
value: number;
valueFormat?: (val: number) => string;
}> = ({ label, change, state }) => {
const theme = useTheme();
const text =
state === 'neutral'
? label
: state === 'positive'
? 'Increasing ' + label
: 'Decreasing ' + label;
const useMultiplierFormat = Math.abs(change) > 100;
const formattedChange = useMultiplierFormat
? `${percentageToMultiplier(Math.abs(change))}`
: `${Math.abs(Math.round(change))}%`;
export const DeploymentTrendPill: FC<{
label: string;
change: number;
state: 'positive' | 'negative' | 'neutral';
}> = ({ label, change, state }) => {
const theme = useTheme();
const text =
state === 'neutral'
? label
: state === 'positive'
? 'Increasing ' + label
: 'Decreasing ' + label;
const useMultiplierFormat = Math.abs(change) > 100;
const formattedChange = useMultiplierFormat
? `${percentageToMultiplier(Math.abs(change))}`
: `${Math.abs(Math.round(change))}%`;
🤖 Prompt for AI Agents
In web-server/src/content/DoraMetrics/DoraMetricsTrend.tsx around lines 184 to
203, the DeploymentTrendPill component declares value and valueFormat props but
does not use them, causing unused parameter errors under strict TypeScript
settings. To fix this, either remove value and valueFormat from the component's
props if they are unnecessary, or update the component to use these props in its
rendering logic, such as formatting and displaying the value using valueFormat
if provided.

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