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

Integrated code lifecycle: Limit build logs size #9861

Merged

Conversation

BBesrour
Copy link
Member

@BBesrour BBesrour commented Nov 25, 2024

Checklist

General

Server

  • Important: I implemented the changes with a very good performance and prevented too many (unnecessary) and too complex database calls.
  • I strictly followed the principle of data economy for all database calls.
  • I strictly followed the server coding and design guidelines.
  • I added multiple integration tests (Spring) related to the features (with a high test coverage).
  • I added pre-authorization annotations according to the guidelines and checked the course groups for all new REST Calls (security).
  • I documented the Java code using JavaDoc style.

Changes affecting Programming Exercises

  • High priority: I tested all changes and their related features with all corresponding user types on a test server configured with the integrated lifecycle setup (LocalVC and LocalCI).

Motivation and Context

There is an issue where an exercise can generate huge build logs, which when transferred over hazelcast, could crash the system with out of memory errors. This PR limits the build logs size to max 10.000 logs and max 1.024 chars per log.

Description

Before sending the buildlogs over hazelcast, we truncate them to max 10.000 logs and 1.024 chars per log. Numbers are configurable via application properties (yml settings of the build agents)

Please note that a log can consist of multiple lines. So it's normal if the lines per log file exceed 10000. But each log should not have more than 1024 chars. The number of logs can be counted by counting the timestamps (Ctrl+F [Europe/Berlin])

Steps for Testing

Prerequisites:

  • 1 Instructor
  1. Submit a few times as a student
  2. As instructor, navigate to the build logs (/course-management/{courseId}/build-queue)
  3. Make sure that you can view the build logs. Make sure that each build job has max 10000 logs (the number of logs is equal to the number of timestamps, you can figure out how logs there are by Ctrl+F [Europe/Berlin] and view count)

Testserver States

Note

These badges show the state of the test servers.
Green = Currently available, Red = Currently locked
Click on the badges to get to the test servers.







Review Progress

Code Review

  • Code Review 1
  • Code Review 2

Manual Tests

  • Test 1
  • Test 2

Performance Tests

  • Test 1
  • Test 2

Summary by CodeRabbit

  • New Features

    • Introduced configurable limits on the number of log entries and the length of each log entry for better log management.
    • Added a new BuildLogDTO class to improve the structure of log entries.
  • Bug Fixes

    • Enhanced logging behavior during build job execution, ensuring logs are conditionally added based on new constraints.
  • Refactor

    • Updated logging methods across multiple services to streamline log entry management and improve readability, transitioning from BuildLogEntry to BuildLogDTO.
    • Improved handling of build logs in various services to ensure consistency and efficiency in log management.

@BBesrour BBesrour self-assigned this Nov 25, 2024
@BBesrour BBesrour requested a review from a team as a code owner November 25, 2024 19:00
@github-actions github-actions bot added server Pull requests that update Java code. (Added Automatically!) config-change Pull requests that change the config in a way that they require a deployment via Ansible. buildagent Pull requests that affect the corresponding module labels Nov 25, 2024
Copy link

coderabbitai bot commented Nov 25, 2024

Walkthrough

The changes primarily involve significant updates to the BuildLogsMap class and its integration across various services managing build processes. New integer fields have been introduced to limit the number of log entries and the maximum character length per entry. The method appendBuildLogEntry has been modified to utilize a new method that accepts BuildLogDTO, ensuring that log entries adhere to the defined constraints. This update enhances the logging functionality throughout the build process.

Changes

File Path Change Summary
src/main/java/de/tum/cit/aet/artemis/buildagent/service/BuildLogsMap.java - Added fields: maxLogLinesPerBuildJob, maxCharsPerLine.
- Introduced methods: appendBuildLogEntry(String buildJobId, BuildLogDTO buildLog), getAndTruncateBuildLogs(String buildJobId).
- Updated method appendBuildLogEntry(String buildLogId, String message) to call the new method.
src/main/java/de/tum/cit/aet/artemis/buildagent/service/BuildAgentDockerService.java - Changed logging level from info to debug.
- Replaced method calls to buildLogsMap.appendBuildLogEntry with buildLogsMap.addBuildLogEntryIfBelowMaxLines.
src/main/java/de/tum/cit/aet/artemis/buildagent/service/BuildJobContainerService.java - Updated executeDockerCommand to use BuildLogDTO instead of BuildLogEntry.
src/main/java/de/tum/cit/aet/artemis/buildagent/service/BuildJobExecutionService.java - Changed log entry handling to use buildLogsMap.getAndTruncateBuildLogs instead of appendBuildLogEntry.
src/main/java/de/tum/cit/aet/artemis/buildagent/service/BuildJobManagementService.java - Updated methods to use BuildLogDTO instead of BuildLogEntry for logging.
src/main/java/de/tum/cit/aet/artemis/buildagent/dto/BuildLogDTO.java - Introduced new record class BuildLogDTO with fields time and log.
src/main/java/de/tum/cit/aet/artemis/buildagent/dto/BuildResult.java - Changed field type from List<BuildLogEntry> to List<BuildLogDTO> and updated related methods.
src/main/java/de/tum/cit/aet/artemis/buildagent/dto/ResultQueueItem.java - Updated field type from List<BuildLogEntry> to List<BuildLogDTO>.
src/main/java/de/tum/cit/aet/artemis/buildagent/service/SharedQueueProcessingService.java - Updated variable type from List<BuildLogEntry> to List<BuildLogDTO> and modified log retrieval method.
src/main/java/de/tum/cit/aet/artemis/programming/service/BuildLogEntryService.java - Changed method signature to accept List<BuildLogDTO> instead of List<BuildLogEntry>.
src/main/java/de/tum/cit/aet/artemis/programming/service/localci/LocalCIResultProcessingService.java - Updated variable type from List<BuildLogEntry> to List<BuildLogDTO>.
src/test/java/de/tum/cit/aet/artemis/programming/icl/LocalCIResourceIntegrationTest.java - Changed variable type from BuildLogEntry to BuildLogDTO.

Possibly related PRs

Suggested labels

ready to merge, assessment, core

Suggested reviewers

  • SimonEntholzer
  • JohannesStoehr
  • az108
  • Hialus
  • pzdr7
  • coolchock

Warning

There were issues while running some tools. Please review the errors and either fix the tool’s configuration or disable the tool if it’s a critical failure.

🔧 pmd (7.6.0)
src/main/java/de/tum/cit/aet/artemis/buildagent/service/BuildJobContainerService.java

The following rules are missing or misspelled in your ruleset file category/vm/bestpractices.xml: BooleanInstantiation, DontImportJavaLang, DuplicateImports, EmptyFinallyBlock, EmptyIfStmt, EmptyInitializer, EmptyStatementBlock, EmptyStatementNotInLoop, EmptySwitchStatements, EmptySynchronizedBlock, EmptyTryBlock, EmptyWhileStmt, ExcessiveClassLength, ExcessiveMethodLength, ImportFromSamePackage, MissingBreakInSwitch, SimplifyBooleanAssertion. Please check your ruleset configuration.

src/main/java/de/tum/cit/aet/artemis/buildagent/service/BuildLogsMap.java

The following rules are missing or misspelled in your ruleset file category/vm/bestpractices.xml: BooleanInstantiation, DontImportJavaLang, DuplicateImports, EmptyFinallyBlock, EmptyIfStmt, EmptyInitializer, EmptyStatementBlock, EmptyStatementNotInLoop, EmptySwitchStatements, EmptySynchronizedBlock, EmptyTryBlock, EmptyWhileStmt, ExcessiveClassLength, ExcessiveMethodLength, ImportFromSamePackage, MissingBreakInSwitch, SimplifyBooleanAssertion. Please check your ruleset configuration.

src/main/java/de/tum/cit/aet/artemis/programming/service/BuildLogEntryService.java

The following rules are missing or misspelled in your ruleset file category/vm/bestpractices.xml: BooleanInstantiation, DontImportJavaLang, DuplicateImports, EmptyFinallyBlock, EmptyIfStmt, EmptyInitializer, EmptyStatementBlock, EmptyStatementNotInLoop, EmptySwitchStatements, EmptySynchronizedBlock, EmptyTryBlock, EmptyWhileStmt, ExcessiveClassLength, ExcessiveMethodLength, ImportFromSamePackage, MissingBreakInSwitch, SimplifyBooleanAssertion. Please check your ruleset configuration.


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 or @coderabbitai title 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

@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: 4

🧹 Outside diff range and nitpick comments (3)
src/main/java/de/tum/cit/aet/artemis/buildagent/service/SharedQueueProcessingService.java (3)

400-403: Consider combining retrieval and removal operations for better thread safety

The current implementation makes two separate calls to buildLogsMap which could lead to race conditions in a concurrent environment. Consider combining these operations into a single atomic operation in BuildLogsMap.

-List<BuildLogEntry> buildLogs = buildLogsMap.getAndTruncateBuildLogs(buildJob.id());
-buildLogsMap.removeBuildLogs(buildJob.id());
+List<BuildLogEntry> buildLogs = buildLogsMap.getAndTruncateAndRemoveBuildLogs(buildJob.id());

Line range hint 400-441: Good architectural decision on log size management

The implementation correctly delegates the log truncation responsibility to BuildLogsMap while maintaining the service's primary responsibility of build processing. This separation of concerns aligns well with SOLID principles and effectively addresses the PR's objective of preventing system crashes during Hazelcast transfers.


Migration to getAndTruncateBuildLogs is incomplete

The codebase still contains usages of getBuildLogs() that should be migrated to getAndTruncateBuildLogs(). The new method includes important truncation logic for both the number of log lines and characters per line, which is missing in the old implementation. Specific locations that need updating:

  • BuildJobExecutionService.java: buildResult.setBuildLogEntries(buildLogsMap.getBuildLogs(buildJob.id()))
  • RepositoryProgrammingExerciseParticipationResource.java: Contains an API endpoint using getBuildLogs
🔗 Analysis chain

Line range hint 400-441: Verify complete migration to new build logs method

Let's ensure all occurrences of getBuildLogs have been migrated to getAndTruncateBuildLogs throughout the codebase.


Let me analyze the implementation of both methods to understand if they serve different purposes.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for any remaining usage of getBuildLogs
rg "getBuildLogs\(" --type java

# Search for usage of new method to confirm migration
rg "getAndTruncateBuildLogs\(" --type java

Length of output: 1189


Script:

#!/bin/bash
# Get the implementation of both methods from BuildLogsMap
ast-grep --pattern 'public List<BuildLogEntry> getBuildLogs($_) {
  $$$
}'

ast-grep --pattern 'public List<BuildLogEntry> getAndTruncateBuildLogs($_) {
  $$$
}'

Length of output: 3846

📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between a4c674c and 3e6c24a.

⛔ Files ignored due to path filters (1)
  • src/main/resources/config/application-buildagent.yml is excluded by !**/*.yml
📒 Files selected for processing (2)
  • src/main/java/de/tum/cit/aet/artemis/buildagent/service/BuildLogsMap.java (3 hunks)
  • src/main/java/de/tum/cit/aet/artemis/buildagent/service/SharedQueueProcessingService.java (2 hunks)
🧰 Additional context used
📓 Path-based instructions (2)
src/main/java/de/tum/cit/aet/artemis/buildagent/service/BuildLogsMap.java (1)

Pattern src/main/java/**/*.java: naming:CamelCase; principles:{single_responsibility,small_methods,no_duplication}; db:{perf_queries,datetime_not_timestamp}; rest:{stateless,singleton,delegate_logic,http_only,minimal_dtos}; dtos:{java_records,no_entities,min_data,single_resp}; di:constructor_injection; kiss:simple_code; file_handling:os_indep_paths; practices:{least_access,avoid_transactions,code_reuse,static_member_ref,prefer_primitives}; sql:{param_annotation,uppercase,avoid_subqueries};java:avoid_star_imports

src/main/java/de/tum/cit/aet/artemis/buildagent/service/SharedQueueProcessingService.java (1)

Pattern src/main/java/**/*.java: naming:CamelCase; principles:{single_responsibility,small_methods,no_duplication}; db:{perf_queries,datetime_not_timestamp}; rest:{stateless,singleton,delegate_logic,http_only,minimal_dtos}; dtos:{java_records,no_entities,min_data,single_resp}; di:constructor_injection; kiss:simple_code; file_handling:os_indep_paths; practices:{least_access,avoid_transactions,code_reuse,static_member_ref,prefer_primitives}; sql:{param_annotation,uppercase,avoid_subqueries};java:avoid_star_imports

coderabbitai[bot]
coderabbitai bot previously approved these changes Nov 25, 2024
@az108 az108 added deploy:artemis-test2 and removed deployment-error Added by deployment workflows if an error occured labels Nov 25, 2024
@github-actions github-actions bot added deployment-error Added by deployment workflows if an error occured and removed deploy:artemis-test2 labels Nov 25, 2024
Copy link

@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: 4

🧹 Outside diff range and nitpick comments (10)
src/main/java/de/tum/cit/aet/artemis/buildagent/service/BuildLogsMap.java (1)

33-43: Enhance Javadoc to clarify newline behavior

The method automatically appends a newline character to messages, but this behavior isn't explicitly mentioned in the Javadoc. This implicit behavior could surprise developers.

Add this clarification to the Javadoc:

     /**
      * Appends a build log entry to the list of build logs for the specified build log ID.
      * If the list does not exist, it is created. If the list exceeds the maximum number of log lines,
      * the log entry is not added. If the log entry exceeds the maximum number of characters per line,
      * it is truncated.
+     * Note: A newline character is automatically appended to the message.
      *
      * @param buildLogId the ID of the build log to append to
      * @param message    the message to append
      */
src/main/java/de/tum/cit/aet/artemis/buildagent/service/BuildJobManagementService.java (2)

174-174: Consider limiting stack trace size before logging

While the BuildLogEntry creation is correct, concatenating the full stack trace with the message could potentially create very large log entries. Consider truncating the stack trace if it exceeds a certain length.

Example implementation:

-buildLogsMap.addBuildLogEntryIfBelowMaxLines(buildJobItem.id(), new BuildLogEntry(ZonedDateTime.now(), msg + "\n" + stackTrace));
+String truncatedStackTrace = stackTrace.length() > 800 ? stackTrace.substring(0, 800) + "..." : stackTrace;
+buildLogsMap.addBuildLogEntryIfBelowMaxLines(buildJobItem.id(), new BuildLogEntry(ZonedDateTime.now(), msg + "\n" + truncatedStackTrace));

Line range hint 1-290: Consider adding monitoring for truncated logs

To better understand the impact of log size limitations in production, consider adding monitoring metrics for:

  • Number of truncated log entries
  • Number of times max log lines limit is reached
  • Size of truncated data

This will help in fine-tuning the limits and understanding the impact on users.

Would you like me to provide an example implementation using your metrics system?

src/main/java/de/tum/cit/aet/artemis/buildagent/service/BuildAgentDockerService.java (1)

223-223: Consider structuring error messages for better parsing

While the log limiting changes are correct, consider structuring the error messages in a machine-parseable format. This would help in automated error analysis and monitoring.

Example format:

-String msg = "~~~~~~~~~~~~~~~~~~~~ Pulling docker image " + imageName + " with a lock after error " + e.getMessage() + " ~~~~~~~~~~~~~~~~~~~~";
+String msg = String.format("[DOCKER_PULL_ERROR] image=%s error='%s'", imageName, e.getMessage());

Also applies to: 234-234, 244-244, 264-264

src/main/java/de/tum/cit/aet/artemis/buildagent/service/BuildJobContainerService.java (2)

Line range hint 416-424: Consider enhancing error logging for truncated entries.

While the log size limitation is correctly implemented, it would be beneficial to log a warning when entries are truncated. This would help in debugging scenarios where important information might be cut off.

Consider adding a warning log when entries are truncated:

 if (buildJobId != null) {
-    buildLogsMap.addBuildLogEntryIfBelowMaxLines(buildJobId, buildLogEntry);
+    boolean wasAdded = buildLogsMap.addBuildLogEntryIfBelowMaxLines(buildJobId, buildLogEntry);
+    if (!wasAdded) {
+        log.warn("Build log entry truncated or skipped for buildJobId: {}", buildJobId);
+    }
 }

Line range hint 507-511: Strengthen path validation regex.

The current path validation regex might be too permissive. Consider strengthening it to prevent potential security issues.

Consider updating the path validation:

-    if (path == null || path.contains("..") || !path.matches("[a-zA-Z0-9_*./-]+")) {
+    if (path == null || path.contains("..") || !path.matches("^[a-zA-Z0-9][a-zA-Z0-9_.*/-]*$")) {
         throw new LocalCIException("Invalid path: " + path);
     }

The updated regex:

  1. Ensures paths start with alphanumeric characters
  2. Maintains the same allowed characters
  3. Provides better security against malformed paths
src/main/java/de/tum/cit/aet/artemis/buildagent/service/BuildJobExecutionService.java (4)

145-145: Consider prioritizing critical error messages in the log.

While the change to limit log size is good, critical error messages (like Docker image pull failures or commit hash retrieval failures) might be dropped if the log limit is reached. Consider implementing a priority system for logs to ensure critical error messages are always included.

-        buildLogsMap.addBuildLogEntryIfBelowMaxLines(buildJob.id(), msg);
+        buildLogsMap.addBuildLogEntryWithPriority(buildJob.id(), msg, LogPriority.ERROR);

Also applies to: 153-153, 175-175, 189-189


Line range hint 266-267: Address the TODO comment about method parameters.

The method has too many parameters which makes it hard to maintain. Consider creating a record class to encapsulate these parameters.

public record BuildJobParameters(
    BuildJobQueueItem buildJob,
    String containerName,
    String containerId,
    VcsRepositoryUri assignmentRepositoryUri,
    VcsRepositoryUri testRepositoryUri,
    VcsRepositoryUri solutionRepositoryUri,
    VcsRepositoryUri[] auxiliaryRepositoriesUris,
    Path assignmentRepositoryPath,
    Path testsRepositoryPath,
    Path solutionRepositoryPath,
    Path[] auxiliaryRepositoriesPaths,
    String assignmentRepoCommitHash,
    String testRepoCommitHash
) {}

517-517: Consider rate limiting retry log messages.

The retry messages in the cloneRepository method might consume a significant portion of the log limit. Consider implementing rate limiting for retry messages or logging only the first and last retry attempts.

-                buildLogsMap.addBuildLogEntryIfBelowMaxLines(buildJobId,
-                        "Attempt " + attempt + " to clone repository " + repositoryUri.repositorySlug() + " failed due to " + e.getMessage() + ". Retrying...");
+                if (attempt == 1 || attempt == MAX_CLONE_RETRIES - 1) {
+                    buildLogsMap.addBuildLogEntryIfBelowMaxLines(buildJobId,
+                            "Attempt " + attempt + " to clone repository " + repositoryUri.repositorySlug() + " failed due to " + e.getMessage() + ". Retrying...");
+                }

Also applies to: 520-520, 538-538


Line range hint 1-580: Overall implementation of log size limiting is well done.

The changes consistently implement log size limiting across all logging points in the service. However, there are a few areas for improvement:

  1. Consider implementing a priority system for critical error messages
  2. Refactor the runScriptAndParseResults method to use a parameter object
  3. Implement rate limiting for retry messages

These improvements would make the code more maintainable and ensure important log messages are not lost.

📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 3e6c24a and d2c9ca6.

📒 Files selected for processing (5)
  • src/main/java/de/tum/cit/aet/artemis/buildagent/service/BuildAgentDockerService.java (6 hunks)
  • src/main/java/de/tum/cit/aet/artemis/buildagent/service/BuildJobContainerService.java (1 hunks)
  • src/main/java/de/tum/cit/aet/artemis/buildagent/service/BuildJobExecutionService.java (12 hunks)
  • src/main/java/de/tum/cit/aet/artemis/buildagent/service/BuildJobManagementService.java (3 hunks)
  • src/main/java/de/tum/cit/aet/artemis/buildagent/service/BuildLogsMap.java (2 hunks)
🧰 Additional context used
📓 Path-based instructions (5)
src/main/java/de/tum/cit/aet/artemis/buildagent/service/BuildAgentDockerService.java (1)

Pattern src/main/java/**/*.java: naming:CamelCase; principles:{single_responsibility,small_methods,no_duplication}; db:{perf_queries,datetime_not_timestamp}; rest:{stateless,singleton,delegate_logic,http_only,minimal_dtos}; dtos:{java_records,no_entities,min_data,single_resp}; di:constructor_injection; kiss:simple_code; file_handling:os_indep_paths; practices:{least_access,avoid_transactions,code_reuse,static_member_ref,prefer_primitives}; sql:{param_annotation,uppercase,avoid_subqueries};java:avoid_star_imports

src/main/java/de/tum/cit/aet/artemis/buildagent/service/BuildJobContainerService.java (1)

Pattern src/main/java/**/*.java: naming:CamelCase; principles:{single_responsibility,small_methods,no_duplication}; db:{perf_queries,datetime_not_timestamp}; rest:{stateless,singleton,delegate_logic,http_only,minimal_dtos}; dtos:{java_records,no_entities,min_data,single_resp}; di:constructor_injection; kiss:simple_code; file_handling:os_indep_paths; practices:{least_access,avoid_transactions,code_reuse,static_member_ref,prefer_primitives}; sql:{param_annotation,uppercase,avoid_subqueries};java:avoid_star_imports

src/main/java/de/tum/cit/aet/artemis/buildagent/service/BuildJobExecutionService.java (1)

Pattern src/main/java/**/*.java: naming:CamelCase; principles:{single_responsibility,small_methods,no_duplication}; db:{perf_queries,datetime_not_timestamp}; rest:{stateless,singleton,delegate_logic,http_only,minimal_dtos}; dtos:{java_records,no_entities,min_data,single_resp}; di:constructor_injection; kiss:simple_code; file_handling:os_indep_paths; practices:{least_access,avoid_transactions,code_reuse,static_member_ref,prefer_primitives}; sql:{param_annotation,uppercase,avoid_subqueries};java:avoid_star_imports

src/main/java/de/tum/cit/aet/artemis/buildagent/service/BuildJobManagementService.java (1)

Pattern src/main/java/**/*.java: naming:CamelCase; principles:{single_responsibility,small_methods,no_duplication}; db:{perf_queries,datetime_not_timestamp}; rest:{stateless,singleton,delegate_logic,http_only,minimal_dtos}; dtos:{java_records,no_entities,min_data,single_resp}; di:constructor_injection; kiss:simple_code; file_handling:os_indep_paths; practices:{least_access,avoid_transactions,code_reuse,static_member_ref,prefer_primitives}; sql:{param_annotation,uppercase,avoid_subqueries};java:avoid_star_imports

src/main/java/de/tum/cit/aet/artemis/buildagent/service/BuildLogsMap.java (1)

Pattern src/main/java/**/*.java: naming:CamelCase; principles:{single_responsibility,small_methods,no_duplication}; db:{perf_queries,datetime_not_timestamp}; rest:{stateless,singleton,delegate_logic,http_only,minimal_dtos}; dtos:{java_records,no_entities,min_data,single_resp}; di:constructor_injection; kiss:simple_code; file_handling:os_indep_paths; practices:{least_access,avoid_transactions,code_reuse,static_member_ref,prefer_primitives}; sql:{param_annotation,uppercase,avoid_subqueries};java:avoid_star_imports

🔇 Additional comments (5)
src/main/java/de/tum/cit/aet/artemis/buildagent/service/BuildAgentDockerService.java (3)

184-184: LGTM: Log size limiting properly implemented in callback methods

The changes correctly implement the new log size limiting mechanism in both the progress and completion callbacks, which aligns with the PR's objective to prevent system crashes from large build logs.

Also applies to: 192-192


285-285: LGTM: Proper error handling with size-limited logging

The architecture validation correctly implements the new log size limiting while maintaining proper error handling through LocalCIException.


Line range hint 184-285: Verify log size limits configuration

Let's ensure that the log size limits are properly configured in the application properties and that they're being respected across the build process.

✅ Verification successful

Log size limits are properly configured and enforced

The verification shows that log size limits are properly configured and enforced through:

  1. Configuration properties in application-buildagent.yml:

    build-logs:
        max-lines-per-job: 10000
        max-chars-per-line: 1024
  2. These limits are injected into BuildLogsMap class using Spring's @Value:

    @Value("${artemis.continuous-integration.build-logs.max-lines-per-job:10000}")
    private int maxLogLinesPerBuildJob;
    
    @Value("${artemis.continuous-integration.build-logs.max-chars-per-line:1024}")
    private int maxCharsPerLine;
  3. All log entries are consistently added through addBuildLogEntryIfBelowMaxLines method, which enforces these limits.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check for log size limit configuration and usage

# Look for log size limit configuration
echo "Searching for log size limit configuration..."
rg -l "maxLogLinesPerBuildJob|maxCharsPerLine" --type properties

# Check for other instances of log appending that might bypass the limits
echo "Checking for potential bypass of log limits..."
rg "appendBuildLogEntry|addBuildLogEntry" --type java

# Look for any TODO comments related to logging
echo "Checking for logging-related TODOs..."
rg -i "todo.*log" --type java

Length of output: 8118


Script:

#!/bin/bash
# Let's check the BuildLogsMap implementation to verify the log size limits
echo "Checking BuildLogsMap implementation..."
ast-grep --pattern 'class BuildLogsMap {
  $$$
}'

# Let's also check for any configuration properties files
echo "Searching for configuration files..."
fd -e yml -e yaml -e properties

# Let's check for any constant definitions related to log limits
echo "Checking for log limit constants..."
rg "MAX_LOG_LINES|MAX_CHARS" --type java

Length of output: 7420


Script:

#!/bin/bash
# Let's check the BuildLogsMap class implementation directly
echo "Checking BuildLogsMap class content..."
rg -A 20 "class BuildLogsMap" --type java

# Let's check application configuration files for log-related properties
echo "Checking application configuration files for log properties..."
cat src/main/resources/config/application.yml
cat src/main/resources/config/application-buildagent.yml

# Let's look for any log-related configuration in BuildLogsMap constructor or field declarations
echo "Checking for log-related configurations in BuildLogsMap..."
rg "private.*final.*MAX|private.*static.*final.*MAX" src/main/java/de/tum/cit/aet/artemis/buildagent/service/BuildLogsMap.java

Length of output: 20207

src/main/java/de/tum/cit/aet/artemis/buildagent/service/BuildJobContainerService.java (1)

419-419: LGTM: Log size limitation implementation looks correct.

The change from appendBuildLogEntry to addBuildLogEntryIfBelowMaxLines aligns with the PR objective to limit build log sizes. The implementation properly handles the log entry addition within the Docker command execution callback.

Let's verify the log size limitation implementation:

✅ Verification successful

LGTM: Log size limitation is properly implemented with configurable limits

The implementation is correct and well-designed:

  • The BuildLogsMap class properly implements size limits with configurable properties:
    • maxLogLinesPerBuildJob (default: 10000 lines)
    • maxCharsPerLine (default: 1024 chars)
  • The addBuildLogEntryIfBelowMaxLines method enforces these limits by:
    • Checking the number of lines before adding new entries
    • Truncating long lines that exceed the character limit
  • The change from appendBuildLogEntry to addBuildLogEntryIfBelowMaxLines ensures consistent application of these limits
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify the log size limitation implementation
# Test 1: Check if BuildLogsMap class properly implements the size limits
ast-grep --pattern 'class BuildLogsMap {
  $$$
  private $_ maxLogLinesPerBuildJob;
  private $_ maxCharsPerLine;
  $$$
}'

# Test 2: Check for any direct usage of appendBuildLogEntry that might bypass the size limits
rg "appendBuildLogEntry" -A 2

Length of output: 278


Script:

#!/bin/bash
# Let's try a different approach to verify the implementation

# Check the BuildLogsMap class implementation
fd "BuildLogsMap.java" --exec cat {}

# Check for any references to appendBuildLogEntry or addBuildLogEntryIfBelowMaxLines
rg -l "appendBuildLogEntry|addBuildLogEntryIfBelowMaxLines"

# Look for the configuration of max lines/chars
fd "application.yml|application.properties" --exec cat {}

Length of output: 28752

src/main/java/de/tum/cit/aet/artemis/buildagent/service/BuildJobExecutionService.java (1)

280-280: LGTM: Log limiting changes are consistently applied.

The changes to limit log size are applied consistently throughout the method.

Also applies to: 285-285, 292-292, 298-298, 314-314, 339-339, 352-352, 358-358

@krusche krusche force-pushed the chore/integrated-code-lifecycle/limit-build-logs-size branch from d2c9ca6 to 77a4cd0 Compare November 25, 2024 20:12
@github-actions github-actions bot added tests programming Pull requests that affect the corresponding module labels Nov 25, 2024
@az108 az108 added deploy:artemis-test2 and removed deployment-error Added by deployment workflows if an error occured labels Nov 25, 2024
Copy link

@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: 8

🧹 Outside diff range and nitpick comments (6)
src/main/java/de/tum/cit/aet/artemis/buildagent/dto/BuildLogDTO.java (1)

10-13: LGTM! Consider adding documentation.

The record structure is well-designed with appropriate annotations and field types. The use of ZonedDateTime and Serializable is good practice.

Consider adding Javadoc to document the record's purpose and field constraints:

 @JsonInclude(JsonInclude.Include.NON_EMPTY)
+/**
+ * Data Transfer Object for build log entries.
+ * Used for transferring build logs between services while ensuring serialization compatibility.
+ *
+ * @param time The timestamp when the log entry was created
+ * @param log The actual log message content
+ */
 public record BuildLogDTO(@NotNull ZonedDateTime time, @NotNull String log) implements Serializable {
src/main/java/de/tum/cit/aet/artemis/buildagent/service/BuildLogsMap.java (1)

21-25: Make configuration fields final

The configuration fields should be marked as final since they are only set once during initialization. This enforces immutability and makes the code's intent clearer.

-    private int maxLogLinesPerBuildJob;
+    private final int maxLogLinesPerBuildJob;

-    private int maxCharsPerLine;
+    private final int maxCharsPerLine;
src/main/java/de/tum/cit/aet/artemis/buildagent/dto/BuildResult.java (1)

30-30: Track TODO for future record conversion.

The TODO indicates this class should be converted to a record in the future. This would improve immutability and reduce boilerplate code.

Would you like me to create a GitHub issue to track this technical debt item?

src/main/java/de/tum/cit/aet/artemis/programming/service/localci/LocalCIResultProcessingService.java (1)

Line range hint 195-204: Consider adding error handling for oversized logs

When saving build logs to file, we should consider handling cases where logs might exceed size limits:

  1. Add logging to track when logs are truncated
  2. Consider notifying users when their logs are truncated
 if (!buildLogs.isEmpty()) {
     if (savedBuildJob != null) {
+        log.debug("Saving {} build logs for job {}", buildLogs.size(), savedBuildJob.getBuildJobId());
         buildLogEntryService.saveBuildLogsToFile(buildLogs, savedBuildJob.getBuildJobId(), participation.getProgrammingExercise());
+        if (buildLogs.size() >= 10000) {
+            log.warn("Build logs were truncated for job {} due to size limits", savedBuildJob.getBuildJobId());
+            programmingMessagingService.notifyUserAboutBuildLogsTruncated(participation);
+        }
     } else {
         log.warn("Couldn't save build logs as build job {} was not saved", buildJob.id());
     }
 }
src/test/java/de/tum/cit/aet/artemis/programming/icl/LocalCIResourceIntegrationTest.java (1)

Line range hint 335-341: Test should verify build log size limits

The test should be enhanced to verify the new size limits introduced in this PR:

  1. Maximum number of logs (10,000)
  2. Maximum characters per log (1,024)

Consider adding these test cases:

-    BuildLogDTO buildLogEntry = new BuildLogDTO(ZonedDateTime.now(), "Dummy log");
-    buildLogEntryService.saveBuildLogsToFile(List.of(buildLogEntry), "6", programmingExercise);
-    var response = request.get("/api/build-log/6", HttpStatus.OK, String.class);
-    assertThat(response).contains("Dummy log");
+    // Test max characters per log
+    String longLog = "a".repeat(1025);
+    BuildLogDTO oversizedLogEntry = new BuildLogDTO(ZonedDateTime.now(), longLog);
+    buildLogEntryService.saveBuildLogsToFile(List.of(oversizedLogEntry), "6", programmingExercise);
+    var response1 = request.get("/api/build-log/6", HttpStatus.OK, String.class);
+    assertThat(response1).hasSize(1024); // Verify truncation
+    
+    // Test max number of logs
+    List<BuildLogDTO> manyLogs = IntStream.range(0, 10001)
+        .mapToObj(i -> new BuildLogDTO(ZonedDateTime.now(), "Log " + i))
+        .collect(Collectors.toList());
+    buildLogEntryService.saveBuildLogsToFile(manyLogs, "6", programmingExercise);
+    var response2 = request.get("/api/build-log/6", HttpStatus.OK, String.class);
+    assertThat(response2.lines().count()).isEqualTo(10000); // Verify log count limit

Additionally, consider renaming the test to better describe what it's testing:

-    void testGetBuildLogsForResult()
+    void testGetBuildLogsForResult_respectsSizeLimits()
src/main/java/de/tum/cit/aet/artemis/programming/service/BuildLogEntryService.java (1)

Line range hint 1-479: Consider architectural improvements for better separation of concerns

The service currently handles both database and file operations. Consider:

  1. Extracting file operations to a dedicated BuildLogFileService
  2. Adding metrics to monitor:
    • Total log size per build
    • Number of truncated logs
    • Storage space usage

This would improve maintainability and provide better observability of the log size limits.

📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between d2c9ca6 and 77a4cd0.

📒 Files selected for processing (12)
  • src/main/java/de/tum/cit/aet/artemis/buildagent/dto/BuildLogDTO.java (1 hunks)
  • src/main/java/de/tum/cit/aet/artemis/buildagent/dto/BuildResult.java (3 hunks)
  • src/main/java/de/tum/cit/aet/artemis/buildagent/dto/ResultQueueItem.java (1 hunks)
  • src/main/java/de/tum/cit/aet/artemis/buildagent/service/BuildAgentDockerService.java (1 hunks)
  • src/main/java/de/tum/cit/aet/artemis/buildagent/service/BuildJobContainerService.java (2 hunks)
  • src/main/java/de/tum/cit/aet/artemis/buildagent/service/BuildJobExecutionService.java (1 hunks)
  • src/main/java/de/tum/cit/aet/artemis/buildagent/service/BuildJobManagementService.java (3 hunks)
  • src/main/java/de/tum/cit/aet/artemis/buildagent/service/BuildLogsMap.java (1 hunks)
  • src/main/java/de/tum/cit/aet/artemis/buildagent/service/SharedQueueProcessingService.java (3 hunks)
  • src/main/java/de/tum/cit/aet/artemis/programming/service/BuildLogEntryService.java (3 hunks)
  • src/main/java/de/tum/cit/aet/artemis/programming/service/localci/LocalCIResultProcessingService.java (2 hunks)
  • src/test/java/de/tum/cit/aet/artemis/programming/icl/LocalCIResourceIntegrationTest.java (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (4)
  • src/main/java/de/tum/cit/aet/artemis/buildagent/service/BuildAgentDockerService.java
  • src/main/java/de/tum/cit/aet/artemis/buildagent/service/BuildJobContainerService.java
  • src/main/java/de/tum/cit/aet/artemis/buildagent/service/BuildJobExecutionService.java
  • src/main/java/de/tum/cit/aet/artemis/buildagent/service/BuildJobManagementService.java
🧰 Additional context used
📓 Path-based instructions (8)
src/main/java/de/tum/cit/aet/artemis/buildagent/dto/BuildLogDTO.java (1)

Pattern src/main/java/**/*.java: naming:CamelCase; principles:{single_responsibility,small_methods,no_duplication}; db:{perf_queries,datetime_not_timestamp}; rest:{stateless,singleton,delegate_logic,http_only,minimal_dtos}; dtos:{java_records,no_entities,min_data,single_resp}; di:constructor_injection; kiss:simple_code; file_handling:os_indep_paths; practices:{least_access,avoid_transactions,code_reuse,static_member_ref,prefer_primitives}; sql:{param_annotation,uppercase,avoid_subqueries};java:avoid_star_imports

src/main/java/de/tum/cit/aet/artemis/buildagent/dto/BuildResult.java (1)

Pattern src/main/java/**/*.java: naming:CamelCase; principles:{single_responsibility,small_methods,no_duplication}; db:{perf_queries,datetime_not_timestamp}; rest:{stateless,singleton,delegate_logic,http_only,minimal_dtos}; dtos:{java_records,no_entities,min_data,single_resp}; di:constructor_injection; kiss:simple_code; file_handling:os_indep_paths; practices:{least_access,avoid_transactions,code_reuse,static_member_ref,prefer_primitives}; sql:{param_annotation,uppercase,avoid_subqueries};java:avoid_star_imports

src/main/java/de/tum/cit/aet/artemis/buildagent/dto/ResultQueueItem.java (1)

Pattern src/main/java/**/*.java: naming:CamelCase; principles:{single_responsibility,small_methods,no_duplication}; db:{perf_queries,datetime_not_timestamp}; rest:{stateless,singleton,delegate_logic,http_only,minimal_dtos}; dtos:{java_records,no_entities,min_data,single_resp}; di:constructor_injection; kiss:simple_code; file_handling:os_indep_paths; practices:{least_access,avoid_transactions,code_reuse,static_member_ref,prefer_primitives}; sql:{param_annotation,uppercase,avoid_subqueries};java:avoid_star_imports

src/main/java/de/tum/cit/aet/artemis/buildagent/service/BuildLogsMap.java (1)

Pattern src/main/java/**/*.java: naming:CamelCase; principles:{single_responsibility,small_methods,no_duplication}; db:{perf_queries,datetime_not_timestamp}; rest:{stateless,singleton,delegate_logic,http_only,minimal_dtos}; dtos:{java_records,no_entities,min_data,single_resp}; di:constructor_injection; kiss:simple_code; file_handling:os_indep_paths; practices:{least_access,avoid_transactions,code_reuse,static_member_ref,prefer_primitives}; sql:{param_annotation,uppercase,avoid_subqueries};java:avoid_star_imports

src/main/java/de/tum/cit/aet/artemis/buildagent/service/SharedQueueProcessingService.java (1)

Pattern src/main/java/**/*.java: naming:CamelCase; principles:{single_responsibility,small_methods,no_duplication}; db:{perf_queries,datetime_not_timestamp}; rest:{stateless,singleton,delegate_logic,http_only,minimal_dtos}; dtos:{java_records,no_entities,min_data,single_resp}; di:constructor_injection; kiss:simple_code; file_handling:os_indep_paths; practices:{least_access,avoid_transactions,code_reuse,static_member_ref,prefer_primitives}; sql:{param_annotation,uppercase,avoid_subqueries};java:avoid_star_imports

src/main/java/de/tum/cit/aet/artemis/programming/service/BuildLogEntryService.java (1)

Pattern src/main/java/**/*.java: naming:CamelCase; principles:{single_responsibility,small_methods,no_duplication}; db:{perf_queries,datetime_not_timestamp}; rest:{stateless,singleton,delegate_logic,http_only,minimal_dtos}; dtos:{java_records,no_entities,min_data,single_resp}; di:constructor_injection; kiss:simple_code; file_handling:os_indep_paths; practices:{least_access,avoid_transactions,code_reuse,static_member_ref,prefer_primitives}; sql:{param_annotation,uppercase,avoid_subqueries};java:avoid_star_imports

src/main/java/de/tum/cit/aet/artemis/programming/service/localci/LocalCIResultProcessingService.java (1)

Pattern src/main/java/**/*.java: naming:CamelCase; principles:{single_responsibility,small_methods,no_duplication}; db:{perf_queries,datetime_not_timestamp}; rest:{stateless,singleton,delegate_logic,http_only,minimal_dtos}; dtos:{java_records,no_entities,min_data,single_resp}; di:constructor_injection; kiss:simple_code; file_handling:os_indep_paths; practices:{least_access,avoid_transactions,code_reuse,static_member_ref,prefer_primitives}; sql:{param_annotation,uppercase,avoid_subqueries};java:avoid_star_imports

src/test/java/de/tum/cit/aet/artemis/programming/icl/LocalCIResourceIntegrationTest.java (1)

Pattern src/test/java/**/*.java: test_naming: descriptive; test_size: small_specific; fixed_data: true; junit5_features: true; assert_use: assertThat; assert_specificity: true; archunit_use: enforce_package_rules; db_query_count_tests: track_performance; util_service_factory_pattern: true; avoid_db_access: true; mock_strategy: static_mocks; context_restart_minimize: true

🔇 Additional comments (12)
src/main/java/de/tum/cit/aet/artemis/buildagent/dto/ResultQueueItem.java (2)

Line range hint 1-10: LGTM! Well-structured DTO with proper annotations

The class follows DTO best practices with appropriate serialization support and JSON handling.


11-11: Document this breaking change in release notes

The change from BuildLogEntry to BuildLogDTO is well-aligned with DTO patterns, but as noted in the comment, this is a breaking change affecting shared data structures.

Let's verify the impact and usage of this change:

src/main/java/de/tum/cit/aet/artemis/buildagent/service/BuildLogsMap.java (1)

21-82: Implementation successfully addresses log size limitations

The implementation effectively achieves the PR's objective of preventing system crashes from large build logs by:

  1. Limiting the number of log entries per build job
  2. Restricting the character length of each log entry
  3. Using thread-safe data structures

The suggested improvements for parameter validation and thread safety will further enhance the robustness of this solution.

src/main/java/de/tum/cit/aet/artemis/programming/service/localci/LocalCIResultProcessingService.java (2)

30-30: LGTM: Clean import addition

The import follows Java best practices by avoiding star imports and maintaining a clear organization.


136-136: Verify BuildLogDTO size limits implementation

The change from BuildLogEntry to BuildLogDTO aligns with the PR's objective to limit build log sizes. However, we should verify that the DTO properly implements the size constraints (10,000 logs max, 1,024 chars per log).

✅ Verification successful

Let's search more specifically for the BuildLogDTO implementation and any size-related constraints.


Let's check the actual implementation of BuildLogDTO and the BuildLogsMap class which seems to handle the size constraints.


Size constraints are properly implemented in BuildLogsMap

The size constraints are correctly implemented in the BuildLogsMap service, which handles BuildLogDTO objects:

  • Maximum 10,000 logs per build job (maxLogLinesPerBuildJob)
  • Maximum 1,024 characters per log line (maxCharsPerLine)
  • Truncation is properly implemented for both limits with appropriate handling

The change from BuildLogEntry to BuildLogDTO maintains these size constraints through the BuildLogsMap service, which enforces the limits before storing any logs.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify BuildLogDTO implementation contains size constraints
# Expected: Find size limit constants and truncation logic in BuildLogDTO

# Search for size limit constants
echo "Searching for size limit constants..."
rg -l "10000|1024" --type java

# Search for BuildLogDTO implementation
echo "Searching for BuildLogDTO implementation..."
ast-grep --pattern 'class BuildLogDTO {
  $$$
}'

Length of output: 2660


Script:

#!/bin/bash
# Search for BuildLogDTO file
echo "Searching for BuildLogDTO file..."
fd BuildLogDTO

# If found, examine its content
echo "Searching for size-related constants and methods in BuildLogDTO..."
rg -A 5 "class BuildLogDTO" --type java

# Search for any build log size limits in the codebase
echo "Searching for build log size limit references..."
rg -A 5 "(?i)(build.*log.*size|log.*size.*limit)" --type java

Length of output: 8452


Script:

#!/bin/bash
# Check BuildLogDTO implementation
echo "Content of BuildLogDTO:"
cat src/main/java/de/tum/cit/aet/artemis/buildagent/dto/BuildLogDTO.java

# Check BuildLogsMap implementation for size constants
echo "Content of BuildLogsMap:"
cat src/main/java/de/tum/cit/aet/artemis/buildagent/service/BuildLogsMap.java

Length of output: 4117

src/test/java/de/tum/cit/aet/artemis/programming/icl/LocalCIResourceIntegrationTest.java (1)

32-32: LGTM!

The import of BuildLogDTO is correctly placed and aligns with the PR's objective of managing build log sizes.

src/main/java/de/tum/cit/aet/artemis/buildagent/service/SharedQueueProcessingService.java (4)

52-52: LGTM: Import change aligns with build log size limitation.

The addition of BuildLogDTO import is consistent with the PR's objective to implement build log size limitations.


400-403: LGTM: Build log size limitation implemented correctly in success path.

The implementation correctly retrieves truncated logs and cleans up afterward, preventing memory leaks.


438-441: LGTM: Build log size limitation implemented consistently in failure path.

The implementation maintains consistency with the success path, ensuring log size limitations are applied uniformly.


400-403: Extract duplicated build log handling logic.

The build log retrieval and removal logic is duplicated between success and failure paths.

Also applies to: 438-441

src/main/java/de/tum/cit/aet/artemis/programming/service/BuildLogEntryService.java (2)

26-26: LGTM: Import follows Java best practices

The specific import of BuildLogDTO follows Java best practices by avoiding wildcard imports.


304-311: LGTM: Well-documented method signature change

The updated method signature and Javadoc are thorough, clearly documenting the parameter changes and possible exceptions.

@github-actions github-actions bot added the deployment-error Added by deployment workflows if an error occured label Nov 25, 2024
@az108 az108 removed the deployment-error Added by deployment workflows if an error occured label Nov 25, 2024
Copy link

@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: 6

🧹 Outside diff range and nitpick comments (10)
src/main/java/de/tum/cit/aet/artemis/buildagent/dto/BuildLogDTO.java (1)

1-13: Consider validation at the DTO level vs. service level.

While the current implementation is clean, consider whether size validation should be:

  1. Embedded in the DTO using annotations (fail-fast approach)
  2. Handled at the service level (more flexible but less enforced)
  3. Both (defense in depth)

This decision impacts where truncation occurs and how invalid data is handled across the system.

src/main/java/de/tum/cit/aet/artemis/buildagent/dto/ResultQueueItem.java (1)

8-9: Document breaking change in release notes.

The comment indicates this is a breaking change affecting shared data structures in Hazelcast/Redis. This change should be prominently documented in release notes.

Consider adding a detailed migration guide in the release notes covering:

  1. Impact on existing Hazelcast/Redis data
  2. Required steps for system administrators
  3. Potential downtime during migration
  4. Rollback procedures

Also applies to: 11-11

src/main/java/de/tum/cit/aet/artemis/buildagent/service/BuildLogsMap.java (2)

21-25: Document configuration properties in application properties file

The configuration properties should be documented in the application properties file with descriptions of their purpose and impact on system behavior.

Add the following to your application properties documentation:

# Maximum number of build log lines stored per job (default: 10000)
artemis.continuous-integration.build-logs.max-lines-per-job=10000
# Maximum characters per log line to prevent memory issues (default: 1024)
artemis.continuous-integration.build-logs.max-chars-per-line=1024

58-59: Enhance removeBuildLogs method with validation and feedback

The method should validate input and provide feedback about the operation's success.

Consider this improvement:

-    public void removeBuildLogs(String buildJobId) {
-        buildLogsMap.remove(buildJobId);
+    public boolean removeBuildLogs(String buildJobId) {
+        if (buildJobId == null || buildJobId.isBlank()) {
+            throw new IllegalArgumentException("buildJobId cannot be null or blank");
+        }
+        return buildLogsMap.remove(buildJobId) != null;
     }
src/main/java/de/tum/cit/aet/artemis/buildagent/dto/BuildResult.java (2)

30-30: Consider implications of record conversion

While converting to a record would be ideal for a DTO, note that this class extends AbstractBuildResultNotificationDTO. Java records don't support inheritance, so this would require architectural changes:

  1. Extract common fields to an interface
  2. Make this class a record implementing that interface
  3. Update the inheritance hierarchy

Would you like me to propose a detailed refactoring plan?


127-128: Add null safety to the stream operation

While the stream operation is efficient, consider adding null checks to prevent NullPointerException.

Consider this safer implementation:

-        return buildLogEntries.stream().map(log -> new BuildLogEntry(log.time(), log.log())).toList();
+        return buildLogEntries == null ? List.of() : buildLogEntries.stream()
+            .map(log -> new BuildLogEntry(log.time(), log.log()))
+            .toList();
src/main/java/de/tum/cit/aet/artemis/programming/service/localci/LocalCIResultProcessingService.java (1)

Line range hint 192-199: Add error handling for build logs file saving operation

While the code handles the case of a missing build job, it should also handle potential errors during the file saving operation to ensure robustness.

Consider wrapping the file operation in a try-catch block:

 if (!buildLogs.isEmpty()) {
     if (savedBuildJob != null) {
-        buildLogEntryService.saveBuildLogsToFile(buildLogs, savedBuildJob.getBuildJobId(), participation.getProgrammingExercise());
+        try {
+            buildLogEntryService.saveBuildLogsToFile(buildLogs, savedBuildJob.getBuildJobId(), participation.getProgrammingExercise());
+        } catch (Exception e) {
+            log.error("Failed to save build logs to file for build job {}: {}", savedBuildJob.getBuildJobId(), e.getMessage());
+        }
     } else {
         log.warn("Couldn't save build logs as build job {} was not saved", buildJob.id());
     }
 }
src/test/java/de/tum/cit/aet/artemis/programming/icl/LocalCIResourceIntegrationTest.java (1)

Line range hint 335-341: Enhance test coverage for build log size limits

The test should be extended to verify the new size limits mentioned in the PR objectives (10,000 logs and 1,024 characters per log). Consider adding test cases for:

  1. Maximum number of logs (10,000)
  2. Maximum characters per log (1,024)
  3. Truncation behavior when limits are exceeded

Here's a suggested enhancement:

-            BuildLogDTO buildLogEntry = new BuildLogDTO(ZonedDateTime.now(), "Dummy log");
-            buildLogEntryService.saveBuildLogsToFile(List.of(buildLogEntry), "6", programmingExercise);
-            var response = request.get("/api/build-log/6", HttpStatus.OK, String.class);
-            assertThat(response).contains("Dummy log");
+            // Test max characters per log
+            String longLog = "a".repeat(1500);
+            BuildLogDTO oversizedLogEntry = new BuildLogDTO(ZonedDateTime.now(), longLog);
+            buildLogEntryService.saveBuildLogsToFile(List.of(oversizedLogEntry), "6", programmingExercise);
+            var response = request.get("/api/build-log/6", HttpStatus.OK, String.class);
+            assertThat(response).hasSize(1024);  // Verify truncation to 1024 chars
+            
+            // Test max number of logs
+            List<BuildLogDTO> manyLogs = new ArrayList<>();
+            for (int i = 0; i < 11000; i++) {
+                manyLogs.add(new BuildLogDTO(ZonedDateTime.now(), "Log " + i));
+            }
+            buildLogEntryService.saveBuildLogsToFile(manyLogs, "6", programmingExercise);
+            response = request.get("/api/build-log/6", HttpStatus.OK, String.class);
+            assertThat(response.lines().count()).isEqualTo(10000);  // Verify max logs limit
src/main/java/de/tum/cit/aet/artemis/buildagent/service/SharedQueueProcessingService.java (1)

400-403: Consider adding logging for truncation events

To help monitor the impact of log truncation, consider adding debug logging when logs are truncated. This would help track how often and by how much logs are being truncated.

 List<BuildLogDTO> buildLogs = buildLogsMap.getAndTruncateBuildLogs(buildJob.id());
+if (log.isDebugEnabled()) {
+    log.debug("Retrieved {} build logs for job {}", buildLogs.size(), buildJob.id());
+}
 buildLogsMap.removeBuildLogs(buildJob.id());

Also applies to: 438-441

src/main/java/de/tum/cit/aet/artemis/programming/service/BuildLogEntryService.java (1)

327-328: Optimize StringBuilder usage

Pre-size the StringBuilder to improve performance and reduce memory reallocations. Calculate the estimated size based on the number of entries and maximum log length.

Apply this diff:

+// Pre-calculate buffer size: entries * (timestamp + tab + max log length)
+int estimatedSize = buildLogEntries.size() * (24 + 1 + 1024);
-StringBuilder logsStringBuilder = new StringBuilder();
+StringBuilder logsStringBuilder = new StringBuilder(estimatedSize);
📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between d2c9ca6 and 77a4cd0.

📒 Files selected for processing (12)
  • src/main/java/de/tum/cit/aet/artemis/buildagent/dto/BuildLogDTO.java (1 hunks)
  • src/main/java/de/tum/cit/aet/artemis/buildagent/dto/BuildResult.java (3 hunks)
  • src/main/java/de/tum/cit/aet/artemis/buildagent/dto/ResultQueueItem.java (1 hunks)
  • src/main/java/de/tum/cit/aet/artemis/buildagent/service/BuildAgentDockerService.java (1 hunks)
  • src/main/java/de/tum/cit/aet/artemis/buildagent/service/BuildJobContainerService.java (2 hunks)
  • src/main/java/de/tum/cit/aet/artemis/buildagent/service/BuildJobExecutionService.java (1 hunks)
  • src/main/java/de/tum/cit/aet/artemis/buildagent/service/BuildJobManagementService.java (3 hunks)
  • src/main/java/de/tum/cit/aet/artemis/buildagent/service/BuildLogsMap.java (1 hunks)
  • src/main/java/de/tum/cit/aet/artemis/buildagent/service/SharedQueueProcessingService.java (3 hunks)
  • src/main/java/de/tum/cit/aet/artemis/programming/service/BuildLogEntryService.java (3 hunks)
  • src/main/java/de/tum/cit/aet/artemis/programming/service/localci/LocalCIResultProcessingService.java (2 hunks)
  • src/test/java/de/tum/cit/aet/artemis/programming/icl/LocalCIResourceIntegrationTest.java (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (4)
  • src/main/java/de/tum/cit/aet/artemis/buildagent/service/BuildAgentDockerService.java
  • src/main/java/de/tum/cit/aet/artemis/buildagent/service/BuildJobContainerService.java
  • src/main/java/de/tum/cit/aet/artemis/buildagent/service/BuildJobExecutionService.java
  • src/main/java/de/tum/cit/aet/artemis/buildagent/service/BuildJobManagementService.java
🧰 Additional context used
📓 Path-based instructions (8)
src/main/java/de/tum/cit/aet/artemis/buildagent/dto/BuildLogDTO.java (1)

Pattern src/main/java/**/*.java: naming:CamelCase; principles:{single_responsibility,small_methods,no_duplication}; db:{perf_queries,datetime_not_timestamp}; rest:{stateless,singleton,delegate_logic,http_only,minimal_dtos}; dtos:{java_records,no_entities,min_data,single_resp}; di:constructor_injection; kiss:simple_code; file_handling:os_indep_paths; practices:{least_access,avoid_transactions,code_reuse,static_member_ref,prefer_primitives}; sql:{param_annotation,uppercase,avoid_subqueries};java:avoid_star_imports

src/main/java/de/tum/cit/aet/artemis/buildagent/dto/BuildResult.java (1)

Pattern src/main/java/**/*.java: naming:CamelCase; principles:{single_responsibility,small_methods,no_duplication}; db:{perf_queries,datetime_not_timestamp}; rest:{stateless,singleton,delegate_logic,http_only,minimal_dtos}; dtos:{java_records,no_entities,min_data,single_resp}; di:constructor_injection; kiss:simple_code; file_handling:os_indep_paths; practices:{least_access,avoid_transactions,code_reuse,static_member_ref,prefer_primitives}; sql:{param_annotation,uppercase,avoid_subqueries};java:avoid_star_imports

src/main/java/de/tum/cit/aet/artemis/buildagent/dto/ResultQueueItem.java (1)

Pattern src/main/java/**/*.java: naming:CamelCase; principles:{single_responsibility,small_methods,no_duplication}; db:{perf_queries,datetime_not_timestamp}; rest:{stateless,singleton,delegate_logic,http_only,minimal_dtos}; dtos:{java_records,no_entities,min_data,single_resp}; di:constructor_injection; kiss:simple_code; file_handling:os_indep_paths; practices:{least_access,avoid_transactions,code_reuse,static_member_ref,prefer_primitives}; sql:{param_annotation,uppercase,avoid_subqueries};java:avoid_star_imports

src/main/java/de/tum/cit/aet/artemis/buildagent/service/BuildLogsMap.java (1)

Pattern src/main/java/**/*.java: naming:CamelCase; principles:{single_responsibility,small_methods,no_duplication}; db:{perf_queries,datetime_not_timestamp}; rest:{stateless,singleton,delegate_logic,http_only,minimal_dtos}; dtos:{java_records,no_entities,min_data,single_resp}; di:constructor_injection; kiss:simple_code; file_handling:os_indep_paths; practices:{least_access,avoid_transactions,code_reuse,static_member_ref,prefer_primitives}; sql:{param_annotation,uppercase,avoid_subqueries};java:avoid_star_imports

src/main/java/de/tum/cit/aet/artemis/buildagent/service/SharedQueueProcessingService.java (1)

Pattern src/main/java/**/*.java: naming:CamelCase; principles:{single_responsibility,small_methods,no_duplication}; db:{perf_queries,datetime_not_timestamp}; rest:{stateless,singleton,delegate_logic,http_only,minimal_dtos}; dtos:{java_records,no_entities,min_data,single_resp}; di:constructor_injection; kiss:simple_code; file_handling:os_indep_paths; practices:{least_access,avoid_transactions,code_reuse,static_member_ref,prefer_primitives}; sql:{param_annotation,uppercase,avoid_subqueries};java:avoid_star_imports

src/main/java/de/tum/cit/aet/artemis/programming/service/BuildLogEntryService.java (1)

Pattern src/main/java/**/*.java: naming:CamelCase; principles:{single_responsibility,small_methods,no_duplication}; db:{perf_queries,datetime_not_timestamp}; rest:{stateless,singleton,delegate_logic,http_only,minimal_dtos}; dtos:{java_records,no_entities,min_data,single_resp}; di:constructor_injection; kiss:simple_code; file_handling:os_indep_paths; practices:{least_access,avoid_transactions,code_reuse,static_member_ref,prefer_primitives}; sql:{param_annotation,uppercase,avoid_subqueries};java:avoid_star_imports

src/main/java/de/tum/cit/aet/artemis/programming/service/localci/LocalCIResultProcessingService.java (1)

Pattern src/main/java/**/*.java: naming:CamelCase; principles:{single_responsibility,small_methods,no_duplication}; db:{perf_queries,datetime_not_timestamp}; rest:{stateless,singleton,delegate_logic,http_only,minimal_dtos}; dtos:{java_records,no_entities,min_data,single_resp}; di:constructor_injection; kiss:simple_code; file_handling:os_indep_paths; practices:{least_access,avoid_transactions,code_reuse,static_member_ref,prefer_primitives}; sql:{param_annotation,uppercase,avoid_subqueries};java:avoid_star_imports

src/test/java/de/tum/cit/aet/artemis/programming/icl/LocalCIResourceIntegrationTest.java (1)

Pattern src/test/java/**/*.java: test_naming: descriptive; test_size: small_specific; fixed_data: true; junit5_features: true; assert_use: assertThat; assert_specificity: true; archunit_use: enforce_package_rules; db_query_count_tests: track_performance; util_service_factory_pattern: true; avoid_db_access: true; mock_strategy: static_mocks; context_restart_minimize: true

🔇 Additional comments (13)
src/main/java/de/tum/cit/aet/artemis/buildagent/dto/BuildLogDTO.java (2)

1-9: LGTM! Package and imports are well-organized.

The package naming and import statements follow best practices with specific imports and logical grouping.


11-11: Verify ZonedDateTime serialization across the system.

The use of ZonedDateTime might require special handling during JSON serialization/deserialization, especially when transmitted over Hazelcast.

✅ Verification successful

Let me generate another script to specifically look for ZonedDateTime serialization configuration and usage.


Based on the analysis of the shell script results, I can now provide a final response:

ZonedDateTime serialization is properly configured and safe to use.

The codebase has proper configuration for handling ZonedDateTime serialization:

  • JavaTimeModule is registered in JacksonConfiguration for proper datetime handling
  • DateTimeFormatConfiguration ensures ISO format for dates
  • Multiple services consistently use DateTimeFormatter for string conversions
  • The system uses standard Jackson serialization with proper modules
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for Jackson configuration related to ZonedDateTime handling
rg -l "ObjectMapper|JavaTimeModule|DateTimeFormatter" src/

# Search for other DTOs using ZonedDateTime to ensure consistent handling
ast-grep --pattern 'record $NAME($_) { $$$ ZonedDateTime $$$ }'

Length of output: 9475


Script:

#!/bin/bash
# Check for Jackson configuration specifically for ZonedDateTime
rg -A 5 "JavaTimeModule|ZonedDateTime.*serializ|DateTimeFormatter" src/main/

# Look for ObjectMapper configuration
rg -A 5 "ObjectMapper.*configure" src/main/

# Check JacksonConfiguration class specifically
cat src/main/java/de/tum/cit/aet/artemis/core/config/JacksonConfiguration.java

Length of output: 23617

src/main/java/de/tum/cit/aet/artemis/buildagent/dto/ResultQueueItem.java (1)

11-11: LGTM! Verify data migration strategy.

The change from BuildLogEntry to BuildLogDTO aligns well with DTO patterns and the PR's objective to limit build log sizes. The record structure is appropriate for this use case.

Let's verify the migration strategy and usage:

src/main/java/de/tum/cit/aet/artemis/buildagent/dto/BuildResult.java (2)

136-139: LGTM! Method follows best practices

The setter implementation:

  • Follows the least access principle (package-private)
  • Maintains the hasLogs state correctly
  • Accepts the new DTO type consistently

45-45: LGTM! Verify BuildLogDTO usage across the codebase

The change from BuildLogEntry to BuildLogDTO aligns with the PR's objective to limit build log size and follows the DTO pattern correctly.

Let's verify the consistency of BuildLogDTO usage:

✅ Verification successful

Let me try a different approach to verify the BuildLogDTO usage.


Change from BuildLogEntry to BuildLogDTO is correctly implemented

The verification shows that:

  1. BuildLogDTO is properly defined as a record in src/main/java/de/tum/cit/aet/artemis/buildagent/dto/BuildLogDTO.java
  2. The DTO is consistently used across the build agent codebase
  3. The remaining BuildLogEntry references are in different components (main Artemis application, tests) and are not affected by this build agent change
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check for any remaining BuildLogEntry usages that might need updating
# and verify that BuildLogDTO is properly defined

# Check for BuildLogEntry direct usage
echo "Checking for BuildLogEntry usage patterns..."
rg "BuildLogEntry(?!.*import)" -g "!*.java.orig" -g "!*.java.bak"

# Verify BuildLogDTO definition
echo "Verifying BuildLogDTO structure..."
ast-grep --pattern 'record BuildLogDTO($_, $_) { $$$  }'

Length of output: 670


Script:

#!/bin/bash
# Search for BuildLogEntry and BuildLogDTO usages with proper regex
echo "Checking BuildLogEntry usages..."
rg --pcre2 "BuildLogEntry(?!\s*import)" -l

echo "Checking BuildLogDTO usages and definition..."
rg "BuildLogDTO" -A 3

# Find all Java files that might contain the DTO
echo "Looking for BuildLogDTO definition file..."
fd "BuildLogDTO.java"

Length of output: 19009

src/main/java/de/tum/cit/aet/artemis/programming/service/localci/LocalCIResultProcessingService.java (2)

30-30: LGTM!

The import is correctly placed and follows the Java import guidelines.


136-136: Verify BuildLogDTO size limits implementation

The type change aligns with the PR objective to limit build logs size. Let's verify that BuildLogDTO properly implements the size constraints.

src/test/java/de/tum/cit/aet/artemis/programming/icl/LocalCIResourceIntegrationTest.java (1)

32-32: LGTM!

The BuildLogDTO import is correctly placed and follows the alphabetical ordering convention.

src/main/java/de/tum/cit/aet/artemis/buildagent/service/SharedQueueProcessingService.java (3)

52-52: LGTM: Import statement follows guidelines

The BuildLogDTO import is correctly placed in the dto section, maintaining clean code organization.


400-403: Previous comment about duplicated build log handling still applies

The build log retrieval and removal logic is duplicated between success and failure paths.


Line range hint 438-444: LGTM: Consistent log handling in error path

The error path correctly uses the truncated logs and properly updates the BuildResult, maintaining consistency with the success path.

src/main/java/de/tum/cit/aet/artemis/programming/service/BuildLogEntryService.java (2)

26-26: LGTM: Import of BuildLogDTO is appropriate

The introduction of BuildLogDTO aligns with the PR's objective of limiting build logs size and follows proper DTO pattern for data transfer.


304-311: LGTM: Well-documented method signature change

The method signature change to use BuildLogDTO is appropriate, and the Javadoc is comprehensive with proper parameter and exception documentation.

coderabbitai[bot]
coderabbitai bot previously approved these changes Nov 25, 2024
Copy link
Contributor

@az108 az108 left a comment

Choose a reason for hiding this comment

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

Overall Code LGTM, only one small request for 3 spots

Copy link
Contributor

@az108 az108 left a comment

Choose a reason for hiding this comment

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

Thanks for the quick changes 👍

Copy link

@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 (6)
src/main/java/de/tum/cit/aet/artemis/buildagent/service/BuildLogsMap.java (6)

27-28: Enhance map documentation with size constraints

The comment should include information about the size constraints to better document the behavior.

-    // buildJobId --> List of build logs
+    // Maps buildJobId to a size-constrained list of build logs (max ${maxLogLinesPerBuildJob} entries per job)

36-37: Consider using @nonnull annotation

Since this method always returns a non-null value, consider adding @Nonnull annotation to make the contract explicit.

+    @Nonnull
     public void appendBuildLogEntry(String buildJobId, String message) {

48-55: Add logging for dropped entries

Consider logging when entries are dropped due to size constraints to help with debugging and monitoring.

     public void appendBuildLogEntry(String buildJobId, BuildLogDTO buildLog) {
         List<BuildLogDTO> buildLogs = buildLogsMap.computeIfAbsent(buildJobId, k -> new ArrayList<>());
-        if (buildLogs.size() < maxLogLinesPerBuildJob) {
+        synchronized (buildLogs) {
+            if (buildLogs.size() >= maxLogLinesPerBuildJob) {
+                log.warn("Dropping build log entry for job {} as maximum size {} is reached", buildJobId, maxLogLinesPerBuildJob);
+                return;
+            }
             if (buildLog.log() != null && buildLog.log().length() > maxCharsPerLine) {
+                log.debug("Truncating build log entry for job {} from {} to {} characters", buildJobId, buildLog.log().length(), maxCharsPerLine);
                 buildLog = new BuildLogDTO(buildLog.time(), buildLog.log().substring(0, maxCharsPerLine) + "\n");
             }
             buildLogs.add(buildLog);
         }
     }

58-59: Consider returning boolean to indicate success

The method could return a boolean to indicate whether logs were actually removed, which could be useful for the caller.

-    public void removeBuildLogs(String buildJobId) {
-        buildLogsMap.remove(buildJobId);
+    public boolean removeBuildLogs(String buildJobId) {
+        return buildLogsMap.remove(buildJobId) != null;
     }

77-79: Improve truncation message handling

The truncation message should be more informative and possibly include the number of dropped entries.

             List<BuildLogDTO> truncatedBuildLogs = new ArrayList<>(buildLogs.subList(0, maxLogLinesPerBuildJob));
-            truncatedBuildLogs.add(new BuildLogDTO(ZonedDateTime.now(), "Truncated build logs...\n"));
+            int droppedEntries = buildLogs.size() - maxLogLinesPerBuildJob;
+            truncatedBuildLogs.add(new BuildLogDTO(ZonedDateTime.now(), 
+                String.format("Truncated %d build log entries to stay within limit of %d entries\n", 
+                    droppedEntries, maxLogLinesPerBuildJob)));

21-82: Consider adding metrics collection

To better monitor the system's behavior, consider adding metrics collection for:

  • Number of truncated logs
  • Number of dropped entries
  • Current size of logs per job
  • Total number of jobs with logs

This would help in tuning the size constraints and capacity planning.

📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 77a4cd0 and ef0ae62.

📒 Files selected for processing (3)
  • src/main/java/de/tum/cit/aet/artemis/buildagent/service/BuildJobContainerService.java (2 hunks)
  • src/main/java/de/tum/cit/aet/artemis/buildagent/service/BuildLogsMap.java (1 hunks)
  • src/main/java/de/tum/cit/aet/artemis/programming/service/BuildLogEntryService.java (3 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • src/main/java/de/tum/cit/aet/artemis/buildagent/service/BuildJobContainerService.java
  • src/main/java/de/tum/cit/aet/artemis/programming/service/BuildLogEntryService.java
🧰 Additional context used
📓 Path-based instructions (1)
src/main/java/de/tum/cit/aet/artemis/buildagent/service/BuildLogsMap.java (1)

Pattern src/main/java/**/*.java: naming:CamelCase; principles:{single_responsibility,small_methods,no_duplication}; db:{perf_queries,datetime_not_timestamp}; rest:{stateless,singleton,delegate_logic,http_only,minimal_dtos}; dtos:{java_records,no_entities,min_data,single_resp}; di:constructor_injection; kiss:simple_code; file_handling:os_indep_paths; practices:{least_access,avoid_transactions,code_reuse,static_member_ref,prefer_primitives}; sql:{param_annotation,uppercase,avoid_subqueries};java:avoid_star_imports

@krusche krusche self-assigned this Nov 25, 2024
@krusche krusche added this to the 7.7.2 milestone Nov 25, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
buildagent Pull requests that affect the corresponding module config-change Pull requests that change the config in a way that they require a deployment via Ansible. programming Pull requests that affect the corresponding module ready for review server Pull requests that update Java code. (Added Automatically!) tests
Projects
Status: Merged
Development

Successfully merging this pull request may close these issues.

3 participants