Olá a todos. Deixe-me lembrá-lo: na primeira parte adicionamos Flyway. Vamos continuar.
Adicionando um banco de dados ao docker-compose.yml
A próxima etapa é configurar o trabalho com o banco de dados no docker-compose.yml principal. Vamos adicionar o banco de dados ao arquivo docker-compose:version: '3.1'
services:
jrtb-bot:
depends_on:
- jrtb-db
build:
context: .
environment:
BOT_NAME: ${BOT_NAME}
BOT_TOKEN: ${BOT_TOKEN}
BOT_DB_USERNAME: ${BOT_DB_USERNAME}
BOT_DB_PASSWORD: ${BOT_DB_PASSWORD}
restart: always
jrtb-db:
image: mysql:5.7
restart: always
environment:
MYSQL_USER: ${BOT_DB_USERNAME}
MYSQL_PASSWORD: ${BOT_DB_PASSWORD}
MYSQL_DATABASE: 'jrtb_db'
MYSQL_ROOT_PASSWORD: 'root'
ports:
- '3306:3306'
expose:
- '3306'
Também adicionei esta linha ao nosso aplicativo:
depends_on:
- jrtb-db
Isso significa que esperamos o banco de dados iniciar antes de iniciar a aplicação. A seguir, você pode notar a adição de mais duas variáveis que precisamos para trabalhar com o banco de dados:
${BOT_DB_USERNAME}
${BOT_DB_PASSWORD}
Iremos colocá-los no docker-compose da mesma forma que no bot do telegrama - por meio de variáveis de ambiente. Fiz isso para que tivéssemos apenas um local onde definimos os valores do nome de usuário do banco de dados e sua senha. Nós os passamos para a imagem docker do nosso aplicativo e para o contêiner docker do nosso banco de dados. Em seguida, precisamos atualizar o Dockerfile para ensinar nosso SpringBoot a aceitar variáveis para o banco de dados.
FROM adoptopenjdk/openjdk11:ubi
ARG JAR_FILE=target/*.jar
ENV BOT_NAME=test.javarush_community_bot
ENV BOT_TOKEN=1375780501:AAE4A6Rz0BSnIGzeu896OjQnjzsMEG6_uso
ENV BOT_DB_USERNAME=jrtb_db_user
ENV BOT_DB_PASSWORD=jrtb_db_password
COPY ${JAR_FILE} app.jar
ENTRYPOINT ["java","-Dspring.datasource.password=${BOT_DB_PASSWORD}", "-Dbot.username=${BOT_NAME}", "-Dbot.token=${BOT_TOKEN}", "-Dspring.datasource.username=${BOT_DB_USERNAME}", "-jar", "app.jar"]
Agora adicionamos variáveis de banco de dados ao Dockerfile:
ENV BOT_DB_USERNAME=jrtb_db_user
ENV BOT_DB_PASSWORD=jrtb_db_password
Os valores das variáveis serão diferentes. Aqueles que passaremos para o Dockerfile, entretanto, exigem valores padrão, então inseri alguns. Expandimos a última linha com dois elementos, com a ajuda dos quais passaremos o nome de usuário e a senha do banco de dados para iniciar o aplicativo:
"-Dspring.datasource.password=${BOT_DB_PASSWORD}", "-Dbot.username=${BOT_NAME}"
A última linha do Dockerfile (que começa com ENTRYPOINT) deve estar sem quebra. Se você fizer uma transferência, este código não funcionará. A última etapa é atualizar o arquivo start.sh para passar variáveis ao banco de dados.
#!/bin/bash
# Pull new changes
git pull
# Prepare Jar
mvn clean
mvn package
# Ensure, that docker-compose stopped
docker-compose stop
# Add environment variables
export BOT_NAME=$1
export BOT_TOKEN=$2
export BOT_DB_USERNAME='prod_jrtb_db_user'
export BOT_DB_PASSWORD='Pap9L9VVUkNYj99GCUCC3mJkb'
# Start new deployment
docker-compose up --build -d
Já sabemos como adicionar variáveis de ambiente antes de executar o docker-compose. Para fazer isso, basta executar export var_name=var_value.. Portanto, adicionamos apenas duas linhas:
export BOT_DB_USERNAME='prod_jrtb_db_user'
export BOT_DB_PASSWORD='Pap9L9VVUkNYj99GCUCC3mJkb'
É aqui que definimos o nome de usuário e a senha do banco de dados. Claro, seria possível passar essas variáveis ao executar o script bash, como fazemos para o nome e token do bot. Mas me parece que isso é desnecessário. Para realmente acessar o banco de dados, você precisa saber o IP do servidor no qual o banco de dados será implantado e estar na lista de endereços IP permitidos para a solicitação. Quanto a mim, isso já é suficiente. A base foi lançada: agora você pode fazer coisas que são mais compreensíveis para um desenvolvedor - escrever código. Antes disso, estávamos fazendo o que os engenheiros de DevOps fazem: configurando o ambiente.
Adicionando uma camada de repositório
Normalmente, um aplicativo possui três camadas:- Os controladores são os pontos de entrada no aplicativo.
- Os serviços são onde a lógica de negócios funciona. Já temos isto parcialmente: SendMessageService é um representante explícito da lógica de negócios.
- Os repositórios são um local para trabalhar com um banco de dados. No nosso caso, este é um bot de telegrama.
- Não teremos que trabalhar com JDBC: trabalharemos diretamente com abstrações superiores. Ou seja, armazene POJOs que correspondem às tabelas do banco de dados. Chamaremos essas classes de entidade , como são oficialmente chamadas na API Java Persistence (este é um conjunto comum de interfaces para trabalhar com um banco de dados por meio de um ORM, ou seja, uma abstração sobre o trabalho com JDBC). Teremos uma classe de entidade que salvaremos no banco de dados e serão gravadas exatamente na tabela que precisamos. Receberemos os mesmos objetos ao pesquisar no banco de dados.
- Spring Data oferece o uso de seu conjunto de interfaces: JpaRepository , CrudRepository , etc... Existem outras interfaces: uma lista completa pode ser encontrada aqui . A beleza é que você pode usar seus métodos sem implementá-los (!). Além disso, existe um determinado modelo com o qual você pode escrever novos métodos na interface, e eles serão implementados automaticamente.
- Spring simplifica nosso desenvolvimento tanto quanto pode. Para fazer isso, precisamos criar nossa própria interface e herdar as descritas acima. E para que o Spring saiba que precisa utilizar esta interface, adicione a anotação Repository.
- Se precisarmos escrever um método para trabalhar com um banco de dados que não existe, isso também não será um problema - nós o escreveremos. Vou te mostrar o que e como fazer lá.
package com.github.javarushcommunity.jrtb.repository.entity;
import lombok.Data;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Table;
/**
* Telegram User entity.
*/
@Data
@Entity
@Table(name = "tg_user")
public class TelegramUser {
@Id
@Column(name = "chat_id")
private String chatId;
@Column(name = "active")
private boolean active;
}
Aqui você pode ver que temos todas as anotações do pacote javax.persistence. Estas são anotações comuns usadas para todas as implementações de ORM. Por padrão, Spring Data Jpa usa Hibernate, embora outras implementações possam ser usadas. Aqui está uma lista de anotações que usamos:
- Entidade - indica que se trata de uma entidade para trabalhar com banco de dados;
- Tabela – aqui definimos o nome da tabela;
- Id - a anotação diz qual campo será a Chave Primária da tabela;
- Coluna - determine o nome do campo da tabela.
package com.github.javarushcommunity.jrtb.repository;
import com.github.javarushcommunity.jrtb.repository.entity.TelegramUser;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import java.util.List;
/**
* {@link Repository} for handling with {@link TelegramUser} entity.
*/
@Repository
public interface TelegramUserRepository extends JpaRepository<TelegramUser, String> {
List<TelegramUser> findAllByActiveTrue();
}
Aqui você pode ver como adicionei o método findAllByActiveTrue() , que não implemento em lugar nenhum. Mas isso não o impedirá de trabalhar. Spring Data entenderá que precisa obter todos os registros da tabela tg_user cujo campo ativo = true . Adicionamos um serviço para trabalhar com a entidade TelegramUser (usamos inversão de dependência do SOLID no contexto de que serviços de outras entidades não podem se comunicar diretamente com o repositório de outra entidade - apenas através do serviço dessa entidade). Criamos um serviço TelegramUserService no pacote, que por enquanto terá vários métodos: salvar o usuário, pegar o usuário pelo seu ID e exibir uma lista de usuários ativos. Primeiro criamos a interface TelegramUserService:
package com.github.javarushcommunity.jrtb.service;
import com.github.javarushcommunity.jrtb.repository.entity.TelegramUser;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.Optional;
/**
* {@link Service} for handling {@link TelegramUser} entity.
*/
public interface TelegramUserService {
/**
* Save provided {@link TelegramUser} entity.
*
* @param telegramUser provided telegram user.
*/
void save(TelegramUser telegramUser);
/**
* Retrieve all active {@link TelegramUser}.
*
* @return the collection of the active {@link TelegramUser} objects.
*/
List<TelegramUser> retrieveAllActiveUsers();
/**
* Find {@link TelegramUser} by chatId.
*
* @param chatId provided Chat ID
* @return {@link TelegramUser} with provided chat ID or null otherwise.
*/
Optional<TelegramUser> findByChatId(String chatId);
}
E, de fato, a implementação do TelegramUserServiceImpl:
package com.github.javarushcommunity.jrtb.service;
import com.github.javarushcommunity.jrtb.repository.TelegramUserRepository;
import com.github.javarushcommunity.jrtb.repository.entity.TelegramUser;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.Optional;
/**
* Implementation of {@link TelegramUserService}.
*/
@Service
public class TelegramUserServiceImpl implements TelegramUserService {
private final TelegramUserRepository telegramUserRepository;
@Autowired
public TelegramUserServiceImpl(TelegramUserRepository telegramUserRepository) {
this.telegramUserRepository = telegramUserRepository;
}
@Override
public void save(TelegramUser telegramUser) {
telegramUserRepository.save(telegramUser);
}
@Override
public List<TelegramUser> retrieveAllActiveUsers() {
return telegramUserRepository.findAllByActiveTrue();
}
@Override
public Optional<TelegramUser> findByChatId(String chatId) {
return telegramUserRepository.findById(chatId);
}
}
Deve-se notar aqui que usamos injeção de dependência (introduzimos uma instância de classe) do objeto TelegramuserRepository usando a anotação Autowired e no construtor. Você pode fazer isso para uma variável, mas esta é a abordagem que a equipe do Spring Framework nos recomenda.
Adicionando estatísticas para o bot
Em seguida, você precisa atualizar os comandos /start e /stop. Quando o comando /start é usado, você precisa salvar o novo usuário no banco de dados e configurá-lo para active = true. E quando houver /stop, atualize os dados do usuário: set active = false. Vamos corrigir a classe StartCommand :package com.github.javarushcommunity.jrtb.command;
import com.github.javarushcommunity.jrtb.repository.entity.TelegramUser;
import com.github.javarushcommunity.jrtb.service.SendBotMessageService;
import com.github.javarushcommunity.jrtb.service.TelegramUserService;
import org.telegram.telegrambots.meta.api.objects.Update;
/**
* Start {@link Command}.
*/
public class StartCommand implements Command {
private final SendBotMessageService sendBotMessageService;
private final TelegramUserService telegramUserService;
public final static String START_MESSAGE = "Привет. Я Javarush Telegram Bot. Я помогу тебе быть в курсе последних " +
"статей тех авторов, котрые тебе интересны. Я еще маленький и только учусь.";
public StartCommand(SendBotMessageService sendBotMessageService, TelegramUserService telegramUserService) {
this.sendBotMessageService = sendBotMessageService;
this.telegramUserService = telegramUserService;
}
@Override
public void execute(Update update) {
String chatId = update.getMessage().getChatId().toString();
telegramUserService.findByChatId(chatId).ifPresentOrElse(
user -> {
user.setActive(true);
telegramUserService.save(user);
},
() -> {
TelegramUser telegramUser = new TelegramUser();
telegramUser.setActive(true);
telegramUser.setChatId(chatId);
telegramUserService.save(telegramUser);
});
sendBotMessageService.sendMessage(chatId, START_MESSAGE);
}
}
Aqui também passamos o objeto TelegramuserService para o construtor, com o qual salvaremos o novo usuário. Além disso, usando as delícias do Opcional em Java, a seguinte lógica funciona: se tivermos um usuário no banco de dados, simplesmente o tornamos ativo, caso contrário, criamos um novo ativo. Comando Parar:
package com.github.javarushcommunity.jrtb.command;
import com.github.javarushcommunity.jrtb.repository.entity.TelegramUser;
import com.github.javarushcommunity.jrtb.service.SendBotMessageService;
import com.github.javarushcommunity.jrtb.service.TelegramUserService;
import org.telegram.telegrambots.meta.api.objects.Update;
import java.util.Optional;
/**
* Stop {@link Command}.
*/
public class StopCommand implements Command {
private final SendBotMessageService sendBotMessageService;
private final TelegramUserService telegramUserService;
public static final String STOP_MESSAGE = "Деактивировал все ваши подписки \uD83D\uDE1F.";
public StopCommand(SendBotMessageService sendBotMessageService, TelegramUserService telegramUserService) {
this.sendBotMessageService = sendBotMessageService;
this.telegramUserService = telegramUserService;
}
@Override
public void execute(Update update) {
sendBotMessageService.sendMessage(update.getMessage().getChatId().toString(), STOP_MESSAGE);
telegramUserService.findByChatId(update.getMessage().getChatId().toString())
.ifPresent(it -> {
it.setActive(false);
telegramUserService.save(it);
});
}
}
Passamos TelegramServiceTest para StopCommand da mesma maneira. A lógica adicional é esta: se tivermos um usuário com esse ID de chat, nós o desativamos, ou seja, definimos active = false. Como você pode ver isso com seus próprios olhos? Vamos criar um novo comando /stat, que exibirá as estatísticas do bot. Nesta fase, estas serão estatísticas simples disponíveis para todos os utilizadores. No futuro, iremos limitá-lo e tornar o acesso apenas para administradores. Haverá uma entrada nas estatísticas: o número de usuários de bot ativos. Para fazer isso, adicione o valor STAT("/stat") a CommandName. A seguir, crie a classe StatCommand :
package com.github.javarushcommunity.jrtb.command;
import com.github.javarushcommunity.jrtb.service.SendBotMessageService;
import com.github.javarushcommunity.jrtb.service.TelegramUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.telegram.telegrambots.meta.api.objects.Update;
/**
* Statistics {@link Command}.
*/
public class StatCommand implements Command {
private final TelegramUserService telegramUserService;
private final SendBotMessageService sendBotMessageService;
public final static String STAT_MESSAGE = "Javarush Telegram Bot использует %s человек.";
@Autowired
public StatCommand(SendBotMessageService sendBotMessageService, TelegramUserService telegramUserService) {
this.sendBotMessageService = sendBotMessageService;
this.telegramUserService = telegramUserService;
}
@Override
public void execute(Update update) {
int activeUserCount = telegramUserService.retrieveAllActiveUsers().size();
sendBotMessageService.sendMessage(update.getMessage().getChatId().toString(), String.format(STAT_MESSAGE, activeUserCount));
}
}
Tudo é simples aqui: obtemos uma lista de todos os usuários ativos usando o método retrieveAllActiveUsers e obtemos o tamanho da coleção. Agora também precisamos atualizar as classes ascendentes: CommandContainer e JavarushTelegramBot para que aprendam a transferir o novo serviço que precisamos. CommandContainer:
package com.github.javarushcommunity.jrtb.command;
import com.github.javarushcommunity.jrtb.service.SendBotMessageService;
import com.github.javarushcommunity.jrtb.service.TelegramUserService;
import com.google.common.collect.ImmutableMap;
import static com.github.javarushcommunity.jrtb.command.CommandName.*;
/**
* Container of the {@link Command}s, which are using for handling telegram commands.
*/
public class CommandContainer {
private final ImmutableMap<String, Command> commandMap;
private final Command unknownCommand;
public CommandContainer(SendBotMessageService sendBotMessageService, TelegramUserService telegramUserService) {
commandMap = ImmutableMap.<String, Command>builder()
.put(START.getCommandName(), new StartCommand(sendBotMessageService, telegramUserService))
.put(STOP.getCommandName(), new StopCommand(sendBotMessageService, telegramUserService))
.put(HELP.getCommandName(), new HelpCommand(sendBotMessageService))
.put(NO.getCommandName(), new NoCommand(sendBotMessageService))
.put(STAT.getCommandName(), new StatCommand(sendBotMessageService, telegramUserService))
.build();
unknownCommand = new UnknownCommand(sendBotMessageService);
}
public Command retrieveCommand(String commandIdentifier) {
return commandMap.getOrDefault(commandIdentifier, unknownCommand);
}
}
Aqui adicionamos um novo comando ao mapa e o passamos pelo construtor TelegramUserService. Mas no próprio bot, apenas o construtor mudará:
@Autowired
public JavarushTelegramBot(TelegramUserService telegramUserService) {
this.commandContainer = new CommandContainer(new SendBotMessageServiceImpl(this), telegramUserService);
}
Agora passamos TelegramUserService como argumento, adicionando a anotação Autowired. Isso significa que o receberemos do Contexto do Aplicativo. Também atualizaremos a classe HelpCommand para que um novo comando de estatísticas apareça na descrição.
Teste manual
Vamos iniciar o banco de dados de docker-compose-test.yml e o método principal na classe JavarushTelegramBotApplication. A seguir, escrevemos um conjunto de comandos:- /stat - esperamos que se o banco de dados estiver vazio, não haverá nenhuma pessoa usando este bot;
- /start – inicia o bot;
- /stat - agora esperamos que o bot seja usado por 1 pessoa;
- /stop - para o bot;
- /stat - esperamos que novamente haja 0 pessoas usando-o.
Escrevemos e atualizamos testes
Como alteramos os construtores, precisaremos atualizar também as classes de teste. Na classe AbstractCommandTest , precisamos adicionar mais um campo - a classe telegramUserService , necessária para três comandos:protected TelegramUserService telegramUserService = Mockito.mock(TelegramUserService.class);
A seguir, vamos atualizar o método init() em CommandContainer :
@BeforeEach
public void init() {
SendBotMessageService sendBotMessageService = Mockito.mock(SendBotMessageService.class);
TelegramUserService telegramUserService = Mockito.mock(TelegramUserService.class);
commandContainer = new CommandContainer(sendBotMessageService, telegramUserService);
}
No StartCommand você precisa atualizar o método getCommand() :
@Override
Command getCommand() {
return new StartCommand(sendBotMessageService, telegramUserService);
}
Também em StopCommand:
@Override
Command getCommand() {
return new StopCommand(sendBotMessageService, telegramUserService);
}
A seguir, vamos dar uma olhada nos novos testes. Vamos criar um teste típico para StatCommand :
package com.github.javarushcommunity.jrtb.command;
import static com.github.javarushcommunity.jrtb.command.CommandName.STAT;
import static com.github.javarushcommunity.jrtb.command.StatCommand.STAT_MESSAGE;
public class StatCommandTest extends AbstractCommandTest {
@Override
String getCommandName() {
return STAT.getCommandName();
}
@Override
String getCommandMessage() {
return String.format(STAT_MESSAGE, 0);
}
@Override
Command getCommand() {
return new StatCommand(sendBotMessageService, telegramUserService);
}
}
Isto é simples. Agora vamos falar sobre como testaremos o trabalho com o banco de dados. Tudo o que fizemos antes foram testes unitários. Um teste de integração testa a integração entre várias partes de um aplicativo. Por exemplo, aplicativos e bancos de dados. Aqui tudo será mais complicado, pois para testar precisamos de um banco de dados implantado. Portanto, quando executamos nossos testes localmente, devemos ter o banco de dados rodando em docker-compose-test.yml. Para executar este teste, você precisa executar todo o aplicativo SpringBoot. A classe de teste possui uma anotação SpringBootTest que iniciará o aplicativo. Mas essa abordagem não funcionará para nós, porque quando o aplicativo for iniciado, o bot do telegrama também será iniciado. Mas há uma contradição aqui. Os testes serão executados localmente em nossa máquina e publicamente por meio do GitHub Actions. Para que os testes passem com o lançamento de toda a aplicação, devemos executá-los com dados válidos no bot do telegrama: ou seja, pelo seu nome e token... Portanto, temos duas opções:
- Portanto, torne público o nome e o token do bot e torça para que tudo fique bem, ninguém vai usá-lo e interferir conosco.
- Pense em outra maneira.
@Sql(scripts = {"/sql/clearDbs.sql", "/sql/telegram_users.sql"})
Para nós, eles estarão localizados ao longo do caminho ./src/test/resources/ + o caminho especificado na anotação. Esta é a aparência deles:
clearDbs.sql:
DELETE FROM tg_user;
telegram_users.sql:
INSERT INTO tg_user VALUES ("123456789", 1);
INSERT INTO tg_user VALUES ("123456788", 1);
INSERT INTO tg_user VALUES ("123456787", 1);
INSERT INTO tg_user VALUES ("123456786", 1);
INSERT INTO tg_user VALUES ("123456785", 1);
INSERT INTO tg_user VALUES ("123456784", 0);
INSERT INTO tg_user VALUES ("123456782", 0);
INSERT INTO tg_user VALUES ("123456781", 0);
Esta é a aparência do nosso teste TelegramUserRepositoryIT (como você pode ver, o nome do teste de integração será diferente - adicionamos TI, não Teste):
package com.github.javarushcommunity.jrtb.repository;
import com.github.javarushcommunity.jrtb.repository.entity.TelegramUser;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase;
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.jdbc.Sql;
import java.util.List;
import java.util.Optional;
import static org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase.Replace.NONE;
/**
* Integration-level testing for {@link TelegramUserRepository}.
*/
@ActiveProfiles("test")
@DataJpaTest
@AutoConfigureTestDatabase(replace = NONE)
public class TelegramUserRepositoryIT {
@Autowired
private TelegramUserRepository telegramUserRepository;
@Sql(scripts = {"/sql/clearDbs.sql", "/sql/telegram_users.sql"})
@Test
public void shouldProperlyFindAllActiveUsers() {
//when
List<TelegramUser> users = telegramUserRepository.findAllByActiveTrue();
//then
Assertions.assertEquals(5, users.size());
}
@Sql(scripts = {"/sql/clearDbs.sql"})
@Test
public void shouldProperlySaveTelegramUser() {
//given
TelegramUser telegramUser = new TelegramUser();
telegramUser.setChatId("1234567890");
telegramUser.setActive(false);
telegramUserRepository.save(telegramUser);
//when
Optional<TelegramUser> saved = telegramUserRepository.findById(telegramUser.getChatId());
//then
Assertions.assertTrue(saved.isPresent());
Assertions.assertEquals(telegramUser, saved.get());
}
}
Escrevemos os testes, mas surge a pergunta: o que acontecerá com o lançamento do nosso processo de CI no GitHub? Não terá um banco de dados. Por enquanto, haverá apenas uma construção vermelha. Para isso, temos ações do GitHub, nas quais podemos configurar o lançamento do nosso build. Antes de executar os testes, é necessário adicionar uma inicialização de banco de dados com as configurações necessárias. Acontece que não há muitos exemplos na Internet, então aconselho você a salvar isso em algum lugar. Vamos atualizar o arquivo .github/workflows/maven.yml:
# This workflow will build a Java project with Maven
# For more information see: https://help.github.com/actions/language-and-framework-guides/building-and-testing-java-with-maven
name: Java CI with Maven
on:
push:
branches: [ main ]
pull_request:
branches: [ main ]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Set up MySQL
uses: mirromutth/mysql-action@v1.1
with:
mysql version: '5.7'
mysql database: 'dev_jrtb_db'
mysql root password: 'root'
mysql user: 'dev_jrtb_db_user'
mysql password: 'dev_jrtb_db_password'
- name: Set up JDK 1.11
uses: actions/setup-java@v1
with:
java-version: 1.11
- name: Build with Maven
run: mvn -B package --file pom.xml
Agora há um novo bloco Configurar MySQL . Nele adicionamos MySQL ao nosso processo de CI, definindo simultaneamente as variáveis que necessitamos. Agora adicionamos tudo o que queríamos. A última etapa é empurrar as mudanças e ver se a construção vai passar e ficar verde.
Atualizando a documentação
Vamos atualizar a versão do projeto de 0.3.0-SNAPSHOT para 0.4.0-SNAPSHOT em pom.xml e também adicionar em RELEASE_NOTES:## 0.4.0-SNAPSHOT
* JRTB-1: added repository layer.
Depois de tudo isso, criamos uma solicitação de commit, push e pull. E o mais importante, nossa construção é verde!
Links Úteis:
- Repositório do nosso bot de telegrama
- Pull request com todas as alterações descritas no artigo
- Artigo SpringBoot + Flyway
- Imagem MySQL do DockerHub
- Médio: como criar uma instância MySql com Docker Compose
- Habr: Spring Data Jpa
- Meu canal de telegrama
GO TO FULL VERSION