No description
Find a file
Julio Caicedo 04ec176099
Some checks failed
_analytics.yaml / Based on the provided git diff, here are the conventional commit messages: (push) Failing after 0s
_build-docker.yaml / Based on the provided git diff, here are the conventional commit messages: (push) Failing after 0s
_deploy-k8s.yaml / Based on the provided git diff, here are the conventional commit messages: (push) Failing after 0s
_test.yaml / Based on the provided git diff, here are the conventional commit messages: (push) Failing after 0s
Based on the provided git diff, here are the conventional commit messages:
ci(workflows): update PR branch naming and Go version

- Change Sonar PR branch format to use PR number prefix
- Update default Go version from 1.25.4 to 1.25.5

Or, if you prefer a more concise single-line format:

ci(workflows): update PR branch naming format and Go version to 1.25.5
2025-12-23 15:41:13 -05:00
.forgejo/workflows Based on the provided git diff, here are the conventional commit messages: 2025-12-23 15:41:13 -05:00
examples feat: Consolidate Go private module credentials into registry user/password secrets, removing dedicated GIT_USER/GIT_TOKEN. 2025-12-16 13:45:32 -05:00
k8s refactor: update CI/CD templates to use Forgejo Actions instead of Gitea Actions 2025-12-08 09:41:02 -05:00
.gitignore Add CI/CD templates and setup script for Go microservices 2025-11-19 17:54:51 -05:00
README.md feat: Consolidate Go private module credentials into registry user/password secrets, removing dedicated GIT_USER/GIT_TOKEN. 2025-12-16 13:45:32 -05:00
setup-microservice.sh refactor: update CI/CD templates to use Forgejo Actions instead of Gitea Actions 2025-12-08 09:41:02 -05:00

Templates de CI/CD y Kubernetes - StartCodex

Templates reutilizables para microservicios Go con Forgejo Actions y Kubernetes.

Estructura

infra/
├── .forgejo/
│   └── workflows/                        # Workflows de Forgejo Actions
│       ├── go-microservice.yaml          # Workflow monolítico (todo-en-uno)
│       ├── _test.yaml                    # Modular: Tests & Coverage (multi-lenguaje)
│       ├── _analytics.yaml               # Modular: Opengrep + SonarQube (código)
│       ├── _build-docker.yaml            # Modular: Build Docker + Trivy (imagen)
│       └── _deploy-k8s.yaml              # Modular: Deploy a Kubernetes
├── k8s/                        # Templates de Kubernetes con Kustomize
│   ├── base/                   # Configuración base
│   └── overlays/               # Configuraciones por ambiente (dev, test, production)
├── examples/                   # Ejemplos de uso
├── setup-microservice.sh       # Script de setup automatizado (legacy)
└── README.md                  # Este archivo

Workflows reutilizables (prefijo _): Pueden ser llamados por otros workflows (Node.js, Python, etc.).

Uso Rápido

Hay dos formas de usar estos workflows:

  1. Workflow Monolítico (go-microservice.yaml) - Un solo job que ejecuta todo

    • Más simple de configurar
    • Menos visibilidad (todos los jobs aparecen colapsados como uno)
  2. Workflows Modulares (Recomendado) - Jobs independientes

    • Mejor visibilidad: Cada etapa aparece como un job separado en la UI
    • Fácil identificar qué etapa falló
    • Más flexible
    • ⚠️ Configuración inicial un poco más larga

Opción A: Workflow Modular (Recomendado para mejor visibilidad)

En tu microservicio, crea .forgejo/workflows/ci-cd.yaml:

name: CI/CD

on:
  push:
    branches: [dev, test, main]
  pull_request:
    branches: [dev, test, main]

jobs:
  # Cada job se verá por separado en la UI
  test:
    uses: startcodex/infra/.forgejo/workflows/_test.yaml@v1
    with:
      # project_type: auto    # auto, go, nodejs, react, nextjs, flutter, python
      go_version: '1.25.4'    # Para proyectos Go
      # node_version: '20'    # Para proyectos Node.js
      # python_version: '3.12' # Para proyectos Python

  analytics:
    needs: test
    uses: startcodex/infra/.forgejo/workflows/_analytics.yaml@v1
    with:
      service_name: tu-servicio-ms
      sonar_project_key: startcodex-tu-servicio-ms
      # project_type: auto       # auto, go, nodejs, react, nextjs, flutter, python
    secrets:
      SONARQUBE_TOKEN: ${{ secrets.SONARQUBE_TOKEN }}

  build:
    if: >
      forgejo.event_name != 'pull_request' &&
      (forgejo.ref_name == 'test' || forgejo.ref_name == 'main')
    needs: analytics
    uses: startcodex/infra/.forgejo/workflows/_build-docker.yaml@v1
    with:
      service_name: tu-servicio-ms
      registry_url: git.startcodex.dev
      registry_org: startcodex
    secrets:
      REGISTRY_USER: ${{ secrets.REGISTRY_USER }}
      REGISTRY_PASSWORD: ${{ secrets.REGISTRY_PASSWORD }}

  deploy:
    if: >
      forgejo.event_name != 'pull_request' &&
      (forgejo.ref_name == 'test' || forgejo.ref_name == 'main')
    needs: build
    uses: startcodex/infra/.forgejo/workflows/_deploy-k8s.yaml@v1
    with:
      service_name: tu-servicio-ms
      image_tag: ${{ needs.build.outputs.image_tag }}
      registry_url: git.startcodex.dev
      registry_org: startcodex
      k8s_namespace_test: startcodex-test
      k8s_namespace_prod: startcodex
      service_type: http-only
      http_port: '8080'
      # ... más configuración según necesites
    secrets:
      KUBECONFIG: ${{ secrets.KUBECONFIG }}
      INFRA_CLONE_TOKEN: ${{ secrets.INFRA_CLONE_TOKEN }}

Ver ejemplo completo en: examples/modular-workflow-example.yaml


Opción B: Workflow Monolítico (Más simple pero menos visible)

En tu microservicio, crea .forgejo/workflows/ci-cd.yaml:

name: CI/CD

on:
  push:
    branches: [dev, test, main]
  pull_request:
    branches: [dev, test, main]

jobs:
  ci-cd:
    uses: startcodex/infra/.forgejo/workflows/go-microservice.yaml@v1.0.0
    with:
      # Requeridos:
      service_name: tu-servicio-ms
      sonar_project_key: startcodex-tu-servicio-ms

      # Configuración del servicio:
      service_type: http-only      # http-only, grpc-only, both
      k8s_service_type: ClusterIP  # ClusterIP, NodePort, LoadBalancer
      http_port: '8080'
      grpc_port: '50051'           # Solo si usas gRPC

      # Secrets management (opcional):
      use_infisical: false         # true para usar Infisical
      # infisical_project_slug: startcodex-tu-servicio-ms
      # infisical_env_slug_test: staging
      # infisical_env_slug_prod: production

      # HPA - Autoscaling (opcional):
      # hpa_min_replicas_test: 2
      # hpa_max_replicas_test: 5
      # hpa_cpu_threshold_test: 70
      # hpa_memory_threshold_test: 80
      # hpa_min_replicas_prod: 3
      # hpa_max_replicas_prod: 10
      # hpa_cpu_threshold_prod: 60
      # hpa_memory_threshold_prod: 70

      # Health Checks (opcional):
      # enable_health_checks: true   # false para deshabilitar liveness/readiness

      # Opcionales (tienen defaults):
      # registry_url: git.startcodex.dev
      # registry_org: startcodex
      # k8s_namespace_dev: startcodex-dev
      # k8s_namespace_test: startcodex-test
      # k8s_namespace_prod: startcodex
      # sonarqube_host: https://sonar.startcodex.dev
      # go_version: '1.24.1'
    secrets: inherit

Versionado de Workflows

IMPORTANTE: Debido a limitaciones en Forgejo Actions, debes usar tags o SHA completo en lugar de nombres de branches (@main no funciona correctamente).

Opción 1: Tags Semánticos (Recomendado)

# Versión estable específica (recomendado para producción)
uses: startcodex/infra/.forgejo/workflows/go-microservice.yaml@v1.0.0

# Última versión minor (recibe bug fixes automáticamente)
uses: startcodex/infra/.forgejo/workflows/go-microservice.yaml@v1.0

# Última versión major (recibe todas las actualizaciones compatibles)
uses: startcodex/infra/.forgejo/workflows/go-microservice.yaml@v1

Semantic Versioning:

  • v1.0.0 → v1.0.1 (PATCH): Bug fixes, sin cambios funcionales
  • v1.0.0 → v1.1.0 (MINOR): Nuevas features compatibles
  • v1.0.0 → v2.0.0 (MAJOR): Breaking changes

Opción 2: SHA Completo

# Si necesitas una versión específica inmutable
uses: startcodex/infra/.forgejo/workflows/go-microservice.yaml@725dfbe7bf4bbc2ac1b5d3193789f25e598c1bd8

Recomendación: Usa tags semánticos para facilitar el mantenimiento y actualizaciones.

Referencia de Inputs

Inputs Requeridos

Input Descripción Ejemplo
service_name Nombre del microservicio users-ms
sonar_project_key Key del proyecto en SonarQube startcodex-users-ms

Inputs de Configuración del Servicio

Input Descripción Valores Default
service_type Tipo de protocolo del servicio http-only, grpc-only, both http-only
k8s_service_type Tipo de Service de Kubernetes ClusterIP, NodePort, LoadBalancer ClusterIP
http_port Puerto HTTP del servicio Cualquier puerto 8080
grpc_port Puerto gRPC del servicio Cualquier puerto 50051
enable_health_checks Habilitar liveness y readiness probes HTTP true/false true

Inputs de Secrets Management

Input Descripción Tipo Default
use_infisical Usar Infisical para secrets true/false false
infisical_project_slug Project slug en Infisical string ''
infisical_env_slug_test Environment slug para test string staging
infisical_env_slug_prod Environment slug para production string production

Inputs de Autoscaling (HPA)

Input Descripción Default
hpa_min_replicas_test Mínimo de réplicas para HPA en test 2
hpa_max_replicas_test Máximo de réplicas para HPA en test 5
hpa_cpu_threshold_test Umbral de CPU (%) para escalar en test 70
hpa_memory_threshold_test Umbral de memoria (%) para escalar en test 80
hpa_min_replicas_prod Mínimo de réplicas para HPA en production 3
hpa_max_replicas_prod Máximo de réplicas para HPA en production 10
hpa_cpu_threshold_prod Umbral de CPU (%) para escalar en production 60
hpa_memory_threshold_prod Umbral de memoria (%) para escalar en production 70

Inputs de Recursos por Ambiente

Recursos para TEST

Input Descripción Default
test_memory_request Memoria request para test 256Mi
test_memory_limit Memoria limit para test 512Mi
test_cpu_request CPU request para test 200m
test_cpu_limit CPU limit para test 500m

Recursos para PRODUCTION

Input Descripción Default
prod_memory_request Memoria request para production 512Mi
prod_memory_limit Memoria limit para production 1Gi
prod_cpu_request CPU request para production 500m
prod_cpu_limit CPU limit para production 1000m

Inputs de Infraestructura

Input Descripción Default
registry_url URL del Docker registry git.startcodex.dev
registry_org Organización en el registry startcodex
k8s_namespace_dev Namespace de Kubernetes para dev startcodex-dev
k8s_namespace_test Namespace de Kubernetes para test startcodex-test
k8s_namespace_prod Namespace de Kubernetes para production startcodex
sonarqube_host URL de SonarQube https://sonarqube.com
go_version Versión de Go 1.24.1

Secrets Requeridos en Forgejo

Secret Descripción Requerido Ejemplo
REGISTRY_USER Usuario del Docker registry (también para repos Go privados) forgejo-ci
REGISTRY_PASSWORD Password del Docker registry (también para repos Go privados) ***
SONARQUBE_TOKEN Token de autenticación de SonarQube squ_***
KUBECONFIG Configuración de kubectl (base64) apiVersion: v1...
INFRA_CLONE_TOKEN Token para clonar repo infra privado ⚠️ Solo si infra es privado ***

Módulos Go Privados

Si tu microservicio Go depende de módulos privados en git.startcodex.dev, los workflows automáticamente configuran .netrc usando REGISTRY_USER y REGISTRY_PASSWORD.

Dockerfile de ejemplo (ver examples/Dockerfile.go):

# El workflow pasa automáticamente .netrc como secret de BuildKit
RUN --mount=type=secret,id=netrc,target=/root/.netrc \
    go mod download

Funcionamiento automático:

  • En el job de test: Se configura ~/.netrc antes de go mod tidy
  • En el build de Docker: Se usa BuildKit secrets para no exponer credenciales en la imagen

2. Configurar Secrets en Forgejo

Configurar Secrets (Settings → Secrets and Variables → Secrets):

Secrets Requeridos:

REGISTRY_USER
REGISTRY_PASSWORD
SONARQUBE_TOKEN
KUBECONFIG

Secret Opcional (solo si el repo infra es privado):

INFRA_CLONE_TOKEN   # Token de Forgejo con permisos read:repository

Configuración del Repo Infra

Opción A: Repo Público (Recomendado)

  • En Forgejo: startcodex/infra → Settings → Make Repository Public
  • No requiere INFRA_CLONE_TOKEN
  • Más simple

Opción B: Repo Privado

  1. Crear Personal Access Token en Forgejo:
    • Settings → Applications → Generate New Token
    • Name: infra-workflows-readonly
    • Scopes: read:repository
  2. Agregar secret INFRA_CLONE_TOKEN en cada microservicio
  3. ⚠️ Requiere configuración adicional

Eso es todo! Los manifiestos de Kubernetes se generan automáticamente en el deploy.

3. (Opcional) Configurar Secrets

Tienes dos opciones para manejar secrets:

Opción A: Kubernetes Secrets (default, use_infisical: false)

Crear secrets directamente en Kubernetes:

kubectl create secret generic nombre-servicio-env \
  --from-literal=DATABASE_URL="postgresql://..." \
  --from-literal=API_KEY="..." \
  -n startcodex-test

Opción B: Infisical (use_infisical: true)

Si usas Infisical para secrets management, el workflow genera automáticamente el InfisicalSecret CRD:

with:
  use_infisical: true
  infisical_project_slug: startcodex-users-ms-mp-t7
  infisical_env_slug_test: staging        # Para branch test
  infisical_env_slug_prod: production     # Para branch main

Prerrequisitos:

  1. Infisical Operator instalado en el cluster
  2. Secret universal-auth-credentials creado en namespace default:
    kubectl create secret generic universal-auth-credentials \
      --from-literal=clientId="YOUR_CLIENT_ID" \
      --from-literal=clientSecret="YOUR_CLIENT_SECRET" \
      -n default
    

El workflow automáticamente:

  • Genera el InfisicalSecret con el project y environment correcto
  • El Infisical operator sincroniza los secrets al secret SERVICE_NAME-env
  • El deployment carga los secrets automáticamente

4. Commit y Deploy

git add .
git commit -m "Add CI/CD and K8s configuration"
git push origin dev

Esquema de Ramas

Rama Ambiente Deploy Automático Tag Docker
dev Development No -
test Testing YYYY.MM.DD.HHMM-test
main Production YYYY.MM.DD.HHMM

Pipeline CI/CD

  1. Test: Tests unitarios + cobertura
  2. Security: Escaneo de seguridad (Opengrep, Trivy, Grype, Syft)
  3. SonarQube: Análisis de código y Quality Gate
  4. Build: Build y push de imagen Docker (solo test/main)
  5. Deploy: Deploy a Kubernetes (solo test/main)

Security Scanning

Las herramientas de seguridad están integradas en los workflows existentes:

┌─────────────────────────────────────────────────────────────────────────┐
│                     PIPELINE DE SEGURIDAD                                │
├─────────────────────────────────────────────────────────────────────────┤
│                                                                          │
│  test ──► _analytics.yaml ──────────► _build-docker.yaml ──► deploy     │
│           │                           │                                  │
│           ├── Opengrep (SAST)         └── Trivy (imagen Docker)         │
│           └── SonarQube (Quality)         ├── CVEs                      │
│                                           ├── Secrets                    │
│                                           └── SBOM (CycloneDX)          │
│                                                                          │
└─────────────────────────────────────────────────────────────────────────┘
Herramienta Ubicación Qué analiza
Opengrep _analytics.yaml Código fuente: injection, XSS, secrets (100% open source)
SonarQube _analytics.yaml Código fuente: bugs, code smells, coverage
Trivy _build-docker.yaml Imagen Docker: CVEs, secrets, SBOM

Code Analytics (Opengrep + SonarQube)

jobs:
  analytics:
    uses: startcodex/infra/.forgejo/workflows/_analytics.yaml@v1
    with:
      service_name: tu-servicio-ms
      sonar_project_key: startcodex-tu-servicio-ms
      # project_type: auto       # auto, go, nodejs, react, nextjs, flutter, python
    secrets:
      SONARQUBE_TOKEN: ${{ secrets.SONARQUBE_TOKEN }}

Nota: Opengrep es un fork 100% open source de Semgrep con análisis avanzado (taint analysis inter-file) sin restricciones de licencia.

Build + Trivy (Docker Image Scan)

jobs:
  build:
    uses: startcodex/infra/.forgejo/workflows/_build-docker.yaml@v1
    with:
      service_name: tu-servicio-ms
      # Trivy scan de imagen
      trivy_enabled: true
      trivy_severity: 'CRITICAL,HIGH,MEDIUM'
      trivy_exit_code: '1'                # 0=warn, 1=fail (bloquea si hay vulns)
    secrets:
      REGISTRY_USER: ${{ secrets.REGISTRY_USER }}
      REGISTRY_PASSWORD: ${{ secrets.REGISTRY_PASSWORD }}

Artifacts Generados

  • opengrep-results-{service_name}: Reporte SARIF de Opengrep
  • trivy-image-{service_name}: Reporte JSON + SBOM (CycloneDX)

Configuración Recomendada

Por defecto, el pipeline bloquea si encuentra vulnerabilidades MEDIUM, HIGH o CRITICAL.

Parámetro Default Descripción
trivy_severity CRITICAL,HIGH,MEDIUM Severidades a detectar
trivy_exit_code 1 Bloquea el pipeline si encuentra vulns
opengrep_enabled true Habilita SAST en código

Para ambiente de desarrollo (solo warnings):

trivy_exit_code: '0'   # No bloquea, solo reporta

Recursos por Ambiente

Ambiente Replicas Memory CPU HPA
Dev 1 64Mi / 128Mi 50m / 100m 1-3
Test 2 256Mi / 512Mi 200m / 500m 2-5
Prod 3 512Mi / 1Gi 500m / 1000m 3-10

Personalización

Los archivos generados son totalmente editables:

Recursos: Editar k8s/overlays/{dev,test,production}/deployment-patch.yaml

HPA: Editar k8s/overlays/{dev,test,production}/hpa-patch.yaml

ConfigMap: Editar k8s/base/configmap.yaml

Ejemplos

Ver directorio examples/users-ms-example/ para ver un ejemplo completo.

Ejemplo: API REST simple

with:
  service_name: orders-api
  sonar_project_key: startcodex-orders-api
  service_type: http-only
  http_port: '8080'

Ejemplo: Servicio gRPC

with:
  service_name: payment-service
  sonar_project_key: startcodex-payment-service
  service_type: grpc-only
  grpc_port: '50051'
  # enable_health_checks se deshabilita automáticamente para grpc-only

Ejemplo: API sin health checks

with:
  service_name: worker-service
  sonar_project_key: startcodex-worker-service
  service_type: http-only
  http_port: '8080'
  enable_health_checks: false  # Deshabilita liveness y readiness probes

Ejemplo: API híbrida con Infisical

with:
  service_name: users-ms
  sonar_project_key: startcodex-users-ms
  service_type: both
  http_port: '8080'
  grpc_port: '50051'
  use_infisical: true
  infisical_project_slug: startcodex-users-ms-mp-t7
  infisical_env_slug_test: staging
  infisical_env_slug_prod: production

Tipos de Servicio Soportados

Configura el tipo de servicio con el parámetro service_type:

  1. http-only: Para APIs REST, webhooks, etc.

    • Solo puerto HTTP (default: 8080)
    • Health checks HTTP en /health y /ready (si enable_health_checks: true)
    • Ejemplo: APIs REST, microservicios web
  2. grpc-only: Para servicios gRPC puros

    • Solo puerto gRPC (default: 50051)
    • Health checks HTTP deshabilitados automáticamente
    • Ejemplo: Servicios backend internos
  3. both: Para servicios que exponen ambos protocolos

    • Ambos puertos configurables
    • Health checks HTTP en /health y /ready (si enable_health_checks: true)
    • Ejemplo: APIs híbridas REST + gRPC

Tipos de Service de Kubernetes

Configura el tipo de Service de Kubernetes con el parámetro k8s_service_type:

  1. ClusterIP (default): Acceso solo dentro del cluster

    • IP interna del cluster
    • No accesible desde fuera
    • Ideal para servicios internos
    • Ejemplo: Microservicios backend que solo hablan entre sí
  2. NodePort: Expone el servicio en un puerto del nodo

    • Accesible desde fuera del cluster en <NodeIP>:<NodePort>
    • Puerto asignado en rango 30000-32767
    • Útil para desarrollo/testing
    • Ejemplo: Servicios que necesitan acceso externo sin Load Balancer
  3. LoadBalancer: Provisiona un Load Balancer externo

    • Obtiene una IP externa del proveedor de cloud
    • Balanceo automático de carga
    • Ideal para producción con tráfico externo
    • Ejemplo: APIs públicas, servicios expuestos a internet

Ejemplo de uso:

with:
  service_type: http-only          # Tipo de protocolo (http/grpc)
  k8s_service_type: LoadBalancer   # Tipo de Service de K8s
  http_port: '8080'

Troubleshooting

Workflow no se ejecuta:

  • Verificar que existe .forgejo/workflows/ci-cd.yaml
  • Verificar nombre de rama: dev, test, o main

Error al clonar repo infra:

authentication required: Unauthorized
  • Solución 1: Hacer el repo infra público en Forgejo (Settings → Make Public)
  • Solución 2: Crear token de Forgejo y agregarlo como secret INFRA_CLONE_TOKEN

Error de Docker registry:

  • Verificar secrets REGISTRY_USER y REGISTRY_PASSWORD en Forgejo

Pods en CrashLoopBackOff:

kubectl logs -n <namespace> <pod-name>
kubectl get secret -n <namespace> nombre-servicio-env
  • Si enable_health_checks: true, verificar que /health y /ready endpoints estén implementados
  • Para servicios sin health checks HTTP, usar enable_health_checks: false

SonarQube falla:

  • Verificar variables SONARQUBE_HOST y SONAR_PROJECT_KEY
  • Verificar secret SONARQUBE_TOKEN

Migración de Ramas Antiguas

Si tu proyecto usa integration, staging, master:

# Renombrar localmente
git branch -m integration dev
git branch -m staging test
git branch -m master main

# Push nuevas ramas
git push -u origin dev
git push -u origin test
git push -u origin main

# Actualizar rama por defecto en Forgejo: Settings → Repository → Default Branch → main

Soporte

  • Issues en repo infra
  • Equipo DevOps/Platform