CI/CD para Go: construindo um pipeline do zero em 20 minutos

Treinador Online de Python para Iniciantes

Aprenda Python facilmente sem sobrecarga teórica. Resolva tarefas práticas com verificação automática e escreva código diretamente no navegador.

Start Course

Por que seu projeto Go pede CI/CD como um cachorro pede para passear



Você escreveu um microsserviço incrível em Go. Ele voa, os testes passam, o código é bonito. Mas toda manhã você executa manualmente go build, envia o binário para o servidor via SSH e reza para que nada quebre. Familiar? Se sim — tenho uma novidade para você: você está gastando 15% da sua vida com algo que um robô pode fazer.



CI/CD (Integração Contínua / Entrega Contínua) não é apenas uma palavra da moda nas vagas de DevOps. É seu assistente pessoal que:

  • executa testes a cada push no Git;
  • compila o binário para Linux/amd64, mesmo que você use Mac;
  • envia notificações no Telegram se o build falhar;
  • faz deploy automático no servidor quando você faz merge de um PR na main.


Neste artigo, vamos configurar um pipeline CI/CD para Go do zero. Sem enrolação, sem "instale o Jenkins em 20 servidores". Apenas GitHub Actions, Docker e um pouco de mágica. Vamos lá!



O que vamos precisar

Para a configuração, precisaremos de:

  • Um repositório no GitHub (você pode criar um de teste agora mesmo);
  • Um projeto Go com módulos (vamos escrever um servidor HTTP simples);
  • Uma conta no Docker Hub (ou qualquer outro registry);
  • 5 minutos de atenção e vontade de automatizar a rotina.


Todo o código que usaremos está disponível publicamente. Você pode copiá-lo e adaptá-lo ao seu projeto. O importante é não esquecer de substituir os tokens e nomes de repositórios pelos seus.



Passo 1: Escrevendo uma aplicação Go simples

Para demonstração, vamos usar um servidor HTTP mínimo. Crie o arquivo main.go:



package main

import ( "fmt" "net/http")

func main() { http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { fmt.Fprintf(w, "Hello from Go CI/CD pipeline!") })

http.ListenAndServe(":8080", nil)}


E o arquivo main_test.go para verificar o funcionamento:



package main

import ( "net/http" "net/http/httptest" "testing")

func TestHelloHandler(t *testing.T) { req := httptest.NewRequest("GET", "/", nil) w := httptest.NewRecorder()

http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { fmt.Fprintf(w, "Hello from Go CI/CD pipeline!") })

http.DefaultServeMux.ServeHTTP(w, req)

if w.Code != http.StatusOK { t.Errorf("expected status 200, got %d", w.Code) }}


Inicializamos o módulo:

go mod init github.com/seu-usuario/go-cicd-examplego mod tidy


Verificamos se tudo funciona:

go test ./... -vgo run main.go


Se você vir ok e a saudação em localhost:8080 — você é incrível. Vamos em frente.



Passo 2: Criando um Dockerfile para a aplicação Go

Containerização é uma etapa obrigatória no deploy moderno. Vamos compilar um binário estático (sem CGO) e empacotá-lo em uma imagem mínima baseada em scratch ou alpine. Isso nos dará uma imagem de cerca de 10–15 MB em vez de 300+ MB.



Crie o arquivo Dockerfile na raiz do projeto:



FROM golang:1.22-alpine AS builder

WORKDIR /appCOPY go.mod go.sum ./RUN go mod downloadCOPY . .RUN CGO_ENABLED=0 GOOS=linux go build -o main .

FROM alpine:latestRUN apk --no-cache add ca-certificatesWORKDIR /root/COPY --from=builder /app/main .EXPOSE 8080CMD ["./main"]


Observe: usamos uma compilação multi-estágio. O primeiro estágio é a compilação no ambiente completo do Go. O segundo é uma imagem Alpine mínima, onde apenas o binário é copiado. Isso é o padrão da indústria para aplicações Go.



Vamos compilar a imagem localmente e verificar:

docker build -t go-cicd-example .docker run -p 8080:8080 go-cicd-example


Se tudo estiver certo — vamos para o

Blogs

Book Recommendations