@@ -124,4 +124,9 @@ public interface AnalysisMetadataHolder { | |||
* Scm Revision of the analysed code | |||
*/ | |||
Optional<String> getScmRevision(); | |||
/** | |||
* Reference branch for the new code period, set by scanner parameter sonar.newCode.referenceBranch | |||
*/ | |||
Optional<String> getNewCodeReferenceBranch(); | |||
} |
@@ -48,6 +48,7 @@ public class AnalysisMetadataHolderImpl implements MutableAnalysisMetadataHolder | |||
private final InitializedProperty<Map<String, QualityProfile>> qProfilesPerLanguage = new InitializedProperty<>(); | |||
private final InitializedProperty<Map<String, ScannerPlugin>> pluginsByKey = new InitializedProperty<>(); | |||
private final InitializedProperty<String> scmRevision = new InitializedProperty<>(); | |||
private final InitializedProperty<String> newCodeReferenceBranch = new InitializedProperty<>(); | |||
private final PlatformEditionProvider editionProvider; | |||
@@ -209,6 +210,14 @@ public class AnalysisMetadataHolderImpl implements MutableAnalysisMetadataHolder | |||
return this; | |||
} | |||
@Override | |||
public MutableAnalysisMetadataHolder setNewCodeReferenceBranch(String newCodeReferenceBranch) { | |||
checkState(!this.newCodeReferenceBranch.isInitialized(), "newCodeReferenceBranch has already been set"); | |||
requireNonNull(newCodeReferenceBranch, "newCodeReferenceBranch can't be null"); | |||
this.newCodeReferenceBranch.setProperty(newCodeReferenceBranch); | |||
return this; | |||
} | |||
@Override | |||
public Optional<String> getScmRevision() { | |||
if (!scmRevision.isInitialized()) { | |||
@@ -217,6 +226,14 @@ public class AnalysisMetadataHolderImpl implements MutableAnalysisMetadataHolder | |||
return Optional.ofNullable(scmRevision.getProperty()); | |||
} | |||
@Override | |||
public Optional<String> getNewCodeReferenceBranch() { | |||
if (!newCodeReferenceBranch.isInitialized()) { | |||
return Optional.empty(); | |||
} | |||
return Optional.of(newCodeReferenceBranch.getProperty()); | |||
} | |||
@Override | |||
public boolean isBranch() { | |||
checkState(this.branch.isInitialized(), BRANCH_NOT_SET); |
@@ -80,4 +80,6 @@ public interface MutableAnalysisMetadataHolder extends AnalysisMetadataHolder { | |||
* @throws IllegalStateException if scm revision id has already been set | |||
*/ | |||
MutableAnalysisMetadataHolder setScmRevision(String scmRevisionId); | |||
MutableAnalysisMetadataHolder setNewCodeReferenceBranch(String newCodeReferenceBranch); | |||
} |
@@ -23,6 +23,9 @@ import java.util.Arrays; | |||
import java.util.Collection; | |||
import java.util.Optional; | |||
import java.util.function.Supplier; | |||
import org.sonar.api.utils.System2; | |||
import org.sonar.ce.task.log.CeTaskMessages; | |||
import org.sonar.ce.task.log.CeTaskMessages.Message; | |||
import org.sonar.ce.task.projectanalysis.analysis.AnalysisMetadataHolder; | |||
import org.sonar.ce.task.projectanalysis.component.TreeRootHolder; | |||
import org.sonar.ce.task.projectanalysis.period.NewCodePeriodResolver; | |||
@@ -34,7 +37,8 @@ import org.sonar.db.DbClient; | |||
import org.sonar.db.DbSession; | |||
import org.sonar.db.newcodeperiod.NewCodePeriodDao; | |||
import org.sonar.db.newcodeperiod.NewCodePeriodDto; | |||
import org.sonar.db.newcodeperiod.NewCodePeriodType; | |||
import static org.sonar.db.newcodeperiod.NewCodePeriodType.REFERENCE_BRANCH; | |||
/** | |||
* Populates the {@link PeriodHolder} | |||
@@ -52,15 +56,19 @@ public class LoadPeriodsStep implements ComputationStep { | |||
private final PeriodHolderImpl periodsHolder; | |||
private final DbClient dbClient; | |||
private final NewCodePeriodResolver resolver; | |||
private final CeTaskMessages ceTaskMessages; | |||
private final System2 system2; | |||
public LoadPeriodsStep(AnalysisMetadataHolder analysisMetadataHolder, NewCodePeriodDao newCodePeriodDao, TreeRootHolder treeRootHolder, | |||
PeriodHolderImpl periodsHolder, DbClient dbClient, NewCodePeriodResolver resolver) { | |||
PeriodHolderImpl periodsHolder, DbClient dbClient, NewCodePeriodResolver resolver, CeTaskMessages ceTaskMessages, System2 system2) { | |||
this.analysisMetadataHolder = analysisMetadataHolder; | |||
this.newCodePeriodDao = newCodePeriodDao; | |||
this.treeRootHolder = treeRootHolder; | |||
this.periodsHolder = periodsHolder; | |||
this.dbClient = dbClient; | |||
this.resolver = resolver; | |||
this.ceTaskMessages = ceTaskMessages; | |||
this.system2 = system2; | |||
} | |||
@Override | |||
@@ -79,18 +87,27 @@ public class LoadPeriodsStep implements ComputationStep { | |||
String branchUuid = treeRootHolder.getRoot().getUuid(); | |||
String projectVersion = treeRootHolder.getRoot().getProjectAttributes().getProjectVersion(); | |||
var newCodePeriod = analysisMetadataHolder.getNewCodeReferenceBranch() | |||
.filter(s -> !s.isBlank()) | |||
.map(b -> new NewCodePeriodDto().setType(REFERENCE_BRANCH).setValue(b)) | |||
.orElse(null); | |||
try (DbSession dbSession = dbClient.openSession(false)) { | |||
Optional<NewCodePeriodDto> dto = firstPresent(Arrays.asList( | |||
Optional<NewCodePeriodDto> specificSetting = firstPresent(Arrays.asList( | |||
() -> getBranchSetting(dbSession, projectUuid, branchUuid), | |||
() -> getProjectSetting(dbSession, projectUuid), | |||
() -> getGlobalSetting(dbSession) | |||
() -> getProjectSetting(dbSession, projectUuid) | |||
)); | |||
NewCodePeriodDto newCodePeriod = dto.orElse(NewCodePeriodDto.defaultInstance()); | |||
if (newCodePeriod == null) { | |||
newCodePeriod = specificSetting.or(() -> getGlobalSetting(dbSession)).orElse(NewCodePeriodDto.defaultInstance()); | |||
if (analysisMetadataHolder.isFirstAnalysis() && newCodePeriod.getType() != NewCodePeriodType.REFERENCE_BRANCH) { | |||
periodsHolder.setPeriod(null); | |||
return; | |||
if (analysisMetadataHolder.isFirstAnalysis() && newCodePeriod.getType() != REFERENCE_BRANCH) { | |||
periodsHolder.setPeriod(null); | |||
return; | |||
} | |||
} else if (specificSetting.isPresent()) { | |||
ceTaskMessages.add(new Message("A scanner parameter is defining a new code reference branch " | |||
+ "but one is already defined specifically for the branch in the New Code Period settings", system2.now())); | |||
} | |||
Period period = resolver.resolve(dbSession, branchUuid, newCodePeriod, projectVersion); |
@@ -80,6 +80,7 @@ public class LoadReportAnalysisMetadataHolderStep implements ComputationStep { | |||
analysisMetadata.setRootComponentRef(reportMetadata.getRootComponentRef()); | |||
analysisMetadata.setCrossProjectDuplicationEnabled(reportMetadata.getCrossProjectDuplicationActivated()); | |||
analysisMetadata.setScmRevision(reportMetadata.getScmRevisionId()); | |||
analysisMetadata.setNewCodeReferenceBranch(reportMetadata.getNewCodeReferenceBranch()); | |||
} | |||
/** |
@@ -49,7 +49,6 @@ public class AnalysisMetadataHolderImplTest { | |||
.build(); | |||
private static final long SOME_DATE = 10000000L; | |||
private final PlatformEditionProvider editionProvider = mock(PlatformEditionProvider.class); | |||
private final AnalysisMetadataHolderImpl underTest = new AnalysisMetadataHolderImpl(editionProvider); | |||
@@ -77,6 +76,32 @@ public class AnalysisMetadataHolderImplTest { | |||
assertThat(underTest.getAnalysisDate()).isEqualTo(SOME_DATE); | |||
} | |||
@Test | |||
public void get_new_code_reference_branch() { | |||
String newCodeReferenceBranch = "newCodeReferenceBranch"; | |||
underTest.setNewCodeReferenceBranch(newCodeReferenceBranch); | |||
assertThat(underTest.getNewCodeReferenceBranch()).hasValue(newCodeReferenceBranch); | |||
} | |||
@Test | |||
public void get_new_code_reference_branch_return_empty_when_holder_is_not_initialized() { | |||
assertThat(underTest.getNewCodeReferenceBranch()).isEmpty(); | |||
} | |||
@Test | |||
public void set_new_code_reference_branch_throws_ISE_when_called_twice() { | |||
String newCodeReferenceBranch = "newCodeReferenceBranch"; | |||
underTest.setNewCodeReferenceBranch(newCodeReferenceBranch); | |||
assertThatThrownBy(() -> underTest.setNewCodeReferenceBranch(newCodeReferenceBranch)) | |||
.isInstanceOf(IllegalStateException.class) | |||
.hasMessage("newCodeReferenceBranch has already been set"); | |||
} | |||
@Test | |||
public void getAnalysisDate_throws_ISE_when_holder_is_not_initialized() { | |||
assertThatThrownBy(() -> new AnalysisMetadataHolderImpl(editionProvider).getAnalysisDate()) | |||
@@ -338,7 +363,7 @@ public class AnalysisMetadataHolderImplTest { | |||
AnalysisMetadataHolderImpl underTest = new AnalysisMetadataHolderImpl(editionProvider); | |||
underTest.setRootComponentRef(10); | |||
assertThatThrownBy(() -> underTest.setRootComponentRef(9)) | |||
assertThatThrownBy(() -> underTest.setRootComponentRef(9)) | |||
.isInstanceOf(IllegalStateException.class) | |||
.hasMessage("Root component ref has already been set"); | |||
} | |||
@@ -359,7 +384,7 @@ public class AnalysisMetadataHolderImplTest { | |||
AnalysisMetadataHolderImpl underTest = new AnalysisMetadataHolderImpl(editionProvider); | |||
underTest.setScmRevision("bd56dab"); | |||
assertThatThrownBy(() -> underTest.setScmRevision("bd56dab")) | |||
assertThatThrownBy(() -> underTest.setScmRevision("bd56dab")) | |||
.isInstanceOf(IllegalStateException.class) | |||
.hasMessage("ScmRevision has already been set"); | |||
} |
@@ -27,6 +27,7 @@ import java.time.ZonedDateTime; | |||
import java.util.ArrayList; | |||
import java.util.Arrays; | |||
import java.util.List; | |||
import java.util.Optional; | |||
import java.util.Random; | |||
import java.util.stream.Stream; | |||
import javax.annotation.Nullable; | |||
@@ -39,6 +40,7 @@ import org.sonar.api.utils.System2; | |||
import org.sonar.api.utils.log.LogAndArguments; | |||
import org.sonar.api.utils.log.LogTester; | |||
import org.sonar.api.utils.log.LoggerLevel; | |||
import org.sonar.ce.task.log.CeTaskMessages; | |||
import org.sonar.ce.task.projectanalysis.analysis.AnalysisMetadataHolder; | |||
import org.sonar.ce.task.projectanalysis.component.Component; | |||
import org.sonar.ce.task.projectanalysis.component.ReportComponent; | |||
@@ -62,8 +64,10 @@ import static org.apache.commons.lang.RandomStringUtils.randomAlphanumeric; | |||
import static org.assertj.core.api.Assertions.assertThat; | |||
import static org.assertj.core.api.Assertions.assertThatThrownBy; | |||
import static org.assertj.core.api.Assertions.fail; | |||
import static org.mockito.ArgumentMatchers.any; | |||
import static org.mockito.Mockito.mock; | |||
import static org.mockito.Mockito.verify; | |||
import static org.mockito.Mockito.verifyNoInteractions; | |||
import static org.mockito.Mockito.verifyNoMoreInteractions; | |||
import static org.mockito.Mockito.when; | |||
import static org.sonar.db.component.SnapshotDto.STATUS_PROCESSED; | |||
@@ -80,14 +84,15 @@ public class LoadPeriodsStepTest extends BaseStepTest { | |||
@Rule | |||
public LogTester logTester = new LogTester(); | |||
private AnalysisMetadataHolder analysisMetadataHolder = mock(AnalysisMetadataHolder.class); | |||
private PeriodHolderImpl periodsHolder = new PeriodHolderImpl(); | |||
private System2 system2Mock = mock(System2.class); | |||
private NewCodePeriodDao dao = new NewCodePeriodDao(system2Mock, new SequenceUuidFactory()); | |||
private NewCodePeriodResolver newCodePeriodResolver = new NewCodePeriodResolver(dbTester.getDbClient(), analysisMetadataHolder); | |||
private ZonedDateTime analysisDate = ZonedDateTime.of(2019, 3, 20, 5, 30, 40, 0, ZoneId.systemDefault()); | |||
private LoadPeriodsStep underTest = new LoadPeriodsStep(analysisMetadataHolder, dao, treeRootHolder, periodsHolder, dbTester.getDbClient(), newCodePeriodResolver); | |||
private final AnalysisMetadataHolder analysisMetadataHolder = mock(AnalysisMetadataHolder.class); | |||
private final PeriodHolderImpl periodsHolder = new PeriodHolderImpl(); | |||
private final System2 system2Mock = mock(System2.class); | |||
private final NewCodePeriodDao dao = new NewCodePeriodDao(system2Mock, new SequenceUuidFactory()); | |||
private final NewCodePeriodResolver newCodePeriodResolver = new NewCodePeriodResolver(dbTester.getDbClient(), analysisMetadataHolder); | |||
private final ZonedDateTime analysisDate = ZonedDateTime.of(2019, 3, 20, 5, 30, 40, 0, ZoneId.systemDefault()); | |||
private final CeTaskMessages ceTaskMessages = mock(CeTaskMessages.class); | |||
private final LoadPeriodsStep underTest = new LoadPeriodsStep(analysisMetadataHolder, dao, treeRootHolder, periodsHolder, dbTester.getDbClient(), newCodePeriodResolver, | |||
ceTaskMessages, system2Mock); | |||
private ComponentDto project; | |||
@@ -115,6 +120,7 @@ public class LoadPeriodsStepTest extends BaseStepTest { | |||
verify(analysisMetadataHolder).isFirstAnalysis(); | |||
verify(analysisMetadataHolder).isBranch(); | |||
verify(analysisMetadataHolder).getProject(); | |||
verify(analysisMetadataHolder).getNewCodeReferenceBranch(); | |||
assertThat(periodsHolder.hasPeriod()).isFalse(); | |||
verifyNoMoreInteractions(analysisMetadataHolder); | |||
} | |||
@@ -166,6 +172,7 @@ public class LoadPeriodsStepTest extends BaseStepTest { | |||
setBranchPeriod(project.uuid(), branch.uuid(), NewCodePeriodType.NUMBER_OF_DAYS, "10"); | |||
testNumberOfDays(branch); | |||
verifyNoInteractions(ceTaskMessages); | |||
} | |||
@Test | |||
@@ -177,6 +184,50 @@ public class LoadPeriodsStepTest extends BaseStepTest { | |||
underTest.execute(new TestComputationStepContext()); | |||
assertPeriod(NewCodePeriodType.REFERENCE_BRANCH, "master", null); | |||
verifyNoInteractions(ceTaskMessages); | |||
} | |||
@Test | |||
public void add_analysis_warning_if_scanner_defines_reference_when_branch_setting_also_defines_reference() { | |||
ComponentDto branch = dbTester.components().insertProjectBranch(project); | |||
setupRoot(branch); | |||
setBranchPeriod(project.uuid(), branch.uuid(), NewCodePeriodType.REFERENCE_BRANCH, "master"); | |||
String newCodeReferenceBranch = "newCodeReferenceBranch"; | |||
when(analysisMetadataHolder.getNewCodeReferenceBranch()).thenReturn(Optional.of(newCodeReferenceBranch)); | |||
underTest.execute(new TestComputationStepContext()); | |||
assertPeriod(NewCodePeriodType.REFERENCE_BRANCH, newCodeReferenceBranch, null); | |||
verify(ceTaskMessages).add(any(CeTaskMessages.Message.class)); | |||
} | |||
@Test | |||
public void scanner_defines_new_code_reference_branch() { | |||
ComponentDto branch = dbTester.components().insertProjectBranch(project); | |||
setupRoot(branch); | |||
String newCodeReferenceBranch = "newCodeReferenceBranch"; | |||
when(analysisMetadataHolder.getNewCodeReferenceBranch()).thenReturn(Optional.of(newCodeReferenceBranch)); | |||
underTest.execute(new TestComputationStepContext()); | |||
assertPeriod(NewCodePeriodType.REFERENCE_BRANCH, newCodeReferenceBranch, null); | |||
verifyNoInteractions(ceTaskMessages); | |||
} | |||
@Test | |||
public void scanner_overrides_new_code_reference_branch() { | |||
ComponentDto branch = dbTester.components().insertProjectBranch(project); | |||
setupRoot(branch); | |||
setProjectPeriod(project.uuid(), NewCodePeriodType.REFERENCE_BRANCH, "master"); | |||
String newCodeReferenceBranch = "newCodeReferenceBranch"; | |||
when(analysisMetadataHolder.getNewCodeReferenceBranch()).thenReturn(Optional.of(newCodeReferenceBranch)); | |||
underTest.execute(new TestComputationStepContext()); | |||
assertPeriod(NewCodePeriodType.REFERENCE_BRANCH, newCodeReferenceBranch, null); | |||
verify(ceTaskMessages).add(any(CeTaskMessages.Message.class)); | |||
} | |||
@Test | |||
@@ -188,6 +239,7 @@ public class LoadPeriodsStepTest extends BaseStepTest { | |||
underTest.execute(new TestComputationStepContext()); | |||
assertPeriod(NewCodePeriodType.REFERENCE_BRANCH, "master", null); | |||
verifyNoInteractions(ceTaskMessages); | |||
} | |||
private void testNumberOfDays(ComponentDto projectOrBranch) { | |||
@@ -217,6 +269,7 @@ public class LoadPeriodsStepTest extends BaseStepTest { | |||
assertPeriod(NewCodePeriodType.SPECIFIC_ANALYSIS, selectedAnalysis.getUuid(), selectedAnalysis.getCreatedAt()); | |||
verifyDebugLogs("Resolving new code period with a specific analysis"); | |||
verifyNoInteractions(ceTaskMessages); | |||
} | |||
@Test |
@@ -103,6 +103,19 @@ public class LoadReportAnalysisMetadataHolderStepTest { | |||
assertThat(analysisMetadataHolder.getAnalysisDate()).isEqualTo(ANALYSIS_DATE); | |||
} | |||
@Test | |||
public void set_new_code_reference_branch() { | |||
String newCodeReferenceBranch = "newCodeReferenceBranch"; | |||
reportReader.setMetadata( | |||
newBatchReportBuilder() | |||
.setNewCodeReferenceBranch(newCodeReferenceBranch) | |||
.build()); | |||
underTest.execute(new TestComputationStepContext()); | |||
assertThat(analysisMetadataHolder.getNewCodeReferenceBranch()).hasValue(newCodeReferenceBranch); | |||
} | |||
@Test | |||
public void set_project_from_dto() { | |||
reportReader.setMetadata( |
@@ -47,6 +47,7 @@ public class AnalysisMetadataHolderRule extends ExternalResource implements Muta | |||
private final InitializedProperty<Map<String, QualityProfile>> qProfilesPerLanguage = new InitializedProperty<>(); | |||
private final InitializedProperty<Map<String, ScannerPlugin>> pluginsByKey = new InitializedProperty<>(); | |||
private final InitializedProperty<String> scmRevision = new InitializedProperty<>(); | |||
private final InitializedProperty<String> newCodeReferenceBranch = new InitializedProperty<>(); | |||
@Override | |||
public AnalysisMetadataHolderRule setUuid(String s) { | |||
@@ -193,6 +194,13 @@ public class AnalysisMetadataHolderRule extends ExternalResource implements Muta | |||
return this; | |||
} | |||
@Override | |||
public MutableAnalysisMetadataHolder setNewCodeReferenceBranch(String newCodeReferenceBranch) { | |||
checkState(!this.newCodeReferenceBranch.isInitialized(), "ScmRevisionId has already been set"); | |||
this.newCodeReferenceBranch.setProperty(defaultIfBlank(newCodeReferenceBranch, null)); | |||
return this; | |||
} | |||
@Override | |||
public Optional<String> getScmRevision() { | |||
if (!scmRevision.isInitialized()) { | |||
@@ -201,6 +209,14 @@ public class AnalysisMetadataHolderRule extends ExternalResource implements Muta | |||
return Optional.ofNullable(scmRevision.getProperty()); | |||
} | |||
@Override | |||
public Optional<String> getNewCodeReferenceBranch() { | |||
if (!newCodeReferenceBranch.isInitialized()) { | |||
return Optional.empty(); | |||
} | |||
return Optional.ofNullable(newCodeReferenceBranch.getProperty()); | |||
} | |||
@Override | |||
public boolean isBranch() { | |||
Branch property = this.branch.getProperty(); |
@@ -165,11 +165,20 @@ public class MutableAnalysisMetadataHolderRule extends ExternalResource implemen | |||
return this; | |||
} | |||
@Override public MutableAnalysisMetadataHolder setNewCodeReferenceBranch(String newCodeReferenceBranch) { | |||
delegate.setNewCodeReferenceBranch(newCodeReferenceBranch); | |||
return this; | |||
} | |||
@Override | |||
public Optional<String> getScmRevision() { | |||
return delegate.getScmRevision(); | |||
} | |||
@Override public Optional<String> getNewCodeReferenceBranch() { | |||
return delegate.getNewCodeReferenceBranch(); | |||
} | |||
@Override | |||
public boolean isBranch() { | |||
return delegate.isBranch(); |