Skip to content

Commit

Permalink
Merge branch 'feature/adaptive-learning/competency-link-weight' into …
Browse files Browse the repository at this point in the history
…feature/adaptive-learning/competency-link-weight-usage
  • Loading branch information
JohannesStoehr authored Oct 23, 2024
2 parents c38e022 + 038d66c commit 89eb015
Show file tree
Hide file tree
Showing 126 changed files with 6,343 additions and 1,743 deletions.
1 change: 1 addition & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -257,6 +257,7 @@ dependencies {
implementation "de.jplag:rust:${jplag_version}"
implementation "de.jplag:swift:${jplag_version}"
implementation "de.jplag:text:${jplag_version}"
implementation "de.jplag:typescript:${jplag_version}"

// those are transitive dependencies of JPlag Text --> Stanford NLP
// Note: ideally we would exclude them, but for some reason this does not work
Expand Down
4 changes: 4 additions & 0 deletions docs/user/exercises/programming-exercise-features.inc
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ Instructors can still use those templates to generate programming exercises and
+----------------------+----------+---------+
| C++ | yes | yes |
+----------------------+----------+---------+
| TypeScript | yes | yes |
+----------------------+----------+---------+

- Not all ``templates`` support the same feature set and supported features can also change depending on the continuous integration system setup.
Depending on the feature set, some options might not be available during the creation of the programming exercise.
Expand Down Expand Up @@ -79,6 +81,8 @@ Instructors can still use those templates to generate programming exercises and
+----------------------+----------------------+----------------------+---------------------+--------------+------------------------------------------+------------------------------+----------------------------+------------------------+
| C++ | no | no | yes | no | n/a | no | no | L: yes, J: no |
+----------------------+----------------------+----------------------+---------------------+--------------+------------------------------------------+------------------------------+----------------------------+------------------------+
| TypeScript | no | no | yes | no | n/a | no | no | L: yes, J: no |
+----------------------+----------------------+----------------------+---------------------+--------------+------------------------------------------+------------------------------+----------------------------+------------------------+

- *Sequential Test Runs*: ``Artemis`` can generate a build plan which first executes structural and then behavioral tests. This feature can help students to better concentrate on the immediate challenge at hand.
- *Static Code Analysis*: ``Artemis`` can generate a build plan which additionally executes static code analysis tools.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,11 @@
import java.io.IOException;
import java.net.URISyntaxException;
import java.nio.charset.StandardCharsets;
import java.nio.file.DirectoryStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.time.Duration;
import java.time.ZonedDateTime;
import java.util.ArrayList;
import java.util.List;
Expand All @@ -27,7 +30,10 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.event.ApplicationReadyEvent;
import org.springframework.context.annotation.Profile;
import org.springframework.context.event.EventListener;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import com.github.dockerjava.api.command.CreateContainerResponse;
Expand Down Expand Up @@ -71,6 +77,8 @@ public class BuildJobExecutionService {
@Value("${artemis.version-control.default-branch:main}")
private String defaultBranch;

private static final Duration TEMP_DIR_RETENTION_PERIOD = Duration.ofMinutes(5);

public BuildJobExecutionService(BuildJobContainerService buildJobContainerService, BuildJobGitService buildJobGitService, BuildAgentDockerService buildAgentDockerService,
BuildLogsMap buildLogsMap) {
this.buildJobContainerService = buildJobContainerService;
Expand All @@ -79,6 +87,38 @@ public BuildJobExecutionService(BuildJobContainerService buildJobContainerServic
this.buildLogsMap = buildLogsMap;
}

/**
* This method is responsible for cleaning up temporary directories that were used for checking out repositories.
* It is triggered when the application is ready and runs asynchronously.
*/
@EventListener(ApplicationReadyEvent.class)
@Async
public void initAsync() {
final ZonedDateTime currentTime = ZonedDateTime.now();
cleanUpTempDirectoriesAsync(currentTime);
}

private void cleanUpTempDirectoriesAsync(ZonedDateTime currentTime) {
log.info("Cleaning up temporary directories in {}", CHECKED_OUT_REPOS_TEMP_DIR);
try (DirectoryStream<Path> directoryStream = Files.newDirectoryStream(Path.of(CHECKED_OUT_REPOS_TEMP_DIR))) {
for (Path path : directoryStream) {
try {
ZonedDateTime lastModifiedTime = ZonedDateTime.ofInstant(Files.getLastModifiedTime(path).toInstant(), currentTime.getZone());
if (Files.isDirectory(path) && lastModifiedTime.isBefore(currentTime.minus(TEMP_DIR_RETENTION_PERIOD))) {
FileUtils.deleteDirectory(path.toFile());
}
}
catch (IOException e) {
log.error("Could not delete temporary directory {}", path, e);
}
}
}
catch (IOException e) {
log.error("Could not delete temporary directories", e);
}
log.info("Clean up of temporary directories in {} completed.", CHECKED_OUT_REPOS_TEMP_DIR);
}

/**
* Orchestrates the execution of a build job in a Docker container. This method handles the preparation and configuration of the container,
* including cloning the necessary repositories, checking out the appropriate branches, and preparing the environment for the build.
Expand Down Expand Up @@ -512,15 +552,16 @@ private void deleteCloneRepo(VcsRepositoryUri repositoryUri, @Nullable String co
}
buildJobGitService.deleteLocalRepository(repository);
}
// Do not throw an exception if deletion fails. If an exception occurs, clean up will happen in the next server start.
catch (EntityNotFoundException e) {
msg = "Error while checking out repository";
buildLogsMap.appendBuildLogEntry(buildJobId, msg);
throw new LocalCIException(msg, e);
log.error("Error while deleting repository with URI {} and Path {}", repositoryUri, repositoryPath, e);
}
catch (IOException e) {
msg = "Error while deleting repository";
buildLogsMap.appendBuildLogEntry(buildJobId, msg);
throw new LocalCIException(msg, e);
log.error("Error while deleting repository with URI {} and Path {}", repositoryUri, repositoryPath, e);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
import de.jplag.rlang.RLanguage;
import de.jplag.rust.RustLanguage;
import de.jplag.swift.SwiftLanguage;
import de.jplag.typescript.TypeScriptLanguage;
import de.tum.cit.aet.artemis.core.exception.BadRequestAlertException;
import de.tum.cit.aet.artemis.core.exception.GitException;
import de.tum.cit.aet.artemis.core.service.FileService;
Expand Down Expand Up @@ -321,7 +322,8 @@ private Language getJPlagProgrammingLanguage(ProgrammingExercise programmingExer
case R -> new RLanguage();
case RUST -> new RustLanguage();
case SWIFT -> new SwiftLanguage();
case EMPTY, PHP, DART, HASKELL, ASSEMBLER, OCAML, C_SHARP, SQL, TYPESCRIPT, GO, MATLAB, BASH, VHDL, RUBY, POWERSHELL, ADA -> throw new BadRequestAlertException(
case TYPESCRIPT -> new TypeScriptLanguage();
case EMPTY, PHP, DART, HASKELL, ASSEMBLER, OCAML, C_SHARP, SQL, GO, MATLAB, BASH, VHDL, RUBY, POWERSHELL, ADA -> throw new BadRequestAlertException(
"Programming language " + programmingExercise.getProgrammingLanguage() + " not supported for plagiarism check.", "ProgrammingExercise", "notSupported");
};
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ public enum ProgrammingLanguage {
R,
RUST,
SWIFT,
TYPESCRIPT,
VHDL,
EMPTY
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,8 @@ public TemplateUpgradePolicyService(JavaTemplateUpgradeService javaRepositoryUpg
public TemplateUpgradeService getUpgradeService(ProgrammingLanguage programmingLanguage) {
return switch (programmingLanguage) {
case JAVA -> javaRepositoryUpgradeService;
case KOTLIN, PYTHON, C, HASKELL, VHDL, ASSEMBLER, SWIFT, OCAML, EMPTY, RUST, JAVASCRIPT, R, C_PLUS_PLUS -> defaultRepositoryUpgradeService;
case C_SHARP, SQL, TYPESCRIPT, GO, MATLAB, BASH, RUBY, POWERSHELL, ADA, DART, PHP ->
case KOTLIN, PYTHON, C, HASKELL, VHDL, ASSEMBLER, SWIFT, OCAML, EMPTY, RUST, JAVASCRIPT, R, C_PLUS_PLUS, TYPESCRIPT -> defaultRepositoryUpgradeService;
case C_SHARP, SQL, GO, MATLAB, BASH, RUBY, POWERSHELL, ADA, DART, PHP ->
throw new UnsupportedOperationException("Unsupported programming language: " + programmingLanguage);
};
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -219,8 +219,8 @@ enum RepositoryCheckoutPath implements CustomizableCheckoutPath {
@Override
public String forProgrammingLanguage(ProgrammingLanguage language) {
return switch (language) {
case JAVA, PYTHON, C, HASKELL, KOTLIN, VHDL, ASSEMBLER, SWIFT, OCAML, EMPTY, RUST, JAVASCRIPT, R, C_PLUS_PLUS -> "assignment";
case C_SHARP, SQL, TYPESCRIPT, GO, MATLAB, BASH, RUBY, POWERSHELL, ADA, DART, PHP ->
case JAVA, PYTHON, C, HASKELL, KOTLIN, VHDL, ASSEMBLER, SWIFT, OCAML, EMPTY, RUST, JAVASCRIPT, R, C_PLUS_PLUS, TYPESCRIPT -> "assignment";
case C_SHARP, SQL, GO, MATLAB, BASH, RUBY, POWERSHELL, ADA, DART, PHP ->
throw new UnsupportedOperationException("Unsupported programming language: " + language);
};
}
Expand All @@ -230,9 +230,9 @@ public String forProgrammingLanguage(ProgrammingLanguage language) {
@Override
public String forProgrammingLanguage(ProgrammingLanguage language) {
return switch (language) {
case JAVA, PYTHON, HASKELL, KOTLIN, SWIFT, EMPTY, RUST, JAVASCRIPT, R, C_PLUS_PLUS -> "";
case JAVA, PYTHON, HASKELL, KOTLIN, SWIFT, EMPTY, RUST, JAVASCRIPT, R, C_PLUS_PLUS, TYPESCRIPT -> "";
case C, VHDL, ASSEMBLER, OCAML -> "tests";
case C_SHARP, SQL, TYPESCRIPT, GO, MATLAB, BASH, RUBY, POWERSHELL, ADA, DART, PHP ->
case C_SHARP, SQL, GO, MATLAB, BASH, RUBY, POWERSHELL, ADA, DART, PHP ->
throw new UnsupportedOperationException("Unsupported programming language: " + language);
};
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import static de.tum.cit.aet.artemis.programming.domain.ProgrammingLanguage.R;
import static de.tum.cit.aet.artemis.programming.domain.ProgrammingLanguage.RUST;
import static de.tum.cit.aet.artemis.programming.domain.ProgrammingLanguage.SWIFT;
import static de.tum.cit.aet.artemis.programming.domain.ProgrammingLanguage.TYPESCRIPT;
import static de.tum.cit.aet.artemis.programming.domain.ProjectType.FACT;
import static de.tum.cit.aet.artemis.programming.domain.ProjectType.GCC;
import static de.tum.cit.aet.artemis.programming.domain.ProjectType.GRADLE_GRADLE;
Expand Down Expand Up @@ -47,5 +48,6 @@ public JenkinsProgrammingLanguageFeatureService() {
programmingLanguageFeatures.put(RUST, new ProgrammingLanguageFeature(RUST, false, false, true, false, false, List.of(), false, false));
// Jenkins is not supporting XCODE at the moment
programmingLanguageFeatures.put(SWIFT, new ProgrammingLanguageFeature(SWIFT, false, true, true, true, false, List.of(PLAIN), false, false));
programmingLanguageFeatures.put(TYPESCRIPT, new ProgrammingLanguageFeature(TYPESCRIPT, false, false, true, false, false, List.of(), false, false));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -184,8 +184,8 @@ private JenkinsXmlConfigBuilder builderFor(ProgrammingLanguage programmingLangua
throw new UnsupportedOperationException("Xcode templates are not available for Jenkins.");
}
return switch (programmingLanguage) {
case JAVA, KOTLIN, PYTHON, C, HASKELL, SWIFT, EMPTY, RUST, JAVASCRIPT, R, C_PLUS_PLUS -> jenkinsBuildPlanCreator;
case VHDL, ASSEMBLER, OCAML, C_SHARP, SQL, TYPESCRIPT, GO, MATLAB, BASH, RUBY, POWERSHELL, ADA, DART, PHP ->
case JAVA, KOTLIN, PYTHON, C, HASKELL, SWIFT, EMPTY, RUST, JAVASCRIPT, R, C_PLUS_PLUS, TYPESCRIPT -> jenkinsBuildPlanCreator;
case VHDL, ASSEMBLER, OCAML, C_SHARP, SQL, GO, MATLAB, BASH, RUBY, POWERSHELL, ADA, DART, PHP ->
throw new UnsupportedOperationException(programmingLanguage + " templates are not available for Jenkins.");
};
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
import static de.tum.cit.aet.artemis.programming.domain.ProgrammingLanguage.R;
import static de.tum.cit.aet.artemis.programming.domain.ProgrammingLanguage.RUST;
import static de.tum.cit.aet.artemis.programming.domain.ProgrammingLanguage.SWIFT;
import static de.tum.cit.aet.artemis.programming.domain.ProgrammingLanguage.TYPESCRIPT;
import static de.tum.cit.aet.artemis.programming.domain.ProgrammingLanguage.VHDL;
import static de.tum.cit.aet.artemis.programming.domain.ProjectType.FACT;
import static de.tum.cit.aet.artemis.programming.domain.ProjectType.GCC;
Expand Down Expand Up @@ -54,6 +55,7 @@ public LocalCIProgrammingLanguageFeatureService() {
programmingLanguageFeatures.put(R, new ProgrammingLanguageFeature(R, false, false, true, false, false, List.of(), false, true));
programmingLanguageFeatures.put(RUST, new ProgrammingLanguageFeature(RUST, false, false, true, false, false, List.of(), false, true));
programmingLanguageFeatures.put(SWIFT, new ProgrammingLanguageFeature(SWIFT, false, false, true, true, false, List.of(PLAIN), false, true));
programmingLanguageFeatures.put(TYPESCRIPT, new ProgrammingLanguageFeature(TYPESCRIPT, false, false, true, false, false, List.of(), false, true));
programmingLanguageFeatures.put(VHDL, new ProgrammingLanguageFeature(VHDL, false, false, false, false, false, List.of(), false, true));
}
}
2 changes: 2 additions & 0 deletions src/main/resources/config/application.yml
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,8 @@ artemis:
default: "ghcr.io/ls1intum/artemis-r-docker:v1.0.0"
c_plus_plus:
default: "ghcr.io/ls1intum/artemis-cpp-docker:v1.0.0"
typescript:
default: "ghcr.io/ls1intum/artemis-javascript-docker:v1.0.0"

management:
endpoints:
Expand Down
33 changes: 33 additions & 0 deletions src/main/resources/templates/aeolus/typescript/default.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
#!/usr/bin/env bash
set -e
export AEOLUS_INITIAL_DIRECTORY=${PWD}
install_dependencies () {
echo '⚙️ executing install_dependencies'
npm ci --prefer-offline --no-audit
}

build () {
echo '⚙️ executing build'
npm run build
}

test () {
echo '⚙️ executing test'
npm run test:ci
}

main () {
if [[ "${1}" == "aeolus_sourcing" ]]; then
return 0 # just source to use the methods in the subshell, no execution
fi
local _script_name
_script_name=${BASH_SOURCE[0]:-$0}
cd "${AEOLUS_INITIAL_DIRECTORY}"
bash -c "source ${_script_name} aeolus_sourcing; install_dependencies"
cd "${AEOLUS_INITIAL_DIRECTORY}"
bash -c "source ${_script_name} aeolus_sourcing; build"
cd "${AEOLUS_INITIAL_DIRECTORY}"
bash -c "source ${_script_name} aeolus_sourcing; test"
}

main "${@}"
16 changes: 16 additions & 0 deletions src/main/resources/templates/aeolus/typescript/default.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
api: v0.0.1
metadata:
name: TypeScript
description: Run tests using Jest
actions:
- name: install_dependencies
script: 'npm ci --prefer-offline --no-audit'
- name: build
script: 'npm run build'
- name: test
script: 'npm run test:ci'
runAlways: false
results:
- name: junit
path: 'junit.xml'
type: junit
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
/*
* This file configures the actual build steps for the automatic grading.
*
* !!!
* For regular exercises, there is no need to make changes to this file.
* Only this base configuration is actively supported by the Artemis maintainers
* and/or your Artemis instance administrators.
* !!!
*/

dockerImage = '#dockerImage'
dockerFlags = '#dockerArgs'

/**
* Main function called by Jenkins.
*/
void testRunner() {
docker.image(dockerImage).inside(dockerFlags) { c ->
runTestSteps()
}
}

private void runTestSteps() {
test()
}

/**
* Run unit tests
*/
private void test() {
stage('Install Dependencies') {
sh 'npm ci --prefer-offline --no-audit'
}
stage('Build') {
sh 'npm run build'
}
stage('Test') {
sh 'npm run test:ci'
}
}

/**
* Script of the post build tasks aggregating all JUnit files in $WORKSPACE/results.
*
* Called by Jenkins.
*/
void postBuildTasks() {
sh '''
rm -rf results
mkdir results
if [ -e junit.xml ]
then
sed -i 's/<testsuites[^>]*>/<testsuite>/g ; s/<\\/testsuites>/<\\/testsuite>/g' junit.xml
fi
cp junit.xml $WORKSPACE/results/ || true
sed -i 's/[^[:print:]\t]/�/g' $WORKSPACE/results/*.xml || true
'''
}

// very important, do not remove
// required so that Jenkins finds the methods defined in this script
return this
Loading

0 comments on commit 89eb015

Please sign in to comment.