Integração Contínua (CI)

GitBeginner
Pratique Agora

Introdução

Imagine que você esteja escrevendo um livro com uma equipe grande. Sempre que alguém envia um novo capítulo, você precisa verificar erros de ortografia e falhas no enredo. Fazer isso manualmente é cansativo.

No desenvolvimento de software, resolvemos esse problema com a integração contínua (CI). A CI verifica automaticamente as alterações desde o início, normalmente instalando dependências, executando testes e validando o projeto após cada atualização.

A ideia principal é obter feedback rapidamente. É mais fácil corrigir os problemas quando eles são identificados logo após uma alteração, em vez de dias depois.

É por isso que a CI costuma ser a primeira camada de automação criada pelas equipes. Ela protege a branch principal ao transformar cada push em uma verificação automática de qualidade.

Neste laboratório, você criará essa rede de segurança para uma aplicação Node.js simples. Você vai:

  • Criar uma aplicação pequena que faz cálculos matemáticos básicos.
  • Escrever um teste para comprovar que os cálculos estão corretos.
  • Configurar o GitHub Actions para executar esse teste automaticamente sempre que você fizer push do código.
  • Quebrar o código de propósito para ver como a rede de segurança identifica o erro.

Pré-requisitos

Este laboratório dá continuidade ao anterior. Continuaremos usando o repositório github-actions-basics que você criou.

Preparar o projeto Node.js

Primeiro, precisamos de um código para testar. Vamos criar uma aplicação Node.js pequena. Se você não é programador, não se preocupe: forneceremos todo o código necessário.

Acesse o diretório do projeto. Como este é um novo ambiente de laboratório, precisamos baixar o repositório novamente.

cd ~/project
git clone https://github.com/your-username/github-actions-basics.git
cd github-actions-basics

Observação: lembre-se de substituir your-username pelo seu nome de usuário real do GitHub.

Precisamos criar três arquivos para simular um projeto real. Usaremos o comando cat, que permite criar rapidamente arquivos com conteúdo diretamente pela linha de comando.

1. A “receita” (package.json)

Este arquivo informa ao computador o que é o nosso projeto e quais ferramentas ele precisa. Estamos informando que o projeto depende de uma ferramenta de testes chamada jest.

cat > package.json << EOF
{
  "name": "ci-demo",
  "version": "1.0.0",
  "scripts": {
    "test": "jest"
  },
  "dependencies": {
    "jest": "^29.7.0"
  }
}
EOF

2. A “comida” (index.js)

Este é o código da nossa aplicação. Trata-se de uma função simples que soma dois números.

cat > index.js << EOF
function sum(a, b) {
  return a + b;
}
module.exports = sum;
EOF

3. O “teste de sabor” (index.test.js)

Este é o nosso teste automatizado. Ele verifica que, se somarmos 1 e 2, o resultado deve ser 3.

cat > index.test.js << EOF
const sum = require('./index');

test('adds 1 + 2 to equal 3', () => {
  expect(sum(1, 2)).toBe(3);
});
EOF

Agora que criamos os arquivos, precisamos salvá-los no GitHub. Execute os comandos padrão do Git para enviar seu trabalho.

git add .
git commit -m "Add Node.js project files"
git push

Talvez seja necessário entrar no GitHub novamente. Use seu nome de usuário e o Personal Access Token (PAT), como antes.

Criar o workflow de CI

Agora precisamos informar ao nosso assistente robótico como testar esse código. Vamos criar um novo arquivo de workflow chamado ci.yml na pasta padrão .github/workflows.

touch .github/workflows/ci.yml

Abra esse arquivo no editor nano.

nano .github/workflows/ci.yml

Adicione a configuração a seguir. Explicaremos as novas partes abaixo.

name: Node.js CI

on: [push]

jobs:
  build:
    runs-on: ubuntu-latest

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

      - name: Setup Node.js
        uses: actions/setup-node@v3
        with:
          node-version: 16

Aqui, estamos apresentando uma nova palavra-chave importante: uses.

Esse é um padrão importante do GitHub Actions. Em vez de escrever manualmente cada etapa do shell, os workflows geralmente combinam actions reutilizáveis que agrupam tarefas comuns, como fazer checkout, configurar uma linguagem ou enviar artefatos.

Pense em uses como o download de uma habilidade para o cérebro do robô. Em vez de escrever scripts complexos do zero, podemos usar actions prontas criadas por outras pessoas.

  • actions/checkout@v4: esta action padrão informa ao robô: “Baixe meu código”. Sem ela, o robô teria um workspace vazio.
  • actions/setup-node@v3: instala o Node.js no runner. Também informamos uma versão específica (16) para garantir consistência.

Salve e saia do editor (Ctrl+X, Y, Enter).

Adicionar as etapas de instalação e teste

Já temos o código (checkout) e as ferramentas (Node.js). Agora precisamos executar o teste de fato.

No ecossistema Node.js, há dois comandos padrão para isso:

  1. npm install: baixa todas as dependências listadas no seu package.json, como a ferramenta de testes jest.
  2. npm test: executa o script de teste definido no seu package.json.

Juntas, essas etapas representam o núcleo da CI: preparar o ambiente, instalar as dependências e validar o código em um runner limpo antes de considerar a alteração saudável.

Vamos adicionar essas etapas ao workflow. Abra .github/workflows/ci.yml novamente.

nano .github/workflows/ci.yml

Acrescente estas duas etapas ao final do arquivo. Verifique se a indentação está alinhada com as etapas anteriores.

- name: Install dependencies
  run: npm install

- name: Run tests
  run: npm test

O arquivo completo deve ficar assim:

name: Node.js CI

on: [push]

jobs:
  build:
    runs-on: ubuntu-latest

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

      - name: Setup Node.js
        uses: actions/setup-node@v3
        with:
          node-version: 16

      - name: Install dependencies
        run: npm install

      - name: Run tests
        run: npm test

Salve e saia do editor.

Agora, ative sua rede de segurança enviando esse arquivo para o GitHub.

git add .
git commit -m "Add CI pipeline"
git push

Acesse o repositório no GitHub e clique na guia Actions. Você deverá ver um novo workflow chamado “Node.js CI” em execução. Quando ele terminar, aparecerá uma marca de verificação verde. Isso significa que o código está funcionando!

CI Pipeline

Quebrar o build

Uma rede de segurança só é útil se conseguir amparar você quando cair. Vamos “quebrar” o código de propósito para ver o sistema de CI em ação.

Vamos editar o arquivo de teste para fazer uma afirmação incorreta. Diremos que 1 + 2 deve ser igual a 4.

Abra index.test.js usando o nano.

nano index.test.js

Altere a expectativa do teste de 3 para 4.

const sum = require("./index");

test("adds 1 + 2 to equal 3", () => {
  expect(sum(1, 2)).toBe(4); // CHANGED 3 to 4
});

Salve e saia. Agora faça o commit e o push desse “bug”.

git add .
git commit -m "Intentionally break the test"
git push

Volte imediatamente para a guia Actions no GitHub. Observe a execução do novo workflow.

Em instantes, a execução deverá falhar. Você verá um ícone de X vermelho ao lado do commit. Esse é o sistema de CI gritando: “Pare! Há algo errado!”.

Clique na execução que falhou e, em seguida, clique no job build. Expanda a etapa Run tests para ver o log do erro:

Error: expect(received).toBe(expected) // Object.is equality

Expected: 4
Received: 3

Esse simples X vermelho poupa inúmeras horas dos desenvolvedores ao identificar os bugs no momento em que acontecem, em vez de dias ou semanas depois.

CI Pipeline Failed

Resumo

Neste laboratório, você criou um pipeline de Integração Contínua de nível profissional.

Você aprendeu:

  • Como definir a “receita” de um projeto com package.json.
  • Como usar a palavra-chave uses para instalar ferramentas importantes, como actions/checkout e actions/setup-node.
  • Como automatizar os testes para que cada alteração no código seja verificada por um robô.
  • A importância do “X vermelho” como uma rede de segurança para o seu código.

A seguir, aprenderemos a pegar um código funcional e empacotá-lo para que o mundo possa conhecê-lo!