import org.sonar.ce.task.projectanalysis.event.EventRepository;
import org.sonar.ce.task.step.ComputationStep;
import org.sonar.ce.task.step.TestComputationStepContext;
+import org.sonar.core.platform.SonarQubeVersion;
import org.sonar.core.util.UuidFactory;
import org.sonar.core.util.UuidFactoryImpl;
import org.sonar.db.DbTester;
import static org.sonar.db.event.EventDto.CATEGORY_ALERT;
import static org.sonar.db.event.EventDto.CATEGORY_ISSUE_DETECTION;
import static org.sonar.db.event.EventDto.CATEGORY_PROFILE;
+import static org.sonar.db.event.EventDto.CATEGORY_SQ_UPGRADE;
import static org.sonar.db.event.EventDto.CATEGORY_VERSION;
public class PersistEventsStepIT extends BaseStepTest {
private final EventRepository eventRepository = mock(EventRepository.class);
private final UuidFactory uuidFactory = UuidFactoryImpl.INSTANCE;
+ private final SonarQubeVersion sonarQubeVersion = mock();
+
private PersistEventsStep underTest;
@Before
assertThat(eventDto.getCreatedAt()).isEqualTo(NOW);
}
+ @Test
+ public void execute_whenSqUpgradeEventRaised_shouldPersist() {
+ when(system2.now()).thenReturn(NOW);
+ treeRootHolder.setRoot(ROOT);
+ Event sqUpgradeEvent = Event.createSqUpgrade("10.3");
+ when(eventRepository.getEvents()).thenReturn(List.of(sqUpgradeEvent));
+
+ underTest.execute(new TestComputationStepContext());
+
+ assertThat(dbTester.countRowsOfTable(dbTester.getSession(), "events")).isEqualTo(2);
+ List<EventDto> eventDtos = dbTester.getDbClient().eventDao().selectByComponentUuid(dbTester.getSession(), ROOT.getUuid());
+ assertThat(eventDtos)
+ .extracting(EventDto::getCategory)
+ .containsOnly(CATEGORY_SQ_UPGRADE, CATEGORY_VERSION);
+ EventDto eventDto = eventDtos.stream()
+ .filter(t -> CATEGORY_SQ_UPGRADE.equals(t.getCategory()))
+ .findAny()
+ .orElseGet(() -> fail("Issue detection event not found"));
+ assertThat(eventDto.getComponentUuid()).isEqualTo(ROOT.getUuid());
+ assertThat(eventDto.getName()).isEqualTo(sqUpgradeEvent.getName());
+ assertThat(eventDto.getCategory()).isEqualTo(CATEGORY_SQ_UPGRADE);
+ assertThat(eventDto.getDescription()).isNull();
+ assertThat(eventDto.getData()).isNull();
+ assertThat(eventDto.getDate()).isEqualTo(analysisMetadataHolder.getAnalysisDate());
+ assertThat(eventDto.getCreatedAt()).isEqualTo(NOW);
+ }
+
@Test
public void keep_one_event_by_version() {
ComponentDto projectDto = dbTester.components().insertPublicProject().getMainBranchComponent();
return new Event(name, Category.ISSUE_DETECTION);
}
+ public static Event createSqUpgrade(String name) {
+ return new Event(name, Category.SQ_UPGRADE);
+ }
+
public String getName() {
return name;
}
}
public enum Category {
- ALERT, PROFILE, ISSUE_DETECTION
+ ALERT, PROFILE, ISSUE_DETECTION, SQ_UPGRADE
}
}
case ALERT -> EventDto.CATEGORY_ALERT;
case PROFILE -> EventDto.CATEGORY_PROFILE;
case ISSUE_DETECTION -> EventDto.CATEGORY_ISSUE_DETECTION;
+ case SQ_UPGRADE -> EventDto.CATEGORY_SQ_UPGRADE;
};
}
// Pre analysis operations
PreMeasuresComputationChecksStep.class,
+ SqUpgradeDetectionEventsStep.class,
// load project related stuffs
LoadFileHashesAndStatusStep.class,
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2023 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.ce.task.projectanalysis.step;
+
+import java.util.List;
+import org.sonar.ce.task.projectanalysis.component.Component;
+import org.sonar.ce.task.projectanalysis.component.TreeRootHolder;
+import org.sonar.ce.task.projectanalysis.event.Event;
+import org.sonar.ce.task.projectanalysis.event.EventRepository;
+import org.sonar.ce.task.step.ComputationStep;
+import org.sonar.core.platform.SonarQubeVersion;
+import org.sonar.db.DbClient;
+import org.sonar.db.DbSession;
+import org.sonar.db.event.EventDto;
+
+/**
+ * Computation of SQ Upgrade events
+ */
+public class SqUpgradeDetectionEventsStep implements ComputationStep {
+ private final TreeRootHolder treeRootHolder;
+ private final DbClient dbClient;
+ private final EventRepository eventRepository;
+ private final SonarQubeVersion sonarQubeVersion;
+
+ public SqUpgradeDetectionEventsStep(TreeRootHolder treeRootHolder, DbClient dbClient,
+ EventRepository eventRepository, SonarQubeVersion sonarQubeVersion) {
+ this.treeRootHolder = treeRootHolder;
+ this.dbClient = dbClient;
+ this.eventRepository = eventRepository;
+ this.sonarQubeVersion = sonarQubeVersion;
+ }
+
+ @Override
+ public void execute(Context context) {
+ executeForBranch(treeRootHolder.getRoot());
+ }
+
+ private void executeForBranch(Component branchComponent) {
+ String currentSqVersion = sonarQubeVersion.get().toString();
+ try (DbSession dbSession = dbClient.openSession(false)) {
+ List<EventDto> sqUpgradeEvents = dbClient.eventDao().selectSqUpgradesByMostRecentFirst(dbSession, branchComponent.getUuid());
+
+ //We don't really care about newer versions, we want to log the events related to a version change.
+ boolean isFirstAnalysisForSqVersion = sqUpgradeEvents.isEmpty() || !currentSqVersion.equals(sqUpgradeEvents.get(0).getName());
+
+ if (isFirstAnalysisForSqVersion) {
+ Event event = Event.createSqUpgrade(currentSqVersion);
+ eventRepository.add(event);
+ }
+ }
+ }
+
+ @Override
+ public String getDescription() {
+ return "Generate SQ Upgrade analysis events";
+ }
+}
.isEqualTo(source)
.isNotNull();
}
+
+ @Test
+ public void createSqUpgradeEvents_verify_fields() {
+ Event event = Event.createSqUpgrade(SOME_NAME);
+ assertThat(event.getName()).isEqualTo(SOME_NAME);
+ assertThat(event.getCategory()).isEqualTo(Event.Category.SQ_UPGRADE);
+ assertThat(event.getData()).isNull();
+ assertThat(event.getDescription()).isNull();
+ }
}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2023 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.ce.task.projectanalysis.step;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.mockito.ArgumentCaptor;
+import org.sonar.api.utils.Version;
+import org.sonar.ce.task.projectanalysis.component.Component;
+import org.sonar.ce.task.projectanalysis.component.ReportComponent;
+import org.sonar.ce.task.projectanalysis.component.TreeRootHolderRule;
+import org.sonar.ce.task.projectanalysis.event.Event;
+import org.sonar.ce.task.projectanalysis.event.EventRepository;
+import org.sonar.ce.task.step.TestComputationStepContext;
+import org.sonar.core.platform.SonarQubeVersion;
+import org.sonar.db.DbClient;
+import org.sonar.db.event.EventDto;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.groups.Tuple.tuple;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyNoMoreInteractions;
+import static org.mockito.Mockito.when;
+
+public class SqUpgradeDetectionEventsStepTest {
+
+ @Rule
+ public TreeRootHolderRule treeRootHolder = new TreeRootHolderRule();
+
+ private final DbClient dbClient = mock();
+ private final EventRepository eventRepository = mock();
+
+ private final ArgumentCaptor<Event> eventArgumentCaptor = ArgumentCaptor.forClass(Event.class);
+
+ private final SonarQubeVersion sonarQubeVersion = mock();
+
+ private final SqUpgradeDetectionEventsStep underTest = new SqUpgradeDetectionEventsStep(treeRootHolder, dbClient, eventRepository, sonarQubeVersion);
+
+ @Before
+ public void setUp() {
+ treeRootHolder.setRoot(ReportComponent.builder(Component.Type.PROJECT, 1).setUuid("uuid").setKey("key").build());
+ }
+
+ @Test
+ public void givenNoPreviousUpgradeEvents_whenStepIsExecuted_thenANewUpgradeEventIsCreated() {
+ when(sonarQubeVersion.get()).thenReturn(Version.parse("10.3"));
+ when(dbClient.eventDao()).thenReturn(mock());
+ when(dbClient.eventDao().selectSqUpgradesByMostRecentFirst(any(), any())).thenReturn(Collections.emptyList());
+
+ underTest.execute(new TestComputationStepContext());
+
+ verify(eventRepository, times(1)).add(eventArgumentCaptor.capture());
+ verifyNoMoreInteractions(eventRepository);
+
+ assertThat(eventArgumentCaptor.getAllValues())
+ .extracting(Event::getCategory, Event::getName)
+ .containsExactly(tuple(Event.Category.SQ_UPGRADE, "10.3"));
+ }
+
+ @Test
+ public void givenUpgradeEventWithTheSameSqVersion_whenStepIsExecuted_thenNothingIsPersisted() {
+ when(sonarQubeVersion.get()).thenReturn(Version.parse("10.3"));
+ when(dbClient.eventDao()).thenReturn(mock());
+ when(dbClient.eventDao().selectSqUpgradesByMostRecentFirst(any(), any())).thenReturn(getUpgradeEvents("10.3", "10.2"));
+
+ underTest.execute(new TestComputationStepContext());
+
+ verifyNoMoreInteractions(eventRepository);
+ }
+
+ private List<EventDto> getUpgradeEvents(String... versions) {
+ return Arrays.stream(versions)
+ .map(version -> new EventDto().setCategory(EventDto.CATEGORY_SQ_UPGRADE).setName(version))
+ .toList();
+ }
+
+ @Test
+ public void givenUpgradeEventWithDifferentSqVersion_whenStepIsExecuted_thenANewUpgradeEventIsCreated() {
+ when(sonarQubeVersion.get()).thenReturn(Version.parse("10.3"));
+ when(dbClient.eventDao()).thenReturn(mock());
+ when(dbClient.eventDao().selectSqUpgradesByMostRecentFirst(any(), any())).thenReturn(getUpgradeEvents("10.2", "10.1"));
+
+ underTest.execute(new TestComputationStepContext());
+
+ verify(eventRepository, times(1)).add(eventArgumentCaptor.capture());
+ verifyNoMoreInteractions(eventRepository);
+
+ assertThat(eventArgumentCaptor.getAllValues())
+ .extracting(Event::getCategory, Event::getName)
+ .containsExactly(tuple(Event.Category.SQ_UPGRADE, "10.3"));
+ }
+
+ @Test
+ public void whenGetDescriptionIsCalled_shouldReturnExpectedValue() {
+ assertThat(underTest.getDescription()).isEqualTo("Generate SQ Upgrade analysis events");
+ }
+
+}
assertThat(result.getDescription()).isEqualTo("New Description");
}
+ @Test
+ public void givenSomeSqUpgradeEvents_whenRetrieved_shouldReturnCorrectlyOrderedByDateDescending() {
+ long olderDate = 1L;
+ long newerDate = 2L;
+
+ ComponentDto componentDto = ComponentTesting.newPrivateProjectDto();
+ SnapshotDto analysis = dbTester.components().insertProjectAndSnapshot(componentDto);
+ dbTester.events().insertEvent(newEvent(analysis).setCategory(EventDto.CATEGORY_SQ_UPGRADE).setDate(olderDate).setUuid("E1"));
+ dbTester.events().insertEvent(newEvent(analysis).setCategory(EventDto.CATEGORY_SQ_UPGRADE).setDate(newerDate).setUuid("E2"));
+
+ List<EventDto> events = underTest.selectSqUpgradesByMostRecentFirst(dbSession, componentDto.uuid());
+ assertThat(events).hasSize(2);
+ assertThat(events.get(0).getUuid()).isEqualTo("E2");
+ assertThat(events.get(0).getDate()).isEqualTo(newerDate);
+ assertThat(events.get(1).getUuid()).isEqualTo("E1");
+ assertThat(events.get(1).getDate()).isEqualTo(olderDate);
+ }
+
@Test
public void delete_by_uuid() {
dbTester.events().insertEvent(newEvent(newAnalysis(ComponentTesting.newPrivateProjectDto())).setUuid("E1"));
return mapper(session).selectVersions(componentUuid);
}
+ public List<EventDto> selectSqUpgradesByMostRecentFirst(DbSession session, String componentUuid) {
+ return mapper(session).selectSqUpgrades(componentUuid);
+ }
+
public EventDto insert(DbSession session, EventDto dto) {
mapper(session).insert(dto);
public static final String CATEGORY_PROFILE = "Profile";
public static final String CATEGORY_DEFINITION_CHANGE = "Definition change";
public static final String CATEGORY_ISSUE_DETECTION = "Issue Detection";
+ public static final String CATEGORY_SQ_UPGRADE = "SQ Upgrade";
private String uuid;
private String analysisUuid;
private String componentUuid;
List<EventDto> selectVersions(@Param("componentUuid") String componentUuid);
+ List<EventDto> selectSqUpgrades(@Param("componentUuid") String componentUuid);
+
void insert(EventDto dto);
void update(@Param("uuid") String uuid, @Param("name") @Nullable String name, @Param("description") @Nullable String description);
e.event_date desc
</select>
+ <select id="selectSqUpgrades" resultType="Event" parameterType="map">
+ select
+ <include refid="eventColumns"/>
+ from events e
+ inner join snapshots s on
+ s.uuid = e.analysis_uuid
+ and s.status = 'P'
+ and s.root_component_uuid = #{componentUuid,jdbcType=VARCHAR}
+ where
+ e.category = 'SQ Upgrade'
+ order by
+ e.event_date desc
+ </select>
+
<insert id="insert" parameterType="Event">
INSERT INTO events (uuid, analysis_uuid, component_uuid, name, category, description, event_data, event_date, created_at)
VALUES (
QUALITY_PROFILE("Profile"),
QUALITY_GATE("Alert"),
DEFINITION_CHANGE("Definition change"),
- ISSUE_DETECTION("Issue Detection");
+ ISSUE_DETECTION("Issue Detection"),
+ SQ_UPGRADE("SQ Upgrade");
private final String label;