CI/CD do zero: GitHub Actions pra projetos Node.js e React

CI/CD do zero: GitHub Actions para projetos Node.js e React

Automatizar o processo de integração e entrega contínua (CI/CD) é uma prática essencial no desenvolvimento moderno de software. No entanto, para muitos, a configuração inicial de um pipeline pode parecer uma tarefa complicada. O que se pode fazer para simplificar essa jornada? Aqui, vou mostrar como configurar um workflow básico no GitHub Actions para projetos Node.js e React, garantindo que suas aplicações estejam sempre prontas para serem entregues de forma eficiente e confiável.

Workflow básico

O primeiro passo para implementar CI/CD com GitHub Actions é criar um arquivo de workflow. Este arquivo, geralmente localizado na pasta .github/workflows, define as etapas que o GitHub deve seguir a cada push ou pull request.

Vamos criar um exemplo básico para um projeto Node.js. Aqui está um exemplo de um arquivo de workflow chamado ci.yml:

name: CI

on:
  push:
    branches:
      - main
  pull_request:
    branches:
      - main

jobs:
  build:
    runs-on: ubuntu-latest

    steps:
    - name: Checkout code
      uses: actions/checkout@v2

    - name: Setup Node.js
      uses: actions/setup-node@v2
      with:
        node-version: '14'

    - name: Install dependencies
      run: npm install

    - name: Run tests
      run: npm test

Neste exemplo, o workflow é acionado em qualquer push ou pull request para o branch main. O job build é executado em um ambiente Ubuntu, onde as etapas incluem fazer checkout do código, configurar a versão do Node.js, instalar as dependências do projeto e executar os testes.

Matriz de versões

Um recurso poderoso do GitHub Actions é a capacidade de criar matrizes de versões. Isso permite que você teste seu código em múltiplas versões do Node.js simultaneamente. Aqui está como você pode modificar o workflow para incluir uma matriz:

jobs:
  build:
    runs-on: ubuntu-latest

    strategy:
      matrix:
        node-version: [12, 14, 16]

    steps:
    - name: Checkout code
      uses: actions/checkout@v2

    - name: Setup Node.js
      uses: actions/setup-node@v2
      with:
        node-version: ${{ matrix.node-version }}

    - name: Install dependencies
      run: npm install

    - name: Run tests
      run: npm test

Com essa configuração, o GitHub Actions irá executar os testes para cada versão especificada na matriz. Isso é crucial para garantir que seu aplicativo funcione corretamente em diferentes ambientes.

Cache de dependências

Um dos aspectos que pode melhorar significativamente a eficiência do seu pipeline é o cache de dependências. Ao armazenar em cache as dependências instaladas, você pode reduzir o tempo de execução do seu workflow. Aqui está um exemplo de como implementar isso:

    steps:
    - name: Checkout code
      uses: actions/checkout@v2

    - name: Cache Node.js modules
      uses: actions/cache@v2
      with:
        path: ~/.npm
        key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
        restore-keys: |
          ${{ runner.os }}-node-

    - name: Setup Node.js
      uses: actions/setup-node@v2
      with:
        node-version: ${{ matrix.node-version }}

    - name: Install dependencies
      run: npm install

Nesta configuração, utilizamos a ação actions/cache para armazenar o diretório ~/.npm, que contém as dependências instaladas. O cache é identificado por uma chave gerada com base no hash do arquivo package-lock.json, garantindo que, sempre que houver uma alteração nas dependências, o cache será invalidado e atualizado.

Testes + lint

Garantir a qualidade do código é fundamental. Integrar testes automatizados e linting no seu pipeline CI/CD ajuda a manter os padrões de qualidade. Vamos adicionar essas etapas ao nosso workflow:

    - name: Run lint
      run: npm run lint

    - name: Run tests
      run: npm test

Certifique-se de que você tenha scripts correspondentes no seu package.json. Por exemplo:

{
  "scripts": {
    "lint": "eslint .",
    "test": "jest"
  }
}

Com isso, cada vez que o workflow for executado, seu código será verificado quanto a problemas de estilo e os testes automatizados serão realizados.

Deploy automático

Depois que seu código passa em todos os testes, é hora de fazer o deploy. Podemos adicionar uma etapa de deploy ao nosso workflow. Neste exemplo, vamos usar o GitHub Pages como destino de deploy. Abaixo está como você pode configurar isso:

    - name: Deploy to GitHub Pages
      uses: peaceiris/actions-gh-pages@v3
      with:
        github_token: ${{ secrets.GITHUB_TOKEN }}
        publish_dir: ./build

Neste passo, a ação peaceiris/actions-gh-pages é usada para fazer o deploy do conteúdo da pasta ./build (supondo que você tenha configurado seu projeto para gerar os arquivos de build nesta pasta) para o GitHub Pages.

Secrets e variáveis

Ao trabalhar com CI/CD, é comum precisar lidar com informações sensíveis, como credenciais e tokens. O GitHub oferece a funcionalidade de Secrets para armazenar essas informações de forma segura. Você pode configurar secrets no repositório através das configurações do GitHub.

Para usar um secret no seu workflow, basta referenciá-lo usando a sintaxe ${{ secrets.NOME_DO_SECRET }}. Por exemplo, se você tiver um secret chamado API_TOKEN, você pode usá-lo assim:

    - name: Deploy to API
      run: curl -X POST -H "Authorization: Bearer ${{ secrets.API_TOKEN }}" https://api.example.com/deploy

Isso assegura que suas credenciais não fiquem expostas no código.

Conclusão

Implementar um pipeline de CI/CD com GitHub Actions para projetos Node.js e React pode parecer desafiador à primeira vista, mas seguindo os passos corretos, torna-se uma tarefa simples e eficiente. Com a configuração adequada, você garante que seu código esteja sempre pronto para ser entregue, testado e verificado, aumentando a qualidade e a confiança no seu trabalho.

Takeaways práticos:

  • Crie workflows no GitHub Actions para automatizar testes e deployments.
  • Utilize matrizes de versões para assegurar compatibilidade com múltiplas versões do Node.js.
  • Implemente cache de dependências para otimizar o tempo de build.
  • Integre testes e linting para garantir a qualidade do código.
  • Utilize secrets para gerenciar informações sensíveis de forma segura.

Glossário do post

ci
Continuous Integration: prática de integrar e testar mudanças de código automaticamente e com frequência.
github
Plataforma de hospedagem de código fonte com controle de versão Git, usada para colaboração e deploy de projetos.
node
Node.js: runtime JavaScript fora do navegador, baseado no motor V8, usado principalmente para construir servidores e ferramentas de linha de comando.
react
Biblioteca JavaScript para construir interfaces de usuário a partir de componentes reutilizáveis, mantida pela Meta.
cache
Armazenamento temporário de dados já calculados ou buscados para acelerar acessos futuros e reduzir carga no servidor.
npm
Gerenciador de pacotes padrão do ecossistema Node.js, usado para instalar e publicar bibliotecas JavaScript.
json
JavaScript Object Notation: formato leve de troca de dados baseado em pares chave/valor, legível para humanos e máquinas.
Ismael Douglas

Sobre o autor

Ismael Douglas

Desenvolvedor Full Stack apaixonado por construir produtos web rápidos e bem projetados. Escrevo sobre o que aprendo no caminho — código, infra e boas práticas.

Veja meus projetos no portfólio →