GitLab CI
pipeline-cicd-gitlab-circleci FastAPI · Python 3.12 · AWS ECS

Pipeline CI/CD — NutriTrack API

Proyecto: nutritrack/api Stack: FastAPI + Poetry + Pytest + Docker Deploy: AWS ECR → ECS Fargate Entornos: staging (auto) · production (manual)
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
auto
mypy-typecheck
Type checking estático (strict)
auto
2 · Test
pytest-unit
Tests unitarios + cobertura XML
auto
pytest-integration
Tests contra PostgreSQL 16 service
auto
3 · Build
docker-build-push
Build multi-stage → push a ECR
main/develop
4a · Staging
deploy-staging
ECS update-service automático
auto
4b · Prod
deploy-production
ECS deploy con aprobación manual
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