Skip to content

Conversation

ekayandan
Copy link
Contributor

@ekayandan ekayandan commented Sep 4, 2025

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).
  • I tested all changes and their related features with all corresponding user types on a test server configured with LocalVC and Jenkins.

Motivation and Context

Athena and Artemis currently use zip files to transfer code repositories between them. On both sides, this introduces unnecessary overhead from repeatedly creating and extracting zip archives. The temporary files not only consume additional storage but also require periodic cleanup. Moreover, this process is more prone to I/O errors.
To address these issues, I am updating related programming exercise/submission functions to work with file maps of the repositories instead of zip files.

Description

  • Replace ZIPs with file maps: Endpoints return Map<String,String> (text files only) instead of ZIPs.
  • Updated endpoints: Student and instructor repo routes now return file maps:
    • GET /api/athena/public/programming-exercises/{exerciseId}/submissions/{submissionId}/repository
    • GET /api/athena/public/programming-exercises/{exerciseId}/repository/{template|solution|tests}
  • Service refactor: AthenaRepositoryExportService now uses RepositoryService to read from bare repos; picks latest commit or latest commit before deadline for student repos.
  • RepositoryService: added getFilesContentFromBareRepositoryForLastCommitBeforeOrAt(...).
  • Tests adapted: Assert file-map responses and use server.url for repositoryUri.

Steps for Testing

Important! In order to test this PR, an Athena deployment to athena-test1 is required. Please check 'Testserver States' section below.

  • Artemis should be deployed to TS1-3 since rest doesn't have Athena enabled.

Prerequisites:

  • 1 Instructor
  • 1 Student
  • 1 Programming Exam with Athena feedbacks enabled
  1. Log in to Artemis as Instructor
  2. Either use the existing test exercise on TS2 and jump to step 5. Or, continue with step 3.
  3. Create a Programming Exercise with "Allow automatic non graded feedback..." enabled (in order to allow it, select "Advanced Mode" during creation check the related checkbox as shown in the screenshot. you can enable the checkbox by setting a due date and assessment to manual as shown is screenshot) image
  4. Log in to Artemis as Student
  5. Submit a solution for the exercise. Include comments and intentional mistakes to verify that Athena correctly receives and processes the submission.
  6. Go to "Recent Results" section of the programming exercise detail page.
  7. Feedback should be visible as preliminary result. Make sure that feedback is correct/as expected for your submission.

Testserver States

You can manage test servers using Helios. Check environment statuses in the environment list. To deploy to a test server, go to the CI/CD page, find your PR or branch, and trigger the deployment.

**!**We need the branch 'chore/programming-llm-improve-repository-imports' to be deployed in order to test this PR. Label below shows currently deployed branch on athena test server. If you see another branch name, please let me know so I can deploy it.

Review Progress

Performance Review

  • I (as a reviewer) confirm that the client changes (in particular related to REST calls and UI responsiveness) are implemented with a very good performance even for very large courses with more than 2000 students.
  • I (as a reviewer) confirm that the server changes (in particular related to database calls) are implemented with a very good performance even for very large courses with more than 2000 students.

Code Review

  • Code Review 1
  • Code Review 2

Manual Tests

  • Test 1
  • Test 2

Performance Tests

  • Test 1
  • Test 2

Test Coverage

Class/File Line Coverage Confirmation (assert/expect)
AthenaFeedbackSuggestionsService 89%
AthenaModuleService 87%
AthenaRepositoryExportService 85%
AthenaResource 87%
RepositoryType 100%
RepositoryService 83%

### Screenshots

Summary by CodeRabbit

  • New Features

    • Repository endpoints now return a JSON map of file paths → text contents (binaries omitted); supports fetching contents as-of a deadline.
  • Refactor

    • Replaced ZIP downloads with JSON responses; unified instructor repository endpoint with case-insensitive repository-type parsing and bare-repository retrieval.
  • Bug Fixes

    • Feedback-suggestion APIs return empty list with warning when module missing; module URL lookup now validates presence. Scheduler timing tweaked.
  • Tests

    • Integration tests updated to assert JSON file-map responses using local VCS setups.
  • Documentation

    • Added i18n messages for invalid student repo URL and invalid instructor repository type.

@github-project-automation github-project-automation bot moved this to Work In Progress in Artemis Development Sep 4, 2025
@github-actions github-actions bot added tests server Pull requests that update Java code. (Added Automatically!) athena Pull requests that affect the corresponding module programming Pull requests that affect the corresponding module labels Sep 4, 2025
@ekayandan ekayandan changed the title converted athena endpoints to return filemaps Development: Convert athena endpoints to return file maps of repositories Sep 4, 2025
@helios-aet helios-aet bot temporarily deployed to artemis-test3.artemis.cit.tum.de September 4, 2025 10:02 Inactive
Copy link

github-actions bot commented Sep 4, 2025

End-to-End (E2E) Test Results Summary

TestsPassed ☑️Skipped ⚠️Failed ❌️Time ⏱
End-to-End (E2E) Test Report205 ran198 passed3 skipped4 failed1h 14m 23s 432ms
TestResultTime ⏱
End-to-End (E2E) Test Report
e2e/exam/ExamResults.spec.ts
ts.Exam Results › Check exam exercise results › Check exam results for text exercise › Check exam result overview❌ failure1m 25s 767ms
e2e/exercise/quiz-exercise/QuizExerciseManagement.spec.ts
ts.Quiz Exercise Management › Quiz Exercise Creation › Creates a Quiz with Drag and Drop❌ failure2m 3s 137ms
e2e/exam/ExamResults.spec.ts
ts.Exam Results › Check exam exercise results › Check exam results for text exercise › Check exam text exercise results❌ failure3m 22s 169ms
ts.Exam Results › Check exam exercise results › Check exam results for modeling exercise › Check exam modeling exercise results❌ failure3m 26s 360ms

Copy link

github-actions bot commented Sep 4, 2025

End-to-End (E2E) Test Results Summary

TestsPassed ☑️Skipped ⚠️Failed ❌️Time ⏱
End-to-End (E2E) Test Report205 ran198 passed3 skipped4 failed1h 16m 28s 759ms
TestResultTime ⏱
End-to-End (E2E) Test Report
e2e/course/CourseManagement.spec.ts
ts.Course management › Course deletion › Delete summary shows correct values❌ failure2m 12s 764ms
e2e/exercise/quiz-exercise/QuizExerciseManagement.spec.ts
ts.Quiz Exercise Management › Quiz Exercise Creation › Creates a Quiz with Drag and Drop❌ failure2m 3s 445ms
e2e/exercise/quiz-exercise/QuizExerciseParticipation.spec.ts
ts.Quiz Exercise Participation › DnD Quiz participation › Student can participate in DnD Quiz❌ failure2m 3s 29ms
e2e/exercise/programming/ProgrammingExerciseStaticCodeAnalysis.spec.ts
ts.Static code analysis tests › Configures SCA grading and makes a successful submission with SCA errors❌ failure2m 14s 109ms

Copy link

github-actions bot commented Sep 5, 2025

End-to-End (E2E) Test Results Summary

TestsPassed ☑️Skipped ⚠️Failed ❌️Time ⏱
End-to-End (E2E) Test Report205 ran200 passed3 skipped2 failed1h 10m 54s 243ms
TestResultTime ⏱
End-to-End (E2E) Test Report
e2e/exercise/quiz-exercise/QuizExerciseManagement.spec.ts
ts.Quiz Exercise Management › Quiz Exercise Creation › Creates a Quiz with Drag and Drop❌ failure2m 3s 990ms
e2e/exercise/programming/ProgrammingExerciseStaticCodeAnalysis.spec.ts
ts.Static code analysis tests › Configures SCA grading and makes a successful submission with SCA errors❌ failure2m 20s 129ms

@ekayandan ekayandan marked this pull request as ready for review September 5, 2025 14:24
@ekayandan ekayandan requested a review from a team as a code owner September 5, 2025 14:24
@ekayandan ekayandan requested a review from a team as a code owner September 5, 2025 14:24
Copy link
Contributor

coderabbitai bot commented Sep 5, 2025

Walkthrough

Replaces ZIP-based repository export with Map<String,String> text-file content retrieval via RepositoryService; adds deadline-aware bare-repo APIs; consolidates instructor endpoints using RepositoryType.fromString; adds feedback-module null guards and module validation exception; updates localization keys and tests to use LocalVC and JSON map assertions.

Changes

Cohort / File(s) Summary of changes
Athena export service API refactor
src/main/java/de/tum/cit/aet/artemis/athena/service/AthenaRepositoryExportService.java
Removed ZIP export and filesystem/clone logic; constructor now injects RepositoryService; added getStudentRepositoryFilesContent(...) and getInstructorRepositoryFilesContent(...) returning Map<String,String> of text file contents; resolves repo URIs, computes optional deadline, calls RepositoryService; updated logs and Javadoc.
Athena REST endpoints
src/main/java/de/tum/cit/aet/artemis/athena/web/AthenaResource.java
Endpoints now return ResponseEntity<Map<String,String>>; student endpoint uses getStudentRepositoryFilesContent; template/solution/tests consolidated into a single instructor endpoint with repositoryType parsed via RepositoryType.fromString(...); removed separate solution/test endpoints; added BadRequest handling for invalid repositoryType; imports and Javadoc updated.
RepositoryService extensions
src/main/java/de/tum/cit/aet/artemis/programming/service/RepositoryService.java
Added getFilesContentFromBareRepositoryForLastCommitBeforeOrAt(...) overloads for Repository and LocalVCRepositoryUri; traverse commits (RevWalk, COMMIT_TIME_DESC) to pick last commit ≤ deadline (or HEAD if no deadline); return Map<path,content> excluding binaries/symlinks; return empty map if no suitable commit/HEAD unresolved.
RepositoryType helper
src/main/java/de/tum/cit/aet/artemis/programming/domain/RepositoryType.java
Added public static RepositoryType fromString(String name) for case-insensitive enum lookup and input validation.
Athena feedback & module guards
src/main/java/de/tum/cit/aet/artemis/athena/service/AthenaFeedbackSuggestionsService.java, src/main/java/de/tum/cit/aet/artemis/athena/service/AthenaModuleService.java
Added null-checks that log and return empty lists when an exercise lacks a feedback-suggestion module in feedback-suggestion methods; getAthenaModuleUrl now validates presence of the module and throws BadRequestAlertException (ENTITY_NAME="exercise", error key "missingFeedbackSuggestionModule") if missing; Javadoc updated.
Localization keys
src/main/webapp/i18n/en/error.json, src/main/webapp/i18n/de/error.json
Added error keys/messages for invalid student repository URL and invalid instructor repository type.
Tests: integration and unit updates
src/test/java/de/tum/cit/aet/artemis/athena/AthenaResourceIntegrationTest.java, src/test/java/de/tum/cit/aet/artemis/athena/service/connectors/AthenaRepositoryExportServiceTest.java, src/test/java/de/tum/cit/aet/artemis/athena/service/connectors/AthenaFeedbackSuggestionsServiceTest.java
Tests switched from ZIP to JSON Map assertions; integration test seeds LocalVC bare repositories and participations (uses ProgrammingExerciseParticipationUtilService), parses response JSON into Map<String,String> and asserts contents; export service tests updated to call new methods and assert maps; feedback suggestions test injects server.url and updates expected URI.
Minor test timing change
src/test/java/de/tum/cit/aet/artemis/shared/base/AbstractArtemisIntegrationTest.java
Adjusted lastScheduledRun to now().minusSeconds(1) when resetting ParticipantScoreScheduleService to add a small negative buffer.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  actor Client
  participant REST as AthenaResource
  participant Service as AthenaRepositoryExportService
  participant RepoSvc as RepositoryService
  participant VCS as Bare VCS Repo

  Client->>REST: GET repository (exerciseId, submissionId / repositoryType)
  REST->>Service: getStudentRepositoryFilesContent(...) / getInstructorRepositoryFilesContent(...)
  Service->>Service: resolve exercise/participation -> repoUri (BadRequest if null)
  alt deadline present
    Service->>RepoSvc: getFilesContentFromBareRepositoryForLastCommitBeforeOrAt(repoUri, deadline)
  else
    Service->>RepoSvc: getFilesContentFromBareRepositoryForLastCommit(repoUri)
  end
  RepoSvc->>VCS: open bare repo, find commit (HEAD or last ≤ deadline)
  VCS-->>RepoSvc: tree contents (text files only)
  RepoSvc-->>Service: Map<String,String>
  Service-->>REST: Map<String,String>
  REST-->>Client: 200 OK (JSON map)
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title Check ✅ Passed The title clearly and concisely describes the primary change of converting Athena endpoints to return file maps, directly reflecting the core update in this PR without extraneous details.
Docstring Coverage ✅ Passed No functions found in the changes. Docstring coverage check skipped.
✨ Finishing touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch chore/convert-athena-endpoints-to-filemap

📜 Recent review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between ded36b3 and 99efbf8.

📒 Files selected for processing (1)
  • src/main/webapp/i18n/de/error.json (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/main/webapp/i18n/de/error.json
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (10)
  • GitHub Check: Codacy Static Code Analysis
  • GitHub Check: Build and Push Docker Image / Build linux/arm64 Docker Image for ls1intum/artemis
  • GitHub Check: Build and Push Docker Image / Build linux/amd64 Docker Image for ls1intum/artemis
  • GitHub Check: Build .war artifact
  • GitHub Check: client-style
  • GitHub Check: client-tests
  • GitHub Check: server-tests
  • GitHub Check: server-style
  • GitHub Check: bean-instantiation-check
  • GitHub Check: Analyse

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

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (13)
src/test/java/de/tum/cit/aet/artemis/athena/service/connectors/AthenaFeedbackSuggestionsServiceTest.java (1)

54-56: Stabilize serverUrl injection to avoid nulls in CI

Provide a default to prevent "null/api/…" expectations when server.url isn’t set.

Apply:

-    @Value("${server.url}")
+    @Value("${server.url:http://localhost:8080}")
     private String serverUrl;
src/main/java/de/tum/cit/aet/artemis/programming/service/RepositoryService.java (1)

216-241: Commit selection by deadline: minor nits (epoch conversion + topo ordering)

Current logic is correct. Two tiny hardening tweaks:

  • Use ZonedDateTime.toEpochSecond().
  • Add TOPO sort to keep traversal stable when commit times collide.

Apply:

-        long epochSeconds = deadline.toInstant().getEpochSecond();
+        long epochSeconds = deadline.toEpochSecond();
         try (RevWalk walk = new RevWalk(repository)) {
             walk.markStart(walk.parseCommit(headCommitId));
             walk.sort(RevSort.COMMIT_TIME_DESC, true);
+            walk.sort(RevSort.TOPO, true);
src/main/java/de/tum/cit/aet/artemis/athena/service/AthenaRepositoryExportService.java (3)

65-74: Fix Javadoc: thrown exception type

Method can surface ServiceUnavailableException (via checkFeedbackSuggestions…), not AccessForbiddenException.

Apply:

-     * @throws AccessForbiddenException if the feedback suggestions are not enabled for the given exercise
+     * @throws ServiceUnavailableException if the feedback suggestions are not enabled for the given exercise

103-109: Deadline handling LGTM; consider simplifying source of deadline (optional)

Using RepositoryExportOptionsDTO just to read dueDate is a bit indirect; consider using programmingExercise.getDueDate() directly to reduce coupling.


95-104: Require submissionId for student repositories to fail fast with a clear message
Apply:

-        var submission = programmingSubmissionRepository.findById(submissionId).orElseThrow();
+        java.util.Objects.requireNonNull(submissionId, "submissionId must be provided for student repositories");
+        var submission = programmingSubmissionRepository.findById(submissionId).orElseThrow();
src/test/java/de/tum/cit/aet/artemis/athena/service/connectors/AthenaRepositoryExportServiceTest.java (2)

66-92: Rename test to reflect new contract (maps, not ZIP).

Clarifies intent and avoids legacy terminology.

-    void shouldExportRepository() throws Exception {
+    void shouldReturnFileMap() throws Exception {

85-92: Strengthen assertions and pass null submissionId for non-student repos.

  • SOLUTION repo doesn’t need a submissionId; passing null is clearer.
  • Assert non-empty maps to meet “assert_specificity” guideline.
-        Map<String, String> resultSolutionRepo = athenaRepositoryExportService.getRepositoryFilesContent(programmingExerciseWithId.getId(), programmingSubmissionWithId.getId(),
-                RepositoryType.SOLUTION);
+        Map<String, String> resultSolutionRepo = athenaRepositoryExportService.getRepositoryFilesContent(
+                programmingExerciseWithId.getId(), null, RepositoryType.SOLUTION);

-        assertThat(resultStudentRepo).isNotNull(); // The student repository files are returned
-        assertThat(resultSolutionRepo).isNotNull(); // The solution repository files are returned
+        assertThat(resultStudentRepo).isNotNull().isNotEmpty(); // Student repository files are returned
+        assertThat(resultSolutionRepo).isNotNull().isNotEmpty(); // Solution repository files are returned

If flakiness appears, ensure a committed file exists at HEAD in the relevant bare repos before invoking the service.

src/test/java/de/tum/cit/aet/artemis/athena/AthenaResourceIntegrationTest.java (2)

390-414: LocalVC seeding looks good; add a positive test for student submission endpoint.

Symmetry with template/solution/tests improves coverage of the new API surface.

Add this test (outside this hunk):

@Test
void testStudentRepositoryExportEndpoint() throws Exception {
    // Enable Athena
    programmingExercise.setFeedbackSuggestionModule(ATHENA_MODULE_PROGRAMMING_TEST);
    programmingExerciseRepository.save(programmingExercise);

    // Seed repos (reuse the same setup as in testRepositoryExportEndpoint or extract to helper)

    var sourceRepo = new LocalRepository(defaultBranch);
    sourceRepo.configureRepos(localVCRepoPath, "athenaSrcLocalRepo2", "athenaSrcOriginRepo2");

    var testsSlug = programmingExercise.getProjectKey().toLowerCase() + "-tests";
    var testsUri = new LocalVCRepositoryUri(localVCBaseUri, programmingExercise.getProjectKey(), testsSlug);
    programmingExercise.setTestRepositoryUri(testsUri.toString());
    programmingExerciseRepository.save(programmingExercise);

    var sourceUri = new LocalVCRepositoryUri(localVCBaseUri, sourceRepo.remoteBareGitRepoFile.toPath());
    gitService.copyBareRepositoryWithoutHistory(sourceUri, new LocalVCRepositoryUri(programmingExercise.getTemplateRepositoryUri()), defaultBranch);
    gitService.copyBareRepositoryWithoutHistory(sourceUri, new LocalVCRepositoryUri(programmingExercise.getSolutionRepositoryUri()), defaultBranch);
    gitService.copyBareRepositoryWithoutHistory(sourceUri, new LocalVCRepositoryUri(programmingExercise.getTestRepositoryUri()), defaultBranch);

    var authHeaders = new HttpHeaders();
    authHeaders.add(HttpHeaders.AUTHORIZATION, athenaSecret);

    String json = request.get("/api/athena/public/programming-exercises/" + programmingExercise.getId() + "/submissions/" + programmingSubmission.getId() + "/repository",
            HttpStatus.OK, String.class, authHeaders);
    Map<String, String> repoFiles = request.getObjectMapper().readValue(json, new com.fasterxml.jackson.core.type.TypeReference<Map<String, String>>() {});
    assertThat(repoFiles).isNotNull().hasSize(1).containsOnlyKeys("README.md").containsEntry("README.md", "Initial commit");
}

419-423: JSON extraction — OK; consider using mapper helper for brevity.

If the test infrastructure supports it, prefer a helper that deserializes directly to Map<String, String>.

-        String json = request.get("/api/athena/public/programming-exercises/" + programmingExercise.getId() + "/" + urlSuffix, HttpStatus.OK, String.class, authHeaders);
-        Map<String, String> repoFiles = request.getObjectMapper().readValue(json, new TypeReference<Map<String, String>>() {
-        });
+        Map<String, String> repoFiles = request.get(
+                "/api/athena/public/programming-exercises/" + programmingExercise.getId() + "/" + urlSuffix,
+                HttpStatus.OK,
+                new TypeReference<Map<String, String>>() {},
+                authHeaders);
src/main/java/de/tum/cit/aet/artemis/athena/web/AthenaResource.java (4)

256-271: Make content negotiation explicit.

Add produces = MediaType.APPLICATION_JSON_VALUE to the mapping.

-    @GetMapping("public/programming-exercises/{exerciseId}/submissions/{submissionId}/repository")
+    @GetMapping(value = "public/programming-exercises/{exerciseId}/submissions/{submissionId}/repository", produces = org.springframework.http.MediaType.APPLICATION_JSON_VALUE)

Optionally add:

import org.springframework.http.MediaType;

and use MediaType.APPLICATION_JSON_VALUE.


274-287: Ditto: declare JSON explicitly for template repo.

-    @GetMapping("public/programming-exercises/{exerciseId}/repository/template")
+    @GetMapping(value = "public/programming-exercises/{exerciseId}/repository/template", produces = org.springframework.http.MediaType.APPLICATION_JSON_VALUE)

290-303: Ditto: declare JSON explicitly for solution repo.

-    @GetMapping("public/programming-exercises/{exerciseId}/repository/solution")
+    @GetMapping(value = "public/programming-exercises/{exerciseId}/repository/solution", produces = org.springframework.http.MediaType.APPLICATION_JSON_VALUE)

306-319: Ditto: declare JSON explicitly for tests repo.

-    @GetMapping("public/programming-exercises/{exerciseId}/repository/tests")
+    @GetMapping(value = "public/programming-exercises/{exerciseId}/repository/tests", produces = org.springframework.http.MediaType.APPLICATION_JSON_VALUE)
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 4f0da27 and 0356671.

📒 Files selected for processing (6)
  • src/main/java/de/tum/cit/aet/artemis/athena/service/AthenaRepositoryExportService.java (3 hunks)
  • src/main/java/de/tum/cit/aet/artemis/athena/web/AthenaResource.java (2 hunks)
  • src/main/java/de/tum/cit/aet/artemis/programming/service/RepositoryService.java (3 hunks)
  • src/test/java/de/tum/cit/aet/artemis/athena/AthenaResourceIntegrationTest.java (5 hunks)
  • src/test/java/de/tum/cit/aet/artemis/athena/service/connectors/AthenaFeedbackSuggestionsServiceTest.java (3 hunks)
  • src/test/java/de/tum/cit/aet/artemis/athena/service/connectors/AthenaRepositoryExportServiceTest.java (3 hunks)
🧰 Additional context used
📓 Path-based instructions (2)
src/test/java/**/*.java

⚙️ CodeRabbit configuration file

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

Files:

  • src/test/java/de/tum/cit/aet/artemis/athena/service/connectors/AthenaFeedbackSuggestionsServiceTest.java
  • src/test/java/de/tum/cit/aet/artemis/athena/AthenaResourceIntegrationTest.java
  • src/test/java/de/tum/cit/aet/artemis/athena/service/connectors/AthenaRepositoryExportServiceTest.java
src/main/java/**/*.java

⚙️ CodeRabbit configuration file

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

Files:

  • src/main/java/de/tum/cit/aet/artemis/programming/service/RepositoryService.java
  • src/main/java/de/tum/cit/aet/artemis/athena/web/AthenaResource.java
  • src/main/java/de/tum/cit/aet/artemis/athena/service/AthenaRepositoryExportService.java
🧠 Learnings (5)
📚 Learning: 2025-02-11T12:05:49.151Z
Learnt from: janthoXO
PR: ls1intum/Artemis#9406
File: src/main/java/de/tum/cit/aet/artemis/programming/web/ProgrammingExerciseParticipationResource.java:209-209
Timestamp: 2025-02-11T12:05:49.151Z
Learning: In ProgrammingExerciseParticipationResource, exam-related authorization checks and sensitive information filtering for results and feedbacks are handled by resultService.filterSensitiveInformationIfNecessary().

Applied to files:

  • src/main/java/de/tum/cit/aet/artemis/athena/web/AthenaResource.java
📚 Learning: 2025-06-06T14:47:54.300Z
Learnt from: Wallenstein61
PR: ls1intum/Artemis#10989
File: src/main/java/de/tum/cit/aet/artemis/programming/web/ExerciseSharingResource.java:122-135
Timestamp: 2025-06-06T14:47:54.300Z
Learning: In Artemis sharing platform integration (under "sharing" profile), endpoints in ExerciseSharingResource use checksum-based authentication with shared secrets instead of PreAuthorize annotations. These endpoints (like getProblemStatement, getExerciseDetails, loadShoppingBasket) validate security through sharingInfo.checkChecksum() calls rather than role-based access control, as they serve as API interfaces for external sharing platform communication.

Applied to files:

  • src/main/java/de/tum/cit/aet/artemis/athena/web/AthenaResource.java
📚 Learning: 2024-11-26T20:43:17.588Z
Learnt from: magaupp
PR: ls1intum/Artemis#9751
File: src/test/java/de/tum/cit/aet/artemis/programming/util/ProgrammingExerciseFactory.java:143-148
Timestamp: 2024-11-26T20:43:17.588Z
Learning: In `src/test/java/de/tum/cit/aet/artemis/programming/util/ProgrammingExerciseFactory.java`, the test package name assigned in `populateUnreleasedProgrammingExercise` does not need to adhere to naming conventions.

Applied to files:

  • src/test/java/de/tum/cit/aet/artemis/athena/AthenaResourceIntegrationTest.java
📚 Learning: 2025-08-08T08:50:28.791Z
Learnt from: tobias-lippert
PR: ls1intum/Artemis#11248
File: src/main/java/de/tum/cit/aet/artemis/programming/service/ProgrammingExerciseParticipationService.java:401-402
Timestamp: 2025-08-08T08:50:28.791Z
Learning: In src/main/java/de/tum/cit/aet/artemis/programming/service/ProgrammingExerciseParticipationService.java, method findStudentParticipationWithLatestSubmissionResultAndFeedbacksElseThrow(long), using List.of() for latestSubmission.setResults(...) is acceptable because the results list is not mutated afterward and is only returned to the client; no follow-up code appends to it.

Applied to files:

  • src/test/java/de/tum/cit/aet/artemis/athena/AthenaResourceIntegrationTest.java
📚 Learning: 2024-10-08T15:35:48.767Z
Learnt from: jakubriegel
PR: ls1intum/Artemis#8050
File: src/test/java/de/tum/in/www1/artemis/plagiarism/PlagiarismUtilService.java:125-136
Timestamp: 2024-10-08T15:35:48.767Z
Learning: The `createTeamTextExerciseAndSimilarSubmissions` method in `PlagiarismUtilService.java` uses fixed inputs as it is designed to be a test helper method for simplifying the setup of team exercises and submissions in tests.

Applied to files:

  • src/test/java/de/tum/cit/aet/artemis/athena/AthenaResourceIntegrationTest.java
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (11)
  • GitHub Check: Codacy Static Code Analysis
  • GitHub Check: Mend Security Check
  • GitHub Check: Build and Push Docker Image / Build Docker Image for ls1intum/artemis
  • GitHub Check: Build and Push Docker Image / Build Docker Image for ls1intum/artemis
  • GitHub Check: Build .war artifact
  • GitHub Check: client-style
  • GitHub Check: client-tests
  • GitHub Check: server-style
  • GitHub Check: server-tests
  • GitHub Check: bean-instantiation-check
  • GitHub Check: Analyse
🔇 Additional comments (10)
src/test/java/de/tum/cit/aet/artemis/athena/service/connectors/AthenaFeedbackSuggestionsServiceTest.java (1)

100-103: Guard against trailing slash in serverUrl
Trim trailing slashes inline to avoid // in the constructed URI for the JSON assertion.

-                jsonPath("$.submission.repositoryUri").value(serverUrl + "/api/athena/public/programming-exercises/" + programmingExercise.getId() + "/submissions/3/repository"));
+                jsonPath("$.submission.repositoryUri").value(serverUrl.replaceAll("/+$", "") + "/api/athena/public/programming-exercises/" + programmingExercise.getId() + "/submissions/3/repository"));

Verify that your server.url property (in test and application configs) doesn’t include a trailing slash or is consistently normalized to prevent double slashes.

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

247-251: Overload delegation LGTM

Clean delegation to the repository-based variant with proper resource handling.

src/main/java/de/tum/cit/aet/artemis/athena/service/AthenaRepositoryExportService.java (1)

78-93: Instructor repo branch: null-URI guard LGTM

Clear error when the template/solution/tests repository isn’t initialized yet; subsequent call uses bare repo API correctly.

src/test/java/de/tum/cit/aet/artemis/athena/service/connectors/AthenaRepositoryExportServiceTest.java (2)

10-10: Import aligns with new API shape — LGTM.


100-102: Exception path update — LGTM.

Correctly asserts ServiceUnavailable when feature is disabled.

src/test/java/de/tum/cit/aet/artemis/athena/AthenaResourceIntegrationTest.java (4)

13-13: Import for Map — LGTM.


25-25: Import for TypeReference — LGTM.


70-72: Autowired participation util — LGTM.

Used later to prepare template/solution participations.


425-447: Negative-path coverage — LGTM.

Forbidden and service-unavailable cases are properly asserted.

src/main/java/de/tum/cit/aet/artemis/athena/web/AthenaResource.java (1)

9-9: Map-based response import — LGTM.

coderabbitai[bot]
coderabbitai bot previously approved these changes Sep 5, 2025
Copy link

github-actions bot commented Sep 5, 2025

End-to-End (E2E) Test Results Summary

TestsPassed ✅SkippedFailedTime ⏱
End-to-End (E2E) Test Report1 ran1 passed0 skipped0 failed1s 593ms
TestResultTime ⏱
No test annotations available

Copy link
Contributor

coderabbitai bot commented Sep 5, 2025

Caution

An unexpected error occurred while opening a pull request: Reference update failed - https://docs.github.com/rest/git/refs#create-a-reference

Copy link

github-actions bot commented Sep 5, 2025

End-to-End (E2E) Test Results Summary

TestsPassed ☑️Skipped ⚠️Failed ❌️Time ⏱
End-to-End (E2E) Test Report205 ran199 passed3 skipped3 failed1h 9m 47s 299ms
TestResultTime ⏱
End-to-End (E2E) Test Report
e2e/exam/ExamResults.spec.ts
ts.Exam Results › Check exam exercise results › Check exam results for text exercise › Check exam result overview❌ failure1m 28s 363ms
e2e/exercise/quiz-exercise/QuizExerciseManagement.spec.ts
ts.Quiz Exercise Management › Quiz Exercise Creation › Creates a Quiz with Drag and Drop❌ failure2m 3s 384ms
e2e/exercise/quiz-exercise/QuizExerciseParticipation.spec.ts
ts.Quiz Exercise Participation › DnD Quiz participation › Student can participate in DnD Quiz❌ failure2m 3s 586ms

coderabbitai[bot]
coderabbitai bot previously approved these changes Oct 1, 2025
…m:ls1intum/Artemis into chore/convert-athena-endpoints-to-filemap
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (1)
src/main/java/de/tum/cit/aet/artemis/athena/service/AthenaRepositoryExportService.java (1)

129-133: Consider simplifying the error message construction.

The error message construction is verbose and repeats repositoryType.name().toLowerCase() multiple times. Consider extracting this to a variable for clarity.

Apply this diff:

         var repoUri = programmingExercise.getRepositoryURI(repositoryType);
         if (repoUri == null) {
-            String errorKey = "error.invalid." + repositoryType.name().toLowerCase() + ".repository.url";
-            throw new BadRequestAlertException("Repository URI is null for exercise " + exerciseId + " and repository type " + repositoryType + ". This may indicate that the "
-                    + repositoryType.name().toLowerCase() + " repository has not been set up yet.", ENTITY_NAME, errorKey);
+            String repoTypeLower = repositoryType.name().toLowerCase();
+            String errorKey = "error.invalid." + repoTypeLower + ".repository.url";
+            throw new BadRequestAlertException("Repository URI is null for exercise " + exerciseId + " and repository type " + repositoryType + ". This may indicate that the "
+                    + repoTypeLower + " repository has not been set up yet.", ENTITY_NAME, errorKey);
         }
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 4127676 and 9bbfc4b.

📒 Files selected for processing (3)
  • src/main/java/de/tum/cit/aet/artemis/athena/service/AthenaModuleService.java (2 hunks)
  • src/main/java/de/tum/cit/aet/artemis/athena/service/AthenaRepositoryExportService.java (3 hunks)
  • src/test/java/de/tum/cit/aet/artemis/athena/service/connectors/AthenaRepositoryExportServiceTest.java (4 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • src/main/java/de/tum/cit/aet/artemis/athena/service/AthenaModuleService.java
  • src/test/java/de/tum/cit/aet/artemis/athena/service/connectors/AthenaRepositoryExportServiceTest.java
🧰 Additional context used
📓 Path-based instructions (1)
src/main/java/**/*.java

⚙️ CodeRabbit configuration file

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

Files:

  • src/main/java/de/tum/cit/aet/artemis/athena/service/AthenaRepositoryExportService.java
🧠 Learnings (1)
📚 Learning: 2025-09-15T11:21:15.983Z
Learnt from: SamuelRoettgermann
PR: ls1intum/Artemis#11378
File: src/main/java/de/tum/cit/aet/artemis/exam/service/ExamRoomDistributionService.java:72-79
Timestamp: 2025-09-15T11:21:15.983Z
Learning: SamuelRoettgermann prefers iterative development approach - initial implementations should be working starting points rather than full-fledged, finished implementations. Optimization and robustness improvements can be added later.

Applied to files:

  • src/main/java/de/tum/cit/aet/artemis/athena/service/AthenaRepositoryExportService.java
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (9)
  • GitHub Check: Build and Push Docker Image / Build linux/arm64 Docker Image for ls1intum/artemis
  • GitHub Check: Build and Push Docker Image / Build linux/amd64 Docker Image for ls1intum/artemis
  • GitHub Check: Build .war artifact
  • GitHub Check: client-style
  • GitHub Check: client-tests
  • GitHub Check: server-tests
  • GitHub Check: server-style
  • GitHub Check: bean-instantiation-check
  • GitHub Check: Analyse

coderabbitai[bot]
coderabbitai bot previously approved these changes Oct 1, 2025
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

♻️ Duplicate comments (1)
src/main/java/de/tum/cit/aet/artemis/athena/service/AthenaRepositoryExportService.java (1)

87-107: Critical: Missing feature gate check and exercise-submission validation.

Based on past review feedback marked as addressed, this method should:

  1. Call checkFeedbackSuggestionsOrAutomaticFeedbackEnabledElseThrow(programmingExercise) after loading the exercise to enforce the feature gate consistently with the instructor flow (line 130).
  2. Validate that the submission's participation belongs to the specified exerciseId to prevent data leakage.

Both validations are currently absent.

Apply this diff to add the missing validations:

     public Map<String, String> getStudentRepositoryFilesContent(long exerciseId, Long submissionId) throws IOException {
         log.debug("Retrieving student repository file contents for exercise {}, submission {}", exerciseId, submissionId);
 
         ProgrammingExercise programmingExercise = programmingExerciseRepository.findByIdElseThrow(exerciseId);
+        checkFeedbackSuggestionsOrAutomaticFeedbackEnabledElseThrow(programmingExercise);
 
         ProgrammingSubmission submission = programmingSubmissionRepository.findByIdElseThrow(submissionId);
         ProgrammingExerciseStudentParticipation participation = programmingExerciseStudentParticipationRepository.findByIdElseThrow(submission.getParticipation().getId());
+        
+        // Validate that the submission belongs to the specified exercise
+        if (participation.getProgrammingExercise() == null || !participation.getProgrammingExercise().getId().equals(exerciseId)) {
+            throw new BadRequestAlertException("Submission does not belong to the specified exercise", ENTITY_NAME, "error.submission.exercise.mismatch");
+        }
+        
         LocalVCRepositoryUri repoUri = participation.getVcsRepositoryUri();
         if (repoUri == null) {
             throw new BadRequestAlertException(
                     "Repository URI is null for student participation " + participation.getId() + ". This may indicate that the student repository has not been set up yet.",
                     ENTITY_NAME, "error.invalid.student.repository.url");
         }
         ZonedDateTime deadline = programmingExercise.getDueDate();
         if (deadline != null) {
             return repositoryService.getFilesContentFromBareRepositoryForLastCommitBeforeOrAt(repoUri, deadline);
         }
         else {
             return repositoryService.getFilesContentFromBareRepositoryForLastCommit(repoUri);
         }
     }
🧹 Nitpick comments (1)
src/main/webapp/i18n/de/error.json (1)

72-77: Use gender-inclusive wording for student message
Elsewhere in this file we rely on gender-inclusive phrasing (e.g., “Studierende:r”). Please update the new student-facing string accordingly—e.g. “Die Repository-URL der Studierenden …”—to stay consistent with existing locale style.

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 9bbfc4b and 2e13784.

📒 Files selected for processing (2)
  • src/main/java/de/tum/cit/aet/artemis/athena/service/AthenaRepositoryExportService.java (3 hunks)
  • src/main/webapp/i18n/de/error.json (1 hunks)
🧰 Additional context used
📓 Path-based instructions (2)
src/main/webapp/i18n/de/**/*.json

⚙️ CodeRabbit configuration file

German language translations should be informal (dutzen) and should never be formal (sietzen). So the user should always be addressed with "du/dein" and never with "sie/ihr".

Files:

  • src/main/webapp/i18n/de/error.json
src/main/java/**/*.java

⚙️ CodeRabbit configuration file

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

Files:

  • src/main/java/de/tum/cit/aet/artemis/athena/service/AthenaRepositoryExportService.java
🧠 Learnings (1)
📚 Learning: 2025-09-15T11:21:15.983Z
Learnt from: SamuelRoettgermann
PR: ls1intum/Artemis#11378
File: src/main/java/de/tum/cit/aet/artemis/exam/service/ExamRoomDistributionService.java:72-79
Timestamp: 2025-09-15T11:21:15.983Z
Learning: SamuelRoettgermann prefers iterative development approach - initial implementations should be working starting points rather than full-fledged, finished implementations. Optimization and robustness improvements can be added later.

Applied to files:

  • src/main/java/de/tum/cit/aet/artemis/athena/service/AthenaRepositoryExportService.java
🧬 Code graph analysis (1)
src/main/java/de/tum/cit/aet/artemis/athena/service/AthenaRepositoryExportService.java (1)
src/main/java/de/tum/cit/aet/artemis/programming/service/localvc/LocalVCRepositoryUri.java (1)
  • LocalVCRepositoryUri (17-318)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (10)
  • GitHub Check: Codacy Static Code Analysis
  • GitHub Check: Build and Push Docker Image / Build linux/amd64 Docker Image for ls1intum/artemis
  • GitHub Check: Build and Push Docker Image / Build linux/arm64 Docker Image for ls1intum/artemis
  • GitHub Check: Build .war artifact
  • GitHub Check: server-style
  • GitHub Check: client-tests
  • GitHub Check: server-tests
  • GitHub Check: client-style
  • GitHub Check: Analyse
  • GitHub Check: bean-instantiation-check
🔇 Additional comments (5)
src/main/java/de/tum/cit/aet/artemis/athena/service/AthenaRepositoryExportService.java (5)

1-28: LGTM! Clean imports following coding guidelines.

All imports are specific (no star imports), properly organized, and relevant to the refactored functionality.


30-54: LGTM! Well-structured class with proper encapsulation.

The class follows coding guidelines with proper annotations, immutable final fields, and a defensive constant for valid repository types.


55-61: LGTM! Proper constructor injection.

The constructor follows dependency injection best practices as per coding guidelines.


63-74: LGTM! Helper method follows best practices.

The method properly encapsulates the feature gate check with appropriate logging.


109-139: LGTM! Instructor repository method is well-implemented.

The method properly validates repository types, enforces the feature gate, handles null URIs with appropriate exceptions, and follows all coding guidelines. The defensive validation against invalid repository types (including USER) is excellent.

coderabbitai[bot]
coderabbitai bot previously approved these changes Oct 1, 2025
Copy link

github-actions bot commented Oct 1, 2025

End-to-End (E2E) Test Results Summary

TestsPassed ✅SkippedFailedTime ⏱
End-to-End (E2E) Test Report1 ran1 passed0 skipped0 failed1s 576ms
TestResultTime ⏱
No test annotations available

coderabbitai[bot]
coderabbitai bot previously approved these changes Oct 1, 2025
Copy link

github-actions bot commented Oct 1, 2025

End-to-End (E2E) Test Results Summary

TestsPassed ☑️Skipped ⚠️Failed ❌️Time ⏱
End-to-End (E2E) Test Report205 ran199 passed3 skipped3 failed1h 20m 12s 591ms
TestResultTime ⏱
End-to-End (E2E) Test Report
e2e/exercise/quiz-exercise/QuizExerciseManagement.spec.ts
ts.Quiz Exercise Management › Quiz Exercise Creation › Creates a Quiz with Drag and Drop❌ failure2m 3s 924ms
e2e/exercise/quiz-exercise/QuizExerciseParticipation.spec.ts
ts.Quiz Exercise Participation › DnD Quiz participation › Student can participate in DnD Quiz❌ failure2m 5s 238ms
e2e/exercise/programming/ProgrammingExerciseStaticCodeAnalysis.spec.ts
ts.Static code analysis tests › Configures SCA grading and makes a successful submission with SCA errors❌ failure2m 32s 43ms

@helios-aet helios-aet bot temporarily deployed to artemis-test1.artemis.cit.tum.de October 1, 2025 18:14 Inactive
Copy link
Contributor

@SamuelRoettgermann SamuelRoettgermann left a comment

Choose a reason for hiding this comment

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

Code lgtm

@helios-aet helios-aet bot temporarily deployed to artemis-test3.artemis.cit.tum.de October 3, 2025 09:38 Inactive
@helios-aet helios-aet bot temporarily deployed to artemis-test2.artemis.cit.tum.de October 3, 2025 09:50 Inactive
HawKhiem
HawKhiem previously approved these changes Oct 3, 2025
Copy link
Contributor

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

Retested on TS2

Copy link
Contributor

@tobias-lippert tobias-lippert left a comment

Choose a reason for hiding this comment

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

just one comment regarding our language guidelines

Copy link

github-actions bot commented Oct 3, 2025

End-to-End (E2E) Test Results Summary

TestsPassed ✅SkippedFailedTime ⏱
End-to-End (E2E) Test Report1 ran1 passed0 skipped0 failed1s 578ms
TestResultTime ⏱
No test annotations available

Copy link

github-actions bot commented Oct 4, 2025

End-to-End (E2E) Test Results Summary

TestsPassed ✅SkippedFailedTime ⏱
End-to-End (E2E) Test Report1 ran1 passed0 skipped0 failed1s 583ms
TestResultTime ⏱
No test annotations available

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
athena Pull requests that affect the corresponding module client Pull requests that update TypeScript code. (Added Automatically!) programming Pull requests that affect the corresponding module server Pull requests that update Java code. (Added Automatically!) tests
Projects
Status: Ready For Review
Development

Successfully merging this pull request may close these issues.

7 participants