Доработка уведомлений о конфликтах MR
All checks were successful
continuous-integration/drone/push Build is passing

This commit is contained in:
Struchkov Mark 2023-01-30 12:33:39 +03:00
parent 157ff0b4f0
commit 99c9cd5ee2
Signed by: upagge
GPG Key ID: D3018BE7BA428CA6
12 changed files with 166 additions and 19 deletions

View File

@ -0,0 +1,30 @@
package dev.struchkov.bot.gitlab.context.domain.notify.mergerequest;
import lombok.Builder;
import lombok.Getter;
@Getter
public class ConflictResolveMrNotify extends MrNotify {
public static final String TYPE = "ConflictResolveMrNotify";
private final String sourceBranch;
@Builder
private ConflictResolveMrNotify(
Long mrId,
String name,
String url,
String projectKey,
String sourceBranch
) {
super(mrId, projectKey, name, url);
this.sourceBranch = sourceBranch;
}
@Override
public String getType() {
return TYPE;
}
}

View File

@ -28,6 +28,8 @@ public interface MergeRequestRepository {
Set<Long> findAllIds(); Set<Long> findAllIds();
void disableNotify(Long mrId); void notification(boolean enable, Long mrId);
void notificationByProjectId(boolean enable, Set<Long> projectIds);
} }

View File

@ -38,6 +38,8 @@ public interface MergeRequestsService {
Set<Long> getAllIds(); Set<Long> getAllIds();
void disableNotify(@NonNull Long mrId); void notification(boolean enable, @NonNull Long mrId);
void notificationByProjectId(boolean enable, @NonNull Set<Long> projectIds);
} }

View File

@ -16,6 +16,7 @@ public class Icons {
public static final String TASK = "\uD83D\uDCBC"; public static final String TASK = "\uD83D\uDCBC";
public static final String ARROW = ""; public static final String ARROW = "";
public static final String DANGEROUS = "⚠️"; public static final String DANGEROUS = "⚠️";
public static final String GREEN_CIRCLE = "\uD83D\uDFE2";
public static final String PEN = "✏️"; public static final String PEN = "✏️";
public static final String ASSIGNEE = "\uD83C\uDFA9"; public static final String ASSIGNEE = "\uD83C\uDFA9";
public static final String BUILD = "⚙️"; public static final String BUILD = "⚙️";

View File

@ -12,6 +12,7 @@ import dev.struchkov.bot.gitlab.context.domain.entity.MergeRequestForDiscussion;
import dev.struchkov.bot.gitlab.context.domain.entity.Person; import dev.struchkov.bot.gitlab.context.domain.entity.Person;
import dev.struchkov.bot.gitlab.context.domain.entity.Project; import dev.struchkov.bot.gitlab.context.domain.entity.Project;
import dev.struchkov.bot.gitlab.context.domain.notify.mergerequest.ConflictMrNotify; import dev.struchkov.bot.gitlab.context.domain.notify.mergerequest.ConflictMrNotify;
import dev.struchkov.bot.gitlab.context.domain.notify.mergerequest.ConflictResolveMrNotify;
import dev.struchkov.bot.gitlab.context.domain.notify.mergerequest.NewMrForAssignee; import dev.struchkov.bot.gitlab.context.domain.notify.mergerequest.NewMrForAssignee;
import dev.struchkov.bot.gitlab.context.domain.notify.mergerequest.NewMrForReview; import dev.struchkov.bot.gitlab.context.domain.notify.mergerequest.NewMrForReview;
import dev.struchkov.bot.gitlab.context.domain.notify.mergerequest.StatusMrNotify; import dev.struchkov.bot.gitlab.context.domain.notify.mergerequest.StatusMrNotify;
@ -179,7 +180,8 @@ public class MergeRequestsServiceImpl implements MergeRequestsService {
if (isChangedMr) { if (isChangedMr) {
notifyAboutStatus(oldMergeRequest, mergeRequest, project); notifyAboutStatus(oldMergeRequest, mergeRequest, project);
notifyAboutConflict(oldMergeRequest, mergeRequest, project); notifyAboutNewConflict(oldMergeRequest, mergeRequest, project);
notifyAboutResolveConflict(oldMergeRequest, mergeRequest, project);
notifyAboutUpdate(oldMergeRequest, mergeRequest, project); notifyAboutUpdate(oldMergeRequest, mergeRequest, project);
} }
@ -195,14 +197,15 @@ public class MergeRequestsServiceImpl implements MergeRequestsService {
} }
//TODO [05.12.2022|uPagge]: Добавить уведомление, если происходит удаление //TODO [05.12.2022|uPagge]: Добавить уведомление, если происходит удаление
private void notifyAssignee(AssigneeChanged assigneeChanged, MergeRequest oldMergeRequest, MergeRequest mergeRequest, Project project) { private void notifyAssignee(AssigneeChanged assigneeChanged, MergeRequest oldMergeRequest, MergeRequest mergeRequest, Project project) {
switch (assigneeChanged) { switch (assigneeChanged) {
case BECOME -> case BECOME ->
sendNotifyNewAssignee(mergeRequest, project.getName(), Optional.ofNullable(oldMergeRequest.getAssignee()).map(Person::getName).orElse(null)); sendNotifyNewAssignee(mergeRequest, project.getName(), Optional.ofNullable(oldMergeRequest.getAssignee()).map(Person::getName).orElse(null));
} }
} }
//TODO [05.12.2022|uPagge]: Добавить уведомление, если происходит удаление ревьювера //TODO [05.12.2022|uPagge]: Добавить уведомление, если происходит удаление ревьювера
private void notifyReviewer(ReviewerChanged reviewerChanged, MergeRequest mergeRequest, Project project) { private void notifyReviewer(ReviewerChanged reviewerChanged, MergeRequest mergeRequest, Project project) {
switch (reviewerChanged) { switch (reviewerChanged) {
case BECOME -> sendNotifyNewMrReview(mergeRequest, project.getName()); case BECOME -> sendNotifyNewMrReview(mergeRequest, project.getName());
@ -268,8 +271,14 @@ public class MergeRequestsServiceImpl implements MergeRequestsService {
@Override @Override
@Transactional @Transactional
public void disableNotify(@NonNull Long mrId) { public void notification(boolean enable, @NonNull Long mrId) {
repository.disableNotify(mrId); repository.notification(enable, mrId);
}
@Override
@Transactional
public void notificationByProjectId(boolean enable, @NonNull Set<Long> projectIds) {
repository.notificationByProjectId(enable, projectIds);
} }
private void notifyAboutUpdate(MergeRequest oldMergeRequest, MergeRequest mergeRequest, Project project) { private void notifyAboutUpdate(MergeRequest oldMergeRequest, MergeRequest mergeRequest, Project project) {
@ -317,7 +326,7 @@ public class MergeRequestsServiceImpl implements MergeRequestsService {
} }
} }
protected void notifyAboutConflict(MergeRequest oldMergeRequest, MergeRequest mergeRequest, Project project) { protected void notifyAboutNewConflict(MergeRequest oldMergeRequest, MergeRequest mergeRequest, Project project) {
final Long gitlabUserId = personInformation.getId(); final Long gitlabUserId = personInformation.getId();
if ( if (
!oldMergeRequest.isConflict() // У старого MR не было конфликта !oldMergeRequest.isConflict() // У старого MR не было конфликта
@ -336,6 +345,25 @@ public class MergeRequestsServiceImpl implements MergeRequestsService {
} }
} }
private void notifyAboutResolveConflict(MergeRequest oldMergeRequest, MergeRequest mergeRequest, Project project) {
final Long gitlabUserId = personInformation.getId();
if (
oldMergeRequest.isConflict() // У старого MR был конфликт
&& !mergeRequest.isConflict() // А у нового нет
&& gitlabUserId.equals(oldMergeRequest.getAuthor().getId()) // и MR создан пользователем бота
) {
notifyService.send(
ConflictResolveMrNotify.builder()
.mrId(oldMergeRequest.getId())
.sourceBranch(oldMergeRequest.getSourceBranch())
.name(mergeRequest.getTitle())
.url(mergeRequest.getWebUrl())
.projectKey(project.getName())
.build()
);
}
}
protected void notifyAboutStatus(MergeRequest oldMergeRequest, MergeRequest newMergeRequest, Project project) { protected void notifyAboutStatus(MergeRequest oldMergeRequest, MergeRequest newMergeRequest, Project project) {
final MergeRequestState oldStatus = oldMergeRequest.getState(); final MergeRequestState oldStatus = oldMergeRequest.getState();
final MergeRequestState newStatus = newMergeRequest.getState(); final MergeRequestState newStatus = newMergeRequest.getState();

View File

@ -3,6 +3,7 @@ package dev.struchkov.bot.gitlab.core.service.parser;
import dev.struchkov.bot.gitlab.context.domain.ExistContainer; import dev.struchkov.bot.gitlab.context.domain.ExistContainer;
import dev.struchkov.bot.gitlab.context.domain.entity.Person; import dev.struchkov.bot.gitlab.context.domain.entity.Person;
import dev.struchkov.bot.gitlab.context.domain.entity.Project; import dev.struchkov.bot.gitlab.context.domain.entity.Project;
import dev.struchkov.bot.gitlab.context.service.MergeRequestsService;
import dev.struchkov.bot.gitlab.context.service.PersonService; import dev.struchkov.bot.gitlab.context.service.PersonService;
import dev.struchkov.bot.gitlab.context.service.ProjectService; import dev.struchkov.bot.gitlab.context.service.ProjectService;
import dev.struchkov.bot.gitlab.core.config.properties.GitlabProperty; import dev.struchkov.bot.gitlab.core.config.properties.GitlabProperty;
@ -39,8 +40,8 @@ public class ProjectParser {
public static final String OWNER = "&owned=true"; public static final String OWNER = "&owned=true";
public static final String PRIVATE = "&visibility=private"; public static final String PRIVATE = "&visibility=private";
public static final String PUBLIC_OWNER = "&visibility=public&owned=true";
private final MergeRequestsService mergeRequestsService;
private final ProjectService projectService; private final ProjectService projectService;
private final PersonService personService; private final PersonService personService;
@ -99,8 +100,10 @@ public class ProjectParser {
final Project newProject = conversionService.convert(projectJson, Project.class); final Project newProject = conversionService.convert(projectJson, Project.class);
projectService.create(newProject); projectService.create(newProject);
} else { } else {
projectService.notification(true, singleton(projectJson.getId())); final Set<Long> projectId = singleton(projectJson.getId());
projectService.processing(true, singleton(projectJson.getId())); projectService.notification(true, projectId);
projectService.processing(true, projectId);
mergeRequestsService.notificationByProjectId(true, projectId);
} }
} }

View File

@ -71,8 +71,13 @@ public class MergeRequestRepositoryImpl implements MergeRequestRepository {
} }
@Override @Override
public void disableNotify(Long mrId) { public void notification(boolean enable, Long mrId) {
jpaRepository.disableNotify(mrId); jpaRepository.disableNotify(enable, mrId);
}
@Override
public void notificationByProjectId(boolean enable, Set<Long> projectIds) {
jpaRepository.notificationByProjectId(enable, projectIds);
} }
} }

View File

@ -29,7 +29,11 @@ public interface MergeRequestJpaRepository extends JpaRepositoryImplementation<M
Set<Long> findAllIds(); Set<Long> findAllIds();
@Modifying @Modifying
@Query("UPDATE MergeRequest mr SET mr.notification = false WHERE mr.id = :mrId") @Query("UPDATE MergeRequest mr SET mr.notification = :enable WHERE mr.id = :mrId")
void disableNotify(@Param("mrId") Long mrId); void disableNotify(@Param("enable") boolean enable, @Param("mrId") Long mrId);
@Modifying
@Query("UPDATE MergeRequest mr SET mr.notification = :enable WHERE mr.projectId in :projectIds")
void notificationByProjectId(@Param("enable") boolean enable, @Param("projectIds") Set<Long> projectIds);
} }

View File

@ -5,8 +5,15 @@ import dev.struchkov.bot.gitlab.context.utils.Icons;
import dev.struchkov.godfather.main.domain.BoxAnswer; import dev.struchkov.godfather.main.domain.BoxAnswer;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import static dev.struchkov.bot.gitlab.context.utils.Icons.link; import static dev.struchkov.bot.gitlab.telegram.utils.Const.BUTTON_ARG_CONFIRMATION;
import static dev.struchkov.bot.gitlab.telegram.utils.Const.BUTTON_ARG_DISABLE_NOTIFY_MR_ID;
import static dev.struchkov.bot.gitlab.telegram.utils.Const.BUTTON_VALUE_FALSE;
import static dev.struchkov.bot.gitlab.telegram.utils.UnitName.DELETE_MESSAGE;
import static dev.struchkov.godfather.main.domain.BoxAnswer.boxAnswer; import static dev.struchkov.godfather.main.domain.BoxAnswer.boxAnswer;
import static dev.struchkov.godfather.main.domain.keyboard.button.SimpleButton.simpleButton;
import static dev.struchkov.godfather.main.domain.keyboard.simple.SimpleKeyBoardLine.simpleLine;
import static dev.struchkov.godfather.telegram.domain.keyboard.InlineKeyBoard.inlineKeyBoard;
import static dev.struchkov.godfather.telegram.domain.keyboard.button.UrlButton.urlButton;
import static dev.struchkov.haiti.utils.Strings.escapeMarkdown; import static dev.struchkov.haiti.utils.Strings.escapeMarkdown;
@Component @Component
@ -15,12 +22,24 @@ public class ConflictPrNotifyGenerator implements NotifyBoxAnswerGenerator<Confl
@Override @Override
public BoxAnswer generate(ConflictMrNotify notify) { public BoxAnswer generate(ConflictMrNotify notify) {
final StringBuilder builder = new StringBuilder(Icons.DANGEROUS).append(" *Attention! MergeRequest conflict | ").append(escapeMarkdown(notify.getProjectName())).append("*") final StringBuilder builder = new StringBuilder(Icons.DANGEROUS).append(" *Attention. MergeRequest conflict!*")
.append(Icons.HR) .append(Icons.HR)
.append(link(notify.getTitle(), notify.getUrl())); .append(escapeMarkdown(notify.getTitle()))
.append(Icons.HR)
.append(Icons.PROJECT).append(": ").append(escapeMarkdown(notify.getProjectName())).append("\n")
.append(Icons.TREE).append(": ").append(escapeMarkdown(notify.getSourceBranch()));
final String notifyMessage = builder.toString(); final String notifyMessage = builder.toString();
return boxAnswer(notifyMessage); return boxAnswer(
notifyMessage,
inlineKeyBoard(
simpleLine(
simpleButton(Icons.VIEW, DELETE_MESSAGE),
urlButton(Icons.LINK, notify.getUrl()),
simpleButton(Icons.DISABLE_NOTIFY, "[" + BUTTON_ARG_DISABLE_NOTIFY_MR_ID + ":" + notify.getMrId() + ";" + BUTTON_ARG_CONFIRMATION + ":" + BUTTON_VALUE_FALSE + "]")
)
)
);
} }
@Override @Override

View File

@ -0,0 +1,50 @@
package dev.struchkov.bot.gitlab.telegram.service.notify;
import dev.struchkov.bot.gitlab.context.domain.notify.mergerequest.ConflictResolveMrNotify;
import dev.struchkov.bot.gitlab.context.utils.Icons;
import dev.struchkov.godfather.main.domain.BoxAnswer;
import org.springframework.stereotype.Component;
import static dev.struchkov.bot.gitlab.telegram.utils.Const.BUTTON_ARG_CONFIRMATION;
import static dev.struchkov.bot.gitlab.telegram.utils.Const.BUTTON_ARG_DISABLE_NOTIFY_MR_ID;
import static dev.struchkov.bot.gitlab.telegram.utils.Const.BUTTON_VALUE_FALSE;
import static dev.struchkov.bot.gitlab.telegram.utils.UnitName.DELETE_MESSAGE;
import static dev.struchkov.godfather.main.domain.BoxAnswer.boxAnswer;
import static dev.struchkov.godfather.main.domain.keyboard.button.SimpleButton.simpleButton;
import static dev.struchkov.godfather.main.domain.keyboard.simple.SimpleKeyBoardLine.simpleLine;
import static dev.struchkov.godfather.telegram.domain.keyboard.InlineKeyBoard.inlineKeyBoard;
import static dev.struchkov.godfather.telegram.domain.keyboard.button.UrlButton.urlButton;
import static dev.struchkov.haiti.utils.Strings.escapeMarkdown;
@Component
public class ConflictResolvePrNotifyGenerator implements NotifyBoxAnswerGenerator<ConflictResolveMrNotify> {
@Override
public BoxAnswer generate(ConflictResolveMrNotify notify) {
final StringBuilder builder = new StringBuilder(Icons.GREEN_CIRCLE).append(" *Merge request conflict resolved!*")
.append(Icons.HR)
.append(escapeMarkdown(notify.getTitle()))
.append(Icons.HR)
.append(Icons.PROJECT).append(": ").append(escapeMarkdown(notify.getProjectName())).append("\n")
.append(Icons.TREE).append(": ").append(escapeMarkdown(notify.getSourceBranch()));
final String notifyMessage = builder.toString();
return boxAnswer(
notifyMessage,
inlineKeyBoard(
simpleLine(
simpleButton(Icons.VIEW, DELETE_MESSAGE),
urlButton(Icons.LINK, notify.getUrl()),
simpleButton(Icons.DISABLE_NOTIFY, "[" + BUTTON_ARG_DISABLE_NOTIFY_MR_ID + ":" + notify.getMrId() + ";" + BUTTON_ARG_CONFIRMATION + ":" + BUTTON_VALUE_FALSE + "]")
)
)
);
}
@Override
public String getNotifyType() {
return ConflictResolveMrNotify.TYPE;
}
}

View File

@ -79,7 +79,7 @@ public class DisableNotifyMrUnit {
.orElseThrow(); .orElseThrow();
if (confirmation) { if (confirmation) {
mergeRequestsService.disableNotify(mrId); mergeRequestsService.notification(false, mrId);
scheduledExecutorService.schedule(() -> telegramSending.deleteMessage(mail.getPersonId(), clickButton.getMessageId()), 5, TimeUnit.SECONDS); scheduledExecutorService.schedule(() -> telegramSending.deleteMessage(mail.getPersonId(), clickButton.getMessageId()), 5, TimeUnit.SECONDS);
return replaceBoxAnswer(SUCCESSFULLY_DISABLED); return replaceBoxAnswer(SUCCESSFULLY_DISABLED);
} else { } else {

View File

@ -2,6 +2,7 @@ package dev.struchkov.bot.gitlab.telegram.unit.command;
import dev.struchkov.bot.gitlab.context.domain.PersonInformation; import dev.struchkov.bot.gitlab.context.domain.PersonInformation;
import dev.struchkov.bot.gitlab.context.service.AppSettingService; import dev.struchkov.bot.gitlab.context.service.AppSettingService;
import dev.struchkov.bot.gitlab.context.service.MergeRequestsService;
import dev.struchkov.bot.gitlab.context.service.ProjectService; import dev.struchkov.bot.gitlab.context.service.ProjectService;
import dev.struchkov.bot.gitlab.context.utils.Icons; import dev.struchkov.bot.gitlab.context.utils.Icons;
import dev.struchkov.bot.gitlab.telegram.utils.UnitName; import dev.struchkov.bot.gitlab.telegram.utils.UnitName;
@ -28,6 +29,7 @@ import static dev.struchkov.godfather.main.domain.BoxAnswer.replaceBoxAnswer;
public class EnableProjectNotify { public class EnableProjectNotify {
private final ProjectService projectService; private final ProjectService projectService;
private final MergeRequestsService mergeRequestsService;
private final AppSettingService settingService; private final AppSettingService settingService;
private final PersonInformation personInformation; private final PersonInformation personInformation;
@ -59,6 +61,7 @@ public class EnableProjectNotify {
final Set<Long> setProjectId = Set.of(projectId); final Set<Long> setProjectId = Set.of(projectId);
projectService.processing(true, setProjectId); projectService.processing(true, setProjectId);
projectService.notification(true, setProjectId); projectService.notification(true, setProjectId);
mergeRequestsService.notificationByProjectId(true, setProjectId);
return replaceBoxAnswer(mail.getId(), Icons.GOOD + " you will now receive notifications!"); return replaceBoxAnswer(mail.getId(), Icons.GOOD + " you will now receive notifications!");
} }
) )