Рефакторинг урлов гитлаба

This commit is contained in:
Struchkov Mark 2024-08-23 22:25:17 +03:00
parent 5c8ddb8e08
commit 58fed44e04
No known key found for this signature in database
GPG Key ID: A3F0AC3F0FA52F3C
9 changed files with 97 additions and 107 deletions

View File

@ -1,6 +1,10 @@
package dev.struchkov.bot.gitlab.context.domain; package dev.struchkov.bot.gitlab.context.domain;
import lombok.AccessLevel;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter; import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter; import lombok.Setter;
/** /**
@ -8,6 +12,9 @@ import lombok.Setter;
*/ */
@Getter @Getter
@Setter @Setter
@Builder
@NoArgsConstructor
@AllArgsConstructor(access = AccessLevel.PRIVATE)
public class PersonInformation { public class PersonInformation {
private String username; private String username;

View File

@ -8,7 +8,7 @@ import dev.struchkov.bot.gitlab.context.domain.entity.Person;
import dev.struchkov.bot.gitlab.context.service.DiscussionService; import dev.struchkov.bot.gitlab.context.service.DiscussionService;
import dev.struchkov.bot.gitlab.context.service.MergeRequestsService; import dev.struchkov.bot.gitlab.context.service.MergeRequestsService;
import dev.struchkov.bot.gitlab.sdk.GitlabSdkManager; import dev.struchkov.bot.gitlab.sdk.GitlabSdkManager;
import dev.struchkov.bot.gitlab.sdk.config.GitlabProperty; import dev.struchkov.bot.gitlab.sdk.config.GitlabUrl;
import dev.struchkov.bot.gitlab.sdk.domain.json.DiscussionJson; import dev.struchkov.bot.gitlab.sdk.domain.json.DiscussionJson;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
@ -42,7 +42,7 @@ public class DiscussionParser {
public static final int PAGE_COUNT = 100; public static final int PAGE_COUNT = 100;
//TODO [23.08.2024|uPagge]: Убрать //TODO [23.08.2024|uPagge]: Убрать
private final GitlabProperty gitlabProperty; private final GitlabUrl gitlabUrl;
private final GitlabSdkManager gitlabSdkManager; private final GitlabSdkManager gitlabSdkManager;
private final DiscussionService discussionService; private final DiscussionService discussionService;
@ -174,7 +174,7 @@ public class DiscussionParser {
private Consumer<Note> createNoteLink(MergeRequestForDiscussion mergeRequest) { private Consumer<Note> createNoteLink(MergeRequestForDiscussion mergeRequest) {
return note -> { return note -> {
final String url = MessageFormat.format( final String url = MessageFormat.format(
gitlabProperty.getNoteUrl(), gitlabUrl.getNote(),
mergeRequest.getWebUrl(), mergeRequest.getWebUrl(),
note.getId() note.getId()
); );

View File

@ -3,8 +3,7 @@ package dev.struchkov.bot.gitlab.config;
import dev.struchkov.bot.gitlab.context.domain.PersonInformation; import dev.struchkov.bot.gitlab.context.domain.PersonInformation;
import dev.struchkov.bot.gitlab.context.prop.AppProperty; import dev.struchkov.bot.gitlab.context.prop.AppProperty;
import dev.struchkov.bot.gitlab.context.prop.PersonProperty; import dev.struchkov.bot.gitlab.context.prop.PersonProperty;
import dev.struchkov.bot.gitlab.sdk.client.HttpParse; import dev.struchkov.bot.gitlab.sdk.GitlabSdkManager;
import dev.struchkov.bot.gitlab.sdk.client.StringUtils;
import dev.struchkov.bot.gitlab.sdk.config.GitlabProperty; import dev.struchkov.bot.gitlab.sdk.config.GitlabProperty;
import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
@ -15,11 +14,9 @@ import org.springframework.core.convert.support.DefaultConversionService;
import org.springframework.scheduling.annotation.EnableScheduling; import org.springframework.scheduling.annotation.EnableScheduling;
import java.util.Arrays; import java.util.Arrays;
import java.util.Optional;
import java.util.concurrent.ForkJoinPool; import java.util.concurrent.ForkJoinPool;
import static dev.struchkov.bot.gitlab.sdk.client.HttpParse.ACCEPT;
import static dev.struchkov.haiti.context.exception.NotFoundException.notFoundException;
/** /**
* Общий файл настройки всего приложения. * Общий файл настройки всего приложения.
* *
@ -71,16 +68,18 @@ public class AppConfig {
@Bean @Bean
public PersonInformation personInformation( public PersonInformation personInformation(
PersonProperty personProperty, GitlabSdkManager gitlabSdkManager,
GitlabProperty gitlabProperty PersonProperty personProperty
) { ) {
final PersonInformation personInformation = HttpParse.request(gitlabProperty.getUserUrl()) return Optional.of(gitlabSdkManager.getAuthPerson())
.header(ACCEPT) .map(
.header(StringUtils.H_PRIVATE_TOKEN, gitlabProperty.getAccessToken()) authUser -> PersonInformation.builder()
.execute(PersonInformation.class) .id(authUser.getId())
.orElseThrow(notFoundException("Пользователь не найден")); .username(authUser.getUsername())
personInformation.setTelegramId(personProperty.getTelegramId()); .name(authUser.getName())
return personInformation; .telegramId(personProperty.getTelegramId())
.build()
).orElseThrow();
} }
} }

View File

@ -49,23 +49,6 @@ gitlab-bot:
access-token: ${GITLAB_PERSONAL_TOKEN} access-token: ${GITLAB_PERSONAL_TOKEN}
base-url: ${GITLAB_URL} base-url: ${GITLAB_URL}
replaceUrl: ${GITLAB_REPLACE_URL} replaceUrl: ${GITLAB_REPLACE_URL}
users-url: "${GITLAB_URL}/api/v4/users"
user-url: "${GITLAB_URL}/api/v4/user"
projects-url: "${GITLAB_URL}/api/v4/projects?page={0, number, integer}&per_page=100"
open-merge-requests-url: "${GITLAB_URL}/api/v4/projects/{0,number,#}/merge_requests?state=opened&page={1, number, integer}&per_page={2, number, integer}"
close-merge-requests-url: "${GITLAB_URL}/api/v4/projects/{0,number,#}/merge_requests?state=closed&page={1, number, integer}&per_page=100"
comments-of-merge-request-url: "${GITLAB_URL}/api/v4/projects/{0,number,#}/merge_requests/{1,number,#}/notes?&page={2,number,#}&per_page=100"
merge-request-url: "${GITLAB_URL}/api/v4/projects/{0,number,#}/merge_requests/{1,number,#}"
merge-request-approval-url: "${GITLAB_URL}/api/v4/projects/{0,number,#}/merge_requests/{1,number,#}/approvals"
project-add-url: "${GITLAB_URL}/api/v4/projects/"
note-url: "{0}#note_{1,number,#}"
notes-of-merge-request-url: "${GITLAB_URL}/api/v4/projects/{0,number,#}/merge_requests/{1,number,#}/notes/{2,number,#}"
pipelines-url: "${GITLAB_URL}/api/v4/projects/{0,number,#}/pipelines?&page={1,number,#}&per_page={2,number,#}"
pipeline-url: "${GITLAB_URL}/api/v4/projects/{0,number,#}/pipelines/{1,number,#}"
last-commit-of-merge-request-url: "${GITLAB_URL}/api/v4/projects/{0,number,#}/merge_requests/{1,number,#}/commits?&page=1&per_page=1"
new-note-url: "${GITLAB_URL}/api/v4/projects/{0,number,#}/merge_requests/{1,number,#}/discussions/{2}/notes?body={3}"
discussions-url: "${GITLAB_URL}/api/v4/projects/{0,number,#}/merge_requests/{1,number,#}/discussions?&page={2,number,#}&per_page={3,number,#}"
discussion-url: "${GITLAB_URL}/api/v4/projects/{0,number,#}/merge_requests/{1,number,#}/discussions/{2}"
--- ---
spring: spring:

View File

@ -3,6 +3,7 @@ package dev.struchkov.bot.gitlab.sdk;
import dev.struchkov.bot.gitlab.sdk.client.HttpParse; import dev.struchkov.bot.gitlab.sdk.client.HttpParse;
import dev.struchkov.bot.gitlab.sdk.client.StringUtils; import dev.struchkov.bot.gitlab.sdk.client.StringUtils;
import dev.struchkov.bot.gitlab.sdk.config.GitlabProperty; import dev.struchkov.bot.gitlab.sdk.config.GitlabProperty;
import dev.struchkov.bot.gitlab.sdk.config.GitlabUrl;
import dev.struchkov.bot.gitlab.sdk.domain.GitlabProjectParam; import dev.struchkov.bot.gitlab.sdk.domain.GitlabProjectParam;
import dev.struchkov.bot.gitlab.sdk.domain.json.ApprovalContainerJson; import dev.struchkov.bot.gitlab.sdk.domain.json.ApprovalContainerJson;
import dev.struchkov.bot.gitlab.sdk.domain.json.ApprovalJson; import dev.struchkov.bot.gitlab.sdk.domain.json.ApprovalJson;
@ -39,6 +40,7 @@ import java.util.stream.Collectors;
import static dev.struchkov.bot.gitlab.sdk.client.HttpParse.ACCEPT; import static dev.struchkov.bot.gitlab.sdk.client.HttpParse.ACCEPT;
import static dev.struchkov.bot.gitlab.sdk.client.StringUtils.H_PRIVATE_TOKEN; import static dev.struchkov.bot.gitlab.sdk.client.StringUtils.H_PRIVATE_TOKEN;
import static dev.struchkov.haiti.context.exception.NotFoundException.notFoundException;
import static dev.struchkov.haiti.utils.concurrent.ForkJoinUtils.pullTaskResult; import static dev.struchkov.haiti.utils.concurrent.ForkJoinUtils.pullTaskResult;
import static dev.struchkov.haiti.utils.concurrent.ForkJoinUtils.pullTaskResults; import static dev.struchkov.haiti.utils.concurrent.ForkJoinUtils.pullTaskResults;
import static java.util.Collections.emptyList; import static java.util.Collections.emptyList;
@ -50,10 +52,19 @@ import static java.util.stream.Collectors.toList;
public class GitlabSdkManager { public class GitlabSdkManager {
private final ForkJoinPool forkJoinPool; private final ForkJoinPool forkJoinPool;
private final GitlabUrl gitlabUrl;
private final GitlabProperty gitlabProperty; private final GitlabProperty gitlabProperty;
public PersonJson getAuthPerson() {
return HttpParse.request(gitlabUrl.getUser())
.header(ACCEPT)
.header(StringUtils.H_PRIVATE_TOKEN, gitlabProperty.getAccessToken())
.execute(PersonJson.class)
.orElseThrow(notFoundException("Пользователь не найден"));
}
public Optional<PersonJson> getPersonById(Long userId) { public Optional<PersonJson> getPersonById(Long userId) {
return HttpParse.request(gitlabProperty.getUsersUrl() + "/" + userId) return HttpParse.request(gitlabUrl.getUsers() + "/" + userId)
.header(ACCEPT) .header(ACCEPT)
.header(StringUtils.H_PRIVATE_TOKEN, gitlabProperty.getAccessToken()) .header(StringUtils.H_PRIVATE_TOKEN, gitlabProperty.getAccessToken())
.execute(PersonJson.class); .execute(PersonJson.class);
@ -63,7 +74,7 @@ public class GitlabSdkManager {
String param = Arrays.stream(params) String param = Arrays.stream(params)
.map(GitlabProjectParam::getUrl) .map(GitlabProjectParam::getUrl)
.collect(Collectors.joining()); .collect(Collectors.joining());
final String url = MessageFormat.format(gitlabProperty.getProjectsUrl(), pageNumber); final String url = MessageFormat.format(gitlabUrl.getProjects(), pageNumber);
return HttpParse.request(url + param) return HttpParse.request(url + param)
.header(ACCEPT) .header(ACCEPT)
.header(StringUtils.H_PRIVATE_TOKEN, gitlabProperty.getAccessToken()) .header(StringUtils.H_PRIVATE_TOKEN, gitlabProperty.getAccessToken())
@ -85,7 +96,7 @@ public class GitlabSdkManager {
*/ */
public List<MergeRequestJson> getAllMergeRequestByProjectIds(Set<Long> projectIds) { public List<MergeRequestJson> getAllMergeRequestByProjectIds(Set<Long> projectIds) {
final List<ForkJoinTask<List<MergeRequestJson>>> tasks = projectIds.stream() final List<ForkJoinTask<List<MergeRequestJson>>> tasks = projectIds.stream()
.map(projectId -> new GetAllMergeRequestForProjectTask(projectId, gitlabProperty.getOpenMergeRequestsUrl(), gitlabProperty.getAccessToken())) .map(projectId -> new GetAllMergeRequestForProjectTask(projectId, gitlabUrl.getOpenMergeRequests(), gitlabProperty.getAccessToken()))
.map(forkJoinPool::submit) .map(forkJoinPool::submit)
.collect(Collectors.toList()); .collect(Collectors.toList());
@ -94,7 +105,7 @@ public class GitlabSdkManager {
public List<CommitJson> getAllCommitByProjectId(Long projectId, Long mergeRequestIdForProject) { public List<CommitJson> getAllCommitByProjectId(Long projectId, Long mergeRequestIdForProject) {
return HttpParse.request( return HttpParse.request(
MessageFormat.format(gitlabProperty.getLastCommitOfMergeRequestUrl(), projectId, mergeRequestIdForProject) MessageFormat.format(gitlabUrl.getLastCommitOfMergeRequest(), projectId, mergeRequestIdForProject)
) )
.header(ACCEPT) .header(ACCEPT)
.header(StringUtils.H_PRIVATE_TOKEN, gitlabProperty.getAccessToken()) .header(StringUtils.H_PRIVATE_TOKEN, gitlabProperty.getAccessToken())
@ -103,7 +114,7 @@ public class GitlabSdkManager {
public List<ApprovalJson> getAllApprovalForMergeRequest(Long projectId, Long mergeRequestIdForProject) { public List<ApprovalJson> getAllApprovalForMergeRequest(Long projectId, Long mergeRequestIdForProject) {
return HttpParse.request( return HttpParse.request(
MessageFormat.format(gitlabProperty.getMergeRequestApprovalUrl(), projectId, mergeRequestIdForProject) MessageFormat.format(gitlabUrl.getMergeRequestApproval(), projectId, mergeRequestIdForProject)
) )
.header(ACCEPT) .header(ACCEPT)
.header(StringUtils.H_PRIVATE_TOKEN, gitlabProperty.getAccessToken()) .header(StringUtils.H_PRIVATE_TOKEN, gitlabProperty.getAccessToken())
@ -119,7 +130,7 @@ public class GitlabSdkManager {
final List<ForkJoinTask<Optional<MergeRequestJson>>> tasks = projectIdAndMrIdForProject.stream() final List<ForkJoinTask<Optional<MergeRequestJson>>> tasks = projectIdAndMrIdForProject.stream()
.map( .map(
pair -> new GetSingleMergeRequestTask( pair -> new GetSingleMergeRequestTask(
gitlabProperty.getMergeRequestUrl(), gitlabUrl.getMergeRequest(),
pair.getKey(), pair.getKey(),
pair.getValue(), pair.getValue(),
gitlabProperty.getAccessToken() gitlabProperty.getAccessToken()
@ -138,7 +149,7 @@ public class GitlabSdkManager {
pair -> GetPipelineTask.builder() pair -> GetPipelineTask.builder()
.pipelineId(pair.getValue()) .pipelineId(pair.getValue())
.projectId(pair.getKey()) .projectId(pair.getKey())
.urlPipeline(gitlabProperty.getPipelineUrl()) .urlPipeline(gitlabUrl.getPipeline())
.gitlabToken(gitlabProperty.getAccessToken()) .gitlabToken(gitlabProperty.getAccessToken())
.build() .build()
) )
@ -153,7 +164,7 @@ public class GitlabSdkManager {
public List<PipelineShortJson> getAllPipeline(Collection<Long> projectIds, LocalDateTime updatedAfter) { public List<PipelineShortJson> getAllPipeline(Collection<Long> projectIds, LocalDateTime updatedAfter) {
final List<ForkJoinTask<List<PipelineShortJson>>> tasks = projectIds.stream() final List<ForkJoinTask<List<PipelineShortJson>>> tasks = projectIds.stream()
.map(projectId -> new GetPipelineShortTask( .map(projectId -> new GetPipelineShortTask(
gitlabProperty.getPipelinesUrl(), gitlabUrl.getPipelines(),
projectId, projectId,
updatedAfter, updatedAfter,
gitlabProperty.getAccessToken() gitlabProperty.getAccessToken()
@ -165,7 +176,7 @@ public class GitlabSdkManager {
} }
public List<DiscussionJson> getDiscussionForMergeRequest(Long projectId, Long mergeRequestIdForProject, int pageNumber) { public List<DiscussionJson> getDiscussionForMergeRequest(Long projectId, Long mergeRequestIdForProject, int pageNumber) {
return HttpParse.request(MessageFormat.format(gitlabProperty.getDiscussionsUrl(), projectId, mergeRequestIdForProject, pageNumber, pageNumber)) return HttpParse.request(MessageFormat.format(gitlabUrl.getDiscussions(), projectId, mergeRequestIdForProject, pageNumber, pageNumber))
.header(ACCEPT) .header(ACCEPT)
.header(H_PRIVATE_TOKEN, gitlabProperty.getAccessToken()) .header(H_PRIVATE_TOKEN, gitlabProperty.getAccessToken())
.executeList(DiscussionJson.class); .executeList(DiscussionJson.class);
@ -180,7 +191,7 @@ public class GitlabSdkManager {
private String createLinkOldDiscussion(Long projectId, Long mergeRequestIdForProject, String discussionId) { private String createLinkOldDiscussion(Long projectId, Long mergeRequestIdForProject, String discussionId) {
return MessageFormat.format( return MessageFormat.format(
gitlabProperty.getDiscussionUrl(), gitlabUrl.getDiscussion(),
projectId, projectId,
mergeRequestIdForProject, mergeRequestIdForProject,
discussionId discussionId
@ -188,7 +199,7 @@ public class GitlabSdkManager {
} }
public void sendMessageToDiscussion(Long projectId, Long mergeRequestIdForProject, String discussionId, String message) { public void sendMessageToDiscussion(Long projectId, Long mergeRequestIdForProject, String discussionId, String message) {
final String requestUrl = MessageFormat.format(gitlabProperty.getNewNoteUrl(), projectId, mergeRequestIdForProject, discussionId, message); final String requestUrl = MessageFormat.format(gitlabUrl.getNewNote(), projectId, mergeRequestIdForProject, discussionId, message);
final RequestBody formBody = new FormBody.Builder().build(); final RequestBody formBody = new FormBody.Builder().build();

View File

@ -18,57 +18,4 @@ public class GitlabProperty {
private String replaceUrl; private String replaceUrl;
private String usersUrl;
private String userUrl;
private String projectsUrl;
/**
* Адрес, по которому можно получить открытые MR
*/
private String openMergeRequestsUrl;
/**
* Адрес, по которому можно получить закрытые MR
*/
private String closeMergeRequestsUrl;
/**
* Адрес, по которому можно получить комментарии к MR
*/
private String commentsOfMergeRequestUrl;
/**
* Адрес MR
*/
private String mergeRequestUrl;
/**
* Адрес, по которому можно получить апрувы.
*/
private String mergeRequestApprovalUrl;
private String projectAddUrl;
private String noteUrl;
private String notesOfMergeRequestUrl;
private String pipelinesUrl;
private String pipelineUrl;
private String lastCommitOfMergeRequestUrl;
private String newNoteUrl;
/**
* Адрес дискуссий для MR
*/
private String discussionsUrl;
private String discussionUrl;
} }

View File

@ -0,0 +1,49 @@
package dev.struchkov.bot.gitlab.sdk.config;
import lombok.Getter;
import org.springframework.stereotype.Component;
@Getter
@Component
public class GitlabUrl {
private final String users;
private final String user;
private final String projects;
private final String openMergeRequests;
private final String closeMergeRequests;
private final String commentsOfMergeRequest;
private final String mergeRequest;
private final String mergeRequestApproval;
private final String projectAdd;
private final String note;
private final String noteOfMergeRequest;
private final String pipelines;
private final String pipeline;
private final String lastCommitOfMergeRequest;
private final String newNote;
private final String discussions;
private final String discussion;
public GitlabUrl(GitlabProperty gitlabProperty) {
final String baseUrl = gitlabProperty.getBaseUrl();
this.users = baseUrl + "/api/v4/users";
this.user = baseUrl + "/api/v4/user";
this.projects = baseUrl + "/api/v4/projects?page={0, number, integer}&per_page=100";
this.openMergeRequests = baseUrl + "/api/v4/projects/{0,number,#}/merge_requests?state=opened&page={1, number, integer}&per_page={2, number, integer}";
this.closeMergeRequests = baseUrl + "/api/v4/projects/{0,number,#}/merge_requests?state=closed&page={1, number, integer}&per_page=100";
this.commentsOfMergeRequest = baseUrl + "/api/v4/projects/{0,number,#}/merge_requests/{1,number,#}/notes?&page={2,number,#}&per_page=100";
this.mergeRequest = baseUrl + "/api/v4/projects/{0,number,#}/merge_requests/{1,number,#}";
this.mergeRequestApproval = baseUrl + "/api/v4/projects/{0,number,#}/merge_requests/{1,number,#}/approvals";
this.projectAdd = baseUrl + "/api/v4/projects/";
this.note = baseUrl + "{0}#note_{1,number,#}";
this.noteOfMergeRequest = baseUrl + "/api/v4/projects/{0,number,#}/merge_requests/{1,number,#}/notes/{2,number,#}";
this.pipelines = baseUrl + "/api/v4/projects/{0,number,#}/pipelines?&page={1,number,#}&per_page={2,number,#}";
this.pipeline = baseUrl + "/api/v4/projects/{0,number,#}/pipelines/{1,number,#}";
this.lastCommitOfMergeRequest = baseUrl + "/api/v4/projects/{0,number,#}/merge_requests/{1,number,#}/commits?&page=1&per_page=1";
this.newNote = baseUrl + "/api/v4/projects/{0,number,#}/merge_requests/{1,number,#}/discussions/{2}/notes?body={3}";
this.discussions = baseUrl + "/api/v4/projects/{0,number,#}/merge_requests/{1,number,#}/discussions?&page={2,number,#}&per_page={3,number,#}";
this.discussion = baseUrl + "/api/v4/projects/{0,number,#}/merge_requests/{1,number,#}/discussions/{2}";
}
}

View File

@ -1,8 +0,0 @@
package dev.struchkov.bot.gitlab.sdk.util;
import lombok.experimental.UtilityClass;
@UtilityClass
public class GitlabUrlParser {
}

View File

@ -10,6 +10,7 @@ import dev.struchkov.bot.gitlab.context.service.ProjectService;
import dev.struchkov.bot.gitlab.context.utils.Icons; import dev.struchkov.bot.gitlab.context.utils.Icons;
import dev.struchkov.bot.gitlab.core.parser.ProjectParser; import dev.struchkov.bot.gitlab.core.parser.ProjectParser;
import dev.struchkov.bot.gitlab.sdk.config.GitlabProperty; import dev.struchkov.bot.gitlab.sdk.config.GitlabProperty;
import dev.struchkov.bot.gitlab.sdk.config.GitlabUrl;
import dev.struchkov.bot.gitlab.telegram.utils.UnitName; import dev.struchkov.bot.gitlab.telegram.utils.UnitName;
import dev.struchkov.godfather.main.domain.annotation.Unit; import dev.struchkov.godfather.main.domain.annotation.Unit;
import dev.struchkov.godfather.main.domain.content.Mail; import dev.struchkov.godfather.main.domain.content.Mail;
@ -57,6 +58,7 @@ import static java.util.Collections.singleton;
public class MenuConfig implements PersonUnitConfiguration { public class MenuConfig implements PersonUnitConfiguration {
private final GitlabProperty gitlabProperty; private final GitlabProperty gitlabProperty;
private final GitlabUrl gitlabUrl;
private final PersonInformation personInformation; private final PersonInformation personInformation;
private final ProjectParser projectParser; private final ProjectParser projectParser;
@ -148,7 +150,7 @@ public class MenuConfig implements PersonUnitConfiguration {
.answer(mail -> { .answer(mail -> {
final List<LinkAttachment> links = Attachments.findAllLinks(mail.getAttachments()); final List<LinkAttachment> links = Attachments.findAllLinks(mail.getAttachments());
for (LinkAttachment link : links) { for (LinkAttachment link : links) {
final String projectUrl = gitlabProperty.getProjectAddUrl() + link.getUrl().replace(gitlabProperty.getBaseUrl(), "") final String projectUrl = gitlabUrl.getProjectAdd() + link.getUrl().replace(gitlabProperty.getBaseUrl(), "")
.substring(1) .substring(1)
.replace("/", "%2F"); .replace("/", "%2F");
final Project project = projectParser.parseByUrl(projectUrl); final Project project = projectParser.parseByUrl(projectUrl);