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

Programming exercises: Only replace existing files when populating build plan repositories #9968

Conversation

SimonEntholzer
Copy link
Contributor

@SimonEntholzer SimonEntholzer commented Dec 8, 2024

Checklist

General

Server

  • Important: I implemented the changes with a very good performance and prevented too many (unnecessary) and too complex database calls.

Client

  • I translated all newly inserted strings into English and German.

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

In #9521 the build plan population of programming was changed, to provide a consistent insertion of repository content during build plan population.

When inserting the contents of an auxiliary repository, at the moment, all content is replaced, even files which do not exist in the auxiliary repository. (First rm and then mv)

Description

We want to retain files which are not overwritten.
To do this, this PR changes the rm + mv to a single cp -r operation. This overwrites files with the same name, and retains files not present in the auxiliary repository.

Example with a simple template repository and a simple auxiliary repository with nested directories:
(First screenshot is the directory structure, the second shows the file's content.)

Before copying the auxiliary repository:

After copying the auxiliary repository into the template repository with cp -r auxrepo/. assignment/src/:

Notice, that after this operation, f2 and file2 were overwritten by the operation and have a different content now.

Steps for Testing

  1. Create a programming exercise (java e.g.) with an auxiliary repository, with a checkout path that will replace data from the template. E.g. if the package name is "package", set the auxiliary repository's checkout directory to assignment/src/package"
  2. Save the exercise. Both the template and solution build plan should succeed. (0% and 100%)
  3. Now add the BubbleSort.java file from the solution repository's src/package folder to the root of the auxiliary repository.
  4. The soultion bulid should stay at 100% (the BubbleSort.java file is replaced with an identical copy)
  5. The template build should get a build failure, because the SortStrategy is not yet implemented, but needed by the injected BubbleSort.java

Expected build results:
image

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

Test Coverage

Server

Class/File Line Coverage Confirmation (assert/expect)
BuildJobContainerService.java 79% ✅ ❌

Summary by CodeRabbit

Summary by CodeRabbit

  • New Features
    • Enhanced file handling process for Docker containers, simplifying the management of repository files during build jobs.
    • Updated descriptions in the localization files for auxiliary repositories, clarifying file overwriting behavior.
  • Bug Fixes
    • Removed outdated methods for directory management, improving overall efficiency and clarity in file operations.

@SimonEntholzer SimonEntholzer requested a review from a team as a code owner December 8, 2024 14:11
@github-actions github-actions bot added server Pull requests that update Java code. (Added Automatically!) buildagent Pull requests that affect the corresponding module labels Dec 8, 2024
Copy link

coderabbitai bot commented Dec 8, 2024

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

Walkthrough

The BuildJobContainerService class has been modified to enhance the handling of directories and files within Docker containers. Key changes include the introduction of a new method, insertRepositoryFiles, which replaces the previous methods for removing and renaming directories. This new method utilizes the cp command for copying files, streamlining the process of managing repository files during build job preparation. Additionally, the localization files for programming exercises have been updated to clarify the behavior of auxiliary repositories regarding file overwriting.

Changes

File Path Change Summary
src/main/java/de/tum/cit/aet/artemis/buildagent/service/BuildJobContainerService.java - Removed methods: removeDirectoryAndFiles, renameDirectoryOrFile.
- Added method: insertRepositoryFiles.
src/main/webapp/i18n/de/programmingExercise.json - Updated usageDescription to clarify that only files with the same name will be overwritten.
src/main/webapp/i18n/en/programmingExercise.json - Updated usageDescription to clarify that only files with the same name will be overwritten.

Possibly related PRs

Suggested labels

documentation, bugfix

Suggested reviewers

  • BBesrour
  • florian-glombik
  • JohannesStoehr
  • az108

📜 Recent review details

Configuration used: .coderabbit.yaml
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 8a864c0 and 69efd85.

📒 Files selected for processing (1)
  • src/main/java/de/tum/cit/aet/artemis/buildagent/service/BuildJobContainerService.java (1 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
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

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

345-345: LGTM! Path construction is secure and follows best practices.

The method correctly uses path components and maintains the single responsibility principle.


348-350: ⚠️ Potential issue

Add path validation and copy verification.

While the implementation is clean and efficient, consider these security and reliability improvements:

  1. Validate paths using the existing checkPath method
  2. Verify successful copy operation by checking the destination directory
     private void insertRepositoryFiles(String containerId, String oldName, String newName) {
+        checkPath(oldName);
+        checkPath(newName);
         executeDockerCommand(containerId, null, false, false, true, "cp", "-r", oldName + (oldName.endsWith("/") ? "." : "/."), newName);
+        // Verify copy operation
+        executeDockerCommand(containerId, null, false, false, true, "test", "-d", newName);
     }

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: 1

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

343-343: LGTM! Consider adding error handling.

The simplified approach using insertRepositoryFiles is more efficient than the previous implementation. However, consider adding error handling for cases where the source directory doesn't exist or the copy operation fails.

-        insertRepositoryFiles(containerId, LOCALCI_WORKING_DIRECTORY + "/" + repositoryPath.getFileName().toString(), newDirectoryName);
+        String sourcePath = LOCALCI_WORKING_DIRECTORY + "/" + repositoryPath.getFileName().toString();
+        try {
+            insertRepositoryFiles(containerId, sourcePath, newDirectoryName);
+        } catch (LocalCIException e) {
+            throw new LocalCIException("Failed to copy repository files from " + sourcePath + " to " + newDirectoryName, e);
+        }
📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 0005603 and 95c15a7.

📒 Files selected for processing (1)
  • src/main/java/de/tum/cit/aet/artemis/buildagent/service/BuildJobContainerService.java (1 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
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

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

343-348: Verify behavior in exam mode.

The changes look good and improve efficiency. However, since the PR mentions exam mode testing requirements, please verify that these file operations maintain the expected behavior during exams, particularly when:

  1. Multiple students submit simultaneously
  2. Network connectivity is limited
  3. Container resources are constrained
✅ Verification successful

Based on the search results, I can generate the final response since I have enough information to verify the exam mode behavior:

File operations are safe for exam mode scenarios

The codebase shows that exam mode is well-handled across the application with specific considerations for:

  1. Network connectivity issues:

    • Local saving and 30-second auto-sync for student work
    • Offline work support for text, quiz and modeling exercises
    • Repository operations only require connectivity during initial clone and final submission
  2. Concurrent submissions:

    • Each student gets a unique exam with randomized exercise order
    • Container operations are isolated per student (unique containerId)
    • File operations use container-specific paths
  3. Resource constraints:

    • Container operations are minimal - single cp command for file transfer
    • No redundant operations or resource-intensive processes in the implementation

The changes maintain these safeguards while improving efficiency through the simplified file replacement approach.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Check for exam mode specific configurations and tests
rg -A 5 "exam.*mode|isExam" 

# Check for concurrent submission handling
rg -A 5 "concurrent|simultaneous|parallel"

# Check for resource constraints
ast-grep --pattern 'class $_ implements $_ {
  $$$
  private $_ buildJobContainerId;
  $$$
  private void $_(String containerId, $_) {
    $$$
    resources
    $$$
  }
}'

Length of output: 69120

@github-actions github-actions bot added the client Pull requests that update TypeScript code. (Added Automatically!) label Dec 8, 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: 0

🧹 Outside diff range and nitpick comments (1)
src/main/webapp/i18n/en/programmingExercise.json (1)

581-581: Improve clarity by removing redundant sentence.

The description effectively explains how auxiliary repositories work, but contains a repetitive sentence.

Apply this diff to remove the redundancy:

-                "usageDescription": "You can use auxiliary repositories to provide additional code that students cannot see or modify. The additional code is inserted into the specified checkout directory before the submission is built. The additional code is inserted in the specified checkout directory before the build is created. The inserted files overwrite all files in the checkout directory which have the same name. Files that are not overwritten are retained.",
+                "usageDescription": "You can use auxiliary repositories to provide additional code that students cannot see or modify. The additional code is inserted into the specified checkout directory before the build is created. The inserted files overwrite all files in the checkout directory which have the same name. Files that are not overwritten are retained.",
📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 95c15a7 and 8a864c0.

📒 Files selected for processing (2)
  • src/main/webapp/i18n/de/programmingExercise.json (1 hunks)
  • src/main/webapp/i18n/en/programmingExercise.json (1 hunks)
✅ Files skipped from review due to trivial changes (1)
  • src/main/webapp/i18n/de/programmingExercise.json

Copy link

@HawKhiem HawKhiem left a comment

Choose a reason for hiding this comment

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

Tested on TS1. Everything works as described

Screenshot 2024-12-08 181726
Screenshot 2024-12-08 181844

Copy link

@SimonKaran13 SimonKaran13 left a comment

Choose a reason for hiding this comment

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

I tested on TS1 and it does not work as expect. I followed the instructions and created an aux repo. And I get a build failed in the solution repo. It says that the BubbleSort class is duplicate. Additionally, it is not possible to use usual java package names that contain '.' like 'de.tum.cit.xyz' because you are not allowed to set as the check out directory path.

Aux Repo checkout path:
image

Aux repo BubbleSort.java:
image

Solution repo BubbleSort.java
image

Solution Repo build output:
image

@SimonEntholzer
Copy link
Contributor Author

I tested on TS1 and it does not work as expect. I followed the instructions and created an aux repo. And I get a build failed in the solution repo. It says that the BubbleSort class is duplicate. Additionally, it is not possible to use usual java package names that contain '.' like 'de.tum.cit.xyz' because you are not allowed to set as the check out directory path.
...

The problem is that you added the BubbleSort.java in the auxiliary reposiotory, within its own src/testPackage folders. This means the whole folder is injected, and you end up with two identical files, although in different folder places.

This is what you end up with (excluding all other files):
image

By removing the folders from the auxiliary repository, and having the BubbleSort.java at the directory root, it should work as described.
I adapted the testing instructions to make this more clear.

Copy link

@SimonKaran13 SimonKaran13 left a comment

Choose a reason for hiding this comment

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

I tested again on TS3 following the updated instructions and it worked as expected. I also tried a nested package name (as usually used in java) and it worked.
image

Copy link
Member

@BBesrour BBesrour left a comment

Choose a reason for hiding this comment

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

code

@bassner bassner added this to the 7.7.5 milestone Dec 10, 2024
@bassner bassner merged commit 3f38127 into develop Dec 10, 2024
86 of 94 checks passed
@bassner bassner deleted the feature/programming-exercises/do-not-remove-not-overwritten-files branch December 10, 2024 16:45
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 client Pull requests that update TypeScript code. (Added Automatically!) ready for review ready to merge server Pull requests that update Java code. (Added Automatically!)
Projects
Status: Merged
Status: Done
Development

Successfully merging this pull request may close these issues.

7 participants