Artigo original: What is CI/CD? Learn Continuous Integration/Continuous Deployment by Building a Project

Olá! Neste artigo, você aprenderá sobre CI/CD (integração contínua e implantação contínua).

Vamos revisar o que essa prática significa, como ela se compara à abordagem anterior na indústria de desenvolvimento de software e, finalmente, ver um exemplo prático de como podemos implementá-la em nossos projetos.

Vamos lá!

Índice

Introdução

Integração Contínua e Entrega Contínua (CI/CD, do inglês Continuous Integration/Continuous Delivery) é uma abordagem de desenvolvimento de software que visa melhorar a velocidade, eficiência e confiabilidade da entrega de software. Ela envolve integração frequente de código, testes automatizados e entrega contínua de alterações de software em produção.

Antes da adoção do CI/CD na indústria de desenvolvimento de software, a abordagem comum era um modelo tradicional em cascata de desenvolvimento de software.

Nessa abordagem, os desenvolvedores trabalhavam em silos, com cada etapa do ciclo de vida do desenvolvimento de software sendo concluída após a anterior. O processo normalmente envolvia a coleta de requisitos, o design do software, a programação, os testes e a implantação.

As desvantagens dessa abordagem tradicional incluem:

  1. Ciclos de lançamento lentos: como cada etapa do ciclo de vida do desenvolvimento de software era concluída em sequência, o ciclo de lançamento era lento, o que dificultava a resposta rápida às mudanças nas necessidades do cliente.
  2. Altas taxas de falha: os projetos de software eram propensos a falhas devido à falta de testes automatizados, o que significava que os desenvolvedores tinham que confiar em testes manuais, levando a erros e bugs no código.
  3. Colaboração limitada: a abordagem tradicional não incentivava a colaboração entre desenvolvedores, testadores e outras partes interessadas, o que dificultava a identificação e correção de problemas.
  4. Alto custo: a natureza manual do desenvolvimento de software significava que era caro, com altos custos associados a testes, depuração e correção de erros.
  5. Agilidade limitada: como a abordagem tradicional era linear, não era possível fazer alterações no software rapidamente ou responder às necessidades do cliente em tempo real.

O CI/CD surgiu como uma solução para essas desvantagens, introduzindo uma abordagem mais ágil e colaborativa para o desenvolvimento de software. O CI/CD permite que as equipes trabalhem juntas, integrando suas alterações de código com frequência e automatizando o processo de teste e implantação.

Como o CI/CD funciona

O CI/CD é um processo automatizado que envolve integração frequente de código, testes automatizados e implantação contínua de alterações de software em produção.

Vamos explicar cada etapa com um pouco mais de detalhes:

Integração de código

A primeira etapa no pipeline de CI/CD é a integração de código. Nessa etapa, os desenvolvedores confirmam suas alterações de código em um repositório remoto (como GitHub, GitLab ou BitBucket), onde o código é integrado à base de código principal.

Essa etapa visa garantir que as alterações de código sejam compatíveis com o restante da base de código e não interrompam a compilação.

Testes automatizados

Uma vez que o código é integrado, a próxima etapa é o teste automatizado. O teste automatizado envolve a execução de um conjunto de testes para garantir que as alterações de código sejam funcionais, atendam aos padrões de qualidade esperados e estejam livres de defeitos.

Essa etapa ajuda a identificar problemas no início do processo de desenvolvimento, permitindo que os desenvolvedores os corrijam de maneira rápida e eficiente.

Se você não está familiarizado com o tópico de testes, consulte este artigo.

Entrega contínua

Depois que as alterações de código passam na etapa de teste automatizado, a próxima etapa é a entrega contínua. Nessa etapa, as alterações de código são implantadas automaticamente em um ambiente de teste para testes adicionais.

Essa etapa visa garantir que o software seja atualizado continuamente com as alterações de código mais recentes, entregando novos recursos e funcionalidades aos usuários de maneira rápida e eficiente.

Implantação em produção

A etapa final no pipeline de CI/CD é a implantação em produção. Nessa etapa, as alterações de software são lançadas para os usuários finais. Essa etapa envolve o monitoramento do ambiente de produção, garantindo que o software esteja funcionando sem problemas e identificando e corrigindo quaisquer problemas que surjam.

As quatro etapas de um pipeline de CI/CD trabalhem juntas para garantir que as alterações de software sejam testadas, integradas e implantadas em produção automaticamente. Essa automação ajuda a reduzir erros, aumentar a eficiência e melhorar a qualidade geral do software.

Ao adotar um pipeline de CI/CD, as equipes de desenvolvimento podem alcançar ciclos de lançamento mais rápidos, reduzir o risco de defeitos de software e melhorar a experiência do usuário.

Lembre-se de que as etapas do pipeline podem parecer diferentes, dado o projeto ou empresa específica sobre a qual estamos falando. Ou seja, algumas equipes podem ou não usar testes automatizados, algumas equipes podem ou não ter um ambiente de "teste" e assim por diante.

As partes principais que compõem a prática de CI/CD são a integração e a implantação (entrega). Isso significa que o código deve ser continuamente integrado em um repositório remoto e que esse código deve ser continuamente implantado em um determinado ambiente após cada integração.

Os principais benefícios do CI/CD

Os principais benefícios do CI/CD incluem:

  1. Ciclos de lançamento mais rápidos: ao automatizar o processo de teste e implantação, o CI/CD permite que as equipes lancem software com mais frequência, respondendo rapidamente às necessidades do cliente.
  2. Qualidade aprimorada: o teste automatizado garante que as alterações de software não introduzam novos bugs ou problemas, melhorando a qualidade geral do software.
  3. Maior colaboração: a integração e o teste frequentes de código exigem que os desenvolvedores trabalhem em estreita colaboração, levando a uma melhor colaboração e comunicação.
  4. Risco reduzido: a implantação contínua permite que os desenvolvedores identifiquem e corrijam problemas rapidamente, reduzindo o risco de falhas graves e tempo de inatividade.
  5. Custo-benefício: o CI/CD reduz a quantidade de trabalho manual necessária para implantar alterações de software, economizando tempo e reduzindo custos.

Em resumo, o CI/CD surgiu como uma solução para as limitações da abordagem tradicional e linear para o desenvolvimento de software. Ao introduzir uma abordagem mais ágil e colaborativa para o desenvolvimento de software, o CI/CD permite que as equipes trabalhem juntas, lancem software com mais frequência e respondam rapidamente às necessidades do cliente.

Ferramentas para CI/CD

Existem várias ferramentas disponíveis para implementar pipelines de CI/CD no desenvolvimento de software. Cada ferramenta tem seus recursos, prós e contras exclusivos. Aqui estão algumas das ferramentas mais usadas em pipelines de CI/CD hoje:

Jenkins

O Jenkins é um servidor de automação de código aberto amplamente utilizado em pipelines de CI/CD. É altamente personalizável e suporta uma grande variedade de plug-ins, tornando-o adequado para vários ambientes de desenvolvimento. Alguns de seus principais recursos incluem:

Prós:

  • Altamente personalizável com uma grande quantidade de plug-ins
  • Suporta integração com várias ferramentas e tecnologias
  • Fornece relatórios e análises detalhados

Contras:

  • Requer alguma experiência técnica para configurar e manter
  • Pode consumir muitos recursos, especialmente para grandes projetos
  • Falta de um painel centralizado para gerenciar vários projetos

Se você quiser saber mais sobre o Jenkins, clique aqui (em inglês).

Travis CI

O Travis CI é uma plataforma de CI/CD baseada em nuvem que fornece testes e implantação automatizados para projetos de software. Ele suporta várias linguagens de programação e frameworks, tornando-o adequado para vários ambientes de desenvolvimento. Alguns de seus principais recursos incluem:

Prós:

  • Fácil de configurar e usar
  • Baseado em nuvem, não havendo a necessidade de configurar e manter a infraestrutura
  • Suporta uma grande variedade de linguagens de programação e frameworks
  • Fornece relatórios e análises detalhados

Contras:

  • Opções de personalização limitadas
  • Não é adequado para grandes projetos com requisitos complexos
  • Suporte limitado para instalações locais

Para saber mais sobre o Travis CI, clique aqui (em inglês).

GitHub Actions

GitHub Actions é uma ferramenta poderosa de CI/CD, que permite que os desenvolvedores automatizem fluxos de trabalho, executem testes e implantem código diretamente de seus repositórios no GitHub.

Prós:

  • Integrado ao GitHub
  • Fácil de usar
  • Fornece um grande ecossistema e boa documentação

Contras:

  • Minutos de compilação limitados
  • Sintaxe YAML complexa
Nota: menciono GitHub Actions aqui porque é uma ferramenta popular – mas lembre-se de que outros provedores de repositórios online, como GitLab e BitBucket, também oferecem opções muito semelhantes às GitHub Actions.

Recursos de CI/CD integrados por hosts

Hosts populares, como Vercel ou Netlify, têm recursos de CI/CD integrados que permitem vincular um repositório on-line a um determinado site e implantar nesse site após um determinado evento ocorrer nesse repositório.

Prós:

  • Muito simples de configurar e usar

Contras:

  • Opções de personalização limitadas

Cada uma dessas ferramentas tem seus recursos, prós e contras exclusivos. A escolha da ferramenta dependerá dos requisitos específicos do seu projeto, da experiência técnica da sua equipe e do seu orçamento.

Como configurar um pipeline de CI/CD com GitHub Actions

Agora que temos uma ideia clara do que é CI/CD, vamos ver como podemos implementar um exemplo simples com um projeto real usando GitHub Actions.

Inicializando o projeto

Começaremos com uma aplicação do React muito básica construída com Vite. Você pode fazer isso executando yarn create vite no seu console.

Vamos nos concentrar no pipeline de CI/CD aqui. Então, não haverá complexidade no código real da aplicação. Para se ter uma ideia, porém, o componente app.jsx terá este código:

import './App.css';

function App() {

    return (
        <div className='App'>
            <h1>Vite + Reactooooo</h1>
        </div>
    );
}

export default App;

Então, teremos um arquivo de teste que verificará se esse texto é renderizado:

import { describe, expect, it } from 'vitest';
import { render, screen } from './utils/test-utils/test-utils.jsx';

import App from 'src/App.jsx';

describe('App', async () => {
    it('deve renderizar durante a autenticação', () => {
        render(<App />);

        expect(screen.getByText('Vite + Reactooooo')).toBeInTheDocument();
    });
});

Esse teste será executado cada vez que executarmos o comando yarn test.

O próximo passo deve ser enviar nosso código para um repositório no GitHub. Vamos falar um pouco mais sobre o que são GitHub Actions e sobre como funcionam.

O que são GitHub Actions e como funcionam?

GitHub Actions é um serviço de CI/CD (Integração Contínua/Entrega Contínua) fornecido pelo GitHub. Ele permite que os desenvolvedores automatizem fluxos de trabalho definindo scripts personalizados, conhecidos como "ações", que podem ser acionados por eventos como pushes para um repositório, pull requests ou issues.

As ações são definidas em um arquivo YAML, também conhecido como "fluxo de trabalho", que especifica as etapas necessárias para concluir uma tarefa. Os fluxos de trabalho das GitHub Actions podem ser executados em ambientes Linux, Windows e macOS e suportam uma grande variedade de linguagens de programação e frameworks.

Quando um evento aciona um fluxo de trabalho das GitHub Actions, o serviço cria um novo ambiente, instala dependências e executa as etapas definidas na ordem especificada. Isso pode incluir tarefas como compilar, testar, empacotar e implantar código.

As GitHub Actions também fornecem várias ações integradas, que podem ser usadas para simplificar tarefas comuns, como verificar código, compilar e testar aplicações, publicar lançamentos e implantar em provedores de nuvem populares como AWS, Azure e Google Cloud.

Os fluxos de trabalho das GitHub Actions podem ser executados em um cronograma, manualmente ou automaticamente, quando um evento específico ocorre, como um pull request sendo aberto ou um novo commit sendo enviado para uma branch.

Configurando nosso fluxo de trabalho

Como vimos, basicamente, as GitHub Actions são um recurso que nos permite definir fluxos de trabalho para nossos projetos. Esses fluxos de trabalho nada mais são do que uma série de tarefas ou etapas que serão executadas na nuvem do GitHub após um determinado evento que declaramos.

A maneira como o GitHub lê e executa esses fluxos de trabalho é lendo automaticamente os arquivos dentro do diretório .github/workflows na raiz do nosso projeto. Esses arquivos de fluxo de trabalho devem ter a extensão .yaml e usar a sintaxe YAML.

Para criar um fluxo de trabalho, basta criar um arquivo YAML dentro desse diretório. Chamaremos o nosso de prod.yaml, pois o usaremos para implantar a branch de produção do nosso projeto.

Lembre-se de que um único projeto pode ter muitos fluxos de trabalho diferentes que executam tarefas diferentes em ocasiões diferentes. Por exemplo, poderíamos ter um fluxo de trabalho para branches de desenvolvimento e teste também, pois esses ambientes podem exigir tarefas diferentes para executar e provavelmente serão implantados em sites diferentes.

Depois de criar esse arquivo, vamos colocar o seguinte código nele:

# Nome do nosso fluxo de trabalho
name: Implantação de Produção

# Aciona o fluxo de trabalho no push para o branch principal
on:
  push:
    branches:
      - main

# Lista de trabalhos
# Um "trabalho" é um conjunto de etapas que são executadas no mesmo executor
jobs:
  # Nome do trabalho
  testar-e-implantar-no-netlify:
    # Sistema operacional para executar
    runs-on: ubuntu-latest

    # Lista de etapas que compõem o trabalho
    steps:
    # Faz checkout do seu repositório em $GITHUB_WORKSPACE, para que seu trabalho possa acessá-lo
    - name: Checkout do código
      uses: actions/checkout@v2

    # Configurar ambiente Node.js
    - name: Usar Node.js 16.x
      uses: actions/setup-node@v2
      with:
        node-version: '16.x'

    # Instalar dependências
    - name: Instalar dependências
      run: yarn install

    # Executar testes
    - name: Executar testes
      run: yarn test

    # Implantar no Netlify
    - name: Implantação Netlify
      uses: jsmrcaga/action-netlify-deploy@v2.0.0
      with:
        # Token de autenticação para usar com o Netlify
        NETLIFY_AUTH_TOKEN: ${{ secrets.NETLIFY_AUTH_TOKEN }}
        # ID do seu site Netlify
        NETLIFY_SITE_ID:  ${{ secrets.NETLIFY_SITE_ID }}
        # Diretório onde os arquivos compilados são armazenados
        build_directory: './dist'
        # Comando para instalar dependências
        install_command: yarn install
        # Comando para compilar o site estático
        build_command: yarn build   

Então, nosso fluxo de trabalho tem as seguintes tarefas declaradas:

  1. Etapa "Checkout do código", que faz checkout do último commit na branch atual.
  2. Etapa "Usar Node.js 16.x", que configura o ambiente Node.js para a versão 16.x.
  3. Etapa "Instalar dependências", que instala as dependências do projeto usando o gerenciador de pacotes Yarn.
  4. Etapa "Executar testes", que executa os testes do projeto usando o gerenciador de pacotes Yarn.
  5. Etapa "Implantação no Netlify", que implanta o projeto no Netlify usando a ação jsmrcaga/action-netlify-deploy. Essa etapa usa o token de autenticação do Netlify e os segredos de ID do site armazenados nos segredos do repositório GitHub. O diretório de compilação, o comando de instalação e o comando de compilação também são especificados.

Você provavelmente notou que a primeira e a última etapas têm a palavra-chave uses. Essa palavra-chave permite que você use ações ou fluxos de trabalho desenvolvidos por outros usuários do GitHub e é um dos melhores recursos das GitHub Actions.

Algo fantástico é o fato de que, ao usar essas ações de terceiros, podemos executar tarefas complexas, como implantar em um host externo ou construir infraestrutura de nuvem complexa, sem a necessidade de escrever cada linha de código necessária.

Como essas tarefas tendem a ser repetitivas e frequentemente executadas em muitos projetos, podemos simplesmente usar um fluxo de trabalho desenvolvido por uma conta oficial da empresa (como Azure ou AWS, por exemplo) ou um desenvolvedor independente de código aberto. Pense nisso como usar uma biblioteca de terceiros. É a mesma ideia, mas aplicada aos fluxos de trabalho de CI/CD. É muito conveniente.

Outra coisa importante a mencionar aqui é que, nos fluxos de trabalho das GitHub Actions, as tarefas são executadas sequencialmente, uma após a outra. Se uma determinada tarefa falhar ou lançar um erro, a próxima não será executada. Isso é importante porque, se tivermos um problema ao instalar nossas dependências ou se um teste falhar, não queremos que esse código seja implantado.

Antes de enviarmos esse código e vermos como a mágica funciona, primeiro, precisamos criar um site no Netlify e obter o NETLIFY_AUTH_TOKEN e o NETLIFY_SITE_ID. Isso é bastante direto. Mesmo quee você não tenha experiência anterior com o Netlify, experimente e pesquise um pouco no Google se não conseguir descobrir. 😉

Depois de ter esses dois tokens, você precisa declará-los como segredos do repositório no seu repositório do GitHub. Você pode fazer isso na guia  de configurações (Settings):

image-32
Configure os dois tokens secretos do Netlify no seu repositório

Com isso em vigor, agora nosso arquivo prod.yaml poderá ler esses dois tokens e executar a ação de implantação do Netlify.

A mágica

Agora, que temos tudo no lugar, vamos enviar nosso código e ver como vai.

Após o push, se formos para a guia "Actions" do nosso repositório, à esquerda veremos uma lista de todos os fluxos de trabalho que temos em nosso repositório. À direita, veremos uma lista de cada execução do fluxo de trabalho selecionado. Como nosso fluxo de trabalho é executado após cada push, devemos ver uma nova execução cada vez que enviarmos.

image-33
Uma execução de fluxo de trabalho

Quando a execução tem uma luz amarela à esquerda, significa que ainda está em execução (executando tarefas). Se tiver uma luz verde, significa que terminou de executar com sucesso. Se a luz estiver vermelha, você sabe que algo deu errado.

Depois de clicar na execução, podemos ver uma lista dos trabalhos do fluxo de trabalho (tínhamos apenas um).

image-34
Os trabalhos do fluxo de trabalho

Depois de clicar no trabalho, podemos ver uma lista das tarefas do trabalho.

image-35
As tarefas do trabalho

Cada tarefa é expansível e, dentro dela, podemos ver os logs correspondentes à execução dessa tarefa. Isso é muito útil para fins de depuração. 😉

Agora, se formos para o nosso site do Netlify configurado anteriormente, devemos ver nossa aplicação funcionando!

Como temos nosso pipeline de CI/CD em funcionamento, podemos implantar nossa aplicação após cada push para a branch principal, tudo sem precisar de mais esforços. 😀

Conclusão

CI/CD é uma abordagem de desenvolvimento de software que oferece vários benefícios às equipes de desenvolvimento de software, incluindo tempo mais rápido de lançamento no mercado, qualidade aprimorada, maior colaboração, risco reduzido e custo-benefício.

Ao automatizar o pipeline de entrega de software, as equipes podem implantar rapidamente novos recursos e correções de bugs, ao mesmo tempo em que reduzem o risco de falhas graves e tempo de inatividade.

Com a disponibilidade de várias ferramentas de CI/CD, tornou-se mais fácil para as equipes implementarem essa abordagem e melhorarem seu processo de entrega de software.

Como sempre, espero que tenham gostado do artigo e aprendido algo novo.