import org.sonar.db.DbClient;
import org.sonar.db.DbTester;
import org.sonar.db.component.BranchDto;
+import org.sonar.db.component.ComponentDbTester;
+import org.sonar.db.component.ComponentDto;
+import org.sonar.db.component.ComponentTesting;
+import org.sonar.db.project.ProjectDto;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
.hasMessage("entity not found in task");
}
+ @Test
+ public void execute_givenMainBranchWithDifferentUuidFromProject_shouldNotIncludeItInPurge() {
+ BranchDto branchDto = new BranchDto()
+ .setBranchType(BRANCH)
+ .setKey("main")
+ .setUuid(BRANCH_UUID)
+ .setProjectUuid(ENTITY_UUID)
+ .setIsMain(true)
+ .setNeedIssueSync(true)
+ .setExcludeFromPurge(true);
+ dbClient.branchDao().insert(dbTester.getSession(), branchDto);
+
+ ProjectDto projectDto = ComponentTesting.newProjectDto().setUuid(ENTITY_UUID).setKey("component key");
+ ComponentDto componentDto = ComponentTesting.newBranchComponent(projectDto, branchDto);
+ dbClient.componentDao().insert(dbTester.getSession(), componentDto, false);
+ dbClient.projectDao().insert(dbTester.getSession(), projectDto, false);
+ dbTester.commit();
+
+ underTest.execute(() -> null);
+
+ Optional<BranchDto> branch = dbClient.branchDao().selectByUuid(dbTester.getSession(), BRANCH_UUID);
+ assertThat(branch.get().isNeedIssueSync()).isTrue();
+ assertThat(branch.get().isExcludeFromPurge()).isTrue();
+ }
+
+ @Test
+ public void execute_givenNotExistingEntityUuid_shouldIncludeItInPurge() {
+ BranchDto branchDto = new BranchDto()
+ .setBranchType(BRANCH)
+ .setKey("main")
+ .setUuid(BRANCH_UUID)
+ .setProjectUuid(ENTITY_UUID)
+ .setIsMain(false)
+ .setNeedIssueSync(true)
+ .setExcludeFromPurge(true);
+ dbClient.branchDao().insert(dbTester.getSession(), branchDto);
+ dbTester.commit();
+
+ underTest.execute(() -> null);
+
+ Optional<BranchDto> branch = dbClient.branchDao().selectByUuid(dbTester.getSession(), BRANCH_UUID);
+ assertThat(branch.get().isNeedIssueSync()).isFalse();
+ assertThat(branch.get().isExcludeFromPurge()).isFalse();
+ }
+
@Test
public void verify_step_description() {
assertThat(underTest.getDescription()).isEqualTo("Ignore orphan component");
import org.sonar.db.DbClient;
import org.sonar.db.DbSession;
import org.sonar.db.component.ComponentDto;
+import org.sonar.db.entity.EntityDto;
public final class IgnoreOrphanBranchStep implements ComputationStep {
private static final Logger LOG = LoggerFactory.getLogger(IgnoreOrphanBranchStep.class);
String componentUuid = ceTask.getComponent().orElseThrow(() -> new UnsupportedOperationException("component not found in task")).getUuid();
try (DbSession dbSession = dbClient.openSession(false)) {
- Optional<ComponentDto> componentDto = dbClient.componentDao().selectByUuid(dbSession, entityUuid);
- if(!componentDto.isPresent()){
+ Optional<ComponentDto> componentDto = dbClient.componentDao().selectByUuid(dbSession, componentUuid);
+ Optional<EntityDto> entityDto = dbClient.entityDao().selectByUuid(dbSession, entityUuid);
+ if (componentDto.isEmpty() || entityDto.isEmpty()) {
LOG.info("reindexation task has been trigger on an orphan branch. removing any exclude_from_purge flag, and skip the indexation");
dbClient.branchDao().updateExcludeFromPurge(dbSession, componentUuid, false);
dbClient.branchDao().updateNeedIssueSync(dbSession, componentUuid, false);
branchLikes.length > 2 ||
(branchLikes.length === 2 && branchLikes.some((branch) => isBranch(branch)));
- const showWarning = isMainBranch(branchLike) && hasBranches;
const showTutorial = isMainBranch(branchLike) && !hasBranches && !hasAnalyses;
let warning;
- if (isLoggedIn(currentUser) && showWarning && hasBadBranchConfig) {
+ if (isLoggedIn(currentUser) && isMainBranch(branchLike) && hasBranches && hasBadBranchConfig) {
warning = translateWithParameters(
'provisioning.no_analysis_on_main_branch.bad_configuration',
getBranchLikeDisplayName(branchLike),
<div className="page page-limited">
{isLoggedIn(currentUser) ? (
<>
- {showWarning && (
+ {hasBranches && (
<Alert variant="warning" aria-label={warning}>
{warning}
</Alert>
return (
<Modal
- headerTitle={translateWithParameters(
- 'project_branch_pull_request.branch.set_x_as_main',
- branch.name
- )}
+ headerTitle={
+ <span className="sw-break-all">
+ {translateWithParameters('project_branch_pull_request.branch.set_x_as_main', branch.name)}
+ </span>
+ }
loading={isLoading}
onClose={onClose}
body={
/**
* This method is called after the specified projects have branches deleted or main branch changed.
*/
- void onProjectBranchesChanged(Set<Project> projects);
+ void onProjectBranchesChanged(Set<Project> projects, Set<String> impactedBranches);
/**
* This method is called after the specified projects' keys have been modified.
/**
* This method is called after the specified project have any king of change (branch deleted, change of main branch, ...)
- * This method will call method {@link ProjectLifeCycleListener#onProjectBranchesChanged(Set)} of all known
+ * This method will call method {@link ProjectLifeCycleListener#onProjectBranchesChanged(Set,Set)} of all known
* {@link ProjectLifeCycleListener} implementations.
* <p>
* This method ensures all {@link ProjectLifeCycleListener} implementations are called, even if one or more of
* them fail with an exception.
*/
- void onProjectBranchesChanged(Set<Project> projects);
+ void onProjectBranchesChanged(Set<Project> projects, Set<String> impactedBranches);
/**
* This method is called after the specified project's key has been changed and will call method
}
@Override
- public void onProjectBranchesChanged(Set<Project> projects) {
+ public void onProjectBranchesChanged(Set<Project> projects, Set<String> impactedBranches) {
checkNotNull(projects, "projects can't be null");
if (projects.isEmpty()) {
return;
}
Arrays.stream(listeners)
- .forEach(safelyCallListener(listener -> listener.onProjectBranchesChanged(projects)));
+ .forEach(safelyCallListener(listener -> listener.onProjectBranchesChanged(projects, impactedBranches)));
}
@Override
import org.mockito.InOrder;
import org.mockito.Mockito;
+import static java.util.Collections.emptySet;
import static java.util.Collections.singleton;
import static org.assertj.core.api.Assertions.assertThatCode;
import static org.assertj.core.api.Assertions.assertThatNoException;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anySet;
import static org.mockito.ArgumentMatchers.same;
+import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verifyNoInteractions;
@Test
public void onProjectBranchesChanged_throws_NPE_if_set_is_null() {
- assertThatThrownBy(() -> underTestWithListeners.onProjectBranchesChanged(null))
+ assertThatThrownBy(() -> underTestWithListeners.onProjectBranchesChanged(null, null))
.isInstanceOf(NullPointerException.class)
.hasMessage("projects can't be null");
}
@Test
public void onProjectBranchesChanged_throws_NPE_if_set_is_null_even_if_no_listeners() {
- assertThatThrownBy(() -> underTestNoListeners.onProjectBranchesChanged(null))
+ assertThatThrownBy(() -> underTestNoListeners.onProjectBranchesChanged(null, null))
.isInstanceOf(NullPointerException.class)
.hasMessage("projects can't be null");
}
@Test
public void onProjectBranchesChanged_has_no_effect_if_set_is_empty() {
- underTestNoListeners.onProjectBranchesChanged(Collections.emptySet());
+ underTestNoListeners.onProjectBranchesChanged(Collections.emptySet(), emptySet());
- underTestWithListeners.onProjectBranchesChanged(Collections.emptySet());
+ underTestWithListeners.onProjectBranchesChanged(Collections.emptySet(), emptySet());
verifyNoInteractions(listener1, listener2, listener3);
}
@Test
@UseDataProvider("oneOrManyProjects")
public void onProjectBranchesChanged_does_not_fail_if_there_is_no_listener(Set<Project> projects) {
- assertThatNoException().isThrownBy(()-> underTestNoListeners.onProjectBranchesChanged(projects));
+ assertThatNoException().isThrownBy(()-> underTestNoListeners.onProjectBranchesChanged(projects, emptySet()));
}
@Test
public void onProjectBranchesChanged_calls_all_listeners_in_order_of_addition_to_constructor(Set<Project> projects) {
InOrder inOrder = Mockito.inOrder(listener1, listener2, listener3);
- underTestWithListeners.onProjectBranchesChanged(projects);
+ underTestWithListeners.onProjectBranchesChanged(projects, emptySet());
- inOrder.verify(listener1).onProjectBranchesChanged(same(projects));
- inOrder.verify(listener2).onProjectBranchesChanged(same(projects));
- inOrder.verify(listener3).onProjectBranchesChanged(same(projects));
+ inOrder.verify(listener1).onProjectBranchesChanged(same(projects), eq(emptySet()));
+ inOrder.verify(listener2).onProjectBranchesChanged(same(projects), eq(emptySet()));
+ inOrder.verify(listener3).onProjectBranchesChanged(same(projects), eq(emptySet()));
inOrder.verifyNoMoreInteractions();
}
InOrder inOrder = Mockito.inOrder(listener1, listener2, listener3);
doThrow(new RuntimeException("Faking listener2 throwing an exception"))
.when(listener2)
- .onProjectBranchesChanged(any());
+ .onProjectBranchesChanged(any(), anySet());
- underTestWithListeners.onProjectBranchesChanged(projects);
+ underTestWithListeners.onProjectBranchesChanged(projects, emptySet());
- inOrder.verify(listener1).onProjectBranchesChanged(same(projects));
- inOrder.verify(listener2).onProjectBranchesChanged(same(projects));
- inOrder.verify(listener3).onProjectBranchesChanged(same(projects));
+ inOrder.verify(listener1).onProjectBranchesChanged(same(projects), eq(emptySet()));
+ inOrder.verify(listener2).onProjectBranchesChanged(same(projects), eq(emptySet()));
+ inOrder.verify(listener3).onProjectBranchesChanged(same(projects), eq(emptySet()));
inOrder.verifyNoMoreInteractions();
}
InOrder inOrder = Mockito.inOrder(listener1, listener2, listener3);
doThrow(new Error("Faking listener2 throwing an Error"))
.when(listener2)
- .onProjectBranchesChanged(any());
+ .onProjectBranchesChanged(any(), anySet());
- underTestWithListeners.onProjectBranchesChanged(projects);
+ underTestWithListeners.onProjectBranchesChanged(projects, emptySet());
- inOrder.verify(listener1).onProjectBranchesChanged(same(projects));
- inOrder.verify(listener2).onProjectBranchesChanged(same(projects));
- inOrder.verify(listener3).onProjectBranchesChanged(same(projects));
+ inOrder.verify(listener1).onProjectBranchesChanged(same(projects), eq(emptySet()));
+ inOrder.verify(listener2).onProjectBranchesChanged(same(projects), eq(emptySet()));
+ inOrder.verify(listener3).onProjectBranchesChanged(same(projects), eq(emptySet()));
inOrder.verifyNoMoreInteractions();
}
import org.sonar.server.tester.UserSessionRule;
import org.sonar.server.ws.WsActionTester;
+import static java.util.Collections.emptySet;
import static java.util.Collections.singleton;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
.execute();
verifyDeletedKey("branch1");
- verify(projectLifeCycleListeners).onProjectBranchesChanged(singleton(Project.fromProjectDtoWithTags(project)));
+ verify(projectLifeCycleListeners).onProjectBranchesChanged(singleton(Project.fromProjectDtoWithTags(project)), emptySet());
}
@Test
.setParam(PARAM_PROJECT, projectData.projectKey())
.setParam(PARAM_BRANCH, newMainBranch.getKey()).execute();
- checkCallToProjectLifeCycleListenersOnProjectBranchesChanges(projectData.getProjectDto());
+ checkCallToProjectLifeCycleListenersOnProjectBranchesChanges(projectData.getProjectDto(), projectData.getMainBranchDto().getUuid());
verify(indexers).commitAndIndexBranches(any(), eq(List.of(projectData.getMainBranchDto(), newMainBranch)), eq(Indexers.BranchEvent.SWITCH_OF_MAIN_BRANCH));
checkNewMainBranch(projectData.projectUuid(), newMainBranch.getUuid());
checkPreviousMainBranch(projectData);
.formatted(projectData.projectKey(), newMainBranch.getKey(), projectData.getMainBranchDto().getKey()));
}
- private void checkCallToProjectLifeCycleListenersOnProjectBranchesChanges(ProjectDto projectDto) {
+ private void checkCallToProjectLifeCycleListenersOnProjectBranchesChanges(ProjectDto projectDto, String oldMainBranchUuid) {
Project project = Project.from(projectDto);
- verify(projectLifeCycleListeners).onProjectBranchesChanged(Set.of(project));
+ verify(projectLifeCycleListeners).onProjectBranchesChanged(Set.of(project), Set.of(oldMainBranchUuid) );
}
private void checkNewMainBranch(String projectUuid, String newBranchUuid) {
import org.sonar.server.project.ProjectLifeCycleListeners;
import org.sonar.server.user.UserSession;
+import static java.util.Collections.emptySet;
import static java.util.Collections.singleton;
import static org.sonar.server.branch.ws.BranchesWs.addBranchParam;
import static org.sonar.server.branch.ws.BranchesWs.addProjectParam;
"Branch '%s' not found for project '%s'", branchKey, projectKey);
componentCleanerService.deleteBranch(dbSession, branch);
- projectLifeCycleListeners.onProjectBranchesChanged(singleton(Project.fromProjectDtoWithTags(project)));
+ projectLifeCycleListeners.onProjectBranchesChanged(singleton(Project.fromProjectDtoWithTags(project)), emptySet());
response.noContent();
}
}
import java.util.List;
import java.util.Objects;
+import java.util.Set;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.sonar.api.server.ws.Request;
return;
}
configureProjectWithNewMainBranch(dbSession, projectDto.getKey(), oldMainBranch, newMainBranch);
- refreshApplicationsAndPortfoliosComputedByProject(projectDto);
+ refreshApplicationsAndPortfoliosComputedByProject(projectDto, Set.of(oldMainBranch.getUuid()));
indexers.commitAndIndexBranches(dbSession, List.of(oldMainBranch, newMainBranch), Indexers.BranchEvent.SWITCH_OF_MAIN_BRANCH);
dbSession.commit();
return false;
}
- private void refreshApplicationsAndPortfoliosComputedByProject(ProjectDto projectDto) {
- projectLifeCycleListeners.onProjectBranchesChanged(singleton(Project.from(projectDto)));
+ private void refreshApplicationsAndPortfoliosComputedByProject(ProjectDto projectDto, Set<String> impactedBranchesUuids) {
+ projectLifeCycleListeners.onProjectBranchesChanged(singleton(Project.from(projectDto)), impactedBranchesUuids);
}
private void updateNewMainBranch(DbSession dbSession, BranchDto newMainBranch) {