DataFlow AI · SaaS B2B ⚡ Escrito en Rust 100x mas rapido que pip

Migracion a uv
Package Manager

Guia completa para migrar el backend Python de DataFlow AI a uv: entornos reproducibles, CI/CD optimizado y Docker sin dolor.

4 min Ahorro en CI/CD por build
uv.lock Reproducibilidad garantizada
60% Reduccion imagen Docker
1 sprint Tiempo de migracion
Diagnostico inicial
😨
CI lento: 4-6 min
pip install sin cache tarda hasta 6 minutos por build en GitHub Actions
🔓
Sin lockfile
"En mi maquina funciona" — versions distintas entre los 4 devs
📸
Docker 1.2 GB
Sin cache de dependencias: imagen enorme reconstruida completa en cada deploy
🔄
Python 3.10 vs 3.11
Mix de versiones entre devs sin pinning centralizado
CI: 45 segundos
uv con cache global: 10-100x mas rapido que pip en cada build
🔒
uv.lock en git
Lockfile exacto + .python-version: misma instalacion en todos los entornos
📦
Docker ~480 MB
Multi-stage Dockerfile con uv: solo el venv copiado al runtime
📌
Python 3.12 pinado
uv python pin 3.12 en .python-version — consistente en todo el equipo
Plan de migracion — 4 pasos
1
Instalar uv y configurar el proyecto
Instalacion del binario y configuracion inicial del repositorio dataflow-ai
bash
# 1. Instalar uv (macOS/Linux — sin necesitar Python)
curl -LsSf https://astral.sh/uv/install.sh | sh

# 2. Verificar instalacion
uv --version
# uv 0.4.x

# 3. En el repo dataflow-ai — inicializar proyecto uv
#    (mantiene requirements.txt existente temporalmente)
cd dataflow-ai/
uv init --no-package .

# 4. Pinear Python 3.12 para todo el equipo
uv python pin 3.12
# Crea .python-version con "3.12"

# 5. uv descarga automaticamente Python 3.12 si no esta instalado
uv python install 3.12
2
Migrar dependencias y generar lockfile
Del requirements.txt anterior al pyproject.toml moderno con uv.lock
toml — pyproject.toml
[project]
name = "dataflow-ai"
version = "0.3.1"
description = "SaaS B2B de analisis de datos con IA para pymes"
requires-python = ">=3.12"
dependencies = [
    "fastapi>=0.110.0,<1.0",
    "uvicorn[standard]>=0.29.0",
    "pandas>=2.2.0",
    "anthropic>=0.28.0",
    "pydantic>=2.7.0",
    "sqlalchemy>=2.0.0",
    "psycopg2-binary>=2.9.9",
]

[project.optional-dependencies]
dev = [
    "pytest>=8.0.0",
    "pytest-cov>=5.0.0",
    "black>=24.0.0",
    "ruff>=0.4.0",
    "mypy>=1.10.0",
    "httpx>=0.27.0",  # TestClient de FastAPI
]

[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"
bash — generar lockfile
# Sincronizar todas las dependencias (crea .venv + uv.lock)
uv sync --all-extras
# Resuelto en ~1.8s vs ~45s con pip

# Commit del lockfile (obligatorio para reproducibilidad)
git add pyproject.toml uv.lock .python-version
git commit -m "chore: migrar a uv package manager"

# Verificar arbol de dependencias
uv tree
3
GitHub Actions con cache uv
CI/CD de 6 min a ~45 seg gracias al cache de uv entre builds
yaml — .github/workflows/ci.yml
name: CI

on: [push, pull_request]

jobs:
  test:
    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@v4

      - name: Instalar uv (con cache)
        uses: astral-sh/setup-uv@v2
        with:
          enable-cache: true
          cache-dependency-glob: "uv.lock"

      - name: Instalar Python 3.12
        run: uv python install

      - name: Instalar dependencias (frozen)
        run: uv sync --frozen --all-extras
                # --frozen: usa uv.lock exacto, sin resolver

      - name: Linting con ruff
        run: uv run ruff check .

      - name: Formato con black
        run: uv run black --check .

      - name: Tests con cobertura
        run: uv run pytest --cov=src --cov-report=xml -v

      - name: Type check con mypy
        run: uv run mypy src/
4
Dockerfile multi-stage optimizado
Imagen de produccion que copia solo el .venv al runtime stage: de 1.2 GB a ~480 MB
dockerfile — Dockerfile
# ====== BUILD STAGE ======
FROM python:3.12-slim AS builder

# Copiar binario uv (no requiere Rust ni cargo)
COPY --from=ghcr.io/astral-sh/uv:0.6 /uv /usr/local/bin/uv

WORKDIR /app

# Instalar dependencias (cacheado si pyproject.toml/uv.lock no cambian)
COPY pyproject.toml uv.lock ./
RUN uv sync --frozen --no-dev --no-editable
# Solo produccion, sin dev tools

# ====== RUNTIME STAGE ======
FROM python:3.12-slim

WORKDIR /app

# Copiar SOLO el venv del builder (sin uv, sin pip, limpio)
COPY --from=builder /app/.venv .venv
COPY src/ ./src/

# Activar venv via PATH
ENV PATH="/app/.venv/bin:$PATH"
ENV PYTHONDONTWRITEBYTECODE=1
ENV PYTHONUNBUFFERED=1

EXPOSE 8000
CMD ["uvicorn", "src.main:app", "--host", "0.0.0.0", "--port", "8000"]
pip vs uv — comparativa DataFlow AI
Metrica pip + requirements.txt uv + uv.lock Mejora
Tiempo install CI (cold) 4 min 52 seg 1 min 05 seg 4.5x mas rapido
Tiempo install CI (cache) 4 min 12 seg 18 seg 14x mas rapido
Reproducibilidad No garantizada 100% via uv.lock Determinista
Tamano imagen Docker 1.2 GB ~480 MB 60% menos
Conflictos de version Frecuentes Ninguno Eliminados
Gestion Python version Manual / pyenv uv python pin Integrado
Compatibilidad pip Nativa Compatible (uv pip) Sin rotura
Entregables del sprint de migracion
Checklist de migracion
  • uv instalado en maquinas de los 4 devs
  • pyproject.toml con deps + dev extras
  • uv.lock commiteado al repositorio
  • .python-version con 3.12
  • GitHub Actions actualizado con setup-uv
  • Dockerfile multi-stage con uv
  • requirements.txt eliminado del repo
  • CONTRIBUTING.md actualizado con uv run
fastapi pandas anthropic-sdk pytest ruff
Timeline (1 sprint)
Lunes Instalar uv + pyproject.toml + uv.lock en rama feature/uv
Martes Actualizar GitHub Actions + validar CI en todas las PRs abiertas
Miercoles Dockerfile multi-stage + medir reduccion de tamano
Jueves Onboarding del equipo: uv run en lugar de activar venv
Viernes Merge a main + eliminar requirements.txt + actualizar docs