Integração contínua (CI) no GitHub Actions em projetos Java
Produzir software de qualidade é uma tarefa difícil pois exige constante investigação e manutenção para mantê-lo funcionando corretamente durante o passar do tempo. A integração contínua é uma técnica de desenvolvimento que busca acelerar a detecção de bugs e problemas de integração, utilizando um repositório de código único para mesclar o código fonte desenvolvido por cada programador da equipe e executando o build do software a cada push.
Para facilitar a automação de todos os fluxos de trabalho de software é que surgiu o GitHub Actions, através dele podemos criar, testar e implantar nosso software sem maiores dificuldades.
O ecossistema do Java é muito rico e conta com diversas ferramentas para que um código de qualidade seja produzido, vamos utilizar algumas dessas ferramentas para nos fornecer um feedback sobre a qualidade do nosso código e até mesmo quebrando nosso build em caso de falhas em algumas etapas.
Ferramentas Utilizadas
-
Apache Maven
Apache Maven é uma ferramenta de gerenciamento e compreensão de projetos de software. Com base no conceito de modelo de objeto de projeto (POM), o Maven pode gerenciar a construção, o relatório e a documentação de um projeto a partir de uma informação central.
-
JaCoCo
JaCoCo é uma biblioteca de cobertura de código Java gratuita distribuída sob a Licença Pública Eclipse.
-
SonarQube
O SonarQube é uma plataforma de código aberto desenvolvida pela SonarSource para inspeção contínua da qualidade do código, para executar revisões automáticas com análise estática do código para detectar bugs, odores de código e vulnerabilidades de segurança.
-
DockerHub
Docker Hub é o maior repositório do mundo de imagens de contêiner com uma variedade de fontes de conteúdo, incluindo desenvolvedores de comunidades de contêineres, projetos de código aberto e fornecedores de software independentes (ISV) construindo e distribuindo seu código em contêineres. Os usuários têm acesso a repositórios públicos gratuitos para armazenamento e compartilhamento de imagens ou podem escolher um plano de assinatura para repositórios privados.
-
JUnit
JUnit é uma estrutura simples para escrever testes repetíveis. É uma instância da arquitetura xUnit para estruturas de teste de unidade.
Integrações
Algumas ferramentas mencionadas acima estão hospedadas na nuvem, portanto precisaremos criar uma conta de acesso e gerar um token para que seja possível realizar a integração do GitHub com as ferramentas.
Configuração do Token de acesso ao DockerHub
O artefato gerado pela nossa aplicação será uma imagem docker e a mesma será armazenada no repositório de imagens do DockerHub.
Faça um cadastro no DockerHub e execute os passos abaixo para gerar um token de acesso.
Configuração do Token de acesso ao SonarCloud
Utilizaremos o SonarCloud para realizar analise estática dos nossos códigos fontes.
Faça um cadastro no SonarCloud e execute os passos abaixo para gerar um token de acesso.
Armazenando os Tokens dos serviços no GitHub
Configurando o Projeto Java
Vamos adicionar os seguintes plugins no Maven que são responsáveis por gerar as estatísticas de cobertura do código fonte, realizar a integração com o SonarQube e também gerar a nossa imagem Docker.
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>0.8.6</version>
<executions>
<execution>
<id>prepare-agent</id>
<goals>
<goal>prepare-agent</goal>
</goals>
</execution>
<execution>
<id>report</id>
<phase>prepare-package</phase>
<goals>
<goal>report</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.sonarsource.scanner.maven</groupId>
<artifactId>sonar-maven-plugin</artifactId>
<version>3.7.0.1746</version>
<executions>
<execution>
<phase>verify</phase>
<goals>
<goal>sonar</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>com.google.cloud.tools</groupId>
<artifactId>jib-maven-plugin</artifactId>
<version>2.6.0</version>
<configuration>
<from>
<image>openjdk:15-jdk-slim-buster</image>
</from>
<to>
<image>gasparbarancelli/blog:${project.version}</image>
<auth>
<username>
${env.DOCKERHUB_USERNAME}
</username>
<password>
${env.DOCKERHUB_TOKEN}
</password>
</auth>
</to>
<container>
<jvmFlags>
<jvmFlag>-Xms256m</jvmFlag>
<jvmFlag>-Xmx512m</jvmFlag>
</jvmFlags>
<mainClass>io.github.gasparbarancelli.blog.BlogApplication</mainClass>
</container>
</configuration>
</plugin>
Configurando o GitHub Actions
Agora o passo mais importante, acessar o nosso repositório no GitHub e configurar uma nova Action.
A nossa Action vai conter os 4 seguintes jobs:
-
Compilar o código fonte
-
Executar os testes
-
Gerar as estatísticas de cobertura de testes e também realizar a integração com o SonarCloud para analise estática do código fonte
-
Realizar o build da aplicação e criar uma imagem Docker publicando a mesma no DockerHub
Segue o código fonte da Action contendo os jobs mencionados acima, observe o uso das Secrets que adicionamos no GitHUb, em nenhum momento passamos os valores dos tokens.
name: Java CI with Maven
on:
push:
branches: [ master ]
pull_request:
branches: [ master ]
jobs:
compile:
runs-on: ubuntu-latest
name: Compile
steps:
- uses: actions/checkout@v2
- name: Set up JDK 15
uses: actions/setup-java@v1
with:
java-version: 15
- name: Compile code
run: mvn -B compile
test:
runs-on: ubuntu-latest
name: Tests
needs: compile
steps:
- uses: actions/checkout@v2
- name: Set up JDK 15
uses: actions/setup-java@v1
with:
java-version: 15
- name: Run unit tests
run: mvn -B test
analysis:
runs-on: ubuntu-latest
name: Analysis and Coverage
needs: test
steps:
- uses: actions/checkout@v2
- name: Set up JDK 15
uses: actions/setup-java@v1
with:
java-version: 15
- name: Integrate with sonarcloud
run: mvn -B org.jacoco:jacoco-maven-plugin:prepare-agent verify sonar:sonar -Dsonar.coverage.jacoco.xmlReportPaths=target/site/jacoco/jacoco.xml -Dsonar.projectKey=gasparbarancelli_blog -Dsonar.organization=gasparbarancelli -Dsonar.host.url=https://sonarcloud.io -Dsonar.login=${{secrets.SONARCLOUD_TOKEN}}
env:
GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}}
build:
runs-on: ubuntu-latest
name: Build and Deliver
needs: analysis
steps:
- uses: actions/checkout@v2
- name: Set up JDK 15
uses: actions/setup-java@v1
with:
java-version: 15
- name: Build Project, create docker image and send image to dockerhub
env:
DOCKERHUB_USERNAME: ${{secrets.DOCKERHUB_USERNAME}}
DOCKERHUB_TOKEN: ${{secrets.DOCKERHUB_TOKEN}}
run: mvn -B package jib:build -DskipTests
Resultado Final
Ao executarmos um push na Branch master o Action criado acima será executado e os seguintes resultados são esperados.