diff options
Diffstat (limited to 'server/sonar-ce-task-projectanalysis')
4 files changed, 88 insertions, 48 deletions
diff --git a/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/pushevent/PushEventFactory.java b/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/pushevent/PushEventFactory.java index 18a8a17b8fb..30b12214562 100644 --- a/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/pushevent/PushEventFactory.java +++ b/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/pushevent/PushEventFactory.java @@ -57,7 +57,7 @@ public class PushEventFactory { this.flowGenerator = flowGenerator; } - public Optional<PushEventDto> raiseEventOnIssue(DefaultIssue currentIssue) { + public Optional<PushEventDto> raiseEventOnIssue(String projectUuid, DefaultIssue currentIssue) { var currentIssueComponentUuid = currentIssue.componentUuid(); if (!taintChecker.isTaintVulnerability(currentIssue) || currentIssueComponentUuid == null) { return Optional.empty(); @@ -65,10 +65,10 @@ public class PushEventFactory { var component = treeRootHolder.getComponentByUuid(Objects.requireNonNull(currentIssue.componentUuid())); if (currentIssue.isNew() || currentIssue.isCopied() || isReopened(currentIssue)) { - return Optional.of(raiseTaintVulnerabilityRaisedEvent(component, currentIssue)); + return Optional.of(raiseTaintVulnerabilityRaisedEvent(projectUuid, component, currentIssue)); } if (currentIssue.isBeingClosed()) { - return Optional.of(raiseTaintVulnerabilityClosedEvent(currentIssue)); + return Optional.of(raiseTaintVulnerabilityClosedEvent(projectUuid, currentIssue)); } return Optional.empty(); } @@ -82,11 +82,12 @@ public class PushEventFactory { return status != null && status.toString().equals("CLOSED|OPEN"); } - private PushEventDto raiseTaintVulnerabilityRaisedEvent(Component component, DefaultIssue issue) { + private PushEventDto raiseTaintVulnerabilityRaisedEvent(String projectUuid, Component component, DefaultIssue issue) { TaintVulnerabilityRaised event = prepareEvent(component, issue); return new PushEventDto() .setName("TaintVulnerabilityRaised") - .setProjectUuid(treeRootHolder.getRoot().getUuid()) + .setProjectUuid(projectUuid) + .setLanguage(issue.language()) .setPayload(serializeEvent(event)); } @@ -116,11 +117,12 @@ public class PushEventFactory { return event; } - private PushEventDto raiseTaintVulnerabilityClosedEvent(DefaultIssue issue) { + private static PushEventDto raiseTaintVulnerabilityClosedEvent(String projectUuid, DefaultIssue issue) { TaintVulnerabilityClosed event = new TaintVulnerabilityClosed(issue.key(), issue.projectKey()); return new PushEventDto() .setName("TaintVulnerabilityClosed") - .setProjectUuid(treeRootHolder.getRoot().getUuid()) + .setProjectUuid(projectUuid) + .setLanguage(issue.language()) .setPayload(serializeEvent(event)); } diff --git a/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/step/PersistPushEventsStep.java b/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/step/PersistPushEventsStep.java index 8c302b0f4b2..722af961aef 100644 --- a/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/step/PersistPushEventsStep.java +++ b/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/step/PersistPushEventsStep.java @@ -22,6 +22,7 @@ package org.sonar.ce.task.projectanalysis.step; import java.util.Optional; import org.sonar.api.utils.log.Logger; import org.sonar.api.utils.log.Loggers; +import org.sonar.ce.task.projectanalysis.component.TreeRootHolder; import org.sonar.ce.task.projectanalysis.issue.ProtoIssueCache; import org.sonar.ce.task.projectanalysis.pushevent.PushEventFactory; import org.sonar.ce.task.step.ComputationStep; @@ -38,13 +39,16 @@ public class PersistPushEventsStep implements ComputationStep { private final DbClient dbClient; private final ProtoIssueCache protoIssueCache; private final PushEventFactory pushEventFactory; + private final TreeRootHolder treeRootHolder; public PersistPushEventsStep(DbClient dbClient, ProtoIssueCache protoIssueCache, - PushEventFactory pushEventFactory) { + PushEventFactory pushEventFactory, + TreeRootHolder treeRootHolder) { this.dbClient = dbClient; this.protoIssueCache = protoIssueCache; this.pushEventFactory = pushEventFactory; + this.treeRootHolder = treeRootHolder; } @Override @@ -52,10 +56,11 @@ public class PersistPushEventsStep implements ComputationStep { try (DbSession dbSession = dbClient.openSession(true); CloseableIterator<DefaultIssue> issues = protoIssueCache.traverse()) { int batchCounter = 0; + var projectUuid = getProjectUuid(dbSession); while (issues.hasNext()) { DefaultIssue currentIssue = issues.next(); - Optional<PushEventDto> raisedEvent = pushEventFactory.raiseEventOnIssue(currentIssue); + Optional<PushEventDto> raisedEvent = pushEventFactory.raiseEventOnIssue(projectUuid, currentIssue); if (raisedEvent.isEmpty()) { continue; @@ -72,6 +77,14 @@ public class PersistPushEventsStep implements ComputationStep { } } + private String getProjectUuid(DbSession dbSession) { + var branch = dbClient.branchDao().selectByUuid(dbSession, treeRootHolder.getRoot().getUuid()); + if (branch.isEmpty()) { + return treeRootHolder.getRoot().getUuid(); + } + return branch.get().getProjectUuid(); + } + private static int flushIfNeeded(DbSession dbSession, int batchCounter) { if (batchCounter > MAX_BATCH_SIZE) { flushSession(dbSession); diff --git a/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/pushevent/PushEventFactoryTest.java b/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/pushevent/PushEventFactoryTest.java index 65548362402..1b4a04e3d5d 100644 --- a/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/pushevent/PushEventFactoryTest.java +++ b/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/pushevent/PushEventFactoryTest.java @@ -24,7 +24,6 @@ import java.util.List; import org.junit.Before; import org.junit.Rule; import org.junit.Test; -import org.mockito.ArgumentMatcher; import org.sonar.api.rule.RuleKey; import org.sonar.api.rules.RuleType; import org.sonar.api.utils.DateUtils; @@ -38,7 +37,6 @@ import org.sonar.core.issue.DefaultIssue; import org.sonar.core.issue.FieldDiffs; import org.sonar.db.protobuf.DbCommons; import org.sonar.db.protobuf.DbIssues; -import org.sonar.db.pushevent.PushEventDto; import org.sonar.server.issue.TaintChecker; import static org.assertj.core.api.Assertions.assertThat; @@ -71,11 +69,13 @@ public class PushEventFactoryTest { DefaultIssue defaultIssue = createDefaultIssue() .setNew(true); - assertThat(underTest.raiseEventOnIssue(defaultIssue)) + assertThat(underTest.raiseEventOnIssue("some-project-uuid", defaultIssue)) .isNotEmpty() .hasValueSatisfying(pushEventDto -> { assertThat(pushEventDto.getName()).isEqualTo("TaintVulnerabilityRaised"); assertThat(pushEventDto.getPayload()).isNotNull(); + assertThat(pushEventDto.getLanguage()).isEqualTo("java"); + assertThat(pushEventDto.getProjectUuid()).isEqualTo("some-project-uuid"); }); } @@ -88,7 +88,7 @@ public class PushEventFactoryTest { .setCopied(false) .setCurrentChange(new FieldDiffs().setDiff("status", "CLOSED", "OPEN")); - assertThat(underTest.raiseEventOnIssue(defaultIssue)) + assertThat(underTest.raiseEventOnIssue("some-project-uuid", defaultIssue)) .isNotEmpty() .hasValueSatisfying(pushEventDto -> { assertThat(pushEventDto.getName()).isEqualTo("TaintVulnerabilityRaised"); @@ -99,12 +99,12 @@ public class PushEventFactoryTest { @Test public void skip_event_if_taint_vulnerability_status_change() { DefaultIssue defaultIssue = createDefaultIssue() - .setChanged(true) - .setNew(false) - .setCopied(false) - .setCurrentChange(new FieldDiffs().setDiff("status", "OPEN", "FIXED")); + .setChanged(true) + .setNew(false) + .setCopied(false) + .setCurrentChange(new FieldDiffs().setDiff("status", "OPEN", "FIXED")); - assertThat(underTest.raiseEventOnIssue(defaultIssue)).isEmpty(); + assertThat(underTest.raiseEventOnIssue("some-project-uuid", defaultIssue)).isEmpty(); } @Test @@ -112,7 +112,7 @@ public class PushEventFactoryTest { DefaultIssue defaultIssue = createDefaultIssue() .setCopied(true); - assertThat(underTest.raiseEventOnIssue(defaultIssue)) + assertThat(underTest.raiseEventOnIssue("some-project-uuid", defaultIssue)) .isNotEmpty() .hasValueSatisfying(pushEventDto -> { assertThat(pushEventDto.getName()).isEqualTo("TaintVulnerabilityRaised"); @@ -128,7 +128,7 @@ public class PushEventFactoryTest { .setCopied(false) .setBeingClosed(true); - assertThat(underTest.raiseEventOnIssue(defaultIssue)) + assertThat(underTest.raiseEventOnIssue("some-project-uuid", defaultIssue)) .isNotEmpty() .hasValueSatisfying(pushEventDto -> { assertThat(pushEventDto.getName()).isEqualTo("TaintVulnerabilityClosed"); @@ -147,7 +147,7 @@ public class PushEventFactoryTest { .setCreationDate(DateUtils.parseDate("2022-01-01")) .setRuleKey(RuleKey.of("javasecurity", "S123")); - assertThat(underTest.raiseEventOnIssue(defaultIssue)).isEmpty(); + assertThat(underTest.raiseEventOnIssue("some-project-uuid", defaultIssue)).isEmpty(); } @Test @@ -160,7 +160,7 @@ public class PushEventFactoryTest { when(taintChecker.isTaintVulnerability(any())).thenReturn(false); - assertThat(underTest.raiseEventOnIssue(defaultIssue)).isEmpty(); + assertThat(underTest.raiseEventOnIssue("some-project-uuid", defaultIssue)).isEmpty(); defaultIssue = new DefaultIssue() .setComponentUuid("issue-component-uuid") @@ -170,7 +170,7 @@ public class PushEventFactoryTest { .setType(RuleType.VULNERABILITY) .setRuleKey(RuleKey.of("weirdrepo", "S123")); - assertThat(underTest.raiseEventOnIssue(defaultIssue)).isEmpty(); + assertThat(underTest.raiseEventOnIssue("some-project-uuid", defaultIssue)).isEmpty(); } @Test @@ -183,7 +183,7 @@ public class PushEventFactoryTest { when(taintChecker.isTaintVulnerability(any())).thenReturn(false); - assertThat(underTest.raiseEventOnIssue(defaultIssue)).isEmpty(); + assertThat(underTest.raiseEventOnIssue("some-project-uuid", defaultIssue)).isEmpty(); } @Test @@ -196,7 +196,7 @@ public class PushEventFactoryTest { when(taintChecker.isTaintVulnerability(any())).thenReturn(false); - assertThat(underTest.raiseEventOnIssue(defaultIssue)).isEmpty(); + assertThat(underTest.raiseEventOnIssue("some-project-uuid", defaultIssue)).isEmpty(); } private void buildComponentTree() { @@ -215,6 +215,7 @@ public class PushEventFactoryTest { return new DefaultIssue() .setComponentUuid("issue-component-uuid") .setType(RuleType.VULNERABILITY) + .setLanguage("java") .setCreationDate(new Date()) .setLocations(DbIssues.Locations.newBuilder() .addFlow(DbIssues.Flow.newBuilder() @@ -230,22 +231,4 @@ public class PushEventFactoryTest { .setRuleKey(RuleKey.of("javasecurity", "S123")); } - private static class PushEventMatcher implements ArgumentMatcher<PushEventDto> { - - private final PushEventDto left; - - static PushEventMatcher eq(PushEventDto left) { - return new PushEventMatcher(left); - } - - private PushEventMatcher(PushEventDto left) { - this.left = left; - } - - @Override - public boolean matches(PushEventDto right) { - return left.getName().equals(right.getName()); - } - } - } diff --git a/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/step/PersistPushEventsStepTest.java b/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/step/PersistPushEventsStepTest.java index ab54b01d72d..c2495c8cb67 100644 --- a/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/step/PersistPushEventsStepTest.java +++ b/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/step/PersistPushEventsStepTest.java @@ -31,6 +31,9 @@ import org.sonar.api.impl.utils.TestSystem2; import org.sonar.api.rule.RuleKey; import org.sonar.api.rules.RuleType; import org.sonar.api.utils.System2; +import org.sonar.ce.task.projectanalysis.component.Component; +import org.sonar.ce.task.projectanalysis.component.MutableTreeRootHolderRule; +import org.sonar.ce.task.projectanalysis.component.ReportComponent; import org.sonar.ce.task.projectanalysis.issue.ProtoIssueCache; import org.sonar.ce.task.projectanalysis.pushevent.PushEventFactory; import org.sonar.ce.task.step.ComputationStep; @@ -42,6 +45,8 @@ import static java.nio.charset.StandardCharsets.UTF_8; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatCode; import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; @@ -55,14 +60,16 @@ public class PersistPushEventsStepTest { public final PushEventFactory pushEventFactory = mock(PushEventFactory.class); @Rule public TemporaryFolder temp = new TemporaryFolder(); - + @Rule + public MutableTreeRootHolderRule treeRootHolder = new MutableTreeRootHolderRule(); private ProtoIssueCache protoIssueCache; private PersistPushEventsStep underTest; @Before public void before() throws IOException { protoIssueCache = new ProtoIssueCache(temp.newFile(), System2.INSTANCE); - underTest = new PersistPushEventsStep(db.getDbClient(), protoIssueCache, pushEventFactory); + buildComponentTree(); + underTest = new PersistPushEventsStep(db.getDbClient(), protoIssueCache, pushEventFactory, treeRootHolder); } @Test @@ -83,7 +90,7 @@ public class PersistPushEventsStepTest { createIssue("key1").setType(RuleType.VULNERABILITY)) .close(); - when(pushEventFactory.raiseEventOnIssue(any())).thenThrow(new RuntimeException("I have a bad feelings about this")); + when(pushEventFactory.raiseEventOnIssue(any(), any())).thenThrow(new RuntimeException("I have a bad feelings about this")); assertThatCode(() -> underTest.execute(mock(ComputationStep.Context.class))) .doesNotThrowAnyException(); @@ -125,7 +132,30 @@ public class PersistPushEventsStepTest { .setComponentKey("ck2")) .close(); - when(pushEventFactory.raiseEventOnIssue(any(DefaultIssue.class))).thenReturn( + when(pushEventFactory.raiseEventOnIssue(eq("uuid_1"), any(DefaultIssue.class))).thenReturn( + Optional.of(createPushEvent()), + Optional.of(createPushEvent())); + + underTest.execute(mock(ComputationStep.Context.class)); + + assertThat(db.countSql(db.getSession(), "SELECT count(uuid) FROM push_events")).isEqualTo(2); + } + + @Test + public void store_push_events_for_branch() { + var project = db.components().insertPrivateProject(); + db.components().insertProjectBranch(project, b -> b.setUuid("uuid_1")); + + protoIssueCache.newAppender() + .append(createIssue("key1").setType(RuleType.VULNERABILITY) + .setComponentUuid("cu1") + .setComponentKey("ck1")) + .append(createIssue("key2").setType(RuleType.VULNERABILITY) + .setComponentUuid("cu2") + .setComponentKey("ck2")) + .close(); + + when(pushEventFactory.raiseEventOnIssue(eq(project.uuid()), any(DefaultIssue.class))).thenReturn( Optional.of(createPushEvent()), Optional.of(createPushEvent())); @@ -144,7 +174,7 @@ public class PersistPushEventsStepTest { .setComponentUuid("cu" + value) .setComponentKey("ck" + value); appender.append(defaultIssue); - when(pushEventFactory.raiseEventOnIssue(defaultIssue)).thenReturn(Optional.of(createPushEvent())); + when(pushEventFactory.raiseEventOnIssue(anyString(), eq(defaultIssue))).thenReturn(Optional.of(createPushEvent())); }); appender.close(); @@ -169,4 +199,16 @@ public class PersistPushEventsStepTest { return new PushEventDto().setProjectUuid("project-uuid").setName("event").setPayload("test".getBytes(UTF_8)); } + private void buildComponentTree() { + treeRootHolder.setRoot(ReportComponent.builder(Component.Type.PROJECT, 1) + .setUuid("uuid_1") + .addChildren(ReportComponent.builder(Component.Type.FILE, 2) + .setUuid("issue-component-uuid") + .build()) + .addChildren(ReportComponent.builder(Component.Type.FILE, 3) + .setUuid("location-component-uuid") + .build()) + .build()); + } + } |