Skip to content

Commit

Permalink
Development: Add build config entity for programming exercises (#8897)
Browse files Browse the repository at this point in the history
  • Loading branch information
BBesrour authored and JohannesWt committed Sep 23, 2024
1 parent 0ac2da5 commit b259b89
Show file tree
Hide file tree
Showing 111 changed files with 1,406 additions and 577 deletions.
186 changes: 35 additions & 151 deletions src/main/java/de/tum/in/www1/artemis/domain/ProgrammingExercise.java
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.UUID;
import java.util.stream.Collectors;
import java.util.stream.Stream;

Expand All @@ -28,7 +27,6 @@
import jakarta.persistence.OneToOne;
import jakarta.persistence.OrderColumn;
import jakarta.persistence.SecondaryTable;
import jakarta.validation.constraints.Size;

import org.hibernate.Hibernate;
import org.slf4j.Logger;
Expand All @@ -37,8 +35,6 @@
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.core.JsonProcessingException;

import de.tum.in.www1.artemis.domain.enumeration.AssessmentType;
import de.tum.in.www1.artemis.domain.enumeration.BuildPlanType;
Expand All @@ -56,8 +52,6 @@
import de.tum.in.www1.artemis.domain.participation.TemplateProgrammingExerciseParticipation;
import de.tum.in.www1.artemis.domain.submissionpolicy.SubmissionPolicy;
import de.tum.in.www1.artemis.service.ExerciseDateService;
import de.tum.in.www1.artemis.service.connectors.aeolus.Windfile;
import de.tum.in.www1.artemis.service.connectors.vcs.AbstractVersionControlService;
import de.tum.in.www1.artemis.service.programming.ProgrammingLanguageFeature;
import de.tum.in.www1.artemis.web.rest.errors.BadRequestAlertException;

Expand Down Expand Up @@ -94,6 +88,9 @@ public String getType() {
@Column(name = "allow_offline_ide", table = "programming_exercise_details")
private Boolean allowOfflineIde;

@Column(name = "allow_online_ide", table = "programming_exercise_details", nullable = false)
private boolean allowOnlineIde = false;

@Column(name = "static_code_analysis_enabled", table = "programming_exercise_details")
private Boolean staticCodeAnalysisEnabled;

Expand All @@ -107,9 +104,6 @@ public String getType() {
@Column(name = "package_name")
private String packageName;

@Column(name = "sequential_test_runs")
private Boolean sequentialTestRuns;

@Column(name = "show_test_names_to_students", table = "programming_exercise_details")
private boolean showTestNamesToStudents;

Expand All @@ -124,11 +118,6 @@ public String getType() {
@Column(name = "project_key", table = "programming_exercise_details", nullable = false)
private String projectKey;

@Size(max = 36)
@Nullable
@Column(name = "build_plan_access_secret", table = "programming_exercise_details", length = 36)
private String buildPlanAccessSecret;

@OneToOne(cascade = CascadeType.REMOVE, orphanRemoval = true, fetch = FetchType.LAZY)
@JoinColumn(unique = true, name = "template_participation_id")
@JsonIgnoreProperties("programmingExercise")
Expand Down Expand Up @@ -164,27 +153,13 @@ public String getType() {
@OneToMany(mappedBy = "exercise", cascade = CascadeType.REMOVE, orphanRemoval = true, fetch = FetchType.LAZY)
private Set<ExerciseHint> exerciseHints = new HashSet<>();

@Column(name = "testwise_coverage_enabled", table = "programming_exercise_details")
private boolean testwiseCoverageEnabled;

@Column(name = "branch", table = "programming_exercise_details")
private String branch;

@Column(name = "release_tests_with_example_solution", table = "programming_exercise_details")
private boolean releaseTestsWithExampleSolution;
@Column(name = "release_tests_with_example_solution", table = "programming_exercise_details", nullable = false)
private boolean releaseTestsWithExampleSolution = false;

@Column(name = "build_plan_configuration", table = "programming_exercise_details", columnDefinition = "longtext")
private String buildPlanConfiguration;

@Column(name = "build_script", table = "programming_exercise_details", columnDefinition = "longtext")
private String buildScript;

/**
* This boolean flag determines whether the solution repository should be checked out during the build (additional to the student's submission).
* This is currently only supported for HASKELL and OCAML, thus the default value is false.
*/
@Column(name = "checkout_solution_repository", table = "programming_exercise_details", columnDefinition = "boolean default false")
private boolean checkoutSolutionRepository;
@OneToOne(cascade = CascadeType.REMOVE, orphanRemoval = true, fetch = FetchType.LAZY)
@JoinColumn(unique = true, name = "programming_exercise_build_config_id", table = "programming_exercise_details")
@JsonIgnoreProperties("programmingExercise")
private ProgrammingExerciseBuildConfig buildConfig;

/**
* Convenience getter. The actual URL is stored in the {@link TemplateProgrammingExerciseParticipation}
Expand Down Expand Up @@ -298,6 +273,18 @@ public void setAllowOfflineIde(Boolean allowOfflineIde) {
this.allowOfflineIde = allowOfflineIde;
}

public boolean isAllowOnlineIde() {
return allowOnlineIde;
}

public void setAllowOnlineIde(boolean allowOnlineIde) {
this.allowOnlineIde = allowOnlineIde;
}

public String getProjectKey() {
return this.projectKey;
}

public Boolean isStaticCodeAnalysisEnabled() {
return this.staticCodeAnalysisEnabled;
}
Expand All @@ -314,25 +301,6 @@ public void setMaxStaticCodeAnalysisPenalty(Integer maxStaticCodeAnalysisPenalty
this.maxStaticCodeAnalysisPenalty = maxStaticCodeAnalysisPenalty;
}

public String getProjectKey() {
return this.projectKey;
}

public void setBranch(String branch) {
this.branch = branch;
}

/**
* Getter for the stored default branch of the exercise.
* Use {@link AbstractVersionControlService#getOrRetrieveBranchOfExercise(ProgrammingExercise)} if you are not sure that the value was already set in the Artemis database
*
* @return the name of the default branch or null if not yet stored in Artemis
*/
@JsonIgnore
public String getBranch() {
return branch;
}

public void setReleaseTestsWithExampleSolution(boolean releaseTestsWithExampleSolution) {
this.releaseTestsWithExampleSolution = releaseTestsWithExampleSolution;
}
Expand Down Expand Up @@ -482,6 +450,14 @@ public void setSubmissionPolicy(SubmissionPolicy submissionPolicy) {
this.submissionPolicy = submissionPolicy;
}

public ProgrammingExerciseBuildConfig getBuildConfig() {
return buildConfig;
}

public void setBuildConfig(ProgrammingExerciseBuildConfig buildConfig) {
this.buildConfig = buildConfig;
}

// jhipster-needle-entity-add-getters-setters - Jhipster will add getters and setters here, do not remove

/**
Expand Down Expand Up @@ -606,15 +582,6 @@ public void addStaticCodeAnalysisCategory(final StaticCodeAnalysisCategory categ
staticCodeAnalysisCategories.add(category);
}

@JsonProperty("sequentialTestRuns")
public boolean hasSequentialTestRuns() {
return Objects.requireNonNullElse(sequentialTestRuns, false);
}

public void setSequentialTestRuns(Boolean sequentialTestRuns) {
this.sequentialTestRuns = sequentialTestRuns;
}

public Boolean getShowTestNamesToStudents() {
return showTestNamesToStudents;
}
Expand Down Expand Up @@ -657,14 +624,6 @@ public void setProjectType(@Nullable ProjectType projectType) {
this.projectType = projectType;
}

public Boolean isTestwiseCoverageEnabled() {
return testwiseCoverageEnabled;
}

public void setTestwiseCoverageEnabled(Boolean testwiseCoverageEnabled) {
this.testwiseCoverageEnabled = testwiseCoverageEnabled;
}

/**
* set all sensitive information to null, so no info with respect to the solution gets leaked to students through json
*/
Expand All @@ -675,8 +634,9 @@ public void filterSensitiveInformation() {
setTestRepositoryUri(null);
setTemplateBuildPlanId(null);
setSolutionBuildPlanId(null);
setBuildPlanConfiguration(null);
setBuildScript(null);
if (buildConfig != null && Hibernate.isInitialized(buildConfig)) {
buildConfig.filterSensitiveInformation();
}
super.filterSensitiveInformation();
}

Expand Down Expand Up @@ -761,16 +721,8 @@ private boolean checkForAssessedResult(Result result) {
public String toString() {
return "ProgrammingExercise{" + "id=" + getId() + ", templateRepositoryUri='" + getTemplateRepositoryUri() + "'" + ", solutionRepositoryUri='" + getSolutionRepositoryUri()
+ "'" + ", templateBuildPlanId='" + getTemplateBuildPlanId() + "'" + ", solutionBuildPlanId='" + getSolutionBuildPlanId() + "'" + ", allowOnlineEditor='"
+ isAllowOnlineEditor() + "'" + ", programmingLanguage='" + getProgrammingLanguage() + "'" + ", packageName='" + getPackageName() + "'" + ", testCasesChanged='"
+ testCasesChanged + "'" + "}";
}

public boolean getCheckoutSolutionRepository() {
return this.checkoutSolutionRepository;
}

public void setCheckoutSolutionRepository(boolean checkoutSolutionRepository) {
this.checkoutSolutionRepository = checkoutSolutionRepository;
+ isAllowOnlineEditor() + "'" + ", allowOnlineIde='" + isAllowOnlineIde() + "'" + ", programmingLanguage='" + getProgrammingLanguage() + "'" + ", packageName='"
+ getPackageName() + "'" + "'" + ", testCasesChanged='" + testCasesChanged + "'" + "}";
}

/**
Expand Down Expand Up @@ -812,7 +764,7 @@ public void validateStaticCodeAnalysisSettings(ProgrammingLanguageFeature progra
}

// Check that programming exercise doesn't have sequential test runs and static code analysis enabled
if (Boolean.TRUE.equals(isStaticCodeAnalysisEnabled()) && hasSequentialTestRuns()) {
if (Boolean.TRUE.equals(isStaticCodeAnalysisEnabled()) && getBuildConfig().hasSequentialTestRuns()) {
throw new BadRequestAlertException("The static code analysis with sequential test runs is not supported at the moment", "Exercise", "staticCodeAnalysisAndSequential");
}

Expand Down Expand Up @@ -867,19 +819,6 @@ public void setExerciseHints(Set<ExerciseHint> exerciseHints) {
this.exerciseHints = exerciseHints;
}

public boolean hasBuildPlanAccessSecretSet() {
return buildPlanAccessSecret != null && !buildPlanAccessSecret.isEmpty();
}

@Nullable
public String getBuildPlanAccessSecret() {
return buildPlanAccessSecret;
}

public void generateAndSetBuildPlanAccessSecret() {
buildPlanAccessSecret = UUID.randomUUID().toString();
}

/**
* {@inheritDoc}
*/
Expand All @@ -890,61 +829,6 @@ public void disconnectRelatedEntities() {
super.disconnectRelatedEntities();
}

/**
* Returns the JSON encoded custom build plan configuration
*
* @return the JSON encoded custom build plan configuration or null if the default one should be used
*/
public String getBuildPlanConfiguration() {
return buildPlanConfiguration;
}

/**
* Sets the JSON encoded custom build plan configuration
*
* @param buildPlanConfiguration the JSON encoded custom build plan configuration
*/
public void setBuildPlanConfiguration(String buildPlanConfiguration) {
this.buildPlanConfiguration = buildPlanConfiguration;
}

/**
* We store the build plan configuration as a JSON string in the database, as it is easier to handle than a complex object structure.
* This method parses the JSON string and returns a {@link Windfile} object.
*
* @return the {@link Windfile} object or null if the JSON string could not be parsed
*/
public Windfile getWindfile() {
if (buildPlanConfiguration == null) {
return null;
}
try {
return Windfile.deserialize(buildPlanConfiguration);
}
catch (JsonProcessingException e) {
log.error("Could not parse build plan configuration for programming exercise {}", this.getId(), e);
}
return null;
}

/**
* We store the bash script in the database
*
* @return the build script or null if the build script does not exist
*/
public String getBuildScript() {
return buildScript;
}

/**
* Update the build script
*
* @param buildScript the new build script for the programming exercise
*/
public void setBuildScript(String buildScript) {
this.buildScript = buildScript;
}

/**
* In course exercises students shall receive immediate feedback. {@link Visibility#ALWAYS}
* In Exams misconfiguration and leaking test results to students during an exam shall be prevented by the default setting. {@link Visibility#AFTER_DUE_DATE}
Expand Down
Loading

0 comments on commit b259b89

Please sign in to comment.