├── .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 | { 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 | { loading=lazy align=left width="700" }
21 |
22 |
23 | Так это будет выглядеть в GitLab:
24 |
25 |
26 | { 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 |