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

Development: Cache windfiles on startup #7817

Merged
merged 9 commits into from
Dec 29, 2023

Conversation

reschandreas
Copy link
Contributor

@reschandreas reschandreas commented Dec 21, 2023

Checklist

General

Server

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

Changes affecting Programming Exercises

  • I tested all changes and their related features with all corresponding user types on Test Server 3 (LocalCI and LocalVC).

Motivation, Description, and Context

The fetching of the windfiles was pretty flaky on TS3 with multiple nodes, this fixes it by moving the retrieval to the startup of Artemis and throwing errors if the resources could not be found. This PR also removes Kotlin sequential for LocalCI as it is not yet fully supported. It also improves LocalCI in that it does not use root for the execution of the script.

Steps for Testing

Prerequisites:

  • 1 Instructor
  1. Log in to Artemis
  2. Create Programming Exercises, the build jobs should work as expected

Testserver States

Note

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







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
  • I (as a reviewer) confirm that the server changes (in particular related to database calls) are implemented with a very good performance

Code Review

  • Code Review 1
  • Code Review 2

Manual Tests

  • Test 1
  • Test 2

Test Coverage

Server

Class/File Line Coverage Confirmation (assert/expect)
AeolusTemplateService.java 89%
LocalCIContainerService.java 70%
LocalCIProgrammingLanguageFeatureService.java 100%

Summary by CodeRabbit

  • Refactor

    • Improved logging consistency within the Aeolus Template Service.
    • Enhanced Docker command execution and script creation in Local CI Container Service.
    • Updated programming language feature settings for Kotlin.
  • Chores

    • Streamlined service initialization with pre-loading scripts into cache.

@reschandreas reschandreas self-assigned this Dec 21, 2023
@github-actions github-actions bot added the server Pull requests that update Java code. (Added Automatically!) label Dec 21, 2023
@reschandreas reschandreas force-pushed the bugfix/fix-missing-aeolus-templates branch from 94a5643 to 6201add Compare December 21, 2023 19:27
@reschandreas reschandreas temporarily deployed to artemis-test3.artemis.cit.tum.de December 21, 2023 19:42 — with GitHub Actions Inactive
@reschandreas reschandreas force-pushed the bugfix/fix-missing-aeolus-templates branch 2 times, most recently from 91ddac8 to 55869e1 Compare December 21, 2023 19:56
@reschandreas reschandreas temporarily deployed to artemis-test3.artemis.cit.tum.de December 21, 2023 20:04 — with GitHub Actions Inactive
@reschandreas reschandreas force-pushed the bugfix/fix-missing-aeolus-templates branch 2 times, most recently from 3c3f03c to 6713447 Compare December 21, 2023 20:18
Copy link
Contributor

@mateusmm01 mateusmm01 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 ts3. Works as expected.

Copy link

@georgyia georgyia left a comment

Choose a reason for hiding this comment

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

tested manually on ts2, works as expected

Copy link
Contributor

@egekurt123 egekurt123 left a comment

Choose a reason for hiding this comment

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

manually tested on ts3 and ts5. Works as expected

@krusche krusche added this to the 6.7.4 milestone Dec 28, 2023
Copy link

coderabbitai bot commented Dec 29, 2023

Walkthrough

The recent updates to the Artemis service involve a series of refinements across various components. The logging mechanism has been standardized with a renamed logger variable. Initialization now includes a preloading step for scripts, enhancing efficiency. Docker command execution has been fine-tuned, and the handling of programming language features, particularly for Kotlin, has been altered, potentially impacting how Kotlin is supported or processed within the service.

Changes

File Path Change Summary
.../aeolus/AeolusTemplateService.java Standardized logger variable name, added script preloading method, updated logging in a method.
.../localci/LocalCIContainerService.java Added import, refactored Docker command execution and build script creation, removed specific language script methods.
.../localci/LocalCIProgrammingLanguageFeatureService.java Modified Kotlin feature declaration affecting language support logic.

Poem

🐇 CodeRabbit hopping through the code,
🌟 Refactoring with a playful ode.
🚀 With each commit, we take flight,
🎉 Celebrating changes, oh so right!

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 with CodeRabbit Bot (@coderabbitai)

  • You can directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>.
    • Generate unit-tests for this file.
  • You can tag CodeRabbit on specific lines of code or entire files in the PR by tagging @coderabbitai in a comment. Examples:
    • @coderabbitai generate unit tests for this file.
    • @coderabbitai modularize this function.
  • You can tag @coderabbitai in a PR comment and ask questions about the PR and the codebase. Examples:
    • @coderabbitai generate interesting stats about this repository from git and render them as a table.
    • @coderabbitai show all the console.log statements in this repository.
    • @coderabbitai read src/utils.ts and generate unit tests.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid.
    • @coderabbitai read the files in the src/scheduler package and generate README in the markdown format.

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.

CodeRabbit Commands (invoked as PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger a review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai help to get help.

Additionally, you can add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.

CodeRabbit Configration File (.coderabbit.yaml)

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

CodeRabbit Discord Community

Join our Discord Community to get help, request features, and share feedback.

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.

Review Status

Actionable comments generated: 5

Configuration used: CodeRabbit UI

Commits Files that changed from the base of the PR and between ce8cb00 and fc8b2f7.
Files selected for processing (3)
  • src/main/java/de/tum/in/www1/artemis/service/connectors/aeolus/AeolusTemplateService.java (3 hunks)
  • src/main/java/de/tum/in/www1/artemis/service/connectors/localci/LocalCIContainerService.java (9 hunks)
  • src/main/java/de/tum/in/www1/artemis/service/connectors/localci/LocalCIProgrammingLanguageFeatureService.java (1 hunks)
Additional comments: 3
src/main/java/de/tum/in/www1/artemis/service/connectors/aeolus/AeolusTemplateService.java (1)
  • 36-36: The logger variable name has been changed to follow the Java naming conventions for non-final variables. This is a good practice for consistency and readability.
src/main/java/de/tum/in/www1/artemis/service/connectors/localci/LocalCIContainerService.java (2)
  • 31-31: The addition of the ExecCreateCmd import suggests that there are new usages of this class in the file. This is a standard change when new functionality is introduced.

  • 331-331: The removal of scriptForJavaKotlin and scriptForPython methods indicates a simplification of the script creation process. Ensure that the functionality provided by these methods is either no longer needed or has been appropriately integrated into the new implementation.

@@ -26,7 +26,7 @@ public LocalCIProgrammingLanguageFeatureService() {
programmingLanguageFeatures.put(PYTHON, new ProgrammingLanguageFeature(PYTHON, false, false, true, false, false, List.of(), false, false, true));
programmingLanguageFeatures.put(C, new ProgrammingLanguageFeature(C, false, true, true, false, false, List.of(FACT, GCC), false, true, true));
programmingLanguageFeatures.put(ASSEMBLER, new ProgrammingLanguageFeature(ASSEMBLER, false, false, false, false, false, List.of(), false, true, true));
programmingLanguageFeatures.put(KOTLIN, new ProgrammingLanguageFeature(KOTLIN, true, false, true, true, false, List.of(), false, true, true));
programmingLanguageFeatures.put(KOTLIN, new ProgrammingLanguageFeature(KOTLIN, false, false, true, true, false, List.of(), false, true, true));
Copy link

Choose a reason for hiding this comment

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

The change from true to false for the first parameter in the KOTLIN feature declaration disables the sequential build support for Kotlin. Ensure that this change aligns with the intended functionality and that any dependent features or documentation are updated accordingly.

Comment on lines +51 to +75
private void cacheOnBoot() {
var resources = this.resourceLoaderService.getResources(Path.of("templates", "aeolus"));
for (var resource : resources) {
try {
String filename = resource.getFilename();
if (filename == null) {
continue;
}
String directory = resource.getURL().getPath().split("templates/aeolus/")[1].split("/")[0];
String projectType = filename.split("_")[0].replace(".yaml", "");
Optional<ProjectType> optionalProjectType = Optional.empty();
if (!projectType.equals("default")) {
optionalProjectType = Optional.of(ProjectType.valueOf(projectType.toUpperCase()));
}
String uniqueKey = directory + "_" + filename;
byte[] fileContent = IOUtils.toByteArray(resource.getInputStream());
String script = new String(fileContent, StandardCharsets.UTF_8);
Windfile windfile = readWindfile(script);
this.addInstanceVariablesToWindfile(windfile, ProgrammingLanguage.valueOf(directory.toUpperCase()), optionalProjectType);
templateCache.put(uniqueKey, windfile);
}
catch (IOException | IllegalArgumentException e) {
logger.error("Failed to load windfile {}", resource.getFilename(), e);
}
}
Copy link

Choose a reason for hiding this comment

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

The new cacheOnBoot method preloads windfiles into the cache during service initialization. This approach can improve performance by avoiding runtime file loading. However, ensure that the error handling is robust and that the application can still function correctly if any windfile fails to load.

@@ -118,7 +147,7 @@ public Windfile getDefaultWindfileFor(ProgrammingExercise exercise) {
exercise.hasSequentialTestRuns(), exercise.isTestwiseCoverageEnabled());
}
catch (IOException e) {
LOGGER.info("No windfile for the settings of exercise {}", exercise.getId(), e);
logger.info("No windfile for the settings of exercise {}", exercise.getId(), e);
Copy link

Choose a reason for hiding this comment

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

The logging level in getDefaultWindfileFor has been changed to info when a windfile is not found. This change should be carefully considered; if the absence of a windfile is an expected scenario that does not require immediate attention, info is appropriate. Otherwise, if it is an exceptional situation, a higher severity level might be warranted.

Comment on lines +331 to +337
private List<BuildLogEntry> executeDockerCommand(String containerId, boolean attachStdout, boolean attachStderr, boolean forceRoot, String... command) {
boolean detach = !attachStdout && !attachStderr;

ExecCreateCmdResponse execCreateCmdResponse = dockerClient.execCreateCmd(containerId).withAttachStdout(attachStdout).withAttachStderr(attachStderr).withUser("root")
.withCmd(command).exec();
ExecCreateCmd execCreateCmd = dockerClient.execCreateCmd(containerId).withAttachStdout(attachStdout).withAttachStderr(attachStderr).withCmd(command);
if (forceRoot) {
execCreateCmd = execCreateCmd.withUser("root");
}
Copy link

Choose a reason for hiding this comment

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

The executeDockerCommand method has been refactored to include a forceRoot parameter, which allows commands to be executed as the root user. This change should be carefully reviewed to ensure that it does not introduce security risks, especially considering the implications of running commands as root inside Docker containers.

Comment on lines 413 to 418
}
});

// Fall back to hardcoded scripts for old exercises without windfile
// *****************
// TODO: Delete once windfile templates can be used as fallbacks
if (actions.isEmpty()) {
// Windfile actions are not defined, use default build script
switch (programmingExercise.getProgrammingLanguage()) {
case JAVA, KOTLIN -> scriptForJavaKotlin(programmingExercise, buildScript, hasSequentialTestRuns, hasStaticCodeAnalysis);
case PYTHON -> scriptForPython(buildScript);
default -> throw new IllegalArgumentException("No build stage setup for programming language " + programmingExercise.getProgrammingLanguage());
}
}
// *****************

try {
FileUtils.writeStringToFile(buildScriptPath.toFile(), buildScript.toString(), StandardCharsets.UTF_8);
}
Copy link

Choose a reason for hiding this comment

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

Note: This review was outside the patches, so it was mapped to the patch with the greatest overlap. Original lines [373-418]

The createBuildScript method has been refactored to generate a build script for a programming exercise. It is important to ensure that the script generation logic is secure and that the scripts are stored and executed in a way that does not expose the system to injection attacks or other security vulnerabilities.

Copy link
Member

@bassner bassner left a comment

Choose a reason for hiding this comment

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

LGTM

@bassner bassner merged commit 25177d2 into develop Dec 29, 2023
23 of 26 checks passed
@bassner bassner deleted the bugfix/fix-missing-aeolus-templates branch December 29, 2023 13:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
component:integrated code lifecycle ready to merge server Pull requests that update Java code. (Added Automatically!) small
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants