import com.google.gson.annotations.SerializedName;
import java.util.List;
-import static org.sonar.alm.client.github.GithubApplicationClient.*;
+import static org.sonar.alm.client.github.GithubApplicationClient.Repository;
public class GithubBinding {
this.htmlUrl, this.defaultBranch);
}
}
+
+ public static class GsonGithubCodeScanningAlert {
+ @SerializedName("number")
+ long id;
+ @SerializedName("state")
+ GithubCodeScanningAlertState state;
+ @SerializedName("dismissed_reason")
+ String dismissedReason;
+ @SerializedName("dismissed_comment")
+ String dismissedComment;
+ @SerializedName("most_recent_instance")
+ GithubCodeScanningAlertInstance mostRecentInstance;
+
+ public GsonGithubCodeScanningAlert() {
+ // even if empty constructor is not required for Gson, it is strongly
+ // recommended:
+ // http://stackoverflow.com/a/18645370/229031
+ }
+
+ public long getId() {
+ return id;
+ }
+
+ public GithubCodeScanningAlertState getState() {
+ return state;
+ }
+
+ public String getDismissedReason() {
+ return dismissedReason;
+ }
+
+ public String getDismissedComment() {
+ return dismissedComment;
+ }
+
+ public GithubCodeScanningAlertInstance getInstance() {
+ return mostRecentInstance;
+ }
+
+ public String getMessageText() {
+ return getInstance().getMessageText();
+ }
+ }
+
+ public static class GithubCodeScanningAlertInstance {
+ @SerializedName("state")
+ GithubCodeScanningAlertState state;
+ @SerializedName("message")
+ Message message;
+
+ public GithubCodeScanningAlertInstance() {
+ // even if empty constructor is not required for Gson, it is strongly
+ // recommended:
+ // http://stackoverflow.com/a/18645370/229031
+ }
+
+ public Message getMessage() {
+ return message;
+ }
+
+ public String getMessageText() {
+ return getMessage().getText();
+ }
+ }
+
+ public enum GithubCodeScanningAlertState {
+ @SerializedName("open")
+ OPEN,
+ @SerializedName("fixed")
+ FIXED,
+ @SerializedName("dismissed")
+ DISMISSED;
+ }
+
+ public static class Message {
+ @SerializedName("text")
+ String text;
+
+ public Message() {
+ // even if empty constructor is not required for Gson, it is strongly
+ // recommended:
+ // http://stackoverflow.com/a/18645370/229031
+ }
+
+ public String getText() {
+ return text;
+ }
+ }
}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2022 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.alm.client.github.scanning.alert;
+
+import com.google.gson.annotations.SerializedName;
+import javax.annotation.Nullable;
+
+public class GithubScanningAlertState {
+ protected static final String GH_OPEN = "open";
+ protected static final String GH_DISMISSED = "dismissed";
+ protected static final String GH_WONTFIX = "won't fix";
+ protected static final String GH_FALSE_POSITIVE = "false positive";
+
+ @SerializedName("state")
+ private String state;
+ @SerializedName("dismissed_reason")
+ private String dismissedReason;
+
+ public GithubScanningAlertState(String state, @Nullable String dismissedReason) {
+ this.state = state;
+ this.dismissedReason = dismissedReason;
+ }
+}
import org.sonar.api.rules.RuleType;
import org.sonar.api.server.ServerSide;
+import static org.sonar.api.rules.RuleType.VULNERABILITY;
+
@ServerSide
public interface QGChangeEventListener {
/**
default boolean isNotClosed() {
return !Status.CLOSED_STATUSES.contains(getStatus());
}
+
+ default boolean isVulnerability() {
+ return getType() == VULNERABILITY;
+ }
}
enum Status {
@Rule
public LogTester logTester = new LogTester();
- private QGChangeEventListener listener1 = mock(QGChangeEventListener.class);
- private QGChangeEventListener listener2 = mock(QGChangeEventListener.class);
- private QGChangeEventListener listener3 = mock(QGChangeEventListener.class);
- private List<QGChangeEventListener> listeners = Arrays.asList(listener1, listener2, listener3);
+ private final QGChangeEventListener listener1 = mock(QGChangeEventListener.class);
+ private final QGChangeEventListener listener2 = mock(QGChangeEventListener.class);
+ private final QGChangeEventListener listener3 = mock(QGChangeEventListener.class);
+ private final List<QGChangeEventListener> listeners = Arrays.asList(listener1, listener2, listener3);
- private String project1Uuid = RandomStringUtils.randomAlphabetic(6);
- private BranchDto project1 = newBranchDto(project1Uuid);
- private DefaultIssue component1Issue = newDefaultIssue(project1Uuid);
- private List<DefaultIssue> oneIssueOnComponent1 = singletonList(component1Issue);
- private QGChangeEvent component1QGChangeEvent = newQGChangeEvent(project1);
+ private final String project1Uuid = RandomStringUtils.randomAlphabetic(6);
+ private final BranchDto project1 = newBranchDto(project1Uuid);
+ private final DefaultIssue component1Issue = newDefaultIssue(project1Uuid);
+ private final List<DefaultIssue> oneIssueOnComponent1 = singletonList(component1Issue);
+ private final QGChangeEvent component1QGChangeEvent = newQGChangeEvent(project1);
- private InOrder inOrder = Mockito.inOrder(listener1, listener2, listener3);
+ private final InOrder inOrder = Mockito.inOrder(listener1, listener2, listener3);
- private QGChangeEventListenersImpl underTest = new QGChangeEventListenersImpl(new QGChangeEventListener[] {listener1, listener2, listener3});
+ private final QGChangeEventListenersImpl underTest = new QGChangeEventListenersImpl(new QGChangeEventListener[] {listener1, listener2, listener3});
@Test
public void broadcastOnIssueChange_has_no_effect_when_issues_are_empty() {
List<String> traceLogs = logTester.logs(LoggerLevel.TRACE);
assertThat(traceLogs).hasSize(3)
.containsOnly(
- "calling onChange() on listener " + listener1.getClass().getName() + " for events " + component1QGChangeEvent.toString() + "...",
- "calling onChange() on listener " + listener2.getClass().getName() + " for events " + component1QGChangeEvent.toString() + "...",
- "calling onChange() on listener " + listener3.getClass().getName() + " for events " + component1QGChangeEvent.toString() + "...");
+ "calling onChange() on listener " + listener1.getClass().getName() + " for events " + component1QGChangeEvent + "...",
+ "calling onChange() on listener " + listener2.getClass().getName() + " for events " + component1QGChangeEvent + "...",
+ "calling onChange() on listener " + listener3.getClass().getName() + " for events " + component1QGChangeEvent + "...");
}
@Test
assertThat(changedIssue.isNotClosed()).isFalse();
}
+ @Test
+ public void isVulnerability_returns_true_if_issue_is_of_type_vulnerability() {
+ DefaultIssue defaultIssue = new DefaultIssue();
+ defaultIssue.setStatus(Issue.STATUS_OPEN);
+ defaultIssue.setType(RuleType.VULNERABILITY);
+
+ ChangedIssue changedIssue = new ChangedIssueImpl(defaultIssue);
+
+ assertThat(changedIssue.isVulnerability()).isTrue();
+ }
+
+ @Test
+ public void isVulnerability_returns_false_if_issue_is_not_of_type_vulnerability() {
+ DefaultIssue defaultIssue = new DefaultIssue();
+ defaultIssue.setStatus(Issue.STATUS_OPEN);
+ defaultIssue.setType(RuleType.BUG);
+
+ ChangedIssue changedIssue = new ChangedIssueImpl(defaultIssue);
+
+ assertThat(changedIssue.isVulnerability()).isFalse();
+ }
+
@Test
public void test_status_mapping() {
assertThat(ChangedIssueImpl.statusOf(new DefaultIssue().setStatus(Issue.STATUS_OPEN))).isEqualTo(QGChangeEventListener.Status.OPEN);