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

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:
lob:
non_contextual_creation: true
logging:
config: classpath:logback-dev.xml
bitbucketbot:
scheduler:
person: 0 */1 * * * *

View File

@ -16,6 +16,8 @@ spring:
jdbc:
lob:
non_contextual_creation: true
logging:
config: classpath:logback-prod.xml
bitbucketbot:
scheduler:
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-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-07-add-colum-reviewer-date.xml"/>
</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.ManyToOne;
import javax.persistence.Table;
import java.time.LocalDateTime;
/**
* Ревьювер пулреквеста.
@ -52,6 +53,9 @@ public class Reviewer {
@Column(name = "status")
private ReviewerStatus status;
@Column(name = "date_change")
private LocalDateTime dateChange;
@ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.REFRESH, optional = false)
@JoinColumn(name = "pull_request_id")
private PullRequest pullRequest;

View File

@ -2,7 +2,6 @@ package org.sadtech.bot.vcs.core.domain.notify;
import lombok.Builder;
import lombok.Getter;
import lombok.NonNull;
import org.sadtech.bot.vcs.core.domain.entity.PullRequest;
import org.sadtech.bot.vcs.core.utils.MessageUtils;
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.Set;
import java.util.stream.Collectors;
/**
* // TODO: 20.09.2020 Добавить описание.
@ -36,35 +36,28 @@ public class GoodMorningNotify extends Notify {
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
public String generateMessage() {
StringBuilder message = new StringBuilder().append(Smile.SUN).append(" *Доброе утро* ").append(Smile.SUN).append(Smile.HR);
if (!pullRequestsReviews.isEmpty()) {
message.append("Необходимо проверить ").append(pullRequestsReviews.size()).append(" ПР!").append(Smile.TWO_BR)
.append("Самые старые:").append(Smile.BR);
MessageUtils.pullRequestForReview(pullRequestsReviews).ifPresent(message::append);
MessageUtils.pullRequestForReview(
pullRequestsReviews.stream()
.limit(3)
.collect(Collectors.toList())
).ifPresent(message::append);
} else {
message.append("Ты либо самый лучший работник, либо тебе не доверяют проверку ПР ").append(Smile.MEGA_FUN).append(Smile.TWO_BR)
.append("Поздравляю, у тебя ни одного ПР на проверку!").append(Smile.BR);
}
if (!pullRequestsNeedWork.isEmpty()) {
message.append(Smile.BR).append(Smile.DANGEROUS).append("Требуется доработать ").append(pullRequestsNeedWork.size()).append(" ПР:").append(Smile.BR);
message.append(needWorkPr(pullRequestsNeedWork)).append(Smile.BR);
}
MessageUtils.pullRequestForNeedWork(
pullRequestsNeedWork.stream()
.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
.append(Smile.BR).append("Удачного дня ").append(Smile.FLOWER).append(Smile.TWO_BR);
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);
/**
* Получить все ПР с определенным статусом, который есть хотя бы у одного ревьювера.
*
* @param login Автор ПР.
* @param 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.stereotype.Service;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
@ -64,6 +65,10 @@ public class PullRequestsServiceImpl extends AbstractSimpleManagerService<PullRe
public PullRequest create(@NonNull PullRequest pullRequest) {
Assert.isNull(pullRequest.getId(), "При создании идентификатор должен быть пустым");
pullRequest.getReviewers().forEach(
reviewer -> reviewer.setDateChange(LocalDateTime.now())
);
final PullRequest newPullRequest = pullRequestsRepository.save(pullRequest);
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)) {
reviewerChanges.add(ReviewerChange.ofOld(oldReviewer.getPersonLogin(), oldStatus, newStatus));
oldReviewer.setStatus(newStatus);
oldReviewer.setDateChange(LocalDateTime.now());
}
} else {
reviewerChanges.add(ReviewerChange.ofNew(newReviewer.getPersonLogin(), newReviewer.getStatus()));

View File

@ -18,22 +18,35 @@ import java.util.stream.Collectors;
public final class MessageUtils {
private static final UpdateDataComparator COMPARATOR = new UpdateDataComparator();
private static final Integer PR_COUNT = 4;
public static Optional<String> pullRequestForReview(@NonNull List<PullRequest> pullRequestsReviews) {
if (!pullRequestsReviews.isEmpty()) {
return Optional.of(
pullRequestsReviews.stream()
.sorted(COMPARATOR)
.limit(PR_COUNT)
.map(MessageUtils::topPr)
.map(MessageUtils::generateStringItemPullRequestReview)
.collect(Collectors.joining("\n"))
);
}
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()) + " " +
link(pullRequest.getTitle(), pullRequest.getUrl()) +
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 org.sadtech.bot.vcs.core.domain.PullRequestStatus;
@ -24,7 +24,7 @@ import java.util.List;
*/
@Component
@RequiredArgsConstructor
public class PullRequestProcessing implements ProcessingData<Message> {
public class PullRequestReviewProcessing implements ProcessingData<Message> {
private final PersonService personService;
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 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.TaskProcessing;
import org.sadtech.bot.vcs.telegram.utils.GeneratorKeyBoards;
@ -44,7 +43,7 @@ public class UnitConfig {
@Bean
public AnswerText menu(
AnswerProcessing<Message> getTasks,
AnswerProcessing<Message> getPr,
AnswerText menuPullRequest,
AnswerText settings,
AnswerProcessing<Message> getTopRating
) {
@ -56,7 +55,7 @@ public class UnitConfig {
.build()
)
.nextUnit(getTasks)
.nextUnit(getPr)
.nextUnit(menuPullRequest)
.nextUnit(settings)
.nextUnit(getTopRating)
.build();
@ -90,16 +89,6 @@ public class UnitConfig {
.build();
}
@Bean
public AnswerProcessing<Message> getPr(
PullRequestProcessing pullRequestProcessing
) {
return AnswerProcessing.builder()
.processingData(pullRequestProcessing)
.phrase("Проверить ПР")
.build();
}
@Bean
AnswerProcessing<Message> getTopRating(
RatingTopProcessing ratingTopProcessing

View File

@ -16,7 +16,7 @@ public class GeneratorKeyBoards {
public static KeyBoard menu() {
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 settings = KeyBoardButtonText.builder().label("Настройки").build();