use of de.tum.in.www1.artemis.domain.participation.ProgrammingExerciseStudentParticipation in project ArTEMiS by ls1intum.
the class ProgrammingExerciseExportService method createZipForRepositoryWithParticipation.
/**
* Checks out the repository for the given participation, zips it and adds the path to the given list of already
* zipped repos.
*
* @param programmingExercise The programming exercise for the participation
* @param participation The participation, for which the repository should get zipped
* @param repositoryExportOptions The options, that should get applied to the zipped repo
* @param outputDir The directory used for downloading and zipping the repository
* @return The checked out and zipped repository
* @throws IOException if zip file creation failed
*/
private Path createZipForRepositoryWithParticipation(final ProgrammingExercise programmingExercise, final ProgrammingExerciseStudentParticipation participation, final RepositoryExportOptionsDTO repositoryExportOptions, Path outputDir) throws IOException, UncheckedIOException {
if (participation.getVcsRepositoryUrl() == null) {
log.warn("Ignore participation {} for export, because its repository URL is null", participation.getId());
return null;
}
try {
// Checkout the repository
Repository repository = gitService.getOrCheckoutRepository(participation, outputDir.toString());
if (repository == null) {
log.warn("Cannot checkout repository for participation id: {}", participation.getId());
return null;
}
gitService.resetToOriginHead(repository);
if (repositoryExportOptions.isFilterLateSubmissions()) {
filterLateSubmissions(repositoryExportOptions, participation, repository);
}
if (repositoryExportOptions.isAddParticipantName()) {
log.debug("Adding student or team name to participation {}", participation);
addParticipantIdentifierToProjectName(repository, programmingExercise, participation);
}
if (repositoryExportOptions.isCombineStudentCommits()) {
log.debug("Combining commits for participation {}", participation);
gitService.combineAllStudentCommits(repository, programmingExercise, repositoryExportOptions.isAnonymizeStudentCommits());
}
if (repositoryExportOptions.isAnonymizeStudentCommits()) {
log.debug("Anonymizing commits for participation {}", participation);
gitService.anonymizeStudentCommits(repository, programmingExercise);
}
if (repositoryExportOptions.isNormalizeCodeStyle()) {
try {
log.debug("Normalizing code style for participation {}", participation);
fileService.normalizeLineEndingsDirectory(repository.getLocalPath().toString());
fileService.convertToUTF8Directory(repository.getLocalPath().toString());
} catch (IOException ex) {
log.warn("Cannot normalize code style in the repository {} due to the following exception: {}", repository.getLocalPath(), ex.getMessage());
}
}
log.debug("Create temporary zip file for repository {}", repository.getLocalPath().toString());
return gitService.zipRepositoryWithParticipation(repository, outputDir.toString(), repositoryExportOptions.isHideStudentNameInZippedFolder());
} catch (GitAPIException | GitException ex) {
log.error("Failed to create zip for participation id {} with exercise id {} because of the following exception ", participation.getId(), participation.getProgrammingExercise().getId(), ex);
return null;
}
}
use of de.tum.in.www1.artemis.domain.participation.ProgrammingExerciseStudentParticipation in project ArTEMiS by ls1intum.
the class ProgrammingSubmissionResultSimulationService method createSubmission.
/**
* This method creates a new submission for the provided user
* @param exerciseId the exerciseId of the exercise for which a submission should be created
* This functionality is only for testing purposes (noVersionControlAndContinuousIntegrationAvailable)
* @return the newly created and stored submission
*/
public ProgrammingSubmission createSubmission(Long exerciseId) {
User user = userRepository.getUserWithGroupsAndAuthorities();
Participant participant = user;
ProgrammingExerciseStudentParticipation programmingExerciseStudentParticipation;
ProgrammingExercise programmingExercise = programmingExerciseRepository.findByIdWithStudentParticipationsAndLegalSubmissionsElseThrow(exerciseId);
Optional<StudentParticipation> optionalStudentParticipation = participationService.findOneByExerciseAndStudentLoginWithEagerSubmissionsAnyState(programmingExercise, user.getLogin());
if (optionalStudentParticipation.isEmpty()) {
programmingExerciseStudentParticipation = createParticipation(programmingExercise, participant, user);
} else {
programmingExerciseStudentParticipation = (ProgrammingExerciseStudentParticipation) optionalStudentParticipation.get();
}
ProgrammingSubmission programmingSubmission = new ProgrammingSubmission();
programmingSubmission.setCommitHash(VCSSimulationUtils.simulateCommitHash());
programmingSubmission.setSubmitted(true);
programmingSubmission.setSubmissionDate(ZonedDateTime.now());
programmingSubmission.setType(SubmissionType.MANUAL);
programmingExerciseStudentParticipation.addSubmission(programmingSubmission);
programmingSubmissionRepository.save(programmingSubmission);
return programmingSubmission;
}
use of de.tum.in.www1.artemis.domain.participation.ProgrammingExerciseStudentParticipation in project ArTEMiS by ls1intum.
the class AutomaticProgrammingExerciseCleanupService method deleteBuildPlans.
private void deleteBuildPlans(Set<ProgrammingExerciseStudentParticipation> participationsWithBuildPlanToDelete) {
// Limit to 5000 deletions per night
List<ProgrammingExerciseStudentParticipation> actualParticipationsToClean = participationsWithBuildPlanToDelete.stream().limit(5000).toList();
List<String> buildPlanIds = actualParticipationsToClean.stream().map(ProgrammingExerciseStudentParticipation::getBuildPlanId).toList();
log.info("Build plans to cleanup: {}", buildPlanIds);
int index = 0;
for (ProgrammingExerciseStudentParticipation participation : actualParticipationsToClean) {
if (index > 0 && index % externalSystemRequestBatchSize == 0) {
try {
log.info("Sleep for {}s during cleanupBuildPlansOnContinuousIntegrationServer", externalSystemRequestBatchWaitingTime / 1000);
Thread.sleep(externalSystemRequestBatchWaitingTime);
} catch (InterruptedException ex) {
log.error("Exception encountered when pausing before cleaning up build plans", ex);
}
}
try {
participationService.cleanupBuildPlan(participation);
} catch (Exception ex) {
log.error("Could not cleanup build plan in participation " + participation.getId(), ex);
}
index++;
}
log.info("{} build plans have been cleaned", actualParticipationsToClean.size());
}
use of de.tum.in.www1.artemis.domain.participation.ProgrammingExerciseStudentParticipation in project ArTEMiS by ls1intum.
the class AutomaticProgrammingExerciseCleanupService method cleanupBuildPlansOnContinuousIntegrationServer.
/**
* Cleans up old build plans on the continuous integration server
*/
public void cleanupBuildPlansOnContinuousIntegrationServer() {
log.info("Find build plans for potential cleanup");
AtomicLong countAfterBuildAndTestDate = new AtomicLong();
AtomicLong countNoResult = new AtomicLong();
AtomicLong countSuccessfulLatestResult = new AtomicLong();
AtomicLong countUnsuccessfulLatestResult = new AtomicLong();
Set<ProgrammingExerciseStudentParticipation> participationsWithBuildPlanToDelete = new HashSet<>();
var participationsWithBuildPlans = programmingExerciseStudentParticipationRepository.findAllWithBuildPlanIdWithResults();
log.info("Found {} potential build plans to delete", participationsWithBuildPlans.size());
participationsWithBuildPlans.forEach(participation -> {
if (participation.getBuildPlanId() == null || participation.getParticipant() == null) {
// already cleaned up or we only want to clean up build plans of students or teams (NOT template or solution build plans)
return;
}
if (participation.getProgrammingExercise() != null && Hibernate.isInitialized(participation.getProgrammingExercise())) {
var programmingExercise = participation.getProgrammingExercise();
if (checkFutureExamExercises(programmingExercise)) {
return;
}
if (checkBuildAndTestExercises(programmingExercise, participation, participationsWithBuildPlanToDelete, countAfterBuildAndTestDate)) {
return;
}
if (Boolean.TRUE.equals(programmingExercise.isPublishBuildPlanUrl())) {
// this was an exercise where students needed to configure the build plan, therefore we should not clean it up
return;
}
}
checkLastResults(participation, participationsWithBuildPlanToDelete, countNoResult, countSuccessfulLatestResult, countUnsuccessfulLatestResult);
});
log.info("Found {} old build plans to delete", participationsWithBuildPlanToDelete.size());
log.info(" Found {} build plans at least 1 day older than 'build and test submissions after due date", countAfterBuildAndTestDate);
log.info(" Found {} build plans without results 3 days after initialization", countNoResult);
log.info(" Found {} build plans with successful latest result is older than 1 day", countSuccessfulLatestResult);
log.info(" Found {} build plans with unsuccessful latest result is older than 5 days", countUnsuccessfulLatestResult);
deleteBuildPlans(participationsWithBuildPlanToDelete);
}
use of de.tum.in.www1.artemis.domain.participation.ProgrammingExerciseStudentParticipation in project ArTEMiS by ls1intum.
the class ProgrammingExerciseScheduleService method scheduleBuildAndTestAfterDueDateForParticipation.
private void scheduleBuildAndTestAfterDueDateForParticipation(ProgrammingExerciseStudentParticipation participation) {
scheduleService.scheduleParticipationTask(participation, ParticipationLifecycle.BUILD_AND_TEST_AFTER_DUE_DATE, () -> {
final ProgrammingExercise exercise = participation.getProgrammingExercise();
SecurityUtils.setAuthorizationObject();
try {
log.info("Invoking scheduled task for participation {} in programming exercise with id {}.", participation.getId(), exercise.getId());
programmingSubmissionService.triggerBuildForParticipations(List.of(participation));
} catch (EntityNotFoundException ex) {
log.error("Programming participation with id {} in exercise {} is no longer available in database for use in scheduled task.", participation.getId(), exercise.getId());
}
});
}
Aggregations