|
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
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 |
||
|---|---|---|
| .forgejo/workflows | ||
| examples | ||
| k8s | ||
| .gitignore | ||
| README.md | ||
| setup-microservice.sh | ||
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:
-
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)
-
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 funcionalesv1.0.0 → v1.1.0(MINOR): Nuevas features compatiblesv1.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) | ✅ Sí | forgejo-ci |
REGISTRY_PASSWORD |
Password del Docker registry (también para repos Go privados) | ✅ Sí | *** |
SONARQUBE_TOKEN |
Token de autenticación de SonarQube | ✅ Sí | squ_*** |
KUBECONFIG |
Configuración de kubectl (base64) | ✅ Sí | 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
~/.netrcantes dego 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
- Crear Personal Access Token en Forgejo:
- Settings → Applications → Generate New Token
- Name:
infra-workflows-readonly - Scopes:
read:repository
- Agregar secret
INFRA_CLONE_TOKENen cada microservicio - ⚠️ 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:
- Infisical Operator instalado en el cluster
- Secret
universal-auth-credentialscreado en namespacedefault: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
InfisicalSecretcon 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 | Sí | YYYY.MM.DD.HHMM-test |
| main | Production | Sí | YYYY.MM.DD.HHMM |
Pipeline CI/CD
- Test: Tests unitarios + cobertura
- Security: Escaneo de seguridad (Opengrep, Trivy, Grype, Syft)
- SonarQube: Análisis de código y Quality Gate
- Build: Build y push de imagen Docker (solo test/main)
- 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 Opengreptrivy-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:
-
http-only: Para APIs REST, webhooks, etc.- Solo puerto HTTP (default: 8080)
- Health checks HTTP en
/healthy/ready(sienable_health_checks: true) - Ejemplo: APIs REST, microservicios web
-
grpc-only: Para servicios gRPC puros- Solo puerto gRPC (default: 50051)
- Health checks HTTP deshabilitados automáticamente
- Ejemplo: Servicios backend internos
-
both: Para servicios que exponen ambos protocolos- Ambos puertos configurables
- Health checks HTTP en
/healthy/ready(sienable_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:
-
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í
-
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
- Accesible desde fuera del cluster en
-
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, omain
Error al clonar repo infra:
authentication required: Unauthorized
- Solución 1: Hacer el repo
infrapú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_USERyREGISTRY_PASSWORDen 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/healthy/readyendpoints estén implementados - Para servicios sin health checks HTTP, usar
enable_health_checks: false
SonarQube falla:
- Verificar variables
SONARQUBE_HOSTySONAR_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