├── .drone.yml ├── .gitattributes ├── .github └── FUNDING.yml ├── .gitignore ├── Dockerfile ├── Dockerfile-develop ├── LICENSE ├── README.md ├── bot-context ├── pom.xml └── src │ └── main │ └── java │ └── dev │ └── struchkov │ └── bot │ └── gitlab │ └── context │ ├── domain │ ├── Answer.java │ ├── AssigneeChanged.java │ ├── ExistContainer.java │ ├── IdAndStatusPr.java │ ├── MergeRequestState.java │ ├── MessageSend.java │ ├── PersonInformation.java │ ├── PipelineStatus.java │ ├── ReviewerChanged.java │ ├── entity │ │ ├── AppSetting.java │ │ ├── Discussion.java │ │ ├── MergeRequest.java │ │ ├── MergeRequestForDiscussion.java │ │ ├── Note.java │ │ ├── Person.java │ │ ├── Pipeline.java │ │ └── Project.java │ ├── filter │ │ ├── MergeRequestFilter.java │ │ └── PipelineFilter.java │ └── notify │ │ ├── Notify.java │ │ ├── comment │ │ └── NewCommentNotify.java │ │ ├── level │ │ └── DiscussionLevel.java │ │ ├── mergerequest │ │ ├── ConflictMrNotify.java │ │ ├── ConflictResolveMrNotify.java │ │ ├── MrNotify.java │ │ ├── NewMrForAssignee.java │ │ ├── NewMrForReview.java │ │ ├── NewMrNotify.java │ │ ├── StatusMrNotify.java │ │ └── UpdateMrNotify.java │ │ ├── pipeline │ │ └── PipelineNotify.java │ │ ├── project │ │ └── NewProjectNotify.java │ │ └── task │ │ ├── DiscussionNewNotify.java │ │ ├── ThreadCloseNotify.java │ │ └── ThreadNotify.java │ ├── repository │ ├── AppSettingRepository.java │ ├── DiscussionRepository.java │ ├── MergeRequestRepository.java │ ├── NoteRepository.java │ ├── PersonRepository.java │ ├── PipelineRepository.java │ └── ProjectRepository.java │ ├── service │ ├── AppSettingService.java │ ├── DiscussionService.java │ ├── MergeRequestsService.java │ ├── MessageSendService.java │ ├── NoteService.java │ ├── NotifyService.java │ ├── PersonService.java │ ├── PipelineService.java │ └── ProjectService.java │ └── utils │ └── Icons.java ├── bot-core ├── pom.xml └── src │ └── main │ └── java │ └── dev │ └── struchkov │ └── bot │ └── gitlab │ └── core │ ├── config │ ├── CoreConfig.java │ └── properties │ │ ├── AppProperty.java │ │ ├── GitlabProperty.java │ │ └── PersonProperty.java │ ├── service │ ├── convert │ │ ├── DiscussionJsonConverter.java │ │ ├── MergeRequestJsonConverter.java │ │ ├── NoteJsonConvert.java │ │ ├── PersonJsonConverter.java │ │ ├── PipelineJsonConverter.java │ │ └── ProjectJsonConverter.java │ ├── impl │ │ ├── AppSettingServiceImpl.java │ │ ├── DiscussionServiceImpl.java │ │ ├── MergeRequestsServiceImpl.java │ │ ├── NotifyServiceImpl.java │ │ ├── PersonServiceImpl.java │ │ ├── PipelineServiceImpl.java │ │ ├── ProjectServiceImpl.java │ │ └── note │ │ │ └── NoteServiceImpl.java │ └── parser │ │ ├── DiscussionParser.java │ │ ├── MergeRequestParser.java │ │ ├── PipelineParser.java │ │ ├── ProjectParser.java │ │ └── forktask │ │ ├── GetAllDiscussionForMergeRequestTask.java │ │ ├── GetAllMergeRequestForProjectTask.java │ │ ├── GetPipelineShortTask.java │ │ ├── GetPipelineTask.java │ │ └── GetSingleMergeRequestTask.java │ └── utils │ ├── HttpHeader.java │ ├── HttpParse.java │ ├── OkHttpUtil.java │ └── StringUtils.java ├── bot-data ├── pom.xml └── src │ └── main │ └── java │ └── dev │ └── struchkov │ └── bot │ └── gitlab │ └── data │ ├── impl │ ├── AppSettingRepositoryImpl.java │ ├── DiscussionRepositoryImpl.java │ ├── MergeRequestRepositoryImpl.java │ ├── NoteRepositoryImpl.java │ ├── PersonRepositoryImpl.java │ ├── PipelineRepositoryImpl.java │ └── ProjectRepositoryImpl.java │ └── jpa │ ├── AppSettingJpaRepository.java │ ├── DiscussionJpaRepository.java │ ├── MergeRequestForDiscussionJpaRepository.java │ ├── MergeRequestJpaRepository.java │ ├── NoteJpaRepository.java │ ├── PersonJpaRepository.java │ ├── PipelineJpaRepository.java │ └── ProjectJpaRepository.java ├── documentation └── ru │ ├── .cache │ └── plugin │ │ └── optimize │ │ └── images │ │ └── assets │ │ └── images │ │ └── favicon.png │ ├── assets │ └── images │ │ └── favicon.png │ ├── docs │ ├── architecture │ │ ├── concept.md │ │ └── img │ │ │ └── schema-database.png │ ├── changelog │ │ └── index.md │ ├── features │ │ ├── img │ │ │ ├── gitlab-thread-answer.png │ │ │ ├── notify-conflict-mr.png │ │ │ ├── notify-new-comment-in-thread-without-context.png │ │ │ ├── notify-new-comment-in-thread.png │ │ │ ├── notify-new-mr.png │ │ │ ├── notify-new-pipeline.png │ │ │ ├── notify-new-project.png │ │ │ ├── notify-new-thread-without-context.png │ │ │ ├── notify-new-thread.png │ │ │ ├── notify-update-mr.png │ │ │ ├── notify-update-status-mr.png │ │ │ └── telegram-thread-answer.png │ │ ├── interaction-bot.md │ │ ├── interaction-gitlab.md │ │ └── notify.md │ ├── getting-started │ │ ├── configuration.md │ │ ├── create-gitlab-token.md │ │ ├── creating-telegram-bot.md │ │ ├── first-start.md │ │ └── mp4 │ │ │ ├── create-telegram-bot.mp4 │ │ │ └── init-start.mp4 │ ├── index.md │ ├── privacy │ │ ├── index.md │ │ └── unauth-access.png │ ├── stylesheets │ │ └── extra.css │ └── support-development │ │ └── index.md │ ├── includes │ └── abbreviations.md │ ├── mkdocs.yml │ └── overrides │ ├── main.html │ └── partials │ ├── comments.html │ └── integrations │ └── analytics │ └── custom.html ├── gitlab-app ├── pom.xml └── src │ └── main │ ├── java │ └── dev │ │ └── struchkov │ │ └── bot │ │ └── gitlab │ │ ├── GitLabBotApplication.java │ │ ├── config │ │ └── AppConfig.java │ │ └── scheduler │ │ └── SchedulerService.java │ └── resources │ ├── application.yml │ ├── banner.txt │ └── liquibase │ ├── changelog.xml │ └── v.1.0.0 │ ├── 2022-12-03-create-tables.xml │ ├── 2022-12-03-insert.xml │ └── changelog.xml ├── gitlab-sdk ├── pom.xml └── src │ └── main │ └── java │ └── dev │ └── struchkov │ └── bot │ └── gitlab │ └── sdk │ └── domain │ ├── CommitJson.java │ ├── DiscussionJson.java │ ├── MergeRequestJson.java │ ├── MergeRequestStateJson.java │ ├── NoteJson.java │ ├── PersonJson.java │ ├── PipelineJson.java │ ├── PipelineShortJson.java │ ├── PipelineStatusJson.java │ ├── ProjectJson.java │ └── UserJson.java ├── pom.xml └── telegram-bot ├── pom.xml └── src └── main └── java └── dev └── struchkov └── bot └── gitlab └── telegram ├── config └── AdditionalConfig.java ├── service ├── ErrorHandlerService.java ├── MessageSendTelegramService.java ├── ReplaceUrlLocalhost.java ├── StartNotify.java └── notify │ ├── ConflictPrNotifyGenerator.java │ ├── ConflictResolvePrNotifyGenerator.java │ ├── NewCommentNotifyGenerator.java │ ├── NewMrForAssigneeNotifyGenerator.java │ ├── NewMrForReviewNotifyGenerator.java │ ├── NewProjectNotifyGenerator.java │ ├── NewThreadNotifyGenerator.java │ ├── NotifyBoxAnswerGenerator.java │ ├── PipelineNotifyGenerator.java │ ├── StatusMrNotifyGenerator.java │ ├── ThreadCloseNotifyGenerate.java │ └── UpdateMrNotifyGenerator.java ├── unit ├── LinkService.java ├── MenuConfig.java ├── command │ ├── AnswerNoteUnit.java │ ├── DeleteMessageUnit.java │ ├── DisableNotifyMrUnit.java │ ├── DisableNotifyThreadUnit.java │ └── EnableProjectNotify.java └── flow │ └── InitSettingFlow.java └── utils ├── Const.java ├── Keys.java └── UnitName.java /.gitattributes: -------------------------------------------------------------------------------- 1 | *.mp4 filter=lfs diff=lfs merge=lfs -text 2 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | custom: ["https://docs.struchkov.dev/gitlab-notification/ru/latest/support-development/"] 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | HELP.md 2 | target/ 3 | !.mvn/wrapper/maven-wrapper.jar 4 | !**/src/main/** 5 | !**/src/test/** 6 | 7 | ### STS ### 8 | .apt_generated 9 | .classpath 10 | .factorypath 11 | .project 12 | .settings 13 | .springBeans 14 | .sts4-cache 15 | 16 | ### IntelliJ IDEA ### 17 | .idea 18 | *.iws 19 | *.iml 20 | *.ipr 21 | 22 | ### NetBeans ### 23 | /nbproject/private/ 24 | /nbbuild/ 25 | /dist/ 26 | /nbdist/ 27 | /.nb-gradle/ 28 | build/ 29 | 30 | ### VS Code ### 31 | .vscode/ 32 | /.mvn/wrapper/ 33 | /mvnw 34 | /mvnw.cmd 35 | /documentation/site/ 36 | /documentation/.cache/ 37 | /documentation/ru/site/ 38 | /documentation/ru/.cache/ 39 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM eclipse-temurin:17 as app-build 2 | ENV RELEASE=17 3 | 4 | WORKDIR /opt/build 5 | COPY ./gitlab-app/target/gitlab-notification.jar ./application.jar 6 | 7 | RUN java -Djarmode=layertools -jar application.jar extract 8 | RUN $JAVA_HOME/bin/jlink \ 9 | --add-modules `jdeps --ignore-missing-deps -q -recursive --multi-release ${RELEASE} --print-module-deps -cp 'dependencies/BOOT-INF/lib/*' application.jar`,jdk.crypto.cryptoki \ 10 | --strip-java-debug-attributes \ 11 | --no-man-pages \ 12 | --no-header-files \ 13 | --compress=2 \ 14 | --output jdk 15 | 16 | FROM debian:buster-slim 17 | 18 | ARG BUILD_PATH=/opt/build 19 | ENV JAVA_HOME=/opt/jdk 20 | ENV PATH "${JAVA_HOME}/bin:${PATH}" 21 | 22 | RUN apt update && groupadd --gid 1000 spring-app \ 23 | && useradd --uid 1000 --gid spring-app --shell /bin/bash --create-home spring-app 24 | 25 | USER spring-app:spring-app 26 | WORKDIR /opt/workspace 27 | 28 | COPY --from=app-build $BUILD_PATH/jdk $JAVA_HOME 29 | COPY --from=app-build $BUILD_PATH/spring-boot-loader/ ./ 30 | COPY --from=app-build $BUILD_PATH/dependencies/ ./ 31 | COPY --from=app-build $BUILD_PATH/application/ ./ 32 | 33 | ENTRYPOINT ["java", "-Dfile.encoding=UTF8", "-Dconsole.encoding=UTF8", "org.springframework.boot.loader.JarLauncher"] -------------------------------------------------------------------------------- /Dockerfile-develop: -------------------------------------------------------------------------------- 1 | FROM eclipse-temurin:17 as app-build 2 | ENV RELEASE=17 3 | 4 | WORKDIR /opt/build 5 | COPY ./gitlab-app/target/gitlab-notification.jar ./application.jar 6 | 7 | RUN java -Djarmode=layertools -jar application.jar extract 8 | RUN $JAVA_HOME/bin/jlink \ 9 | --add-modules `jdeps --ignore-missing-deps -q -recursive --multi-release ${RELEASE} --print-module-deps -cp 'dependencies/BOOT-INF/lib/*':'snapshot-dependencies/BOOT-INF/lib/*' application.jar`,jdk.crypto.cryptoki \ 10 | --strip-java-debug-attributes \ 11 | --no-man-pages \ 12 | --no-header-files \ 13 | --compress=2 \ 14 | --output jdk 15 | 16 | FROM debian:buster-slim 17 | 18 | ARG BUILD_PATH=/opt/build 19 | ENV JAVA_HOME=/opt/jdk 20 | ENV PATH "${JAVA_HOME}/bin:${PATH}" 21 | 22 | RUN apt update && groupadd --gid 1000 spring-app \ 23 | && useradd --uid 1000 --gid spring-app --shell /bin/bash --create-home spring-app 24 | 25 | USER spring-app:spring-app 26 | WORKDIR /opt/workspace 27 | 28 | COPY --from=app-build $BUILD_PATH/jdk $JAVA_HOME 29 | COPY --from=app-build $BUILD_PATH/spring-boot-loader/ ./ 30 | COPY --from=app-build $BUILD_PATH/dependencies/ ./ 31 | COPY --from=app-build $BUILD_PATH/snapshot-dependencies/ ./ 32 | COPY --from=app-build $BUILD_PATH/application/ ./ 33 | 34 | ENTRYPOINT ["java", "-Dfile.encoding=UTF8", "-Dconsole.encoding=UTF8", "org.springframework.boot.loader.JarLauncher"] -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Уведомления GitLab в Telegram 2 | 3 | > Документация по проекту, с описанием возможностей: https://docs.struchkov.dev/gitlab-notification 4 | > 5 | > Канал в Telegram, в который публикуется информация о разработке: https://t.me/gitlab_notification 6 | 7 | Запустите своего личного GitLab бота и получайте персональные уведомления из GitLab прямо на свой аккаунт в Telegram! Это не облачное решение, бот запускается на вашей машине или вашем сервере. 8 | 9 | Вы больше никогда не пропустите важное уведомление. Будь то новый запрос на слияние или возникновение конфликта. Больше не нужно заходить в GitLab, чтобы проверить статус сборки - с нашим приложением вы сможете оставаться в курсе дел, где бы вы ни находились. 10 | 11 | Бота легко настроить и использовать, а быстрые действия призваны оптимизировать ваш рабочий процесс. Не ждите больше - запустите своего персонального Telegram бота, и получайте персональные уведомления о событиях в GitLab. 12 | 13 | ## Основные возможности 14 | 15 | 1. Уведомление о новых Merge Request. 16 | 2. Уведомление о возникновении конфликта в MergeRequest. 17 | 3. Уведомление о результате сборки. 18 | 4. Уведомление в тредах. 19 | 5. И многое, многое другое 20 | 21 | ## Как запустить? 22 | 23 | Я серьезно, все подробно описано в [соответствующем разделе документации.](https://docs.struchkov.dev/gitlab-notification/ru/latest/getting-started/configuration/) -------------------------------------------------------------------------------- /bot-context/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4.0.0 4 | 5 | dev.struchkov.bot.gitlab 6 | gitlab-bot 7 | 1.0.0 8 | 9 | 10 | bot-context 11 | 12 | 13 | 14 | dev.struchkov.haiti.utils 15 | haiti-utils-field-constants 16 | 17 | 18 | 19 | org.springframework.data 20 | spring-data-jpa 21 | 22 | 23 | 24 | org.projectlombok 25 | lombok 26 | 27 | 28 | 29 | dev.struchkov.haiti 30 | haiti-utils 31 | 32 | 33 | 34 | dev.struchkov.haiti.filter 35 | haiti-filter-criteria 36 | 37 | 38 | 39 | jakarta.persistence 40 | jakarta.persistence-api 41 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /bot-context/src/main/java/dev/struchkov/bot/gitlab/context/domain/Answer.java: -------------------------------------------------------------------------------- 1 | package dev.struchkov.bot.gitlab.context.domain; 2 | 3 | import lombok.AccessLevel; 4 | import lombok.Getter; 5 | import lombok.NonNull; 6 | import lombok.RequiredArgsConstructor; 7 | 8 | @Getter 9 | @RequiredArgsConstructor(access = AccessLevel.PRIVATE) 10 | public class Answer { 11 | 12 | private final String authorName; 13 | private final String message; 14 | 15 | public static Answer of(@NonNull String name, @NonNull String message) { 16 | return new Answer(name, message); 17 | } 18 | 19 | } 20 | -------------------------------------------------------------------------------- /bot-context/src/main/java/dev/struchkov/bot/gitlab/context/domain/AssigneeChanged.java: -------------------------------------------------------------------------------- 1 | package dev.struchkov.bot.gitlab.context.domain; 2 | 3 | import dev.struchkov.bot.gitlab.context.domain.entity.Person; 4 | import lombok.Getter; 5 | import lombok.RequiredArgsConstructor; 6 | 7 | import static dev.struchkov.haiti.utils.Checker.checkNotNull; 8 | import static dev.struchkov.haiti.utils.Checker.checkNull; 9 | 10 | @Getter 11 | @RequiredArgsConstructor 12 | public enum AssigneeChanged { 13 | 14 | BECOME(true), 15 | DELETED(true), 16 | NOT_AFFECT_USER(true), 17 | NOT_CHANGED(false); 18 | 19 | private final boolean changed; 20 | 21 | public static AssigneeChanged valueOf(Long gitlabUserId, Person oldAssignee, Person newAssignee) { 22 | if (checkNull(oldAssignee) && checkNotNull(newAssignee) && gitlabUserId.equals(newAssignee.getId())) { 23 | return AssigneeChanged.BECOME; 24 | } 25 | if (checkNotNull(oldAssignee) && checkNull(newAssignee) && gitlabUserId.equals(oldAssignee.getId())) { 26 | return AssigneeChanged.DELETED; 27 | } 28 | if (checkNotNull(oldAssignee) && checkNotNull(newAssignee) && !oldAssignee.getId().equals(newAssignee.getId())) { 29 | if (gitlabUserId.equals(oldAssignee.getId())) { 30 | return AssigneeChanged.DELETED; 31 | } 32 | if (gitlabUserId.equals(newAssignee.getId())) { 33 | return AssigneeChanged.BECOME; 34 | } 35 | return AssigneeChanged.NOT_AFFECT_USER; 36 | } 37 | return AssigneeChanged.NOT_CHANGED; 38 | } 39 | 40 | public boolean getNewStatus(boolean oldStatus) { 41 | return switch (this) { 42 | case BECOME -> true; 43 | case DELETED -> false; 44 | case NOT_CHANGED, NOT_AFFECT_USER -> oldStatus; 45 | }; 46 | } 47 | 48 | } -------------------------------------------------------------------------------- /bot-context/src/main/java/dev/struchkov/bot/gitlab/context/domain/ExistContainer.java: -------------------------------------------------------------------------------- 1 | package dev.struchkov.bot.gitlab.context.domain; 2 | 3 | import lombok.NonNull; 4 | 5 | import java.util.Collections; 6 | import java.util.List; 7 | import java.util.Set; 8 | 9 | public class ExistContainer { 10 | 11 | protected final List container; 12 | protected final boolean allFound; 13 | protected final Set idNoFound; 14 | 15 | protected ExistContainer(List container, boolean allFound, Set idNoFound) { 16 | this.container = container; 17 | this.allFound = allFound; 18 | this.idNoFound = idNoFound; 19 | } 20 | 21 | public static ExistContainer allFind(@NonNull List container) { 22 | return new ExistContainer<>(container, true, Collections.emptySet()); 23 | } 24 | 25 | public static ExistContainer notAllFind(@NonNull List container, @NonNull Set idNoFound) { 26 | return new ExistContainer<>(container, false, idNoFound); 27 | } 28 | 29 | public List getContainer() { 30 | return container; 31 | } 32 | 33 | public boolean isAllFound() { 34 | return allFound; 35 | } 36 | 37 | public Set getIdNoFound() { 38 | return idNoFound; 39 | } 40 | 41 | } 42 | -------------------------------------------------------------------------------- /bot-context/src/main/java/dev/struchkov/bot/gitlab/context/domain/IdAndStatusPr.java: -------------------------------------------------------------------------------- 1 | package dev.struchkov.bot.gitlab.context.domain; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Getter; 5 | import lombok.Setter; 6 | 7 | @Setter 8 | @Getter 9 | @AllArgsConstructor 10 | public class IdAndStatusPr { 11 | 12 | private Long id; 13 | private Long twoId; 14 | private Long projectId; 15 | private MergeRequestState status; 16 | 17 | } 18 | -------------------------------------------------------------------------------- /bot-context/src/main/java/dev/struchkov/bot/gitlab/context/domain/MergeRequestState.java: -------------------------------------------------------------------------------- 1 | package dev.struchkov.bot.gitlab.context.domain; 2 | 3 | /** 4 | * 5 | * @author upagge 14.01.2021 6 | */ 7 | public enum MergeRequestState { 8 | 9 | OPENED, CLOSED, LOCKED, MERGED 10 | 11 | } 12 | -------------------------------------------------------------------------------- /bot-context/src/main/java/dev/struchkov/bot/gitlab/context/domain/MessageSend.java: -------------------------------------------------------------------------------- 1 | package dev.struchkov.bot.gitlab.context.domain; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Builder; 5 | import lombok.EqualsAndHashCode; 6 | import lombok.Getter; 7 | import lombok.NoArgsConstructor; 8 | import lombok.Setter; 9 | 10 | @Getter 11 | @Setter 12 | @Builder 13 | @NoArgsConstructor 14 | @AllArgsConstructor 15 | @EqualsAndHashCode(onlyExplicitlyIncluded = true) 16 | public class MessageSend { 17 | 18 | @EqualsAndHashCode.Include 19 | private Long id; 20 | private Long telegramId; 21 | private String message; 22 | 23 | } 24 | -------------------------------------------------------------------------------- /bot-context/src/main/java/dev/struchkov/bot/gitlab/context/domain/PersonInformation.java: -------------------------------------------------------------------------------- 1 | package dev.struchkov.bot.gitlab.context.domain; 2 | 3 | import lombok.Getter; 4 | import lombok.Setter; 5 | 6 | /** 7 | * @author upagge 15.01.2021 8 | */ 9 | @Getter 10 | @Setter 11 | public class PersonInformation { 12 | 13 | private String username; 14 | private String name; 15 | private Long id; 16 | private String telegramId; 17 | 18 | } 19 | -------------------------------------------------------------------------------- /bot-context/src/main/java/dev/struchkov/bot/gitlab/context/domain/PipelineStatus.java: -------------------------------------------------------------------------------- 1 | package dev.struchkov.bot.gitlab.context.domain; 2 | 3 | import lombok.Getter; 4 | import lombok.RequiredArgsConstructor; 5 | 6 | /** 7 | * @author upagge 17.01.2021 8 | */ 9 | @Getter 10 | @RequiredArgsConstructor 11 | public enum PipelineStatus { 12 | 13 | CREATED("\uD83C\uDD95"), 14 | WAITING_FOR_RESOURCE("\uD83D\uDCA2"), 15 | PREPARING("♿️"), 16 | PENDING("⚠️"), 17 | RUNNING("\uD83D\uDD04"), 18 | SUCCESS("✅"), 19 | FAILED("❌"), 20 | CANCELED("\uD83D\uDEAB"), 21 | SKIPPED("\uD83D\uDD18"), 22 | MANUAL("\uD83D\uDD79"), 23 | SCHEDULED("\uD83D\uDD52"), 24 | NULL("\uD83C\uDD95"); 25 | 26 | private final String icon; 27 | 28 | } 29 | -------------------------------------------------------------------------------- /bot-context/src/main/java/dev/struchkov/bot/gitlab/context/domain/ReviewerChanged.java: -------------------------------------------------------------------------------- 1 | package dev.struchkov.bot.gitlab.context.domain; 2 | 3 | import dev.struchkov.bot.gitlab.context.domain.entity.Person; 4 | import lombok.Getter; 5 | import lombok.RequiredArgsConstructor; 6 | 7 | import java.util.List; 8 | import java.util.Map; 9 | import java.util.stream.Collectors; 10 | 11 | @Getter 12 | @RequiredArgsConstructor 13 | public enum ReviewerChanged { 14 | 15 | BECOME(true), 16 | DELETED(true), 17 | NOT_AFFECT_USER(true), 18 | NOT_CHANGED(false); 19 | 20 | private final boolean changed; 21 | 22 | public static ReviewerChanged valueOf(Long gitlabUserId, List oldReviewers, List newReviewers) { 23 | final Map oldMap = oldReviewers.stream().collect(Collectors.toMap(Person::getId, p -> p)); 24 | final Map newMap = newReviewers.stream().collect(Collectors.toMap(Person::getId, p -> p)); 25 | 26 | if (!oldMap.keySet().equals(newMap.keySet())) { 27 | if (oldMap.containsKey(gitlabUserId) && !newMap.containsKey(gitlabUserId)) { 28 | return ReviewerChanged.DELETED; 29 | } 30 | if (!oldMap.containsKey(gitlabUserId) && newMap.containsKey(gitlabUserId)) { 31 | return ReviewerChanged.BECOME; 32 | } 33 | return ReviewerChanged.NOT_AFFECT_USER; 34 | } 35 | return ReviewerChanged.NOT_CHANGED; 36 | } 37 | 38 | public boolean getNewStatus(boolean oldStatus) { 39 | return switch (this) { 40 | case BECOME -> true; 41 | case DELETED -> false; 42 | case NOT_AFFECT_USER, NOT_CHANGED -> oldStatus; 43 | }; 44 | } 45 | 46 | } -------------------------------------------------------------------------------- /bot-context/src/main/java/dev/struchkov/bot/gitlab/context/domain/entity/AppSetting.java: -------------------------------------------------------------------------------- 1 | package dev.struchkov.bot.gitlab.context.domain.entity; 2 | 3 | import dev.struchkov.bot.gitlab.context.domain.notify.level.DiscussionLevel; 4 | import jakarta.persistence.Column; 5 | import jakarta.persistence.Entity; 6 | import jakarta.persistence.EnumType; 7 | import jakarta.persistence.Enumerated; 8 | import jakarta.persistence.Id; 9 | import jakarta.persistence.Table; 10 | import lombok.Getter; 11 | import lombok.Setter; 12 | 13 | import java.util.UUID; 14 | 15 | /** 16 | * Основные настройки приложения. 17 | * 18 | * @author upagge 16.01.2021 19 | */ 20 | @Entity 21 | @Getter 22 | @Setter 23 | @Table(name = "app_setting") 24 | public class AppSetting { 25 | 26 | @Id 27 | @Column(name = "id") 28 | private Long id; 29 | 30 | @Column(name = "service_key") 31 | private UUID serviceKey = UUID.randomUUID(); 32 | 33 | @Column(name = "first_start") 34 | private boolean firstStart; 35 | 36 | @Column(name = "enable_notify") 37 | private boolean enableNotify; 38 | 39 | @Column(name = "project_owner_scan") 40 | private boolean projectOwnerScan; 41 | 42 | @Column(name = "project_private_scan") 43 | private boolean projectPrivateScan; 44 | 45 | @Enumerated(EnumType.STRING) 46 | @Column(name = "discussion_notify_level") 47 | private DiscussionLevel discussionNotifyLevel; 48 | 49 | } 50 | -------------------------------------------------------------------------------- /bot-context/src/main/java/dev/struchkov/bot/gitlab/context/domain/entity/MergeRequestForDiscussion.java: -------------------------------------------------------------------------------- 1 | package dev.struchkov.bot.gitlab.context.domain.entity; 2 | 3 | import jakarta.persistence.CascadeType; 4 | import jakarta.persistence.Column; 5 | import jakarta.persistence.Entity; 6 | import jakarta.persistence.Id; 7 | import jakarta.persistence.JoinColumn; 8 | import jakarta.persistence.ManyToOne; 9 | import jakarta.persistence.Table; 10 | import lombok.EqualsAndHashCode; 11 | import lombok.Getter; 12 | import lombok.Setter; 13 | 14 | /** 15 | * @author upagge 12.09.2020 16 | */ 17 | @Getter 18 | @Setter 19 | @Entity 20 | @Table(name = "merge_request") 21 | @EqualsAndHashCode(onlyExplicitlyIncluded = true) 22 | public class MergeRequestForDiscussion { 23 | 24 | /** 25 | * Идентификатор 26 | */ 27 | @Id 28 | @Column(name = "id") 29 | @EqualsAndHashCode.Include 30 | private Long id; 31 | 32 | @Column(name = "two_id") 33 | private Long twoId; 34 | 35 | @Column(name = "project_id") 36 | private Long projectId; 37 | 38 | @Column(name = "title") 39 | private String title; 40 | 41 | @ManyToOne(cascade = {CascadeType.PERSIST, CascadeType.MERGE}) 42 | @JoinColumn(name = "author_id") 43 | private Person author; 44 | 45 | @Column(name = "web_url") 46 | private String webUrl; 47 | 48 | @Column(name = "notification") 49 | private boolean notification; 50 | 51 | } 52 | -------------------------------------------------------------------------------- /bot-context/src/main/java/dev/struchkov/bot/gitlab/context/domain/entity/Note.java: -------------------------------------------------------------------------------- 1 | package dev.struchkov.bot.gitlab.context.domain.entity; 2 | 3 | import jakarta.persistence.Column; 4 | import jakarta.persistence.Entity; 5 | import jakarta.persistence.Id; 6 | import jakarta.persistence.JoinColumn; 7 | import jakarta.persistence.ManyToOne; 8 | import jakarta.persistence.Table; 9 | import lombok.EqualsAndHashCode; 10 | import lombok.Getter; 11 | import lombok.Setter; 12 | 13 | import java.time.LocalDateTime; 14 | 15 | import static jakarta.persistence.CascadeType.MERGE; 16 | import static jakarta.persistence.CascadeType.PERSIST; 17 | 18 | @Getter 19 | @Setter 20 | @Entity 21 | @Table(name = "note") 22 | @EqualsAndHashCode(onlyExplicitlyIncluded = true) 23 | public class Note { 24 | 25 | @Id 26 | @Column(name = "id") 27 | @EqualsAndHashCode.Include 28 | private Long id; 29 | 30 | @Column(name = "type") 31 | private String type; 32 | 33 | @Column(name = "body") 34 | private String body; 35 | 36 | @Column(name = "created_date") 37 | private LocalDateTime created; 38 | 39 | @Column(name = "updated_date") 40 | private LocalDateTime updated; 41 | 42 | @ManyToOne(cascade = {PERSIST, MERGE}) 43 | @JoinColumn(name = "author_id") 44 | private Person author; 45 | 46 | @Column(name = "noteable_id") 47 | private Long noteableId; 48 | 49 | @Column(name = "noteable_type") 50 | private String noteableType; 51 | 52 | @Column(name = "noteable_iid") 53 | private Long noteableIid; 54 | 55 | @Column(name = "web_url") 56 | private String webUrl; 57 | 58 | @Column(name = "resolvable") 59 | private boolean resolvable; 60 | 61 | @Column(name = "resolved") 62 | private Boolean resolved; 63 | 64 | @ManyToOne(cascade = {PERSIST, MERGE}) 65 | @JoinColumn(name = "resolved_id") 66 | private Person resolvedBy; 67 | 68 | @ManyToOne(optional = false) 69 | @JoinColumn(name = "discussion_id") 70 | private Discussion discussion; 71 | 72 | } 73 | -------------------------------------------------------------------------------- /bot-context/src/main/java/dev/struchkov/bot/gitlab/context/domain/entity/Person.java: -------------------------------------------------------------------------------- 1 | package dev.struchkov.bot.gitlab.context.domain.entity; 2 | 3 | import dev.struchkov.haiti.utils.fieldconstants.annotation.FieldNames; 4 | import dev.struchkov.haiti.utils.fieldconstants.domain.Mode; 5 | import jakarta.persistence.Column; 6 | import jakarta.persistence.Entity; 7 | import jakarta.persistence.Id; 8 | import jakarta.persistence.Table; 9 | import lombok.EqualsAndHashCode; 10 | import lombok.Getter; 11 | import lombok.Setter; 12 | 13 | /** 14 | * @author upagge 14.01.2021 15 | */ 16 | @Entity 17 | @Getter 18 | @Setter 19 | @EqualsAndHashCode(onlyExplicitlyIncluded = true) 20 | @Table(name = "person") 21 | @FieldNames(mode = {Mode.TABLE, Mode.SIMPLE}) 22 | public class Person { 23 | 24 | @Id 25 | @EqualsAndHashCode.Include 26 | @Column(name = "id") 27 | private Long id; 28 | 29 | @Column(name = "name") 30 | private String name; 31 | 32 | @Column(name = "username") 33 | private String userName; 34 | 35 | @Column(name = "web_url") 36 | private String webUrl; 37 | 38 | } 39 | -------------------------------------------------------------------------------- /bot-context/src/main/java/dev/struchkov/bot/gitlab/context/domain/entity/Pipeline.java: -------------------------------------------------------------------------------- 1 | package dev.struchkov.bot.gitlab.context.domain.entity; 2 | 3 | import dev.struchkov.bot.gitlab.context.domain.PipelineStatus; 4 | import dev.struchkov.haiti.utils.fieldconstants.annotation.FieldNames; 5 | import jakarta.persistence.CascadeType; 6 | import jakarta.persistence.Column; 7 | import jakarta.persistence.Entity; 8 | import jakarta.persistence.EnumType; 9 | import jakarta.persistence.Enumerated; 10 | import jakarta.persistence.Id; 11 | import jakarta.persistence.JoinColumn; 12 | import jakarta.persistence.ManyToOne; 13 | import jakarta.persistence.Table; 14 | import lombok.EqualsAndHashCode; 15 | import lombok.Getter; 16 | import lombok.Setter; 17 | 18 | import java.time.LocalDateTime; 19 | 20 | /** 21 | * @author upagge 17.01.2021 22 | */ 23 | 24 | @Entity 25 | @Getter 26 | @Setter 27 | @FieldNames 28 | @Table(name = "pipeline") 29 | @EqualsAndHashCode(onlyExplicitlyIncluded = true) 30 | public class Pipeline { 31 | 32 | @Id 33 | @Column(name = "id") 34 | @EqualsAndHashCode.Include 35 | private Long id; 36 | 37 | @Column(name = "created_date") 38 | private LocalDateTime created; 39 | 40 | @Column(name = "updated_date") 41 | private LocalDateTime updated; 42 | 43 | @Enumerated(EnumType.STRING) 44 | @Column(name = "status") 45 | private PipelineStatus status; 46 | 47 | @Column(name = "ref") 48 | private String ref; 49 | 50 | @Column(name = "web_url") 51 | private String webUrl; 52 | 53 | @Column(name = "project_id") 54 | private Long projectId; 55 | 56 | @ManyToOne(cascade = {CascadeType.PERSIST, CascadeType.MERGE, CascadeType.REFRESH}) 57 | @JoinColumn(name = "person_id") 58 | private Person person; 59 | 60 | } 61 | -------------------------------------------------------------------------------- /bot-context/src/main/java/dev/struchkov/bot/gitlab/context/domain/entity/Project.java: -------------------------------------------------------------------------------- 1 | package dev.struchkov.bot.gitlab.context.domain.entity; 2 | 3 | import jakarta.persistence.Column; 4 | import jakarta.persistence.Entity; 5 | import jakarta.persistence.Id; 6 | import jakarta.persistence.Table; 7 | import lombok.EqualsAndHashCode; 8 | import lombok.Getter; 9 | import lombok.Setter; 10 | 11 | import java.time.LocalDateTime; 12 | 13 | /** 14 | * @author upagge 14.01.2021 15 | */ 16 | @Getter 17 | @Setter 18 | @Entity 19 | @Table(name = "project") 20 | @EqualsAndHashCode(onlyExplicitlyIncluded = true) 21 | public class Project { 22 | 23 | @Id 24 | @Column(name = "id") 25 | private Long id; 26 | 27 | @Column(name = "name") 28 | private String name; 29 | 30 | @Column(name = "description") 31 | private String description; 32 | 33 | @Column(name = "created_date") 34 | private LocalDateTime createdDate; 35 | 36 | @Column(name = "creator_id") 37 | private Long creatorId; 38 | 39 | @Column(name = "web_url") 40 | private String webUrl; 41 | 42 | @Column(name = "ssh_url_to_repo") 43 | private String sshUrlToRepo; 44 | 45 | @Column(name = "http_url_to_repo") 46 | private String httpUrlToRepo; 47 | 48 | @Column(name = "notification") 49 | private boolean notification; 50 | 51 | @Column(name = "processing") 52 | private boolean processing; 53 | 54 | } 55 | -------------------------------------------------------------------------------- /bot-context/src/main/java/dev/struchkov/bot/gitlab/context/domain/filter/MergeRequestFilter.java: -------------------------------------------------------------------------------- 1 | package dev.struchkov.bot.gitlab.context.domain.filter; 2 | 3 | import dev.struchkov.bot.gitlab.context.domain.MergeRequestState; 4 | import lombok.AccessLevel; 5 | import lombok.AllArgsConstructor; 6 | import lombok.Builder; 7 | import lombok.Getter; 8 | import lombok.NoArgsConstructor; 9 | import lombok.Setter; 10 | 11 | import java.util.Set; 12 | 13 | @Getter 14 | @Setter 15 | @Builder 16 | @NoArgsConstructor 17 | @AllArgsConstructor(access = AccessLevel.PRIVATE) 18 | public class MergeRequestFilter { 19 | 20 | private Long assignee; 21 | private Set states; 22 | 23 | } 24 | -------------------------------------------------------------------------------- /bot-context/src/main/java/dev/struchkov/bot/gitlab/context/domain/filter/PipelineFilter.java: -------------------------------------------------------------------------------- 1 | package dev.struchkov.bot.gitlab.context.domain.filter; 2 | 3 | import dev.struchkov.bot.gitlab.context.domain.entity.Pipeline; 4 | import lombok.AccessLevel; 5 | import lombok.AllArgsConstructor; 6 | import lombok.Builder; 7 | import lombok.Getter; 8 | import lombok.NoArgsConstructor; 9 | import lombok.Setter; 10 | 11 | import java.time.LocalDateTime; 12 | 13 | /** 14 | * Объект фильтра для {@link Pipeline}. 15 | * 16 | * @author upagge 08.02.2021 17 | */ 18 | @Getter 19 | @Setter 20 | @Builder 21 | @NoArgsConstructor 22 | @AllArgsConstructor(access = AccessLevel.PRIVATE) 23 | public class PipelineFilter { 24 | 25 | private LocalDateTime lessThanCreatedDate; 26 | 27 | } 28 | -------------------------------------------------------------------------------- /bot-context/src/main/java/dev/struchkov/bot/gitlab/context/domain/notify/Notify.java: -------------------------------------------------------------------------------- 1 | package dev.struchkov.bot.gitlab.context.domain.notify; 2 | 3 | public interface Notify { 4 | 5 | String getType(); 6 | 7 | } 8 | -------------------------------------------------------------------------------- /bot-context/src/main/java/dev/struchkov/bot/gitlab/context/domain/notify/comment/NewCommentNotify.java: -------------------------------------------------------------------------------- 1 | package dev.struchkov.bot.gitlab.context.domain.notify.comment; 2 | 3 | import dev.struchkov.bot.gitlab.context.domain.notify.Notify; 4 | import dev.struchkov.haiti.utils.fieldconstants.annotation.FieldNames; 5 | import lombok.Builder; 6 | import lombok.Getter; 7 | 8 | @Getter 9 | @FieldNames 10 | public final class NewCommentNotify implements Notify { 11 | 12 | public static final String TYPE = "NewCommentNotify"; 13 | 14 | private final String threadId; 15 | private final String mergeRequestName; 16 | private final String url; 17 | private final String discussionMessage; 18 | private final String discussionAuthor; 19 | private final String previousMessage; 20 | private final String previousAuthor; 21 | private final String authorName; 22 | private final String message; 23 | private final int numberNotes; 24 | 25 | @Builder 26 | public NewCommentNotify( 27 | String threadId, 28 | String mergeRequestName, 29 | String url, 30 | String discussionMessage, 31 | String discussionAuthor, 32 | String previousMessage, 33 | String previousAuthor, 34 | String authorName, 35 | String message, 36 | int numberNotes 37 | ) { 38 | this.threadId = threadId; 39 | this.mergeRequestName = mergeRequestName; 40 | this.url = url; 41 | this.discussionMessage = discussionMessage; 42 | this.discussionAuthor = discussionAuthor; 43 | this.previousMessage = previousMessage; 44 | this.previousAuthor = previousAuthor; 45 | this.authorName = authorName; 46 | this.message = message; 47 | this.numberNotes = numberNotes; 48 | } 49 | 50 | @Override 51 | public String getType() { 52 | return TYPE; 53 | } 54 | 55 | } 56 | 57 | 58 | -------------------------------------------------------------------------------- /bot-context/src/main/java/dev/struchkov/bot/gitlab/context/domain/notify/level/DiscussionLevel.java: -------------------------------------------------------------------------------- 1 | package dev.struchkov.bot.gitlab.context.domain.notify.level; 2 | 3 | public enum DiscussionLevel { 4 | 5 | WITHOUT_NOTIFY, NOTIFY_WITHOUT_CONTEXT, NOTIFY_WITH_CONTEXT 6 | 7 | } 8 | -------------------------------------------------------------------------------- /bot-context/src/main/java/dev/struchkov/bot/gitlab/context/domain/notify/mergerequest/ConflictMrNotify.java: -------------------------------------------------------------------------------- 1 | package dev.struchkov.bot.gitlab.context.domain.notify.mergerequest; 2 | 3 | import dev.struchkov.haiti.utils.fieldconstants.annotation.FieldNames; 4 | import lombok.Builder; 5 | import lombok.Getter; 6 | 7 | import static dev.struchkov.bot.gitlab.context.domain.notify.mergerequest.ConflictMrNotifyFields.CLASS_NAME; 8 | 9 | @Getter 10 | @FieldNames 11 | public class ConflictMrNotify extends MrNotify { 12 | 13 | public static final String TYPE = CLASS_NAME; 14 | 15 | private final String sourceBranch; 16 | 17 | @Builder 18 | private ConflictMrNotify( 19 | Long mrId, 20 | String name, 21 | String url, 22 | String projectKey, 23 | String sourceBranch 24 | ) { 25 | super(mrId, projectKey, name, url); 26 | this.sourceBranch = sourceBranch; 27 | } 28 | 29 | @Override 30 | public String getType() { 31 | return TYPE; 32 | } 33 | 34 | } 35 | -------------------------------------------------------------------------------- /bot-context/src/main/java/dev/struchkov/bot/gitlab/context/domain/notify/mergerequest/ConflictResolveMrNotify.java: -------------------------------------------------------------------------------- 1 | package dev.struchkov.bot.gitlab.context.domain.notify.mergerequest; 2 | 3 | import dev.struchkov.haiti.utils.fieldconstants.annotation.FieldNames; 4 | import lombok.Builder; 5 | import lombok.Getter; 6 | 7 | import static dev.struchkov.bot.gitlab.context.domain.notify.mergerequest.ConflictResolveMrNotifyFields.CLASS_NAME; 8 | 9 | @Getter 10 | @FieldNames 11 | public class ConflictResolveMrNotify extends MrNotify { 12 | 13 | public static final String TYPE = CLASS_NAME; 14 | 15 | private final String sourceBranch; 16 | 17 | @Builder 18 | private ConflictResolveMrNotify( 19 | Long mrId, 20 | String name, 21 | String url, 22 | String projectKey, 23 | String sourceBranch 24 | ) { 25 | super(mrId, projectKey, name, url); 26 | this.sourceBranch = sourceBranch; 27 | } 28 | 29 | @Override 30 | public String getType() { 31 | return TYPE; 32 | } 33 | 34 | } 35 | -------------------------------------------------------------------------------- /bot-context/src/main/java/dev/struchkov/bot/gitlab/context/domain/notify/mergerequest/MrNotify.java: -------------------------------------------------------------------------------- 1 | package dev.struchkov.bot.gitlab.context.domain.notify.mergerequest; 2 | 3 | import dev.struchkov.bot.gitlab.context.domain.notify.Notify; 4 | import lombok.Getter; 5 | 6 | @Getter 7 | public abstract class MrNotify implements Notify { 8 | 9 | protected final Long mrId; 10 | protected final String projectName; 11 | protected final String title; 12 | protected final String url; 13 | 14 | protected MrNotify( 15 | Long mrId, 16 | String projectName, 17 | String title, 18 | String url 19 | ) { 20 | this.mrId = mrId; 21 | this.projectName = projectName; 22 | this.title = title; 23 | this.url = url; 24 | } 25 | 26 | } 27 | -------------------------------------------------------------------------------- /bot-context/src/main/java/dev/struchkov/bot/gitlab/context/domain/notify/mergerequest/NewMrForAssignee.java: -------------------------------------------------------------------------------- 1 | package dev.struchkov.bot.gitlab.context.domain.notify.mergerequest; 2 | 3 | import dev.struchkov.haiti.utils.fieldconstants.annotation.FieldNames; 4 | import lombok.Builder; 5 | import lombok.Getter; 6 | import lombok.Singular; 7 | 8 | import java.util.List; 9 | import java.util.Set; 10 | 11 | import static dev.struchkov.bot.gitlab.context.domain.notify.mergerequest.NewMrForAssigneeFields.CLASS_NAME; 12 | 13 | @Getter 14 | @FieldNames 15 | public class NewMrForAssignee extends NewMrNotify { 16 | 17 | public static final String TYPE = CLASS_NAME; 18 | 19 | private final List reviewers; 20 | private final String oldAssigneeName; 21 | private final String newAssigneeName; 22 | 23 | @Builder 24 | private NewMrForAssignee( 25 | Long mrId, 26 | String title, 27 | String url, 28 | String description, 29 | String author, 30 | String projectName, 31 | String targetBranch, 32 | String sourceBranch, 33 | Set labels, 34 | @Singular List reviewers, 35 | String oldAssigneeName, 36 | String newAssigneeName 37 | ) { 38 | super( 39 | mrId, 40 | title, 41 | url, 42 | description, 43 | author, 44 | projectName, 45 | targetBranch, 46 | sourceBranch, 47 | labels 48 | ); 49 | this.reviewers = reviewers; 50 | this.oldAssigneeName = oldAssigneeName; 51 | this.newAssigneeName = newAssigneeName; 52 | } 53 | 54 | @Override 55 | public String getType() { 56 | return TYPE; 57 | } 58 | 59 | } 60 | -------------------------------------------------------------------------------- /bot-context/src/main/java/dev/struchkov/bot/gitlab/context/domain/notify/mergerequest/NewMrForReview.java: -------------------------------------------------------------------------------- 1 | package dev.struchkov.bot.gitlab.context.domain.notify.mergerequest; 2 | 3 | import dev.struchkov.haiti.utils.fieldconstants.annotation.FieldNames; 4 | import lombok.Builder; 5 | import lombok.Getter; 6 | 7 | import java.util.Set; 8 | 9 | import static dev.struchkov.bot.gitlab.context.domain.notify.mergerequest.NewMrForReviewFields.CLASS_NAME; 10 | 11 | @Getter 12 | @FieldNames 13 | public class NewMrForReview extends NewMrNotify { 14 | 15 | public static final String TYPE = CLASS_NAME; 16 | 17 | private final String assignee; 18 | 19 | @Builder 20 | private NewMrForReview( 21 | Long mrId, 22 | String title, 23 | String url, 24 | String description, 25 | String author, 26 | String projectName, 27 | String targetBranch, 28 | String sourceBranch, 29 | Set labels, 30 | String assignee 31 | ) { 32 | super( 33 | mrId, 34 | title, 35 | url, 36 | description, 37 | author, 38 | projectName, 39 | targetBranch, 40 | sourceBranch, 41 | labels 42 | ); 43 | this.assignee = assignee; 44 | } 45 | 46 | @Override 47 | public String getType() { 48 | return TYPE; 49 | } 50 | 51 | } 52 | -------------------------------------------------------------------------------- /bot-context/src/main/java/dev/struchkov/bot/gitlab/context/domain/notify/mergerequest/NewMrNotify.java: -------------------------------------------------------------------------------- 1 | package dev.struchkov.bot.gitlab.context.domain.notify.mergerequest; 2 | 3 | import lombok.Getter; 4 | 5 | import java.util.Set; 6 | 7 | @Getter 8 | public abstract class NewMrNotify extends MrNotify { 9 | 10 | protected final String description; 11 | protected final String author; 12 | protected final String targetBranch; 13 | protected final String sourceBranch; 14 | protected final Set labels; 15 | 16 | protected NewMrNotify( 17 | Long mrId, 18 | String title, 19 | String url, 20 | String description, 21 | String author, 22 | String projectName, 23 | String targetBranch, 24 | String sourceBranch, 25 | Set labels 26 | ) { 27 | super(mrId, projectName, title, url); 28 | this.description = description; 29 | this.author = author; 30 | this.targetBranch = targetBranch; 31 | this.sourceBranch = sourceBranch; 32 | this.labels = labels; 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /bot-context/src/main/java/dev/struchkov/bot/gitlab/context/domain/notify/mergerequest/StatusMrNotify.java: -------------------------------------------------------------------------------- 1 | package dev.struchkov.bot.gitlab.context.domain.notify.mergerequest; 2 | 3 | import dev.struchkov.bot.gitlab.context.domain.MergeRequestState; 4 | import dev.struchkov.haiti.utils.fieldconstants.annotation.FieldNames; 5 | import lombok.Builder; 6 | import lombok.Getter; 7 | 8 | import static dev.struchkov.bot.gitlab.context.domain.notify.mergerequest.StatusMrNotifyFields.CLASS_NAME; 9 | 10 | @Getter 11 | @FieldNames 12 | public class StatusMrNotify extends MrNotify { 13 | 14 | public static final String TYPE = CLASS_NAME; 15 | 16 | private final MergeRequestState oldStatus; 17 | private final MergeRequestState newStatus; 18 | 19 | @Builder 20 | private StatusMrNotify( 21 | Long mrId, 22 | String name, 23 | String url, 24 | String projectName, 25 | MergeRequestState oldStatus, 26 | MergeRequestState newStatus 27 | ) { 28 | super(mrId, projectName, name, url); 29 | this.oldStatus = oldStatus; 30 | this.newStatus = newStatus; 31 | } 32 | 33 | @Override 34 | public String getType() { 35 | return TYPE; 36 | } 37 | 38 | } 39 | -------------------------------------------------------------------------------- /bot-context/src/main/java/dev/struchkov/bot/gitlab/context/domain/notify/mergerequest/UpdateMrNotify.java: -------------------------------------------------------------------------------- 1 | package dev.struchkov.bot.gitlab.context.domain.notify.mergerequest; 2 | 3 | import dev.struchkov.haiti.utils.fieldconstants.annotation.FieldNames; 4 | import lombok.Builder; 5 | import lombok.Getter; 6 | 7 | import static dev.struchkov.bot.gitlab.context.domain.notify.mergerequest.UpdateMrNotifyFields.CLASS_NAME; 8 | 9 | @Getter 10 | @FieldNames 11 | public class UpdateMrNotify extends MrNotify { 12 | 13 | public static final String TYPE = CLASS_NAME; 14 | 15 | private final String author; 16 | private final Long allTasks; 17 | private final Long allResolvedTasks; 18 | private final Long personTasks; 19 | private final Long personResolvedTasks; 20 | private final String comment; 21 | 22 | @Builder 23 | private UpdateMrNotify( 24 | Long mrId, 25 | String name, 26 | String url, 27 | String author, 28 | String projectName, 29 | Long allTasks, 30 | Long allResolvedTasks, 31 | Long personTasks, 32 | Long personResolvedTasks, 33 | String comment 34 | ) { 35 | super(mrId, projectName, name, url); 36 | this.author = author; 37 | this.allTasks = allTasks; 38 | this.allResolvedTasks = allResolvedTasks; 39 | this.personTasks = personTasks; 40 | this.personResolvedTasks = personResolvedTasks; 41 | this.comment = comment; 42 | } 43 | 44 | @Override 45 | public String getType() { 46 | return TYPE; 47 | } 48 | 49 | } 50 | -------------------------------------------------------------------------------- /bot-context/src/main/java/dev/struchkov/bot/gitlab/context/domain/notify/pipeline/PipelineNotify.java: -------------------------------------------------------------------------------- 1 | package dev.struchkov.bot.gitlab.context.domain.notify.pipeline; 2 | 3 | import dev.struchkov.bot.gitlab.context.domain.PipelineStatus; 4 | import dev.struchkov.bot.gitlab.context.domain.notify.Notify; 5 | import dev.struchkov.haiti.utils.fieldconstants.annotation.FieldNames; 6 | import lombok.Builder; 7 | import lombok.Getter; 8 | 9 | import static dev.struchkov.bot.gitlab.context.domain.notify.pipeline.PipelineNotifyFields.CLASS_NAME; 10 | 11 | /** 12 | * @author upagge 17.01.2021 13 | */ 14 | //TODO [16.12.2022|uPagge]: Нужно реализовать заполнение projectName 15 | @Getter 16 | @FieldNames 17 | public final class PipelineNotify implements Notify { 18 | 19 | public static final String TYPE = CLASS_NAME; 20 | 21 | private final Long projectId; 22 | private final Long pipelineId; 23 | private final String refName; 24 | private final PipelineStatus oldStatus; 25 | private final PipelineStatus newStatus; 26 | private final String webUrl; 27 | 28 | @Builder 29 | public PipelineNotify( 30 | Long projectId, 31 | Long pipelineId, 32 | String refName, 33 | PipelineStatus oldStatus, 34 | PipelineStatus newStatus, 35 | String webUrl 36 | ) { 37 | this.projectId = projectId; 38 | this.pipelineId = pipelineId; 39 | this.refName = refName; 40 | this.oldStatus = oldStatus; 41 | this.newStatus = newStatus; 42 | this.webUrl = webUrl; 43 | } 44 | 45 | @Override 46 | public String getType() { 47 | return TYPE; 48 | } 49 | 50 | } 51 | -------------------------------------------------------------------------------- /bot-context/src/main/java/dev/struchkov/bot/gitlab/context/domain/notify/project/NewProjectNotify.java: -------------------------------------------------------------------------------- 1 | package dev.struchkov.bot.gitlab.context.domain.notify.project; 2 | 3 | import dev.struchkov.bot.gitlab.context.domain.notify.Notify; 4 | import dev.struchkov.haiti.utils.fieldconstants.annotation.FieldNames; 5 | import lombok.Builder; 6 | import lombok.Getter; 7 | 8 | import static dev.struchkov.bot.gitlab.context.domain.notify.project.NewProjectNotifyFields.CLASS_NAME; 9 | 10 | /** 11 | * @author upagge 15.01.2021 12 | */ 13 | @Getter 14 | @FieldNames 15 | public final class NewProjectNotify implements Notify { 16 | 17 | public static final String TYPE = CLASS_NAME; 18 | 19 | private final Long projectId; 20 | private final String projectName; 21 | private final String projectUrl; 22 | private final String projectDescription; 23 | private final String authorName; 24 | private final String sshUrlToRepo; 25 | private final String httpUrlToRepo; 26 | 27 | @Builder 28 | public NewProjectNotify( 29 | Long projectId, 30 | String projectName, 31 | String projectUrl, 32 | String projectDescription, 33 | String authorName, 34 | String sshUrlToRepo, 35 | String httpUrlToRepo 36 | ) { 37 | this.projectId = projectId; 38 | this.projectName = projectName; 39 | this.projectUrl = projectUrl; 40 | this.projectDescription = projectDescription; 41 | this.authorName = authorName; 42 | this.sshUrlToRepo = sshUrlToRepo; 43 | this.httpUrlToRepo = httpUrlToRepo; 44 | } 45 | 46 | @Override 47 | public String getType() { 48 | return TYPE; 49 | } 50 | 51 | } 52 | -------------------------------------------------------------------------------- /bot-context/src/main/java/dev/struchkov/bot/gitlab/context/domain/notify/task/DiscussionNewNotify.java: -------------------------------------------------------------------------------- 1 | package dev.struchkov.bot.gitlab.context.domain.notify.task; 2 | 3 | import dev.struchkov.haiti.utils.container.Pair; 4 | import dev.struchkov.haiti.utils.fieldconstants.annotation.FieldNames; 5 | import lombok.Builder; 6 | import lombok.Getter; 7 | import lombok.Singular; 8 | 9 | import java.util.List; 10 | 11 | import static dev.struchkov.bot.gitlab.context.domain.notify.task.DiscussionNewNotifyFields.CLASS_NAME; 12 | 13 | /** 14 | * @author upagge 10.09.2020 15 | */ 16 | @Getter 17 | @FieldNames 18 | public class DiscussionNewNotify extends ThreadNotify { 19 | 20 | public static final String TYPE = CLASS_NAME; 21 | 22 | private final String threadId; 23 | private final List> notes; 24 | 25 | @Builder 26 | public DiscussionNewNotify( 27 | String threadId, 28 | String mergeRequestName, 29 | String authorName, 30 | String url, 31 | String discussionMessage, 32 | @Singular List> notes 33 | ) { 34 | super(mergeRequestName, authorName, url, discussionMessage); 35 | this.threadId = threadId; 36 | this.notes = notes; 37 | } 38 | 39 | @Override 40 | public String getType() { 41 | return TYPE; 42 | } 43 | 44 | } 45 | -------------------------------------------------------------------------------- /bot-context/src/main/java/dev/struchkov/bot/gitlab/context/domain/notify/task/ThreadCloseNotify.java: -------------------------------------------------------------------------------- 1 | package dev.struchkov.bot.gitlab.context.domain.notify.task; 2 | 3 | import dev.struchkov.haiti.utils.fieldconstants.annotation.FieldNames; 4 | import lombok.Builder; 5 | import lombok.Getter; 6 | 7 | import static dev.struchkov.bot.gitlab.context.domain.notify.task.ThreadCloseNotifyFields.CLASS_NAME; 8 | 9 | /** 10 | * @author upagge 10.09.2020 11 | */ 12 | @Getter 13 | @FieldNames 14 | public class ThreadCloseNotify extends ThreadNotify { 15 | 16 | public static final String TYPE = CLASS_NAME; 17 | 18 | private final Long personTasks; 19 | private final Long personResolvedTasks; 20 | private final String authorLastNote; 21 | private final String messageLastNote; 22 | 23 | @Builder 24 | protected ThreadCloseNotify( 25 | String mergeRequestName, 26 | String authorName, 27 | String url, 28 | String messageTask, 29 | Long personTasks, 30 | Long personResolvedTasks, 31 | String authorLastNote, 32 | String messageLastNote 33 | ) { 34 | super(mergeRequestName, authorName, url, messageTask); 35 | this.personTasks = personTasks; 36 | this.personResolvedTasks = personResolvedTasks; 37 | this.authorLastNote = authorLastNote; 38 | this.messageLastNote = messageLastNote; 39 | } 40 | 41 | @Override 42 | public String getType() { 43 | return TYPE; 44 | } 45 | 46 | } 47 | -------------------------------------------------------------------------------- /bot-context/src/main/java/dev/struchkov/bot/gitlab/context/domain/notify/task/ThreadNotify.java: -------------------------------------------------------------------------------- 1 | package dev.struchkov.bot.gitlab.context.domain.notify.task; 2 | 3 | import dev.struchkov.bot.gitlab.context.domain.notify.Notify; 4 | import lombok.Getter; 5 | 6 | @Getter 7 | public abstract class ThreadNotify implements Notify { 8 | 9 | protected final String mergeRequestName; 10 | protected final String authorName; 11 | protected final String url; 12 | protected final String messageTask; 13 | 14 | protected ThreadNotify( 15 | String mergeRequestName, 16 | String authorName, 17 | String url, 18 | String messageTask 19 | ) { 20 | this.mergeRequestName = mergeRequestName; 21 | this.authorName = authorName; 22 | this.url = url; 23 | this.messageTask = messageTask; 24 | } 25 | 26 | } 27 | -------------------------------------------------------------------------------- /bot-context/src/main/java/dev/struchkov/bot/gitlab/context/repository/AppSettingRepository.java: -------------------------------------------------------------------------------- 1 | package dev.struchkov.bot.gitlab.context.repository; 2 | 3 | import dev.struchkov.bot.gitlab.context.domain.entity.AppSetting; 4 | 5 | import java.util.Optional; 6 | 7 | /** 8 | * @author upagge 16.01.2021 9 | */ 10 | public interface AppSettingRepository { 11 | 12 | AppSetting save(AppSetting appSetting); 13 | 14 | Optional findById(Long key); 15 | } 16 | -------------------------------------------------------------------------------- /bot-context/src/main/java/dev/struchkov/bot/gitlab/context/repository/DiscussionRepository.java: -------------------------------------------------------------------------------- 1 | package dev.struchkov.bot.gitlab.context.repository; 2 | 3 | import dev.struchkov.bot.gitlab.context.domain.entity.Discussion; 4 | 5 | import java.util.List; 6 | import java.util.Optional; 7 | import java.util.Set; 8 | 9 | /** 10 | * @author upagge 11.02.2021 11 | */ 12 | public interface DiscussionRepository { 13 | 14 | /** 15 | * Вернуть все дискусии для MR 16 | */ 17 | List findAllByMergeRequestId(Long mergeRequestId); 18 | 19 | Discussion save(Discussion discussion); 20 | 21 | Optional findById(String discussionId); 22 | 23 | List findAll(); 24 | 25 | List findAllById(Set discussionIds); 26 | 27 | Set findAllIds(); 28 | 29 | void deleteById(String id); 30 | 31 | void cleanOld(); 32 | 33 | void notification(boolean enable, String discussionId); 34 | 35 | } 36 | -------------------------------------------------------------------------------- /bot-context/src/main/java/dev/struchkov/bot/gitlab/context/repository/MergeRequestRepository.java: -------------------------------------------------------------------------------- 1 | package dev.struchkov.bot.gitlab.context.repository; 2 | 3 | import dev.struchkov.bot.gitlab.context.domain.IdAndStatusPr; 4 | import dev.struchkov.bot.gitlab.context.domain.MergeRequestState; 5 | import dev.struchkov.bot.gitlab.context.domain.entity.MergeRequest; 6 | import dev.struchkov.bot.gitlab.context.domain.entity.MergeRequestForDiscussion; 7 | import lombok.NonNull; 8 | 9 | import java.util.List; 10 | import java.util.Optional; 11 | import java.util.Set; 12 | 13 | public interface MergeRequestRepository { 14 | 15 | Set findAllIdByStateIn(@NonNull Set states); 16 | 17 | MergeRequest save(MergeRequest mergeRequest); 18 | 19 | Optional findById(Long mergeRequestId); 20 | 21 | List findAllForDiscussion(); 22 | 23 | List findAllById(Set mergeRequestIds); 24 | 25 | List findAllByReviewerId(Long personId); 26 | 27 | void deleteByStates(Set states); 28 | 29 | Set findAllIds(); 30 | 31 | void notification(boolean enable, Long mrId); 32 | 33 | void notificationByProjectId(boolean enable, Set projectIds); 34 | 35 | } 36 | -------------------------------------------------------------------------------- /bot-context/src/main/java/dev/struchkov/bot/gitlab/context/repository/NoteRepository.java: -------------------------------------------------------------------------------- 1 | package dev.struchkov.bot.gitlab.context.repository; 2 | 3 | import dev.struchkov.bot.gitlab.context.domain.entity.Note; 4 | import org.springframework.data.domain.Page; 5 | import org.springframework.data.domain.Pageable; 6 | 7 | import java.util.List; 8 | import java.util.Optional; 9 | 10 | /** 11 | * @author upagge 08.09.2020 12 | */ 13 | public interface NoteRepository { 14 | 15 | List findAllByResponsibleIdAndResolved(Long userId, boolean resolved); 16 | 17 | Page findAllByResolved(boolean resolved, Pageable pagination); 18 | 19 | Optional findById(Long noteId); 20 | } 21 | -------------------------------------------------------------------------------- /bot-context/src/main/java/dev/struchkov/bot/gitlab/context/repository/PersonRepository.java: -------------------------------------------------------------------------------- 1 | package dev.struchkov.bot.gitlab.context.repository; 2 | 3 | import dev.struchkov.bot.gitlab.context.domain.entity.Person; 4 | 5 | import java.util.List; 6 | import java.util.Optional; 7 | import java.util.Set; 8 | 9 | /** 10 | * @author upagge 15.01.2021 11 | */ 12 | public interface PersonRepository { 13 | 14 | Person save(Person person); 15 | 16 | Optional findById(Long personId); 17 | 18 | List findAllById(Set personIds); 19 | 20 | } 21 | -------------------------------------------------------------------------------- /bot-context/src/main/java/dev/struchkov/bot/gitlab/context/repository/PipelineRepository.java: -------------------------------------------------------------------------------- 1 | package dev.struchkov.bot.gitlab.context.repository; 2 | 3 | import dev.struchkov.bot.gitlab.context.domain.PipelineStatus; 4 | import dev.struchkov.bot.gitlab.context.domain.entity.Pipeline; 5 | 6 | import java.time.LocalDateTime; 7 | import java.util.List; 8 | import java.util.Optional; 9 | import java.util.Set; 10 | 11 | /** 12 | * @author upagge 17.01.2021 13 | */ 14 | public interface PipelineRepository { 15 | 16 | Pipeline save(Pipeline pipeline); 17 | 18 | Optional findById(Long pipelineId); 19 | 20 | List findAllByStatuses(Set statuses); 21 | 22 | List findAllById(Set pipelineIds); 23 | 24 | void deleteByCreatedBefore(LocalDateTime date); 25 | 26 | Set findAllIds(); 27 | 28 | } 29 | -------------------------------------------------------------------------------- /bot-context/src/main/java/dev/struchkov/bot/gitlab/context/repository/ProjectRepository.java: -------------------------------------------------------------------------------- 1 | package dev.struchkov.bot.gitlab.context.repository; 2 | 3 | import dev.struchkov.bot.gitlab.context.domain.entity.Project; 4 | import org.springframework.data.domain.Page; 5 | import org.springframework.data.domain.Pageable; 6 | 7 | import java.util.List; 8 | import java.util.Optional; 9 | import java.util.Set; 10 | 11 | /** 12 | * @author upagge 14.01.2021 13 | */ 14 | public interface ProjectRepository { 15 | 16 | Project save(Project project); 17 | 18 | Optional findById(Long projectId); 19 | 20 | List findAllById(Set projectIds); 21 | 22 | boolean existById(Long projectId); 23 | 24 | Page findAllById(Pageable pagination); 25 | 26 | Set findAllIdByProcessingEnable(); 27 | 28 | Optional findProjectNameById(Long projectId); 29 | 30 | Set findAllIds(); 31 | 32 | void notification(boolean enable, Set projectIds); 33 | 34 | void processing(boolean enable, Set projectIds); 35 | 36 | } 37 | -------------------------------------------------------------------------------- /bot-context/src/main/java/dev/struchkov/bot/gitlab/context/service/AppSettingService.java: -------------------------------------------------------------------------------- 1 | package dev.struchkov.bot.gitlab.context.service; 2 | 3 | import dev.struchkov.bot.gitlab.context.domain.notify.level.DiscussionLevel; 4 | 5 | import java.util.UUID; 6 | 7 | /** 8 | * Сервис отвечает за пользовательские настройки приложения. 9 | * 10 | * @author upagge 16.01.2021 11 | */ 12 | public interface AppSettingService { 13 | 14 | /** 15 | * Метод позволяет проверить запускается ли приложение впервые. 16 | * 17 | * @return true - если это первый запуск 18 | */ 19 | boolean isFirstStart(); 20 | 21 | /** 22 | * Метод отмечает, что приложение было запущено. 23 | * 24 | * @see AppSettingService#isFirstStart() 25 | */ 26 | void disableFirstStart(); 27 | 28 | boolean isEnableAllNotify(); 29 | 30 | void turnOnAllNotify(); 31 | 32 | void privateProjectScan(boolean enable); 33 | 34 | void ownerProjectScan(boolean enable); 35 | 36 | boolean isOwnerProjectScan(); 37 | 38 | boolean isPrivateProjectScan(); 39 | 40 | DiscussionLevel getLevelDiscussionNotify(); 41 | 42 | void setDiscussionLevel(DiscussionLevel level); 43 | 44 | UUID getServiceKey(); 45 | 46 | } 47 | -------------------------------------------------------------------------------- /bot-context/src/main/java/dev/struchkov/bot/gitlab/context/service/DiscussionService.java: -------------------------------------------------------------------------------- 1 | package dev.struchkov.bot.gitlab.context.service; 2 | 3 | import dev.struchkov.bot.gitlab.context.domain.ExistContainer; 4 | import dev.struchkov.bot.gitlab.context.domain.entity.Discussion; 5 | import lombok.NonNull; 6 | 7 | import java.util.List; 8 | import java.util.Set; 9 | 10 | /** 11 | * @author upagge 11.02.2021 12 | */ 13 | public interface DiscussionService { 14 | 15 | Discussion create(@NonNull Discussion discussion); 16 | 17 | Discussion update(@NonNull Discussion discussion); 18 | 19 | List updateAll(@NonNull List discussions); 20 | 21 | /** 22 | * Метод отправляющий коментарий в дискуссию. 23 | * 24 | * @param discussionId Идентификатор дискуссии 25 | * @param text Текст комментария 26 | */ 27 | void answer(@NonNull String discussionId, @NonNull String text); 28 | 29 | /** 30 | * Получить все дискусси для MR. 31 | */ 32 | List getAllByMergeRequestId(@NonNull Long mergeRequestId); 33 | 34 | ExistContainer existsById(@NonNull Set discussionIds); 35 | 36 | List createAll(@NonNull List newDiscussions); 37 | 38 | List getAll(); 39 | 40 | Set getAllIds(); 41 | 42 | void deleteById(@NonNull String discussionId); 43 | 44 | void cleanOld(); 45 | 46 | void notification(boolean enable, String discussionId); 47 | 48 | } 49 | -------------------------------------------------------------------------------- /bot-context/src/main/java/dev/struchkov/bot/gitlab/context/service/MergeRequestsService.java: -------------------------------------------------------------------------------- 1 | package dev.struchkov.bot.gitlab.context.service; 2 | 3 | import dev.struchkov.bot.gitlab.context.domain.ExistContainer; 4 | import dev.struchkov.bot.gitlab.context.domain.IdAndStatusPr; 5 | import dev.struchkov.bot.gitlab.context.domain.MergeRequestState; 6 | import dev.struchkov.bot.gitlab.context.domain.entity.MergeRequest; 7 | import dev.struchkov.bot.gitlab.context.domain.entity.MergeRequestForDiscussion; 8 | import lombok.NonNull; 9 | 10 | import java.util.List; 11 | import java.util.Set; 12 | 13 | public interface MergeRequestsService { 14 | 15 | MergeRequest create(@NonNull MergeRequest mergeRequest); 16 | 17 | MergeRequest update(@NonNull MergeRequest mergeRequest); 18 | 19 | List updateAll(@NonNull List mergeRequests); 20 | 21 | /** 22 | * Получить все идентификаторы вместе со статусами. 23 | * 24 | * @param statuses Статусы ПРов 25 | * @return Объект, содержащий идентификатор и статус ПР 26 | */ 27 | Set getAllId(Set statuses); 28 | 29 | List getAllForDiscussion(); 30 | 31 | ExistContainer existsById(@NonNull Set mergeRequestIds); 32 | 33 | List createAll(List newMergeRequests); 34 | 35 | List getAllByReviewerId(@NonNull Long personId); 36 | 37 | void cleanOld(); 38 | 39 | Set getAllIds(); 40 | 41 | void notification(boolean enable, @NonNull Long mrId); 42 | 43 | void notificationByProjectId(boolean enable, @NonNull Set projectIds); 44 | 45 | } 46 | -------------------------------------------------------------------------------- /bot-context/src/main/java/dev/struchkov/bot/gitlab/context/service/MessageSendService.java: -------------------------------------------------------------------------------- 1 | package dev.struchkov.bot.gitlab.context.service; 2 | 3 | import lombok.NonNull; 4 | import dev.struchkov.bot.gitlab.context.domain.notify.Notify; 5 | 6 | @FunctionalInterface 7 | public interface MessageSendService { 8 | 9 | void send(@NonNull Notify notify); 10 | 11 | } 12 | -------------------------------------------------------------------------------- /bot-context/src/main/java/dev/struchkov/bot/gitlab/context/service/NoteService.java: -------------------------------------------------------------------------------- 1 | package dev.struchkov.bot.gitlab.context.service; 2 | 3 | import dev.struchkov.bot.gitlab.context.domain.entity.Note; 4 | import lombok.NonNull; 5 | import org.springframework.data.domain.Page; 6 | import org.springframework.data.domain.Pageable; 7 | 8 | import java.util.List; 9 | 10 | public interface NoteService { 11 | 12 | List getAllPersonTask(@NonNull Long userId, boolean resolved); 13 | 14 | //TODO [28.01.2022]: Решить нужно ли оставлять 15 | Page getAllByResolved(boolean resolved, @NonNull Pageable pagination); 16 | 17 | Note getByIdOrThrow(@NonNull Long noteId); 18 | 19 | } 20 | -------------------------------------------------------------------------------- /bot-context/src/main/java/dev/struchkov/bot/gitlab/context/service/NotifyService.java: -------------------------------------------------------------------------------- 1 | package dev.struchkov.bot.gitlab.context.service; 2 | 3 | import dev.struchkov.bot.gitlab.context.domain.notify.Notify; 4 | 5 | /** 6 | * Сервис по работе с изменениями в битбакете. 7 | * 8 | * @author upagge 9 | * @see Notify 10 | */ 11 | public interface NotifyService { 12 | 13 | void send(T notify); 14 | 15 | } 16 | -------------------------------------------------------------------------------- /bot-context/src/main/java/dev/struchkov/bot/gitlab/context/service/PersonService.java: -------------------------------------------------------------------------------- 1 | package dev.struchkov.bot.gitlab.context.service; 2 | 3 | import dev.struchkov.bot.gitlab.context.domain.ExistContainer; 4 | import dev.struchkov.bot.gitlab.context.domain.entity.Person; 5 | import lombok.NonNull; 6 | 7 | import java.util.List; 8 | import java.util.Set; 9 | 10 | /** 11 | * @author upagge 15.01.2021 12 | */ 13 | public interface PersonService { 14 | 15 | Person create(@NonNull Person person); 16 | 17 | Person update(@NonNull Person person); 18 | 19 | Person getByIdOrThrown(@NonNull Long personId); 20 | 21 | ExistContainer existsById(Set personIds); 22 | 23 | List createAll(List newPersons); 24 | 25 | } 26 | -------------------------------------------------------------------------------- /bot-context/src/main/java/dev/struchkov/bot/gitlab/context/service/PipelineService.java: -------------------------------------------------------------------------------- 1 | package dev.struchkov.bot.gitlab.context.service; 2 | 3 | import dev.struchkov.bot.gitlab.context.domain.ExistContainer; 4 | import dev.struchkov.bot.gitlab.context.domain.PipelineStatus; 5 | import dev.struchkov.bot.gitlab.context.domain.entity.Pipeline; 6 | import lombok.NonNull; 7 | 8 | import java.util.List; 9 | import java.util.Set; 10 | 11 | /** 12 | * Сервис для работы с пайплайнами 13 | * 14 | * @author upagge 17.01.2021 15 | */ 16 | public interface PipelineService { 17 | 18 | Pipeline create(@NonNull Pipeline pipeline); 19 | 20 | List createAll(@NonNull List newPipelines); 21 | 22 | Pipeline update(@NonNull Pipeline pipeline); 23 | 24 | List updateAll(@NonNull List pipelines); 25 | 26 | List getAllByStatuses(@NonNull Set statuses); 27 | 28 | ExistContainer existsById(@NonNull Set pipelineIds); 29 | 30 | void cleanOld(); 31 | 32 | Set getAllIds(); 33 | 34 | } 35 | -------------------------------------------------------------------------------- /bot-context/src/main/java/dev/struchkov/bot/gitlab/context/service/ProjectService.java: -------------------------------------------------------------------------------- 1 | package dev.struchkov.bot.gitlab.context.service; 2 | 3 | import dev.struchkov.bot.gitlab.context.domain.ExistContainer; 4 | import dev.struchkov.bot.gitlab.context.domain.entity.Project; 5 | import lombok.NonNull; 6 | 7 | import java.util.List; 8 | import java.util.Optional; 9 | import java.util.Set; 10 | 11 | /** 12 | * @author upagge 14.01.2021 13 | */ 14 | public interface ProjectService { 15 | 16 | Project create(@NonNull Project project, boolean sendNotify); 17 | 18 | Project update(@NonNull Project project); 19 | 20 | Project getByIdOrThrow(@NonNull Long projectId); 21 | 22 | List createAll(List newProjects); 23 | 24 | boolean existsById(Long projectId); 25 | 26 | ExistContainer existsById(Set projectIds); 27 | 28 | Set getAllIdByProcessingEnable(); 29 | 30 | Optional getProjectNameById(Long projectId); 31 | 32 | Set getAllIds(); 33 | 34 | void notification(boolean enable, Set projectIds); 35 | 36 | void processing(boolean enable, Set projectIds); 37 | 38 | } 39 | -------------------------------------------------------------------------------- /bot-context/src/main/java/dev/struchkov/bot/gitlab/context/utils/Icons.java: -------------------------------------------------------------------------------- 1 | package dev.struchkov.bot.gitlab.context.utils; 2 | 3 | import static dev.struchkov.haiti.utils.Exceptions.utilityClass; 4 | import static dev.struchkov.haiti.utils.Strings.escapeMarkdown; 5 | 6 | public class Icons { 7 | 8 | public static final String HR = "\n-- -- -- -- --\n"; 9 | 10 | public static final String FUN = "\uD83C\uDF89"; 11 | public static final String VIEW = "\uD83D\uDC40"; 12 | public static final String TREE = "\uD83C\uDF33"; 13 | public static final String AUTHOR = "\uD83D\uDC68\u200D\uD83D\uDCBB️"; 14 | public static final String UPDATE = "\uD83D\uDD04"; 15 | public static final String COMMENT = "\uD83D\uDCAC"; 16 | public static final String THREAD = "\uD83E\uDDF5"; 17 | public static final String ARROW = " ➜ "; 18 | public static final String DANGEROUS = "⚠️"; 19 | public static final String GREEN_CIRCLE = "\uD83D\uDFE2"; 20 | public static final String PEN = "✏️"; 21 | public static final String ASSIGNEE = "\uD83C\uDFA9"; 22 | public static final String BUILD = "⚙️"; 23 | public static final String LINK = "\uD83D\uDD17"; 24 | public static final String REVIEWER = "\uD83D\uDD0E"; 25 | public static final String PROJECT = "\uD83C\uDFD7"; 26 | public static final String DISABLE_NOTIFY = "\uD83D\uDD15"; 27 | public static final String YES = "✅"; 28 | public static final String NO = "❌"; 29 | public static final String NOTIFY = "\uD83D\uDD14"; 30 | public static final String GOOD = "\uD83D\uDC4D"; 31 | 32 | private Icons() { 33 | utilityClass(); 34 | } 35 | 36 | public static String link(String title, String url) { 37 | return "[" + escapeMarkdown(title) + "](" + url + ")"; 38 | } 39 | 40 | } 41 | -------------------------------------------------------------------------------- /bot-core/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4.0.0 4 | 5 | dev.struchkov.bot.gitlab 6 | gitlab-bot 7 | 1.0.0 8 | 9 | 10 | bot-core 11 | 12 | 13 | 14 | dev.struchkov.haiti.filter 15 | haiti-filter-criteria 16 | 17 | 18 | 19 | dev.struchkov.bot.gitlab 20 | bot-context 21 | 22 | 23 | 24 | org.springframework.boot 25 | spring-boot-configuration-processor 26 | 27 | 28 | 29 | com.google.guava 30 | guava 31 | 32 | 33 | 34 | org.springframework.boot 35 | spring-boot-starter 36 | 37 | 38 | 39 | org.springframework.boot 40 | spring-boot-devtools 41 | runtime 42 | true 43 | 44 | 45 | 46 | org.springframework.boot 47 | spring-boot-starter-data-jpa 48 | 49 | 50 | 51 | org.postgresql 52 | postgresql 53 | 54 | 55 | 56 | dev.struchkov.bot.gitlab 57 | gitlab-sdk 58 | 59 | 60 | 61 | org.projectlombok 62 | lombok 63 | true 64 | 65 | 66 | 67 | com.squareup.okhttp3 68 | okhttp 69 | 70 | 71 | 72 | com.fasterxml.jackson.core 73 | jackson-databind 74 | 75 | 76 | 77 | org.hibernate.validator 78 | hibernate-validator 79 | 80 | 81 | 82 | javax.el 83 | javax.el-api 84 | 3.0.0 85 | 86 | 87 | org.glassfish 88 | jakarta.el 89 | 4.0.2 90 | 91 | 92 | 93 | -------------------------------------------------------------------------------- /bot-core/src/main/java/dev/struchkov/bot/gitlab/core/config/CoreConfig.java: -------------------------------------------------------------------------------- 1 | package dev.struchkov.bot.gitlab.core.config; 2 | 3 | import org.springframework.context.annotation.Bean; 4 | import org.springframework.context.annotation.Configuration; 5 | 6 | import java.util.concurrent.ForkJoinPool; 7 | 8 | @Configuration 9 | public class CoreConfig { 10 | 11 | @Bean("parserPool") 12 | public ForkJoinPool parserPool() { 13 | return new ForkJoinPool(4); 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /bot-core/src/main/java/dev/struchkov/bot/gitlab/core/config/properties/AppProperty.java: -------------------------------------------------------------------------------- 1 | package dev.struchkov.bot.gitlab.core.config.properties; 2 | 3 | import lombok.Getter; 4 | import lombok.Setter; 5 | import org.springframework.boot.context.properties.ConfigurationProperties; 6 | import org.springframework.context.annotation.Configuration; 7 | 8 | /** 9 | * Основные настройки приложения. 10 | * 11 | * @author upagge 11.10.2020 12 | */ 13 | @Getter 14 | @Setter 15 | @Configuration 16 | @ConfigurationProperties(prefix = "gitlab-bot") 17 | public class AppProperty { 18 | 19 | private String version; 20 | 21 | } 22 | -------------------------------------------------------------------------------- /bot-core/src/main/java/dev/struchkov/bot/gitlab/core/config/properties/GitlabProperty.java: -------------------------------------------------------------------------------- 1 | package dev.struchkov.bot.gitlab.core.config.properties; 2 | 3 | import lombok.Getter; 4 | import lombok.Setter; 5 | import org.springframework.boot.context.properties.ConfigurationProperties; 6 | import org.springframework.stereotype.Component; 7 | 8 | /** 9 | * Данные необходимые для взаимодействия с API GitLab. 10 | * 11 | * @author upagge [31.01.2020] 12 | */ 13 | @Getter 14 | @Setter 15 | @Component 16 | @ConfigurationProperties("gitlab-bot.gitlab") 17 | public class GitlabProperty { 18 | 19 | private String baseUrl; 20 | 21 | private String replaceUrl; 22 | 23 | private String usersUrl; 24 | 25 | private String userUrl; 26 | 27 | private String projectsUrl; 28 | 29 | /** 30 | * Адрес, по которому можно получить открытые MR 31 | */ 32 | private String openMergeRequestsUrl; 33 | 34 | /** 35 | * Адрес, по которому можно получить закрытые MR 36 | */ 37 | private String closeMergeRequestsUrl; 38 | 39 | /** 40 | * Адрес, по которому можно получить комментарии к MR 41 | */ 42 | private String commentsOfMergeRequestUrl; 43 | 44 | /** 45 | * Адрес MR 46 | */ 47 | private String mergeRequestUrl; 48 | 49 | private String projectAddUrl; 50 | 51 | private String noteUrl; 52 | 53 | private String notesOfMergeRequestUrl; 54 | 55 | private String pipelinesUrl; 56 | 57 | private String pipelineUrl; 58 | 59 | private String lastCommitOfMergeRequestUrl; 60 | 61 | private String newNoteUrl; 62 | 63 | /** 64 | * Адрес дискуссий для MR 65 | */ 66 | private String discussionsUrl; 67 | 68 | private String discussionUrl; 69 | 70 | 71 | } 72 | -------------------------------------------------------------------------------- /bot-core/src/main/java/dev/struchkov/bot/gitlab/core/config/properties/PersonProperty.java: -------------------------------------------------------------------------------- 1 | package dev.struchkov.bot.gitlab.core.config.properties; 2 | 3 | import lombok.Getter; 4 | import lombok.Setter; 5 | import org.springframework.boot.context.properties.ConfigurationProperties; 6 | import org.springframework.context.annotation.Configuration; 7 | 8 | /** 9 | * @author upagge 15.01.2021 10 | */ 11 | 12 | @Getter 13 | @Setter 14 | @Configuration 15 | @ConfigurationProperties(prefix = "gitlab-bot.person") 16 | public class PersonProperty { 17 | 18 | private String token; 19 | private String telegramId; 20 | 21 | } 22 | -------------------------------------------------------------------------------- /bot-core/src/main/java/dev/struchkov/bot/gitlab/core/service/convert/DiscussionJsonConverter.java: -------------------------------------------------------------------------------- 1 | package dev.struchkov.bot.gitlab.core.service.convert; 2 | 3 | import dev.struchkov.bot.gitlab.context.domain.entity.Discussion; 4 | import dev.struchkov.bot.gitlab.sdk.domain.DiscussionJson; 5 | import lombok.RequiredArgsConstructor; 6 | import org.springframework.core.convert.converter.Converter; 7 | import org.springframework.stereotype.Component; 8 | 9 | /** 10 | * @author upagge 11.02.2021 11 | */ 12 | @Component 13 | @RequiredArgsConstructor 14 | public class DiscussionJsonConverter implements Converter { 15 | 16 | private final NoteJsonConvert noteJsonConvert; 17 | 18 | @Override 19 | public Discussion convert(DiscussionJson source) { 20 | final Discussion discussion = new Discussion(); 21 | discussion.setId(source.getId()); 22 | discussion.setNotes( 23 | source.getNotes().stream() 24 | .filter(noteJson -> !noteJson.isSystem()) 25 | .map(noteJsonConvert::convert) 26 | .toList() 27 | ); 28 | return discussion; 29 | } 30 | 31 | } 32 | -------------------------------------------------------------------------------- /bot-core/src/main/java/dev/struchkov/bot/gitlab/core/service/convert/MergeRequestJsonConverter.java: -------------------------------------------------------------------------------- 1 | package dev.struchkov.bot.gitlab.core.service.convert; 2 | 3 | import dev.struchkov.bot.gitlab.context.domain.MergeRequestState; 4 | import dev.struchkov.bot.gitlab.context.domain.entity.MergeRequest; 5 | import dev.struchkov.bot.gitlab.context.domain.entity.Person; 6 | import dev.struchkov.bot.gitlab.sdk.domain.MergeRequestJson; 7 | import dev.struchkov.bot.gitlab.sdk.domain.MergeRequestStateJson; 8 | import dev.struchkov.bot.gitlab.sdk.domain.PersonJson; 9 | import lombok.RequiredArgsConstructor; 10 | import org.springframework.core.convert.converter.Converter; 11 | import org.springframework.stereotype.Component; 12 | 13 | import java.util.List; 14 | import java.util.Set; 15 | import java.util.stream.Collectors; 16 | 17 | import static dev.struchkov.haiti.utils.Checker.checkNotEmpty; 18 | import static dev.struchkov.haiti.utils.Checker.checkNotNull; 19 | 20 | /** 21 | * @author upagge 15.01.2021 22 | */ 23 | @Component 24 | @RequiredArgsConstructor 25 | public class MergeRequestJsonConverter implements Converter { 26 | 27 | private final PersonJsonConverter convertPerson; 28 | 29 | @Override 30 | public MergeRequest convert(MergeRequestJson source) { 31 | final MergeRequest mergeRequest = new MergeRequest(); 32 | mergeRequest.setConflict(source.isConflicts()); 33 | mergeRequest.setTitle(source.getTitle()); 34 | mergeRequest.setCreatedDate(source.getCreatedDate()); 35 | mergeRequest.setDescription(source.getDescription()); 36 | mergeRequest.setId(source.getId()); 37 | mergeRequest.setTwoId(source.getTwoId()); 38 | mergeRequest.setUpdatedDate(source.getUpdatedDate()); 39 | mergeRequest.setState(convertState(source.getState())); 40 | mergeRequest.setProjectId(source.getProjectId()); 41 | mergeRequest.setWebUrl(source.getWebUrl()); 42 | 43 | convertLabels(mergeRequest, source.getLabels()); 44 | convertReviewers(mergeRequest, source.getReviewers()); 45 | 46 | if (checkNotNull(source.getAssignee())) { 47 | mergeRequest.setAssignee(convertPerson.convert(source.getAssignee())); 48 | } 49 | 50 | mergeRequest.setAuthor(convertPerson.convert(source.getAuthor())); 51 | mergeRequest.setSourceBranch(source.getSourceBranch()); 52 | mergeRequest.setTargetBranch(source.getTargetBranch()); 53 | return mergeRequest; 54 | } 55 | 56 | private void convertReviewers(MergeRequest mergeRequest, List jsonReviewers) { 57 | if (checkNotEmpty(jsonReviewers)) { 58 | final List reviewers = jsonReviewers.stream() 59 | .map(convertPerson::convert) 60 | .toList(); 61 | mergeRequest.setReviewers(reviewers); 62 | } 63 | } 64 | 65 | private static void convertLabels(MergeRequest mergeRequest, Set source) { 66 | if (checkNotEmpty(source)) { 67 | final Set labels = source.stream() 68 | .map(label -> label.replace("-", "_")) 69 | .collect(Collectors.toSet()); 70 | mergeRequest.setLabels(labels); 71 | } 72 | } 73 | 74 | private MergeRequestState convertState(MergeRequestStateJson state) { 75 | return switch (state) { 76 | case CLOSED -> MergeRequestState.CLOSED; 77 | case LOCKED -> MergeRequestState.LOCKED; 78 | case MERGED -> MergeRequestState.MERGED; 79 | case OPENED -> MergeRequestState.OPENED; 80 | }; 81 | } 82 | 83 | } 84 | -------------------------------------------------------------------------------- /bot-core/src/main/java/dev/struchkov/bot/gitlab/core/service/convert/NoteJsonConvert.java: -------------------------------------------------------------------------------- 1 | package dev.struchkov.bot.gitlab.core.service.convert; 2 | 3 | import dev.struchkov.bot.gitlab.context.domain.entity.Note; 4 | import dev.struchkov.bot.gitlab.sdk.domain.NoteJson; 5 | import lombok.RequiredArgsConstructor; 6 | import org.springframework.core.convert.converter.Converter; 7 | import org.springframework.stereotype.Component; 8 | 9 | /** 10 | * @author upagge 12.09.2020 11 | */ 12 | @Component 13 | @RequiredArgsConstructor 14 | public class NoteJsonConvert implements Converter { 15 | 16 | private final PersonJsonConverter personConverter; 17 | 18 | @Override 19 | public Note convert(NoteJson source) { 20 | final Note note = new Note(); 21 | note.setAuthor(personConverter.convert(source.getAuthor())); 22 | note.setId(source.getId()); 23 | note.setBody(source.getBody()); 24 | note.setType(source.getType()); 25 | note.setNoteableType(source.getNoteableType()); 26 | note.setCreated(source.getCreated()); 27 | note.setUpdated(source.getUpdated()); 28 | note.setNoteableId(source.getNoteableId()); 29 | note.setNoteableIid(source.getNoteableIid()); 30 | note.setResolved(source.getResolved()); 31 | note.setResolvable(source.isResolvable()); 32 | if (source.getResolvedBy() != null) { 33 | note.setResolvedBy(personConverter.convert(source.getResolvedBy())); 34 | } 35 | return note; 36 | } 37 | 38 | } 39 | -------------------------------------------------------------------------------- /bot-core/src/main/java/dev/struchkov/bot/gitlab/core/service/convert/PersonJsonConverter.java: -------------------------------------------------------------------------------- 1 | package dev.struchkov.bot.gitlab.core.service.convert; 2 | 3 | import dev.struchkov.bot.gitlab.context.domain.entity.Person; 4 | import dev.struchkov.bot.gitlab.sdk.domain.PersonJson; 5 | import org.springframework.core.convert.converter.Converter; 6 | import org.springframework.stereotype.Component; 7 | 8 | /** 9 | * @author upagge 15.01.2021 10 | */ 11 | @Component 12 | public class PersonJsonConverter implements Converter { 13 | 14 | @Override 15 | public Person convert(PersonJson source) { 16 | final Person person = new Person(); 17 | person.setId(source.getId()); 18 | person.setName(source.getName()); 19 | person.setUserName(source.getUsername()); 20 | person.setWebUrl(source.getWebUrl()); 21 | return person; 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /bot-core/src/main/java/dev/struchkov/bot/gitlab/core/service/convert/PipelineJsonConverter.java: -------------------------------------------------------------------------------- 1 | package dev.struchkov.bot.gitlab.core.service.convert; 2 | 3 | import dev.struchkov.bot.gitlab.context.domain.PipelineStatus; 4 | import dev.struchkov.bot.gitlab.context.domain.entity.Pipeline; 5 | import dev.struchkov.bot.gitlab.sdk.domain.PipelineJson; 6 | import dev.struchkov.bot.gitlab.sdk.domain.PipelineStatusJson; 7 | import lombok.RequiredArgsConstructor; 8 | import org.springframework.core.convert.converter.Converter; 9 | import org.springframework.stereotype.Component; 10 | 11 | import static dev.struchkov.bot.gitlab.context.domain.PipelineStatus.CANCELED; 12 | import static dev.struchkov.bot.gitlab.context.domain.PipelineStatus.CREATED; 13 | import static dev.struchkov.bot.gitlab.context.domain.PipelineStatus.FAILED; 14 | import static dev.struchkov.bot.gitlab.context.domain.PipelineStatus.MANUAL; 15 | import static dev.struchkov.bot.gitlab.context.domain.PipelineStatus.PENDING; 16 | import static dev.struchkov.bot.gitlab.context.domain.PipelineStatus.PREPARING; 17 | import static dev.struchkov.bot.gitlab.context.domain.PipelineStatus.RUNNING; 18 | import static dev.struchkov.bot.gitlab.context.domain.PipelineStatus.SCHEDULED; 19 | import static dev.struchkov.bot.gitlab.context.domain.PipelineStatus.SKIPPED; 20 | import static dev.struchkov.bot.gitlab.context.domain.PipelineStatus.SUCCESS; 21 | import static dev.struchkov.bot.gitlab.context.domain.PipelineStatus.WAITING_FOR_RESOURCE; 22 | 23 | /** 24 | * @author upagge 17.01.2021 25 | */ 26 | @Component 27 | @RequiredArgsConstructor 28 | public class PipelineJsonConverter implements Converter { 29 | 30 | private final PersonJsonConverter convertPerson; 31 | 32 | @Override 33 | public Pipeline convert(PipelineJson source) { 34 | final Pipeline pipeline = new Pipeline(); 35 | pipeline.setId(source.getId()); 36 | pipeline.setCreated(source.getCreated()); 37 | pipeline.setUpdated(source.getUpdated()); 38 | pipeline.setRef(source.getRef()); 39 | pipeline.setWebUrl(source.getWebUrl()); 40 | pipeline.setStatus(convertStatus(source.getStatus())); 41 | pipeline.setPerson(convertPerson.convert(source.getUser())); 42 | 43 | pipeline.setProjectId(source.getProjectId()); 44 | return pipeline; 45 | } 46 | 47 | private PipelineStatus convertStatus(PipelineStatusJson status) { 48 | return switch (status) { 49 | case SKIPPED -> SKIPPED; 50 | case CANCELED -> CANCELED; 51 | case SUCCESS -> SUCCESS; 52 | case MANUAL -> MANUAL; 53 | case CREATED -> CREATED; 54 | case PENDING -> PENDING; 55 | case RUNNING -> RUNNING; 56 | case PREPARING -> PREPARING; 57 | case SCHEDULED -> SCHEDULED; 58 | case WAITING_FOR_RESOURCE -> WAITING_FOR_RESOURCE; 59 | default -> FAILED; 60 | }; 61 | } 62 | 63 | } 64 | -------------------------------------------------------------------------------- /bot-core/src/main/java/dev/struchkov/bot/gitlab/core/service/convert/ProjectJsonConverter.java: -------------------------------------------------------------------------------- 1 | package dev.struchkov.bot.gitlab.core.service.convert; 2 | 3 | import dev.struchkov.bot.gitlab.context.domain.entity.Project; 4 | import dev.struchkov.bot.gitlab.sdk.domain.ProjectJson; 5 | import lombok.RequiredArgsConstructor; 6 | import org.springframework.core.convert.converter.Converter; 7 | import org.springframework.stereotype.Component; 8 | 9 | /** 10 | * @author upagge 14.01.2021 11 | */ 12 | @Component 13 | @RequiredArgsConstructor 14 | public class ProjectJsonConverter implements Converter { 15 | 16 | @Override 17 | public Project convert(ProjectJson source) { 18 | final Project project = new Project(); 19 | project.setId(source.getId()); 20 | project.setCreatedDate(source.getCreatedDate()); 21 | project.setCreatorId(source.getCreatorId()); 22 | project.setDescription(source.getDescription()); 23 | project.setName(source.getName()); 24 | project.setWebUrl(source.getWebUrl()); 25 | project.setHttpUrlToRepo(source.getHttpUrlToRepo()); 26 | project.setSshUrlToRepo(source.getSshUrlToRepo()); 27 | return project; 28 | } 29 | 30 | } 31 | -------------------------------------------------------------------------------- /bot-core/src/main/java/dev/struchkov/bot/gitlab/core/service/impl/NotifyServiceImpl.java: -------------------------------------------------------------------------------- 1 | package dev.struchkov.bot.gitlab.core.service.impl; 2 | 3 | import dev.struchkov.bot.gitlab.context.domain.notify.Notify; 4 | import dev.struchkov.bot.gitlab.context.service.AppSettingService; 5 | import dev.struchkov.bot.gitlab.context.service.MessageSendService; 6 | import dev.struchkov.bot.gitlab.context.service.NotifyService; 7 | import org.springframework.context.annotation.Lazy; 8 | import org.springframework.stereotype.Service; 9 | 10 | @Service 11 | public class NotifyServiceImpl implements NotifyService { 12 | 13 | private final MessageSendService messageSendService; 14 | private final AppSettingService settingService; 15 | 16 | public NotifyServiceImpl( 17 | @Lazy MessageSendService messageSendService, 18 | AppSettingService settingService 19 | ) { 20 | this.messageSendService = messageSendService; 21 | this.settingService = settingService; 22 | } 23 | 24 | @Override 25 | public void send(T notify) { 26 | if (settingService.isEnableAllNotify()) { 27 | messageSendService.send(notify); 28 | } 29 | } 30 | 31 | } 32 | -------------------------------------------------------------------------------- /bot-core/src/main/java/dev/struchkov/bot/gitlab/core/service/impl/PersonServiceImpl.java: -------------------------------------------------------------------------------- 1 | package dev.struchkov.bot.gitlab.core.service.impl; 2 | 3 | import dev.struchkov.bot.gitlab.context.domain.ExistContainer; 4 | import dev.struchkov.bot.gitlab.context.domain.entity.Person; 5 | import dev.struchkov.bot.gitlab.context.repository.PersonRepository; 6 | import dev.struchkov.bot.gitlab.context.service.PersonService; 7 | import lombok.NonNull; 8 | import lombok.RequiredArgsConstructor; 9 | import org.springframework.stereotype.Service; 10 | import org.springframework.transaction.annotation.Transactional; 11 | 12 | import java.util.List; 13 | import java.util.Set; 14 | import java.util.stream.Collectors; 15 | 16 | import static dev.struchkov.haiti.context.exception.NotFoundException.notFoundException; 17 | 18 | /** 19 | * @author upagge 15.01.2021 20 | */ 21 | @Service 22 | @RequiredArgsConstructor 23 | public class PersonServiceImpl implements PersonService { 24 | 25 | private final PersonRepository repository; 26 | 27 | @Override 28 | public Person create(@NonNull Person person) { 29 | return repository.save(person); 30 | } 31 | 32 | @Override 33 | public Person update(@NonNull Person person) { 34 | return repository.save(person); 35 | } 36 | 37 | @Override 38 | @Transactional(readOnly = true) 39 | public Person getByIdOrThrown(@NonNull Long personId) { 40 | return repository.findById(personId) 41 | .orElseThrow(notFoundException("Пользователь не найден")); 42 | } 43 | 44 | @Override 45 | @Transactional(readOnly = true) 46 | public ExistContainer existsById(Set personIds) { 47 | final List existsEntity = repository.findAllById(personIds); 48 | final Set existsIds = existsEntity.stream().map(Person::getId).collect(Collectors.toSet()); 49 | if (existsIds.containsAll(personIds)) { 50 | return ExistContainer.allFind(existsEntity); 51 | } else { 52 | final Set noExistsId = personIds.stream() 53 | .filter(id -> !existsIds.contains(id)) 54 | .collect(Collectors.toSet()); 55 | return ExistContainer.notAllFind(existsEntity, noExistsId); 56 | } 57 | } 58 | 59 | @Override 60 | @Transactional 61 | public List createAll(List newPersons) { 62 | return newPersons.stream() 63 | .map(this::create) 64 | .toList(); 65 | } 66 | 67 | } 68 | -------------------------------------------------------------------------------- /bot-core/src/main/java/dev/struchkov/bot/gitlab/core/service/impl/note/NoteServiceImpl.java: -------------------------------------------------------------------------------- 1 | package dev.struchkov.bot.gitlab.core.service.impl.note; 2 | 3 | import dev.struchkov.bot.gitlab.context.domain.entity.Note; 4 | import dev.struchkov.bot.gitlab.context.repository.NoteRepository; 5 | import dev.struchkov.bot.gitlab.context.service.NoteService; 6 | import lombok.NonNull; 7 | import lombok.RequiredArgsConstructor; 8 | import lombok.extern.slf4j.Slf4j; 9 | import org.springframework.data.domain.Page; 10 | import org.springframework.data.domain.Pageable; 11 | import org.springframework.stereotype.Service; 12 | 13 | import java.util.List; 14 | 15 | import static dev.struchkov.haiti.context.exception.NotFoundException.notFoundException; 16 | 17 | @Slf4j 18 | @Service 19 | @RequiredArgsConstructor 20 | public class NoteServiceImpl implements NoteService { 21 | 22 | private final NoteRepository noteRepository; 23 | 24 | @Override 25 | public Page getAllByResolved(boolean resolved, @NonNull Pageable pagination) { 26 | return noteRepository.findAllByResolved(resolved, pagination); 27 | } 28 | 29 | @Override 30 | public Note getByIdOrThrow(@NonNull Long noteId) { 31 | return noteRepository.findById(noteId) 32 | .orElseThrow(notFoundException("Note не найдено")); 33 | } 34 | 35 | @Override 36 | public List getAllPersonTask(@NonNull Long userId, boolean resolved) { 37 | return noteRepository.findAllByResponsibleIdAndResolved(userId, resolved); 38 | } 39 | 40 | } 41 | -------------------------------------------------------------------------------- /bot-core/src/main/java/dev/struchkov/bot/gitlab/core/service/parser/forktask/GetAllDiscussionForMergeRequestTask.java: -------------------------------------------------------------------------------- 1 | package dev.struchkov.bot.gitlab.core.service.parser.forktask; 2 | 3 | import dev.struchkov.bot.gitlab.core.utils.HttpParse; 4 | import dev.struchkov.bot.gitlab.sdk.domain.DiscussionJson; 5 | import lombok.AllArgsConstructor; 6 | import lombok.RequiredArgsConstructor; 7 | import lombok.SneakyThrows; 8 | 9 | import java.text.MessageFormat; 10 | import java.util.List; 11 | import java.util.concurrent.RecursiveTask; 12 | 13 | import static dev.struchkov.bot.gitlab.core.utils.HttpParse.ACCEPT; 14 | import static dev.struchkov.bot.gitlab.core.utils.StringUtils.H_PRIVATE_TOKEN; 15 | import static dev.struchkov.haiti.utils.Checker.checkNotEmpty; 16 | 17 | @AllArgsConstructor 18 | @RequiredArgsConstructor 19 | public class GetAllDiscussionForMergeRequestTask extends RecursiveTask> { 20 | 21 | private static final int PAGE_COUNT = 100; 22 | 23 | private final String discussionsUrl; 24 | private final long projectId; 25 | private final long mergeRequestTwoId; 26 | private final String personalGitlabToken; 27 | private int page = 1; 28 | 29 | @Override 30 | @SneakyThrows 31 | protected List compute() { 32 | Thread.sleep(100); 33 | final List jsons = getDiscussionJson(); 34 | if (checkNotEmpty(jsons) && jsons.size() == PAGE_COUNT) { 35 | final var newTask = new GetAllDiscussionForMergeRequestTask(discussionsUrl, projectId, mergeRequestTwoId, personalGitlabToken, page + 1); 36 | newTask.fork(); 37 | jsons.addAll(newTask.join()); 38 | } 39 | return jsons; 40 | } 41 | 42 | private List getDiscussionJson() { 43 | return HttpParse.request(MessageFormat.format(discussionsUrl, projectId, mergeRequestTwoId, page, PAGE_COUNT)) 44 | .header(ACCEPT) 45 | .header(H_PRIVATE_TOKEN, personalGitlabToken) 46 | .executeList(DiscussionJson.class); 47 | } 48 | 49 | } 50 | -------------------------------------------------------------------------------- /bot-core/src/main/java/dev/struchkov/bot/gitlab/core/service/parser/forktask/GetAllMergeRequestForProjectTask.java: -------------------------------------------------------------------------------- 1 | package dev.struchkov.bot.gitlab.core.service.parser.forktask; 2 | 3 | import dev.struchkov.bot.gitlab.core.utils.HttpParse; 4 | import dev.struchkov.bot.gitlab.core.utils.StringUtils; 5 | import dev.struchkov.bot.gitlab.sdk.domain.MergeRequestJson; 6 | import lombok.AllArgsConstructor; 7 | import lombok.RequiredArgsConstructor; 8 | import lombok.SneakyThrows; 9 | import lombok.extern.slf4j.Slf4j; 10 | 11 | import java.text.MessageFormat; 12 | import java.util.List; 13 | import java.util.concurrent.RecursiveTask; 14 | 15 | import static dev.struchkov.bot.gitlab.core.utils.HttpParse.ACCEPT; 16 | import static dev.struchkov.haiti.utils.Checker.checkNotEmpty; 17 | 18 | @Slf4j 19 | @AllArgsConstructor 20 | @RequiredArgsConstructor 21 | public class GetAllMergeRequestForProjectTask extends RecursiveTask> { 22 | 23 | private static final int PAGE_COUNT = 100; 24 | 25 | private final long projectId; 26 | private int pageNumber = 1; 27 | private final String urlMrOpen; 28 | private final String gitlabToken; 29 | 30 | @Override 31 | @SneakyThrows 32 | protected List compute() { 33 | Thread.sleep(100); 34 | final List mergeRequestJsons = getMergeRequestJsons(); 35 | if (checkNotEmpty(mergeRequestJsons) && mergeRequestJsons.size() == PAGE_COUNT) { 36 | final GetAllMergeRequestForProjectTask newTask = new GetAllMergeRequestForProjectTask(projectId, pageNumber + 1, urlMrOpen, gitlabToken); 37 | newTask.fork(); 38 | mergeRequestJsons.addAll(newTask.join()); 39 | } 40 | return mergeRequestJsons; 41 | } 42 | 43 | private List getMergeRequestJsons() { 44 | final List jsons = HttpParse.request(MessageFormat.format(urlMrOpen, projectId, pageNumber, PAGE_COUNT)) 45 | .header(StringUtils.H_PRIVATE_TOKEN, gitlabToken) 46 | .header(ACCEPT) 47 | .executeList(MergeRequestJson.class); 48 | log.trace("Получено {} шт потенциально новых MR для проекта id:'{}' ", jsons.size(), projectId); 49 | return jsons; 50 | } 51 | 52 | } 53 | -------------------------------------------------------------------------------- /bot-core/src/main/java/dev/struchkov/bot/gitlab/core/service/parser/forktask/GetPipelineShortTask.java: -------------------------------------------------------------------------------- 1 | package dev.struchkov.bot.gitlab.core.service.parser.forktask; 2 | 3 | import dev.struchkov.bot.gitlab.core.utils.HttpParse; 4 | import dev.struchkov.bot.gitlab.core.utils.StringUtils; 5 | import dev.struchkov.bot.gitlab.sdk.domain.PipelineShortJson; 6 | import lombok.AllArgsConstructor; 7 | import lombok.RequiredArgsConstructor; 8 | import lombok.SneakyThrows; 9 | import lombok.extern.slf4j.Slf4j; 10 | 11 | import java.text.MessageFormat; 12 | import java.time.LocalDateTime; 13 | import java.util.List; 14 | import java.util.concurrent.RecursiveTask; 15 | 16 | import static dev.struchkov.bot.gitlab.core.utils.HttpParse.ACCEPT; 17 | 18 | 19 | @Slf4j 20 | @AllArgsConstructor 21 | @RequiredArgsConstructor 22 | public class GetPipelineShortTask extends RecursiveTask> { 23 | 24 | private static final int PAGE_COUNT = 100; 25 | 26 | private final String urlPipelines; 27 | private final long projectId; 28 | private int pageNumber = 1; 29 | private final LocalDateTime lastUpdate; 30 | private final String gitlabToken; 31 | 32 | @Override 33 | @SneakyThrows 34 | protected List compute() { 35 | Thread.sleep(100); 36 | final List jsons = getPipelineJsons(); 37 | if (jsons.size() == PAGE_COUNT) { 38 | final GetPipelineShortTask newTask = new GetPipelineShortTask(urlPipelines, projectId, pageNumber + 1, lastUpdate, gitlabToken); 39 | newTask.fork(); 40 | jsons.addAll(newTask.join()); 41 | } 42 | jsons.forEach(pipelineJson -> pipelineJson.setProjectId(projectId)); 43 | return jsons; 44 | } 45 | 46 | private List getPipelineJsons() { 47 | final List jsons = HttpParse.request(MessageFormat.format(urlPipelines, projectId, pageNumber, PAGE_COUNT)) 48 | .header(ACCEPT) 49 | .header(StringUtils.H_PRIVATE_TOKEN, gitlabToken) 50 | .getParameter("updated_after", lastUpdate.minusHours(12L).toString()) 51 | .executeList(PipelineShortJson.class); 52 | log.trace("Получено {} шт потенциально новых пайплайнов для проекта id:'{}' ", jsons.size(), projectId); 53 | return jsons; 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /bot-core/src/main/java/dev/struchkov/bot/gitlab/core/service/parser/forktask/GetPipelineTask.java: -------------------------------------------------------------------------------- 1 | package dev.struchkov.bot.gitlab.core.service.parser.forktask; 2 | 3 | import dev.struchkov.bot.gitlab.core.utils.HttpParse; 4 | import dev.struchkov.bot.gitlab.core.utils.StringUtils; 5 | import dev.struchkov.bot.gitlab.sdk.domain.PipelineJson; 6 | import lombok.RequiredArgsConstructor; 7 | import lombok.SneakyThrows; 8 | import lombok.extern.slf4j.Slf4j; 9 | 10 | import java.text.MessageFormat; 11 | import java.util.Optional; 12 | import java.util.concurrent.RecursiveTask; 13 | 14 | import static dev.struchkov.bot.gitlab.core.utils.HttpParse.ACCEPT; 15 | 16 | 17 | @Slf4j 18 | @RequiredArgsConstructor 19 | public class GetPipelineTask extends RecursiveTask> { 20 | 21 | private final String urlPipeline; 22 | private final long projectId; 23 | private final long pipelineId; 24 | private final String gitlabToken; 25 | 26 | @Override 27 | @SneakyThrows 28 | protected Optional compute() { 29 | Thread.sleep(100); 30 | return HttpParse.request(MessageFormat.format(urlPipeline, projectId, pipelineId)) 31 | .header(ACCEPT) 32 | .header(StringUtils.H_PRIVATE_TOKEN, gitlabToken) 33 | .execute(PipelineJson.class) 34 | .map(json -> { 35 | json.setProjectId(projectId); 36 | return json; 37 | }); 38 | } 39 | 40 | } 41 | -------------------------------------------------------------------------------- /bot-core/src/main/java/dev/struchkov/bot/gitlab/core/service/parser/forktask/GetSingleMergeRequestTask.java: -------------------------------------------------------------------------------- 1 | package dev.struchkov.bot.gitlab.core.service.parser.forktask; 2 | 3 | import dev.struchkov.bot.gitlab.core.utils.HttpParse; 4 | import dev.struchkov.bot.gitlab.core.utils.StringUtils; 5 | import dev.struchkov.bot.gitlab.sdk.domain.MergeRequestJson; 6 | import lombok.RequiredArgsConstructor; 7 | import lombok.SneakyThrows; 8 | import lombok.extern.slf4j.Slf4j; 9 | 10 | import java.text.MessageFormat; 11 | import java.util.Optional; 12 | import java.util.concurrent.RecursiveTask; 13 | 14 | import static dev.struchkov.bot.gitlab.core.utils.HttpParse.ACCEPT; 15 | 16 | 17 | @Slf4j 18 | @RequiredArgsConstructor 19 | public class GetSingleMergeRequestTask extends RecursiveTask> { 20 | 21 | private final String urlMr; 22 | private final long projectId; 23 | private final long mrTwoId; 24 | private final String gitlabToken; 25 | 26 | @Override 27 | @SneakyThrows 28 | protected Optional compute() { 29 | Thread.sleep(100); 30 | final String mrUrl = MessageFormat.format(urlMr, projectId, mrTwoId); 31 | return HttpParse.request(mrUrl) 32 | .header(ACCEPT) 33 | .header(StringUtils.H_PRIVATE_TOKEN, gitlabToken) 34 | .execute(MergeRequestJson.class); 35 | } 36 | 37 | } 38 | -------------------------------------------------------------------------------- /bot-core/src/main/java/dev/struchkov/bot/gitlab/core/utils/HttpHeader.java: -------------------------------------------------------------------------------- 1 | package dev.struchkov.bot.gitlab.core.utils; 2 | 3 | import static dev.struchkov.haiti.utils.Inspector.isNotNull; 4 | 5 | /** 6 | * Утилитарная сущность для {@link HttpParse}. Упрощает сохранения в константы заголовков для запроса. 7 | * 8 | * @author upagge 23.12.2020 9 | */ 10 | public class HttpHeader { 11 | 12 | private final String name; 13 | private final String value; 14 | 15 | private HttpHeader(String name, String value) { 16 | this.name = name; 17 | this.value = value; 18 | } 19 | 20 | public static HttpHeader of(String name, String value) { 21 | isNotNull(name, value); 22 | return new HttpHeader(name, value); 23 | } 24 | 25 | public String getName() { 26 | return name; 27 | } 28 | 29 | public String getValue() { 30 | return value; 31 | } 32 | 33 | } 34 | -------------------------------------------------------------------------------- /bot-core/src/main/java/dev/struchkov/bot/gitlab/core/utils/OkHttpUtil.java: -------------------------------------------------------------------------------- 1 | package dev.struchkov.bot.gitlab.core.utils; 2 | 3 | import okhttp3.OkHttpClient; 4 | import org.slf4j.Logger; 5 | import org.slf4j.LoggerFactory; 6 | 7 | import javax.net.ssl.SSLContext; 8 | import javax.net.ssl.SSLSocketFactory; 9 | import javax.net.ssl.TrustManager; 10 | import javax.net.ssl.X509TrustManager; 11 | 12 | import static dev.struchkov.haiti.utils.Exceptions.utilityClass; 13 | 14 | public class OkHttpUtil { 15 | 16 | private static final Logger log = LoggerFactory.getLogger(OkHttpUtil.class); 17 | 18 | public OkHttpUtil() { 19 | utilityClass(); 20 | } 21 | 22 | public static void ignoreCertificate(OkHttpClient.Builder builder) { 23 | log.info("Initialising httpUtil with default configuration"); 24 | configureToIgnoreCertificate(builder); 25 | } 26 | 27 | //Setting testMode configuration. If set as testMode, the connection will skip certification check 28 | private static void configureToIgnoreCertificate(OkHttpClient.Builder builder) { 29 | log.warn("Ignore Ssl Certificate"); 30 | try { 31 | 32 | // Create a trust manager that does not validate certificate chains 33 | final TrustManager[] trustAllCerts = new TrustManager[]{ 34 | new X509TrustManager() { 35 | @Override 36 | public void checkClientTrusted(java.security.cert.X509Certificate[] chain, String authType) { 37 | } 38 | 39 | @Override 40 | public void checkServerTrusted(java.security.cert.X509Certificate[] chain, String authType) { 41 | } 42 | 43 | @Override 44 | public java.security.cert.X509Certificate[] getAcceptedIssuers() { 45 | return new java.security.cert.X509Certificate[]{}; 46 | } 47 | } 48 | }; 49 | 50 | final SSLContext sslContext = SSLContext.getInstance("SSL"); 51 | sslContext.init(null, trustAllCerts, new java.security.SecureRandom()); 52 | final SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory(); 53 | 54 | builder.sslSocketFactory(sslSocketFactory, (X509TrustManager) trustAllCerts[0]); 55 | builder.hostnameVerifier((hostname, session) -> true); 56 | } catch (Exception e) { 57 | log.warn("Exception while configuring IgnoreSslCertificate" + e, e); 58 | } 59 | } 60 | 61 | } 62 | -------------------------------------------------------------------------------- /bot-core/src/main/java/dev/struchkov/bot/gitlab/core/utils/StringUtils.java: -------------------------------------------------------------------------------- 1 | package dev.struchkov.bot.gitlab.core.utils; 2 | 3 | import lombok.AccessLevel; 4 | import lombok.NoArgsConstructor; 5 | 6 | /** 7 | * Утилитарный класс для работы со сторками. 8 | * 9 | * @author upagge 29.09.2020 10 | */ 11 | @NoArgsConstructor(access = AccessLevel.PRIVATE) 12 | public class StringUtils { 13 | 14 | public static final String H_PRIVATE_TOKEN = "PRIVATE-TOKEN"; 15 | 16 | } 17 | -------------------------------------------------------------------------------- /bot-data/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4.0.0 4 | 5 | dev.struchkov.bot.gitlab 6 | gitlab-bot 7 | 1.0.0 8 | 9 | 10 | bot-data 11 | 12 | GitLab Server Data 13 | Implementation of the GitLab server version repository layer 14 | 15 | 16 | 17 | dev.struchkov.bot.gitlab 18 | bot-context 19 | 20 | 21 | org.springframework.boot 22 | spring-boot-starter-data-jpa 23 | 24 | 25 | org.liquibase 26 | liquibase-core 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /bot-data/src/main/java/dev/struchkov/bot/gitlab/data/impl/AppSettingRepositoryImpl.java: -------------------------------------------------------------------------------- 1 | package dev.struchkov.bot.gitlab.data.impl; 2 | 3 | import dev.struchkov.bot.gitlab.context.domain.entity.AppSetting; 4 | import dev.struchkov.bot.gitlab.context.repository.AppSettingRepository; 5 | import dev.struchkov.bot.gitlab.data.jpa.AppSettingJpaRepository; 6 | import lombok.RequiredArgsConstructor; 7 | import org.springframework.stereotype.Repository; 8 | 9 | import java.util.Optional; 10 | 11 | /** 12 | * @author upagge 16.01.2021 13 | */ 14 | @Repository 15 | @RequiredArgsConstructor 16 | public class AppSettingRepositoryImpl implements AppSettingRepository { 17 | 18 | private final AppSettingJpaRepository jpaRepository; 19 | 20 | @Override 21 | public AppSetting save(AppSetting appSetting) { 22 | return jpaRepository.save(appSetting); 23 | } 24 | 25 | @Override 26 | public Optional findById(Long key) { 27 | return jpaRepository.findById(key); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /bot-data/src/main/java/dev/struchkov/bot/gitlab/data/impl/DiscussionRepositoryImpl.java: -------------------------------------------------------------------------------- 1 | package dev.struchkov.bot.gitlab.data.impl; 2 | 3 | import dev.struchkov.bot.gitlab.context.domain.entity.Discussion; 4 | import dev.struchkov.bot.gitlab.context.repository.DiscussionRepository; 5 | import dev.struchkov.bot.gitlab.data.jpa.DiscussionJpaRepository; 6 | import lombok.NonNull; 7 | import lombok.RequiredArgsConstructor; 8 | import lombok.extern.slf4j.Slf4j; 9 | import org.springframework.stereotype.Repository; 10 | 11 | import java.util.List; 12 | import java.util.Optional; 13 | import java.util.Set; 14 | 15 | /** 16 | * @author upagge 11.02.2021 17 | */ 18 | @Slf4j 19 | @Repository 20 | @RequiredArgsConstructor 21 | public class DiscussionRepositoryImpl implements DiscussionRepository { 22 | 23 | private final DiscussionJpaRepository jpaRepository; 24 | 25 | @Override 26 | public List findAllByMergeRequestId(@NonNull Long mergeRequestId) { 27 | return jpaRepository.findAllByMergeRequestId(mergeRequestId); 28 | } 29 | 30 | @Override 31 | public Discussion save(Discussion discussion) { 32 | return jpaRepository.save(discussion); 33 | } 34 | 35 | @Override 36 | public Optional findById(String discussionId) { 37 | return jpaRepository.findById(discussionId); 38 | } 39 | 40 | @Override 41 | public List findAll() { 42 | return jpaRepository.findAll(); 43 | } 44 | 45 | @Override 46 | public List findAllById(Set discussionIds) { 47 | return jpaRepository.findAllById(discussionIds); 48 | } 49 | 50 | @Override 51 | public Set findAllIds() { 52 | return jpaRepository.findAllIds(); 53 | } 54 | 55 | @Override 56 | public void deleteById(String id) { 57 | jpaRepository.deleteById(id); 58 | } 59 | 60 | @Override 61 | public void cleanOld() { 62 | jpaRepository.removeAllByMergeRequestIsNull(); 63 | } 64 | 65 | @Override 66 | public void notification(boolean enable, String discussionId) { 67 | jpaRepository.notification(enable, discussionId); 68 | } 69 | 70 | } 71 | -------------------------------------------------------------------------------- /bot-data/src/main/java/dev/struchkov/bot/gitlab/data/impl/MergeRequestRepositoryImpl.java: -------------------------------------------------------------------------------- 1 | package dev.struchkov.bot.gitlab.data.impl; 2 | 3 | import dev.struchkov.bot.gitlab.context.domain.IdAndStatusPr; 4 | import dev.struchkov.bot.gitlab.context.domain.MergeRequestState; 5 | import dev.struchkov.bot.gitlab.context.domain.entity.MergeRequest; 6 | import dev.struchkov.bot.gitlab.context.domain.entity.MergeRequestForDiscussion; 7 | import dev.struchkov.bot.gitlab.context.repository.MergeRequestRepository; 8 | import dev.struchkov.bot.gitlab.data.jpa.MergeRequestForDiscussionJpaRepository; 9 | import dev.struchkov.bot.gitlab.data.jpa.MergeRequestJpaRepository; 10 | import lombok.NonNull; 11 | import lombok.RequiredArgsConstructor; 12 | import org.springframework.stereotype.Repository; 13 | import org.springframework.transaction.annotation.Transactional; 14 | 15 | import java.util.List; 16 | import java.util.Optional; 17 | import java.util.Set; 18 | 19 | @Repository 20 | @RequiredArgsConstructor 21 | public class MergeRequestRepositoryImpl implements MergeRequestRepository { 22 | 23 | private final MergeRequestJpaRepository jpaRepository; 24 | private final MergeRequestForDiscussionJpaRepository forDiscussionJpaRepository; 25 | 26 | @Override 27 | @Transactional(readOnly = true) 28 | public Set findAllIdByStateIn(@NonNull Set statuses) { 29 | return jpaRepository.findAllIdByStateIn(statuses); 30 | } 31 | 32 | @Override 33 | @Transactional 34 | public MergeRequest save(MergeRequest mergeRequest) { 35 | return jpaRepository.save(mergeRequest); 36 | } 37 | 38 | @Override 39 | @Transactional(readOnly = true) 40 | public Optional findById(Long mergeRequestId) { 41 | return jpaRepository.findById(mergeRequestId); 42 | } 43 | 44 | @Override 45 | @Transactional(readOnly = true) 46 | public List findAllForDiscussion() { 47 | return forDiscussionJpaRepository.findAll(); 48 | } 49 | 50 | @Override 51 | @Transactional(readOnly = true) 52 | public List findAllById(Set mergeRequestIds) { 53 | return jpaRepository.findAllById(mergeRequestIds); 54 | } 55 | 56 | @Override 57 | @Transactional(readOnly = true) 58 | public List findAllByReviewerId(Long personId) { 59 | return jpaRepository.findAllByReviewersIn(personId); 60 | } 61 | 62 | @Override 63 | @Transactional 64 | public void deleteByStates(Set states) { 65 | jpaRepository.deleteAllByStateIn(states); 66 | } 67 | 68 | @Override 69 | public Set findAllIds() { 70 | return jpaRepository.findAllIds(); 71 | } 72 | 73 | @Override 74 | public void notification(boolean enable, Long mrId) { 75 | jpaRepository.disableNotify(enable, mrId); 76 | } 77 | 78 | @Override 79 | public void notificationByProjectId(boolean enable, Set projectIds) { 80 | jpaRepository.notificationByProjectId(enable, projectIds); 81 | } 82 | 83 | } 84 | -------------------------------------------------------------------------------- /bot-data/src/main/java/dev/struchkov/bot/gitlab/data/impl/NoteRepositoryImpl.java: -------------------------------------------------------------------------------- 1 | package dev.struchkov.bot.gitlab.data.impl; 2 | 3 | import dev.struchkov.bot.gitlab.context.domain.entity.Note; 4 | import dev.struchkov.bot.gitlab.context.repository.NoteRepository; 5 | import dev.struchkov.bot.gitlab.data.jpa.NoteJpaRepository; 6 | import lombok.NonNull; 7 | import lombok.RequiredArgsConstructor; 8 | import org.springframework.data.domain.Page; 9 | import org.springframework.data.domain.Pageable; 10 | import org.springframework.stereotype.Repository; 11 | 12 | import java.util.List; 13 | import java.util.Optional; 14 | 15 | /** 16 | * @author upagge 08.09.2020 17 | */ 18 | @Repository 19 | @RequiredArgsConstructor 20 | public class NoteRepositoryImpl implements NoteRepository { 21 | 22 | private final NoteJpaRepository jpaRepository; 23 | 24 | @Override 25 | public Page findAllByResolved(boolean resolved, @NonNull Pageable pagination) { 26 | return jpaRepository.findAllByResolved(resolved, pagination); 27 | } 28 | 29 | @Override 30 | public Optional findById(Long noteId) { 31 | return jpaRepository.findById(noteId); 32 | } 33 | 34 | @Override 35 | public List findAllByResponsibleIdAndResolved(@NonNull Long userId, boolean resolved) { 36 | return jpaRepository.findAllByDiscussionResponsibleIdAndResolved(userId, resolved); 37 | } 38 | 39 | 40 | } 41 | -------------------------------------------------------------------------------- /bot-data/src/main/java/dev/struchkov/bot/gitlab/data/impl/PersonRepositoryImpl.java: -------------------------------------------------------------------------------- 1 | package dev.struchkov.bot.gitlab.data.impl; 2 | 3 | import dev.struchkov.bot.gitlab.context.domain.entity.Person; 4 | import dev.struchkov.bot.gitlab.context.repository.PersonRepository; 5 | import dev.struchkov.bot.gitlab.data.jpa.PersonJpaRepository; 6 | import lombok.RequiredArgsConstructor; 7 | import org.springframework.stereotype.Repository; 8 | 9 | import java.util.List; 10 | import java.util.Optional; 11 | import java.util.Set; 12 | 13 | /** 14 | * @author upagge 15.01.2021 15 | */ 16 | @Repository 17 | @RequiredArgsConstructor 18 | public class PersonRepositoryImpl implements PersonRepository { 19 | 20 | private final PersonJpaRepository jpaRepository; 21 | 22 | @Override 23 | public Person save(Person person) { 24 | return jpaRepository.save(person); 25 | } 26 | 27 | @Override 28 | public Optional findById(Long personId) { 29 | return jpaRepository.findById(personId); 30 | } 31 | 32 | @Override 33 | public List findAllById(Set personIds) { 34 | return jpaRepository.findAllById(personIds); 35 | } 36 | 37 | } 38 | -------------------------------------------------------------------------------- /bot-data/src/main/java/dev/struchkov/bot/gitlab/data/impl/PipelineRepositoryImpl.java: -------------------------------------------------------------------------------- 1 | package dev.struchkov.bot.gitlab.data.impl; 2 | 3 | import dev.struchkov.bot.gitlab.context.domain.PipelineStatus; 4 | import dev.struchkov.bot.gitlab.context.domain.entity.Pipeline; 5 | import dev.struchkov.bot.gitlab.context.repository.PipelineRepository; 6 | import dev.struchkov.bot.gitlab.data.jpa.PipelineJpaRepository; 7 | import lombok.RequiredArgsConstructor; 8 | import org.springframework.stereotype.Repository; 9 | import org.springframework.transaction.annotation.Transactional; 10 | 11 | import java.time.LocalDateTime; 12 | import java.util.List; 13 | import java.util.Optional; 14 | import java.util.Set; 15 | 16 | /** 17 | * @author upagge 17.01.2021 18 | */ 19 | @Repository 20 | @RequiredArgsConstructor 21 | public class PipelineRepositoryImpl implements PipelineRepository { 22 | 23 | private final PipelineJpaRepository jpaRepository; 24 | 25 | @Override 26 | public Pipeline save(Pipeline pipeline) { 27 | return jpaRepository.save(pipeline); 28 | } 29 | 30 | @Override 31 | public Optional findById(Long pipelineId) { 32 | return jpaRepository.findById(pipelineId); 33 | } 34 | 35 | @Override 36 | public List findAllByStatuses(Set statuses) { 37 | return jpaRepository.findAllByStatusIn(statuses); 38 | } 39 | 40 | @Override 41 | public List findAllById(Set pipelineIds) { 42 | return jpaRepository.findAllById(pipelineIds); 43 | } 44 | 45 | @Override 46 | @Transactional 47 | public void deleteByCreatedBefore(LocalDateTime date) { 48 | jpaRepository.deleteAllByCreatedBefore(date); 49 | } 50 | 51 | @Override 52 | public Set findAllIds() { 53 | return jpaRepository.findAllIds(); 54 | } 55 | 56 | } 57 | -------------------------------------------------------------------------------- /bot-data/src/main/java/dev/struchkov/bot/gitlab/data/impl/ProjectRepositoryImpl.java: -------------------------------------------------------------------------------- 1 | package dev.struchkov.bot.gitlab.data.impl; 2 | 3 | import dev.struchkov.bot.gitlab.context.domain.entity.Project; 4 | import dev.struchkov.bot.gitlab.context.repository.ProjectRepository; 5 | import dev.struchkov.bot.gitlab.data.jpa.ProjectJpaRepository; 6 | import lombok.RequiredArgsConstructor; 7 | import org.springframework.data.domain.Page; 8 | import org.springframework.data.domain.Pageable; 9 | import org.springframework.stereotype.Repository; 10 | 11 | import java.util.List; 12 | import java.util.Optional; 13 | import java.util.Set; 14 | 15 | /** 16 | * @author upagge 14.01.2021 17 | */ 18 | @Repository 19 | @RequiredArgsConstructor 20 | public class ProjectRepositoryImpl implements ProjectRepository { 21 | 22 | private final ProjectJpaRepository jpaRepository; 23 | 24 | @Override 25 | public Project save(Project project) { 26 | return jpaRepository.save(project); 27 | } 28 | 29 | @Override 30 | public Optional findById(Long projectId) { 31 | return jpaRepository.findById(projectId); 32 | } 33 | 34 | @Override 35 | public List findAllById(Set projectIds) { 36 | return jpaRepository.findAllById(projectIds); 37 | } 38 | 39 | @Override 40 | public boolean existById(Long projectId) { 41 | return jpaRepository.existsById(projectId); 42 | } 43 | 44 | @Override 45 | public Page findAllById(Pageable pagination) { 46 | return jpaRepository.findAll(pagination); 47 | } 48 | 49 | @Override 50 | public Set findAllIdByProcessingEnable() { 51 | return jpaRepository.findAllIdByProcessingEnableTrue(); 52 | } 53 | 54 | @Override 55 | public Optional findProjectNameById(Long projectId) { 56 | return jpaRepository.findProjectNameById(projectId); 57 | } 58 | 59 | @Override 60 | public Set findAllIds() { 61 | return jpaRepository.findAllIds(); 62 | } 63 | 64 | @Override 65 | public void notification(boolean enable, Set projectIds) { 66 | jpaRepository.notification(enable, projectIds); 67 | } 68 | 69 | @Override 70 | public void processing(boolean enable, Set projectIds) { 71 | jpaRepository.processing(enable, projectIds); 72 | } 73 | 74 | } 75 | -------------------------------------------------------------------------------- /bot-data/src/main/java/dev/struchkov/bot/gitlab/data/jpa/AppSettingJpaRepository.java: -------------------------------------------------------------------------------- 1 | package dev.struchkov.bot.gitlab.data.jpa; 2 | 3 | import dev.struchkov.bot.gitlab.context.domain.entity.AppSetting; 4 | import org.springframework.data.jpa.repository.JpaRepository; 5 | 6 | /** 7 | * @author upagge 16.01.2021 8 | */ 9 | public interface AppSettingJpaRepository extends JpaRepository { 10 | } 11 | -------------------------------------------------------------------------------- /bot-data/src/main/java/dev/struchkov/bot/gitlab/data/jpa/DiscussionJpaRepository.java: -------------------------------------------------------------------------------- 1 | package dev.struchkov.bot.gitlab.data.jpa; 2 | 3 | import dev.struchkov.bot.gitlab.context.domain.entity.Discussion; 4 | import org.springframework.data.jpa.repository.JpaRepository; 5 | import org.springframework.data.jpa.repository.Modifying; 6 | import org.springframework.data.jpa.repository.Query; 7 | import org.springframework.data.repository.query.Param; 8 | 9 | import java.util.List; 10 | import java.util.Set; 11 | 12 | /** 13 | * @author upagge 11.02.2021 14 | */ 15 | public interface DiscussionJpaRepository extends JpaRepository { 16 | 17 | /** 18 | * Находит все обсуждения MR 19 | */ 20 | List findAllByMergeRequestId(Long mergeRequestId); 21 | 22 | @Query("SELECT d.id FROM Discussion d") 23 | Set findAllIds(); 24 | 25 | void removeAllByMergeRequestIsNull(); 26 | 27 | @Modifying 28 | @Query("DELETE FROM Discussion d WHERE d.id = :id") 29 | void deleteById(@Param("id") String id); 30 | 31 | @Modifying 32 | @Query("UPDATE Discussion d SET d.notification = :enable WHERE d.id = :discussionId") 33 | void notification(@Param("enable") boolean enable, @Param("discussionId") String discussionId); 34 | 35 | } 36 | -------------------------------------------------------------------------------- /bot-data/src/main/java/dev/struchkov/bot/gitlab/data/jpa/MergeRequestForDiscussionJpaRepository.java: -------------------------------------------------------------------------------- 1 | package dev.struchkov.bot.gitlab.data.jpa; 2 | 3 | import dev.struchkov.bot.gitlab.context.domain.entity.MergeRequestForDiscussion; 4 | import org.springframework.data.jpa.repository.support.JpaRepositoryImplementation; 5 | 6 | /** 7 | * @author upagge [31.01.2020] 8 | */ 9 | 10 | public interface MergeRequestForDiscussionJpaRepository extends JpaRepositoryImplementation { 11 | 12 | } 13 | -------------------------------------------------------------------------------- /bot-data/src/main/java/dev/struchkov/bot/gitlab/data/jpa/MergeRequestJpaRepository.java: -------------------------------------------------------------------------------- 1 | package dev.struchkov.bot.gitlab.data.jpa; 2 | 3 | import dev.struchkov.bot.gitlab.context.domain.IdAndStatusPr; 4 | import dev.struchkov.bot.gitlab.context.domain.MergeRequestState; 5 | import dev.struchkov.bot.gitlab.context.domain.entity.MergeRequest; 6 | import org.springframework.data.jpa.repository.Modifying; 7 | import org.springframework.data.jpa.repository.Query; 8 | import org.springframework.data.jpa.repository.support.JpaRepositoryImplementation; 9 | import org.springframework.data.repository.query.Param; 10 | 11 | import java.util.List; 12 | import java.util.Set; 13 | 14 | /** 15 | * @author upagge [31.01.2020] 16 | */ 17 | 18 | public interface MergeRequestJpaRepository extends JpaRepositoryImplementation { 19 | 20 | @Query("SELECT new dev.struchkov.bot.gitlab.context.domain.IdAndStatusPr(p.id, p.twoId, p.projectId, p.state) FROM MergeRequest p WHERE p.state IN :states") 21 | Set findAllIdByStateIn(@Param("states") Set states); 22 | 23 | @Query("SELECT mr FROM MergeRequest mr LEFT JOIN mr.reviewers r WHERE r.id = :reviewerId") 24 | List findAllByReviewersIn(@Param("reviewerId") Long reviewerId); 25 | 26 | void deleteAllByStateIn(Set states); 27 | 28 | @Query("SELECT mr.id FROM MergeRequest mr") 29 | Set findAllIds(); 30 | 31 | @Modifying 32 | @Query("UPDATE MergeRequest mr SET mr.notification = :enable WHERE mr.id = :mrId") 33 | void disableNotify(@Param("enable") boolean enable, @Param("mrId") Long mrId); 34 | 35 | @Modifying 36 | @Query("UPDATE MergeRequest mr SET mr.notification = :enable WHERE mr.projectId in :projectIds") 37 | void notificationByProjectId(@Param("enable") boolean enable, @Param("projectIds") Set projectIds); 38 | 39 | } 40 | -------------------------------------------------------------------------------- /bot-data/src/main/java/dev/struchkov/bot/gitlab/data/jpa/NoteJpaRepository.java: -------------------------------------------------------------------------------- 1 | package dev.struchkov.bot.gitlab.data.jpa; 2 | 3 | import dev.struchkov.bot.gitlab.context.domain.entity.Note; 4 | import org.springframework.data.domain.Page; 5 | import org.springframework.data.domain.Pageable; 6 | import org.springframework.data.jpa.repository.JpaRepository; 7 | 8 | import java.util.List; 9 | 10 | public interface NoteJpaRepository extends JpaRepository { 11 | 12 | Page findAllByResolved(boolean resolved, Pageable pageable); 13 | 14 | List findAllByDiscussionResponsibleIdAndResolved(Long responsibleId, boolean resolved); 15 | 16 | } 17 | -------------------------------------------------------------------------------- /bot-data/src/main/java/dev/struchkov/bot/gitlab/data/jpa/PersonJpaRepository.java: -------------------------------------------------------------------------------- 1 | package dev.struchkov.bot.gitlab.data.jpa; 2 | 3 | import dev.struchkov.bot.gitlab.context.domain.entity.Person; 4 | import org.springframework.data.jpa.repository.JpaRepository; 5 | 6 | /** 7 | * @author upagge 15.01.2021 8 | */ 9 | public interface PersonJpaRepository extends JpaRepository { 10 | 11 | } 12 | -------------------------------------------------------------------------------- /bot-data/src/main/java/dev/struchkov/bot/gitlab/data/jpa/PipelineJpaRepository.java: -------------------------------------------------------------------------------- 1 | package dev.struchkov.bot.gitlab.data.jpa; 2 | 3 | import dev.struchkov.bot.gitlab.context.domain.PipelineStatus; 4 | import dev.struchkov.bot.gitlab.context.domain.entity.Pipeline; 5 | import org.springframework.data.jpa.repository.Query; 6 | import org.springframework.data.jpa.repository.support.JpaRepositoryImplementation; 7 | 8 | import java.time.LocalDateTime; 9 | import java.util.List; 10 | import java.util.Set; 11 | 12 | /** 13 | * @author upagge 17.01.2021 14 | */ 15 | public interface PipelineJpaRepository extends JpaRepositoryImplementation { 16 | 17 | List findAllByStatusIn(Set statuses); 18 | 19 | void deleteAllByCreatedBefore(LocalDateTime date); 20 | 21 | @Query("SELECT p.id FROM Pipeline p") 22 | Set findAllIds(); 23 | 24 | } 25 | -------------------------------------------------------------------------------- /bot-data/src/main/java/dev/struchkov/bot/gitlab/data/jpa/ProjectJpaRepository.java: -------------------------------------------------------------------------------- 1 | package dev.struchkov.bot.gitlab.data.jpa; 2 | 3 | import dev.struchkov.bot.gitlab.context.domain.entity.Project; 4 | import org.springframework.data.jpa.repository.JpaRepository; 5 | import org.springframework.data.jpa.repository.Modifying; 6 | import org.springframework.data.jpa.repository.Query; 7 | import org.springframework.data.repository.query.Param; 8 | 9 | import java.util.Optional; 10 | import java.util.Set; 11 | 12 | /** 13 | * @author upagge 14.01.2021 14 | */ 15 | public interface ProjectJpaRepository extends JpaRepository { 16 | 17 | @Query("SELECT p.id FROM Project p WHERE p.processing = true") 18 | Set findAllIdByProcessingEnableTrue(); 19 | 20 | @Query("SELECT p.name FROM Project p WHERE p.id = :projectId") 21 | Optional findProjectNameById(@Param("projectId") Long projectId); 22 | 23 | @Query("SELECT p.id FROM Project p") 24 | Set findAllIds(); 25 | 26 | @Modifying 27 | @Query("UPDATE Project p SET p.notification = :enable WHERE p.id in :projectIds") 28 | void notification(@Param("enable") boolean enable, @Param("projectIds") Set projectIds); 29 | 30 | @Modifying 31 | @Query("UPDATE Project p SET p.processing = :enable WHERE p.id in :projectIds") 32 | void processing(@Param("enable") boolean enable, @Param("projectIds") Set projectIds); 33 | 34 | } 35 | -------------------------------------------------------------------------------- /documentation/ru/.cache/plugin/optimize/images/assets/images/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uPagge/gitlab-notification/ebc692c84265ef16bfc012784b6b5c3a35d57f35/documentation/ru/.cache/plugin/optimize/images/assets/images/favicon.png -------------------------------------------------------------------------------- /documentation/ru/assets/images/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uPagge/gitlab-notification/ebc692c84265ef16bfc012784b6b5c3a35d57f35/documentation/ru/assets/images/favicon.png -------------------------------------------------------------------------------- /documentation/ru/docs/architecture/concept.md: -------------------------------------------------------------------------------- 1 | # Общая архитектура 2 | 3 | !!! warning 4 | 5 | Данный раздел находится в процессе написания 6 | 7 | Поддерживается два режима работы: периодические запуски на ПК и запуск на сервере в режиме 24/7. 8 | 9 | ## Схема БД { id="schema-database" } 10 | 11 | Приложение имеет БД, которая используется для сохранения состояния отслеживаемых сущностей GitLab. 12 | 13 |
14 | ![schema-database.png](img/schema-database.png){ loading=lazy } 15 |
Схема приложения версия 1.0.0
16 |
17 | 18 | Важно подчеркнуть, что приложение не сохраняет все бездумно в БД. Во время первого запуска вам будет задан ряд вопросов, ответы на которые повлияют на наполнение БД. 19 | 20 | Также приложение старается не хранить лишние данные. Например, если MR был вмержен или закрыт, то нет смысла хранить информацию об этом MR, поэтому при следующем сканировании запись об этом MR, а также обо всех связанных сущностях этого MR (пайплайны, треды...) будут удалены. 21 | 22 | ## Сканирование GitLab 23 | Раз в 1 минуту происходит обращение к GitLab API с вашим персональным токеном. Получаемые от GitLab данные сверяются с имеющимися в БД, после чего формируются уведомления, если обнаружены изменения. 24 | 25 | !!! question "Почему не использовать Webhook?" 26 | 27 | Не везде имется возможность установить произвольные Webhook. Например, вряд ли кто-то позволит вам установить Webhook из корпоративного GitLab во внешнюю сеть. Переодическое обращение к GitLab API можно выполнять прямо с рабочей машины. 28 | 29 | В будущем планирую добавить поддержку и Webhook. -------------------------------------------------------------------------------- /documentation/ru/docs/architecture/img/schema-database.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uPagge/gitlab-notification/ebc692c84265ef16bfc012784b6b5c3a35d57f35/documentation/ru/docs/architecture/img/schema-database.png -------------------------------------------------------------------------------- /documentation/ru/docs/changelog/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: ChangeLog 3 | hide: 4 | - comments 5 | 6 | --- 7 | 8 | # ChangeLog 9 | 10 | ## v.0.1.0 11 | Это первая стабильная публичная версия бота, которую я тестировал пару месяцев на своей работе. -------------------------------------------------------------------------------- /documentation/ru/docs/features/img/gitlab-thread-answer.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uPagge/gitlab-notification/ebc692c84265ef16bfc012784b6b5c3a35d57f35/documentation/ru/docs/features/img/gitlab-thread-answer.png -------------------------------------------------------------------------------- /documentation/ru/docs/features/img/notify-conflict-mr.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uPagge/gitlab-notification/ebc692c84265ef16bfc012784b6b5c3a35d57f35/documentation/ru/docs/features/img/notify-conflict-mr.png -------------------------------------------------------------------------------- /documentation/ru/docs/features/img/notify-new-comment-in-thread-without-context.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uPagge/gitlab-notification/ebc692c84265ef16bfc012784b6b5c3a35d57f35/documentation/ru/docs/features/img/notify-new-comment-in-thread-without-context.png -------------------------------------------------------------------------------- /documentation/ru/docs/features/img/notify-new-comment-in-thread.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uPagge/gitlab-notification/ebc692c84265ef16bfc012784b6b5c3a35d57f35/documentation/ru/docs/features/img/notify-new-comment-in-thread.png -------------------------------------------------------------------------------- /documentation/ru/docs/features/img/notify-new-mr.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uPagge/gitlab-notification/ebc692c84265ef16bfc012784b6b5c3a35d57f35/documentation/ru/docs/features/img/notify-new-mr.png -------------------------------------------------------------------------------- /documentation/ru/docs/features/img/notify-new-pipeline.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uPagge/gitlab-notification/ebc692c84265ef16bfc012784b6b5c3a35d57f35/documentation/ru/docs/features/img/notify-new-pipeline.png -------------------------------------------------------------------------------- /documentation/ru/docs/features/img/notify-new-project.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uPagge/gitlab-notification/ebc692c84265ef16bfc012784b6b5c3a35d57f35/documentation/ru/docs/features/img/notify-new-project.png -------------------------------------------------------------------------------- /documentation/ru/docs/features/img/notify-new-thread-without-context.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uPagge/gitlab-notification/ebc692c84265ef16bfc012784b6b5c3a35d57f35/documentation/ru/docs/features/img/notify-new-thread-without-context.png -------------------------------------------------------------------------------- /documentation/ru/docs/features/img/notify-new-thread.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uPagge/gitlab-notification/ebc692c84265ef16bfc012784b6b5c3a35d57f35/documentation/ru/docs/features/img/notify-new-thread.png -------------------------------------------------------------------------------- /documentation/ru/docs/features/img/notify-update-mr.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uPagge/gitlab-notification/ebc692c84265ef16bfc012784b6b5c3a35d57f35/documentation/ru/docs/features/img/notify-update-mr.png -------------------------------------------------------------------------------- /documentation/ru/docs/features/img/notify-update-status-mr.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uPagge/gitlab-notification/ebc692c84265ef16bfc012784b6b5c3a35d57f35/documentation/ru/docs/features/img/notify-update-status-mr.png -------------------------------------------------------------------------------- /documentation/ru/docs/features/img/telegram-thread-answer.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uPagge/gitlab-notification/ebc692c84265ef16bfc012784b6b5c3a35d57f35/documentation/ru/docs/features/img/telegram-thread-answer.png -------------------------------------------------------------------------------- /documentation/ru/docs/features/interaction-bot.md: -------------------------------------------------------------------------------- 1 | # Взаимодействие с ботом 2 | 3 | Главное меню бота вызывается с помощью команды `/start` 4 | 5 | !!! note 6 | 7 | На данный момент главное меню содержит только пункт: "Добавить новый репозиторий". В будущем функционал существенно расширится. 8 | 9 | ## Добавить новый репозиторий { id="add-new-repository" } 10 | 11 | Если во время первичной инициализации не стали добавлять все доступные репозитории, или не включили автоматическое отслеживание появления новых репозиториев, то вы можете добавлять репозитории самостоятельно. 12 | 13 | Для этого: 14 | 15 | * Вызовите главное меню командой `/start` 16 | * Выберете пункт `Add repository`, который позволяет поставить репозиторий на отслеживание 17 | * Скопируйте ссылку на репозиторий из адресной строки браузера и отправьте ее боту. 18 | * Если все пройдет успешно, то вы получите уведомление `👍 Projects added successfully!` 19 | 20 | Это позволит вам получать все уведомления репозитория и его сущностей, таких как MR, пайплайны и так далее. 21 | 22 | !!! tip "Массовое добавление" 23 | 24 | Если вы хотите добавить множество репозиториев разом, то вы можете это сделать. Сформируйте сообщение с несколькими ссылками, где каждая ссылка на репозиторий будет на новой строке: 25 | 26 | ``` 27 | https://gitlab.com/groupname/projectname1/repositoryname1 28 | https://gitlab.com/groupname/projectname1/repositoryname2 29 | https://gitlab.com/groupname/projectname2/repositoryname3 30 | ``` 31 | 32 | 33 | ## Быстрые действия { id="fast-actions" } 34 | 35 | Быстрые действия выглядят в виде кнопок под уведомлением, и позволяют в одно нажатие изменять настройки бота. 36 | 37 | Самые частые быстрые действия: 38 | 39 | - :eyes: — прочитано. Просто удаляет сообщение. 40 | - :link: — ссылка для перехода в GitLab. 41 | - :no_bell: — отключить уведомления данного типа. -------------------------------------------------------------------------------- /documentation/ru/docs/features/interaction-gitlab.md: -------------------------------------------------------------------------------- 1 | --- 2 | description: Отправляйте события из Telegram в GitLab 3 | 4 | --- 5 | 6 | # Взаимодействие с GitLab 7 | 8 | Здесь собраны все возможности, которые позволяют вам что-то сделать в GitLab прямо из Telegram. 9 | 10 | !!! warning 11 | 12 | Все эти функции работают, если при создании GitLab токена вы указали уровень доступа `api`. 13 | 14 | ## Ответ в треде 15 | Допустим вас упомянули в обсуждении, сразу знаете что ответить? Не тратьте время, отвечайте прямо из телеграм. Для этого просто ответьте на сообщение и напишите ваш комментарий. 16 | 17 | Просто ответьте на сообщение уведомления: 18 | 19 |
20 | ![telegram-thread-answer.png](img/telegram-thread-answer.png){ loading=lazy align=left width="700" } 21 |
22 | 23 | Так это будет выглядеть в GitLab: 24 | 25 |
26 | ![gitlab-thread-answer.png](img/gitlab-thread-answer.png){ loading=lazy align=left width="700" } 27 |
-------------------------------------------------------------------------------- /documentation/ru/docs/getting-started/create-gitlab-token.md: -------------------------------------------------------------------------------- 1 | # Создание токена GitLab 2 | 3 | Для взаимодействия с GitLab необходим персональный токен доступа. 4 | 5 | Чтобы его получить перейдите по адресу: [https://gitlab.com/-/profile/personal_access_tokens](https://gitlab.com/-/profile/personal_access_tokens) 6 | 7 | !!! tip "Корпоративный GitLab" 8 | 9 | Замените `https://gitlab.com/` на адрес своего GitLab, если вы используете self-host решение. 10 | 11 | * Придумайте название токену, например, `GitLab Notify`. 12 | * Выдайте права на чтение - `read_api` 13 | 14 | !!! info "Уровень разрешений" 15 | 16 | Выберете уровень разрешения `api`, если планируете пользоваться такими функциями, как: [ответ в треде](../features/interaction-gitlab.md#ответ-в-треде) 17 | 18 | * Нажмите кнопку `Create personal access token`. 19 | * Сохраните полученный токен. -------------------------------------------------------------------------------- /documentation/ru/docs/getting-started/creating-telegram-bot.md: -------------------------------------------------------------------------------- 1 | # Регистрируем бота в Telegram 2 | 3 | Перед первым запуском необходимо создать бота в Telegram. Для этого перейдите в официального бота [@GodFather](https://t.me/BotFather) и выполните команду `/newbot`. 4 | 5 | !!! warning "Имя бота" 6 | 7 | Первые два пункта диалогового меню будет про название бота. Учтите, что это называние общедоступно и случайноы пользователь Telegram сможет найти вашего бота. 8 | 9 | Не переживайте, приложение имеет встроенную [защиту от несанкционарованного доступа к боту](../privacy/index.md#access-control). Но не смотря на это, ==не рекомендуется использовать в названии бота название организации, или вашу фамилию. Лучше использовать случайное имя.== 10 | 11 | После регистрации вам будет выдан токен доступа. Он будет использоваться при запуске ассистента. 12 | 13 | Видео процесса: 14 |
15 |
-------------------------------------------------------------------------------- /documentation/ru/docs/getting-started/first-start.md: -------------------------------------------------------------------------------- 1 | # Первичная настройка 2 | 3 | Первичная настройка выполняется один раз после первого запуска бота. Она позволяет задать первоначальную конфигурацию поведения сканирования и прочих параметров. 4 | 5 | В данном видео демонстрируется процесс первичной настройки бота, чтобы вы знали, чего ожидать: 6 | 7 |