Skip to content

Commit

Permalink
Merge pull request #2 from aquarellian/master
Browse files Browse the repository at this point in the history
Fix for JENKINS-31006
  • Loading branch information
aquarellian committed Oct 18, 2015
2 parents 2e51279 + 1487f16 commit 2994332
Show file tree
Hide file tree
Showing 10 changed files with 229 additions and 20 deletions.
Expand Up @@ -13,6 +13,7 @@
import com.google.gerrit.extensions.common.FileInfo;
import com.google.gerrit.extensions.restapi.RestApiException;
import com.sonyericsson.hudson.plugins.gerrit.trigger.GerritManagement;
import com.sonyericsson.hudson.plugins.gerrit.trigger.VerdictCategory;
import com.sonyericsson.hudson.plugins.gerrit.trigger.config.IGerritHudsonTriggerConfig;
import com.sonyericsson.hudson.plugins.gerrit.trigger.hudsontrigger.GerritTrigger;
import com.urswolfer.gerrit.client.rest.GerritAuthData;
Expand Down Expand Up @@ -60,6 +61,9 @@ public class SonarToGerritBuilder extends Builder {

private static final String DEFAULT_PATH = "target/sonar/sonar-report.json";
private static final String DEFAULT_SONAR_URL = "http://localhost:9000";
private static final String DEFAULT_CATEGORY = "Code-Review";
private static final int DEFAULT_SCORE = 0;

public static final String GERRIT_FILE_DELIMITER = "/";
public static final String EMPTY_STR = "";

Expand All @@ -77,12 +81,17 @@ public class SonarToGerritBuilder extends Builder {
private final String noIssuesToPostText;
private final String someIssuesToPostText;
private final String issueComment;
private final boolean postScore;
private final String category;
private final String noIssuesScore;
private final String issuesScore;


@DataBoundConstructor
public SonarToGerritBuilder(String projectPath, String sonarURL, String path,
String severity, boolean changedLinesOnly, boolean newIssuesOnly,
String noIssuesToPostText, String someIssuesToPostText, String issueComment) {
String noIssuesToPostText, String someIssuesToPostText, String issueComment,
boolean postScore, String category, String noIssuesScore, String issuesScore) {
this.projectPath = MoreObjects.firstNonNull(projectPath, EMPTY_STR);
this.sonarURL = MoreObjects.firstNonNull(sonarURL, DEFAULT_SONAR_URL);
this.path = MoreObjects.firstNonNull(path, DEFAULT_PATH);
Expand All @@ -92,6 +101,10 @@ public SonarToGerritBuilder(String projectPath, String sonarURL, String path,
this.noIssuesToPostText = noIssuesToPostText;
this.someIssuesToPostText = someIssuesToPostText;
this.issueComment = issueComment;
this.postScore = postScore;
this.category = MoreObjects.firstNonNull(category, DEFAULT_CATEGORY);
this.noIssuesScore = noIssuesScore;
this.issuesScore = issuesScore;
}

public String getPath() {
Expand Down Expand Up @@ -130,6 +143,22 @@ public String getProjectPath() {
return projectPath;
}

public boolean isPostScore() {
return postScore;
}

public String getCategory() {
return category;
}

public String getNoIssuesScore() {
return noIssuesScore;
}

public String getIssuesScore() {
return issuesScore;
}

@Override
public boolean perform(AbstractBuild build, Launcher launcher, BuildListener listener) throws IOException,
InterruptedException {
Expand Down Expand Up @@ -199,7 +228,8 @@ public boolean apply(@Nullable String input) {
}

// Step 6 - Send review to Gerrit
ReviewInput reviewInput = getReviewResult(file2issues);
Collection<String> categoryNames = getCategoryNames(gerritConfig.getCategories());
ReviewInput reviewInput = getReviewResult(file2issues, categoryNames);

// Step 7 - Post review
revision.review(reviewInput);
Expand Down Expand Up @@ -227,8 +257,22 @@ private String getReviewMessage(Multimap<String, Issue> finalIssues) {
return new CustomReportFormatter(finalIssues.values(), someIssuesToPostText, noIssuesToPostText).getMessage();
}

private int getReviewMark(Multimap<String, Issue> finalIssues) {
String mark = finalIssues.size() > 0 ? issuesScore : noIssuesScore;
return parseNumber(mark, DEFAULT_SCORE);
}

private int parseNumber(String number, int deflt) {
try {
return Integer.parseInt(number);
} catch (NumberFormatException e) {
return deflt;
}

}

@VisibleForTesting
ReviewInput getReviewResult(Multimap<String, Issue> finalIssues) {
ReviewInput getReviewResult(Multimap<String, Issue> finalIssues, Collection<String> existingCategories) {
String reviewMessage = getReviewMessage(finalIssues);
ReviewInput reviewInput = new ReviewInput().message(reviewMessage);

Expand All @@ -255,9 +299,26 @@ public ReviewInput.CommentInput apply(@Nullable Issue input) {
)
);
}
if (postScore) {
String realCategory = getRealCategory(existingCategories);
reviewInput.label(realCategory, getReviewMark(finalIssues));
}
return reviewInput;
}

private Collection<String> getCategoryNames(List<VerdictCategory> categories){
Set<String> availableCategories = new HashSet<String>();
for (VerdictCategory verdictCategory : categories) {
availableCategories.add(verdictCategory.getVerdictDescription());
}
return availableCategories;
}

protected String getRealCategory(Collection<String> categories) {
// todo notify user about switching category to default?
return categories.contains(category) ? category : DEFAULT_CATEGORY;
}

@VisibleForTesting
void filterIssuesByChangedLines(Multimap<String, Issue> finalIssues, RevisionApi revision) throws RestApiException {
for (String filename : new HashSet<String>(finalIssues.keySet())) {
Expand Down Expand Up @@ -489,6 +550,45 @@ public FormValidation doCheckSeverity(@QueryParameter String value) {
return FormValidation.ok();
}

/**
* Performs on-the-fly validation of the form field 'noIssuesScore'.
*
* @param value This parameter receives the value that the user has typed.
* @return Indicates the outcome of the validation. This is sent to the browser.
* <p/>
* Note that returning {@link FormValidation#error(String)} does not
* prevent the form from being saved. It just means that a message
* will be displayed to the user.
*/
@SuppressWarnings(value = "unused")
public FormValidation doCheckNoIssuesScore(@QueryParameter String value) {
return checkScore(value);
}

/**
* Performs on-the-fly validation of the form field 'issuesScore'.
*
* @param value This parameter receives the value that the user has typed.
* @return Indicates the outcome of the validation. This is sent to the browser.
* <p/>
* Note that returning {@link FormValidation#error(String)} does not
* prevent the form from being saved. It just means that a message
* will be displayed to the user.
*/
@SuppressWarnings(value = "unused")
public FormValidation doCheckIssuesScore(@QueryParameter String value) {
return checkScore(value);
}

private FormValidation checkScore(@QueryParameter String value) {
try{
Integer.parseInt(value);
} catch (NumberFormatException e){
return FormValidation.error(getLocalized("jenkins.plugin.validation.review.score.not.numeric"));
}
return FormValidation.ok();
}

@Override
public boolean isApplicable(Class<? extends AbstractProject> aClass) {
// Indicates that this builder can be used with all kinds of project types
Expand Down
Expand Up @@ -35,7 +35,9 @@ private static String prepareText(String text, String defaultValue) {
public String getMessage() {
String res = text;
for (Tag tag : Tag.values()) {
res = res.replace(tag.getName(), getValueToReplace(tag));
if (res.contains(tag.getName())) {
res = res.replace(tag.getName(), getValueToReplace(tag));
}
}
return res;
}
Expand Down
2 changes: 2 additions & 0 deletions src/main/resources/messages.properties
Expand Up @@ -16,3 +16,5 @@ jenkins.plugin.error.gerrit.config.empty=Cannot obtain Gerrit configuration. Ple
jenkins.plugin.error.gerrit.user.empty=Gerrit authentication is not configured. Please check Gerrit Trigger settings
jenkins.plugin.error.sonar.report.not.exists=Sonar report '%s' does not exist. Please check plugin settings
jenkins.plugin.validation.review.severity.unknown=Unknown severity
jenkins.plugin.validation.review.category.unknown=Unknown category
jenkins.plugin.validation.review.score.not.numeric=Score should be numeric
Expand Up @@ -25,12 +25,30 @@
</f:entry>
</f:section>

<f:section title="${%jenkins.plugin.settings.section.gerrit.name}">
<f:entry title="${%jenkins.plugin.settings.gerrit.post.score}" field="postScore"
description="${%jenkins.plugin.settings.gerrit.post.score.description}">
<f:checkbox default="true"/>
</f:entry>
<f:entry title="${%jenkins.plugin.settings.gerrit.category}" field="category">
<f:textbox default="Code-Review"/>
</f:entry>
<f:entry title="${%jenkins.plugin.settings.gerrit.score.no.issues}" field="noIssuesScore">
<f:textbox default="+1" />
</f:entry>
<f:entry title="${%jenkins.plugin.settings.gerrit.score.issues}" field="issuesScore">
<f:textbox default="-1" />
</f:entry>
</f:section>

<f:section title="${%jenkins.plugin.settings.section.filter.name}">
<f:entry name="severity" title="${%jenkins.plugin.settings.filter.severity}" field="severity">
<select name="severity" field="severity">
<f:option value="INFO" selected="${instance.severity =='INFO'}">INFO</f:option>
<f:option value="MINOR" selected="${instance.severity =='MINOR'}">MINOR</f:option>
<f:option value="MAJOR" selected="${instance.severity =='MAJOR' || instance.severity == null}">MAJOR</f:option>
<f:option value="MAJOR"
selected="${instance.severity =='MAJOR' || instance.severity == null}">MAJOR
</f:option>
<f:option value="CRITICAL" selected="${instance.severity =='CRITICAL'}">CRITICAL</f:option>
<f:option value="BLOCKER" selected="${instance.severity =='BLOCKER'}">BLOCKER</f:option>
</select>
Expand Down
Expand Up @@ -24,5 +24,12 @@ jenkins.plugin.default.review.body=<severity> Sonar violation:\n\n\n<message>\n\
jenkins.plugin.default.review.title.no.issues=Sonar violations have not been found.
jenkins.plugin.default.review.title.issues=<total_count> Sonar violations have been found.

jenkins.plugin.settings.section.gerrit.name=Gerrit Settings
jenkins.plugin.settings.gerrit.post.score=Post score?
jenkins.plugin.settings.gerrit.post.score.description=This setting describes whether it is necessary to post score to Gerrit or not
jenkins.plugin.settings.gerrit.category=Category
jenkins.plugin.settings.gerrit.score.no.issues=Score for no Sonar violations found case
jenkins.plugin.settings.gerrit.score.issues=Score for Sonar violations found case



@@ -0,0 +1,4 @@
<div>
This field describes under what category score will appear in Gerrit.
This category should match one of existent Gerrit categories.
</div>
@@ -0,0 +1,3 @@
<div>
Score to be posted to Gerrit in case when there are Sonar violations found
</div>
@@ -0,0 +1,3 @@
<div>
Score to be posted to Gerrit in case when there are no Sonar violations found
</div>
@@ -0,0 +1,3 @@
<div>
This setting describes whether it is necessary to post score to Gerrit or not.
</div>

0 comments on commit 2994332

Please sign in to comment.