Skip to content

Conversation

@iam-flo
Copy link
Contributor

@iam-flo iam-flo commented Aug 1, 2025

Test

@iam-flo iam-flo requested a review from FelixTJDietrich August 1, 2025 10:39
@iam-flo iam-flo self-assigned this Aug 1, 2025
Copilot AI review requested due to automatic review settings August 1, 2025 10:39
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Aug 1, 2025

Walkthrough

The changes enhance the notification system for pull request best practice detection. The system now tracks and reports both good and bad practices. Email notifications and templates are updated to display detected good practices alongside bad practices, and a new HTML template for listing good practices is added. Method signatures and email content are adjusted accordingly.

Changes

Cohort / File(s) Change Summary
Bad Practice Detection Logic
server/application-server/src/main/java/de/tum/in/www1/hephaestus/activity/badpracticedetector/BadPracticeDetectorTask.java
Collects good practices into a separate list; updates email notification logic to include both unresolved bad and good practices.
Notification Service
server/application-server/src/main/java/de/tum/in/www1/hephaestus/notification/MailService.java
Modifies the email method to accept and process good practices; adds a helper for generating good practice summary strings; updates method signature.
Email Template: Bad Practices
server/application-server/src/main/resources/mail-templates/bad-practices-detected.html
Updates the template to display detected good practices, including a summary and a list of good practices with details.
Email Template: Good Practices
server/application-server/src/main/resources/mail-templates/good-practice-list.html
Adds a new HTML template for reporting good practices detected in pull requests, with dynamic content and instructions for users.

Sequence Diagram(s)

sequenceDiagram
    participant Detector as BadPracticeDetectorTask
    participant MailService
    participant User

    Detector->Detector: Identify bad and good practices in PR
    Detector->MailService: sendBadPracticesDetectedInPullRequestEmail(user, pullRequest, badPractices, goodPractices)
    MailService->MailService: Prepare email content (bad + good practices)
    MailService->User: Send notification email with both practice lists
Loading

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~8 minutes

Poem

🐇
In the code, both good and bad now shine,
Emails tell the tale in every line.
Good practices cheered, bad ones flagged anew,
Templates refreshed with a positive view.
Hippity-hop, let’s keep it bright,
For best practices make the code just right!
🌱✨

Note

⚡️ Unit Test Generation is now available in beta!

Learn more here, or try it out under "Finishing Touches" below.


📜 Recent review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 56c1d99 and f670a26.

📒 Files selected for processing (4)
  • server/application-server/src/main/java/de/tum/in/www1/hephaestus/activity/badpracticedetector/BadPracticeDetectorTask.java (1 hunks)
  • server/application-server/src/main/java/de/tum/in/www1/hephaestus/notification/MailService.java (3 hunks)
  • server/application-server/src/main/resources/mail-templates/bad-practices-detected.html (1 hunks)
  • server/application-server/src/main/resources/mail-templates/good-practice-list.html (1 hunks)
✅ Files skipped from review due to trivial changes (2)
  • server/application-server/src/main/resources/mail-templates/good-practice-list.html
  • server/application-server/src/main/resources/mail-templates/bad-practices-detected.html
🚧 Files skipped from review as they are similar to previous changes (2)
  • server/application-server/src/main/java/de/tum/in/www1/hephaestus/activity/badpracticedetector/BadPracticeDetectorTask.java
  • server/application-server/src/main/java/de/tum/in/www1/hephaestus/notification/MailService.java
⏰ 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). (12)
  • GitHub Check: docker-build / application-server-build / Build linux/amd64 Docker Image for ls1intum/hephaestus/application-server
  • GitHub Check: docker-build / webapp-react-build / Build linux/amd64 Docker Image for ls1intum/hephaestus/webapp-react
  • GitHub Check: docker-build / intelligence-service-build / Build linux/amd64 Docker Image for ls1intum/hephaestus/intelligence-service
  • GitHub Check: docker-build / application-server-build / Build linux/arm64 Docker Image for ls1intum/hephaestus/application-server
  • GitHub Check: docker-build / webapp-react-build / Build linux/arm64 Docker Image for ls1intum/hephaestus/webapp-react
  • GitHub Check: docker-build / webhook-ingest-build / Build linux/arm64 Docker Image for ls1intum/hephaestus/webhook-ingest
  • GitHub Check: docker-build / intelligence-service-build / Build linux/arm64 Docker Image for ls1intum/hephaestus/intelligence-service
  • GitHub Check: docker-build / webhook-ingest-build / Build linux/amd64 Docker Image for ls1intum/hephaestus/webhook-ingest
  • GitHub Check: test-suite / application-server-integration
  • GitHub Check: quality-gates / openapi-validation
  • GitHub Check: security-scan / dependencies
  • GitHub Check: security-scan / sast
✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch good-practices-mail

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai generate unit tests to generate unit tests for this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@github-actions github-actions bot added application-server Spring Boot server: APIs, business logic, database size:M This PR changes 30-99 lines, ignoring generated files. labels Aug 1, 2025
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull Request Overview

This PR introduces functionality to notify users about good practices detected in their pull requests, expanding the existing bad practice notification system. The implementation adds email notifications for good practices while refactoring the existing code to handle both types of practices more generically.

Key changes:

  • Added email notifications for detected good practices in pull requests
  • Refactored the mail service to handle both good and bad practices with a unified method
  • Created a new HTML email template for good practice notifications

Reviewed Changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.

File Description
good-practices-detected.html New email template for notifying users about detected good practices
MailService.java Added good practice email method and refactored practice string generation to be generic
BadPracticeDetectorTask.java Added logic to filter and send notifications for good practices
Comments suppressed due to low confidence (2)

server/application-server/src/main/java/de/tum/in/www1/hephaestus/notification/MailService.java:77

  • The parameter name badPractices is misleading since this method handles good practices. Consider renaming it to practices or goodPractices for clarity.
        List<PullRequestBadPractice> badPractices

server/application-server/src/main/java/de/tum/in/www1/hephaestus/notification/MailService.java:111

  • The parameter name badPractices is misleading since this method now handles both good and bad practices. Consider renaming it to practices for clarity.
    private String getGoodOrBadPracticeString(List<PullRequestBadPractice> badPractices, String goodOrBad) {

}
} else if (sendBadPracticeDetectionEmail && !goodPractices.isEmpty()) {
for (User user : pullRequest.getAssignees()) {
mailService.sendGoodPracticesDetectedInPullRequestEmail(user, pullRequest, unResolvedBadPractices);
Copy link

Copilot AI Aug 1, 2025

Choose a reason for hiding this comment

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

The method is being called with unResolvedBadPractices instead of goodPractices. This will send an email about good practices but include the bad practices list, which is incorrect.

Suggested change
mailService.sendGoodPracticesDetectedInPullRequestEmail(user, pullRequest, unResolvedBadPractices);
mailService.sendGoodPracticesDetectedInPullRequestEmail(user, pullRequest, goodPractices);

Copilot uses AI. Check for mistakes.
@dosubot dosubot bot added the enhancement label Aug 1, 2025
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: 2

🧹 Nitpick comments (2)
server/application-server/src/main/resources/mail-templates/good-practices-detected.html (1)

7-11: Consider the data structure inconsistency.

The template iterates over goodPractices but accesses goodPractice.state.getValue(). Since good practices are filtered from the same PullRequestBadPractice objects, this works but creates semantic confusion.

Consider renaming the variable in the template context to better reflect that these are practices marked as good:

-    <li th:each="goodPractice : ${goodPractices}">
-        <strong th:text="${goodPractice.title}">Good Practice Title</strong>: [[${goodPractice.state.getValue()}]]<br />
-        <span th:text="${goodPractice.description}">Good Practice Description</span>
+    <li th:each="practice : ${goodPractices}">
+        <strong th:text="${practice.title}">Good Practice Title</strong>: [[${practice.state.getValue()}]]<br />
+        <span th:text="${practice.description}">Good Practice Description</span>
server/application-server/src/main/java/de/tum/in/www1/hephaestus/notification/MailService.java (1)

111-119: Consider refactoring to reduce code duplication.

Both email methods share significant duplicate code. Consider extracting the common Keycloak user lookup and email sending logic.

Extract common functionality:

+private String getUserEmail(User user) throws Exception {
+    UserRepresentation keyCloakUser = keycloak
+        .realm(realm)
+        .users()
+        .searchByUsername(user.getLogin(), true)
+        .getFirst();
+    return keyCloakUser.getEmail();
+}
+
+private void sendPracticeEmail(User user, PullRequest pullRequest, 
+                              List<PullRequestBadPractice> practices, 
+                              String practiceType, String templateName) {
+    logger.info("Sending {} practice detected email to user: {}", practiceType, user.getLogin());
+    
+    try {
+        String email = getUserEmail(user);
+        String subject = "Hephaestus: " + 
+            getGoodOrBadPracticeString(practices, practiceType) +
+            " detected in your pull request #" + pullRequest.getNumber();
+
+        MailBuilder mailBuilder = new MailBuilder(mailConfig, user, email, subject, templateName);
+        mailBuilder
+            .fillPlaceholder(user, "user")
+            .fillPlaceholder(pullRequest, "pullRequest")
+            .fillPlaceholder(practices, practiceType + "Practices")
+            .fillPlaceholder(getGoodOrBadPracticeString(practices, practiceType), practiceType + "PracticeString")
+            .fillPlaceholder(pullRequest.getRepository().getName(), "repository")
+            .send(javaMailSender);
+    } catch (Exception e) {
+        logger.error("Failed to find user in Keycloak: {}", user.getLogin(), e);
+    }
+}
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 22a8e4c and 56c1d99.

📒 Files selected for processing (3)
  • server/application-server/src/main/java/de/tum/in/www1/hephaestus/activity/badpracticedetector/BadPracticeDetectorTask.java (1 hunks)
  • server/application-server/src/main/java/de/tum/in/www1/hephaestus/notification/MailService.java (2 hunks)
  • server/application-server/src/main/resources/mail-templates/good-practices-detected.html (1 hunks)
⏰ 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). (9)
  • GitHub Check: security-scan / dependencies
  • GitHub Check: quality-gates / application-server-quality
  • GitHub Check: docker-build / webapp-react-build / Build linux/arm64 Docker Image for ls1intum/hephaestus/webapp-react
  • GitHub Check: quality-gates / database-documentation-validation
  • GitHub Check: quality-gates / database-schema-validation
  • GitHub Check: quality-gates / openapi-validation
  • GitHub Check: quality-gates / intelligence-service-quality
  • GitHub Check: security-scan / sast
  • GitHub Check: test-suite / application-server-integration
🔇 Additional comments (4)
server/application-server/src/main/resources/mail-templates/good-practices-detected.html (2)

4-4: Verify the goodPracticeString variable is correctly passed.

The template expects a goodPracticeString variable, but based on the MailService implementation, this should contain the formatted count of good practices.


13-13: /best-practices endpoint verified – no action required.

Found in both frontends:

  • Angular (webapp): webapp/src/app/app.routes.ts defines { path: 'best-practices', component: ActivityDashboardComponent, canActivate: [AuthGuard] }
  • React (webapp-react): src/routes/_authenticated/best-practices.tsx and src/routes/_authenticated/user/$username/best-practices.tsx via createFileRoute("/_authenticated/best-practices")
server/application-server/src/main/java/de/tum/in/www1/hephaestus/activity/badpracticedetector/BadPracticeDetectorTask.java (1)

45-48: LGTM! Good practice filtering logic is correct.

The filtering correctly identifies practices marked with GOOD_PRACTICE state.

server/application-server/src/main/java/de/tum/in/www1/hephaestus/notification/MailService.java (1)

60-60: LGTM! Refactoring to use the generalized string method.

The refactoring correctly maintains the existing functionality while using the new generalized method.

Also applies to: 69-69

Comment on lines 54 to 58
} else if (sendBadPracticeDetectionEmail && !goodPractices.isEmpty()) {
for (User user : pullRequest.getAssignees()) {
mailService.sendGoodPracticesDetectedInPullRequestEmail(user, pullRequest, unResolvedBadPractices);
}
}
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Critical: Wrong parameter passed to good practice email method.

Line 56 passes unResolvedBadPractices to the good practice email method, but it should pass goodPractices since that's what the email template expects.

Apply this fix:

-                mailService.sendGoodPracticesDetectedInPullRequestEmail(user, pullRequest, unResolvedBadPractices);
+                mailService.sendGoodPracticesDetectedInPullRequestEmail(user, pullRequest, goodPractices);
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
} else if (sendBadPracticeDetectionEmail && !goodPractices.isEmpty()) {
for (User user : pullRequest.getAssignees()) {
mailService.sendGoodPracticesDetectedInPullRequestEmail(user, pullRequest, unResolvedBadPractices);
}
}
} else if (sendBadPracticeDetectionEmail && !goodPractices.isEmpty()) {
for (User user : pullRequest.getAssignees()) {
mailService.sendGoodPracticesDetectedInPullRequestEmail(user, pullRequest, goodPractices);
}
}
🤖 Prompt for AI Agents
In
server/application-server/src/main/java/de/tum/in/www1/hephaestus/activity/badpracticedetector/BadPracticeDetectorTask.java
between lines 54 and 58, the method
mailService.sendGoodPracticesDetectedInPullRequestEmail is incorrectly called
with unResolvedBadPractices instead of goodPractices. To fix this, replace the
unResolvedBadPractices argument with goodPractices in the method call to match
the expected email template parameter.

Comment on lines 74 to 109
public void sendGoodPracticesDetectedInPullRequestEmail(
User user,
PullRequest pullRequest,
List<PullRequestBadPractice> badPractices
) {
logger.info("Sending good practice detected email to user: {}", user.getLogin());
String email;

try {
UserRepresentation keyCloakUser = keycloak
.realm(realm)
.users()
.searchByUsername(user.getLogin(), true)
.getFirst();

email = keyCloakUser.getEmail();
} catch (Exception e) {
logger.error("Failed to find user in Keycloak: {}", user.getLogin(), e);
return;
}

String subject =
"Hephaestus: " +
getGoodOrBadPracticeString(badPractices,"good") +
" detected in your pull request #" +
pullRequest.getNumber();

MailBuilder mailBuilder = new MailBuilder(mailConfig, user, email, subject, "good-practices-detected");
mailBuilder
.fillPlaceholder(user, "user")
.fillPlaceholder(pullRequest, "pullRequest")
.fillPlaceholder(badPractices, "goodPractices")
.fillPlaceholder(getGoodOrBadPracticeString(badPractices,"good"), "goodPracticeString")
.fillPlaceholder(pullRequest.getRepository().getName(), "repository")
.send(javaMailSender);
}
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Fix parameter naming and method signature.

The method parameter is named badPractices but is used for good practices, creating confusion. Additionally, the method logic assumes it receives good practices but the parameter suggests otherwise.

Apply this fix to improve clarity:

 public void sendGoodPracticesDetectedInPullRequestEmail(
     User user,
     PullRequest pullRequest,
-    List<PullRequestBadPractice> badPractices
+    List<PullRequestBadPractice> goodPractices
 ) {
     logger.info("Sending good practice detected email to user: {}", user.getLogin());
     String email;

     try {
         UserRepresentation keyCloakUser = keycloak
             .realm(realm)
             .users()
             .searchByUsername(user.getLogin(), true)
             .getFirst();

         email = keyCloakUser.getEmail();
     } catch (Exception e) {
         logger.error("Failed to find user in Keycloak: {}", user.getLogin(), e);
         return;
     }

     String subject =
         "Hephaestus: " +
-                getGoodOrBadPracticeString(badPractices,"good") +
+                getGoodOrBadPracticeString(goodPractices,"good") +
         " detected in your pull request #" +
         pullRequest.getNumber();

     MailBuilder mailBuilder = new MailBuilder(mailConfig, user, email, subject, "good-practices-detected");
     mailBuilder
         .fillPlaceholder(user, "user")
         .fillPlaceholder(pullRequest, "pullRequest")
-        .fillPlaceholder(badPractices, "goodPractices")
-        .fillPlaceholder(getGoodOrBadPracticeString(badPractices,"good"), "goodPracticeString")
+        .fillPlaceholder(goodPractices, "goodPractices")
+        .fillPlaceholder(getGoodOrBadPracticeString(goodPractices,"good"), "goodPracticeString")
         .fillPlaceholder(pullRequest.getRepository().getName(), "repository")
         .send(javaMailSender);
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
public void sendGoodPracticesDetectedInPullRequestEmail(
User user,
PullRequest pullRequest,
List<PullRequestBadPractice> badPractices
) {
logger.info("Sending good practice detected email to user: {}", user.getLogin());
String email;
try {
UserRepresentation keyCloakUser = keycloak
.realm(realm)
.users()
.searchByUsername(user.getLogin(), true)
.getFirst();
email = keyCloakUser.getEmail();
} catch (Exception e) {
logger.error("Failed to find user in Keycloak: {}", user.getLogin(), e);
return;
}
String subject =
"Hephaestus: " +
getGoodOrBadPracticeString(badPractices,"good") +
" detected in your pull request #" +
pullRequest.getNumber();
MailBuilder mailBuilder = new MailBuilder(mailConfig, user, email, subject, "good-practices-detected");
mailBuilder
.fillPlaceholder(user, "user")
.fillPlaceholder(pullRequest, "pullRequest")
.fillPlaceholder(badPractices, "goodPractices")
.fillPlaceholder(getGoodOrBadPracticeString(badPractices,"good"), "goodPracticeString")
.fillPlaceholder(pullRequest.getRepository().getName(), "repository")
.send(javaMailSender);
}
public void sendGoodPracticesDetectedInPullRequestEmail(
User user,
PullRequest pullRequest,
List<PullRequestBadPractice> goodPractices
) {
logger.info("Sending good practice detected email to user: {}", user.getLogin());
String email;
try {
UserRepresentation keyCloakUser = keycloak
.realm(realm)
.users()
.searchByUsername(user.getLogin(), true)
.getFirst();
email = keyCloakUser.getEmail();
} catch (Exception e) {
logger.error("Failed to find user in Keycloak: {}", user.getLogin(), e);
return;
}
String subject =
"Hephaestus: " +
getGoodOrBadPracticeString(goodPractices, "good") +
" detected in your pull request #" +
pullRequest.getNumber();
MailBuilder mailBuilder = new MailBuilder(mailConfig, user, email, subject, "good-practices-detected");
mailBuilder
.fillPlaceholder(user, "user")
.fillPlaceholder(pullRequest, "pullRequest")
.fillPlaceholder(goodPractices, "goodPractices")
.fillPlaceholder(getGoodOrBadPracticeString(goodPractices, "good"), "goodPracticeString")
.fillPlaceholder(pullRequest.getRepository().getName(), "repository")
.send(javaMailSender);
}
🤖 Prompt for AI Agents
In
server/application-server/src/main/java/de/tum/in/www1/hephaestus/notification/MailService.java
between lines 74 and 109, the method parameter named 'badPractices' is
misleading because the method handles good practices. Rename the parameter to
'goodPractices' and update all references within the method accordingly to
reflect that it deals with good practices, ensuring the method signature and
internal usage are consistent and clear.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

application-server Spring Boot server: APIs, business logic, database size:M This PR changes 30-99 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants