From 2739efff328cb9ed07cc6fa4af87c29dd6cc4489 Mon Sep 17 00:00:00 2001 From: Mark Struchkov Date: Mon, 10 Feb 2020 11:50:18 +0300 Subject: [PATCH] =?UTF-8?q?=D0=9F=D0=B5=D1=80=D0=B2=D0=B0=D1=8F=20=D1=80?= =?UTF-8?q?=D0=B0=D0=B1=D0=BE=D1=87=D0=B0=D1=8F=20=D0=B2=D0=B5=D1=80=D1=81?= =?UTF-8?q?=D0=B8=D1=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../bitbucketbot/bitbucket/FromRefJson.java | 15 ++ .../bitbucket/PullRequestJson.java | 1 + .../bitbucket/RepositoryJson.java | 15 ++ .../bitbucketbot/domain/ReviewerStatus.java | 13 +- .../domain/entity/PullRequest.java | 30 ++- .../bitbucketbot/domain/entity/Reviewer.java | 8 - .../domain/util/ReviewerChange.java | 57 ++++++ .../repository/PullRequestsRepository.java | 11 + .../scheduler/SchedulerPullRequest.java | 189 +++++++++++------- .../service/PullRequestsService.java | 18 +- .../converter/PullRequestJsonConverter.java | 9 +- .../service/impl/PullRequestsServiceImpl.java | 42 ++-- .../com/tsc/bitbucketbot/utils/Message.java | 88 ++++++++ src/main/resources/application.yaml | 4 +- .../liquibase/change-set/create-table.xml | 10 +- 15 files changed, 402 insertions(+), 108 deletions(-) create mode 100644 src/main/java/com/tsc/bitbucketbot/bitbucket/FromRefJson.java create mode 100644 src/main/java/com/tsc/bitbucketbot/bitbucket/RepositoryJson.java create mode 100644 src/main/java/com/tsc/bitbucketbot/domain/util/ReviewerChange.java create mode 100644 src/main/java/com/tsc/bitbucketbot/utils/Message.java diff --git a/src/main/java/com/tsc/bitbucketbot/bitbucket/FromRefJson.java b/src/main/java/com/tsc/bitbucketbot/bitbucket/FromRefJson.java new file mode 100644 index 0000000..100dc33 --- /dev/null +++ b/src/main/java/com/tsc/bitbucketbot/bitbucket/FromRefJson.java @@ -0,0 +1,15 @@ +package com.tsc.bitbucketbot.bitbucket; + +import lombok.Data; + +/** + * TODO: Добавить описание класса. + * + * @author upagge [04.02.2020] + */ +@Data +public class FromRefJson { + + private RepositoryJson repository; + +} diff --git a/src/main/java/com/tsc/bitbucketbot/bitbucket/PullRequestJson.java b/src/main/java/com/tsc/bitbucketbot/bitbucket/PullRequestJson.java index 69dc253..5798a65 100644 --- a/src/main/java/com/tsc/bitbucketbot/bitbucket/PullRequestJson.java +++ b/src/main/java/com/tsc/bitbucketbot/bitbucket/PullRequestJson.java @@ -20,5 +20,6 @@ public class PullRequestJson { private LinkJson links; private UserDecisionJson author; private List reviewers; + private FromRefJson fromRef; } diff --git a/src/main/java/com/tsc/bitbucketbot/bitbucket/RepositoryJson.java b/src/main/java/com/tsc/bitbucketbot/bitbucket/RepositoryJson.java new file mode 100644 index 0000000..1e2dc90 --- /dev/null +++ b/src/main/java/com/tsc/bitbucketbot/bitbucket/RepositoryJson.java @@ -0,0 +1,15 @@ +package com.tsc.bitbucketbot.bitbucket; + +import lombok.Data; + +/** + * TODO: Добавить описание класса. + * + * @author upagge [04.02.2020] + */ +@Data +public class RepositoryJson { + + private Long id; + +} diff --git a/src/main/java/com/tsc/bitbucketbot/domain/ReviewerStatus.java b/src/main/java/com/tsc/bitbucketbot/domain/ReviewerStatus.java index 42c1416..2031f0c 100644 --- a/src/main/java/com/tsc/bitbucketbot/domain/ReviewerStatus.java +++ b/src/main/java/com/tsc/bitbucketbot/domain/ReviewerStatus.java @@ -1,12 +1,23 @@ package com.tsc.bitbucketbot.domain; +import lombok.Getter; + /** * TODO: Добавить комментарий енума. * * @author upagge [01.02.2020] */ +@Getter public enum ReviewerStatus { - NEEDS_WORK, APPROVED, UNAPPROVED + NEEDS_WORK("'NEEDS WORK'"), + APPROVED("'APPROVED'"), + UNAPPROVED("'UNAPPROVED'"); + + private String value; + + ReviewerStatus(String value) { + this.value = value; + } } diff --git a/src/main/java/com/tsc/bitbucketbot/domain/entity/PullRequest.java b/src/main/java/com/tsc/bitbucketbot/domain/entity/PullRequest.java index 4923cf7..0ae7852 100644 --- a/src/main/java/com/tsc/bitbucketbot/domain/entity/PullRequest.java +++ b/src/main/java/com/tsc/bitbucketbot/domain/entity/PullRequest.java @@ -32,21 +32,29 @@ import java.util.List; @Setter @Entity @Builder -@NoArgsConstructor @AllArgsConstructor +@NoArgsConstructor @EqualsAndHashCode(of = "id") @ToString public class PullRequest { @Id @Column(name = "id") + @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; + @Column(name = "bitbucket_pr_id") + private Long bitbucketId; + + @Column(name = "repository_id") + private Long repositoryId; + @ManyToOne - @JoinColumn(name = "autor_login") + @JoinColumn(name = "author_login") private User author; - @OneToMany(mappedBy = "pullRequestId", cascade = CascadeType.ALL, fetch = FetchType.EAGER) + @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER, orphanRemoval = true) + @JoinColumn(name = "pull_request_id") private List reviewers; @Column(name = "url") @@ -59,4 +67,20 @@ public class PullRequest { @Column(name = "status") private PullRequestStatus status; +// public void setReviewers(List reviewers) { +// this.reviewers = reviewers; +// this.reviewers.forEach(reviewer -> reviewer.setPullRequest(this)); +// } +// +// public PullRequest(Long bitbucketId, Long repositoryId, User author, List reviewers, String url, String name, PullRequestStatus status) { +// this.bitbucketId = bitbucketId; +// this.repositoryId = repositoryId; +// this.author = author; +// this.reviewers = reviewers; +// this.url = url; +// this.name = name; +// this.status = status; +// this.reviewers.forEach(reviewer -> reviewer.setPullRequest(this)); +// } + } diff --git a/src/main/java/com/tsc/bitbucketbot/domain/entity/Reviewer.java b/src/main/java/com/tsc/bitbucketbot/domain/entity/Reviewer.java index c30e997..be3ea6c 100644 --- a/src/main/java/com/tsc/bitbucketbot/domain/entity/Reviewer.java +++ b/src/main/java/com/tsc/bitbucketbot/domain/entity/Reviewer.java @@ -35,13 +35,6 @@ public class Reviewer { @Column(name = "id") private Long id; - // @OneToMany(fetch = FetchType.LAZY) -// @JoinColumn(name = "pull_request_id") - @Column(name = "pull_request_id") - private Long pullRequestId; - - // @OneToMany(fetch = FetchType.LAZY) -// @JoinColumn(name = "user_login") @Column(name = "user_login") private String user; @@ -49,5 +42,4 @@ public class Reviewer { @Column(name = "status") private ReviewerStatus status; - } diff --git a/src/main/java/com/tsc/bitbucketbot/domain/util/ReviewerChange.java b/src/main/java/com/tsc/bitbucketbot/domain/util/ReviewerChange.java new file mode 100644 index 0000000..e5be195 --- /dev/null +++ b/src/main/java/com/tsc/bitbucketbot/domain/util/ReviewerChange.java @@ -0,0 +1,57 @@ +package com.tsc.bitbucketbot.domain.util; + +import com.tsc.bitbucketbot.domain.ReviewerStatus; +import lombok.Getter; +import lombok.NonNull; + +/** + * TODO: Добавить описание класса. + * + * @author upagge [07.02.2020] + */ +@Getter +public class ReviewerChange { + + private String name; + private Type type; + private ReviewerStatus status; + private ReviewerStatus oldStatus; + + private ReviewerChange(String name, Type type, ReviewerStatus status) { + this.name = name; + this.type = type; + this.status = status; + } + + private ReviewerChange(String name, Type type, ReviewerStatus status, ReviewerStatus oldStatus) { + this.name = name; + this.type = type; + this.status = status; + this.oldStatus = oldStatus; + } + + private ReviewerChange(String name, Type type) { + this.name = name; + this.type = type; + } + + @NonNull + public static ReviewerChange ofNew(String name, ReviewerStatus reviewerStatus) { + return new ReviewerChange(name, Type.NEW, reviewerStatus); + } + + @NonNull + public static ReviewerChange ofOld(String name, ReviewerStatus oldStatus, ReviewerStatus newStatus) { + return new ReviewerChange(name, Type.OLD, newStatus, oldStatus); + } + + @NonNull + public static ReviewerChange ofDeleted(String name) { + return new ReviewerChange(name, Type.DELETED); + } + + public enum Type { + NEW, DELETED, OLD + } + +} diff --git a/src/main/java/com/tsc/bitbucketbot/repository/PullRequestsRepository.java b/src/main/java/com/tsc/bitbucketbot/repository/PullRequestsRepository.java index c985301..ae6b326 100644 --- a/src/main/java/com/tsc/bitbucketbot/repository/PullRequestsRepository.java +++ b/src/main/java/com/tsc/bitbucketbot/repository/PullRequestsRepository.java @@ -2,7 +2,11 @@ package com.tsc.bitbucketbot.repository; import com.tsc.bitbucketbot.domain.entity.PullRequest; import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; +import java.util.Collection; +import java.util.Optional; import java.util.Set; /** @@ -14,4 +18,11 @@ public interface PullRequestsRepository extends JpaRepository Set findAllByIdIn(Set ids); + Boolean existsByBitbucketIdAndRepositoryId(Long bitbucketId, Long repositoryId); + + @Query("SELECT p.id FROM PullRequest p WHERE p.bitbucketId=:bitbucketId AND p.repositoryId=:repositoryId") + Optional findIdByBitbucketIdAndRepositoryId(@Param("bitbucketId") Long bitbucketId, @Param("repositoryId") Long repositoryId); + + void deleteAllByIdIn(Collection id); + } diff --git a/src/main/java/com/tsc/bitbucketbot/scheduler/SchedulerPullRequest.java b/src/main/java/com/tsc/bitbucketbot/scheduler/SchedulerPullRequest.java index 4295bd1..cf7b192 100644 --- a/src/main/java/com/tsc/bitbucketbot/scheduler/SchedulerPullRequest.java +++ b/src/main/java/com/tsc/bitbucketbot/scheduler/SchedulerPullRequest.java @@ -1,7 +1,6 @@ package com.tsc.bitbucketbot.scheduler; import com.tsc.bitbucketbot.bitbucket.PullRequestJson; -import com.tsc.bitbucketbot.bitbucket.UserDecisionJson; import com.tsc.bitbucketbot.bitbucket.sheet.PullRequestSheetJson; import com.tsc.bitbucketbot.config.BitbucketConfig; import com.tsc.bitbucketbot.domain.PullRequestStatus; @@ -9,10 +8,13 @@ import com.tsc.bitbucketbot.domain.ReviewerStatus; import com.tsc.bitbucketbot.domain.entity.PullRequest; import com.tsc.bitbucketbot.domain.entity.Reviewer; import com.tsc.bitbucketbot.domain.entity.User; +import com.tsc.bitbucketbot.domain.util.ReviewerChange; import com.tsc.bitbucketbot.service.PullRequestsService; import com.tsc.bitbucketbot.service.UserService; import com.tsc.bitbucketbot.service.Utils; import com.tsc.bitbucketbot.service.converter.PullRequestJsonConverter; +import com.tsc.bitbucketbot.utils.Message; +import javafx.util.Pair; import lombok.NonNull; import lombok.RequiredArgsConstructor; import org.sadtech.social.core.domain.BoxAnswer; @@ -21,9 +23,11 @@ import org.springframework.core.convert.ConversionService; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Service; +import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Objects; import java.util.Optional; import java.util.Set; import java.util.stream.Collectors; @@ -37,8 +41,8 @@ import java.util.stream.Collectors; @RequiredArgsConstructor public class SchedulerPullRequest { - private static final String URL_NEW_PR = "http://192.168.236.164:7990/rest/api/1.0/dashboard/pull-requests?limit=150&state=OPEN"; - private static final String URL_OLD_PR = "http://192.168.236.164:7990/rest/api/1.0/dashboard/pull-requests?limit=150&closedSince=86400"; + private static final String URL_OPEN_PR = "http://192.168.236.164:7990/rest/api/1.0/dashboard/pull-requests?limit=150&state=OPEN"; + private static final String URL_CLOSE_PR = "http://192.168.236.164:7990/rest/api/1.0/dashboard/pull-requests?limit=150&closedSince=86400"; private final BitbucketConfig bitbucketConfig; private final PullRequestsService pullRequestsService; private final UserService userService; @@ -46,34 +50,48 @@ public class SchedulerPullRequest { private final Sending sending; @Scheduled(fixedRate = 15000) - public void checkOldPullRequest() { + public void checkClosePullRequest() { final List users = userService.getAllRegistered(); for (User user : users) { - Optional sheetJson = Utils.urlToJson(URL_OLD_PR, user.getToken(), PullRequestSheetJson.class); + Optional sheetJson = Utils.urlToJson(URL_CLOSE_PR, user.getToken(), PullRequestSheetJson.class); while (sheetJson.isPresent() && sheetJson.get().getValues() != null && !sheetJson.get().getValues().isEmpty()) { final PullRequestSheetJson pullRequestBitbucketSheet = sheetJson.get(); - Set existsId = pullRequestsService.existsById( - pullRequestBitbucketSheet.getValues().stream() - .map(PullRequestJson::getId) - .collect(Collectors.toSet()) - ); - final Map existsPullRequestBitbucket = pullRequestBitbucketSheet.getValues().stream() - .filter(pullRequestJson -> existsId.contains(pullRequestJson.getId())) - .collect(Collectors.toMap(PullRequestJson::getId, pullRequestJson -> pullRequestJson)); - final Set pullRequests = pullRequestsService.getAllById(existsId); - if (!existsPullRequestBitbucket.isEmpty() && !pullRequests.isEmpty()) { - processingUpdate(existsPullRequestBitbucket, pullRequests); + final List bitbucketPullRequests = pullRequestBitbucketSheet.getValues().stream() + .filter( + pullRequestJson -> pullRequestsService.existsByBitbucketIdAndReposId( + pullRequestJson.getId(), + pullRequestJson.getFromRef().getRepository().getId() + ) + ) + .collect(Collectors.toList()); + final Set pullRequestId = bitbucketPullRequests.stream() + .map( + pullRequestJson -> pullRequestsService.getIdByBitbucketIdAndReposId( + pullRequestJson.getId(), + pullRequestJson.getFromRef().getRepository().getId() + ) + ) + .filter(Optional::isPresent) + .map(Optional::get) + .collect(Collectors.toSet()); + + for (PullRequestJson bitbucketPullRequest : bitbucketPullRequests) { + final Optional optUser = userService.getByLogin(bitbucketPullRequest.getAuthor().getUser().getName()); + if (optUser.isPresent()) { + final User author = optUser.get(); + final Long telegramId = author.getTelegramId(); + if (telegramId != null) { + final PullRequestStatus pullRequestStatus = PullRequestJsonConverter.convertPullRequestStatus(bitbucketPullRequest.getState()); + @NonNull final String message = Message.statusPullRequest(bitbucketPullRequest.getTitle(), bitbucketPullRequest.getLinks().getSelf().get(0).getHref(), PullRequestStatus.OPEN, pullRequestStatus); + sending.send(telegramId, BoxAnswer.of(message)); + } + } } - if (!existsPullRequestBitbucket.isEmpty()) { - pullRequestsService.updateAll( - existsPullRequestBitbucket.values().stream() - .map(pullRequestBitbucket -> conversionService.convert(pullRequestBitbucket, PullRequest.class)) - .collect(Collectors.toList()) - ); - } + pullRequestsService.deleteAll(pullRequestId); + if (pullRequestBitbucketSheet.getNextPageStart() != null) { - sheetJson = Utils.urlToJson(URL_OLD_PR + pullRequestBitbucketSheet.getNextPageStart(), bitbucketConfig.getToken(), PullRequestSheetJson.class); + sheetJson = Utils.urlToJson(URL_CLOSE_PR + pullRequestBitbucketSheet.getNextPageStart(), bitbucketConfig.getToken(), PullRequestSheetJson.class); } else { break; } @@ -81,76 +99,113 @@ public class SchedulerPullRequest { } } - private void processingUpdate(Map existsPullRequestBitbucket, Set pullRequests) { + @Scheduled(fixedRate = 15000) + public void checkOldPullRequest() { + final List users = userService.getAllRegistered(); + for (User user : users) { + Optional sheetJson = Utils.urlToJson(URL_OPEN_PR, user.getToken(), PullRequestSheetJson.class); + while (sheetJson.isPresent() && sheetJson.get().getValues() != null && !sheetJson.get().getValues().isEmpty()) { + final PullRequestSheetJson pullRequestBitbucketSheet = sheetJson.get(); + final Map existsPullRequestBitbucket = pullRequestBitbucketSheet.getValues().stream() + .filter( + pullRequestJson -> pullRequestsService.existsByBitbucketIdAndReposId( + pullRequestJson.getId(), + pullRequestJson.getFromRef().getRepository().getId() + ) + ) + .map(pullRequestJson -> conversionService.convert(pullRequestJson, PullRequest.class)) + .filter(Objects::nonNull) + .peek(pullRequest -> pullRequestsService.getIdByBitbucketIdAndReposId(pullRequest.getBitbucketId(), pullRequest.getRepositoryId()).ifPresent(pullRequest::setId)) + .collect(Collectors.toMap(PullRequest::getId, pullRequest -> pullRequest)); + final Set pullRequests = pullRequestsService.getAllById(existsPullRequestBitbucket.keySet()); + if (!existsPullRequestBitbucket.isEmpty() && !pullRequests.isEmpty()) { + pullRequestsService.updateAll(processingUpdate(existsPullRequestBitbucket, pullRequests)); + } + + if (pullRequestBitbucketSheet.getNextPageStart() != null) { + sheetJson = Utils.urlToJson(URL_CLOSE_PR + pullRequestBitbucketSheet.getNextPageStart(), bitbucketConfig.getToken(), PullRequestSheetJson.class); + } else { + break; + } + } + } + } + + @NonNull + private List processingUpdate(Map newPullRequests, Set pullRequests) { + List updatePullRequest = new ArrayList<>(); for (PullRequest pullRequest : pullRequests) { - final PullRequestJson pullRequestBitbucket = existsPullRequestBitbucket.get(pullRequest.getId()); + final PullRequest newPullRequest = newPullRequests.get(pullRequest.getId()); final User author = pullRequest.getAuthor(); + StringBuilder stringBuilder = new StringBuilder(); if (author.getTelegramId() != null) { - sendStatusPR(pullRequest, pullRequestBitbucket); - sendReviewersPR(pullRequest, pullRequestBitbucket); + changeStatusPR(pullRequest, newPullRequest).ifPresent(stringBuilder::append); + changeReviewersPR(pullRequest, newPullRequest).ifPresent(stringBuilder::append); + final String message = stringBuilder.toString(); + if (!Message.EMPTY.equalsIgnoreCase(message)) { + updatePullRequest.add(newPullRequest); + sending.send(author.getTelegramId(), BoxAnswer.of(message)); + } } } + return updatePullRequest; } - private void sendReviewersPR(PullRequest pullRequest, PullRequestJson pullRequestBitbucket) { - final Map oldReviewers = pullRequest.getReviewers().stream().collect(Collectors.toMap(Reviewer::getUser, reviewer -> reviewer)); - final List newReviewers = pullRequestBitbucket.getReviewers(); - for (UserDecisionJson newReviewer : newReviewers) { - if (oldReviewers.containsKey(newReviewer.getUser().getName())) { - final Reviewer oldReviewer = oldReviewers.get(newReviewer.getUser().getName()); + @NonNull + private Optional changeReviewersPR(PullRequest pullRequest, PullRequest newPullRequest) { + final Map oldReviewers = pullRequest.getReviewers().stream() + .collect(Collectors.toMap(Reviewer::getUser, reviewer -> reviewer)); + final Map newReviewers = newPullRequest.getReviewers().stream() + .collect(Collectors.toMap(Reviewer::getUser, reviewer -> reviewer)); + List reviewerChanges = new ArrayList<>(); + for (Reviewer newReviewer : newReviewers.values()) { + if (oldReviewers.containsKey(newReviewer.getUser())) { + final Reviewer oldReviewer = oldReviewers.get(newReviewer.getUser()); final ReviewerStatus oldStatus = oldReviewer.getStatus(); - final ReviewerStatus newStatus = PullRequestJsonConverter.convertStatusReviewer(newReviewer.getStatus()); - boolean flag = false; - StringBuilder stringBuilder = new StringBuilder("✏️ *Изменилось решение по вашему ПР*\n") - .append("[").append(pullRequest.getName()).append("](").append(pullRequest.getUrl()).append(")\n"); + final ReviewerStatus newStatus = newReviewer.getStatus(); if (!oldStatus.equals(newStatus)) { - flag = true; - stringBuilder.append("\uD83D\uDC68\u200D\uD83D\uDCBB️ ").append(oldReviewer.getUser()).append(" ") - .append(oldStatus).append(" -> ").append(newStatus).append("\n"); - } - if (flag) { - sending.send(pullRequest.getAuthor().getTelegramId(), BoxAnswer.of(stringBuilder.toString())); + reviewerChanges.add(ReviewerChange.ofOld(oldReviewer.getUser(), oldStatus, newStatus)); } + } else { + reviewerChanges.add(ReviewerChange.ofNew(newReviewer.getUser(), newReviewer.getStatus())); } } + final Set oldLogins = oldReviewers.keySet(); + oldLogins.removeAll(newReviewers.keySet()); + oldLogins.forEach(login -> reviewerChanges.add(ReviewerChange.ofDeleted(login))); + return Message.statusReviewers(pullRequest, reviewerChanges); } - private void sendStatusPR(PullRequest pullRequest, PullRequestJson pullRequestBitbucket) { + + @NonNull + private Optional changeStatusPR(PullRequest pullRequest, PullRequest newPullRequest) { final PullRequestStatus oldStatus = pullRequest.getStatus(); - final PullRequestStatus newStatus = PullRequestJsonConverter.convertPullRequestStatus(pullRequestBitbucket.getState()); + final PullRequestStatus newStatus = newPullRequest.getStatus(); if (!oldStatus.equals(newStatus)) { - StringBuilder stringBuilder = new StringBuilder("✏️ *Изменился статус вашего ПР*\n") - .append("[").append(pullRequest.getName()).append("](").append(pullRequest.getUrl()).append(")\n") - .append(oldStatus.name()).append(" -> ").append(newStatus.name()) - .append("\n-- -- -- --\n") - .append("\uD83D\uDCCC: #pullRequest #change") - .append("\n\n"); - sending.send(pullRequest.getAuthor().getTelegramId(), BoxAnswer.of(stringBuilder.toString())); + return Optional.of(Message.statusPullRequest(pullRequest.getName(), pullRequest.getUrl(), oldStatus, newStatus)); } + return Optional.empty(); } + @Scheduled(fixedRate = 15000) public void checkNewPullRequest() { final List users = userService.getAllRegistered(); for (User user : users) { - Optional sheetJson = Utils.urlToJson(URL_NEW_PR, user.getToken(), PullRequestSheetJson.class); + Optional sheetJson = Utils.urlToJson(URL_OPEN_PR, user.getToken(), PullRequestSheetJson.class); while (sheetJson.isPresent() && sheetJson.get().getValues() != null && !sheetJson.get().getValues().isEmpty()) { final PullRequestSheetJson pullRequestBitbucketSheet = sheetJson.get(); - final Set pullRequestBitbucketId = pullRequestBitbucketSheet.getValues().stream() - .map(PullRequestJson::getId) - .collect(Collectors.toSet()); - Set existsId = pullRequestsService.existsAllIdById(pullRequestBitbucketId); - final Set newPullRequestBitbucket = pullRequestBitbucketSheet.getValues().stream() - .filter(pullRequestJson -> !existsId.contains(pullRequestJson.getId())) - .collect(Collectors.toSet()); - final List newPullRequests = pullRequestsService.addAll( - newPullRequestBitbucket.stream() - .map(pullRequestJson -> conversionService.convert(pullRequestJson, PullRequest.class)) - .collect(Collectors.toSet()) - ); + final List newPullRequest = pullRequestBitbucketSheet.getValues().stream() + .collect(Collectors.toMap(pullRequestJson -> new Pair<>(pullRequestJson.getId(), pullRequestJson.getFromRef().getRepository().getId()), pullRequestJson -> pullRequestJson)) + .entrySet() + .stream() + .filter(test -> !pullRequestsService.existsByBitbucketIdAndReposId(test.getKey().getKey(), test.getKey().getValue())) + .map(test -> conversionService.convert(test.getValue(), PullRequest.class)) + .collect(Collectors.toList()); + final List newPullRequests = pullRequestsService.addAll(newPullRequest); sendNotification(newPullRequests); if (pullRequestBitbucketSheet.getNextPageStart() != null) { - sheetJson = Utils.urlToJson(URL_NEW_PR + pullRequestBitbucketSheet.getNextPageStart(), bitbucketConfig.getToken(), PullRequestSheetJson.class); + sheetJson = Utils.urlToJson(URL_OPEN_PR + pullRequestBitbucketSheet.getNextPageStart(), bitbucketConfig.getToken(), PullRequestSheetJson.class); } else { break; } diff --git a/src/main/java/com/tsc/bitbucketbot/service/PullRequestsService.java b/src/main/java/com/tsc/bitbucketbot/service/PullRequestsService.java index c89fcc4..243e9fa 100644 --- a/src/main/java/com/tsc/bitbucketbot/service/PullRequestsService.java +++ b/src/main/java/com/tsc/bitbucketbot/service/PullRequestsService.java @@ -1,9 +1,9 @@ package com.tsc.bitbucketbot.service; import com.tsc.bitbucketbot.domain.entity.PullRequest; -import com.tsc.bitbucketbot.domain.entity.Reviewer; import lombok.NonNull; +import java.util.Collection; import java.util.List; import java.util.Optional; import java.util.Set; @@ -15,14 +15,20 @@ import java.util.Set; */ public interface PullRequestsService { - Set existsById(@NonNull final Set pullRequestId); - - Set existsAllIdById(@NonNull Set pullRequestId); + @NonNull + boolean existsByBitbucketIdAndReposId(Long bitbucketId, Long repositoryId); Set getAllById(@NonNull Set pullRequestJsonId); - List addAll(@NonNull Set pullRequests); + List addAll(@NonNull Collection pullRequests); - List updateAll(@NonNull List pullRequests); + List updateAll(@NonNull Collection pullRequests); + + @NonNull + Optional getIdByBitbucketIdAndReposId(Long bitbucketId, Long repositoryId); + + void deleteAll(@NonNull Set id); + + Optional update(PullRequest pullRequest); } diff --git a/src/main/java/com/tsc/bitbucketbot/service/converter/PullRequestJsonConverter.java b/src/main/java/com/tsc/bitbucketbot/service/converter/PullRequestJsonConverter.java index 11b52c8..a19d98e 100644 --- a/src/main/java/com/tsc/bitbucketbot/service/converter/PullRequestJsonConverter.java +++ b/src/main/java/com/tsc/bitbucketbot/service/converter/PullRequestJsonConverter.java @@ -33,12 +33,13 @@ public class PullRequestJsonConverter implements Converter convertReviewers(Long id, List jsonReviewers) { + private List convertReviewers(List jsonReviewers) { return jsonReviewers.stream() .map( jsonReviewer -> { final Reviewer reviewer = new Reviewer(); - reviewer.setPullRequestId(id); reviewer.setUser(jsonReviewer.getUser().getName()); reviewer.setStatus(convertStatusReviewer(jsonReviewer.getStatus())); return reviewer; @@ -85,5 +85,4 @@ public class PullRequestJsonConverter implements Converter existsById(@NonNull Set idList) { - return idList.stream() - .filter(pullRequestsRepository::existsById) - .collect(Collectors.toSet()); - } - - @Override - public Set existsAllIdById(@NonNull Set pullRequestJsonId) { - return pullRequestJsonId.stream().filter(pullRequestsRepository::existsById).collect(Collectors.toSet()); + public boolean existsByBitbucketIdAndReposId(@NonNull Long bitbucketId, @NonNull Long repositoryId) { + return pullRequestsRepository.existsByBitbucketIdAndRepositoryId(bitbucketId, repositoryId); } @Override @@ -43,13 +36,36 @@ public class PullRequestsServiceImpl implements PullRequestsService { } @Override - public List addAll(@NonNull Set pullRequests) { + @Transactional + public List addAll(@NonNull Collection pullRequests) { return pullRequestsRepository.saveAll(pullRequests); } @Override - public List updateAll(@NonNull List pullRequests) { - return pullRequestsRepository.saveAll(pullRequests); + public List updateAll(@NonNull Collection pullRequests) { + final List updatePullRequests = pullRequests.stream() + .filter(pullRequest -> pullRequestsRepository.existsById(pullRequest.getId())) + .collect(Collectors.toList()); + return pullRequestsRepository.saveAll(updatePullRequests); + } + + @Override + public Optional update(PullRequest pullRequest) { + if (pullRequestsRepository.existsById(pullRequest.getId())) { + pullRequestsRepository.save(pullRequest); + } + return Optional.empty(); + } + + @Override + public Optional getIdByBitbucketIdAndReposId(@NonNull Long bitbucketId, @NonNull Long repositoryId) { + return pullRequestsRepository.findIdByBitbucketIdAndRepositoryId(bitbucketId, repositoryId); + } + + @Override + @Transactional + public void deleteAll(@NonNull Set id) { + pullRequestsRepository.deleteAllByIdIn(id); } } diff --git a/src/main/java/com/tsc/bitbucketbot/utils/Message.java b/src/main/java/com/tsc/bitbucketbot/utils/Message.java new file mode 100644 index 0000000..8f671e7 --- /dev/null +++ b/src/main/java/com/tsc/bitbucketbot/utils/Message.java @@ -0,0 +1,88 @@ +package com.tsc.bitbucketbot.utils; + +import com.tsc.bitbucketbot.domain.PullRequestStatus; +import com.tsc.bitbucketbot.domain.entity.PullRequest; +import com.tsc.bitbucketbot.domain.util.ReviewerChange; +import lombok.NonNull; + +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.stream.Collectors; + +import static com.tsc.bitbucketbot.domain.util.ReviewerChange.Type.DELETED; +import static com.tsc.bitbucketbot.domain.util.ReviewerChange.Type.NEW; +import static com.tsc.bitbucketbot.domain.util.ReviewerChange.Type.OLD; + +/** + * TODO: Добавить описание класса. + * + * @author upagge [07.02.2020] + */ +public class Message { + + public static final String EMPTY = ""; + private static final String BREAK = "\n"; + private static final String TWO_BREAK = "\n\n"; + private static final String SMILE_AUTHOR = "\uD83D\uDC68\u200D\uD83D\uDCBB️"; + private static final String SMILE_PEN = "✏️"; + + private Message() { + throw new IllegalStateException("Утилитарный класс"); + } + + @NonNull + public static String statusPullRequest(String name, String url, PullRequestStatus oldStatus, PullRequestStatus newStatus) { + return "✏️ *Изменился статус вашего ПР*" + BREAK + + "[" + name + "](" + url + ")" + BREAK + + oldStatus.name() + " -> " + newStatus.name() + + BREAK + "-- -- -- --" + BREAK + + "\uD83D\uDCCC: #pullRequest #change" + + TWO_BREAK; + } + + @NonNull + public static Optional statusReviewers(PullRequest pullRequest, List reviewerChanges) { + StringBuilder stringBuilder = new StringBuilder(); + final Map> changes = reviewerChanges.stream() + .collect(Collectors.groupingBy(ReviewerChange::getType)); + if (changes.containsKey(OLD)) { + stringBuilder.append(BREAK).append("Изменили свое решение:").append(BREAK); + changes.get(OLD).forEach( + change -> stringBuilder + .append(SMILE_AUTHOR).append(change.getName()).append(": ") + .append(change.getOldStatus().getValue()).append(" -> ") + .append(change.getStatus().getValue()) + .append(BREAK) + ); + } + if (changes.containsKey(NEW)) { + stringBuilder.append(BREAK).append("Новые ревьюверы:").append(BREAK); + changes.get(NEW).forEach( + change -> stringBuilder + .append(change.getName()).append(" (").append(change.getStatus().getValue()).append(")") + .append(BREAK) + ); + } + if (changes.containsKey(DELETED)) { + stringBuilder.append(BREAK).append("Не выдержали ревью:").append(BREAK) + .append( + changes.get(DELETED).stream() + .map(ReviewerChange::getName).collect(Collectors.joining(",")) + ); + } + + final String createMessage = stringBuilder.toString(); + if (!EMPTY.equalsIgnoreCase(createMessage)) { + return Optional.of( + SMILE_PEN + " *Изменения ревьюверов вашего ПР*" + BREAK + + "[" + pullRequest.getName() + "](" + pullRequest.getUrl() + ")" + BREAK + + createMessage + + "\n-- -- -- -- --" + ); + } + return Optional.empty(); + } + + +} diff --git a/src/main/resources/application.yaml b/src/main/resources/application.yaml index bee6a93..2895b9c 100644 --- a/src/main/resources/application.yaml +++ b/src/main/resources/application.yaml @@ -22,9 +22,11 @@ bitbucketbot: bot-token: 1096235968:AAHvIy_mlZJXiNc9aDQWtCuiksz9YGknoXE admin-chatid: 3000811 proxy-config: - host: 167.172.171.134 + host: 212.237.23.75 port: 1080 type: SOCKS5 + user: upagge + password: seAbotd9Bidu%ZqZB3g4 bitbucket: token: Nzg5NjUyNDQwMzk2OlA+6naQz02+GxOG0Q9li/jnsn7E url: http://192.168.236.164:7990/rest/api/1.0/dashboard/pull-requests?limit=50 diff --git a/src/main/resources/liquibase/change-set/create-table.xml b/src/main/resources/liquibase/change-set/create-table.xml index 845bd95..77b7d35 100644 --- a/src/main/resources/liquibase/change-set/create-table.xml +++ b/src/main/resources/liquibase/change-set/create-table.xml @@ -18,10 +18,12 @@ - + - + + + @@ -34,13 +36,14 @@ + - + - \ No newline at end of file