Skip to content

Commit 93aa645

Browse files
committed
Initial commit: Complete MLOps project setup
0 parents  commit 93aa645

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

55 files changed

+2476
-0
lines changed

.dockerignore

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
# Excluir archivos de caché y bytecode de Python
2+
__pycache__/
3+
*.pyc
4+
*.log
5+
6+
# Excluir artefactos generados, ya que se manejan con volúmenes
7+
artifacts/
8+
9+
# Excluir configuraciones y caché de herramientas de desarrollo
10+
.vscode/
11+
.idea/
12+
13+
# Excluir entornos virtuales de Python
14+
.venv/
15+
venv/
16+
env/
17+
18+
# Excluir documentación y archivos de CI/CD
19+
.github/
20+
docs/
21+
README.md
22+
DEVELOPMENT_GUIDE.md # Si estuviera en la raíz
23+
24+
# Excluir tests, ya que se montan como volumen para el servicio 'tester'
25+
tests/

.github/workflows/ci-cd.yml

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
# .github/workflows/ci-cd.yml
2+
3+
name: CI/CD - Build and Deploy to Google Cloud
4+
5+
# 1. Control de Concurrencia: Evita despliegues simultáneos.
6+
concurrency:
7+
group: ${{ github.workflow }}-${{ github.ref }}
8+
cancel-in-progress: true
9+
10+
on:
11+
push:
12+
branches:
13+
- main
14+
# Opcional: Ejecutar también con tags para releases
15+
tags:
16+
- 'v*.*.*'
17+
18+
jobs:
19+
test-and-build:
20+
# Cambiamos el nombre para reflejar la nueva función
21+
name: Continuous Integration - Test and Build
22+
runs-on: ubuntu-latest
23+
24+
permissions:
25+
contents: 'read'
26+
id-token: 'write'
27+
28+
steps:
29+
- name: Checkout repository
30+
uses: actions/checkout@v3
31+
32+
# 2. Caché para dependencias de Python
33+
- name: Cache Python dependencies
34+
uses: actions/cache@v3
35+
with:
36+
path: ~/.cache/pip
37+
key: ${{ runner.os }}-pip-${{ hashFiles('**/requirements/*.txt') }}
38+
restore-keys: |
39+
${{ runner.os }}-pip-
40+
41+
- name: Set up Docker Buildx
42+
uses: docker/setup-buildx-action@v2
43+
44+
- name: Run Model Training
45+
run: |
46+
pip install -r requirements/dev.txt
47+
python breast_cancer_app/model/train_model.py
48+
49+
- name: Run Integration Tests
50+
run: |
51+
docker-compose up -d api
52+
docker-compose run --rm tester
53+
54+
- name: Build Docker Images (no push)
55+
uses: docker/build-push-action@v4
56+
with:
57+
context: .
58+
# Construye todas las etapas, pero no sube las imágenes
59+
push: false
60+
# Especificamos los targets para que se construyan
61+
# y se almacenen en la caché local de la ejecución.
62+
target: |
63+
api
64+
frontend
65+
66+
# --- El job de despliegue está comentado por defecto ---
67+
# deploy:
68+
# name: Deploy to Cloud Run
69+
# needs: test-and-build
70+
# runs-on: ubuntu-latest
71+
# if: github.ref == 'refs/heads/main' # Only deploy on push to main
72+
73+
# permissions:
74+
# contents: 'read'
75+
# id-token: 'write'
76+
77+
# steps:
78+
# - name: Authenticate to Google Cloud
79+
# uses: 'google-github-actions/auth@v1'
80+
# with:
81+
# workload_identity_provider: ${{ secrets.GCP_WORKLOAD_IDENTITY_PROVIDER }}
82+
# service_account: ${{ secrets.GCP_SERVICE_ACCOUNT }}
83+
84+
# - name: Deploy API to Cloud Run
85+
# uses: 'google-github-actions/deploy-cloudrun@v1'
86+
# with:
87+
# service: ${{ env.API_SERVICE_NAME }}
88+
# region: ${{ env.REGION }}
89+
# image: ${{ env.GAR_LOCATION }}-docker.pkg.dev/${{ env.PROJECT_ID }}/${{ env.API_REPOSITORY }}/${{ env.API_SERVICE_NAME }}:main
90+
91+
# - name: Deploy Frontend to Cloud Run
92+
# uses: 'google-github-actions/deploy-cloudrun@v1'
93+
# with:
94+
# service: ${{ env.FRONTEND_SERVICE_NAME }}
95+
# region: ${{ env.REGION }}
96+
# image: ${{ env.GAR_LOCATION }}-docker.pkg.dev/${{ env.PROJECT_ID }}/${{ env.FRONTEND_REPOSITORY }}/${{ env.FRONTEND_SERVICE_NAME }}:main
97+
# env_vars: |
98+
# API_URL=https://$(gcloud run services describe ${{ env.API_SERVICE_NAME }} --platform managed --region ${{ env.REGION }} --format 'value(status.url)' | sed 's|https://||')

.gitignore

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
# Entornos virtuales de Python
2+
.venv/
3+
venv/
4+
env/
5+
6+
# Archivos de caché y compilados de Python
7+
__pycache__/
8+
*.pyc
9+
*.pyo
10+
*.pyd
11+
12+
# Archivos generados por el entrenamiento del modelo
13+
# Estos se crean al ejecutar el script y no deben ser versionados
14+
artifacts/
15+
16+
# Archivos de log
17+
*.log
18+
19+
# Configuraciones de IDE/Editor
20+
.vscode/
21+
.idea/
22+
23+
# Archivos de sistema operativo
24+
.DS_Store
25+
Thumbs.db
26+
27+
# Archivos de distribución/build de Python
28+
dist/
29+
build/
30+
*.egg-info/

Dockerfile

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
# === Etapa 1: Base ===
2+
# Imagen común con Python y dependencias base.
3+
FROM python:3.9-slim-bullseye AS base
4+
WORKDIR /app
5+
# Instala dependencias del sistema y limpia la caché para mantener la imagen ligera.
6+
RUN apt-get update && apt-get install -y curl && rm -rf /var/lib/apt/lists/*
7+
8+
# Copia e instala las dependencias comunes.
9+
COPY requirements/common.txt .
10+
RUN pip install --no-cache-dir -r common.txt
11+
12+
13+
# === Etapa 2: Builder de Dependencias de Desarrollo ===
14+
# Etapa para instalar TODAS las dependencias (dev, api, frontend).
15+
# Usada por 'training' y 'tester' en docker-compose.
16+
FROM base AS dev_builder
17+
COPY requirements/ ./requirements/
18+
RUN pip install --no-cache-dir -r requirements/dev.txt
19+
20+
21+
# === Etapa 3: Imagen Final de la API ===
22+
# Imagen de producción para la API. Ligera y específica.
23+
FROM base AS api
24+
# Copia las dependencias instaladas de la etapa 'dev_builder'.
25+
COPY --from=dev_builder /usr/local/lib/python3.9/site-packages /usr/local/lib/python3.9/site-packages
26+
# ¡CORRECCIÓN CLAVE! Copia también los ejecutables como 'waitress-serve'.
27+
COPY --from=dev_builder /usr/local/bin /usr/local/bin
28+
# Copia solo el código de la API. La imagen NO debe contener artefactos.
29+
COPY breast_cancer_app/api /app/breast_cancer_app/api
30+
EXPOSE 5000
31+
# Comando para ejecutar la API en producción con Waitress.
32+
CMD ["waitress-serve", "--host=0.0.0.0", "--port=5000", "breast_cancer_app.api.api:app"]
33+
34+
# === Etapa 5: Imagen Final del Frontend ===
35+
# Imagen de producción para el Frontend.
36+
FROM base AS frontend
37+
COPY --from=dev_builder /usr/local/lib/python3.9/site-packages /usr/local/lib/python3.9/site-packages
38+
# ¡CORRECCIÓN CLAVE! Copia también los ejecutables como 'streamlit'.
39+
COPY --from=dev_builder /usr/local/bin /usr/local/bin
40+
COPY breast_cancer_app/frontend /app/breast_cancer_app/frontend
41+
EXPOSE 8501
42+
CMD ["streamlit", "run", "breast_cancer_app/frontend/frontend.py", "--server.port=8501", "--server.address=0.0.0.0"]
43+
44+
45+
# === Etapa 6: Imagen de Desarrollo ===
46+
# Imagen que contiene todo el código y todas las dependencias.
47+
# Ideal para los servicios 'training' y 'tester'.
48+
FROM base AS dev
49+
COPY --from=dev_builder /usr/local/lib/python3.9/site-packages /usr/local/lib/python3.9/site-packages
50+
# ¡CORRECCIÓN CLAVE! Copia también los ejecutables como 'pytest'.
51+
COPY --from=dev_builder /usr/local/bin /usr/local/bin
52+
COPY . .

0 commit comments

Comments
 (0)