10000 fix: Add Trends Line graph on Deployment events page by harshit078 · Pull Request #652 · middlewarehq/middleware · GitHub
[go: up one dir, main page]

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 3 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 a new React component DoraMetricsDuration to display the longest and shortest deployments from a list, with robust date formatting and deployment detail cards.
web-server/src/content/DoraMetrics/DoraMetricsTrend.tsx Added a new React component DoraMetricsTrend and supporting functions to visualize deployment trends, compute averages and changes, and render a dual-axis bar chart with trend indicators.
web-server/src/content/PullRequests/DeploymentInsightsOverlay.tsx Refactored to introduce a tabbed interface with "Deployment Analytics" and "Deployment Events" tabs. Integrated the new metrics components into the analytics tab and reorganized the deployment event list into the 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

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.

Tip

⚡️ Faster reviews with caching
  • CodeRabbit now supports caching for code and dependencies, helping speed up reviews. This means quicker feedback, reduced wait times, and a smoother review experience overall. Cached data is encrypted and stored securely. This feature will be automatically enabled for all accounts on May 16th. To opt out, configure Review - Disable Cache at either the organization or repository level. If you prefer to disable all data retention across your organization, simply turn off the Data Retention setting under your Organization Settings.

Enjoy the performance boost—your workflow just got faster.

✨ 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 8000 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
+                      }

8000
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)

Comment on lines +253 to +255
const maxDuration = Math.max(...durations);
const yAxisMax = Math.ceil(maxDuration);

Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Guard against empty data when computing Math.max

When there are no deployments durations is an empty array and Math.max(...durations) returns -Infinity, breaking the y-axis.

-const maxDuration = Math.max(...durations);
-const yAxisMax = Math.ceil(maxDuration);
+const maxDuration =
+  durations.length > 0 ? Math.max(...durations) : 0;
+const yAxisMax = Math.ceil(maxDuration);
📝 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
const maxDuration = Math.max(...durations);
const yAxisMax = Math.ceil(maxDuration);
const maxDuration =
durations.length > 0 ? Math.max(...durations) : 0;
const yAxisMax = Math.ceil(maxDuration);

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.

1 participant
0