Вроде работает :)

This commit is contained in:
upagge 2020-09-22 14:35:27 +03:00
parent c7141f980c
commit 9f687469ee
No known key found for this signature in database
GPG Key ID: 15CD012E46F6BA34
51 changed files with 1201 additions and 31 deletions

View File

@ -31,6 +31,12 @@
<version>2.1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.sadtech.bot.bitbucketbot</groupId>
<artifactId>teamcity-core</artifactId>
<version>2.1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.sadtech.bot.bitbucketbot</groupId>
<artifactId>bitbucket-sdk</artifactId>

View File

@ -5,9 +5,9 @@ import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.domain.EntityScan;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
@EnableJpaRepositories(basePackages = "org.sadtech.bot.vcs.core.repository.jpa")
@EnableJpaRepositories(basePackages = {"org.sadtech.bot.vcs.core.repository.jpa", "org.sadtech.bot.vcs.teamcity.core.repository.jpa"})
@SpringBootApplication(scanBasePackages = "org.sadtech.bot.vcs")
@EntityScan(basePackages = "org.sadtech.bot.vcs.core.domain.entity")
@EntityScan(basePackages = {"org.sadtech.bot.vcs.core.domain.entity", "org.sadtech.bot.vcs.teamcity.core.domain.entity"})
public class BitbucketbotApplication {
public static void main(String[] args) {

View File

@ -24,7 +24,7 @@ public class AppConfig {
@Bean
public TaskScheduler taskScheduler() {
ThreadPoolTaskScheduler taskScheduler = new ThreadPoolTaskScheduler();
taskScheduler.setPoolSize(10);
taskScheduler.setPoolSize(12);
return taskScheduler;
}

View File

@ -30,9 +30,9 @@ public class PullRequestJsonConverter implements Converter<PullRequestJson, Pull
pullRequest.setCreateDate(json.getCreatedDate());
pullRequest.setUpdateDate(json.getUpdatedDate());
pullRequest.setConflict(convertConflict(json.getProperties()));
pullRequest.setDescription(convertDescription(json.getDescription()));
pullRequest.setDescription(convertString(json.getDescription(), 180));
pullRequest.setAuthorLogin(json.getAuthor().getUser().getName());
pullRequest.setTitle(json.getTitle());
pullRequest.setTitle(convertString(json.getTitle(), 90));
pullRequest.setUrl(json.getLinks().getSelf().get(0).getHref());
pullRequest.setStatus(convertPullRequestStatus(json.getState()));
pullRequest.setProjectKey(json.getFromRef().getRepository().getProject().getKey());
@ -50,9 +50,9 @@ public class PullRequestJsonConverter implements Converter<PullRequestJson, Pull
&& Outcome.CONFLICTED.equals(properties.getMergeResult().getOutcome());
}
private String convertDescription(String description) {
if (description != null) {
return description.length() > 180 ? description.substring(0, 180) + "..." : description;
private String convertString(String string, int length) {
if (string != null) {
return string.length() > length ? string.substring(0, length) + "..." : string;
}
return null;
}

View File

@ -32,4 +32,8 @@ bitbucketbot:
url-pull-request-close: http://192.168.236.164:7990/rest/api/1.0/dashboard/pull-requests?limit=150&closedSince=86400
url-pull-request-comment: http://192.168.236.164:7990/rest/api/1.0/projects/{projectKey}/repos/{repositorySlug}/pull-requests/{pullRequestId}/comments/{commentId}
url-pull-request: http://192.168.236.164:7990/projects/{projectKey}/repos/{repositorySlug}/pull-requests/{pullRequestId}/overview
url-users: http://192.168.236.164:7990/rest/api/1.0/admin/users
url-users: http://192.168.236.164:7990/rest/api/1.0/admin/users
teamcity:
token: ${TEAMCITY_ADMIN_TOKEN}
project-url: http://192.168.236.164:8111/app/rest/projects
build-url: http://192.168.236.164:8111/app/rest/builds/?locator=project:(id:{0}),branch:(default:any)

View File

@ -32,4 +32,8 @@ bitbucketbot:
url-pull-request-close: http://localhost:7990/rest/api/1.0/dashboard/pull-requests?limit=150&closedSince=86400
url-pull-request-comment: http://localhost:7990/rest/api/1.0/projects/{projectKey}/repos/{repositorySlug}/pull-requests/{pullRequestId}/comments/{commentId}
url-pull-request: http://localhost:7990/projects/{projectKey}/repos/{repositorySlug}/pull-requests/{pullRequestId}/overview
url-users: http://localhost:7990/rest/api/1.0/admin/users
url-users: http://localhost:7990/rest/api/1.0/admin/users
teamcity:
token: ${TEAMCITY_ADMIN_TOKEN}
project-url: http://localhost:8111/app/rest/projects
build-url: http://localhost:8111/app/rest/builds/?locator=project:(id:{0}),branch:(default:any)

View File

@ -3,12 +3,6 @@
xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.1.xsd">
<changeSet id="2020-09-20-create-table-teamcity-setting" author="upagge">
<createTable tableName="teamcity_setting">
<column name="chat_id"></column>
</createTable>
</changeSet>
<changeSet id="2020-09-21-create-table-teamcity_project" author="upagge">
<createTable tableName="teamcity_project">
<column name="id" type="varchar(64)">
@ -24,15 +18,55 @@
</createTable>
</changeSet>
<changeSet id="2020-09-20-create-table-teamcity_builds" author="upagge">
<createTable tableName="teamcity_builds">
<column name="id" type="int">
<constraints primaryKey="true" nullable="false"/>
<changeSet id="2020-09-20-create-table-teamcity-setting" author="upagge">
<createTable tableName="teamcity_setting">
<column name="id" type="integer" autoIncrement="true">
<constraints nullable="false" primaryKey="true"/>
</column>
<column name="chat_id" type="integer">
<constraints nullable="false"/>
</column>
<column name="project_id" type="varchar(64)">
<constraints nullable="false" foreignKeyName="teamcity_setting_project_id_teamcity_project_id"
references="teamcity_project(id)" deleteCascade="true"/>
</column>
<column name="number" type="int"/>
</createTable>
</changeSet>
<changeSet id="2020-09-20-create-table-teamcity-build" author="upagge">
<createTable tableName="teamcity_build">
<column name="id" type="integer">
<constraints primaryKey="true" nullable="false"/>
</column>
<column name="project_id" type="varchar(64)">
<constraints nullable="false" foreignKeyName="teamcity_build_project_id_teamcity_project_id"
references="teamcity_project(id)" deleteCascade="true"/>
</column>
<column name="number" type="integer"/>
<column name="status" type="varchar(64)">
<constraints nullable="false"/>
</column>
<column name="state" type="varchar(64)">
<constraints nullable="false"/>
</column>
<column name="branch_name" type="varchar(64)">
<constraints nullable="false"/>
</column>
<column name="api_url" type="varchar(64)">
<constraints nullable="false"/>
</column>
<column name="url" type="varchar(300)">
<constraints nullable="false"/>
</column>
</createTable>
</changeSet>
<changeSet id="2020-09-22-add-column-build-type-id" author="upagge">
<addColumn tableName="teamcity_build">
<column name="build_type_id" type="varchar(200)">
<constraints nullable="false"/>
</column>
</addColumn>
</changeSet>
</databaseChangeLog>

View File

@ -55,8 +55,8 @@ public class GoodMorningNotify extends Notify {
StringBuilder message = new StringBuilder().append(Smile.SUN).append(" *Доброе утро* ").append(Smile.SUN).append(Smile.HR);
if (!pullRequestsReviews.isEmpty()) {
message.append("Необходимо проверить ").append(pullRequestsReviews.size()).append(" ПР!").append(Smile.TWO_BR)
.append("Самые старые:").append(Smile.BR)
.append(MessageUtils.pullRequestForReview(pullRequestsReviews));
.append("Самые старые:").append(Smile.BR);
MessageUtils.pullRequestForReview(pullRequestsReviews).ifPresent(message::append);
} else {
message.append("Ты либо самый лучший работник, либо тебе не доверяют проверку ПР ").append(Smile.MEGA_FUN).append(Smile.TWO_BR)
.append("Поздравляю, у тебя ни одного ПР на проверку!").append(Smile.BR);

View File

@ -9,9 +9,11 @@ import java.util.Set;
@Setter
public abstract class Notify {
protected TypeNotify typeNotify;
protected Set<String> logins;
protected Notify(Set<String> logins) {
this.typeNotify = TypeNotify.PERSON;
this.logins = logins;
}

View File

@ -0,0 +1,13 @@
package org.sadtech.bot.vcs.core.domain.notify;
/**
* // TODO: 21.09.2020 Добавить описание.
*
* @author upagge 21.09.2020
*/
public enum TypeNotify {
SERVICE,
PERSON
}

View File

@ -39,6 +39,7 @@ public class Utils {
Request request = new Request.Builder()
.url(urlValue)
.header("Authorization", "Bearer " + token)
.header("Accept", "text/html,application/xhtml+xml,application/json")
.build();
try (final Response execute = client.newCall(request).execute()) {
if (execute.isSuccessful() && execute.body() != null) {

View File

@ -128,7 +128,7 @@ public class TaskServiceImpl extends AbstractSimpleManagerService<Task, Long> im
notifyService.send(
AnswerCommentNotify.builder()
.logins(Collections.singleton(oldTask.getAuthor()))
.url(task.getUrl())
.url(oldTask.getUrl())
.youMessage(oldTask.getDescription())
.answers(
newAnswers.stream()

View File

@ -30,7 +30,10 @@ public enum Smile {
MEGA_FUN("\uD83D\uDE02"),
DANGEROUS("⚠️"),
BELL("\uD83D\uDECE"),
HR("\n -- -- -- -- --\n");
HR("\n -- -- -- -- --\n"),
FAILURE(""),
SUCCESS(""),
BUILD("♻️");
@Getter
private String value;

10
pom.xml
View File

@ -14,6 +14,7 @@
<module>bot-core</module>
<module>bitbucket-app</module>
<module>bot-rest</module>
<module>teamcity</module>
</modules>
<groupId>org.sadtech.bot.bitbucketbot</groupId>
@ -24,7 +25,7 @@
<properties>
<java.version>1.8</java.version>
<vcs.core>2.1.0-SNAPSHPOT></vcs.core>
<vcs.core>2.1.0-SNAPSHOT</vcs.core>
<sadtech.project.database>0.1.0-SNAPSHOT</sadtech.project.database>
<sadtech.project.filter.criteria>0.1.0-SNAPSHOT</sadtech.project.filter.criteria>
@ -32,6 +33,7 @@
<hibernate.jpamodelgen>6.0.0.Alpha5</hibernate.jpamodelgen>
<liquibase.core>3.8.5</liquibase.core>
<postgresql>42.2.9</postgresql>
<javax.persistance>2.2</javax.persistance>
<springboot.config.processor>2.3.1.RELEASE</springboot.config.processor>
@ -140,6 +142,12 @@
<version>${jackson.version}</version>
</dependency>
<dependency>
<groupId>javax.persistence</groupId>
<artifactId>javax.persistence-api</artifactId>
<version>${javax.persistance}</version>
</dependency>
<!-- <dependency>-->
<!-- <groupId>org.springframework.boot</groupId>-->

30
teamcity/pom.xml Normal file
View File

@ -0,0 +1,30 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>bitbucketbot</artifactId>
<groupId>org.sadtech.bot.bitbucketbot</groupId>
<version>2.1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>teamcity</artifactId>
<packaging>pom</packaging>
<modules>
<module>teamcity-sdk</module>
<module>teamcity-core</module>
</modules>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.sadtech.bot.bitbucketbot</groupId>
<artifactId>teamcity-sdk</artifactId>
<version>2.1.0-SNAPSHOT</version>
</dependency>
</dependencies>
</dependencyManagement>
</project>

View File

@ -0,0 +1,43 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>teamcity</artifactId>
<groupId>org.sadtech.bot.bitbucketbot</groupId>
<version>2.1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>teamcity-core</artifactId>
<dependencies>
<dependency>
<groupId>org.sadtech.bot.bitbucketbot</groupId>
<artifactId>bot-core</artifactId>
</dependency>
<dependency>
<groupId>org.sadtech.bot.bitbucketbot</groupId>
<artifactId>teamcity-sdk</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<!-- <dependency>-->
<!-- <groupId>javax.persistence</groupId>-->
<!-- <artifactId>javax.persistence-api</artifactId>-->
<!-- </dependency>-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,23 @@
package org.sadtech.bot.vcs.teamcity.core.config.property;
import lombok.Getter;
import lombok.Setter;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
/**
* // TODO: 21.09.2020 Добавить описание.
*
* @author upagge 21.09.2020
*/
@Getter
@Setter
@Component
@ConfigurationProperties(prefix = "bitbucketbot.teamcity")
public class TeamcityProperty {
private String token;
private String projectUrl;
private String buildUrl;
}

View File

@ -0,0 +1,55 @@
package org.sadtech.bot.vcs.teamcity.core.domain;
import lombok.Builder;
import lombok.Getter;
import org.sadtech.bot.vcs.core.domain.notify.Notify;
import org.sadtech.bot.vcs.core.domain.notify.TypeNotify;
import org.sadtech.bot.vcs.core.utils.Smile;
import org.sadtech.bot.vcs.teamcity.core.domain.entity.BuildShort;
import org.sadtech.bot.vcs.teamcity.sdk.BuildStatus;
import java.text.MessageFormat;
import java.util.Collections;
/**
* // TODO: 21.09.2020 Добавить описание.
*
* @author upagge 21.09.2020
*/
@Getter
public class ServiceNotify extends Notify {
private final Long chatId;
private final BuildShort buildShort;
@Builder
private ServiceNotify(Long chatId, BuildShort buildShort) {
super(Collections.emptySet());
this.chatId = chatId;
this.buildShort = buildShort;
this.typeNotify = TypeNotify.SERVICE;
}
@Override
public String generateMessage() {
return MessageFormat.format(
"{0} *Сборка* | {1,number,#}:{2,number,#} | {3}" +
"{4} [{5}]({6}) {4}" +
"{7} {8}",
Smile.BUILD,
buildShort.getId(),
buildShort.getNumber(),
buildShort.getProjectId(),
Smile.HR,
buildShort.getBuildTypeId(),
buildShort.getUrl(),
getSmile(buildShort),
buildShort.getStatus()
);
}
private String getSmile(BuildShort buildShort) {
return BuildStatus.SUCCESS.equals(buildShort.getStatus()) ? Smile.SUCCESS.getValue() : Smile.FAILURE.getValue();
}
}

View File

@ -0,0 +1,59 @@
package org.sadtech.bot.vcs.teamcity.core.domain.entity;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.Setter;
import org.sadtech.bot.vcs.teamcity.sdk.BuildState;
import org.sadtech.bot.vcs.teamcity.sdk.BuildStatus;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.EnumType;
import javax.persistence.Enumerated;
import javax.persistence.Id;
import javax.persistence.Table;
/**
* // TODO: 21.09.2020 Добавить описание.
*
* @author upagge 21.09.2020
*/
@Getter
@Setter
@Entity
@Table(name = "teamcity_build")
@EqualsAndHashCode(onlyExplicitlyIncluded = true)
public class BuildShort {
@Id
@Column(name = "id")
@EqualsAndHashCode.Include
private Long id;
@Column(name = "project_id")
private String projectId;
@Column(name = "number")
private Integer number;
@Enumerated(EnumType.STRING)
@Column(name = "state")
private BuildState state;
@Enumerated(EnumType.STRING)
@Column(name = "status")
private BuildStatus status;
@Column(name = "branch_name")
private String branchName;
@Column(name = "build_type_id")
private String buildTypeId;
@Column(name = "api_url")
private String apiUrl;
@Column(name = "url")
private String url;
}

View File

@ -0,0 +1,38 @@
package org.sadtech.bot.vcs.teamcity.core.domain.entity;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.Setter;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
/**
* // TODO: 21.09.2020 Добавить описание.
*
* @author upagge 21.09.2020
*/
@Getter
@Setter
@Entity
@Table(name = "teamcity_project")
@EqualsAndHashCode(onlyExplicitlyIncluded = true)
public class TeamcityProject {
@Id
@Column(name = "id")
@EqualsAndHashCode.Include
private String id;
@Column(name = "name")
private String name;
@Column(name = "description")
private String description;
@Column(name = "url")
private String url;
}

View File

@ -0,0 +1,38 @@
package org.sadtech.bot.vcs.teamcity.core.domain.entity;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.Setter;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
/**
* // TODO: 21.09.2020 Добавить описание.
*
* @author upagge 21.09.2020
*/
@Getter
@Setter
@Entity
@Table(name = "teamcity_setting")
@EqualsAndHashCode(onlyExplicitlyIncluded = true)
public class TeamcitySetting {
@Id
@Column(name = "id")
@EqualsAndHashCode.Include
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(name = "chat_id")
private Long chatId;
@Column(name = "project_id")
private String projectId;
}

View File

@ -0,0 +1,18 @@
package org.sadtech.bot.vcs.teamcity.core.repository;
import lombok.NonNull;
import org.sadtech.basic.context.repository.SimpleManagerRepository;
import org.sadtech.bot.vcs.teamcity.core.domain.entity.BuildShort;
import java.util.Set;
/**
* // TODO: 21.09.2020 Добавить описание.
*
* @author upagge 21.09.2020
*/
public interface BuildShortRepository extends SimpleManagerRepository<BuildShort, Long> {
Set<Long> exists(@NonNull Set<Long> buildIds);
}

View File

@ -0,0 +1,19 @@
package org.sadtech.bot.vcs.teamcity.core.repository;
import lombok.NonNull;
import org.sadtech.basic.context.repository.SimpleManagerRepository;
import org.sadtech.bot.vcs.teamcity.core.domain.entity.TeamcityProject;
import java.util.List;
import java.util.Set;
/**
* // TODO: 21.09.2020 Добавить описание.
*
* @author upagge 21.09.2020
*/
public interface TeamcityProjectRepository extends SimpleManagerRepository<TeamcityProject, String> {
List<String> exists(@NonNull Set<String> projectIds);
}

View File

@ -0,0 +1,18 @@
package org.sadtech.bot.vcs.teamcity.core.repository;
import lombok.NonNull;
import org.sadtech.basic.context.repository.SimpleManagerRepository;
import org.sadtech.bot.vcs.teamcity.core.domain.entity.TeamcitySetting;
import java.util.List;
/**
* // TODO: 21.09.2020 Добавить описание.
*
* @author upagge 21.09.2020
*/
public interface TeamcitySettingRepository extends SimpleManagerRepository<TeamcitySetting, Long> {
List<TeamcitySetting> findAllByProjectId(@NonNull String projectId);
}

View File

@ -0,0 +1,32 @@
package org.sadtech.bot.vcs.teamcity.core.repository.impl;
import lombok.NonNull;
import org.sadtech.basic.database.repository.manager.AbstractSimpleManagerRepository;
import org.sadtech.bot.vcs.teamcity.core.domain.entity.BuildShort;
import org.sadtech.bot.vcs.teamcity.core.repository.BuildShortRepository;
import org.sadtech.bot.vcs.teamcity.core.repository.jpa.BuildShortJpaRepository;
import org.springframework.stereotype.Repository;
import java.util.Set;
/**
* // TODO: 21.09.2020 Добавить описание.
*
* @author upagge 21.09.2020
*/
@Repository
public class BuildShortRepositoryImpl extends AbstractSimpleManagerRepository<BuildShort, Long> implements BuildShortRepository {
private final BuildShortJpaRepository jpaRepository;
public BuildShortRepositoryImpl(BuildShortJpaRepository jpaRepository) {
super(jpaRepository);
this.jpaRepository = jpaRepository;
}
@Override
public Set<Long> exists(@NonNull Set<Long> buildIds) {
return jpaRepository.existsByIds(buildIds);
}
}

View File

@ -0,0 +1,32 @@
package org.sadtech.bot.vcs.teamcity.core.repository.impl;
import lombok.NonNull;
import org.sadtech.basic.database.repository.manager.AbstractSimpleManagerRepository;
import org.sadtech.bot.vcs.teamcity.core.domain.entity.TeamcityProject;
import org.sadtech.bot.vcs.teamcity.core.repository.TeamcityProjectRepository;
import org.sadtech.bot.vcs.teamcity.core.repository.jpa.TeamcityProjectJpaRepository;
import org.springframework.stereotype.Repository;
import java.util.List;
import java.util.Set;
/**
* // TODO: 21.09.2020 Добавить описание.
*
* @author upagge 21.09.2020
*/
@Repository
public class TeamcityProjectRepositoryImpl extends AbstractSimpleManagerRepository<TeamcityProject, String> implements TeamcityProjectRepository {
private final TeamcityProjectJpaRepository teamcityProjectJpaRepository;
public TeamcityProjectRepositoryImpl(TeamcityProjectJpaRepository teamcityProjectJpaRepository) {
super(teamcityProjectJpaRepository);
this.teamcityProjectJpaRepository = teamcityProjectJpaRepository;
}
@Override
public List<String> exists(@NonNull Set<String> projectIds) {
return teamcityProjectJpaRepository.existsAllById(projectIds);
}
}

View File

@ -0,0 +1,32 @@
package org.sadtech.bot.vcs.teamcity.core.repository.impl;
import lombok.NonNull;
import org.sadtech.basic.database.repository.manager.AbstractSimpleManagerRepository;
import org.sadtech.bot.vcs.teamcity.core.domain.entity.TeamcitySetting;
import org.sadtech.bot.vcs.teamcity.core.repository.TeamcitySettingRepository;
import org.sadtech.bot.vcs.teamcity.core.repository.jpa.TeamcitySettingJpaRepository;
import org.springframework.stereotype.Repository;
import java.util.List;
/**
* // TODO: 21.09.2020 Добавить описание.
*
* @author upagge 21.09.2020
*/
@Repository
public class TeamcitySettingRepositoryImpl extends AbstractSimpleManagerRepository<TeamcitySetting, Long> implements TeamcitySettingRepository {
private final TeamcitySettingJpaRepository jpaRepository;
public TeamcitySettingRepositoryImpl(TeamcitySettingJpaRepository jpaRepository) {
super(jpaRepository);
this.jpaRepository = jpaRepository;
}
@Override
public List<TeamcitySetting> findAllByProjectId(@NonNull String projectId) {
return jpaRepository.findAllByProjectId(projectId);
}
}

View File

@ -0,0 +1,20 @@
package org.sadtech.bot.vcs.teamcity.core.repository.jpa;
import org.sadtech.bot.vcs.teamcity.core.domain.entity.BuildShort;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import java.util.Set;
/**
* // TODO: 21.09.2020 Добавить описание.
*
* @author upagge 21.09.2020
*/
public interface BuildShortJpaRepository extends JpaRepository<BuildShort, Long> {
@Query("SELECT b.id FROM BuildShort b WHERE b.id IN :buildIds")
Set<Long> existsByIds(@Param("buildIds") Set<Long> buildIds);
}

View File

@ -0,0 +1,21 @@
package org.sadtech.bot.vcs.teamcity.core.repository.jpa;
import org.sadtech.bot.vcs.teamcity.core.domain.entity.TeamcityProject;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import java.util.List;
import java.util.Set;
/**
* // TODO: 21.09.2020 Добавить описание.
*
* @author upagge 21.09.2020
*/
public interface TeamcityProjectJpaRepository extends JpaRepository<TeamcityProject, String> {
@Query("SELECT t.id FROM TeamcityProject t WHERE t.id IN :projectIds")
List<String> existsAllById(@Param("projectIds") Set<String> projectIds);
}

View File

@ -0,0 +1,17 @@
package org.sadtech.bot.vcs.teamcity.core.repository.jpa;
import org.sadtech.bot.vcs.teamcity.core.domain.entity.TeamcitySetting;
import org.springframework.data.jpa.repository.JpaRepository;
import java.util.List;
/**
* // TODO: 21.09.2020 Добавить описание.
*
* @author upagge 21.09.2020
*/
public interface TeamcitySettingJpaRepository extends JpaRepository<TeamcitySetting, Long> {
List<TeamcitySetting> findAllByProjectId(String projectId);
}

View File

@ -0,0 +1,31 @@
package org.sadtech.bot.vcs.teamcity.core.scheduler;
import lombok.RequiredArgsConstructor;
import org.sadtech.bot.vcs.teamcity.core.service.parser.BuildShortParser;
import org.sadtech.bot.vcs.teamcity.core.service.parser.TeamcityProjectParser;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
/**
* // TODO: 21.09.2020 Добавить описание.
*
* @author upagge 21.09.2020
*/
@Component
@RequiredArgsConstructor
public class TeamcityProjectScheduler {
private final TeamcityProjectParser projectParser;
private final BuildShortParser buildShortParser;
@Scheduled(cron = "0 */1 * * * *")
public void parseNewProject() {
projectParser.parseNewProject();
}
@Scheduled(cron = "0 */1 * * * *")
public void parseNewBuilds() {
buildShortParser.parseNewBuilds();
}
}

View File

@ -0,0 +1,17 @@
package org.sadtech.bot.vcs.teamcity.core.service;
import org.sadtech.basic.context.service.SimpleManagerService;
import org.sadtech.bot.vcs.teamcity.core.domain.entity.BuildShort;
import java.util.Set;
/**
* // TODO: 21.09.2020 Добавить описание.
*
* @author upagge 21.09.2020
*/
public interface BuildShortService extends SimpleManagerService<BuildShort, Long> {
Set<Long> exists(Set<Long> buildIds);
}

View File

@ -0,0 +1,19 @@
package org.sadtech.bot.vcs.teamcity.core.service;
import lombok.NonNull;
import org.sadtech.basic.context.service.SimpleManagerService;
import org.sadtech.bot.vcs.teamcity.core.domain.entity.TeamcityProject;
import java.util.List;
import java.util.Set;
/**
* // TODO: 21.09.2020 Добавить описание.
*
* @author upagge 21.09.2020
*/
public interface TeamcityProjectService extends SimpleManagerService<TeamcityProject, String> {
List<String> exists(@NonNull Set<String> projectIds);
}

View File

@ -0,0 +1,18 @@
package org.sadtech.bot.vcs.teamcity.core.service;
import lombok.NonNull;
import org.sadtech.basic.context.service.SimpleManagerService;
import org.sadtech.bot.vcs.teamcity.core.domain.entity.TeamcitySetting;
import java.util.List;
/**
* // TODO: 21.09.2020 Добавить описание.
*
* @author upagge 21.09.2020
*/
public interface TeamcitySettingService extends SimpleManagerService<TeamcitySetting, Long> {
List<TeamcitySetting> getAllByProjectId(@NonNull String projectId);
}

View File

@ -0,0 +1,31 @@
package org.sadtech.bot.vcs.teamcity.core.service.convert;
import org.sadtech.bot.vcs.teamcity.core.domain.entity.BuildShort;
import org.sadtech.bot.vcs.teamcity.sdk.BuildShortJson;
import org.springframework.core.convert.converter.Converter;
import org.springframework.stereotype.Component;
/**
* // TODO: 21.09.2020 Добавить описание.
*
* @author upagge 21.09.2020
*/
@Component
public class BuildShotJsonToBuildShortConvert implements Converter<BuildShortJson, BuildShort> {
@Override
public BuildShort convert(BuildShortJson source) {
final BuildShort buildShort = new BuildShort();
buildShort.setApiUrl(source.getHref());
buildShort.setBranchName(source.getBranchName());
buildShort.setId(source.getId());
buildShort.setNumber(source.getNumber());
buildShort.setState(source.getState());
buildShort.setStatus(source.getStatus());
buildShort.setUrl(source.getWebUrl());
buildShort.setProjectId(source.getProjectId());
buildShort.setBuildTypeId(source.getBuildTypeId());
return buildShort;
}
}

View File

@ -0,0 +1,26 @@
package org.sadtech.bot.vcs.teamcity.core.service.convert;
import org.sadtech.bot.vcs.teamcity.core.domain.entity.TeamcityProject;
import org.sadtech.bot.vcs.teamcity.sdk.TeamcityProjectJson;
import org.springframework.core.convert.converter.Converter;
import org.springframework.stereotype.Component;
/**
* // TODO: 21.09.2020 Добавить описание.
*
* @author upagge 21.09.2020
*/
@Component
public class TeamcityProjectJsonToTeamcityProjectConvert implements Converter<TeamcityProjectJson, TeamcityProject> {
@Override
public TeamcityProject convert(TeamcityProjectJson source) {
final TeamcityProject teamcityProject = new TeamcityProject();
teamcityProject.setId(source.getId());
teamcityProject.setDescription(source.getDescription());
teamcityProject.setName(source.getName());
teamcityProject.setUrl(source.getWebUrl());
return teamcityProject;
}
}

View File

@ -0,0 +1,61 @@
package org.sadtech.bot.vcs.teamcity.core.service.impl;
import lombok.NonNull;
import org.sadtech.basic.core.service.AbstractSimpleManagerService;
import org.sadtech.bot.vcs.core.service.NotifyService;
import org.sadtech.bot.vcs.teamcity.core.domain.ServiceNotify;
import org.sadtech.bot.vcs.teamcity.core.domain.entity.BuildShort;
import org.sadtech.bot.vcs.teamcity.core.repository.BuildShortRepository;
import org.sadtech.bot.vcs.teamcity.core.service.BuildShortService;
import org.sadtech.bot.vcs.teamcity.core.service.TeamcitySettingService;
import org.springframework.stereotype.Service;
import java.util.Set;
/**
* // TODO: 21.09.2020 Добавить описание.
*
* @author upagge 21.09.2020
*/
@Service
public class BuildShortServiceImpl extends AbstractSimpleManagerService<BuildShort, Long> implements BuildShortService {
private final TeamcitySettingService teamcitySettingService;
private final BuildShortRepository buildShortRepository;
private final NotifyService notifyService;
public BuildShortServiceImpl(TeamcitySettingService teamcitySettingService, BuildShortRepository buildShortRepository, NotifyService notifyService) {
super(buildShortRepository);
this.teamcitySettingService = teamcitySettingService;
this.buildShortRepository = buildShortRepository;
this.notifyService = notifyService;
}
@Override
public Set<Long> exists(Set<Long> buildIds) {
return buildShortRepository.exists(buildIds);
}
@Override
public BuildShort create(@NonNull BuildShort buildShort) {
final BuildShort newBuildShort = buildShortRepository.save(buildShort);
teamcitySettingService.getAllByProjectId(buildShort.getProjectId())
.forEach(
teamcitySetting -> notifyService.send(
ServiceNotify.builder()
.buildShort(buildShort)
.chatId(teamcitySetting.getChatId())
.build()
)
);
return newBuildShort;
}
@Override
public BuildShort update(@NonNull BuildShort buildShort) {
return buildShortRepository.save(buildShort);
}
}

View File

@ -0,0 +1,43 @@
package org.sadtech.bot.vcs.teamcity.core.service.impl;
import lombok.NonNull;
import org.sadtech.basic.core.service.AbstractSimpleManagerService;
import org.sadtech.bot.vcs.teamcity.core.domain.entity.TeamcityProject;
import org.sadtech.bot.vcs.teamcity.core.repository.TeamcityProjectRepository;
import org.sadtech.bot.vcs.teamcity.core.service.TeamcityProjectService;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.Set;
/**
* // TODO: 21.09.2020 Добавить описание.
*
* @author upagge 21.09.2020
*/
@Service
public class TeamcityProjectServiceImpl extends AbstractSimpleManagerService<TeamcityProject, String> implements TeamcityProjectService {
private final TeamcityProjectRepository teamcityProjectRepository;
public TeamcityProjectServiceImpl(TeamcityProjectRepository teamcityProjectRepository) {
super(teamcityProjectRepository);
this.teamcityProjectRepository = teamcityProjectRepository;
}
@Override
public List<String> exists(@NonNull Set<String> projectIds) {
return teamcityProjectRepository.exists(projectIds);
}
@Override
public TeamcityProject create(@NonNull TeamcityProject teamcityProject) {
return teamcityProjectRepository.save(teamcityProject);
}
@Override
public TeamcityProject update(@NonNull TeamcityProject teamcityProject) {
return teamcityProjectRepository.save(teamcityProject);
}
}

View File

@ -0,0 +1,42 @@
package org.sadtech.bot.vcs.teamcity.core.service.impl;
import lombok.NonNull;
import org.sadtech.basic.core.service.AbstractSimpleManagerService;
import org.sadtech.bot.vcs.teamcity.core.domain.entity.TeamcitySetting;
import org.sadtech.bot.vcs.teamcity.core.repository.TeamcitySettingRepository;
import org.sadtech.bot.vcs.teamcity.core.service.TeamcitySettingService;
import org.springframework.stereotype.Service;
import java.util.List;
/**
* // TODO: 21.09.2020 Добавить описание.
*
* @author upagge 21.09.2020
*/
@Service
public class TeamcitySettingServiceImpl extends AbstractSimpleManagerService<TeamcitySetting, Long> implements TeamcitySettingService {
private final TeamcitySettingRepository teamcitySettingRepository;
public TeamcitySettingServiceImpl(TeamcitySettingRepository teamcitySettingRepository) {
super(teamcitySettingRepository);
this.teamcitySettingRepository = teamcitySettingRepository;
}
@Override
public List<TeamcitySetting> getAllByProjectId(@NonNull String projectId) {
return teamcitySettingRepository.findAllByProjectId(projectId);
}
@Override
public TeamcitySetting create(@NonNull TeamcitySetting entity) {
return null;
}
@Override
public TeamcitySetting update(@NonNull TeamcitySetting entity) {
return null;
}
}

View File

@ -0,0 +1,71 @@
package org.sadtech.bot.vcs.teamcity.core.service.parser;
/**
* // TODO: 21.09.2020 Добавить описание.
*
* @author upagge 21.09.2020
*/
import lombok.RequiredArgsConstructor;
import org.sadtech.basic.context.page.Sheet;
import org.sadtech.basic.core.page.PaginationImpl;
import org.sadtech.bot.vcs.core.service.Utils;
import org.sadtech.bot.vcs.teamcity.core.config.property.TeamcityProperty;
import org.sadtech.bot.vcs.teamcity.core.domain.entity.BuildShort;
import org.sadtech.bot.vcs.teamcity.core.domain.entity.TeamcityProject;
import org.sadtech.bot.vcs.teamcity.core.service.BuildShortService;
import org.sadtech.bot.vcs.teamcity.core.service.TeamcityProjectService;
import org.sadtech.bot.vcs.teamcity.sdk.BuildShortJson;
import org.sadtech.bot.vcs.teamcity.sdk.sheet.BuildShortJsonSheet;
import org.springframework.core.convert.ConversionService;
import org.springframework.stereotype.Service;
import java.text.MessageFormat;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
@Service
@RequiredArgsConstructor
public class BuildShortParser {
private final BuildShortService buildShortService;
private final TeamcityProjectService projectService;
private final ConversionService conversionService;
private final TeamcityProperty teamcityProperty;
public void parseNewBuilds() {
final Sheet<TeamcityProject> projectSheet = projectService.getAll(PaginationImpl.of(0, 100));
if (projectSheet.hasContent()) {
projectSheet.getContent().forEach(this::parse);
}
}
private void parse(TeamcityProject project) {
final Optional<BuildShortJsonSheet> buildShortJsonSheet = Utils.urlToJson(
MessageFormat.format(
teamcityProperty.getBuildUrl(),
project.getId()
),
teamcityProperty.getToken(),
BuildShortJsonSheet.class
);
if (buildShortJsonSheet.isPresent()) {
final List<BuildShortJson> buildShortJsons = buildShortJsonSheet.get().getContent();
final Set<Long> buildIds = buildShortJsons.stream()
.map(BuildShortJson::getId)
.collect(Collectors.toSet());
final Set<Long> existsId = buildShortService.exists(buildIds);
final List<BuildShort> buildShorts = buildShortJsons.stream()
.filter(json -> !existsId.contains(json.getId()))
.map(json -> conversionService.convert(json, BuildShort.class))
.peek(
buildShort -> buildShort.setProjectId(project.getId())
)
.collect(Collectors.toList());
buildShortService.createAll(buildShorts);
}
}
}

View File

@ -0,0 +1,53 @@
package org.sadtech.bot.vcs.teamcity.core.service.parser;
import lombok.RequiredArgsConstructor;
import org.sadtech.bot.vcs.core.service.Utils;
import org.sadtech.bot.vcs.teamcity.core.config.property.TeamcityProperty;
import org.sadtech.bot.vcs.teamcity.core.domain.entity.TeamcityProject;
import org.sadtech.bot.vcs.teamcity.core.service.TeamcityProjectService;
import org.sadtech.bot.vcs.teamcity.sdk.TeamcityProjectJson;
import org.sadtech.bot.vcs.teamcity.sdk.sheet.TeamcityProjectJsonSheet;
import org.springframework.core.convert.ConversionService;
import org.springframework.stereotype.Component;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
/**
* // TODO: 21.09.2020 Добавить описание.
*
* @author upagge 21.09.2020
*/
@Component
@RequiredArgsConstructor
public class TeamcityProjectParser {
private final TeamcityProjectService teamcityProjectService;
private final TeamcityProperty teamcityProperty;
private final ConversionService conversionService;
public void parseNewProject() {
final Optional<TeamcityProjectJsonSheet> optTeamcityProjectJsonSheet = Utils.urlToJson(
teamcityProperty.getProjectUrl(),
teamcityProperty.getToken(),
TeamcityProjectJsonSheet.class
);
if (optTeamcityProjectJsonSheet.isPresent()) {
final List<TeamcityProjectJson> teamcityProjectJsons = optTeamcityProjectJsonSheet.get().getContent();
final Set<String> projectIds = teamcityProjectJsons.stream()
.map(TeamcityProjectJson::getId)
.collect(Collectors.toSet());
final List<String> exists = teamcityProjectService.exists(projectIds);
final List<TeamcityProject> teamcityProjects = teamcityProjectJsons.stream()
.filter(json -> !exists.contains(json.getId()))
.map(json -> conversionService.convert(json, TeamcityProject.class))
.collect(Collectors.toList());
teamcityProjectService.createAll(teamcityProjects);
}
}
}

View File

@ -0,0 +1,30 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<groupId>org.sadtech.bot.bitbucketbot</groupId>
<artifactId>teamcity</artifactId>
<version>2.1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>teamcity-sdk</artifactId>
<dependencies>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>2.11.2</version>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,25 @@
package org.sadtech.bot.vcs.teamcity.sdk;
import lombok.Getter;
import lombok.Setter;
/**
* // TODO: 21.09.2020 Добавить описание.
*
* @author upagge 21.09.2020
*/
@Getter
@Setter
public class BuildShortJson {
private Long id;
private String projectId;
private Integer number;
private BuildState state;
private BuildStatus status;
private String branchName;
private String buildTypeId;
private String href;
private String webUrl;
}

View File

@ -0,0 +1,15 @@
package org.sadtech.bot.vcs.teamcity.sdk;
import com.fasterxml.jackson.annotation.JsonProperty;
/**
* // TODO: 21.09.2020 Добавить описание.
*
* @author upagge 21.09.2020
*/
public enum BuildState {
@JsonProperty("finished")
FINISHED
}

View File

@ -0,0 +1,13 @@
package org.sadtech.bot.vcs.teamcity.sdk;
/**
* // TODO: 21.09.2020 Добавить описание.
*
* @author upagge 21.09.2020
*/
public enum BuildStatus {
SUCCESS,
FAILURE
}

View File

@ -0,0 +1,21 @@
package org.sadtech.bot.vcs.teamcity.sdk;
import lombok.Getter;
import lombok.Setter;
import java.util.List;
/**
* // TODO: 21.09.2020 Добавить описание.
*
* @author upagge 21.09.2020
*/
@Getter
@Setter
public abstract class Sheet<T> {
private Integer count;
public abstract List<T> getContent();
}

View File

@ -0,0 +1,20 @@
package org.sadtech.bot.vcs.teamcity.sdk;
import lombok.Getter;
import lombok.Setter;
/**
* // TODO: 21.09.2020 Добавить описание.
*
* @author upagge 21.09.2020
*/
@Getter
@Setter
public class TeamcityProjectJson {
private String id;
private String name;
private String description;
private String webUrl;
}

View File

@ -0,0 +1,24 @@
package org.sadtech.bot.vcs.teamcity.sdk.sheet;
import lombok.Setter;
import org.sadtech.bot.vcs.teamcity.sdk.BuildShortJson;
import org.sadtech.bot.vcs.teamcity.sdk.Sheet;
import java.util.List;
/**
* // TODO: 21.09.2020 Добавить описание.
*
* @author upagge 21.09.2020
*/
@Setter
public class BuildShortJsonSheet extends Sheet<BuildShortJson> {
private List<BuildShortJson> build;
@Override
public List<BuildShortJson> getContent() {
return build;
}
}

View File

@ -0,0 +1,24 @@
package org.sadtech.bot.vcs.teamcity.sdk.sheet;
import lombok.Setter;
import org.sadtech.bot.vcs.teamcity.sdk.Sheet;
import org.sadtech.bot.vcs.teamcity.sdk.TeamcityProjectJson;
import java.util.List;
/**
* // TODO: 21.09.2020 Добавить описание.
*
* @author upagge 21.09.2020
*/
@Setter
public class TeamcityProjectJsonSheet extends Sheet<TeamcityProjectJson> {
private List<TeamcityProjectJson> project;
@Override
public List<TeamcityProjectJson> getContent() {
return project;
}
}

View File

@ -19,6 +19,12 @@
<version>2.1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.sadtech.bot.bitbucketbot</groupId>
<artifactId>teamcity-core</artifactId>
<version>2.1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.sadtech.telegram</groupId>
<artifactId>telegram-bot</artifactId>

View File

@ -5,6 +5,7 @@ import lombok.RequiredArgsConstructor;
import org.sadtech.bot.vcs.core.domain.notify.Notify;
import org.sadtech.bot.vcs.core.service.MessageSendService;
import org.sadtech.bot.vcs.core.service.PersonService;
import org.sadtech.bot.vcs.teamcity.core.domain.ServiceNotify;
import org.sadtech.social.core.domain.BoxAnswer;
import org.sadtech.social.core.service.sender.Sending;
import org.springframework.stereotype.Service;
@ -26,10 +27,19 @@ public class MessageSendTelegramService implements MessageSendService {
@Override
public void send(@NonNull Notify notify) {
final Set<Long> telegramIds = personService.getAllTelegramIdByLogin(notify.getLogins());
telegramIds.forEach(
telegramId -> sending.send(telegramId, BoxAnswer.of(notify.generateMessage()))
);
switch (notify.getTypeNotify()) {
case PERSON:
final Set<Long> telegramIds = personService.getAllTelegramIdByLogin(notify.getLogins());
telegramIds.forEach(
telegramId -> sending.send(telegramId, BoxAnswer.of(notify.generateMessage()))
);
break;
case SERVICE:
ServiceNotify serviceNotify = (ServiceNotify) notify;
sending.send(serviceNotify.getChatId(), BoxAnswer.of(notify.generateMessage()));
break;
}
}
}