Skip to content

Commit

Permalink
Merge branch 'develop' into development/fix-PostIntegrationTest
Browse files Browse the repository at this point in the history
  • Loading branch information
bassner authored Sep 22, 2023
2 parents 700da16 + b7213f3 commit cec69c9
Show file tree
Hide file tree
Showing 70 changed files with 2,384 additions and 55 deletions.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 5 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,10 +41,11 @@
15. **[Learning analytics](https://ls1intum.github.io/Artemis/user/learning-analytics/)**: Artemis integrated different statistics for students to compare themselves to the course average. It allows instructors to evaluate the average student performance based on exercises and competencies.
16. **[Adaptive Learning](https://ls1intum.github.io/Artemis/user/adaptive-learning/)**: Artemis allows instructors and students to define and track competencies. Students can monitor their progress towards these goals, while instructors can provide tailored feedback. This approach integrates lectures and exercises under overarching learning objectives.
17. **[Tutorial Groups](https://ls1intum.github.io/Artemis/user/tutorialgroups/)**: Artemis support the management of tutorial groups of a course. This includes planning the sessions, assigning responsible tutors, registering students and tracking the attendance.
18. **[Scalable](https://ls1intum.github.io/Artemis/user/scaling/)**: Artemis scales to multiple courses with thousands of students. In fact, the largest course had 2,400 students. Administrators can easily scale Artemis with additional build agents in the continuous integration environment.
19. **[High user satisfaction](https://ls1intum.github.io/Artemis/user/user-experience/)**: Artemis is easy to use, provides guided tutorials. Developers focus on usability, user experience, and performance.
20. **Customizable**: It supports multiple instructors, editors, and tutors per course and allows instructors to customize many course settings
21. **[Open-source](https://ls1intum.github.io/Artemis/dev/open-source/)**: Free to use with a large community and many active maintainers.
18. **[Iris](https://artemis.cit.tum.de/about-iris)**: Artemis integrates Iris, a chatbot that supports students and instructors with common questions and tasks.
19. **[Scalable](https://ls1intum.github.io/Artemis/user/scaling/)**: Artemis scales to multiple courses with thousands of students. In fact, the largest course had 2,400 students. Administrators can easily scale Artemis with additional build agents in the continuous integration environment.
20. **[High user satisfaction](https://ls1intum.github.io/Artemis/user/user-experience/)**: Artemis is easy to use, provides guided tutorials. Developers focus on usability, user experience, and performance.
21. **Customizable**: It supports multiple instructors, editors, and tutors per course and allows instructors to customize many course settings
22. **[Open-source](https://ls1intum.github.io/Artemis/dev/open-source/)**: Free to use with a large community and many active maintainers.

## Roadmap

Expand Down
5 changes: 3 additions & 2 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -246,10 +246,10 @@ dependencies {
implementation "org.imsglobal:basiclti-util:1.2.0"
implementation "org.jasypt:jasypt:1.9.3"
implementation "me.xdrop:fuzzywuzzy:1.4.0"
implementation "com.atlassian.bamboo:bamboo-specs:9.2.1"
implementation "com.atlassian.bamboo:bamboo-specs:9.3.3"
implementation ("org.yaml:snakeyaml") {
version {
strictly "1.33" // needed for Bamboo-specs and to reduce the number of vulnerabilities, also see https://mvnrepository.com/artifact/org.yaml/snakeyaml
strictly "2.0" // needed for Bamboo-specs and to reduce the number of vulnerabilities, also see https://mvnrepository.com/artifact/org.yaml/snakeyaml
}
}

Expand Down Expand Up @@ -346,6 +346,7 @@ dependencies {
implementation "org.commonmark:commonmark:0.21.0"
implementation "commons-fileupload:commons-fileupload:1.5"
implementation "net.lingala.zip4j:zip4j:2.11.5"
implementation "org.jgrapht:jgrapht-core:1.5.2"


annotationProcessor "org.hibernate:hibernate-jpamodelgen:${hibernate_version}"
Expand Down
4 changes: 2 additions & 2 deletions docker/atlassian.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ services:
hostname: bitbucket
extra_hosts:
- "host.docker.internal:host-gateway"
image: ghcr.io/ls1intum/artemis-bitbucket:8.8.2
image: ghcr.io/ls1intum/artemis-bitbucket:8.13.1
pull_policy: always
volumes:
- artemis-bitbucket-data:/var/atlassian/application-data/bitbucket
Expand All @@ -44,7 +44,7 @@ services:
hostname: bamboo
extra_hosts:
- "host.docker.internal:host-gateway"
image: ghcr.io/ls1intum/artemis-bamboo:9.2.1
image: ghcr.io/ls1intum/artemis-bamboo:9.3.3
pull_policy: always
volumes:
- artemis-bamboo-data:/var/atlassian/application-data/bamboo
Expand Down
3 changes: 2 additions & 1 deletion docs/dev/development-process.rst
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ Naming Conventions for GitHub Pull Requests
1. The first term is a main feature of Artemis and is using code highlighting, e.g. “``Programming exercises``:”.

1. Possible feature tags are: ``Programming exercises``, ``Quiz exercises``, ``Modeling exercises``, ``Text exercises``, ``File upload exercises``, ``Exam mode``,
``Grading``, ``Assessment``, ``Communication``, ``Notifications``, ``Team exercises``, ``Lectures``, ``Plagiarism checks``, ``Learning analytics``, ``Adaptive learning``, ``Tutorial groups``.
``Grading``, ``Assessment``, ``Communication``, ``Notifications``, ``Team exercises``, ``Lectures``, ``Plagiarism checks``, ``Learning analytics``,
``Adaptive learning``, ``Tutorial groups``, ``Iris``.
2. If the change is not visible to end users, or it is a pure development or test improvement, we use the term “``Development``:”.
3. Everything else belongs to the ``General`` category.

Expand Down
10 changes: 0 additions & 10 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,9 @@
"@swimlane/ngx-graph": {
"d3-color": "^3.1.0",
"d3-interpolate": "^3.0.1",
"d3-brush": "^3.0.0"
"d3-transition": "^3.0.0",
"d3-brush": "^3.0.0",
"d3-selection": "^3.0.0"
},
"critters": "0.0.20",
"semver": "7.5.4",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import org.springframework.stereotype.Component;

import de.tum.in.www1.artemis.config.migration.entries.MigrationEntry20230808_203400;
import de.tum.in.www1.artemis.config.migration.entries.MigrationEntry20230920_181600;

/**
* This component allows registering certain entries containing functionality that gets executed on application startup. The entries must extend {@link MigrationEntry}.
Expand All @@ -29,6 +30,7 @@ public MigrationRegistry(MigrationService migrationService) {
this.migrationService = migrationService;

this.migrationEntryMap.put(1, MigrationEntry20230808_203400.class);
this.migrationEntryMap.put(2, MigrationEntry20230920_181600.class);
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import org.springframework.stereotype.Service;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestClientException;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.util.UriComponentsBuilder;

Expand Down Expand Up @@ -116,13 +117,29 @@ private static Optional<String> getRepositoryNameById(String html, Long id) {

@Override
public void overrideBuildPlanNotification(String projectKey, String buildPlanKey, VcsRepositoryUrl vcsRepositoryUrl) {
List<Long> notificationIds = getAllArtemisBuildPlanServerNotificationIds(buildPlanKey);

for (var notificationId : notificationIds) {
deleteBuildPlanServerNotificationId(buildPlanKey, notificationId);
Map<Long, String> notificationIds = getAllArtemisBuildPlanServerNotificationIds(buildPlanKey);
log.info("Found {} notifications for build plan {}", notificationIds.size(), buildPlanKey);

List<Long> idsWithValidUrl = notificationIds.entrySet().stream().filter(entry -> entry.getValue().equals(artemisServerUrl + NEW_RESULT_RESOURCE_API_PATH))
.map(Map.Entry::getKey).toList();
boolean hasValidUrl = !idsWithValidUrl.isEmpty();
if (hasValidUrl) {
log.info("Build plan {} already has a notification with the correct URL", buildPlanKey);
notificationIds.remove(idsWithValidUrl.get(0));
}

createBuildPlanServerNotification(buildPlanKey, artemisServerUrl + NEW_RESULT_RESOURCE_API_PATH);
notificationIds.forEach((id, url) -> {
try {
deleteBuildPlanServerNotificationId(buildPlanKey, id);
}
catch (RestClientException e) {
log.error("Could not delete notification with id " + id + " for build plan " + buildPlanKey, e);
}
});

if (!hasValidUrl) {
createBuildPlanServerNotification(buildPlanKey, artemisServerUrl + NEW_RESULT_RESOURCE_API_PATH);
}
}

@Override
Expand Down Expand Up @@ -297,7 +314,7 @@ public boolean buildPlanExists(String projectKey, String buildPlanKey) {
* @param buildPlanKey The key of the build plan, which is usually the name combined with the project, e.g. 'EIST16W1-GA56HUR'.
* @return a list of all notification ids
*/
private List<Long> getAllArtemisBuildPlanServerNotificationIds(String buildPlanKey) {
private Map<Long, String> getAllArtemisBuildPlanServerNotificationIds(String buildPlanKey) {
MultiValueMap<String, String> parameters = new LinkedMultiValueMap<>();
parameters.add("buildKey", buildPlanKey);
String requestUrl = bambooServerUrl + "/chain/admin/config/defaultChainNotification.action";
Expand All @@ -306,16 +323,16 @@ private List<Long> getAllArtemisBuildPlanServerNotificationIds(String buildPlanK
var response = restTemplate.exchange(builder.build().toUri(), HttpMethod.GET, null, String.class);
var html = response.getBody();
if (html == null) {
return List.of();
return Map.of();
}
Element notificationTableBody = Jsoup.parse(html).selectFirst("table#notificationTable tbody");
if (notificationTableBody == null) {
return List.of();
return Map.of();
}
// First column is the event, second column the recipient, third the actions
// If there is a URL, the URL is the recipient. In that case we take the notification id from the edit button
Elements entries = notificationTableBody.select("tr");
List<Long> notificationIds = new ArrayList<>();
Map<Long, String> notificationIdToRecipient = new HashMap<>();
for (Element entry : entries) {
Elements columns = entry.select("td");
if (columns.size() != 3) {
Expand All @@ -324,16 +341,14 @@ private List<Long> getAllArtemisBuildPlanServerNotificationIds(String buildPlanK
String recipient = columns.get(1).text();
String actions = columns.get(2).toString();
Pattern editNotificationIdPattern = Pattern.compile(".*?id=\"editNotification:(\\d+)\".*?");
if (recipient.trim().startsWith(artemisServerUrl)) {
Matcher matcher = editNotificationIdPattern.matcher(actions);
if (matcher.find()) {
String notificationIdString = matcher.group(1);
notificationIds.add(Long.parseLong(notificationIdString));
}
Matcher matcher = editNotificationIdPattern.matcher(actions);
if (matcher.find()) {
String notificationIdString = matcher.group(1);
notificationIdToRecipient.put(Long.parseLong(notificationIdString), recipient);
}
}

return notificationIds;
return notificationIdToRecipient;
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -223,10 +223,10 @@ private void migrateSolutions(List<SolutionProgrammingExerciseParticipation> par
migrateSolutionBuildPlan(participation, auxiliaryRepositories);

migrateTestRepository(participation);
log.info("Migrated template build plan for exercise {} in {}ms", participation.getProgrammingExercise().getId(), System.currentTimeMillis() - startMs);
log.info("Migrated solution build plan for exercise {} in {}ms", participation.getProgrammingExercise().getId(), System.currentTimeMillis() - startMs);
}
catch (Exception e) {
log.warn("Failed to migrate template build plan for exercise {} with buildPlanId {}", participation.getProgrammingExercise().getId(),
log.warn("Failed to migrate solution build plan for exercise {} with buildPlanId {}", participation.getProgrammingExercise().getId(),
participation.getBuildPlanId(), e);
errorList.add(participation);
}
Expand Down Expand Up @@ -319,8 +319,8 @@ private void migrateStudents(List<ProgrammingExerciseStudentParticipation> parti
log.info("Migrated student build plan for exercise {} in {}ms", participation.getProgrammingExercise().getId(), System.currentTimeMillis() - startMs);
}
catch (Exception e) {
log.warn("Failed to migrate template build plan for exercise {} with buildPlanId {}", participation.getProgrammingExercise().getId(),
participation.getBuildPlanId(), e);
log.warn("Failed to migrate student build plan for exercise {} with buildPlanId {}", participation.getProgrammingExercise().getId(), participation.getBuildPlanId(),
e);
errorList.add(participation);
}
}
Expand Down
Loading

0 comments on commit cec69c9

Please sign in to comment.