]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-4624 new issue resolution "muted"
authorSimon Brandhof <simon.brandhof@sonarsource.com>
Tue, 9 Dec 2014 21:28:16 +0000 (22:28 +0100)
committerSimon Brandhof <simon.brandhof@sonarsource.com>
Tue, 9 Dec 2014 21:28:16 +0000 (22:28 +0100)
server/sonar-server/src/main/java/org/sonar/server/issue/index/IssueIndex.java
server/sonar-server/src/test/resources/org/sonar/server/issue/ws/SearchActionMediumTest/display_facets.json
server/sonar-server/src/test/resources/org/sonar/server/issue/ws/SearchActionMediumTest/display_zero_facets.json
sonar-core/src/main/java/org/sonar/core/issue/workflow/IssueWorkflow.java
sonar-core/src/main/resources/org/sonar/l10n/core.properties
sonar-core/src/test/java/org/sonar/core/issue/workflow/IssueWorkflowTest.java
sonar-plugin-api/src/main/java/org/sonar/api/issue/DefaultTransitions.java
sonar-plugin-api/src/main/java/org/sonar/api/issue/Issue.java

index 2921dc90ab81d766eb84d5e5ed494a081199d3de..f7e1c1c1900b7318c3c812134d46d75d2ea629b5 100644 (file)
@@ -202,15 +202,6 @@ public class IssueIndex extends BaseIndex<Issue, FakeIssueDto, String> {
     return esFilter;
   }
 
-  public void deleteByProjectUuid(String uuid) {
-    QueryBuilder queryBuilder = QueryBuilders.filteredQuery(
-      QueryBuilders.matchAllQuery(),
-      FilterBuilders.boolFilter().must(FilterBuilders.termsFilter(IssueIndexDefinition.FIELD_ISSUE_PROJECT_UUID, uuid))
-      );
-
-    getClient().prepareDeleteByQuery(getIndexName()).setQuery(queryBuilder).get();
-  }
-
   public void deleteClosedIssuesOfProjectBefore(String uuid, Date beforeDate) {
     FilterBuilder projectFilter = FilterBuilders.boolFilter().must(FilterBuilders.termsFilter(IssueIndexDefinition.FIELD_ISSUE_PROJECT_UUID, uuid));
     FilterBuilder dateFilter = FilterBuilders.rangeFilter(IssueNormalizer.IssueField.ISSUE_CLOSE_DATE.field()).lt(beforeDate.getTime());
index 3560bf84625cf0237757a44cb9fc12c7c6fc2edc..20a42e280a08e2466ef4e54551293c10253abd5e 100644 (file)
         {
           "val": "REMOVED",
           "count": 0
+        },
+        {
+          "val": "MUTED",
+          "count": 0
         }
       ]
     },
index 65c2a5466c1e314fbadff20135d83391aee1f604..d4debbcb81f16b1025614013eb21277b2c74927f 100644 (file)
         {
           "val": "REMOVED",
           "count": 0
+        },
+        {
+          "val": "MUTED",
+          "count": 0
         }
       ]
     },
index 6ddf0a270c69545cbe343550b2cf186a66fc4403..c12bce14343ead8d18152a5660b81e876e34c8e5 100644 (file)
@@ -104,7 +104,26 @@ public class IssueWorkflow implements BatchComponent, ServerComponent, Startable
         .from(Issue.STATUS_CONFIRMED).to(Issue.STATUS_RESOLVED)
         .functions(new SetResolution(Issue.RESOLUTION_FALSE_POSITIVE), SetAssignee.UNASSIGN)
         .requiredProjectPermission(UserRole.ISSUE_ADMIN)
-        .build());
+        .build())
+
+      // resolve as muted
+      .transition(Transition.builder(DefaultTransitions.MUTE)
+        .from(Issue.STATUS_OPEN).to(Issue.STATUS_RESOLVED)
+        .functions(new SetResolution(Issue.RESOLUTION_MUTED), SetAssignee.UNASSIGN)
+        .requiredProjectPermission(UserRole.ISSUE_ADMIN)
+        .build())
+      .transition(Transition.builder(DefaultTransitions.MUTE)
+        .from(Issue.STATUS_REOPENED).to(Issue.STATUS_RESOLVED)
+        .functions(new SetResolution(Issue.RESOLUTION_MUTED), SetAssignee.UNASSIGN)
+        .requiredProjectPermission(UserRole.ISSUE_ADMIN)
+        .build())
+      .transition(Transition.builder(DefaultTransitions.MUTE)
+          .from(Issue.STATUS_CONFIRMED).to(Issue.STATUS_RESOLVED)
+          .functions(new SetResolution(Issue.RESOLUTION_MUTED), SetAssignee.UNASSIGN)
+          .requiredProjectPermission(UserRole.ISSUE_ADMIN)
+          .build()
+      );
+
   }
 
   private void buildAutomaticTransitions(StateMachine.Builder builder) {
@@ -143,11 +162,11 @@ public class IssueWorkflow implements BatchComponent, ServerComponent, Startable
         // Reopen issues that are marked as resolved but that are still alive.
         // Manual issues are kept resolved.
       .transition(Transition.builder("automaticreopen")
-        .from(Issue.STATUS_RESOLVED).to(Issue.STATUS_REOPENED)
-        .conditions(new IsEndOfLife(false), new HasResolution(Issue.RESOLUTION_FIXED), new IsManual(false))
-        .functions(new SetResolution(null), new SetCloseDate(false))
-        .automatic()
-        .build()
+          .from(Issue.STATUS_RESOLVED).to(Issue.STATUS_REOPENED)
+          .conditions(new IsEndOfLife(false), new HasResolution(Issue.RESOLUTION_FIXED), new IsManual(false))
+          .functions(new SetResolution(null), new SetCloseDate(false))
+          .automatic()
+          .build()
       );
   }
 
index 0b6a9905610ba928714bbd1380ea6a3af221730a..4dcf2f4b37e329b411603dfbaa4ce7af00b51bcb 100644 (file)
@@ -655,6 +655,7 @@ issue.transition.resolve=Resolve
 issue.transition.falsepositive=False Positive
 issue.transition.reopen=Reopen
 issue.transition.close=Close
+issue.transition.mute=Mute
 issue.set_severity=Change Severity
 issue.set_severity.submit=Change Severity
 issue.do_plan=Plan
@@ -669,6 +670,7 @@ issue.status.CONFIRMED=Confirmed
 issue.status.CLOSED=Closed
 issue.resolution.FALSE-POSITIVE=False Positive
 issue.resolution.FIXED=Fixed
+issue.resolution.MUTED=Muted
 issue.resolution.REMOVED=Removed
 issue.updated=Updated:
 issue.planned_for_x=Planned for {0}
index 6961d78d72c73711f3d422881acaeb9efc8da9d6..65b53358f16b8be875492763e1baab07b2dca5b5 100644 (file)
@@ -47,7 +47,7 @@ public class IssueWorkflowTest {
   IssueWorkflow workflow = new IssueWorkflow(new FunctionExecutor(updater), updater);
 
   @Test
-  public void should_init_state_machine() throws Exception {
+  public void init_state_machine() throws Exception {
     assertThat(workflow.machine()).isNull();
     workflow.start();
     assertThat(workflow.machine()).isNotNull();
@@ -60,54 +60,50 @@ public class IssueWorkflowTest {
   }
 
   @Test
-  public void should_list_statuses() throws Exception {
+  public void list_statuses() throws Exception {
     workflow.start();
     // order is important for UI
     assertThat(workflow.statusKeys()).containsSequence(Issue.STATUS_OPEN, Issue.STATUS_CONFIRMED, Issue.STATUS_REOPENED, Issue.STATUS_RESOLVED, Issue.STATUS_CLOSED);
   }
 
   @Test
-  public void should_list_out_transitions_from_status_open() throws Exception {
+  public void list_out_transitions_from_status_open() throws Exception {
     workflow.start();
 
     DefaultIssue issue = new DefaultIssue().setStatus(Issue.STATUS_OPEN);
     List<Transition> transitions = workflow.outTransitions(issue);
-    assertThat(transitions).hasSize(3);
-    assertThat(keys(transitions)).containsOnly("confirm", "falsepositive", "resolve");
+    assertThat(keys(transitions)).containsOnly("confirm", "falsepositive", "resolve", "mute");
   }
 
   @Test
-  public void should_list_out_transitions_from_status_confirmed() throws Exception {
+  public void list_out_transitions_from_status_confirmed() throws Exception {
     workflow.start();
 
     DefaultIssue issue = new DefaultIssue().setStatus(Issue.STATUS_CONFIRMED);
     List<Transition> transitions = workflow.outTransitions(issue);
-    assertThat(transitions).hasSize(3);
-    assertThat(keys(transitions)).containsOnly("unconfirm", "falsepositive", "resolve");
+    assertThat(keys(transitions)).containsOnly("unconfirm", "falsepositive", "resolve", "mute");
   }
 
   @Test
-  public void should_list_out_transitions_from_status_resolved() throws Exception {
+  public void list_out_transitions_from_status_resolved() throws Exception {
     workflow.start();
 
     DefaultIssue issue = new DefaultIssue().setStatus(Issue.STATUS_RESOLVED);
     List<Transition> transitions = workflow.outTransitions(issue);
-    assertThat(transitions).hasSize(1);
     assertThat(keys(transitions)).containsOnly("reopen");
   }
 
   @Test
-  public void should_list_out_transitions_from_status_reopen() throws Exception {
+  public void list_out_transitions_from_status_reopen() throws Exception {
     workflow.start();
 
     DefaultIssue issue = new DefaultIssue().setStatus(Issue.STATUS_REOPENED);
     List<Transition> transitions = workflow.outTransitions(issue);
-    assertThat(transitions).hasSize(3);
-    assertThat(keys(transitions)).containsOnly("confirm", "resolve", "falsepositive");
+    assertThat(keys(transitions)).containsOnly("confirm", "mute", "resolve", "falsepositive", "mute");
   }
 
   @Test
-  public void should_list_no_out_transition_from_status_closed() throws Exception {
+  public void list_no_out_transition_from_status_closed() throws Exception {
     workflow.start();
 
     DefaultIssue issue = new DefaultIssue().setStatus(Issue.STATUS_CLOSED);
@@ -116,7 +112,7 @@ public class IssueWorkflowTest {
   }
 
   @Test
-  public void should_list_out_transitions_from_status_closed_on_manual_issue() throws Exception {
+  public void list_out_transitions_from_status_closed_on_manual_issue() throws Exception {
     workflow.start();
 
     // Manual issue because of reporter
@@ -127,12 +123,11 @@ public class IssueWorkflowTest {
       .setReporter("simon");
 
     List<Transition> transitions = workflow.outTransitions(issue);
-    assertThat(transitions).hasSize(1);
     assertThat(keys(transitions)).containsOnly("reopen");
   }
 
   @Test
-  public void should_fail_if_unknown_status_when_listing_transitions() throws Exception {
+  public void fail_if_unknown_status_when_listing_transitions() throws Exception {
     workflow.start();
 
     DefaultIssue issue = new DefaultIssue().setStatus("xxx");
@@ -146,7 +141,7 @@ public class IssueWorkflowTest {
 
 
   @Test
-  public void should_do_automatic_transition() throws Exception {
+  public void do_automatic_transition() throws Exception {
     workflow.start();
 
     DefaultIssue issue = new DefaultIssue()
@@ -164,7 +159,7 @@ public class IssueWorkflowTest {
   }
 
   @Test
-  public void should_close_open_dead_issue() throws Exception {
+  public void close_open_dead_issue() throws Exception {
     workflow.start();
 
     DefaultIssue issue = new DefaultIssue()
@@ -182,7 +177,7 @@ public class IssueWorkflowTest {
   }
 
   @Test
-  public void should_close_reopened_dead_issue() throws Exception {
+  public void close_reopened_dead_issue() throws Exception {
     workflow.start();
 
     DefaultIssue issue = new DefaultIssue()
@@ -200,7 +195,7 @@ public class IssueWorkflowTest {
   }
 
   @Test
-  public void should_close_confirmed_dead_issue() throws Exception {
+  public void close_confirmed_dead_issue() throws Exception {
     workflow.start();
 
     DefaultIssue issue = new DefaultIssue()
@@ -219,7 +214,7 @@ public class IssueWorkflowTest {
 
 
   @Test
-  public void should_fail_if_unknown_status_on_automatic_trans() throws Exception {
+  public void fail_if_unknown_status_on_automatic_trans() throws Exception {
     workflow.start();
 
     DefaultIssue issue = new DefaultIssue()
@@ -237,7 +232,7 @@ public class IssueWorkflowTest {
   }
 
   @Test
-  public void should_flag_as_false_positive() throws Exception {
+  public void flag_as_false_positive() throws Exception {
     DefaultIssue issue = new DefaultIssue()
       .setKey("ABCDE")
       .setStatus(Issue.STATUS_OPEN)
@@ -255,7 +250,25 @@ public class IssueWorkflowTest {
   }
 
   @Test
-  public void manual_issues_should_be_resolved_then_closed() throws Exception {
+  public void mute() throws Exception {
+    DefaultIssue issue = new DefaultIssue()
+      .setKey("ABCDE")
+      .setStatus(Issue.STATUS_OPEN)
+      .setRuleKey(RuleKey.of("squid", "AvoidCycle"))
+      .setAssignee("morgan");
+
+    workflow.start();
+    workflow.doTransition(issue, DefaultTransitions.MUTE, IssueChangeContext.createScan(new Date()));
+
+    assertThat(issue.resolution()).isEqualTo(Issue.RESOLUTION_MUTED);
+    assertThat(issue.status()).isEqualTo(Issue.STATUS_RESOLVED);
+
+    // should remove assignee
+    assertThat(issue.assignee()).isNull();
+  }
+
+  @Test
+  public void manual_issues_be_resolved_then_closed() throws Exception {
     // Manual issue because of reporter
     DefaultIssue issue = new DefaultIssue()
       .setKey("ABCDE")
@@ -268,7 +281,8 @@ public class IssueWorkflowTest {
     assertThat(workflow.outTransitions(issue)).containsOnly(
       Transition.create("confirm", "OPEN", "CONFIRMED"),
       Transition.create("resolve", "OPEN", "RESOLVED"),
-      Transition.create("falsepositive", "OPEN", "RESOLVED")
+      Transition.create("falsepositive", "OPEN", "RESOLVED"),
+      Transition.create("mute", "OPEN", "RESOLVED")
     );
 
     workflow.doTransition(issue, "resolve", mock(IssueChangeContext.class));
@@ -285,7 +299,7 @@ public class IssueWorkflowTest {
   }
 
   @Test
-  public void manual_issues_should_be_confirmed_then_kept_open() throws Exception {
+  public void manual_issues_be_confirmed_then_kept_open() throws Exception {
     // Manual issue because of reporter
     DefaultIssue issue = new DefaultIssue()
       .setKey("ABCDE")
@@ -298,7 +312,8 @@ public class IssueWorkflowTest {
     assertThat(workflow.outTransitions(issue)).containsOnly(
       Transition.create("confirm", "OPEN", "CONFIRMED"),
       Transition.create("resolve", "OPEN", "RESOLVED"),
-      Transition.create("falsepositive", "OPEN", "RESOLVED")
+      Transition.create("falsepositive", "OPEN", "RESOLVED"),
+      Transition.create("mute", "OPEN", "RESOLVED")
     );
 
     workflow.doTransition(issue, "confirm", mock(IssueChangeContext.class));
@@ -308,7 +323,8 @@ public class IssueWorkflowTest {
     assertThat(workflow.outTransitions(issue)).containsOnly(
       Transition.create("unconfirm", "CONFIRMED", "REOPENED"),
       Transition.create("resolve", "CONFIRMED", "RESOLVED"),
-      Transition.create("falsepositive", "CONFIRMED", "RESOLVED")
+      Transition.create("falsepositive", "CONFIRMED", "RESOLVED"),
+      Transition.create("mute", "CONFIRMED", "RESOLVED")
     );
 
     // keep confirmed and unresolved
@@ -323,7 +339,7 @@ public class IssueWorkflowTest {
   }
 
   @Test
-  public void manual_issue_on_removed_rule_should_be_closed() throws Exception {
+  public void manual_issue_on_removed_rule_be_closed() throws Exception {
     // Manual issue because of reporter
     DefaultIssue issue = new DefaultIssue()
       .setKey("ABCDE")
@@ -341,7 +357,7 @@ public class IssueWorkflowTest {
   }
 
   @Test
-  public void manual_issue_on_removed_component_should_be_closed() throws Exception {
+  public void manual_issue_on_removed_component_be_closed() throws Exception {
     // Manual issue because of reporter
     DefaultIssue issue = new DefaultIssue()
       .setKey("ABCDE")
index 94109badb362370c59d4cba38dd2bb0bac39951e..b8de744b26608130bb2cc226cfa105d888985b25 100644 (file)
@@ -35,8 +35,13 @@ public interface DefaultTransitions {
   String FALSE_POSITIVE = "falsepositive";
   String CLOSE = "close";
 
+  /**
+   * @since 5.1
+   */
+  String MUTE = "mute";
+
   /**
    * @since 4.4
    */
-  List<String> ALL = ImmutableList.of(CONFIRM, UNCONFIRM, REOPEN, RESOLVE, FALSE_POSITIVE, CLOSE);
+  List<String> ALL = ImmutableList.of(CONFIRM, UNCONFIRM, REOPEN, RESOLVE, FALSE_POSITIVE, MUTE, CLOSE);
 }
index 9bc6322ea1bc1759dbebef6e0ece8a97d357c6e7..55caecffcae5e68cdc0b70583e31daeaa03bc67f 100644 (file)
@@ -61,7 +61,13 @@ public interface Issue extends Serializable {
     */
   String RESOLUTION_REMOVED = "REMOVED";
 
-  List<String> RESOLUTIONS = ImmutableList.of(RESOLUTION_FALSE_POSITIVE, RESOLUTION_FIXED, RESOLUTION_REMOVED);
+  /**
+   * Issue is irrelevant in the context and was muted by user.
+   * @since 5.1
+   */
+  String RESOLUTION_MUTED = "MUTED";
+
+  List<String> RESOLUTIONS = ImmutableList.of(RESOLUTION_FALSE_POSITIVE, RESOLUTION_MUTED, RESOLUTION_FIXED, RESOLUTION_REMOVED);
 
   /**
    * Return all available statuses