Skip to content

Commit

Permalink
Merge pull request #282 from uhafner/pr-summary
Browse files Browse the repository at this point in the history
Add a summary, that can be used as a comment in a PR
  • Loading branch information
uhafner authored Dec 1, 2023
2 parents 467e364 + 97e93d1 commit 88f82a4
Show file tree
Hide file tree
Showing 11 changed files with 334 additions and 131 deletions.
56 changes: 32 additions & 24 deletions src/main/java/edu/hm/hafner/grading/AnalysisMarkdown.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package edu.hm.hafner.grading;

import java.util.List;
import java.util.function.Function;

/**
Expand All @@ -8,7 +9,7 @@
* @author Tobias Effner
* @author Ullrich Hafner
*/
public class AnalysisMarkdown extends ScoreMarkdown {
public class AnalysisMarkdown extends ScoreMarkdown<AnalysisScore, AnalysisConfiguration> {
static final String TYPE = "Static Analysis Warnings Score";

/**
Expand All @@ -18,54 +19,61 @@ public AnalysisMarkdown() {
super(TYPE, "warning");
}

/**
* Renders the static analysis results in Markdown.
*
* @param aggregation
* the aggregation
*
* @return returns formatted string
*/
public String create(final AggregatedScore aggregation) {
var scores = aggregation.getAnalysisScores();
if (scores.isEmpty()) {
return getTitle(": not enabled");
}

var comment = new StringBuilder(MESSAGE_INITIAL_CAPACITY);
@Override
protected List<AnalysisScore> createScores(final AggregatedScore aggregation) {
return aggregation.getAnalysisScores();
}

@Override
protected void createSpecificDetails(final AggregatedScore aggregation, final List<AnalysisScore> scores,
final StringBuilder details) {
for (AnalysisScore score : scores) {
var configuration = score.getConfiguration();
comment.append(getTitle(String.format(": %d of %d", score.getValue(), score.getMaxScore()), score.getName()));
comment.append(formatColumns("Name", "Errors", "Warning High", "Warning Normal", "Warning Low", "Impact"));
comment.append(formatColumns(":-:", ":-:", ":-:", ":-:", ":-:", ":-:"));
score.getSubScores().forEach(subScore -> comment.append(formatColumns(
details.append(getTitle(String.format(": %d of %d", score.getValue(), score.getMaxScore()), score.getName()));
details.append(formatColumns("Name", "Errors", "Warning High", "Warning Normal", "Warning Low", "Impact"));
details.append(formatColumns(":-:", ":-:", ":-:", ":-:", ":-:", ":-:"));
score.getSubScores().forEach(subScore -> details.append(formatColumns(
subScore.getName(),
String.valueOf(subScore.getErrorSize()),
String.valueOf(subScore.getHighSeveritySize()),
String.valueOf(subScore.getNormalSeveritySize()),
String.valueOf(subScore.getLowSeveritySize()),
String.valueOf(subScore.getImpact()))));
if (score.getSubScores().size() > 1) {
comment.append(formatBoldColumns("Total",
details.append(formatBoldColumns("Total",
sum(aggregation, AnalysisScore::getErrorSize),
sum(aggregation, AnalysisScore::getHighSeveritySize),
sum(aggregation, AnalysisScore::getNormalSeveritySize),
sum(aggregation, AnalysisScore::getLowSeveritySize),
sum(aggregation, AnalysisScore::getImpact)));
}
comment.append(formatItalicColumns(IMPACT,
details.append(formatItalicColumns(IMPACT,
renderImpact(configuration.getErrorImpact()),
renderImpact(configuration.getHighImpact()),
renderImpact(configuration.getNormalImpact()),
renderImpact(configuration.getLowImpact()),
LEDGER));
}

return comment.toString();
}

private int sum(final AggregatedScore score, final Function<AnalysisScore, Integer> property) {
return score.getAnalysisScores().stream().map(property).reduce(Integer::sum).orElse(0);
}

@Override
protected void createSpecificSummary(final List<AnalysisScore> scores, final StringBuilder summary) {
for (AnalysisScore score : scores) {
summary.append("#");
summary.append(getTitle(score));
if (score.getReport().isEmpty()) {
summary.append("no warnings found");
}
else {
summary.append(String.format("%d warnings found (%d errors, %d high, %d normal, %d low)",
score.getTotalSize(), score.getErrorSize(),
score.getHighSeveritySize(), score.getNormalSeveritySize(), score.getLowSeveritySize()));
}
summary.append("\n");
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ public CodeCoverageMarkdown() {
}

@Override
protected List<CoverageScore> getCoverageScores(final AggregatedScore aggregation) {
protected List<CoverageScore> createScores(final AggregatedScore aggregation) {
return aggregation.getCodeCoverageScores();
}
}
56 changes: 26 additions & 30 deletions src/main/java/edu/hm/hafner/grading/CoverageMarkdown.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
* @author Tobias Effner
* @author Ullrich Hafner
*/
abstract class CoverageMarkdown extends ScoreMarkdown {
abstract class CoverageMarkdown extends ScoreMarkdown<CoverageScore, CoverageConfiguration> {
private final String coveredText;
private final String missedText;

Expand All @@ -20,54 +20,50 @@ abstract class CoverageMarkdown extends ScoreMarkdown {
this.missedText = missedText;
}

/**
* Renders the code coverage results in Markdown.
*
* @param aggregation
* the aggregated score
*
* @return returns formatted string
*/
public String create(final AggregatedScore aggregation) {
var scores = getCoverageScores(aggregation);
if (scores.isEmpty()) {
return getTitle(": not enabled");
}

var comment = new StringBuilder(MESSAGE_INITIAL_CAPACITY);

@Override
protected void createSpecificDetails(final AggregatedScore aggregation, final List<CoverageScore> scores,
final StringBuilder details) {
for (CoverageScore score : scores) {
var configuration = score.getConfiguration();
comment.append(getTitle(String.format(": %d of %d", score.getValue(), score.getMaxScore()), score.getName()));
comment.append(formatColumns("Name", coveredText, missedText, "Impact"));
comment.append(formatColumns(":-:", ":-:", ":-:", ":-:"));
score.getSubScores().forEach(subScore -> comment.append(formatColumns(
details.append(
getTitle(String.format(": %d of %d", score.getValue(), score.getMaxScore()), score.getName()));
details.append(formatColumns("Name", coveredText, missedText, "Impact"));
details.append(formatColumns(":-:", ":-:", ":-:", ":-:"));
score.getSubScores().forEach(subScore -> details.append(formatColumns(
subScore.getName(),
String.valueOf(subScore.getCoveredPercentage()),
String.valueOf(subScore.getMissedPercentage()),
String.valueOf(subScore.getImpact()))));
if (score.getSubScores().size() > 1) {
comment.append(formatBoldColumns("Total Ø",
details.append(formatBoldColumns("Total Ø",
score.getCoveredPercentage(),
score.getMissedPercentage(),
score.getImpact()));
}
comment.append(formatItalicColumns(IMPACT,
details.append(formatItalicColumns(IMPACT,
renderImpact(configuration.getCoveredPercentageImpact()),
renderImpact(configuration.getMissedPercentageImpact()),
LEDGER));
}

return comment.toString();
}

protected abstract List<CoverageScore> getCoverageScores(AggregatedScore aggregation);
@Override
protected void createSpecificSummary(final List<CoverageScore> scores, final StringBuilder summary) {
for (CoverageScore score : scores) {
summary.append("#");
summary.append(getTitle(score));
summary.append(String.format("%d%% %s, %d%% %s",
score.getCoveredPercentage(), getPlainText(coveredText),
score.getMissedPercentage(), getPlainText(missedText)));
summary.append("\n");
}
}

private int sum(final AggregatedScore score, final Function<CoverageScore, Integer> property) {
return getCoverageScores(score).stream().map(property).reduce(Integer::sum).orElse(0);
private String getPlainText(final String label) {
return label.replace("%", "");
}

private int average(final AggregatedScore score, final Function<CoverageScore, Integer> property) {
return sum(score, property) / getCoverageScores(score).size();
private int sum(final AggregatedScore score, final Function<CoverageScore, Integer> property) {
return createScores(score).stream().map(property).reduce(Integer::sum).orElse(0);
}
}
61 changes: 52 additions & 9 deletions src/main/java/edu/hm/hafner/grading/GradingReport.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,12 @@
* @author Tobias Effner
*/
public class GradingReport {

private static final TestMarkdown TEST_MARKDOWN = new TestMarkdown();
private static final AnalysisMarkdown ANALYSIS_MARKDOWN = new AnalysisMarkdown();
private static final CodeCoverageMarkdown CODE_COVERAGE_MARKDOWN = new CodeCoverageMarkdown();
private static final MutationCoverageMarkdown MUTATION_COVERAGE_MARKDOWN = new MutationCoverageMarkdown();

/**
* Returns a short header for the grading results, this value typically will be used as link name.
*
Expand All @@ -23,8 +29,7 @@ public String getHeader() {
}

/**
* Returns a short summary for the grading results. This text does not use Markdown and fits into a
* single line.
* Returns a short summary for the grading results. This text does not use Markdown and fits into a single line.
*
* @param score
* the aggregated score
Expand Down Expand Up @@ -57,20 +62,56 @@ public String getSummary(final AggregatedScore score) {
summary);
}

/**
* Creates a summary of the grading results in Markdown.
*
* @param score
* the aggregated score
* @param title
* the title of the summary
*
* @return Markdown text
*/
public String getMarkdownSummary(final AggregatedScore score, final String title) {
var summary = new StringBuilder();

summary.append(createTotal(score, title));

if (score.hasTests()) {
summary.append(TEST_MARKDOWN.createSummary(score));
}
if (score.hasCodeCoverage()) {
summary.append(CODE_COVERAGE_MARKDOWN.createSummary(score));
}
if (score.hasMutationCoverage()) {
summary.append(MUTATION_COVERAGE_MARKDOWN.createSummary(score));
}
if (score.hasAnalysis()) {
summary.append(ANALYSIS_MARKDOWN.createSummary(score));
}

return summary.toString();
}

/**
* Creates a detailed description of the grading results in Markdown.
*
* @param score
* the aggregated score
*
* @return Markdown text
*/
public String getDetails(final AggregatedScore score) {
return String.format("# Total score: %s/%s%n",
score.getAchievedScore(), score.getMaxScore())
+ new TestMarkdown().create(score)
+ new AnalysisMarkdown().create(score)
+ new CodeCoverageMarkdown().create(score)
+ new MutationCoverageMarkdown().create(score);
return createTotal(score, "Total score")
+ TEST_MARKDOWN.createDetails(score)
+ ANALYSIS_MARKDOWN.createDetails(score)
+ CODE_COVERAGE_MARKDOWN.createDetails(score)
+ MUTATION_COVERAGE_MARKDOWN.createDetails(score);
}

private String createTotal(final AggregatedScore score, final String title) {
return String.format("## %s: %s/%s%n",
title, score.getAchievedScore(), score.getMaxScore());
}

/**
Expand All @@ -80,10 +121,12 @@ public String getDetails(final AggregatedScore score) {
* the aggregated score
* @param exception
* the exception that caused the error
*
* @return Markdown text
*/
public String getErrors(final AggregatedScore score, final Throwable exception) {
return String.format("# Partial score: %s/%s%n:construction: The grading has been aborted due to an error.:construction:%n",
return String.format(
"# Partial score: %s/%s%n:construction: The grading has been aborted due to an error.:construction:%n",
score.getAchievedScore(), score.getMaxScore())
+ createExceptionSection(exception)
+ createLogSection(score);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ public MutationCoverageMarkdown() {
}

@Override
protected List<CoverageScore> getCoverageScores(final AggregatedScore aggregation) {
protected List<CoverageScore> createScores(final AggregatedScore aggregation) {
return aggregation.getMutationCoverageScores();
}
}
Loading

0 comments on commit 88f82a4

Please sign in to comment.