Skip to content

Conversation

@adityachoudhari26
Copy link
Contributor

@adityachoudhari26 adityachoudhari26 commented Jul 12, 2025

Summary by CodeRabbit

  • New Features

    • Added support for setting a numeric priority on deployment variable values, enabling conflict resolution based on priority.
    • Updated API and schema to include an optional priority field for deployment variable values.
    • Introduced a priority input field in the UI for deployment variable values.
  • Bug Fixes

    • Enhanced resolution logic to correctly select the highest priority variable value when multiple values match a resource.
  • Tests

    • Added an end-to-end test verifying that variable value conflicts are resolved using the priority field.
  • Refactor

    • Unified and simplified variable value retrieval and resolution logic for better maintainability and performance.
  • Chores

    • Updated database schema and OpenAPI documentation to include the new priority field.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jul 12, 2025

## Walkthrough

This change introduces a `priority` field to deployment variable values, updates schemas, APIs, and database logic to support it, and refactors variable resolution to unify direct and reference values into a single array. The system now resolves variable values for resources based on priority, and test coverage for priority-based resolution is added.

## Changes

| Files / Areas                                                                                 | Change Summary                                                                                           |
|----------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------|
| `packages/db/drizzle/0126_wandering_sasquatch.sql`, `packages/db/src/schema/deployment-variables.ts`, `packages/db/src/utils/deployment-variables/upsert-direct-value.ts`, `packages/db/src/utils/deployment-variables/upsert-reference-value.ts` | Add `priority` column to deployment variable values, update schema, and handle priority in upsert logic |
| `openapi.v1.json`, `e2e/api/schema.ts`, `apps/webservice/src/app/api/v1/deployments/[deploymentId]/variables/openapi.ts` | Make `resourceSelector` optional and add `priority` property to API schema                              |
| `packages/db/src/utils/deployment-variables/get-deployment-variables.ts`, `apps/webservice/src/app/api/v1/deployments/[deploymentId]/variables/route.ts` | Refactor to unify direct/reference values, update API response shape, and handle priority               |
| `packages/rule-engine/src/manager/variables/db-variable-providers.ts`, `packages/rule-engine/src/manager/variables/resolve-variable-value.ts`, `packages/rule-engine/src/manager/variables/index.ts`, `packages/rule-engine/package.json` | Unify value resolution logic, add value resolver module, and update exports/dependencies                |
| `packages/api/src/router/deployment-variable/by-deployment-id.ts`                            | Refactor variable value/resource resolution to use unified logic and priority handling                  |
| `apps/webservice/src/app/[workspaceSlug]/.../variables/page.tsx`                             | Remove transformation of variable values; fetch and pass variables directly                             |
| `apps/webservice/src/app/[workspaceSlug]/(app)/(deploy)/(raw)/systems/[systemSlug]/(raw)/deployments/[deploymentSlug]/(sidebar)/variables/_components/direct-value/CreateDirectValueDialog.tsx` | Add `PriorityFormField` component and include it in the direct value creation form                      |
| `e2e/tests/api/resource-variables.spec.ts`                                                   | Add test for priority-based variable value resolution                                                   |
| `packages/db/drizzle/meta/_journal.json`                                                     | Add migration journal entry for priority column                                                         |

## Sequence Diagram(s)

```mermaid
sequenceDiagram
    participant Client
    participant API
    participant DB
    participant RuleEngine

    Client->>API: Request deployment variables for a resource
    API->>DB: Fetch deployment variable values (with priorities)
    DB-->>API: Return variables with values (priority included)
    API->>RuleEngine: Resolve variable value for resource (considering priority)
    RuleEngine->>DB: Check resourceSelector, priority, resolve value
    RuleEngine-->>API: Return resolved value
    API-->>Client: Respond with resolved variable value

Possibly related PRs

  • ctrlplanedev/ctrlplane#561: Modifies deployment variable value types and handling, introducing/refining the distinction between direct and reference values at schema and code level.
  • ctrlplanedev/ctrlplane#517: Introduces the initial deployment variables API route and schema, related to the API and schema changes refined here.
  • ctrlplanedev/ctrlplane#580: Refactors frontend to explicitly separate direct and reference values, related to frontend variable handling changes.

Suggested reviewers

  • jsbroks

Poem

In the meadow where variables grow,
A new field called "priority" starts to show.
Direct and reference, now side by side,
With resolution logic unified.
The rabbit hops, the tests all pass—
May your configs be sorted,
And your code run fast!
🐇✨


<!-- walkthrough_end -->
<!-- internal state start -->


<!-- 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 -->

<!-- internal state end -->
<!-- finishing_touch_checkbox_start -->

<details open="true">
<summary>✨ Finishing Touches</summary>

- [ ] <!-- {"checkboxId": "7962f53c-55bc-4827-bfbf-6a18da830691"} --> 📝 Generate Docstrings

</details>

<!-- finishing_touch_checkbox_end -->
<!-- tips_start -->

---

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.

<details>
<summary>❤️ Share</summary>

- [X](https://twitter.com/intent/tweet?text=I%20just%20used%20%40coderabbitai%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20the%20proprietary%20code.%20Check%20it%20out%3A&url=https%3A//coderabbit.ai)
- [Mastodon](https://mastodon.social/share?text=I%20just%20used%20%40coderabbitai%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20the%20proprietary%20code.%20Check%20it%20out%3A%20https%3A%2F%2Fcoderabbit.ai)
- [Reddit](https://www.reddit.com/submit?title=Great%20tool%20for%20code%20review%20-%20CodeRabbit&text=I%20just%20used%20CodeRabbit%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20proprietary%20code.%20Check%20it%20out%3A%20https%3A//coderabbit.ai)
- [LinkedIn](https://www.linkedin.com/sharing/share-offsite/?url=https%3A%2F%2Fcoderabbit.ai&mini=true&title=Great%20tool%20for%20code%20review%20-%20CodeRabbit&summary=I%20just%20used%20CodeRabbit%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20proprietary%20code)

</details>

<details>
<summary>🪧 Tips</summary>

### Chat

There are 3 ways to chat with [CodeRabbit](https://coderabbit.ai?utm_source=oss&utm_medium=github&utm_campaign=ctrlplanedev/ctrlplane&utm_content=619):

- 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](https://www.coderabbit.ai/contact-us/support) 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](https://docs.coderabbit.ai/finishing-touches/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](https://docs.coderabbit.ai) for detailed information on how to use CodeRabbit.
- Join our [Discord Community](http://discord.gg/coderabbit) to get help, request features, and share feedback.
- Follow us on [X/Twitter](https://twitter.com/coderabbitai) for updates and announcements.

</details>

<!-- tips_end -->

Copy link
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: 3

🧹 Nitpick comments (1)
apps/webservice/src/app/api/v1/deployments/[deploymentId]/variables/openapi.ts (1)

20-20: Consider type precision and consistency with database constraints.

Since the database schema uses a non-nullable integer column with a default value, consider:

  1. Using "integer" type instead of "number" for better precision
  2. Evaluating if this should be a required field in responses, since the database always provides a value
-          priority: { type: "number" },
+          priority: { type: "integer" },
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 8c1ad18 and e72f347.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (17)
  • apps/webservice/src/app/[workspaceSlug]/(app)/(deploy)/(raw)/systems/[systemSlug]/(raw)/deployments/[deploymentSlug]/(sidebar)/variables/page.tsx (1 hunks)
  • apps/webservice/src/app/api/v1/deployments/[deploymentId]/variables/openapi.ts (1 hunks)
  • apps/webservice/src/app/api/v1/deployments/[deploymentId]/variables/route.ts (3 hunks)
  • e2e/api/schema.ts (1 hunks)
  • e2e/tests/api/resource-variables.spec.ts (1 hunks)
  • openapi.v1.json (1 hunks)
  • packages/api/src/router/deployment-variable/by-deployment-id.ts (3 hunks)
  • packages/db/drizzle/0126_wandering_sasquatch.sql (1 hunks)
  • packages/db/drizzle/meta/_journal.json (1 hunks)
  • packages/db/src/schema/deployment-variables.ts (4 hunks)
  • packages/db/src/utils/deployment-variables/get-deployment-variables.ts (2 hunks)
  • packages/db/src/utils/deployment-variables/upsert-direct-value.ts (2 hunks)
  • packages/db/src/utils/deployment-variables/upsert-reference-value.ts (2 hunks)
  • packages/rule-engine/package.json (1 hunks)
  • packages/rule-engine/src/manager/variables/db-variable-providers.ts (3 hunks)
  • packages/rule-engine/src/manager/variables/index.ts (1 hunks)
  • packages/rule-engine/src/manager/variables/resolve-variable-value.ts (1 hunks)
🧰 Additional context used
📓 Path-based instructions (3)
**/*.{js,jsx,ts,tsx,json,css,md,yml,yaml}

Instructions used from:

Sources:
📄 CodeRabbit Inference Engine

  • CLAUDE.md
**/*.{ts,tsx}

Instructions used from:

Sources:
📄 CodeRabbit Inference Engine

  • CLAUDE.md

⚙️ CodeRabbit Configuration File

**/*.{js,jsx,ts,tsx}

Instructions used from:

Sources:
📄 CodeRabbit Inference Engine

  • CLAUDE.md
🧠 Learnings (17)
📓 Common learnings
Learnt from: adityachoudhari26
PR: ctrlplanedev/ctrlplane#561
File: packages/db/drizzle/0100_robust_eternals.sql:2-2
Timestamp: 2025-05-11T17:51:40.365Z
Learning: The deployment_variable_value table needs to support multiple records with null values for the same variable_id, which is why a unique index with COALESCE would be problematic as it would treat all nulls as equal.
Learnt from: adityachoudhari26
PR: ctrlplanedev/ctrlplane#601
File: e2e/tests/api/policies/retry-policy.spec.ts:23-24
Timestamp: 2025-06-24T23:52:50.732Z
Learning: The user adityachoudhari26 prefers not to add null safety checks or defensive programming in test code, particularly in e2e tests, as they prioritize simplicity and focus on the main functionality being tested rather than comprehensive error handling within the test itself.
Learnt from: adityachoudhari26
PR: ctrlplanedev/ctrlplane#601
File: e2e/tests/api/policies/retry-policy.spec.ts:117-130
Timestamp: 2025-06-24T23:53:25.398Z
Learning: User adityachoudhari26 prefers to keep non-null assertions in e2e test code without extensive null safety checks, reasoning that test failures serve the same purpose of catching issues and the extra validation doesn't add much value in test contexts.
packages/rule-engine/package.json (2)
Learnt from: adityachoudhari26
PR: ctrlplanedev/ctrlplane#579
File: packages/rule-engine/src/rules/concurrency-rule.ts:8-11
Timestamp: 2025-06-01T19:10:47.122Z
Learning: In packages/rule-engine/src/rules/concurrency-rule.ts, the ConcurrencyRule should remain simple without additional validation since database and Zod schemas already handle concurrency validation. The user prefers this rule to be "dumb" and just perform the comparison check rather than duplicating validation logic.
Learnt from: CR
PR: ctrlplanedev/ctrlplane#0
File: CLAUDE.md:0-0
Timestamp: 2025-06-30T21:36:42.935Z
Learning: Applies to **/*.{js,jsx,ts,tsx,json,css,md,yml,yaml} : Formatting: Prettier is used with `@ctrlplane/prettier-config`
apps/webservice/src/app/[workspaceSlug]/(app)/(deploy)/(raw)/systems/[systemSlug]/(raw)/deployments/[deploymentSlug]/(sidebar)/variables/page.tsx (7)
Learnt from: adityachoudhari26
PR: ctrlplanedev/ctrlplane#237
File: apps/webservice/src/app/[workspaceSlug]/(app)/_components/deployment-resource-drawer/DeploymentResourceDrawer.tsx:43-50
Timestamp: 2024-11-27T23:16:35.580Z
Learning: In `DeploymentResourceDrawer.tsx`, the `isOpen` variable already checks whether `deploymentId`, `environmentId`, and `resourceId` are non-null, so additional null checks in query `enabled` conditions are not necessary.
Learnt from: adityachoudhari26
PR: ctrlplanedev/ctrlplane#188
File: apps/webservice/src/app/[workspaceSlug]/_components/release-channel-drawer/Usage.tsx:42-44
Timestamp: 2024-11-01T02:35:07.352Z
Learning: In `apps/webservice/src/app/[workspaceSlug]/_components/release-channel-drawer/Usage.tsx`, within the `Usage` component, the arrays used for filtering inherited environments are expected to remain small. Therefore, performance optimizations for this filtering logic are not necessary.
Learnt from: adityachoudhari26
PR: ctrlplanedev/ctrlplane#515
File: apps/webservice/src/app/api/v1/release-targets/[releaseTargetId]/releases/route.ts:103-108
Timestamp: 2025-04-28T18:41:58.813Z
Learning: In this project, full records from the `deployment` and `deployment_version` tables are considered safe for public API consumption, and there's no need to create restricted DTOs for them.
Learnt from: adityachoudhari26
PR: ctrlplanedev/ctrlplane#187
File: apps/jobs/src/ephemeral-env-checker/index.ts:57-0
Timestamp: 2024-10-30T23:10:58.869Z
Learning: In the codebase, deployments are decoupled from environments. When deleting environments (e.g., in `apps/jobs/src/ephemeral-env-checker/index.ts`), associated deployments should not be deleted.
Learnt from: adityachoudhari26
PR: ctrlplanedev/ctrlplane#181
File: packages/api/src/router/deployment.ts:116-131
Timestamp: 2024-10-29T02:04:50.312Z
Learning: In `packages/api/src/router/deployment.ts`, the `list.byDeploymentId` procedure requires multiple database queries due to limitations of the `releaseMatchesCondition` function.
Learnt from: zacharyblasczyk
PR: ctrlplanedev/ctrlplane#382
File: apps/webservice/src/app/api/v1/deployments/[deploymentId]/route.ts:82-88
Timestamp: 2025-03-16T19:41:44.129Z
Learning: In Next.js 15, dynamic route parameters (params) return Promises instead of direct values in async contexts. When accessing properties like `params.deploymentId` in an async function, use `(await params).deploymentId` to avoid the "params should be awaited before using its properties" error. This applies to API routes, page components, and other async contexts.
Learnt from: zacharyblasczyk
PR: ctrlplanedev/ctrlplane#382
File: apps/webservice/src/app/api/v1/deployments/[deploymentId]/route.ts:82-88
Timestamp: 2025-03-16T19:41:44.129Z
Learning: In Next.js 15, params in dynamic routes must be awaited before accessing their properties in async contexts. For example, `params.deploymentId` should be accessed as `(await params).deploymentId` in async functions.
packages/db/drizzle/0126_wandering_sasquatch.sql (1)
Learnt from: adityachoudhari26
PR: ctrlplanedev/ctrlplane#561
File: packages/db/drizzle/0100_robust_eternals.sql:2-2
Timestamp: 2025-05-11T17:51:40.365Z
Learning: The deployment_variable_value table needs to support multiple records with null values for the same variable_id, which is why a unique index with COALESCE would be problematic as it would treat all nulls as equal.
apps/webservice/src/app/api/v1/deployments/[deploymentId]/variables/openapi.ts (4)
Learnt from: adityachoudhari26
PR: ctrlplanedev/ctrlplane#237
File: apps/webservice/src/app/[workspaceSlug]/(app)/_components/deployment-resource-drawer/DeploymentResourceDrawer.tsx:43-50
Timestamp: 2024-11-27T23:16:35.580Z
Learning: In `DeploymentResourceDrawer.tsx`, the `isOpen` variable already checks whether `deploymentId`, `environmentId`, and `resourceId` are non-null, so additional null checks in query `enabled` conditions are not necessary.
Learnt from: adityachoudhari26
PR: ctrlplanedev/ctrlplane#181
File: packages/api/src/router/deployment.ts:116-131
Timestamp: 2024-10-29T02:04:50.312Z
Learning: In `packages/api/src/router/deployment.ts`, the `list.byDeploymentId` procedure requires multiple database queries due to limitations of the `releaseMatchesCondition` function.
Learnt from: adityachoudhari26
PR: ctrlplanedev/ctrlplane#187
File: apps/jobs/src/ephemeral-env-checker/index.ts:57-0
Timestamp: 2024-10-30T23:10:58.869Z
Learning: In the codebase, deployments are decoupled from environments. When deleting environments (e.g., in `apps/jobs/src/ephemeral-env-checker/index.ts`), associated deployments should not be deleted.
Learnt from: adityachoudhari26
PR: ctrlplanedev/ctrlplane#515
File: apps/webservice/src/app/api/v1/release-targets/[releaseTargetId]/releases/route.ts:103-108
Timestamp: 2025-04-28T18:41:58.813Z
Learning: In this project, full records from the `deployment` and `deployment_version` tables are considered safe for public API consumption, and there's no need to create restricted DTOs for them.
packages/db/src/utils/deployment-variables/upsert-reference-value.ts (2)
Learnt from: adityachoudhari26
PR: ctrlplanedev/ctrlplane#187
File: apps/jobs/src/ephemeral-env-checker/index.ts:57-0
Timestamp: 2024-10-30T23:10:58.869Z
Learning: In the codebase, deployments are decoupled from environments. When deleting environments (e.g., in `apps/jobs/src/ephemeral-env-checker/index.ts`), associated deployments should not be deleted.
Learnt from: adityachoudhari26
PR: ctrlplanedev/ctrlplane#237
File: apps/webservice/src/app/[workspaceSlug]/(app)/_components/deployment-resource-drawer/DeploymentResourceDrawer.tsx:43-50
Timestamp: 2024-11-27T23:16:35.580Z
Learning: In `DeploymentResourceDrawer.tsx`, the `isOpen` variable already checks whether `deploymentId`, `environmentId`, and `resourceId` are non-null, so additional null checks in query `enabled` conditions are not necessary.
packages/db/src/utils/deployment-variables/upsert-direct-value.ts (4)
Learnt from: adityachoudhari26
PR: ctrlplanedev/ctrlplane#187
File: apps/jobs/src/ephemeral-env-checker/index.ts:57-0
Timestamp: 2024-10-30T23:10:58.869Z
Learning: In the codebase, deployments are decoupled from environments. When deleting environments (e.g., in `apps/jobs/src/ephemeral-env-checker/index.ts`), associated deployments should not be deleted.
Learnt from: adityachoudhari26
PR: ctrlplanedev/ctrlplane#237
File: apps/webservice/src/app/[workspaceSlug]/(app)/_components/deployment-resource-drawer/DeploymentResourceDrawer.tsx:43-50
Timestamp: 2024-11-27T23:16:35.580Z
Learning: In `DeploymentResourceDrawer.tsx`, the `isOpen` variable already checks whether `deploymentId`, `environmentId`, and `resourceId` are non-null, so additional null checks in query `enabled` conditions are not necessary.
Learnt from: adityachoudhari26
PR: ctrlplanedev/ctrlplane#181
File: packages/api/src/router/deployment.ts:116-131
Timestamp: 2024-10-29T02:04:50.312Z
Learning: In `packages/api/src/router/deployment.ts`, the `list.byDeploymentId` procedure requires multiple database queries due to limitations of the `releaseMatchesCondition` function.
Learnt from: adityachoudhari26
PR: ctrlplanedev/ctrlplane#395
File: packages/api/src/router/environment-page/resources/router.ts:40-45
Timestamp: 2025-03-24T18:46:38.894Z
Learning: The `takeFirst` utility function in the codebase (from `@ctrlplane/db`) throws an Error with message "Found non unique or inexistent value" if the result array doesn't contain exactly one element, making additional null/undefined checks unnecessary after its use.
packages/rule-engine/src/manager/variables/index.ts (1)
Learnt from: CR
PR: ctrlplanedev/ctrlplane#0
File: CLAUDE.md:0-0
Timestamp: 2025-06-30T21:36:42.935Z
Learning: Applies to **/*.{ts,tsx} : Consistent type imports: `import type { Type } from "module"`
openapi.v1.json (2)

undefined

<retrieved_learning>
Learnt from: adityachoudhari26
PR: #580
File: apps/webservice/src/app/api/v1/deployments/[deploymentId]/variables/openapi.ts:21-21
Timestamp: 2025-06-02T17:55:33.889Z
Learning: In OpenAPI schemas, a field marked as both "required" and "nullable" means the field must be present in the request/response object, but its value can be explicitly set to null. This is different from optional fields where the field can be omitted entirely. For example, resourceSelector: null is valid when resourceSelector is required+nullable, but would be invalid if resourceSelector was required+non-nullable.
</retrieved_learning>

<retrieved_learning>
Learnt from: adityachoudhari26
PR: #237
File: apps/webservice/src/app/[workspaceSlug]/(app)/_components/deployment-resource-drawer/DeploymentResourceDrawer.tsx:43-50
Timestamp: 2024-11-27T23:16:35.580Z
Learning: In DeploymentResourceDrawer.tsx, the isOpen variable already checks whether deploymentId, environmentId, and resourceId are non-null, so additional null checks in query enabled conditions are not necessary.
</retrieved_learning>

e2e/tests/api/resource-variables.spec.ts (6)
Learnt from: adityachoudhari26
PR: ctrlplanedev/ctrlplane#517
File: e2e/tests/api/deployment-variable.spec.ts:70-76
Timestamp: 2025-04-28T21:59:04.723Z
Learning: In the ctrlplane e2e tests, tests can be isolated between runs using prefixed systems with random IDs in YAML templates, but tests within the same file may still need to handle isolation between test cases if they operate on the same resources.
Learnt from: adityachoudhari26
PR: ctrlplanedev/ctrlplane#237
File: apps/webservice/src/app/[workspaceSlug]/(app)/_components/deployment-resource-drawer/DeploymentResourceDrawer.tsx:43-50
Timestamp: 2024-11-27T23:16:35.580Z
Learning: In `DeploymentResourceDrawer.tsx`, the `isOpen` variable already checks whether `deploymentId`, `environmentId`, and `resourceId` are non-null, so additional null checks in query `enabled` conditions are not necessary.
Learnt from: adityachoudhari26
PR: ctrlplanedev/ctrlplane#181
File: packages/api/src/router/deployment.ts:116-131
Timestamp: 2024-10-29T02:04:50.312Z
Learning: In `packages/api/src/router/deployment.ts`, the `list.byDeploymentId` procedure requires multiple database queries due to limitations of the `releaseMatchesCondition` function.
Learnt from: adityachoudhari26
PR: ctrlplanedev/ctrlplane#187
File: apps/jobs/src/ephemeral-env-checker/index.ts:57-0
Timestamp: 2024-10-30T23:10:58.869Z
Learning: In the codebase, deployments are decoupled from environments. When deleting environments (e.g., in `apps/jobs/src/ephemeral-env-checker/index.ts`), associated deployments should not be deleted.
Learnt from: zacharyblasczyk
PR: ctrlplanedev/ctrlplane#382
File: apps/webservice/src/app/api/v1/deployments/[deploymentId]/route.ts:82-88
Timestamp: 2025-03-16T19:41:44.129Z
Learning: In Next.js 15, dynamic route parameters (params) return Promises instead of direct values in async contexts. When accessing properties like `params.deploymentId` in an async function, use `(await params).deploymentId` to avoid the "params should be awaited before using its properties" error. This applies to API routes, page components, and other async contexts.
Learnt from: zacharyblasczyk
PR: ctrlplanedev/ctrlplane#382
File: apps/webservice/src/app/api/v1/deployments/[deploymentId]/route.ts:82-88
Timestamp: 2025-03-16T19:41:44.129Z
Learning: In Next.js 15, params in dynamic routes must be awaited before accessing their properties in async contexts. For example, `params.deploymentId` should be accessed as `(await params).deploymentId` in async functions.
packages/rule-engine/src/manager/variables/resolve-variable-value.ts (2)
Learnt from: adityachoudhari26
PR: ctrlplanedev/ctrlplane#181
File: packages/api/src/router/deployment.ts:116-131
Timestamp: 2024-10-29T02:04:50.312Z
Learning: In `packages/api/src/router/deployment.ts`, the `list.byDeploymentId` procedure requires multiple database queries due to limitations of the `releaseMatchesCondition` function.
Learnt from: adityachoudhari26
PR: ctrlplanedev/ctrlplane#237
File: apps/webservice/src/app/[workspaceSlug]/(app)/_components/deployment-resource-drawer/DeploymentResourceDrawer.tsx:43-50
Timestamp: 2024-11-27T23:16:35.580Z
Learning: In `DeploymentResourceDrawer.tsx`, the `isOpen` variable already checks whether `deploymentId`, `environmentId`, and `resourceId` are non-null, so additional null checks in query `enabled` conditions are not necessary.
e2e/api/schema.ts (2)

undefined

<retrieved_learning>
Learnt from: adityachoudhari26
PR: #237
File: apps/webservice/src/app/[workspaceSlug]/(app)/_components/deployment-resource-drawer/DeploymentResourceDrawer.tsx:43-50
Timestamp: 2024-11-27T23:16:35.580Z
Learning: In DeploymentResourceDrawer.tsx, the isOpen variable already checks whether deploymentId, environmentId, and resourceId are non-null, so additional null checks in query enabled conditions are not necessary.
</retrieved_learning>

<retrieved_learning>
Learnt from: adityachoudhari26
PR: #580
File: apps/webservice/src/app/api/v1/deployments/[deploymentId]/variables/openapi.ts:21-21
Timestamp: 2025-06-02T17:55:33.889Z
Learning: In OpenAPI schemas, a field marked as both "required" and "nullable" means the field must be present in the request/response object, but its value can be explicitly set to null. This is different from optional fields where the field can be omitted entirely. For example, resourceSelector: null is valid when resourceSelector is required+nullable, but would be invalid if resourceSelector was required+non-nullable.
</retrieved_learning>

apps/webservice/src/app/api/v1/deployments/[deploymentId]/variables/route.ts (10)
Learnt from: adityachoudhari26
PR: ctrlplanedev/ctrlplane#181
File: packages/api/src/router/deployment.ts:116-131
Timestamp: 2024-10-29T02:04:50.312Z
Learning: In `packages/api/src/router/deployment.ts`, the `list.byDeploymentId` procedure requires multiple database queries due to limitations of the `releaseMatchesCondition` function.
Learnt from: zacharyblasczyk
PR: ctrlplanedev/ctrlplane#382
File: apps/webservice/src/app/api/v1/deployments/[deploymentId]/route.ts:82-88
Timestamp: 2025-03-16T19:41:44.129Z
Learning: In Next.js 15, dynamic route parameters (params) return Promises instead of direct values in async contexts. When accessing properties like `params.deploymentId` in an async function, use `(await params).deploymentId` to avoid the "params should be awaited before using its properties" error. This applies to API routes, page components, and other async contexts.
Learnt from: adityachoudhari26
PR: ctrlplanedev/ctrlplane#237
File: apps/webservice/src/app/[workspaceSlug]/(app)/_components/deployment-resource-drawer/DeploymentResourceDrawer.tsx:43-50
Timestamp: 2024-11-27T23:16:35.580Z
Learning: In `DeploymentResourceDrawer.tsx`, the `isOpen` variable already checks whether `deploymentId`, `environmentId`, and `resourceId` are non-null, so additional null checks in query `enabled` conditions are not necessary.
Learnt from: adityachoudhari26
PR: ctrlplanedev/ctrlplane#188
File: packages/api/src/router/deployment.ts:144-161
Timestamp: 2024-11-01T02:37:25.510Z
Learning: In `packages/api/src/router/deployment.ts`, when using Drizzle ORM, there is a limitation when referencing the same table twice in a relational builder query (rbq), requiring separate queries to avoid issues.
Learnt from: zacharyblasczyk
PR: ctrlplanedev/ctrlplane#382
File: apps/webservice/src/app/api/v1/deployments/[deploymentId]/route.ts:82-88
Timestamp: 2025-03-16T19:41:44.129Z
Learning: In Next.js 15, params in dynamic routes must be awaited before accessing their properties in async contexts. For example, `params.deploymentId` should be accessed as `(await params).deploymentId` in async functions.
Learnt from: adityachoudhari26
PR: ctrlplanedev/ctrlplane#187
File: apps/jobs/src/ephemeral-env-checker/index.ts:57-0
Timestamp: 2024-10-30T23:10:58.869Z
Learning: In the codebase, deployments are decoupled from environments. When deleting environments (e.g., in `apps/jobs/src/ephemeral-env-checker/index.ts`), associated deployments should not be deleted.
Learnt from: adityachoudhari26
PR: ctrlplanedev/ctrlplane#515
File: apps/webservice/src/app/api/v1/release-targets/[releaseTargetId]/releases/route.ts:103-108
Timestamp: 2025-04-28T18:41:58.813Z
Learning: In this project, full records from the `deployment` and `deployment_version` tables are considered safe for public API consumption, and there's no need to create restricted DTOs for them.
Learnt from: adityachoudhari26
PR: ctrlplanedev/ctrlplane#580
File: packages/db/src/utils/deployment-variables/upsert-direct-value.ts:33-49
Timestamp: 2025-06-02T17:59:53.658Z
Learning: In the ctrlplane codebase's deployment variable deduplication logic, null values are intentionally converted to the string "null" using String(null) so that all null values hash to the same value for consistent deduplication behavior across deployment variables.
Learnt from: adityachoudhari26
PR: ctrlplanedev/ctrlplane#395
File: packages/api/src/router/environment-page/resources/router.ts:40-45
Timestamp: 2025-03-24T18:46:38.894Z
Learning: The `takeFirst` utility function in the codebase (from `@ctrlplane/db`) throws an Error with message "Found non unique or inexistent value" if the result array doesn't contain exactly one element, making additional null/undefined checks unnecessary after its use.
Learnt from: adityachoudhari26
PR: ctrlplanedev/ctrlplane#579
File: packages/db/src/schema/rules/concurrency.ts:0-0
Timestamp: 2025-06-01T19:10:11.535Z
Learning: In the ctrlplane codebase, when defining database schemas with Drizzle ORM, it's an intentional pattern to spread base fields (like `basePolicyRuleFields`) and then redefine specific fields to add additional constraints (like unique constraints or foreign key references). The TypeScript field overwriting behavior is deliberately used to override base field definitions with more specific requirements.
packages/db/src/schema/deployment-variables.ts (4)
Learnt from: adityachoudhari26
PR: ctrlplanedev/ctrlplane#561
File: packages/db/drizzle/0100_robust_eternals.sql:2-2
Timestamp: 2025-05-11T17:51:40.365Z
Learning: The deployment_variable_value table needs to support multiple records with null values for the same variable_id, which is why a unique index with COALESCE would be problematic as it would treat all nulls as equal.
Learnt from: adityachoudhari26
PR: ctrlplanedev/ctrlplane#237
File: apps/webservice/src/app/[workspaceSlug]/(app)/_components/deployment-resource-drawer/DeploymentResourceDrawer.tsx:43-50
Timestamp: 2024-11-27T23:16:35.580Z
Learning: In `DeploymentResourceDrawer.tsx`, the `isOpen` variable already checks whether `deploymentId`, `environmentId`, and `resourceId` are non-null, so additional null checks in query `enabled` conditions are not necessary.
Learnt from: adityachoudhari26
PR: ctrlplanedev/ctrlplane#579
File: packages/db/src/schema/rules/concurrency.ts:0-0
Timestamp: 2025-06-01T19:10:11.535Z
Learning: In the ctrlplane codebase, when defining database schemas with Drizzle ORM, it's an intentional pattern to spread base fields (like `basePolicyRuleFields`) and then redefine specific fields to add additional constraints (like unique constraints or foreign key references). The TypeScript field overwriting behavior is deliberately used to override base field definitions with more specific requirements.
Learnt from: adityachoudhari26
PR: ctrlplanedev/ctrlplane#181
File: packages/api/src/router/deployment.ts:116-131
Timestamp: 2024-10-29T02:04:50.312Z
Learning: In `packages/api/src/router/deployment.ts`, the `list.byDeploymentId` procedure requires multiple database queries due to limitations of the `releaseMatchesCondition` function.
packages/rule-engine/src/manager/variables/db-variable-providers.ts (8)
Learnt from: adityachoudhari26
PR: ctrlplanedev/ctrlplane#181
File: packages/api/src/router/deployment.ts:116-131
Timestamp: 2024-10-29T02:04:50.312Z
Learning: In `packages/api/src/router/deployment.ts`, the `list.byDeploymentId` procedure requires multiple database queries due to limitations of the `releaseMatchesCondition` function.
Learnt from: adityachoudhari26
PR: ctrlplanedev/ctrlplane#237
File: apps/webservice/src/app/[workspaceSlug]/(app)/_components/deployment-resource-drawer/DeploymentResourceDrawer.tsx:43-50
Timestamp: 2024-11-27T23:16:35.580Z
Learning: In `DeploymentResourceDrawer.tsx`, the `isOpen` variable already checks whether `deploymentId`, `environmentId`, and `resourceId` are non-null, so additional null checks in query `enabled` conditions are not necessary.
Learnt from: adityachoudhari26
PR: ctrlplanedev/ctrlplane#604
File: packages/rule-engine/src/manager/version-manager.ts:124-139
Timestamp: 2025-06-30T21:19:43.866Z
Learning: In packages/rule-engine/src/manager/version-manager.ts, the findDesiredVersion method should use takeFirst (not takeFirstOrNull) because if a desiredVersionId is set but the query fails to find exactly one matching version, it indicates a data integrity or configuration issue that should fail loudly rather than be handled silently.
Learnt from: adityachoudhari26
PR: ctrlplanedev/ctrlplane#601
File: packages/job-dispatch/src/job-update.ts:264-270
Timestamp: 2025-06-24T23:56:54.799Z
Learning: In this codebase, the `Tx` type is just an alias for the database client type (`Omit<typeof db, "$client">`) and does not necessarily indicate an active transaction context. Functions like `createReleaseJob` need to be called within a transaction, which is why they are wrapped with `db.transaction()` even when the parameter is typed as `Tx`. Drizzle supports nested transactions via breakpoints, so additional transaction wrappers are safe even if already within a transaction.
Learnt from: adityachoudhari26
PR: ctrlplanedev/ctrlplane#181
File: packages/auth/src/utils/rbac.ts:102-118
Timestamp: 2024-10-29T02:05:46.185Z
Learning: The `releaseChannel` scope type is included in the `scopeType` enum in `packages/db/src/schema/rbac.ts`.
Learnt from: adityachoudhari26
PR: ctrlplanedev/ctrlplane#188
File: packages/api/src/router/deployment.ts:144-161
Timestamp: 2024-11-01T02:37:25.510Z
Learning: In `packages/api/src/router/deployment.ts`, when using Drizzle ORM, there is a limitation when referencing the same table twice in a relational builder query (rbq), requiring separate queries to avoid issues.
Learnt from: adityachoudhari26
PR: ctrlplanedev/ctrlplane#579
File: packages/db/src/schema/rules/concurrency.ts:0-0
Timestamp: 2025-06-01T19:10:11.535Z
Learning: In the ctrlplane codebase, when defining database schemas with Drizzle ORM, it's an intentional pattern to spread base fields (like `basePolicyRuleFields`) and then redefine specific fields to add additional constraints (like unique constraints or foreign key references). The TypeScript field overwriting behavior is deliberately used to override base field definitions with more specific requirements.
Learnt from: adityachoudhari26
PR: ctrlplanedev/ctrlplane#561
File: packages/db/drizzle/0100_robust_eternals.sql:2-2
Timestamp: 2025-05-11T17:51:40.365Z
Learning: The deployment_variable_value table needs to support multiple records with null values for the same variable_id, which is why a unique index with COALESCE would be problematic as it would treat all nulls as equal.
packages/db/src/utils/deployment-variables/get-deployment-variables.ts (7)
Learnt from: adityachoudhari26
PR: ctrlplanedev/ctrlplane#181
File: packages/api/src/router/deployment.ts:116-131
Timestamp: 2024-10-29T02:04:50.312Z
Learning: In `packages/api/src/router/deployment.ts`, the `list.byDeploymentId` procedure requires multiple database queries due to limitations of the `releaseMatchesCondition` function.
Learnt from: adityachoudhari26
PR: ctrlplanedev/ctrlplane#237
File: apps/webservice/src/app/[workspaceSlug]/(app)/_components/deployment-resource-drawer/DeploymentResourceDrawer.tsx:43-50
Timestamp: 2024-11-27T23:16:35.580Z
Learning: In `DeploymentResourceDrawer.tsx`, the `isOpen` variable already checks whether `deploymentId`, `environmentId`, and `resourceId` are non-null, so additional null checks in query `enabled` conditions are not necessary.
Learnt from: adityachoudhari26
PR: ctrlplanedev/ctrlplane#187
File: apps/jobs/src/ephemeral-env-checker/index.ts:57-0
Timestamp: 2024-10-30T23:10:58.869Z
Learning: In the codebase, deployments are decoupled from environments. When deleting environments (e.g., in `apps/jobs/src/ephemeral-env-checker/index.ts`), associated deployments should not be deleted.
Learnt from: adityachoudhari26
PR: ctrlplanedev/ctrlplane#515
File: apps/webservice/src/app/api/v1/release-targets/[releaseTargetId]/releases/route.ts:103-108
Timestamp: 2025-04-28T18:41:58.813Z
Learning: In this project, full records from the `deployment` and `deployment_version` tables are considered safe for public API consumption, and there's no need to create restricted DTOs for them.
Learnt from: adityachoudhari26
PR: ctrlplanedev/ctrlplane#601
File: packages/job-dispatch/src/job-update.ts:264-270
Timestamp: 2025-06-24T23:56:54.799Z
Learning: In this codebase, the `Tx` type is just an alias for the database client type (`Omit<typeof db, "$client">`) and does not necessarily indicate an active transaction context. Functions like `createReleaseJob` need to be called within a transaction, which is why they are wrapped with `db.transaction()` even when the parameter is typed as `Tx`. Drizzle supports nested transactions via breakpoints, so additional transaction wrappers are safe even if already within a transaction.
Learnt from: adityachoudhari26
PR: ctrlplanedev/ctrlplane#188
File: packages/api/src/router/deployment.ts:144-161
Timestamp: 2024-11-01T02:37:25.510Z
Learning: In `packages/api/src/router/deployment.ts`, when using Drizzle ORM, there is a limitation when referencing the same table twice in a relational builder query (rbq), requiring separate queries to avoid issues.
Learnt from: zacharyblasczyk
PR: ctrlplanedev/ctrlplane#382
File: apps/webservice/src/app/api/v1/deployments/[deploymentId]/route.ts:82-88
Timestamp: 2025-03-16T19:41:44.129Z
Learning: In Next.js 15, dynamic route parameters (params) return Promises instead of direct values in async contexts. When accessing properties like `params.deploymentId` in an async function, use `(await params).deploymentId` to avoid the "params should be awaited before using its properties" error. This applies to API routes, page components, and other async contexts.
packages/api/src/router/deployment-variable/by-deployment-id.ts (12)
Learnt from: adityachoudhari26
PR: ctrlplanedev/ctrlplane#181
File: packages/api/src/router/deployment.ts:116-131
Timestamp: 2024-10-29T02:04:50.312Z
Learning: In `packages/api/src/router/deployment.ts`, the `list.byDeploymentId` procedure requires multiple database queries due to limitations of the `releaseMatchesCondition` function.
Learnt from: adityachoudhari26
PR: ctrlplanedev/ctrlplane#237
File: apps/webservice/src/app/[workspaceSlug]/(app)/_components/deployment-resource-drawer/DeploymentResourceDrawer.tsx:43-50
Timestamp: 2024-11-27T23:16:35.580Z
Learning: In `DeploymentResourceDrawer.tsx`, the `isOpen` variable already checks whether `deploymentId`, `environmentId`, and `resourceId` are non-null, so additional null checks in query `enabled` conditions are not necessary.
Learnt from: adityachoudhari26
PR: ctrlplanedev/ctrlplane#187
File: apps/jobs/src/ephemeral-env-checker/index.ts:57-0
Timestamp: 2024-10-30T23:10:58.869Z
Learning: In the codebase, deployments are decoupled from environments. When deleting environments (e.g., in `apps/jobs/src/ephemeral-env-checker/index.ts`), associated deployments should not be deleted.
Learnt from: adityachoudhari26
PR: ctrlplanedev/ctrlplane#188
File: packages/api/src/router/deployment.ts:144-161
Timestamp: 2024-11-01T02:37:25.510Z
Learning: In `packages/api/src/router/deployment.ts`, when using Drizzle ORM, there is a limitation when referencing the same table twice in a relational builder query (rbq), requiring separate queries to avoid issues.
Learnt from: zacharyblasczyk
PR: ctrlplanedev/ctrlplane#382
File: apps/webservice/src/app/api/v1/deployments/[deploymentId]/route.ts:82-88
Timestamp: 2025-03-16T19:41:44.129Z
Learning: In Next.js 15, dynamic route parameters (params) return Promises instead of direct values in async contexts. When accessing properties like `params.deploymentId` in an async function, use `(await params).deploymentId` to avoid the "params should be awaited before using its properties" error. This applies to API routes, page components, and other async contexts.
Learnt from: adityachoudhari26
PR: ctrlplanedev/ctrlplane#237
File: packages/api/src/router/job.ts:362-365
Timestamp: 2024-11-27T23:18:42.055Z
Learning: In the file `packages/api/src/router/job.ts`, the function `releaseMatchesCondition` returns undefined if the `filter` parameter is null. This behavior ensures that when constructing the query with `and(...)`, the condition is omitted, allowing the query to function correctly even if there is no release channel associated with the environment.
Learnt from: adityachoudhari26
PR: ctrlplanedev/ctrlplane#515
File: apps/webservice/src/app/api/v1/release-targets/[releaseTargetId]/releases/route.ts:103-108
Timestamp: 2025-04-28T18:41:58.813Z
Learning: In this project, full records from the `deployment` and `deployment_version` tables are considered safe for public API consumption, and there's no need to create restricted DTOs for them.
Learnt from: adityachoudhari26
PR: ctrlplanedev/ctrlplane#601
File: packages/job-dispatch/src/job-update.ts:264-270
Timestamp: 2025-06-24T23:56:54.799Z
Learning: In this codebase, the `Tx` type is just an alias for the database client type (`Omit<typeof db, "$client">`) and does not necessarily indicate an active transaction context. Functions like `createReleaseJob` need to be called within a transaction, which is why they are wrapped with `db.transaction()` even when the parameter is typed as `Tx`. Drizzle supports nested transactions via breakpoints, so additional transaction wrappers are safe even if already within a transaction.
Learnt from: adityachoudhari26
PR: ctrlplanedev/ctrlplane#579
File: packages/db/src/schema/rules/concurrency.ts:0-0
Timestamp: 2025-06-01T19:10:11.535Z
Learning: In the ctrlplane codebase, when defining database schemas with Drizzle ORM, it's an intentional pattern to spread base fields (like `basePolicyRuleFields`) and then redefine specific fields to add additional constraints (like unique constraints or foreign key references). The TypeScript field overwriting behavior is deliberately used to override base field definitions with more specific requirements.
Learnt from: adityachoudhari26
PR: ctrlplanedev/ctrlplane#579
File: packages/rule-engine/src/rules/concurrency-rule.ts:8-11
Timestamp: 2025-06-01T19:10:47.122Z
Learning: In packages/rule-engine/src/rules/concurrency-rule.ts, the ConcurrencyRule should remain simple without additional validation since database and Zod schemas already handle concurrency validation. The user prefers this rule to be "dumb" and just perform the comparison check rather than duplicating validation logic.
Learnt from: adityachoudhari26
PR: ctrlplanedev/ctrlplane#515
File: apps/event-worker/src/workers/compute-systems-release-targets.ts:86-110
Timestamp: 2025-04-28T18:38:21.163Z
Learning: In SQL queries that use `inArray()` with arrays like `deploymentIds` or `environmentIds`, if these arrays are empty, it will generate an invalid `IN ()` clause that PostgreSQL rejects. Adding condition checks (e.g., `if (array.length > 0)`) before executing such queries prevents SQL syntax errors.
Learnt from: adityachoudhari26
PR: ctrlplanedev/ctrlplane#181
File: packages/auth/src/utils/rbac.ts:102-118
Timestamp: 2024-10-29T02:05:46.185Z
Learning: The `releaseChannel` scope type is included in the `scopeType` enum in `packages/db/src/schema/rbac.ts`.
🧬 Code Graph Analysis (5)
e2e/tests/api/resource-variables.spec.ts (3)
e2e/tests/fixtures.ts (1)
  • test (11-26)
packages/db/src/schema/workspace.ts (1)
  • workspace (18-27)
packages/db/src/schema/release.ts (1)
  • releaseTarget (21-47)
packages/rule-engine/src/manager/variables/resolve-variable-value.ts (7)
packages/secrets/src/index.ts (1)
  • variablesAES256 (50-51)
packages/db/src/common.ts (1)
  • Tx (22-22)
packages/validators/src/resources/conditions/resource-condition.ts (1)
  • ResourceCondition (29-39)
packages/db/src/selectors/index.ts (1)
  • selector (13-13)
packages/db/src/schema/deployment-variables.ts (1)
  • DeploymentVariableValue (172-174)
packages/rule-engine/src/manager/variables/db-variable-providers.ts (1)
  • isSelectingResource (75-86)
packages/rule-engine/src/manager/variables/resolve-reference-variable.ts (1)
  • getReferenceVariableValue (8-29)
apps/webservice/src/app/api/v1/deployments/[deploymentId]/variables/route.ts (2)
packages/db/src/schema/deployment-variables.ts (1)
  • DeploymentVariableValue (172-174)
packages/rule-engine/src/manager/variables/resolve-variable-value.ts (1)
  • getResolvedDirectValue (10-20)
packages/rule-engine/src/manager/variables/db-variable-providers.ts (2)
packages/db/src/schema/deployment-variables.ts (1)
  • DeploymentVariableValue (172-174)
packages/rule-engine/src/manager/variables/resolve-variable-value.ts (1)
  • resolveVariableValue (46-75)
packages/db/src/utils/deployment-variables/get-deployment-variables.ts (2)
packages/db/src/schema/deployment-variables.ts (2)
  • DeploymentVariableValue (172-174)
  • DeploymentVariable (52-52)
packages/db/src/common.ts (1)
  • Tx (22-22)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (5)
  • GitHub Check: Typecheck
  • GitHub Check: Lint
  • GitHub Check: build (linux/amd64)
  • GitHub Check: build (linux/amd64)
  • GitHub Check: build (linux/amd64)
🔇 Additional comments (30)
packages/rule-engine/package.json (1)

29-29: LGTM! Dependency addition aligns with new encryption functionality.

The addition of @ctrlplane/secrets dependency is justified for the new variable resolution functionality that handles encryption/decryption of sensitive values.

packages/db/drizzle/meta/_journal.json (1)

887-893: LGTM! Standard migration journal entry.

The migration journal entry follows the correct format and structure for tracking the priority column addition.

packages/db/drizzle/0126_wandering_sasquatch.sql (1)

1-1: LGTM! Safe migration with appropriate defaults.

The migration correctly adds the priority column with a sensible default value (0) and NOT NULL constraint, ensuring existing records remain valid.

apps/webservice/src/app/[workspaceSlug]/(app)/(deploy)/(raw)/systems/[systemSlug]/(raw)/deployments/[deploymentSlug]/(sidebar)/variables/page.tsx (1)

37-37: LGTM! Simplification aligns with backend refactoring.

The removal of client-side variable transformation is appropriate given the backend now handles value resolution and prioritization. This improves maintainability by centralizing the logic.

packages/db/src/utils/deployment-variables/upsert-reference-value.ts (2)

42-42: LGTM! Correct priority handling in insert operation.

The priority field is properly included in the insert values, maintaining consistency with the schema changes.


68-71: LGTM! Consistent priority handling in update operation.

The priority field is correctly included in the update set clause alongside the resourceSelector, ensuring both insert and update operations handle the new field consistently.

packages/rule-engine/src/manager/variables/index.ts (1)

3-3: LGTM! Clean addition following established patterns.

The new export follows the existing module pattern and aligns with the broader refactoring to unify variable value resolution.

packages/db/src/utils/deployment-variables/upsert-direct-value.ts (2)

66-66: LGTM! Priority field properly added to insert operation.

The addition of the priority field to the insert values is correct and maintains consistency with the schema changes.


97-100: LGTM! Priority field properly added to update operation.

The update operation correctly includes both resourceSelector and priority fields, maintaining consistency between insert and update operations for direct variable values.

e2e/api/schema.ts (1)

1070-1074: LGTM! Schema changes align with priority-based variable resolution feature.

The addition of the optional priority field and making resourceSelector optional are semantically correct for the deployment variable value enhancement. These changes properly support the new priority-based resolution while maintaining backward compatibility.

Since this is an auto-generated file, these changes appropriately reflect updates to the underlying OpenAPI specification.

packages/db/src/schema/deployment-variables.ts (4)

9-9: LGTM: Import addition for priority field.

The integer import is correctly added to support the new priority column definition.


65-65: LGTM: Priority column definition is well-structured.

The priority field is properly defined as a non-null integer with a sensible default of 0, ensuring backwards compatibility with existing records.


103-103: LGTM: Consistent priority validation for direct values.

The priority field is correctly added to the validation schema with an optional number type and default of 0, maintaining consistency with the database schema.


149-149: LGTM: Consistent priority validation for reference values.

The priority field definition matches the direct values schema, ensuring consistent validation across both value types.

e2e/tests/api/resource-variables.spec.ts (1)

580-698: LGTM: Comprehensive test for priority-based resolution.

This test effectively validates the priority-based tie-breaking functionality by:

  1. Creating a resource with a unique identifier
  2. Setting up two deployment variable values with different priorities (1 and 2) that both match the resource
  3. Creating a deployment version and waiting for propagation
  4. Verifying that the higher priority value (priority 2) is resolved

The test follows the established patterns in the file and provides good coverage for the new priority feature. The use of random identifiers ensures test isolation.

packages/rule-engine/src/manager/variables/resolve-variable-value.ts (3)

10-20: LGTM: Well-structured decryption logic for sensitive values.

The getResolvedDirectValue function correctly handles both sensitive and non-sensitive values:

  • Returns values as-is when not sensitive
  • Properly converts objects to JSON strings before decryption
  • Uses the established variablesAES256() service for decryption

The type annotation accurately reflects the expected input structure.


22-37: LGTM: Resource selector evaluation is implemented correctly.

The getIsSelectingResource function properly:

  • Returns false for null selectors (no filtering)
  • Uses the established selector() query builder pattern
  • Combines resource ID equality with selector conditions using and()
  • Returns boolean based on whether a matching resource is found

This aligns with the existing patterns seen in packages/rule-engine/src/manager/variables/db-variable-providers.ts.


39-75: LGTM: Main resolution function handles all scenarios correctly.

The resolveVariableValue function is well-designed:

  1. Default handling: Bypasses resource selector evaluation when isDefault=true
  2. Early return: Returns null when resource selector doesn't match
  3. Type discrimination: Uses schema type guards to handle direct vs reference values
  4. Consistent return structure: Both paths return {value, sensitive} objects
  5. Reference resolution: Delegates to the existing getReferenceVariableValue function
  6. Security: Marks reference values as non-sensitive (line 73)

The JSDoc comment clearly documents the function's purpose and return behavior.

apps/webservice/src/app/api/v1/deployments/[deploymentId]/variables/route.ts (3)

15-15: LGTM: Import moved to correct location.

The getResolvedDirectValue import is correctly moved from @ctrlplane/db to @ctrlplane/rule-engine, reflecting the new centralized location of the resolution logic.


27-34: LGTM: Well-structured helper for default value formatting.

The formatDefaultValue function correctly:

  • Handles undefined values gracefully
  • Returns reference values as-is (no resolution needed in this context)
  • Applies getResolvedDirectValue only to direct values
  • Maintains the original object structure while adding the resolved value

This helper promotes code reuse and maintains consistency.


61-85: LGTM: Value separation and formatting logic is well-implemented.

The refactored logic correctly:

  1. Separates values: Uses schema type guards to filter direct vs reference values
  2. Resolves direct values: Applies getResolvedDirectValue to decrypt sensitive values
  3. Adds default flags: Compares each value's ID to the default value ID
  4. Maintains structure: Preserves all original fields while adding resolved values and flags
  5. Handles both types: Applies similar processing to both direct and reference values

The destructuring of { values, defaultValue, ...rest } cleanly separates the new unified values array from other variable properties.

packages/api/src/router/deployment-variable/by-deployment-id.ts (4)

2-2: LGTM: Added utility import for filtering.

The isPresent import from ts-is-present is correctly added to support filtering out null values from the resolution promises.


5-7: LGTM: Import updates reflect the new unified approach.

The imports are correctly updated:

  • Removed unused utilities that are no longer needed
  • Added resolveVariableValue from @ctrlplane/rule-engine which centralizes the resolution logic
  • Simplified the import from @ctrlplane/db by removing no longer needed functions

This reflects the consolidation of variable resolution logic into the rule engine package.


22-43: LGTM: Simplified resource matching using unified resolution.

The refactored getVariableValueWithMatchedResources function is much cleaner:

  1. Unified approach: Uses resolveVariableValue for all variable types instead of separate logic
  2. Async mapping: Efficiently processes all resources in parallel
  3. Proper filtering: Uses isPresent to filter out null results from unmatched resources
  4. Security handling: Masks sensitive values with "***"
  5. Default support: Accepts isDefault parameter to handle default value resolution

The function maintains the same return structure while significantly simplifying the implementation.


52-76: LGTM: Clean consolidation of values handling.

The updated getVariableWithMatchedResources function effectively:

  1. Unified values: Uses the single values array instead of separate directValues and referenceValues
  2. Consistent processing: Applies the same resolution logic to all values regardless of type
  3. Resource tracking: Properly identifies matched vs unmatched resources
  4. Default handling: Resolves default values for unmatched resources with the isDefault=true flag

This consolidation simplifies the code while maintaining full functionality and aligns with the broader refactoring to unify variable value handling.

packages/db/src/utils/deployment-variables/get-deployment-variables.ts (3)

7-15: Type definition looks good!

The VariableValueDbResult type correctly represents the structure expected from the left join query with nullable direct and reference values.


35-62: Well-structured unified query!

The function correctly:

  • Uses left joins to fetch both direct and reference values in a single query
  • Orders by descending priority for proper resolution order
  • Filters out null results cleanly with isPresent

74-76: Clean implementation of unified values!

The refactoring to use a single values array and finding the default value by ID is well implemented.

packages/rule-engine/src/manager/variables/db-variable-providers.ts (2)

105-134: Well-implemented priority-based resolution!

The refactored resolution logic:

  • Correctly iterates through priority-ordered values
  • Consistently uses resolveVariableValue for both regular and default values
  • Properly handles the fallback case when no value resolves

53-58: defaultValue optional handling is correct

The database defaultValueId column is nullable (e.g., in the OpenAPI route we see if (defaultValueId == null) return undefined), and the UI schema marks defaultValueId as nullable as well. Mapping nullundefined aligns with the new defaultValue?: schema.DeploymentVariableValue type, so there are no cases where a missing default would break. No further changes needed.

Copy link
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: 0

🧹 Nitpick comments (1)
apps/webservice/src/app/[workspaceSlug]/(app)/(deploy)/(raw)/systems/[systemSlug]/(raw)/deployments/[deploymentSlug]/(sidebar)/variables/_components/direct-value/CreateDirectValueDialog.tsx (1)

162-203: Consider improving number input validation and UX.

The PriorityFormField implementation follows the established patterns well, but there are a few areas for improvement:

  1. Input constraints: The number input lacks min/max constraints that would align with the backend validation (0-1000 based on the AI summary).
  2. Placeholder/default behavior: When the input is empty, it shows no visual indication of the expected range.
  3. Input width: The fixed w-16 class might be too narrow for 4-digit numbers.

Consider this improved implementation:

            <Input
              type="number"
+             min={0}
+             max={1000}
+             placeholder="0"
              value={value}
              onChange={(e) =>
                onChange(
                  Number.isNaN(e.target.valueAsNumber)
                    ? undefined
                    : e.target.valueAsNumber,
                )
              }
-             className="w-16"
+             className="w-20"
            />

Also consider updating the tooltip to mention the valid range:

                  <TooltipContent className="text-muted-foreground">
-                   Higher numbers take precedence when multiple values select
-                   the same resource.
+                   Higher numbers take precedence when multiple values select
+                   the same resource. Valid range: 0-1000.
                  </TooltipContent>
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 63fdb80 and 3ba1926.

📒 Files selected for processing (3)
  • apps/webservice/src/app/[workspaceSlug]/(app)/(deploy)/(raw)/systems/[systemSlug]/(raw)/deployments/[deploymentSlug]/(sidebar)/variables/_components/direct-value/CreateDirectValueDialog.tsx (2 hunks)
  • packages/api/src/router/deployment-variable/by-deployment-id.ts (3 hunks)
  • packages/db/src/schema/deployment-variables.ts (4 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • packages/db/src/schema/deployment-variables.ts
  • packages/api/src/router/deployment-variable/by-deployment-id.ts
🧰 Additional context used
📓 Path-based instructions (3)
**/*.{ts,tsx}

Instructions used from:

Sources:
📄 CodeRabbit Inference Engine

  • CLAUDE.md

⚙️ CodeRabbit Configuration File

**/*.{js,jsx,ts,tsx}

Instructions used from:

Sources:
📄 CodeRabbit Inference Engine

  • CLAUDE.md
**/*.{js,jsx,ts,tsx,json,css,md,yml,yaml}

Instructions used from:

Sources:
📄 CodeRabbit Inference Engine

  • CLAUDE.md
🧠 Learnings (2)
📓 Common learnings
Learnt from: adityachoudhari26
PR: ctrlplanedev/ctrlplane#561
File: packages/db/drizzle/0100_robust_eternals.sql:2-2
Timestamp: 2025-05-11T17:51:40.365Z
Learning: The deployment_variable_value table needs to support multiple records with null values for the same variable_id, which is why a unique index with COALESCE would be problematic as it would treat all nulls as equal.
Learnt from: adityachoudhari26
PR: ctrlplanedev/ctrlplane#601
File: e2e/tests/api/policies/retry-policy.spec.ts:23-24
Timestamp: 2025-06-24T23:52:50.732Z
Learning: The user adityachoudhari26 prefers not to add null safety checks or defensive programming in test code, particularly in e2e tests, as they prioritize simplicity and focus on the main functionality being tested rather than comprehensive error handling within the test itself.
Learnt from: adityachoudhari26
PR: ctrlplanedev/ctrlplane#601
File: e2e/tests/api/policies/retry-policy.spec.ts:117-130
Timestamp: 2025-06-24T23:53:25.398Z
Learning: User adityachoudhari26 prefers to keep non-null assertions in e2e test code without extensive null safety checks, reasoning that test failures serve the same purpose of catching issues and the extra validation doesn't add much value in test contexts.
apps/webservice/src/app/[workspaceSlug]/(app)/(deploy)/(raw)/systems/[systemSlug]/(raw)/deployments/[deploymentSlug]/(sidebar)/variables/_components/direct-value/CreateDirectValueDialog.tsx (6)
Learnt from: adityachoudhari26
PR: ctrlplanedev/ctrlplane#183
File: apps/webservice/src/app/[workspaceSlug]/_components/environment-drawer/Overview.tsx:46-57
Timestamp: 2024-10-30T00:03:57.878Z
Learning: Accessibility and validation feedback improvements are not desired for form fields in the `Overview` component within `apps/webservice/src/app/[workspaceSlug]/_components/environment-drawer/Overview.tsx`.
Learnt from: zacharyblasczyk
PR: ctrlplanedev/ctrlplane#408
File: apps/webservice/src/components/form/job-agent/JobAgentJenkinsPipelineConfig.tsx:26-31
Timestamp: 2025-04-12T22:08:13.790Z
Learning: For Jenkins job configuration, two approaches are needed: (1) a simple URL input form for airgapped environments (current focus) and (2) a dropdown selection interface for non-airgapped environments where the Jenkins server is accessible. A component similar to DeploymentJobAgentGithubConfig.tsx is preferred.
Learnt from: zacharyblasczyk
PR: ctrlplanedev/ctrlplane#408
File: apps/webservice/src/components/form/job-agent/JobAgentJenkinsPipelineConfig.tsx:26-31
Timestamp: 2025-04-12T22:08:13.790Z
Learning: For Jenkins job configuration, two approaches are needed: (1) a simple URL input form for airgapped environments (current focus) and (2) a dropdown selection interface for non-airgapped environments where the Jenkins server is accessible. A component similar to DeploymentJobAgentGithubConfig.tsx is preferred.
Learnt from: adityachoudhari26
PR: ctrlplanedev/ctrlplane#237
File: apps/webservice/src/app/[workspaceSlug]/(app)/_components/deployment-resource-drawer/DeploymentResourceDrawer.tsx:43-50
Timestamp: 2024-11-27T23:16:35.580Z
Learning: In `DeploymentResourceDrawer.tsx`, the `isOpen` variable already checks whether `deploymentId`, `environmentId`, and `resourceId` are non-null, so additional null checks in query `enabled` conditions are not necessary.
Learnt from: adityachoudhari26
PR: ctrlplanedev/ctrlplane#188
File: apps/webservice/src/app/[workspaceSlug]/_components/release-channel-drawer/Usage.tsx:42-44
Timestamp: 2024-11-01T02:35:07.352Z
Learning: In `apps/webservice/src/app/[workspaceSlug]/_components/release-channel-drawer/Usage.tsx`, within the `Usage` component, the arrays used for filtering inherited environments are expected to remain small. Therefore, performance optimizations for this filtering logic are not necessary.
Learnt from: adityachoudhari26
PR: ctrlplanedev/ctrlplane#578
File: apps/webservice/src/app/[workspaceSlug]/(app)/resources/(sidebar)/providers/integrations/github/GithubDialog.tsx:58-58
Timestamp: 2025-05-30T21:48:48.868Z
Learning: In the ctrlplane codebase, the shadcn form UI version allows initializing forms with `useForm({ schema: formSchema })` directly, without needing to import and use `zodResolver` from '@hookform/resolvers/zod'. This is different from standard react-hook-form usage.
🧬 Code Graph Analysis (1)
apps/webservice/src/app/[workspaceSlug]/(app)/(deploy)/(raw)/systems/[systemSlug]/(raw)/deployments/[deploymentSlug]/(sidebar)/variables/_components/direct-value/CreateDirectValueDialog.tsx (3)
packages/ui/src/form.tsx (4)
  • FormField (220-220)
  • FormItem (215-215)
  • FormControl (217-217)
  • FormLabel (216-216)
packages/ui/src/tooltip.tsx (4)
  • TooltipProvider (30-30)
  • Tooltip (30-30)
  • TooltipTrigger (30-30)
  • TooltipContent (30-30)
packages/ui/src/input.tsx (1)
  • Input (24-24)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (5)
  • GitHub Check: Typecheck
  • GitHub Check: Lint
  • GitHub Check: build (linux/amd64)
  • GitHub Check: build (linux/amd64)
  • GitHub Check: build (linux/amd64)
🔇 Additional comments (1)
apps/webservice/src/app/[workspaceSlug]/(app)/(deploy)/(raw)/systems/[systemSlug]/(raw)/deployments/[deploymentSlug]/(sidebar)/variables/_components/direct-value/CreateDirectValueDialog.tsx (1)

275-275: Well-positioned form field integration.

The PriorityFormField is appropriately positioned in the form flow - after the value configuration fields (Default, Sensitive) and before the resource selector, which makes logical sense from a UX perspective.

@adityachoudhari26 adityachoudhari26 merged commit 73883ed into main Jul 12, 2025
10 checks passed
@adityachoudhari26 adityachoudhari26 deleted the deployment-variable-value-priority branch July 12, 2025 20:42
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