Skip to content
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

fix: Deploy release if it is after latest non-pending #200

Merged
merged 1 commit into from
Nov 4, 2024

Conversation

adityachoudhari26
Copy link
Contributor

@adityachoudhari26 adityachoudhari26 commented Nov 4, 2024

Summary by CodeRabbit

  • New Features
    • Introduced a new policy for release sequencing to enhance job trigger management.
    • Added functionality to check if a release is newer than the last active release.
  • Bug Fixes
    • Improved logic for canceling old release job triggers based on environment policies.
  • Documentation
    • Updated function signatures to reflect new policy checks and enhanced logic for clarity.

Copy link
Contributor

coderabbitai bot commented Nov 4, 2024

Walkthrough

The pull request introduces significant modifications to the release deployment and job dispatching logic within the application. It renames the function isPassingAllPolicies to isPassingAllPoliciesExceptNewerThanLastActive, altering its usage in the context of non-forced releases while maintaining the existing logic for forced releases. New policy functions are added to enhance the handling of release job triggers, particularly focusing on active releases and their statuses. Additionally, improvements are made to SQL queries and job cancellation logic, ensuring a more robust and flexible release management process.

Changes

File Path Change Summary
packages/api/src/router/release-deploy.ts Renamed isPassingAllPolicies to isPassingAllPoliciesExceptNewerThanLastActive in toEnvironment and toTarget.
packages/job-dispatch/src/policies/release-sequencing.ts Added latestActiveReleaseSubQuery and isPassingNewerThanLastActiveReleasePolicy. Replaced eq with ne in a query.
packages/job-dispatch/src/policy-checker.ts Added isPassingAllPoliciesExceptNewerThanLastActive and updated isPassingAllPolicies to include the new policy.
packages/job-dispatch/src/release-sequencing.ts Updated cancelOldReleaseJobTriggersOnJobDispatch function to modify SQL join types and conditions for job cancellation.

Possibly related PRs

Suggested reviewers

  • jsbroks

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?

❤️ 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 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
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

🧹 Outside diff range and nitpick comments (1)
packages/job-dispatch/src/policy-checker.ts (1)

41-43: Consider refactoring to reduce code duplication

The new function largely duplicates code from isPassingAllPolicies. Consider refactoring to extract common logic while maintaining clarity.

Here's a suggested refactor:

+const BASE_POLICY_CHECKS: ReleaseIdPolicyChecker[] = [
+  isPassingLockingPolicy,
+  isPassingApprovalPolicy,
+  isPassingCriteriaPolicy,
+  isPassingConcurrencyPolicy,
+  isPassingReleaseDependencyPolicy,
+  isPassingJobRolloutPolicy,
+  isPassingNoActiveJobsPolicy,
+  isPassingReleaseWindowPolicy,
+];
+
+const applyPolicyChecks = async (
+  db: Tx,
+  releaseJobTriggers: schema.ReleaseJobTrigger[],
+  checks: ReleaseIdPolicyChecker[]
+) => {
+  if (releaseJobTriggers.length === 0) return [];
+  let passingJobs = releaseJobTriggers;
+  for (const check of checks) passingJobs = await check(db, passingJobs);
+  return passingJobs;
+};
+
 export const isPassingAllPolicies = async (
   db: Tx,
   releaseJobTriggers: schema.ReleaseJobTrigger[],
 ) => {
-  if (releaseJobTriggers.length === 0) return [];
-  const checks: ReleaseIdPolicyChecker[] = [
-    isPassingLockingPolicy,
-    isPassingApprovalPolicy,
-    isPassingCriteriaPolicy,
-    isPassingConcurrencyPolicy,
-    isPassingReleaseDependencyPolicy,
-    isPassingJobRolloutPolicy,
-    isPassingNoActiveJobsPolicy,
-    isPassingNewerThanLastActiveReleasePolicy,
-    isPassingReleaseWindowPolicy,
-  ];
-
-  let passingJobs = releaseJobTriggers;
-  for (const check of checks) passingJobs = await check(db, passingJobs);
-
-  return passingJobs;
+  return applyPolicyChecks(db, releaseJobTriggers, [
+    ...BASE_POLICY_CHECKS,
+    isPassingNewerThanLastActiveReleasePolicy,
+  ]);
 };

 export const isPassingAllPoliciesExceptNewerThanLastActive = async (
   db: Tx,
   releaseJobTriggers: schema.ReleaseJobTrigger[],
 ) => {
-  if (releaseJobTriggers.length === 0) return [];
-  const checks: ReleaseIdPolicyChecker[] = [
-    isPassingLockingPolicy,
-    isPassingApprovalPolicy,
-    isPassingCriteriaPolicy,
-    isPassingConcurrencyPolicy,
-    isPassingReleaseDependencyPolicy,
-    isPassingJobRolloutPolicy,
-    isPassingNoActiveJobsPolicy,
-    isPassingReleaseWindowPolicy,
-  ];
-
-  let passingJobs = releaseJobTriggers;
-  for (const check of checks) passingJobs = await check(db, passingJobs);
-
-  return passingJobs;
+  return applyPolicyChecks(db, releaseJobTriggers, BASE_POLICY_CHECKS);
 };

This refactor:

  1. Extracts common policy checks into a constant
  2. Creates a reusable function for applying checks
  3. Reduces duplication while maintaining clear intent
  4. Makes it easier to maintain the list of base policies
📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between f437ae9 and 5eafb4b.

📒 Files selected for processing (4)
  • packages/api/src/router/release-deploy.ts (3 hunks)
  • packages/job-dispatch/src/policies/release-sequencing.ts (2 hunks)
  • packages/job-dispatch/src/policy-checker.ts (1 hunks)
  • packages/job-dispatch/src/release-sequencing.ts (3 hunks)
🔇 Additional comments (11)
packages/job-dispatch/src/policy-checker.ts (2)

11-14: LGTM: Import statements are properly structured

The new imports are correctly added and follow the established conventions.


21-39: Verify the order of policy checks

The order of policy checks is crucial as they are applied sequentially. The new isPassingNewerThanLastActiveReleasePolicy is placed near the end of the chain, just before isPassingReleaseWindowPolicy. Please verify if this ordering is intentional and optimal for performance.

Consider:

  1. More restrictive checks should be placed earlier to fail fast
  2. Computationally expensive checks should be placed later
✅ Verification successful

Based on the code analysis, I can now generate the final response since I have enough information about the policy checks' implementations.

The policy check order is optimal and intentional

The current order follows good practices for performance and reliability:

  1. isPassingLockingPolicy - Fast DB check, should be first as it's a fundamental blocking condition
  2. isPassingApprovalPolicy - Simple approval status check, lightweight
  3. isPassingCriteriaPolicy - Success rate validation, relatively simple
  4. isPassingConcurrencyPolicy - Active jobs check, more complex but essential early filter
  5. isPassingReleaseDependencyPolicy - Complex dependency resolution, correctly placed mid-chain
  6. isPassingJobRolloutPolicy - Gradual rollout logic, depends on previous checks
  7. isPassingNoActiveJobsPolicy - Complex job state check, appropriately late
  8. isPassingNewerThanLastActiveReleasePolicy - Correct placement as it requires active release context
  9. isPassingReleaseWindowPolicy - Time-based check, appropriately last as it's independent

The placement of isPassingNewerThanLastActiveReleasePolicy before the window policy is correct as it:

  • Depends on active release information gathered by previous checks
  • Is more restrictive than the window policy
  • Has moderate complexity (single subquery + release fetch)
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Analyze the complexity and dependencies of each policy check

# Search for the implementation of each policy check to understand their complexity
echo "Analyzing policy implementations..."
for policy in "isPassingLockingPolicy" "isPassingApprovalPolicy" "isPassingCriteriaPolicy" "isPassingConcurrencyPolicy" "isPassingReleaseDependencyPolicy" "isPassingJobRolloutPolicy" "isPassingNoActiveJobsPolicy" "isPassingNewerThanLastActiveReleasePolicy" "isPassingReleaseWindowPolicy"; do
    echo "\nAnalyzing $policy:"
    rg -A 10 "export const $policy" --type ts
done

Length of output: 12501

packages/job-dispatch/src/release-sequencing.ts (3)

3-3: LGTM: Import changes are correct.

The addition of isNull import is properly placed and utilized in the SQL query.


43-43: Consider adding an index for the LEFT JOIN.

The change from INNER JOIN to LEFT JOIN could impact query performance. Consider adding an index on environment.policyId if not already present.


52-55: ⚠️ Potential issue

Replace magic number with explicit enum value.

Using .at(1) to access enum values is fragile and could break if the enum order changes. Consider using the explicit enum value for better maintainability.

Additionally, please add a comment explaining the business logic behind these conditions:

  • Why we're checking for this specific enum value
  • Why null values are now acceptable
✅ Verification successful

From the search results, I found the definition of releaseSequencingType enum in packages/db/src/schema/environment.ts:

export const releaseSequencingType = pgEnum("release_sequencing_type", [
  "wait",
  "cancel",
]);

Now I can generate the final response:

Replace .at(1) with explicit 'cancel' enum value

The magic number .at(1) refers to the 'cancel' value in the releaseSequencingType enum. For better maintainability and to avoid potential issues if the enum order changes, use the explicit value:

${schema.environmentPolicy.releaseSequencing} = 'cancel'

This condition is used to check if the environment policy is configured to cancel existing releases when a new one is triggered, as opposed to waiting for them to complete ('wait' value).

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Find the enum definition to suggest the explicit value

# Search for releaseSequencingType enum definition
ast-grep --pattern 'enum releaseSequencingType {
  $$$
}'

Length of output: 59


Script:

#!/bin/bash
# Let's try different approaches to find the enum definition

# Search for files containing "releaseSequencingType"
fd -t f | xargs rg "releaseSequencingType" -A 5 -B 5

# Also search for schema definitions that might contain this enum
rg "schema\." -A 5 -B 5

Length of output: 186302

packages/api/src/router/release-deploy.ts (3)

19-19: LGTM: Import of new policy check function.

The addition of isPassingAllPoliciesExceptNewerThanLastActive aligns with the PR objective of fixing deployment of releases after the latest non-pending release.


165-167: LGTM: Consistent policy checks across deployment scenarios.

The policy checks in toTarget mirror those in toEnvironment, maintaining consistent behavior whether deploying to an environment or a specific target.


94-96: LGTM: Improved policy checks for forced vs non-forced releases.

The conditional policy checks are well-structured:

  • Forced releases only verify locking policy, appropriate for override scenarios
  • Non-forced releases maintain all policy checks except the "newer than last active" check, allowing deployment of releases after the latest non-pending while maintaining other safety checks

Let's verify the policy checker implementation:

✅ Verification successful

Policy implementation verified and confirmed correct

The implementation is well-structured and matches the intended behavior:

  • isPassingAllPoliciesExceptNewerThanLastActive in packages/job-dispatch/src/policy-checker.ts applies all essential policies:

    • Locking policy
    • Approval policy
    • Criteria policy
    • Concurrency policy
    • Release dependency policy
    • Job rollout policy
    • No active jobs policy
    • Release window policy
  • isPassingLockingPolicy in packages/job-dispatch/src/lock-checker.ts is correctly used as the only check for forced releases

The conditional policy application in the review code correctly implements the intended behavior, where forced releases bypass most checks while maintaining essential safety through the locking policy.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify the policy checker implementation
# Expected: Find the policy checker function and its tests to ensure correct behavior

# Search for the policy checker implementation
echo "Searching for policy checker implementation..."
rg -t typescript "isPassingAllPoliciesExceptNewerThanLastActive" -A 10

# Search for related tests
echo "Searching for related tests..."
rg -t typescript "describe.*isPassingAllPoliciesExceptNewerThanLastActive" -A 10

Length of output: 397


Script:

#!/bin/bash
# Let's try without typescript file type flag since it's not recognized
# Search for the policy checker implementation
echo "Searching for policy checker implementation..."
rg "isPassingAllPoliciesExceptNewerThanLastActive" -A 10

# Search for related tests
echo "Searching for related tests..."
rg "describe.*isPassingAllPoliciesExceptNewerThanLastActive" -A 10

# Also search for the locking policy implementation for completeness
echo "Searching for locking policy implementation..."
rg "isPassingLockingPolicy" -A 10

Length of output: 10397

packages/job-dispatch/src/policies/release-sequencing.ts (3)

1-8: Imports are correctly updated to support new functionalities

The added imports are necessary for the new functions and ensure all dependencies are properly included.


72-93: latestActiveReleaseSubQuery function is well-implemented

The subquery correctly constructs a query to retrieve the latest active releases, partitioned by deployment and environment, with appropriate ranking.


101-159: isPassingNewerThanLastActiveReleasePolicy function accurately enforces the release sequencing policy

The logic effectively checks if a release is newer than the last active release for a given deployment and environment. The use of lodash chaining enhances readability, and the function handles edge cases appropriately.

@adityachoudhari26 adityachoudhari26 merged commit 69408b2 into main Nov 4, 2024
8 checks passed
@adityachoudhari26 adityachoudhari26 deleted the after-latest-active branch November 4, 2024 22: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