Skip to content
This repository has been archived by the owner on Jan 7, 2021. It is now read-only.

Commit

Permalink
implement approval conditioned on issue severities
Browse files Browse the repository at this point in the history
  • Loading branch information
t-8ch committed Jul 26, 2017
1 parent df720b0 commit ebc6931
Show file tree
Hide file tree
Showing 5 changed files with 74 additions and 12 deletions.
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,8 @@ Go to Stash general settings screen on SonarQube server to fill:

**Stash reviewer approval** (sonar.stash.reviewer.approval): SonarQube is able to approve the pull-request if there is no new issue introduced by the change. By default, this feature is deactivated: if activated, **Stash base user must have REPO_WRITE permission for the repositories.**

**Approval severity** (sonar.stash.reviewer.approval.severity.threshold): Only approve the pull-request if no issues higher than this threshold are detected.

**Include Analysis Overview Comment** (sonar.stash.include.overview): Toggles whether a comment with overview information should be created.

![Screenshot SonarQube plugin](resources/Sonar-plugin-approver.PNG)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package org.sonar.plugins.stash;

import java.util.Collection;
import java.util.Optional;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.sonar.api.BatchComponent;
Expand Down Expand Up @@ -116,9 +118,6 @@ private void postInfoAndPRsActions(PullRequestRef pr, List<Issue> issueReport, i
StashDiffReport diffReport,
StashClient stashClient) {

// Some local definitions
boolean canApprovePullrequest = config.canApprovePullRequest();

int issueTotal = issueReport.size();

// if threshold exceeded, do not push issue list to Stash
Expand All @@ -134,17 +133,26 @@ private void postInfoAndPRsActions(PullRequestRef pr, List<Issue> issueReport, i
stashRequestFacade.postAnalysisOverview(pr, issueThreshold, issueReport, stashClient);
}

// if no new issues and coverage is improved,
// plugin approves the pull-request
if (canApprovePullrequest) {
if (issueTotal == 0) {
if (config.canApprovePullRequest()) {
if (shouldApprovePullRequest(config.getApprovalSeverityThreshold(), issueReport)) {
stashRequestFacade.approvePullRequest(pr, stashClient);
} else {
stashRequestFacade.resetPullRequestApproval(pr, stashClient);
}
}
}

static boolean shouldApprovePullRequest(Optional<String> approvalSeverityThreshold, Collection<Issue> report) {
if (approvalSeverityThreshold.isPresent()) {
SeverityComparator sc = new SeverityComparator();
return report.stream().noneMatch(issue ->
sc.compare(issue.severity(), approvalSeverityThreshold.get()) > 0
);
}

return report.isEmpty();
}


/*
* Custom exception to keep nested if statements under control
Expand Down
9 changes: 9 additions & 0 deletions src/main/java/org/sonar/plugins/stash/StashPlugin.java
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ public class StashPlugin extends SonarPlugin {
public static final String STASH_PASSWORD = "sonar.stash.password";
public static final String STASH_PASSWORD_ENVIRONMENT_VARIABLE = "sonar.stash.password.variable";
public static final String STASH_REVIEWER_APPROVAL = "sonar.stash.reviewer.approval";
public static final String STASH_REVIEWER_APPROVAL_SEVERITY_THRESHOLD = "sonar.stash.reviewer.approval.severity.threshold";
public static final String STASH_ISSUE_THRESHOLD = "sonar.stash.issue.threshold";
public static final String STASH_TIMEOUT = "sonar.stash.timeout";
public static final String SONARQUBE_URL = "sonar.host.url";
Expand Down Expand Up @@ -130,6 +131,14 @@ public List getExtensions() {
.subCategory(CONFIG_PAGE_SUB_CATEGORY_STASH)
.onQualifiers(Qualifiers.PROJECT)
.defaultValue(DEFAULT_STASH_THRESHOLD_VALUE).build(),
PropertyDefinition.builder(STASH_REVIEWER_APPROVAL_SEVERITY_THRESHOLD)
.name("Threshold tie the approval to the severity of the found issues")
.description("Maximum severity of an issue for approval to complete")
.type(PropertyType.SINGLE_SELECT_LIST)
.subCategory(CONFIG_PAGE_SUB_CATEGORY_STASH)
.onQualifiers(Qualifiers.PROJECT)
.defaultValue(SEVERITY_NONE)
.options(SEVERITY_LIST_WITH_NONE).build(),
PropertyDefinition.builder(STASH_TASK_SEVERITY_THRESHOLD)
.name("Stash tasks severity threshold")
.description("Only create tasks for issues with the same or higher severity")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -86,11 +86,11 @@ public boolean resetComments() {
}

public Optional<String> getTaskIssueSeverityThreshold() {
String setting = settings.getString(StashPlugin.STASH_TASK_SEVERITY_THRESHOLD);
if (StashPlugin.SEVERITY_NONE.equals(setting)) {
return Optional.empty();
}
return Optional.of(setting);
return getOptionalSeveritySetting(StashPlugin.STASH_TASK_SEVERITY_THRESHOLD);
}

public Optional<String> getApprovalSeverityThreshold() {
return getOptionalSeveritySetting(StashPlugin.STASH_REVIEWER_APPROVAL_SEVERITY_THRESHOLD);
}

public String getSonarQubeVersion() {
Expand Down Expand Up @@ -125,4 +125,12 @@ public Set<RuleKey> excludedRules() {
.map(RuleKey::parse)
.collect(Collectors.toSet());
}

private Optional<String> getOptionalSeveritySetting(String key) {
String setting = settings.getString(key);
if (StashPlugin.SEVERITY_NONE.equals(setting)) {
return Optional.empty();
}
return Optional.of(setting);
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package org.sonar.plugins.stash;

import java.util.Optional;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
Expand All @@ -9,7 +10,9 @@
import org.sonar.api.batch.SensorContext;
import org.sonar.api.issue.Issue;
import org.sonar.api.issue.ProjectIssues;
import org.sonar.api.issue.internal.DefaultIssue;
import org.sonar.api.resources.Project;
import org.sonar.api.rule.Severity;
import org.sonar.plugins.stash.client.StashClient;
import org.sonar.plugins.stash.client.StashCredentials;
import org.sonar.plugins.stash.coverage.CoverageProjectStore;
Expand All @@ -19,6 +22,8 @@
import java.util.ArrayList;
import java.util.List;

import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.times;
Expand Down Expand Up @@ -247,6 +252,36 @@ public void testExecuteOnWithNoDiffReport() throws Exception {
verify(stashRequestFacade, times(0)).resetPullRequestApproval(eq(pr), (StashClient)Mockito.anyObject());
}

@Test
public void testShouldApprovePullRequest() {
Issue minorIssue = new DefaultIssue().setSeverity(Severity.MINOR);
Issue majorIssue = new DefaultIssue().setSeverity(Severity.MAJOR);

report = new ArrayList<>();

report.add(minorIssue);
report.add(majorIssue);

assertFalse(
StashIssueReportingPostJob.shouldApprovePullRequest(Optional.empty(), report)
);

report.clear();
assertTrue(
StashIssueReportingPostJob.shouldApprovePullRequest(Optional.empty(), report)
);

report.add(minorIssue);
assertTrue(
StashIssueReportingPostJob.shouldApprovePullRequest(Optional.of(Severity.MINOR), report)
);

report.add(majorIssue);
assertFalse(
StashIssueReportingPostJob.shouldApprovePullRequest(Optional.of(Severity.MINOR), report)
);
}

/* FIXME
@Test
public void testExecuteOnWithPullRequestApprovalAndNoNewIssueAndCodeCoverageEvolutionPositive() throws Exception {
Expand Down

0 comments on commit ebc6931

Please sign in to comment.