Resumen del pipeline
4
Stages
6
Jobs totales
~6 min
Tiempo estimado
85%
Cobertura mínima
2
Entornos
Flujo de ejecucion
1 · Lint
ruff-check
Linting PEP-8 + imports + estilo
mypy-typecheck
Type checking estático (strict)
→
2 · Test
pytest-unit
Tests unitarios + cobertura XML
pytest-integration
Tests contra PostgreSQL 16 service
→
3 · Build
docker-build-push
Build multi-stage → push a ECR
→
4a · Staging
deploy-staging
ECS update-service automático
→
4b · Prod
deploy-production
ECS deploy con aprobación manual
Archivos generados
.gitlab-ci.yml — stages, variables & cache
YAML
1# NutriTrack API · GitLab CI Pipeline 2# Stack: FastAPI 3.12 · Poetry · Pytest · Docker → AWS ECS 3 4stages: 5 - lint 6 - test 7 - build 8 - deploy 9 10variables: 11 PYTHON_VERSION: "3.12" 12 POETRY_VERSION: "1.8.2" 13 AWS_REGION: "eu-west-1" 14 ECR_REPO: "nutritrack/api" 15 DOCKER_DRIVER: overlay2 16 DOCKER_TLS_CERTDIR: "/certs" 17 18.poetry-cache: &poetry-cache 19 cache: 20 key: 21 files: [poetry.lock] 22 paths: 23 - .venv/ 24 - .cache/pip/ 25 26.python-base: &python-base 27 image: python:${PYTHON_VERSION}-slim 28 before_script: 29 - pip install poetry==$POETRY_VERSION -q 30 - poetry config virtualenvs.in-project true 31 - poetry install --no-root -q
.gitlab-ci.yml — jobs lint & test
YAML
32ruff-check: 33 stage: lint 34 <<: *python-base 35 <<: *poetry-cache 36 script: 37 - poetry run ruff check . --output-format=gitlab 38 - poetry run ruff format --check . 39 40mypy-typecheck: 41 stage: lint 42 <<: *python-base 43 <<: *poetry-cache 44 script: 45 - poetry run mypy src/ --strict 46 47pytest-integration: 48 stage: test 49 <<: *python-base 50 <<: *poetry-cache 51 services: 52 - name: postgres:16-alpine 53 alias: db 54 variables: 55 POSTGRES_DB: nutritrack_test 56 POSTGRES_USER: ci 57 POSTGRES_PASSWORD: ci_secret 58 DATABASE_URL: postgresql://ci:ci_secret@db/nutritrack_test 59 script: 60 - poetry run pytest tests/ -v --cov=src 61 --cov-report=xml:coverage.xml 62 --cov-fail-under=85 63 coverage: '/TOTAL.*\s+([\d\.]+)%/' 64 artifacts: 65 reports: 66 coverage_report: 67 coverage_format: cobertura 68 path: coverage.xml
.gitlab-ci.yml — build Docker → ECR
YAML
70docker-build-push: 71 stage: build 72 image: docker:24 73 services: 74 - docker:24-dind 75 before_script: 76 - apk add --no-cache aws-cli 77 - aws ecr get-login-password --region $AWS_REGION 78 | docker login --username AWS --password-stdin 79 $AWS_ACCOUNT_ID.dkr.ecr.$AWS_REGION.amazonaws.com 80 script: 81 - IMAGE_URI=$AWS_ACCOUNT_ID.dkr.ecr.$AWS_REGION.amazonaws.com/$ECR_REPO 82 - docker build 83 --target production 84 --cache-from $IMAGE_URI:cache 85 --build-arg BUILDKIT_INLINE_CACHE=1 86 -t $IMAGE_URI:$CI_COMMIT_SHA 87 -t $IMAGE_URI:latest . 88 - docker push $IMAGE_URI:$CI_COMMIT_SHA 89 - docker push $IMAGE_URI:latest 90 rules: 91 - if: $CI_COMMIT_BRANCH == "main" 92 - if: $CI_COMMIT_BRANCH == "develop"
.gitlab-ci.yml — deploy staging & production
YAML
93.deploy-base: &deploy-base 94 image: amazon/aws-cli:2.15 95 stage: deploy 96 script: 97 - aws ecs update-service 98 --cluster $ECS_CLUSTER 99 --service $ECS_SERVICE 100 --force-new-deployment 101 --region $AWS_REGION 102 - aws ecs wait services-stable 103 --cluster $ECS_CLUSTER 104 --services $ECS_SERVICE 105 106deploy-staging: 107 <<: *deploy-base 108 variables: 109 ECS_CLUSTER: $ECS_CLUSTER_STAGING 110 ECS_SERVICE: $ECS_SERVICE_STAGING 111 environment: staging 112 rules: 113 - if: $CI_COMMIT_BRANCH == "develop" 114 115deploy-production: 116 <<: *deploy-base 117 variables: 118 ECS_CLUSTER: $ECS_CLUSTER_PROD 119 ECS_SERVICE: $ECS_SERVICE_PROD 120 environment: production 121 when: manual 122 allow_failure: false 123 rules: 124 - if: $CI_COMMIT_BRANCH == "main"
Variables de entorno requeridas
Configurar en GitLab → Settings → CI/CD → Variables (never in code)
| Variable | Descripcion | Alcance | Protegida |
|---|---|---|---|
| AWS_ACCESS_KEY_ID | Credencial IAM para ECR + ECS | todos | si |
| AWS_SECRET_ACCESS_KEY | Secret del usuario IAM ci-deployer | todos | si |
| AWS_ACCOUNT_ID | ID de cuenta AWS (12 dígitos) | todos | si |
| ECS_CLUSTER_STAGING | Nombre del cluster ECS de staging | staging | no |
| ECS_CLUSTER_PROD | Nombre del cluster ECS de produccion | prod | si |
| ECS_SERVICE_STAGING | Nombre del servicio ECS en staging | staging | no |
| ECS_SERVICE_PROD | Nombre del servicio ECS en produccion | prod | si |
Buenas practicas aplicadas
✓
Cache de dependencias Poetry
Key basada en poetry.lock, ahorra ~2 min por job
✓
Servicio PostgreSQL en contenedor
Tests de integracion reales, sin mocks de DB
✓
Docker layer cache de ECR
--cache-from para builds incremetales rapidos
✓
Deploy produccion manual
when: manual + allow_failure: false para produccion
✓
Secretos nunca en el codigo
Variables solo en GitLab Settings, marcadas como protected
✓
YAML anchors para DRY config
&python-base y &deploy-base compartidos entre jobs