Skip to content

feat: version check ui#527

Merged
adityachoudhari26 merged 1 commit intomainfrom
version-check-ui
Apr 30, 2025
Merged

feat: version check ui#527
adityachoudhari26 merged 1 commit intomainfrom
version-check-ui

Conversation

@adityachoudhari26
Copy link
Copy Markdown
Member

@adityachoudhari26 adityachoudhari26 commented Apr 30, 2025

Summary by CodeRabbit

  • New Features

    • Added a version selector check to the deployment flow, allowing users to see if a deployment version meets policy-based selection criteria within an environment.
    • The deployment environment node now displays the version selector check status alongside approval and deny window checks.
  • Bug Fixes

    • Improved reliability and separation of deployment version approval, deny window, and version selector checks.
  • Chores

    • Streamlined backend APIs for deployment version checks and policy updates, enhancing maintainability and future extensibility.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Apr 30, 2025

Walkthrough

This change introduces a new "Version Selector" check for deployment versions, implemented across both the frontend and backend. On the backend, the previously monolithic deployment version checks router is split into modular routers for approvals, deny windows, and version selectors, each with their own files and utility helpers. The version selector logic evaluates deployment versions against policy-based selectors within environments. The frontend adds a new VersionSelectorCheck React component, rendering its status within the environment node UI. Supporting API routes and query hooks are updated accordingly. Additionally, the policy update mutation now enqueues events after updates.

Changes

File(s) Change Summary
apps/webservice/src/app/[...]/VersionSelector.tsx Introduced the VersionSelectorCheck React component, which queries and displays the status of the version selector check for a given version and environment using TRPC.
apps/webservice/src/app/[...]/EnvironmentNode.tsx Imported and rendered the new VersionSelectorCheck within the EnvironmentNode component alongside other checks.
packages/api/src/router/deployment-version-checks.ts Deleted: The original monolithic router for deployment version checks, including approval and deny window logic, was removed.
packages/api/src/router/deployment-version-checks/approvals.ts New: Modular router for approval checks, with endpoints for status and adding approval records, including policy evaluation and event queueing.
packages/api/src/router/deployment-version-checks/deny-window.ts New: Modular router for deny window checks, currently returning a static status.
packages/api/src/router/deployment-version-checks/router.ts New: Main router aggregating approval, deny window, and version selector routers, with an endpoint for listing environments to check for a deployment.
packages/api/src/router/deployment-version-checks/utils.ts New: Utility functions for fetching applicable policies, deployment version metadata, and release targets.
packages/api/src/router/deployment-version-checks/version-selector.ts New: Implements the version selector check as a protected TRPC procedure, evaluating deployment versions against policy selectors.
packages/api/src/router/deployment-version.ts Updated import path for the deployment version checks router to use the new modular router location.
packages/api/src/router/policy.ts Policy update mutation now runs asynchronously and enqueues the updated policy on the event queue after updating.

Sequence Diagram(s)

sequenceDiagram
    participant UI as VersionSelectorCheck (React)
    participant API as TRPC API (versionSelector)
    participant DB as Database

    UI->>API: useQuery({ versionId, environmentId })
    API->>DB: Fetch deployment version metadata
    API->>DB: Fetch environment and system
    API->>DB: Find release target for deployment/environment
    API->>DB: Fetch applicable policies for release target
    API->>API: Merge policies, check for version selector
    alt Selector exists
        API->>DB: Query version matches selector
        API-->>UI: Return true/false
    else No selector
        API-->>UI: Return true
    end
    UI->>UI: Render status (loading, passing, failing)
Loading

Suggested reviewers

  • jsbroks

Poem

In the warren where code flows and hops,
A version selector check now pops!
With policies merged and queries tight,
Our carrots approve what feels just right.
Modular routers, events in the queue,
The deployment meadow feels fresh and new.
🥕✨

✨ 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.
    • Generate unit testing code for this file.
    • 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 generate unit testing code for this file.
    • @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 generate unit testing code.
    • @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.

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.

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
Copy Markdown
Contributor

@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 (2)
packages/api/src/router/deployment-version-checks/utils.ts (1)

58-76: Consider adding more specific error message

The function correctly fetches and returns release target data with added workspace ID. However, the error message could be more specific by including the workspace ID in the message.

-      message: `Release target not found: ${deploymentId} ${environmentId}`,
+      message: `Release target not found for deployment ${deploymentId} in environment ${environmentId} for workspace ${workspaceId}`,
packages/api/src/router/deployment-version-checks/approvals.ts (1)

67-82: Consider using a more specific permission for approval mutations.

The authorization check is using DeploymentVersionGet permission, which is typically used for read operations. For a mutation that adds an approval record, a more specific permission like DeploymentVersionApprove might be more appropriate if it exists in your permission model.

📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 1853f48 and 7bdd05a.

📒 Files selected for processing (10)
  • apps/webservice/src/app/[workspaceSlug]/(app)/(deploy)/(raw)/systems/[systemSlug]/(raw)/deployments/[deploymentSlug]/(raw)/releases/[releaseId]/checks/_components/flow-diagram/checks/VersionSelector.tsx (1 hunks)
  • apps/webservice/src/app/[workspaceSlug]/(app)/(deploy)/(raw)/systems/[systemSlug]/(raw)/deployments/[deploymentSlug]/(raw)/releases/[releaseId]/checks/_components/flow-diagram/nodes/EnvironmentNode.tsx (2 hunks)
  • packages/api/src/router/deployment-version-checks.ts (0 hunks)
  • packages/api/src/router/deployment-version-checks/approvals.ts (1 hunks)
  • packages/api/src/router/deployment-version-checks/deny-window.ts (1 hunks)
  • packages/api/src/router/deployment-version-checks/router.ts (1 hunks)
  • packages/api/src/router/deployment-version-checks/utils.ts (1 hunks)
  • packages/api/src/router/deployment-version-checks/version-selector.ts (1 hunks)
  • packages/api/src/router/deployment-version.ts (1 hunks)
  • packages/api/src/router/policy.ts (2 hunks)
💤 Files with no reviewable changes (1)
  • packages/api/src/router/deployment-version-checks.ts
🧰 Additional context used
📓 Path-based instructions (1)
`**/*.{ts,tsx}`: **Note on Error Handling:** Avoid strict enforcement of try/catch blocks. Code may use early returns, Promise chains (.then().catch()), or other patterns for error...

**/*.{ts,tsx}: Note on Error Handling:
Avoid strict enforcement of try/catch blocks. Code may use early returns, Promise chains (.then().catch()), or other patterns for error handling. These are acceptable as long as they maintain clarity and predictability.

  • apps/webservice/src/app/[workspaceSlug]/(app)/(deploy)/(raw)/systems/[systemSlug]/(raw)/deployments/[deploymentSlug]/(raw)/releases/[releaseId]/checks/_components/flow-diagram/nodes/EnvironmentNode.tsx
  • packages/api/src/router/deployment-version.ts
  • packages/api/src/router/deployment-version-checks/deny-window.ts
  • apps/webservice/src/app/[workspaceSlug]/(app)/(deploy)/(raw)/systems/[systemSlug]/(raw)/deployments/[deploymentSlug]/(raw)/releases/[releaseId]/checks/_components/flow-diagram/checks/VersionSelector.tsx
  • packages/api/src/router/policy.ts
  • packages/api/src/router/deployment-version-checks/approvals.ts
  • packages/api/src/router/deployment-version-checks/version-selector.ts
  • packages/api/src/router/deployment-version-checks/router.ts
  • packages/api/src/router/deployment-version-checks/utils.ts
🧬 Code Graph Analysis (6)
apps/webservice/src/app/[workspaceSlug]/(app)/(deploy)/(raw)/systems/[systemSlug]/(raw)/deployments/[deploymentSlug]/(raw)/releases/[releaseId]/checks/_components/flow-diagram/nodes/EnvironmentNode.tsx (1)
apps/webservice/src/app/[workspaceSlug]/(app)/(deploy)/(raw)/systems/[systemSlug]/(raw)/deployments/[deploymentSlug]/(raw)/releases/[releaseId]/checks/_components/flow-diagram/checks/VersionSelector.tsx (1)
  • VersionSelectorCheck (4-35)
packages/api/src/router/deployment-version-checks/deny-window.ts (1)
packages/api/src/trpc.ts (2)
  • createTRPCRouter (55-55)
  • protectedProcedure (173-173)
apps/webservice/src/app/[workspaceSlug]/(app)/(deploy)/(raw)/systems/[systemSlug]/(raw)/deployments/[deploymentSlug]/(raw)/releases/[releaseId]/checks/_components/flow-diagram/checks/VersionSelector.tsx (1)
apps/webservice/src/app/[workspaceSlug]/(app)/(deploy)/(raw)/systems/[systemSlug]/(raw)/deployments/[deploymentSlug]/(raw)/releases/[releaseId]/checks/_components/flow-diagram/StatusIcons.tsx (3)
  • Loading (28-32)
  • Passing (5-9)
  • Failing (11-15)
packages/api/src/router/policy.ts (2)
packages/rule-engine/src/db/update-policy.ts (1)
  • updatePolicyInTx (139-192)
packages/events/src/index.ts (1)
  • getQueue (28-34)
packages/api/src/router/deployment-version-checks/approvals.ts (7)
packages/api/src/trpc.ts (2)
  • createTRPCRouter (55-55)
  • protectedProcedure (173-173)
packages/api/src/router/deployment-version-checks/utils.ts (3)
  • getVersionWithMetadata (44-56)
  • getAnyReleaseTargetForDeploymentAndEnvironment (58-76)
  • getApplicablePoliciesWithoutResourceScope (7-42)
packages/db/src/schema/release.ts (1)
  • releaseTarget (20-42)
packages/rule-engine/src/utils/merge-policies.ts (1)
  • mergePolicies (29-49)
packages/rule-engine/src/manager/version-manager.ts (1)
  • VersionReleaseManager (37-212)
packages/rule-engine/src/manager/version-manager-rules.ts (1)
  • getVersionApprovalRules (61-67)
packages/events/src/index.ts (1)
  • getQueue (28-34)
packages/api/src/router/deployment-version-checks/router.ts (3)
packages/api/src/trpc.ts (2)
  • createTRPCRouter (55-55)
  • protectedProcedure (173-173)
packages/api/src/router/deployment-version-checks/approvals.ts (1)
  • approvalRouter (20-126)
packages/api/src/router/deployment-version-checks/deny-window.ts (1)
  • denyWindowRouter (7-24)
⏰ Context from checks skipped due to timeout of 90000ms (3)
  • GitHub Check: build (linux/amd64)
  • GitHub Check: Typecheck
  • GitHub Check: Lint
🔇 Additional comments (23)
packages/api/src/router/deployment-version-checks/utils.ts (2)

7-42: Well-structured database query function with clear return type

The getApplicablePoliciesWithoutResourceScope function correctly retrieves policies linked to a release target without resource selectors. The query is well-structured with proper joins and where clauses.


44-56: Good error handling for missing versions

The getVersionWithMetadata function appropriately throws a TRPC error when a version isn't found, which will translate to a proper HTTP response. The metadata transformation from an array to an object is clean and effective.

packages/api/src/router/deployment-version.ts (1)

48-48: Import path updated to reflect new modular structure

This change correctly updates the import path to use the new modular router structure, pointing to the specific router file.

apps/webservice/src/app/[workspaceSlug]/(app)/(deploy)/(raw)/systems/[systemSlug]/(raw)/deployments/[deploymentSlug]/(raw)/releases/[releaseId]/checks/_components/flow-diagram/nodes/EnvironmentNode.tsx (2)

12-12: Clean import of the new VersionSelectorCheck component

The import is correctly added, maintaining the pattern of other similar check components.


39-39: Good integration of the VersionSelectorCheck component

The VersionSelectorCheck component is properly added to the UI alongside existing check components, and all required props are passed through using the spread syntax.

packages/api/src/router/policy.ts (2)

19-19: New import for event queue integration.

Added the Channel and getQueue imports from the events module, which will be used to enqueue policy updates for asynchronous processing.


298-304: Implementation of event-driven policy updates.

The update mutation now not only updates the policy in the database but also enqueues the updated policy object into a message queue for asynchronous processing. This is an important improvement that enables other parts of the system to react to policy changes through the event queue.

This approach is more maintainable and follows better separation of concerns by:

  1. Keeping the transaction focused on data persistence
  2. Delegating downstream effects to event handlers via the queue
  3. Supporting eventual consistency throughout the system
apps/webservice/src/app/[workspaceSlug]/(app)/(deploy)/(raw)/systems/[systemSlug]/(raw)/deployments/[deploymentSlug]/(raw)/releases/[releaseId]/checks/_components/flow-diagram/checks/VersionSelector.tsx (6)

1-3: Clear import structure for the component.

Appropriate imports for the API client and status icon components.


4-7: Well-defined component interface with proper typing.

The component has a clean interface that accepts the necessary props with proper TypeScript types.


8-14: API query integration with appropriate default value.

The component properly uses the TRPC query hook to fetch the version selector status and defaults to false when data is not available, which is a safe fallback.


16-21: Loading state handling with appropriate UI.

The component correctly handles the loading state with a visual indicator and descriptive text.


23-28: Success state handling with appropriate UI.

The component correctly handles the success state with a visual indicator and descriptive text.


30-35: Failure state handling with appropriate UI.

The component correctly handles the failure state with a visual indicator and descriptive text.

packages/api/src/router/deployment-version-checks/router.ts (3)

1-11: Well-organized imports for the router module.

The imports are appropriately grouped and include necessary dependencies for schema access, authorization, and sub-routers.


12-37: Well-implemented environment retrieval procedure with proper authorization.

The environmentsToCheck procedure:

  1. Correctly validates input as a UUID
  2. Implements appropriate authorization checks based on system-level permissions
  3. Returns early with false if the deployment doesn't exist
  4. Efficiently queries for distinct environments associated with a deployment

38-41: Modular router structure with clear component organization.

The router follows good practices by aggregating focused sub-routers for approvals, deny windows, and version selectors, promoting maintainability and separation of concerns.

packages/api/src/router/deployment-version-checks/version-selector.ts (5)

1-15: Well-organized imports with clear structure.

The imports are appropriately grouped by their source and include necessary dependencies for database operations, schema access, and utility functions.


16-29: Well-defined procedure with proper input validation and authorization.

The procedure:

  1. Validates input with proper zod schema for both versionId and environmentId
  2. Implements appropriate authorization checks based on deployment version permissions

30-47: Good error handling and data retrieval.

The procedure correctly:

  1. Extracts input parameters
  2. Fetches the necessary version and environment data
  3. Throws a proper TRPCError with NOT_FOUND code if the environment doesn't exist
  4. Extracts workspace information from the system for further processing

48-61: Effective policy evaluation with appropriate default behavior.

The code properly:

  1. Retrieves the applicable release target and policies
  2. Merges policies to create a combined policy view
  3. Extracts the version selector from the merged policy
  4. Returns true by default if no version selector is defined

63-71: Efficient version selector evaluation using database query.

The implementation efficiently:

  1. Uses a database query to check if the version matches the selector criteria
  2. Applies both ID equality and custom selector conditions
  3. Returns a boolean result based on whether a matching version was found
packages/api/src/router/deployment-version-checks/approvals.ts (2)

20-65: Implementation looks good and follows best practices.

This status endpoint correctly handles authorization, performs policy checks, and evaluates approval status. The code uses appropriate error handling through utility functions, maintains type safety with Zod validation, and ensures proper authorization checks.


83-125: Implementation looks robust, with proper queueing of follow-up evaluations.

The mutation correctly:

  1. Inserts the approval record with appropriate metadata
  2. Fetches affected release targets
  3. Enqueues evaluation jobs to handle downstream effects
  4. Returns the created record

The code follows good practices by using bulk operations for the queue and properly tracking approval timestamps.

Comment on lines +1 to +24
import { z } from "zod";

import { Permission } from "@ctrlplane/validators/auth";

import { createTRPCRouter, protectedProcedure } from "../../trpc";

export const denyWindowRouter = createTRPCRouter({
status: protectedProcedure
.input(
z.object({
workspaceId: z.string().uuid(),
versionId: z.string().uuid(),
environmentId: z.string().uuid(),
}),
)
.meta({
authorizationCheck: ({ canUser, input }) =>
canUser.perform(Permission.DeploymentVersionGet).on({
type: "deploymentVersion",
id: input.versionId,
}),
})
.query(() => false),
});
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Implement actual deny window check logic

The current implementation is a placeholder that always returns false, indicating that deny windows are never active. In a real-world scenario, you would want to implement the actual logic to check if the current time falls within any deny windows associated with the environment or version.

export const denyWindowRouter = createTRPCRouter({
  status: protectedProcedure
    .input(
      z.object({
        workspaceId: z.string().uuid(),
        versionId: z.string().uuid(),
        environmentId: z.string().uuid(),
      }),
    )
    .meta({
      authorizationCheck: ({ canUser, input }) =>
        canUser.perform(Permission.DeploymentVersionGet).on({
          type: "deploymentVersion",
          id: input.versionId,
        }),
    })
-   .query(() => false),
+   .query(async ({ ctx, input }) => {
+     const { db } = ctx;
+     const { versionId, environmentId } = input;
+     
+     // Get release target for this deployment and environment
+     const rt = await db.query.releaseTarget.findFirst({
+       where: and(
+         eq(SCHEMA.releaseTarget.environmentId, environmentId),
+       ),
+       with: {
+         deployment: {
+           with: {
+             versions: {
+               where: eq(SCHEMA.deploymentVersion.id, versionId)
+             }
+           }
+         }
+       }
+     });
+     
+     if (!rt) return false;
+     
+     // Get policies that apply to this release target
+     const policies = await getApplicablePoliciesWithoutResourceScope(db, rt.id);
+     
+     // Check if any policy has active deny windows
+     const now = new Date();
+     return policies.some(policy => 
+       policy.denyWindows.some(window => {
+         const startTime = new Date(window.startTime);
+         const endTime = new Date(window.endTime);
+         return now >= startTime && now <= endTime;
+       })
+     );
+   }),
});

Committable suggestion skipped: line range outside the PR's diff.

@adityachoudhari26 adityachoudhari26 merged commit 6cdffd0 into main Apr 30, 2025
3 of 6 checks passed
@adityachoudhari26 adityachoudhari26 deleted the version-check-ui branch April 30, 2025 06:41
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