Фиксирование рабочей версии

This commit is contained in:
upagge 2020-10-07 09:56:59 +03:00
parent 03ed80b7fd
commit a6e3dc785c
No known key found for this signature in database
GPG Key ID: 15CD012E46F6BA34
16 changed files with 197 additions and 40 deletions

View File

@ -16,6 +16,8 @@ spring:
jdbc: jdbc:
lob: lob:
non_contextual_creation: true non_contextual_creation: true
logging:
config: classpath:logback-dev.xml
bitbucketbot: bitbucketbot:
scheduler: scheduler:
person: 0 */1 * * * * person: 0 */1 * * * *

View File

@ -16,6 +16,8 @@ spring:
jdbc: jdbc:
lob: lob:
non_contextual_creation: true non_contextual_creation: true
logging:
config: classpath:logback-prod.xml
bitbucketbot: bitbucketbot:
scheduler: scheduler:
person: 0 0 0 */1 * * person: 0 0 0 */1 * *

View File

@ -9,5 +9,6 @@
<include file="liquibase/v.2.0.0/2020-09-20-teamcity.xml"/> <include file="liquibase/v.2.0.0/2020-09-20-teamcity.xml"/>
<include file="liquibase/v.2.0.0/2020-10-01-rating.xml"/> <include file="liquibase/v.2.0.0/2020-10-01-rating.xml"/>
<include file="liquibase/v.2.0.0/2020-10-02-add-column-status-teamcity.xml"/> <include file="liquibase/v.2.0.0/2020-10-02-add-column-status-teamcity.xml"/>
<include file="liquibase/v.2.0.0/2020-10-07-add-colum-reviewer-date.xml"/>
</databaseChangeLog> </databaseChangeLog>

View File

@ -0,0 +1,12 @@
<databaseChangeLog
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.1.xsd">
<changeSet id="2020-10-07" author="upagge">
<addColumn tableName="reviewer">
<column name="date_change" type="datetime"/>
</addColumn>
</changeSet>
</databaseChangeLog>

View File

@ -0,0 +1,24 @@
<configuration>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{dd.MM.yyyy HH:mm:ss.SSS} [%thread] %-5level %logger{20} - %msg%n</pattern>
</encoder>
</appender>
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>bitbucketbot-logs.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>bitbucket.%d{yyyy-MM-dd}.log</fileNamePattern>
<maxHistory>10</maxHistory>
<totalSizeCap>50MB</totalSizeCap>
</rollingPolicy>
<encoder>
<pattern>%d{dd.MM.yyyy HH:mm:ss.SSS} [%thread] %-5level %logger{20} - %msg%n</pattern>
</encoder>
</appender>
<root level="info">
<appender-ref ref="STDOUT"/>
</root>
</configuration>

View File

@ -17,6 +17,7 @@ import javax.persistence.Id;
import javax.persistence.JoinColumn; import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne; import javax.persistence.ManyToOne;
import javax.persistence.Table; import javax.persistence.Table;
import java.time.LocalDateTime;
/** /**
* Ревьювер пулреквеста. * Ревьювер пулреквеста.
@ -52,6 +53,9 @@ public class Reviewer {
@Column(name = "status") @Column(name = "status")
private ReviewerStatus status; private ReviewerStatus status;
@Column(name = "date_change")
private LocalDateTime dateChange;
@ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.REFRESH, optional = false) @ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.REFRESH, optional = false)
@JoinColumn(name = "pull_request_id") @JoinColumn(name = "pull_request_id")
private PullRequest pullRequest; private PullRequest pullRequest;

View File

@ -2,7 +2,6 @@ package org.sadtech.bot.vcs.core.domain.notify;
import lombok.Builder; import lombok.Builder;
import lombok.Getter; import lombok.Getter;
import lombok.NonNull;
import org.sadtech.bot.vcs.core.domain.entity.PullRequest; import org.sadtech.bot.vcs.core.domain.entity.PullRequest;
import org.sadtech.bot.vcs.core.utils.MessageUtils; import org.sadtech.bot.vcs.core.utils.MessageUtils;
import org.sadtech.bot.vcs.core.utils.Smile; import org.sadtech.bot.vcs.core.utils.Smile;
@ -10,6 +9,7 @@ import org.sadtech.bot.vcs.core.utils.UpdateDataComparator;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
import java.util.stream.Collectors;
/** /**
* // TODO: 20.09.2020 Добавить описание. * // TODO: 20.09.2020 Добавить описание.
@ -36,35 +36,28 @@ public class GoodMorningNotify extends Notify {
this.pullRequestsNeedWork = pullRequestsNeedWork; this.pullRequestsNeedWork = pullRequestsNeedWork;
} }
private static String needWorkPr(@NonNull List<PullRequest> pullRequestsNeedWork) {
final StringBuilder message = new StringBuilder();
pullRequestsNeedWork.stream()
.limit(3)
.forEach(
pullRequest -> message.append("-- ").append(link(pullRequest.getTitle(), pullRequest.getUrl())).append(Smile.BR)
);
return message.toString();
}
private static String link(String name, String url) {
return "[" + name + "](" + url + ")";
}
@Override @Override
public String generateMessage() { public String generateMessage() {
StringBuilder message = new StringBuilder().append(Smile.SUN).append(" *Доброе утро* ").append(Smile.SUN).append(Smile.HR); StringBuilder message = new StringBuilder().append(Smile.SUN).append(" *Доброе утро* ").append(Smile.SUN).append(Smile.HR);
if (!pullRequestsReviews.isEmpty()) { if (!pullRequestsReviews.isEmpty()) {
message.append("Необходимо проверить ").append(pullRequestsReviews.size()).append(" ПР!").append(Smile.TWO_BR) message.append("Необходимо проверить ").append(pullRequestsReviews.size()).append(" ПР!").append(Smile.TWO_BR)
.append("Самые старые:").append(Smile.BR); .append("Самые старые:").append(Smile.BR);
MessageUtils.pullRequestForReview(pullRequestsReviews).ifPresent(message::append); MessageUtils.pullRequestForReview(
pullRequestsReviews.stream()
.limit(3)
.collect(Collectors.toList())
).ifPresent(message::append);
} else { } else {
message.append("Ты либо самый лучший работник, либо тебе не доверяют проверку ПР ").append(Smile.MEGA_FUN).append(Smile.TWO_BR) message.append("Ты либо самый лучший работник, либо тебе не доверяют проверку ПР ").append(Smile.MEGA_FUN).append(Smile.TWO_BR)
.append("Поздравляю, у тебя ни одного ПР на проверку!").append(Smile.BR); .append("Поздравляю, у тебя ни одного ПР на проверку!").append(Smile.BR);
} }
if (!pullRequestsNeedWork.isEmpty()) { MessageUtils.pullRequestForNeedWork(
message.append(Smile.BR).append(Smile.DANGEROUS).append("Требуется доработать ").append(pullRequestsNeedWork.size()).append(" ПР:").append(Smile.BR); pullRequestsNeedWork.stream()
message.append(needWorkPr(pullRequestsNeedWork)).append(Smile.BR); .limit(3)
} .collect(Collectors.toList())
).ifPresent(
messageNeedWork -> message.append(Smile.BR).append(Smile.DANGEROUS).append("Требуется доработать ").append(pullRequestsNeedWork.size()).append(" ПР:").append(Smile.BR).append(messageNeedWork)
);
message message
.append(Smile.BR).append("Удачного дня ").append(Smile.FLOWER).append(Smile.TWO_BR); .append(Smile.BR).append("Удачного дня ").append(Smile.FLOWER).append(Smile.TWO_BR);
return message.toString(); return message.toString();

View File

@ -25,6 +25,12 @@ public interface PullRequestsService extends SimpleManagerService<PullRequest, L
*/ */
List<PullRequest> getAllByReviewerAndStatuses(@NonNull String login, @NonNull ReviewerStatus reviewerStatus, @NonNull Set<PullRequestStatus> pullRequestStatuses); List<PullRequest> getAllByReviewerAndStatuses(@NonNull String login, @NonNull ReviewerStatus reviewerStatus, @NonNull Set<PullRequestStatus> pullRequestStatuses);
/**
* Получить все ПР с определенным статусом, который есть хотя бы у одного ревьювера.
*
* @param login Автор ПР.
* @param status Статус ревьювера.
*/
List<PullRequest> getAllByAuthorAndReviewerStatus(@NonNull String login, @NonNull ReviewerStatus status); List<PullRequest> getAllByAuthorAndReviewerStatus(@NonNull String login, @NonNull ReviewerStatus status);
/** /**

View File

@ -31,6 +31,7 @@ import org.sadtech.bot.vcs.core.service.RatingService;
import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import java.time.LocalDateTime;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
@ -64,6 +65,10 @@ public class PullRequestsServiceImpl extends AbstractSimpleManagerService<PullRe
public PullRequest create(@NonNull PullRequest pullRequest) { public PullRequest create(@NonNull PullRequest pullRequest) {
Assert.isNull(pullRequest.getId(), "При создании идентификатор должен быть пустым"); Assert.isNull(pullRequest.getId(), "При создании идентификатор должен быть пустым");
pullRequest.getReviewers().forEach(
reviewer -> reviewer.setDateChange(LocalDateTime.now())
);
final PullRequest newPullRequest = pullRequestsRepository.save(pullRequest); final PullRequest newPullRequest = pullRequestsRepository.save(pullRequest);
ratingService.addRating(newPullRequest.getAuthorLogin(), PointType.CREATE_PULL_REQUEST, PointType.CREATE_PULL_REQUEST.getPoints()); ratingService.addRating(newPullRequest.getAuthorLogin(), PointType.CREATE_PULL_REQUEST, PointType.CREATE_PULL_REQUEST.getPoints());
@ -174,6 +179,7 @@ public class PullRequestsServiceImpl extends AbstractSimpleManagerService<PullRe
if (!oldStatus.equals(newStatus)) { if (!oldStatus.equals(newStatus)) {
reviewerChanges.add(ReviewerChange.ofOld(oldReviewer.getPersonLogin(), oldStatus, newStatus)); reviewerChanges.add(ReviewerChange.ofOld(oldReviewer.getPersonLogin(), oldStatus, newStatus));
oldReviewer.setStatus(newStatus); oldReviewer.setStatus(newStatus);
oldReviewer.setDateChange(LocalDateTime.now());
} }
} else { } else {
reviewerChanges.add(ReviewerChange.ofNew(newReviewer.getPersonLogin(), newReviewer.getStatus())); reviewerChanges.add(ReviewerChange.ofNew(newReviewer.getPersonLogin(), newReviewer.getStatus()));

View File

@ -18,22 +18,35 @@ import java.util.stream.Collectors;
public final class MessageUtils { public final class MessageUtils {
private static final UpdateDataComparator COMPARATOR = new UpdateDataComparator(); private static final UpdateDataComparator COMPARATOR = new UpdateDataComparator();
private static final Integer PR_COUNT = 4;
public static Optional<String> pullRequestForReview(@NonNull List<PullRequest> pullRequestsReviews) { public static Optional<String> pullRequestForReview(@NonNull List<PullRequest> pullRequestsReviews) {
if (!pullRequestsReviews.isEmpty()) { if (!pullRequestsReviews.isEmpty()) {
return Optional.of( return Optional.of(
pullRequestsReviews.stream() pullRequestsReviews.stream()
.sorted(COMPARATOR) .sorted(COMPARATOR)
.limit(PR_COUNT) .map(MessageUtils::generateStringItemPullRequestReview)
.map(MessageUtils::topPr)
.collect(Collectors.joining("\n")) .collect(Collectors.joining("\n"))
); );
} }
return Optional.empty(); return Optional.empty();
} }
private static String topPr(PullRequest pullRequest) { public static Optional<String> pullRequestForNeedWork(@NonNull List<PullRequest> pullRequestNeedWork) {
if (!pullRequestNeedWork.isEmpty()) {
return Optional.of(
pullRequestNeedWork.stream()
.map(MessageUtils::generateStringItemPullRequestNeedWork)
.collect(Collectors.joining("\n"))
);
}
return Optional.empty();
}
private static String generateStringItemPullRequestNeedWork(PullRequest pullRequest) {
return "-- " + link(pullRequest.getTitle(), pullRequest.getUrl());
}
private static String generateStringItemPullRequestReview(PullRequest pullRequest) {
return Smile.statusPr(pullRequest.getUpdateDate()) + " " + return Smile.statusPr(pullRequest.getUpdateDate()) + " " +
link(pullRequest.getTitle(), pullRequest.getUrl()) + link(pullRequest.getTitle(), pullRequest.getUrl()) +
Smile.BR; Smile.BR;

View File

@ -0,0 +1,41 @@
package org.sadtech.bot.vcs.telegram.service.unit.pullrequest;
import lombok.RequiredArgsConstructor;
import org.sadtech.bot.vcs.core.domain.ReviewerStatus;
import org.sadtech.bot.vcs.core.domain.entity.Person;
import org.sadtech.bot.vcs.core.domain.entity.PullRequest;
import org.sadtech.bot.vcs.core.exception.NotFoundException;
import org.sadtech.bot.vcs.core.service.PersonService;
import org.sadtech.bot.vcs.core.service.PullRequestsService;
import org.sadtech.bot.vcs.core.utils.MessageUtils;
import org.sadtech.social.bot.service.usercode.ProcessingData;
import org.sadtech.social.core.domain.BoxAnswer;
import org.sadtech.social.core.domain.content.Message;
import org.springframework.stereotype.Component;
import java.util.List;
/**
* // TODO: 17.09.2020 Добавить описание.
*
* @author upagge 17.09.2020
*/
@Component
@RequiredArgsConstructor
public class PullRequestNeedWorkProcessing implements ProcessingData<Message> {
private final PersonService personService;
private final PullRequestsService pullRequestsService;
@Override
public BoxAnswer processing(Message message) {
final Person person = personService.getByTelegramId(message.getPersonId())
.orElseThrow(() -> new NotFoundException("Пользователь не найден"));
final List<PullRequest> pullRequests = pullRequestsService.getAllByAuthorAndReviewerStatus(person.getLogin(), ReviewerStatus.UNAPPROVED);
return BoxAnswer.of(
MessageUtils.pullRequestForNeedWork(pullRequests)
.orElse("Не найдено ПРов, которые нуждаются в доработке :)")
);
}
}

View File

@ -1,4 +1,4 @@
package org.sadtech.bot.vcs.telegram.service.unit; package org.sadtech.bot.vcs.telegram.service.unit.pullrequest;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import org.sadtech.bot.vcs.core.domain.PullRequestStatus; import org.sadtech.bot.vcs.core.domain.PullRequestStatus;
@ -24,7 +24,7 @@ import java.util.List;
*/ */
@Component @Component
@RequiredArgsConstructor @RequiredArgsConstructor
public class PullRequestProcessing implements ProcessingData<Message> { public class PullRequestReviewProcessing implements ProcessingData<Message> {
private final PersonService personService; private final PersonService personService;
private final PullRequestsService pullRequestsService; private final PullRequestsService pullRequestsService;

View File

@ -0,0 +1,64 @@
package org.sadtech.bot.vcs.telegram.unit;
import org.sadtech.bot.vcs.telegram.service.unit.pullrequest.PullRequestNeedWorkProcessing;
import org.sadtech.bot.vcs.telegram.service.unit.pullrequest.PullRequestReviewProcessing;
import org.sadtech.social.bot.domain.unit.AnswerProcessing;
import org.sadtech.social.bot.domain.unit.AnswerText;
import org.sadtech.social.core.domain.BoxAnswer;
import org.sadtech.social.core.domain.content.Message;
import org.sadtech.social.core.utils.KeyBoards;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* // TODO: 02.10.2020 Добавить описание.
*
* @author upagge 02.10.2020
*/
@Configuration
public class PullRequestUnitConfig {
@Bean
public AnswerText menuPullRequest(
AnswerProcessing<Message> reviewPullRequest,
AnswerProcessing<Message> needWorkPullRequest
) {
return AnswerText.builder()
.boxAnswer(
BoxAnswer.builder()
.message("Эта вкладка для работы с Pull Request")
.keyBoard(
KeyBoards.verticalMenuString(
"Нуждаются в ревью",
"Необходимо доработать"
)
)
.build()
)
.phrase("Pull Requests")
.nextUnit(reviewPullRequest)
.nextUnit(needWorkPullRequest)
.build();
}
@Bean
public AnswerProcessing<Message> reviewPullRequest(
PullRequestReviewProcessing pullRequestReviewProcessing
) {
return AnswerProcessing.builder()
.processingData(pullRequestReviewProcessing)
.phrase("Нуждаются в ревью")
.build();
}
@Bean
public AnswerProcessing<Message> needWorkPullRequest(
PullRequestNeedWorkProcessing pullRequestNeedWorkProcessing
) {
return AnswerProcessing.builder()
.processingData(pullRequestNeedWorkProcessing)
.phrase("Необходимо доработать")
.build();
}
}

View File

@ -2,7 +2,6 @@ package org.sadtech.bot.vcs.telegram.unit;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import org.sadtech.bot.vcs.core.service.PersonService; import org.sadtech.bot.vcs.core.service.PersonService;
import org.sadtech.bot.vcs.telegram.service.unit.PullRequestProcessing;
import org.sadtech.bot.vcs.telegram.service.unit.RatingTopProcessing; import org.sadtech.bot.vcs.telegram.service.unit.RatingTopProcessing;
import org.sadtech.bot.vcs.telegram.service.unit.TaskProcessing; import org.sadtech.bot.vcs.telegram.service.unit.TaskProcessing;
import org.sadtech.bot.vcs.telegram.utils.GeneratorKeyBoards; import org.sadtech.bot.vcs.telegram.utils.GeneratorKeyBoards;
@ -44,7 +43,7 @@ public class UnitConfig {
@Bean @Bean
public AnswerText menu( public AnswerText menu(
AnswerProcessing<Message> getTasks, AnswerProcessing<Message> getTasks,
AnswerProcessing<Message> getPr, AnswerText menuPullRequest,
AnswerText settings, AnswerText settings,
AnswerProcessing<Message> getTopRating AnswerProcessing<Message> getTopRating
) { ) {
@ -56,7 +55,7 @@ public class UnitConfig {
.build() .build()
) )
.nextUnit(getTasks) .nextUnit(getTasks)
.nextUnit(getPr) .nextUnit(menuPullRequest)
.nextUnit(settings) .nextUnit(settings)
.nextUnit(getTopRating) .nextUnit(getTopRating)
.build(); .build();
@ -90,16 +89,6 @@ public class UnitConfig {
.build(); .build();
} }
@Bean
public AnswerProcessing<Message> getPr(
PullRequestProcessing pullRequestProcessing
) {
return AnswerProcessing.builder()
.processingData(pullRequestProcessing)
.phrase("Проверить ПР")
.build();
}
@Bean @Bean
AnswerProcessing<Message> getTopRating( AnswerProcessing<Message> getTopRating(
RatingTopProcessing ratingTopProcessing RatingTopProcessing ratingTopProcessing

View File

@ -16,7 +16,7 @@ public class GeneratorKeyBoards {
public static KeyBoard menu() { public static KeyBoard menu() {
final KeyBoardButtonText tasks = KeyBoardButtonText.builder().label("Мои задачи").build(); final KeyBoardButtonText tasks = KeyBoardButtonText.builder().label("Мои задачи").build();
final KeyBoardButtonText pr = KeyBoardButtonText.builder().label("Проверить ПР").build(); final KeyBoardButtonText pr = KeyBoardButtonText.builder().label("Pull Requests").build();
final KeyBoardButtonText top = KeyBoardButtonText.builder().label("\uD83C\uDF1F Таблица рейтинга \uD83C\uDF1F").build(); final KeyBoardButtonText top = KeyBoardButtonText.builder().label("\uD83C\uDF1F Таблица рейтинга \uD83C\uDF1F").build();
final KeyBoardButtonText settings = KeyBoardButtonText.builder().label("Настройки").build(); final KeyBoardButtonText settings = KeyBoardButtonText.builder().label("Настройки").build();