import static org.sonar.api.issue.Issue.STATUSES;
import static org.sonar.api.issue.Issue.STATUS_REVIEWED;
import static org.sonar.api.issue.Issue.STATUS_TO_REVIEW;
+import static org.sonar.api.measures.CoreMetrics.ANALYSIS_FROM_SONARQUBE_9_4_KEY;
import static org.sonar.api.utils.DateUtils.longToDate;
import static org.sonar.api.utils.DateUtils.parseEndingDateOrDateTime;
import static org.sonar.api.utils.DateUtils.parseStartingDateOrDateTime;
if (!QUALIFIERS_WITHOUT_LEAK_PERIOD.contains(component.qualifier()) && request.getPullRequest() == null) {
Optional<SnapshotDto> snapshot = getLastAnalysis(dbSession, component);
- boolean isLastAnalysisUsingReferenceBranch = isLastAnalysisUsingReferenceBranch(snapshot);
- if (isLastAnalysisUsingReferenceBranch) {
- builder.newCodeOnReference(true);
- } else {
- // if last analysis has no period date, then no issue should be considered new.
- Date createdAfterFromSnapshot = findCreatedAfterFromComponentUuid(snapshot);
- setCreatedAfterFromDates(builder, createdAfterFromSnapshot, null, false);
+ if (!snapshot.isEmpty() && isLastAnalysisFromReAnalyzedReferenceBranch(dbSession, snapshot.get())) {
+ builder.newCodeOnReference(true);
+ return;
}
+ // if last analysis has no period date, then no issue should be considered new.
+ Date createdAfterFromSnapshot = findCreatedAfterFromComponentUuid(snapshot);
+ setCreatedAfterFromDates(builder, createdAfterFromSnapshot, null, false);
}
}
}
return snapshot.map(s -> longToDate(s.getPeriodDate())).orElseGet(() -> new Date(clock.millis()));
}
- private static boolean isLastAnalysisUsingReferenceBranch(Optional<SnapshotDto> snapshot) {
- String periodMode = snapshot.map(SnapshotDto::getPeriodMode).orElse("");
- return periodMode.equals(REFERENCE_BRANCH.name());
+ private static boolean isLastAnalysisUsingReferenceBranch(SnapshotDto snapshot) {
+ return !isNullOrEmpty(snapshot.getPeriodMode()) && snapshot.getPeriodMode().equals(REFERENCE_BRANCH.name());
+ }
+
+ private boolean isLastAnalysisFromSonarQube94Onwards(DbSession dbSession, String componentUuid) {
+ return dbClient.liveMeasureDao().selectMeasure(dbSession, componentUuid, ANALYSIS_FROM_SONARQUBE_9_4_KEY).isPresent();
}
private Optional<SnapshotDto> getLastAnalysis(DbSession dbSession, ComponentDto component) {
Set<String> newCodeReferenceByProjects = snapshots
.stream()
- .filter(s -> !isNullOrEmpty(s.getPeriodMode()) && s.getPeriodMode().equals(REFERENCE_BRANCH.name()))
+ .filter(s -> isLastAnalysisFromReAnalyzedReferenceBranch(dbSession, s))
.map(SnapshotDto::getComponentUuid)
.collect(toSet());
Map<String, PeriodStart> leakByProjects = snapshots
.stream()
- .filter(s -> s.getPeriodDate() != null &&
- (isNullOrEmpty(s.getPeriodMode()) || !s.getPeriodMode().equals(REFERENCE_BRANCH.name())))
+ .filter(s -> s.getPeriodDate() != null && !isLastAnalysisFromReAnalyzedReferenceBranch(dbSession, s))
.collect(uniqueIndex(SnapshotDto::getComponentUuid, s -> new PeriodStart(longToDate(s.getPeriodDate()), false)));
builder.createdAfterByProjectUuids(leakByProjects);
builder.newCodeOnReferenceByProjectUuids(newCodeReferenceByProjects);
}
+ private boolean isLastAnalysisFromReAnalyzedReferenceBranch(DbSession dbSession, SnapshotDto snapshot) {
+ return isLastAnalysisUsingReferenceBranch(snapshot) &&
+ isLastAnalysisFromSonarQube94Onwards(dbSession, snapshot.getComponentUuid());
+ }
+
private static void addDirectories(IssueQuery.Builder builder, List<ComponentDto> directories) {
Collection<String> directoryModuleUuids = new HashSet<>();
Collection<String> directoryPaths = new HashSet<>();
import org.sonar.db.DbTester;
import org.sonar.db.component.ComponentDto;
import org.sonar.db.component.SnapshotDto;
+import org.sonar.db.metric.MetricDto;
import org.sonar.db.rule.RuleDbTester;
import org.sonar.db.rule.RuleDefinitionDto;
import org.sonar.db.user.UserDto;
import static org.junit.Assert.fail;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
+import static org.sonar.api.measures.CoreMetrics.ANALYSIS_FROM_SONARQUBE_9_4_KEY;
import static org.sonar.api.resources.Qualifiers.APP;
import static org.sonar.api.utils.DateUtils.addDays;
import static org.sonar.api.utils.DateUtils.parseDateTime;
}
@Test
- public void leak_period_does_not_rely_on_date_for_reference_branch() {
+ public void leak_period_relies_on_date_for_reference_branch_with_analysis_after_sonarqube_94() {
long leakPeriodStart = addDays(new Date(), -14).getTime();
ComponentDto project = db.components().insertPublicProject();
SnapshotDto analysis = db.components().insertSnapshot(project, s -> s.setPeriodMode(REFERENCE_BRANCH.name())
.setPeriodParam("master"));
+ MetricDto analysisMetric = db.measures().insertMetric(m -> m.setKey(ANALYSIS_FROM_SONARQUBE_9_4_KEY));
+ db.measures().insertLiveMeasure(project, analysisMetric, measure -> measure.setData("true"));
+
SearchRequest request = new SearchRequest()
.setComponentUuids(Collections.singletonList(file.uuid()))
.setOnComponentOnly(true)
assertThat(query.newCodeOnReference()).isTrue();
assertThat(query.createdAfter()).isNull();
}
-
@Test
- public void new_code_period_does_not_rely_on_date_for_reference_branch() {
-
+ public void new_code_period_does_not_rely_on_date_for_reference_branch_with_analysis_after_sonarqube_94() {
ComponentDto project = db.components().insertPublicProject();
ComponentDto file = db.components().insertComponent(newFileDto(project));
- SnapshotDto analysis = db.components().insertSnapshot(project, s -> s.setPeriodMode(REFERENCE_BRANCH.name())
+ db.components().insertSnapshot(project, s -> s.setPeriodMode(REFERENCE_BRANCH.name())
.setPeriodParam("master"));
+ MetricDto analysisMetric = db.measures().insertMetric(m -> m.setKey(ANALYSIS_FROM_SONARQUBE_9_4_KEY));
+ db.measures().insertLiveMeasure(project, analysisMetric, measure -> measure.setData("true"));
+
SearchRequest request = new SearchRequest()
.setComponentUuids(Collections.singletonList(file.uuid()))
.setOnComponentOnly(true)
}
@Test
- public void application_search_project_issues_on_leak() {
+ public void application_search_project_issues_on_leak_with_and_without_analysis_after_sonarqube_94() {
Date now = new Date();
when(clock.millis()).thenReturn(now.getTime());
ComponentDto project1 = db.components().insertPublicProject();
db.components().insertSnapshot(project2, s -> s.setPeriodDate(null));
ComponentDto project3 = db.components().insertPublicProject();
ComponentDto project4 = db.components().insertPublicProject();
- SnapshotDto analysis2 = db.components().insertSnapshot(project4,
+ SnapshotDto analysis3 =db.components().insertSnapshot(project3,
+ s -> s.setPeriodMode(REFERENCE_BRANCH.name()).setPeriodParam("master")
+ .setPeriodDate(addDays(now, -14).getTime()));
+ db.components().insertSnapshot(project4,
s -> s.setPeriodMode(REFERENCE_BRANCH.name()).setPeriodParam("master"));
ComponentDto application = db.components().insertPublicApplication();
+ MetricDto analysisMetric = db.measures().insertMetric(m -> m.setKey(ANALYSIS_FROM_SONARQUBE_9_4_KEY));
+ db.measures().insertLiveMeasure(project4, analysisMetric, measure -> measure.setData("true"));
db.components().insertComponents(newProjectCopy("PC1", project1, application));
db.components().insertComponents(newProjectCopy("PC2", project2, application));
db.components().insertComponents(newProjectCopy("PC3", project3, application));
.setComponentUuids(singletonList(application.uuid()))
.setSinceLeakPeriod(true));
- assertThat(result.createdAfterByProjectUuids()).hasSize(1);
+ assertThat(result.createdAfterByProjectUuids()).hasSize(2);
assertThat(result.createdAfterByProjectUuids().entrySet()).extracting(Map.Entry::getKey, e -> e.getValue().date(), e -> e.getValue().inclusive()).containsOnly(
- tuple(project1.uuid(), new Date(analysis1.getPeriodDate()), false));
+ tuple(project1.uuid(), new Date(analysis1.getPeriodDate()), false),
+ tuple(project3.uuid(), new Date(analysis3.getPeriodDate()), false));
assertThat(result.newCodeOnReferenceByProjectUuids()).hasSize(1);
assertThat(result.newCodeOnReferenceByProjectUuids()).containsOnly(project4.uuid());
assertThat(result.viewUuids()).containsExactlyInAnyOrder(application.uuid());
}
@Test
- public void application_search_project_issues_in_new_code() {
+ public void application_search_project_issues_in_new_code_with_and_without_analysis_after_sonarqube_94() {
Date now = new Date();
when(clock.millis()).thenReturn(now.getTime());
ComponentDto project1 = db.components().insertPublicProject();
SnapshotDto analysis2 = db.components().insertSnapshot(project4,
s -> s.setPeriodMode(REFERENCE_BRANCH.name()).setPeriodParam("master"));
ComponentDto application = db.components().insertPublicApplication();
+ MetricDto analysisMetric = db.measures().insertMetric(m -> m.setKey(ANALYSIS_FROM_SONARQUBE_9_4_KEY));
+ db.measures().insertLiveMeasure(project4, analysisMetric, measure -> measure.setData("true"));
db.components().insertComponents(newProjectCopy("PC1", project1, application));
db.components().insertComponents(newProjectCopy("PC2", project2, application));
db.components().insertComponents(newProjectCopy("PC3", project3, application));
@Test
public void fail_if_no_component_provided_with_since_leak_period() {
- assertThatThrownBy(() -> underTest.create(new SearchRequest().setSinceLeakPeriod(true)))
+ assertThatThrownBy(() -> underTest.create(new SearchRequest().setInNewCodePeriod(true)))
.isInstanceOf(IllegalArgumentException.class)
.hasMessageContaining("One and only one component must be provided when searching in new code period");
}