Workflow do GitHub Actions para deploy de aplicação Java

Veja um workflow do GitHub Actions para deploy de aplicação Java em máquina virtual utilizando Maven e Docker.

Por Gabriel Luciano

Criado em 08 de outubro de 2024 às 22:48

Imagem do post

Há um tempo atrás tive a necessidade de implementar um workflow do GitHub Actions para o deploy de uma aplicação Spring Boot para uma máquina virtual utilizando Docker.

Desenvolvi o workflow abaixo que contém os seguintes passos:

  • Execução de testes unitários e de integração (o workflow falha caso algum teste termine com exit code diferente de zero)
  • Build e push da imagem do Docker para o Docker Hub (importante realizar o build do jar a partir do Dockerfile)
  • Transferência do compose file, arquivos de configuração e scripts SQL para o servidor utilizando SSH.
  • Remoção dos containers em execução e deploy dos novos containers.

O arquivo faz uso de GitHub Secrets para garantir a segurança dos tokens e chaves e outras informações sensíveis.

name: Java Test and Deploy CI

on:
  push:
    branches: ["main"]
  workflow_dispatch:

env:
  SSH_PRIVATE_KEY: ${{ secrets.SSH_PRIVATE_KEY }}
  SSH_USER: ${{ secrets.SSH_USER }}
  SSH_HOST: ${{ secrets.SSH_HOST }}

jobs:
  tests:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Set up JDK 21
        uses: actions/setup-java@v4
        with:
          java-version: "21"
          distribution: "temurin"
          cache: maven

      - name: Run unit tests
        run: mvn -B test

      - name: Run integration tests
        run: mvn test -B -P integration-tests

  build:
    runs-on: ubuntu-latest
    needs: tests
    steps:
      - name: Login to Docker Hub
        uses: docker/login-action@v3
        with:
          username: ${{ secrets.DOCKERHUB_USERNAME }}
          password: ${{ secrets.DOCKERHUB_TOKEN }}

      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v3

      - name: Build and push
        uses: docker/build-push-action@v6
        with:
          push: true
          tags: ${{ secrets.DOCKERHUB_USERNAME }}/app-name:latest

  deploy:
    runs-on: ubuntu-latest
    needs: build
    steps:
      - uses: actions/checkout@v4

      - name: Deploy project to the server
        run: |
          eval "$(ssh-agent -s)" && \
          echo "$SSH_PRIVATE_KEY" | ssh-add - && \
          rsync -az --delete-after -e "ssh -o StrictHostKeyChecking=no" docker-compose.prod.yml \
              *.sql *.conf "$SSH_USER@$SSH_HOST:/app/api/" && \
          ssh -o StrictHostKeyChecking=no "$SSH_USER@$SSH_HOST" '\
              cd "/app/api" && \
              docker compose -f docker-compose.prod.yml down && \
              docker compose -f docker-compose.prod.yml pull && \
              docker compose -f docker-compose.prod.yml up -d'

Talvez a parte mais complexa do script seja o comando SSH para envio dos arquivos para a máquina virtual. Vamos entender os passos:

  • eval "$(ssh-agent -s)" && echo "$SSH_PRIVATE_KEY" | ssh-add - - inicia o SSH Agent e adiciona a chave SSH no agent
  • rsync -az --delete-after -e "ssh -o StrictHostKeyChecking=no" docker-compose.prod.yml *.sql *.conf "$SSH_USER@$SSH_HOST:/app/api/" - utiliza o comando rsync (presente na maioria das distribuições Linux) para transferir os arquivos do repositório local para a máquina virtual
  • ssh -o StrictHostKeyChecking=no "$SSH_USER@$SSH_HOST" 'cd "/app/api" && docker compose -f docker-compose.prod.yml down && docker compose -f docker-compose.prod.yml pull && docker compose -f docker-compose.prod.yml up -d' - através de uma conexão SSH, faz o encerramento e remove os containers atuais, realizando o pull das imagens na sequência e subindo os containers novamente.

Concluindo

Com esse simples workflow, é possível automatizar todo o processo de testes automatizados e deploy da aplicação. O workflow pode ser facilmente customizado para outros projetos ou mesmo para outras linguagens. Espero que seja útil para você!