]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-9616 Fix notifications on branches (#2450)
authorJanos Gyerik <janos.gyerik@sonarsource.com>
Wed, 30 Aug 2017 15:20:32 +0000 (17:20 +0200)
committerJanos Gyerik <janos.gyerik@sonarsource.com>
Tue, 12 Sep 2017 09:34:55 +0000 (11:34 +0200)
14 files changed:
server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/step/QualityGateEventsStep.java
server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/step/SendIssueNotificationsStep.java
server/sonar-server/src/main/java/org/sonar/server/issue/notification/IssueChangeNotification.java
server/sonar-server/src/main/java/org/sonar/server/issue/notification/MyNewIssuesEmailTemplate.java
server/sonar-server/src/main/java/org/sonar/server/issue/notification/NewIssuesNotification.java
server/sonar-server/src/main/java/org/sonar/server/notification/email/AlertsEmailTemplate.java
server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/step/QualityGateEventsStepTest.java
server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/step/SendIssueNotificationsStepTest.java
server/sonar-server/src/test/java/org/sonar/server/issue/notification/IssueChangeNotificationTest.java
server/sonar-server/src/test/java/org/sonar/server/issue/notification/NewIssuesNotificationTest.java
server/sonar-server/src/test/java/org/sonar/server/notification/email/AlertsEmailTemplateTest.java
server/sonar-server/src/test/resources/org/sonar/server/issue/notification/MyNewIssuesEmailTemplateTest/email_with_all_details.txt
server/sonar-server/src/test/resources/org/sonar/server/issue/notification/MyNewIssuesEmailTemplateTest/email_with_issue_on_branch.txt
server/sonar-server/src/test/resources/org/sonar/server/issue/notification/MyNewIssuesEmailTemplateTest/email_with_no_assignee_tags_components.txt

index 5a042baf5747462c7f0222c4f2ef50297246700c..6de9d37adf42f7ae0b1e4a0054a472ef3d84c27e 100644 (file)
@@ -126,7 +126,7 @@ public class QualityGateEventsStep implements ComputationStep {
     Notification notification = new Notification("alerts")
       .setDefaultMessage(String.format("Alert on %s: %s", project.getName(), label))
       .setFieldValue("projectName", project.getName())
-      .setFieldValue("projectKey", project.getKey())
+      .setFieldValue("projectKey", getMainBranchProjectKey())
       .setFieldValue("projectUuid", project.getUuid())
       .setFieldValue("alertName", label)
       .setFieldValue("alertText", rawStatus.getText())
@@ -144,4 +144,8 @@ public class QualityGateEventsStep implements ComputationStep {
   public String getDescription() {
     return "Generate Quality gate events";
   }
+
+  private String getMainBranchProjectKey() {
+    return analysisMetadataHolder.getProject().getKey();
+  }
 }
index 1688932db8d6770374a37fe1134b213b4bf5883d..b0e752ec7d4ecfaa924ecbf9e8f6ab6276d9500c 100644 (file)
@@ -106,8 +106,7 @@ public class SendIssueNotificationsStep implements ComputationStep {
     IssueChangeNotification changeNotification = new IssueChangeNotification();
     changeNotification.setRuleName(rules.getByKey(issue.ruleKey()).getName());
     changeNotification.setIssue(issue);
-    String branchName = analysisMetadataHolder.getBranch().flatMap(Branch::getName).orElse(null);
-    changeNotification.setProject(project.getKey(), project.getName(), branchName);
+    changeNotification.setProject(getMainBranchProjectKey(), project.getName(), getBranchName());
     service.deliver(changeNotification);
   }
 
@@ -115,7 +114,7 @@ public class SendIssueNotificationsStep implements ComputationStep {
     NewIssuesStatistics.Stats globalStatistics = statistics.globalStatistics();
     NewIssuesNotification notification = newIssuesNotificationFactory
       .newNewIssuesNotication()
-      .setProject(project.getKey(), project.getUuid(), project.getName())
+      .setProject(getMainBranchProjectKey(), project.getUuid(), project.getName(), getBranchName())
       .setAnalysisDate(new Date(analysisDate))
       .setStatistics(project.getName(), globalStatistics)
       .setDebt(globalStatistics.debt());
@@ -131,7 +130,7 @@ public class SendIssueNotificationsStep implements ComputationStep {
         .newMyNewIssuesNotification()
         .setAssignee(assignee);
       myNewIssuesNotification
-        .setProject(project.getKey(), project.getUuid(), project.getName())
+        .setProject(getMainBranchProjectKey(), project.getUuid(), project.getName(), getBranchName())
         .setAnalysisDate(new Date(analysisDate))
         .setStatistics(project.getName(), assigneeStatistics)
         .setDebt(assigneeStatistics.debt());
@@ -145,4 +144,12 @@ public class SendIssueNotificationsStep implements ComputationStep {
     return "Send issue notifications";
   }
 
+  private String getBranchName() {
+    return analysisMetadataHolder.getBranch().filter(b -> !b.isMain()).flatMap(Branch::getName).orElse(null);
+  }
+
+  private String getMainBranchProjectKey() {
+    return analysisMetadataHolder.getProject().getKey();
+  }
+
 }
index f5aaa6cf104bdf1765fcd2231769f5140879a112..89eb60b901336a187a41864882bd6e57ae800739 100644 (file)
@@ -69,6 +69,7 @@ public class IssueChangeNotification extends Notification {
 
   public IssueChangeNotification setComponent(ComponentDto component) {
     setFieldValue("componentName", component.longName());
+    setFieldValue("componentKey", component.getKey());
     return this;
   }
 
index 3beaa27762cbdd9018e45a2f3d23a7291dbff0b1..5b1a35ecb319c8eb9936b6680122c0958c98eb3f 100644 (file)
@@ -55,21 +55,24 @@ public class MyNewIssuesEmailTemplate extends AbstractNewIssuesEmailTemplate {
 
   @Override
   protected void appendFooter(StringBuilder message, Notification notification) {
-    String projectUuid = notification.getFieldValue(FIELD_PROJECT_UUID);
+    String projectKey = notification.getFieldValue(FIELD_PROJECT_KEY);
     String dateString = notification.getFieldValue(FIELD_PROJECT_DATE);
     String assignee = notification.getFieldValue(FIELD_ASSIGNEE);
-    String branch = notification.getFieldValue(FIELD_BRANCH);
-    if (projectUuid != null && dateString != null && assignee != null) {
+    if (projectKey != null && dateString != null && assignee != null) {
       Date date = DateUtils.parseDateTime(dateString);
-      String url = String.format("%s/issues?projectUuids=%s&assignees=%s",
+      String url = String.format("%s/project/issues?id=%s&assignees=%s",
         settings.getServerBaseURL(),
-        encode(projectUuid),
+        encode(projectKey),
         encode(assignee));
-      if (branch != null) {
-        url += "&branch=" + encode(branch);
+      String branchName = notification.getFieldValue("branch");
+      if (branchName != null) {
+        url += "&branch=" + encode(branchName);
       }
       url += "&createdAt=" + encode(DateUtils.formatDateTime(date));
-      message.append("See it in SonarQube: ").append(url).append(NEW_LINE);
+      message
+        .append("See it in SonarQube: ")
+        .append(url)
+        .append(NEW_LINE);
     }
   }
 }
index b7dbae2629062cfcd05e72359707cdbd04d29f28..69a91c20081266f906623129d29c51dca0dbe2a3 100644 (file)
@@ -22,6 +22,7 @@ package org.sonar.server.issue.notification;
 import com.google.common.collect.Multiset;
 import java.util.Date;
 import java.util.List;
+import javax.annotation.Nullable;
 import org.sonar.api.notifications.Notification;
 import org.sonar.api.rule.RuleKey;
 import org.sonar.api.rule.Severity;
@@ -35,6 +36,7 @@ import org.sonar.server.issue.notification.NewIssuesStatistics.Metric;
 import org.sonar.server.user.index.UserDoc;
 import org.sonar.server.user.index.UserIndex;
 
+import static org.sonar.server.issue.notification.AbstractNewIssuesEmailTemplate.FIELD_BRANCH;
 import static org.sonar.server.issue.notification.NewIssuesEmailTemplate.FIELD_PROJECT_DATE;
 import static org.sonar.server.issue.notification.NewIssuesEmailTemplate.FIELD_PROJECT_KEY;
 import static org.sonar.server.issue.notification.NewIssuesEmailTemplate.FIELD_PROJECT_NAME;
@@ -69,10 +71,13 @@ public class NewIssuesNotification extends Notification {
     return this;
   }
 
-  public NewIssuesNotification setProject(String projectKey, String projectUuid, String projectName) {
+  public NewIssuesNotification setProject(String projectKey, String projectUuid, String projectName, @Nullable String branchName) {
     setFieldValue(FIELD_PROJECT_NAME, projectName);
     setFieldValue(FIELD_PROJECT_KEY, projectKey);
     setFieldValue(FIELD_PROJECT_UUID, projectUuid);
+    if (branchName != null) {
+      setFieldValue(FIELD_BRANCH, branchName);
+    }
     return this;
   }
 
index 4eb547b3821e726eca60205fd01730dc02949d40..58f1b218afebf377024ab125c0e616d912d5e7db 100644 (file)
@@ -19,6 +19,7 @@
  */
 package org.sonar.server.notification.email;
 
+import javax.annotation.Nullable;
 import org.apache.commons.lang.StringUtils;
 import org.sonar.api.config.EmailSettings;
 import org.sonar.api.measures.Metric;
@@ -49,6 +50,7 @@ public class AlertsEmailTemplate extends EmailTemplate {
     String projectId = notification.getFieldValue("projectId");
     String projectKey = notification.getFieldValue("projectKey");
     String projectName = notification.getFieldValue("projectName");
+    String branchName = notification.getFieldValue("branch");
     String alertName = notification.getFieldValue("alertName");
     String alertText = notification.getFieldValue("alertText");
     String alertLevel = notification.getFieldValue("alertLevel");
@@ -56,7 +58,7 @@ public class AlertsEmailTemplate extends EmailTemplate {
 
     // Generate text
     String subject = generateSubject(projectName, alertLevel, isNewAlert);
-    String messageBody = generateMessageBody(projectName, projectKey, alertName, alertText, isNewAlert);
+    String messageBody = generateMessageBody(projectName, projectKey, branchName, alertName, alertText, isNewAlert);
 
     // And finally return the email that will be sent
     return new EmailMessage()
@@ -77,7 +79,7 @@ public class AlertsEmailTemplate extends EmailTemplate {
     return subjectBuilder.toString();
   }
 
-  private String generateMessageBody(String projectName, String projectKey, String alertName, String alertText, boolean isNewAlert) {
+  private String generateMessageBody(String projectName, String projectKey, @Nullable String branchName, String alertName, String alertText, boolean isNewAlert) {
     StringBuilder messageBody = new StringBuilder();
     messageBody.append("Project: ").append(projectName).append("\n");
     messageBody.append("Quality gate status: ").append(alertName).append("\n\n");
@@ -100,6 +102,9 @@ public class AlertsEmailTemplate extends EmailTemplate {
     }
 
     messageBody.append("\n").append("See it in SonarQube: ").append(configuration.getServerBaseURL()).append("/dashboard?id=").append(projectKey);
+    if (branchName != null) {
+      messageBody.append("&branch=").append(branchName);
+    }
 
     return messageBody.toString();
   }
index 2508728aa4ae670ab7c7eb1bbdab1c734c89ac9a..76dcf82762eb4542a1cbc6dc03ade6177f5972f3 100644 (file)
@@ -26,6 +26,7 @@ import org.junit.Test;
 import org.mockito.ArgumentCaptor;
 import org.sonar.api.notifications.Notification;
 import org.sonar.server.computation.task.projectanalysis.analysis.AnalysisMetadataHolderRule;
+import org.sonar.server.computation.task.projectanalysis.analysis.Project;
 import org.sonar.server.computation.task.projectanalysis.component.Component;
 import org.sonar.server.computation.task.projectanalysis.component.DefaultBranchImpl;
 import org.sonar.server.computation.task.projectanalysis.component.ReportComponent;
@@ -81,6 +82,7 @@ public class QualityGateEventsStepTest {
   @Before
   public void setUp() {
     when(metricRepository.getByKey(ALERT_STATUS_KEY)).thenReturn(alertStatusMetric);
+    analysisMetadataHolder.setProject(new Project(PROJECT_COMPONENT.getUuid(), PROJECT_COMPONENT.getKey(), PROJECT_COMPONENT.getName()));
     analysisMetadataHolder.setBranch(null);
     treeRootHolder.setRoot(PROJECT_COMPONENT);
   }
index 6a692d8794e25549d29fbd445ea754f095a7dcb4..9db49085e2f825a29ee87a048d3af65be82c69b2 100644 (file)
@@ -30,6 +30,8 @@ import org.sonar.api.utils.Duration;
 import org.sonar.api.utils.System2;
 import org.sonar.core.issue.DefaultIssue;
 import org.sonar.server.computation.task.projectanalysis.analysis.AnalysisMetadataHolderRule;
+import org.sonar.server.computation.task.projectanalysis.analysis.Project;
+import org.sonar.server.computation.task.projectanalysis.component.DefaultBranchImpl;
 import org.sonar.server.computation.task.projectanalysis.component.TreeRootHolderRule;
 import org.sonar.server.computation.task.projectanalysis.component.Component;
 import org.sonar.server.computation.task.projectanalysis.component.Component.Type;
@@ -59,12 +61,18 @@ public class SendIssueNotificationsStepTest extends BaseStepTest {
   static final String PROJECT_KEY = "PROJECT_KEY";
   static final String PROJECT_NAME = "PROJECT_NAME";
 
+  static final String BRANCH_COMPONENT_UUID = "BRANCH_UUID";
+  static final String BRANCH_COMPONENT_KEY = "BRANCH_KEY";
+  static final String BRANCH_COMPONENT_NAME = "BRANCH_NAME";
+  static final String BRANCH_NAME = "feature";
+
   static final long ANALYSE_DATE = 123L;
 
   static final Duration ISSUE_DURATION = Duration.create(100L);
   static final String ISSUE_ASSIGNEE = "John";
 
   static final Component PROJECT = builder(Type.PROJECT, 1).setUuid(PROJECT_UUID).setKey(PROJECT_KEY).setName(PROJECT_NAME).build();
+  static final Component BRANCH = builder(Type.PROJECT, 2).setUuid(BRANCH_COMPONENT_UUID).setKey(BRANCH_COMPONENT_KEY).setName(BRANCH_COMPONENT_NAME).build();
 
   @Rule
   public TreeRootHolderRule treeRootHolder = new TreeRootHolderRule()
@@ -72,6 +80,8 @@ public class SendIssueNotificationsStepTest extends BaseStepTest {
 
   @Rule
   public AnalysisMetadataHolderRule analysisMetadataHolder = new AnalysisMetadataHolderRule()
+    .setProject(new Project(PROJECT_UUID, PROJECT_KEY, PROJECT_NAME))
+    .setBranch(new DefaultBranchImpl())
     .setAnalysisDate(new Date(ANALYSE_DATE));
 
   @Rule
@@ -115,12 +125,37 @@ public class SendIssueNotificationsStepTest extends BaseStepTest {
     underTest.execute();
 
     verify(notificationService).deliver(any(NewIssuesNotification.class));
-    verify(newIssuesNotificationMock).setProject(PROJECT_KEY, PROJECT_UUID, PROJECT_NAME);
+    verify(newIssuesNotificationMock).setProject(PROJECT_KEY, PROJECT_UUID, PROJECT_NAME, null);
     verify(newIssuesNotificationMock).setAnalysisDate(new Date(ANALYSE_DATE));
     verify(newIssuesNotificationMock).setStatistics(eq(PROJECT_NAME), any(NewIssuesStatistics.Stats.class));
     verify(newIssuesNotificationMock).setDebt(ISSUE_DURATION);
   }
 
+  @Test
+  public void send_global_new_issues_notification_on_branch() throws Exception {
+    issueCache.newAppender().append(
+      new DefaultIssue().setSeverity(Severity.BLOCKER).setEffort(ISSUE_DURATION)
+      ).close();
+
+    when(notificationService.hasProjectSubscribersForTypes(BRANCH_COMPONENT_UUID, SendIssueNotificationsStep.NOTIF_TYPES)).thenReturn(true);
+
+    analysisMetadataHolder.setBranch(new DefaultBranchImpl(BRANCH_NAME) {
+      @Override
+      public boolean isMain() {
+        return false;
+      }
+    });
+    treeRootHolder.setRoot(BRANCH);
+
+    underTest.execute();
+
+    verify(notificationService).deliver(any(NewIssuesNotification.class));
+    verify(newIssuesNotificationMock).setProject(PROJECT_KEY, BRANCH_COMPONENT_UUID, BRANCH_COMPONENT_NAME, BRANCH_NAME);
+    verify(newIssuesNotificationMock).setAnalysisDate(new Date(ANALYSE_DATE));
+    verify(newIssuesNotificationMock).setStatistics(eq(BRANCH_COMPONENT_NAME), any(NewIssuesStatistics.Stats.class));
+    verify(newIssuesNotificationMock).setDebt(ISSUE_DURATION);
+  }
+
   @Test
   public void send_new_issues_notification_to_user() throws Exception {
     issueCache.newAppender().append(
@@ -133,7 +168,7 @@ public class SendIssueNotificationsStepTest extends BaseStepTest {
 
     verify(notificationService, times(2)).deliver(any(Notification.class));
     verify(myNewIssuesNotificationMock).setAssignee(ISSUE_ASSIGNEE);
-    verify(myNewIssuesNotificationMock).setProject(PROJECT_KEY, PROJECT_UUID, PROJECT_NAME);
+    verify(myNewIssuesNotificationMock).setProject(PROJECT_KEY, PROJECT_UUID, PROJECT_NAME, null);
     verify(myNewIssuesNotificationMock).setAnalysisDate(new Date(ANALYSE_DATE));
     verify(myNewIssuesNotificationMock).setStatistics(eq(PROJECT_NAME), any(NewIssuesStatistics.Stats.class));
     verify(myNewIssuesNotificationMock).setDebt(ISSUE_DURATION);
@@ -153,7 +188,7 @@ public class SendIssueNotificationsStepTest extends BaseStepTest {
 
   private NewIssuesNotification createNewIssuesNotificationMock() {
     NewIssuesNotification notification = mock(NewIssuesNotification.class);
-    when(notification.setProject(anyString(), anyString(), anyString())).thenReturn(notification);
+    when(notification.setProject(anyString(), anyString(), anyString(), anyString())).thenReturn(notification);
     when(notification.setAnalysisDate(any(Date.class))).thenReturn(notification);
     when(notification.setStatistics(anyString(), any(NewIssuesStatistics.Stats.class))).thenReturn(notification);
     when(notification.setDebt(any(Duration.class))).thenReturn(notification);
@@ -163,7 +198,7 @@ public class SendIssueNotificationsStepTest extends BaseStepTest {
   private MyNewIssuesNotification createMyNewIssuesNotificationMock() {
     MyNewIssuesNotification notification = mock(MyNewIssuesNotification.class);
     when(notification.setAssignee(anyString())).thenReturn(notification);
-    when(notification.setProject(anyString(), anyString(), anyString())).thenReturn(notification);
+    when(notification.setProject(anyString(), anyString(), anyString(), anyString())).thenReturn(notification);
     when(notification.setAnalysisDate(any(Date.class))).thenReturn(notification);
     when(notification.setStatistics(anyString(), any(NewIssuesStatistics.Stats.class))).thenReturn(notification);
     when(notification.setDebt(any(Duration.class))).thenReturn(notification);
index c3eae3dbea8edb285b12d14d9d1b452f581d1b20..0ce96f6ba881ab685c42bfc9bc784a42684a4914 100644 (file)
@@ -103,6 +103,7 @@ public class IssueChangeNotificationTest {
   public void set_component() {
     IssueChangeNotification result = notification.setComponent(new ComponentDto().setDbKey("MyService").setLongName("My Service"));
     assertThat(result.getFieldValue("componentName")).isEqualTo("My Service");
+    assertThat(result.getFieldValue("componentKey")).isEqualTo("MyService");
   }
 
   @Test
index 9f531ef00bc0139739f853d12f3b264cf01e0ee1..1c62a3c083cf2fbef6a9bc7d9b1670bad7a4afeb 100644 (file)
@@ -55,12 +55,23 @@ public class NewIssuesNotificationTest {
   NewIssuesNotification underTest = new NewIssuesNotification(userIndex, dbClient, durations);
 
   @Test
-  public void set_project() {
-    underTest.setProject("project-key", "project-uuid", "project-long-name");
+  public void set_project_without_branch() {
+    underTest.setProject("project-key", "project-uuid", "project-long-name", null);
 
     assertThat(underTest.getFieldValue(NewIssuesEmailTemplate.FIELD_PROJECT_NAME)).isEqualTo("project-long-name");
     assertThat(underTest.getFieldValue(NewIssuesEmailTemplate.FIELD_PROJECT_UUID)).isEqualTo("project-uuid");
     assertThat(underTest.getFieldValue(NewIssuesEmailTemplate.FIELD_PROJECT_KEY)).isEqualTo("project-key");
+    assertThat(underTest.getFieldValue(NewIssuesEmailTemplate.FIELD_BRANCH)).isNull();
+  }
+
+  @Test
+  public void set_project_with_branch() {
+    underTest.setProject("project-key", "project-uuid", "project-long-name", "feature");
+
+    assertThat(underTest.getFieldValue(NewIssuesEmailTemplate.FIELD_PROJECT_NAME)).isEqualTo("project-long-name");
+    assertThat(underTest.getFieldValue(NewIssuesEmailTemplate.FIELD_PROJECT_UUID)).isEqualTo("project-uuid");
+    assertThat(underTest.getFieldValue(NewIssuesEmailTemplate.FIELD_PROJECT_KEY)).isEqualTo("project-key");
+    assertThat(underTest.getFieldValue(NewIssuesEmailTemplate.FIELD_BRANCH)).isEqualTo("feature");
   }
 
   @Test
index 01fc4bc81cd72ba224eba211fe657ab8bff9b095..550130d2f8918e5bb8bfdbaf8943134aa0907129 100644 (file)
@@ -101,6 +101,23 @@ public class AlertsEmailTemplateTest {
       "See it in SonarQube: http://nemo.sonarsource.org/dashboard?id=org.sonar.foo:foo"));
   }
 
+  @Test
+  public void shouldFormatNewAlertWithOneMessageOnBranch() {
+    Notification notification = createNotification("Orange (was Red)", "violations > 4", "WARN", "true")
+      .setFieldValue("branch", "feature");
+
+    EmailMessage message = template.format(notification);
+    assertThat(message.getMessageId(), is("alerts/45"));
+    assertThat(message.getSubject(), is("New quality gate threshold reached on \"Foo\""));
+    assertThat(message.getMessage(), is("" +
+      "Project: Foo\n" +
+      "Quality gate status: Orange (was Red)\n" +
+      "\n" +
+      "New quality gate threshold: violations > 4\n" +
+      "\n" +
+      "See it in SonarQube: http://nemo.sonarsource.org/dashboard?id=org.sonar.foo:foo&branch=feature"));
+  }
+
   @Test
   public void shouldFormatBackToGreenMessage() {
     Notification notification = createNotification("Green (was Red)", "", "OK", "false");
index 5b020cfc5e80e98dba674195444765a3ee6bd553..9091a95f55d527827098f0c82a162f9465379de9 100644 (file)
@@ -17,4 +17,4 @@ Project: Struts
         /path/to/file: 3
         /path/to/directory: 7
 
-See it in SonarQube: http://nemo.sonarsource.org/issues?projectUuids=ABCDE&assignees=lo.gin&createdAt=2010-05-1
\ No newline at end of file
+See it in SonarQube: http://nemo.sonarsource.org/project/issues?id=org.apache%3Astruts&assignees=lo.gin&createdAt=2010-05-18
index 543e42ea417cc42749291327e865b30fae3aa471..38979565eaa6754e66b737c57ea5f109d4a3b073 100644 (file)
@@ -5,4 +5,4 @@ Project: Struts
     Severity
         Blocker: 0    Critical: 5    Major: 10    Minor: 3    Info: 1
 
-See it in SonarQube: http://nemo.sonarsource.org/issues?projectUuids=ABCDE&assignees=lo.gin&branch=feature1&createdAt=2010-05-1
+See it in SonarQube: http://nemo.sonarsource.org/project/issues?id=org.apache%3Astruts&assignees=lo.gin&branch=feature1&createdAt=2010-05-18
index 7d978bdfcaac35f8e3da836f4286bf44a1ee9823..b5d1129d31246da52bbd79838c702bf9aaefdc4d 100644 (file)
@@ -5,4 +5,4 @@ Project: Struts
     Severity
         Blocker: 0    Critical: 5    Major: 10    Minor: 3    Info: 1
 
-See it in SonarQube: http://nemo.sonarsource.org/issues?projectUuids=ABCDE&assignees=lo.gin&createdAt=2010-05-1
\ No newline at end of file
+See it in SonarQube: http://nemo.sonarsource.org/project/issues?id=org.apache%3Astruts&assignees=lo.gin&createdAt=2010-05-18