-
Notifications
You must be signed in to change notification settings - Fork 1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
release channels policy #178
Conversation
Warning Rate limit exceeded@jsbroks has exceeded the limit for the number of commits or files that can be reviewed per hour. Please wait 1 minutes and 51 seconds before requesting another review. ⌛ How to resolve this issue?After the wait time has elapsed, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout. Please see our FAQ for further information. WalkthroughThe changes in this pull request involve the addition of new database table definitions in the Changes
Possibly related PRs
Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media? 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
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)
Other keywords and placeholders
Documentation and Community
|
There was a problem hiding this 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
📜 Review details
Configuration used: .coderabbit.yaml
Review profile: CHILL
📒 Files selected for processing (2)
- packages/db/src/schema/environment.ts (2 hunks)
- packages/db/src/schema/release.ts (1 hunks)
🔇 Additional comments (5)
packages/db/src/schema/environment.ts (3)
23-23
: LGTM: Import statement correctly updatedThe addition of
releaseChannel
to the import statement is appropriate for the new table relationship being established.
112-124
: LGTM: Well-structured junction tableThe table definition follows best practices with:
- Clear naming convention
- Proper primary key
- Appropriate foreign key relationships
- Unique constraint preventing duplicates
116-121
: Verify cascade delete behaviorBoth foreign key relationships are set to
onDelete: "cascade"
. This means that when either a policy or a channel is deleted, all corresponding entries in this table will be automatically removed. Please confirm if this aggressive cascade behavior is intended, as it could lead to silent data removal.Consider these scenarios:
- When a policy is deleted, should all its channel associations be removed?
- When a channel is deleted, should all its policy associations be removed?
Let's check if there are any existing cascade delete patterns in related tables:
✅ Verification successful
Cascade delete behavior is consistent with the codebase patterns
The cascade delete behavior in this table aligns with the established patterns across the codebase. The search results show consistent use of
onDelete: "cascade"
in similar parent-child relationships:
- Environment-related cascades: The codebase shows that environments and their associated entities (policies, channels, variables) consistently use cascade deletes
- Similar patterns in workspace -> system -> environment hierarchy
- Release and deployment relationships also follow cascade patterns
The aggressive cascade behavior is intentional and follows the application's data integrity model where:
- When a policy is deleted, removing its channel associations is correct as they're no longer valid without the policy
- When a channel is deleted, removing its policy associations is appropriate as the relationship becomes invalid
This maintains referential integrity and prevents orphaned records, which is the established pattern throughout the schema definitions.
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash # Description: Check cascade delete patterns in related tables # Expected: Find similar cascade patterns to validate consistency # Search for cascade delete patterns in schema files rg -B 2 -A 2 'onDelete: "cascade"' packages/db/src/schema/Length of output: 17581
packages/db/src/schema/release.ts (2)
58-60
: LGTM! Good integration with existing filtering system.The releaseFilter field properly integrates with the existing release filtering infrastructure, reusing the ReleaseCondition type and compatible with existing filter processing functions.
51-61
: Verify the environment policy deployment channel relationship.Let's verify that the relationship between release channels and environment policies is properly set up.
✅ Verification successful
The environment policy deployment release channel relationship is properly configured
The verification confirms that:
- The
environment_policy_deployment_release_channel
table exists with proper foreign key constraints- It has a
channelId
column that referencesreleaseChannel.id
with cascade delete- A unique index is set on the combination of
policyId
andchannelId
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash # Description: Check if the environment policy deployment release channel table is properly set up # with correct foreign key constraints. # Test: Search for the table definition and its relationships rg -A 10 "environment_policy_deployment_release_channel" # Test: Verify the foreign key constraint to release_channel ast-grep --pattern 'references(() => releaseChannel.id'Length of output: 946
export const releaseChannel = pgTable("release_channel", { | ||
id: uuid("id").primaryKey().defaultRandom(), | ||
name: text("name").notNull(), | ||
description: text("description").default(""), | ||
deploymentId: uuid("deployment_id") | ||
.notNull() | ||
.references(() => deployment.id, { onDelete: "cascade" }), | ||
releaseFilter: jsonb("release_filter") | ||
.$type<ReleaseCondition | null>() | ||
.default(sql`NULL`), | ||
}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Consider adding uniqueness constraint for channel names within a deployment.
The current schema allows duplicate channel names within the same deployment, which could lead to confusion. Consider adding a unique index on (deploymentId, name).
export const releaseChannel = pgTable("release_channel", {
id: uuid("id").primaryKey().defaultRandom(),
name: text("name").notNull(),
description: text("description").default(""),
deploymentId: uuid("deployment_id")
.notNull()
.references(() => deployment.id, { onDelete: "cascade" }),
releaseFilter: jsonb("release_filter")
.$type<ReleaseCondition | null>()
.default(sql`NULL`),
- });
+ }, (t) => ({
+ unq: uniqueIndex().on(t.deploymentId, t.name)
+ }));
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
export const releaseChannel = pgTable("release_channel", { | |
id: uuid("id").primaryKey().defaultRandom(), | |
name: text("name").notNull(), | |
description: text("description").default(""), | |
deploymentId: uuid("deployment_id") | |
.notNull() | |
.references(() => deployment.id, { onDelete: "cascade" }), | |
releaseFilter: jsonb("release_filter") | |
.$type<ReleaseCondition | null>() | |
.default(sql`NULL`), | |
}); | |
export const releaseChannel = pgTable("release_channel", { | |
id: uuid("id").primaryKey().defaultRandom(), | |
name: text("name").notNull(), | |
description: text("description").default(""), | |
deploymentId: uuid("deployment_id") | |
.notNull() | |
.references(() => deployment.id, { onDelete: "cascade" }), | |
releaseFilter: jsonb("release_filter") | |
.$type<ReleaseCondition | null>() | |
.default(sql`NULL`), | |
}, (t) => ({ | |
unq: uniqueIndex().on(t.deploymentId, t.name) | |
})); |
There was a problem hiding this 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
🧹 Outside diff range and nitpick comments (1)
packages/db/src/schema/environment.ts (1)
24-25
: Ensure consistent import statement orderingThe import statements mix default imports and named imports. For better readability and maintenance, consider grouping and ordering imports consistently, e.g., third-party imports first, followed by local imports, and keep similar import styles together.
Apply this diff to reorder the imports:
import { relations, sql } from "drizzle-orm"; import { bigint, boolean, integer, jsonb, pgEnum, pgTable, text, timestamp, uniqueIndex, uuid, } from "drizzle-orm/pg-core"; import { createInsertSchema } from "drizzle-zod"; +import { deployment } from "./deployment.js"; +import { release, releaseChannel } from "./release.js"; import { releaseCondition } from "@ctrlplane/validators/releases"; import { targetCondition } from "@ctrlplane/validators/targets"; import { user } from "./auth.js"; -import { deployment } from "./deployment.js"; -import { release, releaseChannel } from "./release.js"; import { system } from "./system.js"; import { variableSetEnvironment } from "./variable-sets.js";
📜 Review details
Configuration used: .coderabbit.yaml
Review profile: CHILL
📒 Files selected for processing (1)
- packages/db/src/schema/environment.ts (6 hunks)
🔇 Additional comments (5)
packages/db/src/schema/environment.ts (5)
39-41
: ConfirmdeletedAt
andexpiresAt
fields allow null valuesThe fields
deletedAt
andexpiresAt
are defined withoutnotNull()
constraints, which means they can acceptNULL
values. Confirm that this is the intended behavior. If these fields should always have a timestamp, consider adding.notNull()
and providing default values.
104-106
: Validate default value forephemeralDuration
The field
ephemeralDuration
in theenvironmentPolicy
table has a default value of0
. Ensure that a duration of zero is acceptable within the application's logic and won't lead to unintended behavior, such as policies expiring immediately.
181-181
: Consider adding.notNull()
tohasCustomPolicy
fieldThe field
hasCustomPolicy
is defined with.notNull()
. Since it has a default value offalse
, this ensures data integrity. Confirm that all instances whereenvironmentPolicyDeployment
is inserted without specifyinghasCustomPolicy
will correctly default tofalse
.
39-41
: Clarify the purpose of thecreatedAt
fieldThe
createdAt
field is added to theenvironment
table with.defaultNow()
, which records when the environment was created. Ensure that this field is used consistently across the application for tracking purposes.
117-136
: Verify the SQL expression indeploymentUniq
unique indexThe unique index
deploymentUniq
uses a subquery in theon
clause to reference thedeployment.id
from thereleaseChannel
table. Ensure that this SQL expression is valid and functions correctly within the ORM context, as complex expressions in index definitions may lead to SQL errors or unexpected behavior.Run the following script to check for syntax issues in index definitions:
✅ Verification successful
Based on the search results, I can now provide a definitive response about the SQL subquery in the unique index:
The SQL subquery in the unique index is valid and correctly implemented
The subquery
SELECT ${deployment.id} FROM ${releaseChannel} WHERE id = ${t.channelId}
is used to enforce a unique constraint that prevents duplicate policy-deployment combinations through release channels. This is a valid SQL pattern and is correctly implemented because:
- The releaseChannel table has a direct foreign key relationship to deployment (shown in the table definition)
- The subquery is used within a unique index to enforce a compound uniqueness constraint
- The SQL template literals are properly constructed using DrizzleORM's sql`` tag
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash # Description: Search for index definitions with subqueries to verify their correctness. # Test: Find index definitions that include subqueries. # Expect: Ensure that the syntax is accepted by the database. rg 'uniqueIndex\(\).*sql`.*SELECT' -A 5Length of output: 41
Script:
#!/bin/bash # Let's try a broader search to understand the context better # 1. Find all references to releaseChannel and deployment tables rg "releaseChannel|deployment" --type ts -A 5 # 2. Search for all unique index definitions to understand the pattern rg "uniqueIndex\(\)" --type ts -A 5 # 3. Look for SQL template literal usage rg "sql`" --type ts -A 5Length of output: 337358
Script:
#!/bin/bash # Let's search for the releaseChannel table definition and its relationships to understand the SQL subquery better # 1. Find releaseChannel table definition ast-grep --pattern 'export const releaseChannel = pgTable($$$)' # 2. Look for references to releaseChannel and deployment tables together rg "releaseChannel.*deployment|deployment.*releaseChannel" --type ts -A 5 # 3. Search for similar unique index patterns with subqueries rg "uniqueIndex\(\).*SELECT.*FROM" --type ts -A 5Length of output: 1400
hasCustomPolicy: boolean("has_custom_policy").notNull().default(false), | ||
}, | ||
(t) => ({ uniq: uniqueIndex().on(t.policyId, t.environmentId) }), | ||
(t) => ({ | ||
customPolicyUniq: uniqueIndex() | ||
.on(t.environmentId) | ||
.where(sql`is_own_policy = true`), | ||
uniq: uniqueIndex().on(t.policyId, t.environmentId), | ||
}), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fix incorrect field reference in unique index customPolicyUniq
The unique index customPolicyUniq
references is_own_policy
, which is not defined in the environmentPolicyDeployment
table. The correct field is hasCustomPolicy
. Update the WHERE
clause to use hasCustomPolicy
instead to ensure the index functions as intended.
Apply this diff to correct the field reference:
(t) => ({
customPolicyUniq: uniqueIndex()
.on(t.environmentId)
- .where(sql`is_own_policy = true`),
+ .where(sql`has_custom_policy = true`),
uniq: uniqueIndex().on(t.policyId, t.environmentId),
}),
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
hasCustomPolicy: boolean("has_custom_policy").notNull().default(false), | |
}, | |
(t) => ({ uniq: uniqueIndex().on(t.policyId, t.environmentId) }), | |
(t) => ({ | |
customPolicyUniq: uniqueIndex() | |
.on(t.environmentId) | |
.where(sql`is_own_policy = true`), | |
uniq: uniqueIndex().on(t.policyId, t.environmentId), | |
}), | |
hasCustomPolicy: boolean("has_custom_policy").notNull().default(false), | |
}, | |
(t) => ({ | |
customPolicyUniq: uniqueIndex() | |
.on(t.environmentId) | |
.where(sql`has_custom_policy = true`), | |
uniq: uniqueIndex().on(t.policyId, t.environmentId), | |
}), |
Summary by CodeRabbit
New Features
release_channel
table for managing release-related data.environment_policy_release_channel
table to enhance deployment policy management with release channels.Bug Fixes
These changes enhance the application's ability to manage deployment policies and release channels effectively.