CI/CD para Go: creando un pipeline desde cero en 20 minutos

Entrenador de Python en Línea para Principiantes

Aprende Python fácilmente sin sobrecargarte de teoría. Resuelve tareas prácticas con verificación automática, recibe pistas y escribe código directamente en el navegador, sin instalar nada.

Start Course

Por qué tu proyecto Go pide CI/CD como un perro pide salir a pasear



Escribiste un microservicio increíble en Go. Vuela, las pruebas pasan, el código es hermoso. Pero cada mañana ejecutas manualmente go build, subes el binario al servidor por SSH y rezas para que nada falle. ¿Te suena familiar? Si es así, tengo noticias para ti: estás gastando el 15% de tu vida en lo que un robot puede hacer.



CI/CD (Integración Continua / Despliegue Continuo) no es solo una palabra de moda en las ofertas de DevOps. Es tu asistente personal que:

  • ejecuta pruebas en cada push a Git;
  • compila el binario para Linux/amd64, incluso si tienes Mac;
  • envía notificaciones a Telegram si la compilación falla;
  • despliega automáticamente en el servidor cuando fusionas un PR en main.


En este artículo configuraremos un pipeline CI/CD para Go desde cero. Sin rodeos, sin "instala Jenkins en 20 servidores". Solo GitHub Actions, Docker y un poco de magia. ¡Vamos allá!



Qué necesitaremos

Para la configuración necesitaremos:

  • Un repositorio en GitHub (puedes crear uno de prueba ahora mismo);
  • Un proyecto Go con módulos (escribiremos un servidor HTTP simple);
  • Una cuenta en Docker Hub (o cualquier otro registry);
  • 5 minutos de atención y ganas de automatizar la rutina.


Todo el código que usaremos está disponible públicamente. Puedes copiarlo y adaptarlo a tu proyecto. Lo importante es que no olvides reemplazar los tokens y nombres de repositorios por los tuyos.



Paso 1: Escribimos una aplicación Go simple

Para la demostración, tomaremos un servidor HTTP mínimo. Crea el archivo 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)}


Y el archivo main_test.go para verificar el funcionamiento:



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 el módulo:

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


Verificamos que todo funciona:

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


Si ves ok y el saludo en localhost:8080 — eres increíble. Sigamos adelante.



Paso 2: Creamos un Dockerfile para la aplicación Go

La contenerización es una etapa obligatoria del despliegue moderno. Compilaremos un binario estático (sin CGO) y lo empaquetaremos en una imagen mínima basada en scratch o alpine. Esto nos dará una imagen de aproximadamente 10–15 MB en lugar de 300+ MB.



Crea el archivo Dockerfile en la raíz del proyecto:



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"]


Nota: usamos compilación multi-etapa. La primera etapa es la compilación en un entorno completo de Go. La segunda es una imagen mínima de Alpine, donde solo se copia el binario. Este es el estándar de la industria para aplicaciones Go.



Compilamos la imagen localmente y verificamos:

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


Si todo está bien — pasamos a

Blogs

Book Recommendations