aboutsummaryrefslogtreecommitdiffstats
path: root/sonar-core
diff options
context:
space:
mode:
authorAurelien Poscia <aurelien.poscia@sonarsource.com>2022-09-15 12:05:00 +0200
committersonartech <sonartech@sonarsource.com>2022-09-19 20:03:08 +0000
commit2030fa060a172f6e6eae760ed0abb993efb32755 (patch)
treec20d7ac4cb63e6470d3f482004adb786da7670e6 /sonar-core
parent4a7e7aaa6ca74e8414e6d1a54ff58aab2c772dad (diff)
downloadsonarqube-2030fa060a172f6e6eae760ed0abb993efb32755.tar.gz
sonarqube-2030fa060a172f6e6eae760ed0abb993efb32755.zip
SONAR-17271 update issue changelog with information about webhook
Diffstat (limited to 'sonar-core')
-rw-r--r--sonar-core/src/main/java/org/sonar/core/issue/DefaultIssue.java4
-rw-r--r--sonar-core/src/main/java/org/sonar/core/issue/FieldDiffs.java101
-rw-r--r--sonar-core/src/main/java/org/sonar/core/issue/IssueChangeContext.java52
-rw-r--r--sonar-core/src/test/java/org/sonar/core/issue/DefaultIssueTest.java11
-rw-r--r--sonar-core/src/test/java/org/sonar/core/issue/FieldDiffsTest.java16
-rw-r--r--sonar-core/src/test/java/org/sonar/core/issue/IssueChangeContextTest.java42
6 files changed, 144 insertions, 82 deletions
diff --git a/sonar-core/src/main/java/org/sonar/core/issue/DefaultIssue.java b/sonar-core/src/main/java/org/sonar/core/issue/DefaultIssue.java
index b48470bcc01..ceabe70333c 100644
--- a/sonar-core/src/main/java/org/sonar/core/issue/DefaultIssue.java
+++ b/sonar-core/src/main/java/org/sonar/core/issue/DefaultIssue.java
@@ -33,8 +33,8 @@ import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
-import java.util.Set;
import java.util.Optional;
+import java.util.Set;
import javax.annotation.CheckForNull;
import javax.annotation.Nullable;
import org.apache.commons.lang.StringUtils;
@@ -502,6 +502,8 @@ public class DefaultIssue implements Issue, Trackable, org.sonar.api.ce.measure.
currentChange = new FieldDiffs();
currentChange.setUserUuid(context.userUuid());
currentChange.setCreationDate(context.date());
+ currentChange.setWebhookSource(context.getWebhookSource());
+ currentChange.setExternalUser(context.getExternalUser());
}
currentChange.setDiff(field, oldValue, newValue);
}
diff --git a/sonar-core/src/main/java/org/sonar/core/issue/FieldDiffs.java b/sonar-core/src/main/java/org/sonar/core/issue/FieldDiffs.java
index 1c9e1932116..d3ae735b67e 100644
--- a/sonar-core/src/main/java/org/sonar/core/issue/FieldDiffs.java
+++ b/sonar-core/src/main/java/org/sonar/core/issue/FieldDiffs.java
@@ -21,17 +21,22 @@ package org.sonar.core.issue;
import java.io.Serializable;
import java.nio.charset.StandardCharsets;
+import java.util.ArrayList;
import java.util.Base64;
import java.util.Date;
import java.util.LinkedHashMap;
+import java.util.List;
import java.util.Map;
import java.util.Objects;
+import java.util.Optional;
import javax.annotation.CheckForNull;
import javax.annotation.Nullable;
import org.apache.commons.lang.StringUtils;
import static com.google.common.base.Strings.emptyToNull;
import static com.google.common.base.Strings.isNullOrEmpty;
+import static org.apache.commons.lang.StringUtils.isNotBlank;
+import static org.apache.commons.lang.StringUtils.trimToNull;
/**
* PLUGINS MUST NOT USE THIS CLASS, EXCEPT FOR UNIT TESTING.
@@ -40,15 +45,19 @@ import static com.google.common.base.Strings.isNullOrEmpty;
*/
public class FieldDiffs implements Serializable {
private static final String CHAR_TO_ESCAPE = "|,{}=:";
- public static final String ASSIGNEE = "assignee";
- public static final String ENCODING_PREFIX = "{base64:";
- public static final String ENCODING_SUFFIX = "}";
+ private static final String ASSIGNEE = "assignee";
+ private static final String ENCODING_PREFIX = "{base64:";
+ private static final String ENCODING_SUFFIX = "}";
+ private static final String WEBHOOK_SOURCE = "webhookSource";
+ private static final String EXTERNAL_USER_KEY = "externalUser";
private final Map<String, Diff> diffs = new LinkedHashMap<>();
- private String issueKey;
- private String userUuid;
- private Date creationDate;
+ private String issueKey = null;
+ private String userUuid = null;
+ private Date creationDate = null;
+ private String externalUser = null;
+ private String webhookSource = null;
public Map<String, Diff> diffs() {
if (diffs.containsKey(ASSIGNEE)) {
@@ -66,9 +75,8 @@ public class FieldDiffs implements Serializable {
return diffs.get(field);
}
- @CheckForNull
- public String userUuid() {
- return userUuid;
+ public Optional<String> userUuid() {
+ return Optional.ofNullable(userUuid);
}
public FieldDiffs setUserUuid(@Nullable String s) {
@@ -85,9 +93,8 @@ public class FieldDiffs implements Serializable {
return this;
}
- @CheckForNull
- public String issueKey() {
- return issueKey;
+ public Optional<String> issueKey() {
+ return Optional.ofNullable(issueKey);
}
public FieldDiffs setIssueKey(@Nullable String issueKey) {
@@ -95,6 +102,24 @@ public class FieldDiffs implements Serializable {
return this;
}
+ public Optional<String> externalUser() {
+ return Optional.ofNullable(externalUser);
+ }
+
+ public FieldDiffs setExternalUser(@Nullable String externalUser) {
+ this.externalUser = externalUser;
+ return this;
+ }
+
+ public Optional<String> webhookSource() {
+ return Optional.ofNullable(webhookSource);
+ }
+
+ public FieldDiffs setWebhookSource(@Nullable String webhookSource) {
+ this.webhookSource = webhookSource;
+ return this;
+ }
+
@SuppressWarnings("unchecked")
public FieldDiffs setDiff(String field, @Nullable Serializable oldValue, @Nullable Serializable newValue) {
Diff diff = diffs.get(field);
@@ -121,23 +146,22 @@ public class FieldDiffs implements Serializable {
}
private String serialize(boolean shouldEncode) {
- StringBuilder sb = new StringBuilder();
- boolean notFirst = false;
- for (Map.Entry<String, Diff> entry : diffs.entrySet()) {
- if (notFirst) {
- sb.append(',');
- } else {
- notFirst = true;
- }
- sb.append(entry.getKey());
- sb.append('=');
- if (shouldEncode) {
- sb.append(entry.getValue().toEncodedString());
- } else {
- sb.append(entry.getValue().toString());
- }
+ List<String> serializedStrings = new ArrayList<>();
+ if (isNotBlank(webhookSource)) {
+ serializedStrings.add(WEBHOOK_SOURCE + "=" + webhookSource);
}
- return sb.toString();
+ if (isNotBlank(externalUser)) {
+ serializedStrings.add(EXTERNAL_USER_KEY + "=" + externalUser);
+ }
+ diffs.entrySet().stream()
+ .map(entry -> serializeKeyValuePair(shouldEncode, entry.getKey(), entry.getValue()))
+ .forEach(serializedStrings::add);
+ return StringUtils.join(serializedStrings, ",");
+ }
+
+ private static String serializeKeyValuePair(boolean shouldEncode, String key, Diff values) {
+ String serializedValues = shouldEncode ? values.toEncodedString() : values.toString();
+ return key + "=" + serializedValues;
}
public static FieldDiffs parse(@Nullable String s) {
@@ -152,21 +176,32 @@ public class FieldDiffs implements Serializable {
}
String[] keyValues = field.split("=", 2);
+ String key = keyValues[0];
if (keyValues.length == 2) {
String values = keyValues[1];
- int split = values.indexOf('|');
- if (split > -1) {
- diffs.setDiff(keyValues[0], emptyToNull(values.substring(0, split)), emptyToNull(values.substring(split + 1)));
+ if (EXTERNAL_USER_KEY.equals(key)) {
+ diffs.setExternalUser(trimToNull(values));
+ } else if (WEBHOOK_SOURCE.equals(key)) {
+ diffs.setWebhookSource(trimToNull(values));
} else {
- diffs.setDiff(keyValues[0], null, emptyToNull(values));
+ addDiff(diffs, key, values);
}
} else {
- diffs.setDiff(keyValues[0], null, null);
+ diffs.setDiff(key, null, null);
}
}
return diffs;
}
+ private static void addDiff(FieldDiffs diffs, String key, String values) {
+ int split = values.indexOf('|');
+ if (split > -1) {
+ diffs.setDiff(key, emptyToNull(values.substring(0, split)), emptyToNull(values.substring(split + 1)));
+ } else {
+ diffs.setDiff(key, null, emptyToNull(values));
+ }
+ }
+
@SuppressWarnings("unchecked")
Diff decode(Diff encoded) {
return new Diff(
diff --git a/sonar-core/src/main/java/org/sonar/core/issue/IssueChangeContext.java b/sonar-core/src/main/java/org/sonar/core/issue/IssueChangeContext.java
index a81a0ac2224..629da34db1a 100644
--- a/sonar-core/src/main/java/org/sonar/core/issue/IssueChangeContext.java
+++ b/sonar-core/src/main/java/org/sonar/core/issue/IssueChangeContext.java
@@ -33,14 +33,17 @@ public class IssueChangeContext implements Serializable {
private final Date date;
private final boolean scan;
private final boolean refreshMeasures;
- private final boolean fromAlm;
+ private final String externalUser;
+ private final String webhookSource;
- private IssueChangeContext(@Nullable String userUuid, Date date, boolean scan, boolean refreshMeasures, boolean fromAlm) {
+ private IssueChangeContext(Date date, boolean scan, boolean refreshMeasures, @Nullable String userUuid, @Nullable String externalUser,
+ @Nullable String webhookSource) {
this.userUuid = userUuid;
this.date = requireNonNull(date);
this.scan = scan;
this.refreshMeasures = refreshMeasures;
- this.fromAlm = fromAlm;
+ this.externalUser = externalUser;
+ this.webhookSource = webhookSource;
}
@CheckForNull
@@ -60,8 +63,14 @@ public class IssueChangeContext implements Serializable {
return refreshMeasures;
}
- public boolean fromAlm() {
- return fromAlm;
+ @Nullable
+ public String getExternalUser() {
+ return externalUser;
+ }
+
+ @Nullable
+ public String getWebhookSource() {
+ return webhookSource;
}
@Override
@@ -73,26 +82,13 @@ public class IssueChangeContext implements Serializable {
return false;
}
IssueChangeContext that = (IssueChangeContext) o;
- return scan == that.scan &&
- Objects.equals(userUuid, that.userUuid) &&
- Objects.equals(date, that.date) &&
- refreshMeasures == that.refreshMeasures;
+ return scan == that.scan && refreshMeasures == that.refreshMeasures && Objects.equals(userUuid, that.userUuid) && date.equals(that.date)
+ && Objects.equals(externalUser, that.getExternalUser()) && Objects.equals(webhookSource, that.getWebhookSource());
}
@Override
public int hashCode() {
- return Objects.hash(userUuid, date, scan, refreshMeasures, fromAlm);
- }
-
- @Override
- public String toString() {
- return "IssueChangeContext{" +
- "userUuid='" + userUuid + '\'' +
- ", date=" + date +
- ", scan=" + scan +
- ", refreshMeasures=" + refreshMeasures +
- ", fromAlm=" + fromAlm +
- '}';
+ return Objects.hash(userUuid, date, scan, refreshMeasures, externalUser, webhookSource);
}
public static IssueChangeContextBuilder newBuilder() {
@@ -112,7 +108,8 @@ public class IssueChangeContext implements Serializable {
private Date date;
private boolean scan = false;
private boolean refreshMeasures = false;
- private boolean fromAlm = false;
+ private String externalUser;
+ private String webhookSource;
private IssueChangeContextBuilder() {
}
@@ -137,13 +134,18 @@ public class IssueChangeContext implements Serializable {
return this;
}
- public IssueChangeContextBuilder withFromAlm() {
- this.fromAlm = true;
+ public IssueChangeContextBuilder setExternalUser(@Nullable String externalUser) {
+ this.externalUser = externalUser;
+ return this;
+ }
+
+ public IssueChangeContextBuilder setWebhookSource(@Nullable String webhookSource) {
+ this.webhookSource = webhookSource;
return this;
}
public IssueChangeContext build() {
- return new IssueChangeContext(userUuid, date, scan, refreshMeasures, fromAlm);
+ return new IssueChangeContext(date, scan, refreshMeasures, userUuid, externalUser, webhookSource);
}
}
}
diff --git a/sonar-core/src/test/java/org/sonar/core/issue/DefaultIssueTest.java b/sonar-core/src/test/java/org/sonar/core/issue/DefaultIssueTest.java
index 2a5091278b8..9f16990058b 100644
--- a/sonar-core/src/test/java/org/sonar/core/issue/DefaultIssueTest.java
+++ b/sonar-core/src/test/java/org/sonar/core/issue/DefaultIssueTest.java
@@ -30,6 +30,7 @@ import org.sonar.api.utils.Duration;
import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.Assert.fail;
import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
public class DefaultIssueTest {
@@ -198,9 +199,17 @@ public class DefaultIssueTest {
@Test
public void all_changes_contain_current_change() {
IssueChangeContext issueChangeContext = mock(IssueChangeContext.class);
- DefaultIssue issue = new DefaultIssue().setKey("AAA").setFieldChange(issueChangeContext, "actionPlan", "1.0", "1.1");
+ when(issueChangeContext.getExternalUser()).thenReturn("toto");
+ when(issueChangeContext.getWebhookSource()).thenReturn("github");
+
+ DefaultIssue issue = new DefaultIssue()
+ .setKey("AAA")
+ .setFieldChange(issueChangeContext, "actionPlan", "1.0", "1.1");
assertThat(issue.changes()).hasSize(1);
+ FieldDiffs actualDiffs = issue.changes().iterator().next();
+ assertThat(actualDiffs.externalUser()).contains(issueChangeContext.getExternalUser());
+ assertThat(actualDiffs.webhookSource()).contains(issueChangeContext.getWebhookSource());
}
@Test
diff --git a/sonar-core/src/test/java/org/sonar/core/issue/FieldDiffsTest.java b/sonar-core/src/test/java/org/sonar/core/issue/FieldDiffsTest.java
index dd2cb1d362e..330fe78c0c6 100644
--- a/sonar-core/src/test/java/org/sonar/core/issue/FieldDiffsTest.java
+++ b/sonar-core/src/test/java/org/sonar/core/issue/FieldDiffsTest.java
@@ -123,10 +123,12 @@ public class FieldDiffsTest {
@Test
public void test_toString() {
+ diffs.setWebhookSource("github");
+ diffs.setExternalUser("toto");
diffs.setDiff("severity", "BLOCKER", "INFO");
diffs.setDiff("resolution", "OPEN", "FIXED");
- assertThat(diffs.toString()).isEqualTo("severity=BLOCKER|INFO,resolution=OPEN|FIXED");
+ assertThat(diffs).hasToString("webhookSource=github,externalUser=toto,severity=BLOCKER|INFO,resolution=OPEN|FIXED");
}
@Test
@@ -142,14 +144,17 @@ public class FieldDiffsTest {
diffs.setDiff("severity", null, "INFO");
diffs.setDiff("assignee", "user1", null);
- assertThat(diffs.toString()).isEqualTo("severity=INFO,assignee=user1|");
+ assertThat(diffs).hasToString("severity=INFO,assignee=user1|");
}
@Test
public void test_parse() {
- diffs = FieldDiffs.parse("severity=BLOCKER|INFO,resolution=OPEN|FIXED,donut=|new,gambas=miam,acme=old|");
+ diffs = FieldDiffs.parse("severity=BLOCKER|INFO,webhookSource=github,resolution=OPEN|FIXED,donut=|new,gambas=miam,acme=old|,externalUser=charlie");
assertThat(diffs.diffs()).hasSize(5);
+ assertThat(diffs.webhookSource()).contains("github");
+ assertThat(diffs.externalUser()).contains("charlie");
+
FieldDiffs.Diff diff = diffs.diffs().get("severity");
assertThat(diff.oldValue()).isEqualTo("BLOCKER");
assertThat(diff.newValue()).isEqualTo("INFO");
@@ -187,7 +192,10 @@ public class FieldDiffsTest {
@Test
public void test_parse_empty_values() {
- diffs = FieldDiffs.parse("severity=INFO,resolution=");
+ diffs = FieldDiffs.parse("severity=INFO,resolution=,webhookSource=,externalUser=");
+
+ assertThat(diffs.externalUser()).isEmpty();
+ assertThat(diffs.webhookSource()).isEmpty();
assertThat(diffs.diffs()).hasSize(2);
FieldDiffs.Diff diff = diffs.diffs().get("severity");
diff --git a/sonar-core/src/test/java/org/sonar/core/issue/IssueChangeContextTest.java b/sonar-core/src/test/java/org/sonar/core/issue/IssueChangeContextTest.java
index d5467d90002..dedc1b551db 100644
--- a/sonar-core/src/test/java/org/sonar/core/issue/IssueChangeContextTest.java
+++ b/sonar-core/src/test/java/org/sonar/core/issue/IssueChangeContextTest.java
@@ -32,6 +32,8 @@ public class IssueChangeContextTest {
private static final Date NOW = new Date();
private static final String USER_UUID = "user_uuid";
+ private static final String EXTERNAL_USER = "toto@tata.com";
+ private static final String WEBHOOK_SOURCE = "github";
private IssueChangeContext context;
@@ -39,14 +41,14 @@ public class IssueChangeContextTest {
public void test_issueChangeContextByScanBuilder() {
context = issueChangeContextByScanBuilder(NOW).build();
- verifyContext(null, true, false, false);
+ verifyContext(true, false, null, null, null);
}
@Test
public void test_issueChangeContextByUserBuilder() {
context = issueChangeContextByUserBuilder(NOW, USER_UUID).build();
- verifyContext(USER_UUID, false, false, false);
+ verifyContext(false, false, USER_UUID, null, null);
}
@Test
@@ -56,16 +58,27 @@ public class IssueChangeContextTest {
.withRefreshMeasures()
.setUserUuid(USER_UUID)
.setDate(NOW)
- .withFromAlm()
+ .setExternalUser(EXTERNAL_USER)
+ .setWebhookSource(WEBHOOK_SOURCE)
.build();
- verifyContext(USER_UUID, true, true, true);
+ verifyContext(true, true, USER_UUID, EXTERNAL_USER, WEBHOOK_SOURCE);
}
@Test
public void test_equal() {
- context = IssueChangeContext.newBuilder().setUserUuid(USER_UUID).setDate(NOW).build();
- IssueChangeContext equalContext = IssueChangeContext.newBuilder().setUserUuid(USER_UUID).setDate(NOW).build();
+ context = IssueChangeContext.newBuilder()
+ .setUserUuid(USER_UUID)
+ .setDate(NOW)
+ .setExternalUser(EXTERNAL_USER)
+ .setWebhookSource(WEBHOOK_SOURCE)
+ .build();
+ IssueChangeContext equalContext = IssueChangeContext.newBuilder()
+ .setUserUuid(USER_UUID)
+ .setDate(NOW)
+ .setExternalUser(EXTERNAL_USER)
+ .setWebhookSource(WEBHOOK_SOURCE)
+ .build();
IssueChangeContext notEqualContext = IssueChangeContext.newBuilder().setUserUuid("other_user_uuid").setDate(NOW).build();
assertThat(context).isEqualTo(context)
@@ -79,24 +92,17 @@ public class IssueChangeContextTest {
public void test_hashCode() {
context = IssueChangeContext.newBuilder().setUserUuid(USER_UUID).setDate(NOW).build();
- assertThat(context.hashCode()).isEqualTo(Objects.hash(USER_UUID, NOW, false, false, false));
+ assertThat(context.hashCode()).isEqualTo(Objects.hash(USER_UUID, NOW, false, false, null, null));
}
- @Test
- public void test_toString() {
- context = IssueChangeContext.newBuilder().setUserUuid(USER_UUID).setDate(NOW).build();
- String expected = "IssueChangeContext{userUuid='user_uuid', date=" + NOW + ", scan=false, refreshMeasures=false, fromAlm=false}";
-
- assertThat(context).hasToString(expected);
- }
-
- private void verifyContext(@Nullable String userUuid, boolean scan, boolean refreshMeasures, boolean fromAlm) {
+ private void verifyContext(boolean scan, boolean refreshMeasures, @Nullable String userUuid, @Nullable String externalUser,
+ @Nullable String webhookSource) {
assertThat(context.userUuid()).isEqualTo(userUuid);
assertThat(context.date()).isEqualTo(NOW);
assertThat(context.scan()).isEqualTo(scan);
assertThat(context.refreshMeasures()).isEqualTo(refreshMeasures);
- assertThat(context.fromAlm()).isEqualTo(fromAlm);
+ assertThat(context.getExternalUser()).isEqualTo(externalUser);
+ assertThat(context.getWebhookSource()).isEqualTo(webhookSource);
}
-
}