Skip to main content

Leonardo Murça

Como fazer o deploy de aplicativos React usando Github Actions + Rsync

Publicado em 15 de outubro, 2022

Última atualização 24 de março, 2024

Gato com olhos amarelos

Fig. 1 - Gato com olhos amarelos.

Código fonte e aplicação em produção utilizado nesse post:

TL;DR

  • Crie um usuário em seu servidor para fazer o deploy de sua aplicação:
$ useradd -s /bin/bash -d /home/tutorials -m tutorials
$ su tutorials
  • Crie um diretório para copiar seus arquivos de produção:
$ mkdir rsync-deploy-react-app
  • Add your private tutorials’s user ssh key to your Action Secrets.

  • Adicione a chave ssh privada do usuário tutorials aos seus Action Secrets.

  • Crie uma nova action no github para fazer o deploy da sua aplicação e cole o código abaixo:

# .github/workflows/deploy.yml
name: Deploy 

on:
  push:
    branches: [ "main" ]

jobs:
  build-and-deploy:

    runs-on: ubuntu-latest

    env:
      SSH_KEY: ${{secrets.SSH_KEY}}

    steps:
    - uses: actions/checkout@v3
    - name: Use Node.js 16
      uses: actions/setup-node@v3
      with:
        node-version: 16
        cache: 'npm'
    - run: mkdir ~/.ssh
    - run: 'echo "$SSH_KEY" >> ~/.ssh/id_rsa_tutorials'
    - run: chmod 400 ~/.ssh/id_rsa_tutorials
    - run: echo -e "Host tutorials\n\tUser tutorials\n\tHostname 45.76.5.44\n\tIdentityFile ~/.ssh/id_rsa_tutorials\n\tStrictHostKeyChecking No" >> ~/.ssh/config
    - run: npm install
    - run: npm run build
    - run: rsync -avz --progress build/ tutorials:/home/tutorials/rsync-deploy-react-app --delete

Preste atenção aos Pré-requisitos. É isso! Altere algum código, envie-o para o branch principal e veja a mágica acontecendo!

Motivação

Estive trabalhando em minha tese de bacharelado em sistemas de informação, que é um aplicativo React simples, e estava lutando para encontrar uma maneira simples, segura e rápida de implantá-lo em meu próprio [VPS](https:/ /en.wikipedia.org/wiki/Virtual_private_server). No entanto, a maior parte do conteúdo que encontrei na internet envolve soluções fantasiosas e complexas como docker e [Kubernetes](https://kubernetes.io /) ou soluções bloqueadas pelo fornecedor como Heroku e Vercel.

Reconheço que essas ferramentas têm suas vantagens, mas descobri que, para projetos de pequeno e médio porte, elas exigem mais esforço do que vale a pena manter. Tudo o que preciso fazer é criar o código e copiar os arquivos criados para o servidor. Então, rsync chegou ao meu conhecimento.

Pré-requisitos

  • Uma aplicação React existente;
  • Um servidor ou um serviço de hospedagem para fazer o deploy de sua aplicação;
  • Seu próprio domínio registrado;
  • NGINX instalado em seu servidor;
  • Algum conhecimento sobre como registrar um domínio e criar um servidor em alguma plataforma de hospedagem (adicionarei artigos sobre isso no futuro).

Aplicativo de demonstração a ser implantado

Criei um aplicativo de demonstração para fazer o deploy em meu servidor. Seu código-fonte está disponível em rsync-deploy-react-app.

Screenshot da aplicação escrita em React

Fig. 2 - Screenshot da aplicação escrita em React.

Setup do servidor

Para este tutorial, usarei meu domínio leomurca.xyz configurando um subdomínio para ele. Para ser mais específico, vou apontar tutorial.leomurca.xyz para o IP do meu VPS: 45.76.5.44.

Logar no servidor via SSH

$ ssh root@45.76.5.44

Crie um usuário para gerenciar sua aplicação

Para evitar que nosso pipeline tenha acesso root ao seu servidor, criarei um usuário para gerenciar deploys chamado tutorials:

$ useradd -s /bin/bash -d /home/tutorials -m tutorials

Depois disso, logue como o usuário criado:

$ su tutorials

Como criei o usuário chamado tutorials, este usuário irá hospedar vários tutoriais, então para isolarmos nossa aplicação, crie uma pasta específica para abrigar nossos arquivos de build:

$ mkdir rsync-deploy-react-app

Setup da Github Action

Agora vamos criar o .github/workflows/deploy.yml para definir as etapas do pipeline. Primeiro, adicione uma label para o fluxo de trabalho e quando ele deve ser acionado:

name: Deploy

on:
  push:
    branches: [ "main" ]

Acima, o workflow será acionado toda vez que um novo código for pushed ou merged à branch main (isso também acontece para Pull Requests mergeadas à branch principal).

Em seguida, descreva um novo workflow que vamos nomear como build-and-deploy para lidar com todas as etapas para fazer o build e o deploy de nossa aplicação:

jobs:
  build-and-deploy:

    runs-on: ubuntu-latest

    env:
      SSH_KEY: ${{secrets.SSH_KEY}}
    
    ...

A SSH_KEY: ${{secrets.SSH_KEY}} faz referência a Github Secret que é permitido fazer login em nosso servidor. É importante mencionar que devemos adicionar o secrete às configurações do nosso repositório.

Além disso, para evitar problemas ao autenticar em seu servidor usando ssh, use chaves geradas por RSA para autenticar em vez de chaves Ed25519. Para mais detalhes sobre isso, verifique este documento sobre como gerar uma nova chave SSH.

Depois, vamos começar a definir os passos reais a serem executados:

    ...
    steps:
    - uses: actions/checkout@v3
    - name: Use Node.js 16
      uses: actions/setup-node@v3
      with:
        node-version: 16
        cache: 'npm'
    ...

Essas primeiras etapas basicamente definirão qual versão do NodeJS será usada em nosso pipeline.

E agora, um passo muito importante é adicionar os comandos que realmente serão executados em nosso workflow, preste atenção neles:

    ...
    - run: mkdir ~/.ssh
    - run: 'echo "$SSH_KEY" >> ~/.ssh/id_rsa_tutorials'
    - run: chmod 400 ~/.ssh/id_rsa_tutorials
    - run: echo -e "Host tutorials\n\tUser tutorials\n\tHostname 45.76.5.44\n\tIdentityFile ~/.ssh/id_rsa_tutorials\n\tStrictHostKeyChecking No" >> ~/.ssh/config
    - run: npm install
    - run: npm run build
    ...

As configurações acima nós basicamente:

  • Copiamos a SSH_KEY para um arquivo;
  • Criamos uma configuração ssh para nosso servidor usando a chave criada anteriormente;
  • Baixamos as dependências do aplicativo e gere os arquivos de compilação para serem copiados para o nosso servidor.

Para tornar as configurações do ssh mais legíveis, verifique o trecho de código abaixo:

Host tutorials
  User tutorials
  Hostname 45.76.5.44
  IdentityFile  ~/.ssh/id_rsa_tutorials
  StrictHostKeyChecking No

Usando rsync para fazer o deploy no servidor

E, finalmente, adicione o comando rsync para sincronizar os arquivos da pasta build/ para o nosso servidor:

...
- run: rsync -avz --progress build/ tutorials:/home/tutorials/rsync-deploy-react-app --delete
...

O significado de cada flag utilizada são:

  • -a: É uma maneira rápida de dizer que você quer recursão e quer preservar quase tudo (com -H sendo uma omissão notável);
  • -v (-verbose): Esta opção aumenta a quantidade de informações que o daemon registra durante sua fase de inicialização.
  • -z (-compress): comprime os dados do arquivo à medida que são enviados para a máquina de destino, o que reduz a quantidade de dados sendo transmitidos – algo que é útil em uma conexão lenta.
  • --progress: Esta opção diz ao rsync para imprimir informações mostrando o progresso da transferência. Isso dá a um usuário entediado algo para assistir.
  • --delete: Diz ao rsync para excluir arquivos estranhos do lado receptor (aqueles que não estão no lado remetente), mas apenas para os diretórios que estão sendo sincronizados.

Para obter mais detalhes sobre todas as opções do rsync, consulte sua man page.

Arquivo completo .github/workflows/deploy.yml

name: Deploy 

on:
  push:
    branches: [ "main" ]

jobs:
  build-and-deploy:

    runs-on: ubuntu-latest

    env:
      SSH_KEY: ${{secrets.SSH_KEY}}

    steps:
    - uses: actions/checkout@v3
    - name: Use Node.js 16
      uses: actions/setup-node@v3
      with:
        node-version: 16
        cache: 'npm'
    - run: mkdir ~/.ssh
    - run: 'echo "$SSH_KEY" >> ~/.ssh/id_rsa_tutorials'
    - run: chmod 400 ~/.ssh/id_rsa_tutorials
    - run: echo -e "Host tutorials\n\tUser tutorials\n\tHostname 45.76.5.44\n\tIdentityFile ~/.ssh/id_rsa_tutorials\n\tStrictHostKeyChecking No" >> ~/.ssh/config
    - run: npm install
    - run: npm run build
    - run: rsync -avz --progress build/ tutorials:/home/tutorials/rsync-deploy-react-app --delete

É isso! Altere algum código, envie-o para o branch principal e veja a mágica acontecendo!

Captura de tela da action no Github

Fig. 3 - Captura de tela da action no Github.

Além disso, se você quiser obter mais detalhes sobre as etapas da ação, verifique as ações executadas durante este artigo.

Simples, rápido e seguro, esses são os principais benefícios de usar o fluxo de trabalho mencionado neste tutorial. É realmente um alívio ter esse tipo de ferramenta no meio de tantas soluções inchadas.

Se você tiver alguma dúvida ou assunto para falar, por favor, fale comigo!