diff options
author | Aurelien Poscia <aurelien.poscia@sonarsource.com> | 2022-09-15 12:05:00 +0200 |
---|---|---|
committer | sonartech <sonartech@sonarsource.com> | 2022-09-19 20:03:08 +0000 |
commit | 2030fa060a172f6e6eae760ed0abb993efb32755 (patch) | |
tree | c20d7ac4cb63e6470d3f482004adb786da7670e6 /sonar-core | |
parent | 4a7e7aaa6ca74e8414e6d1a54ff58aab2c772dad (diff) | |
download | sonarqube-2030fa060a172f6e6eae760ed0abb993efb32755.tar.gz sonarqube-2030fa060a172f6e6eae760ed0abb993efb32755.zip |
SONAR-17271 update issue changelog with information about webhook
Diffstat (limited to 'sonar-core')
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); } - } |