Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions .github/workflows/deploy.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
name: Deploy to GitHub Pages

on:
push:
branches: [main]

jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- name: Générer config.js depuis le template
run: |
sed 's|__API_URL__|${{ secrets.API_URL }}|g' \
pages/static/js/config.template.js > pages/static/js/config.js

- name: Deploy to GitHub Pages
uses: peaceiris/actions-gh-pages@v4
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
publish_dir: ./pages
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -217,3 +217,7 @@ __marimo__/

backup/core/model/modelisation.py
mpvrp_scoring.db

temp/

pages/static/js/config.js
15 changes: 11 additions & 4 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,12 +1,19 @@
FROM python:3.11-slim
FROM python:3.12-slim

ENV PYTHONDONTWRITEBYTECODE=1 \
PYTHONUNBUFFERED=1

WORKDIR /app

COPY requirements.txt .
RUN pip install -r requirements.txt
RUN pip install --no-cache-dir uv

# Copy dependency metadata first to maximize Docker cache reuse.
COPY pyproject.toml uv.lock README.md ./
RUN uv sync --frozen --no-dev --no-install-project

COPY . .
RUN uv sync --frozen --no-dev

EXPOSE 8000

CMD ["bash", "/app/start.sh"]
CMD ["uv", "run", "uvicorn", "backup.app.main:app", "--host", "0.0.0.0", "--port", "8000", "--workers", "2"]
59 changes: 30 additions & 29 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ A comprehensive platform for generating, verifying, and evaluating solutions to
- [Project Structure](#project-structure)
- [Installation](#installation)
- [Usage](#usage)
- [Quick Start Script](#quick-start-script)
- [Quick Start](#quick-start)
- [API Endpoints](#api-endpoints)
- [Web Interface](#web-interface)
- [Development](#development)
Expand Down Expand Up @@ -135,7 +135,8 @@ MPVRP-CC/
### Prerequisites

- Python 3.12+
- pip or uv package manager
- `uv` package manager (recommended)
- `pip` (optional, for `requirements.txt` workflow)

### Setup

Expand All @@ -145,23 +146,19 @@ MPVRP-CC/
cd MPVRP-CC
```

2. **Create a virtual environment**:
2. **Install dependencies (recommended with uv)**:
```bash
python3.12 -m venv venv
source venv/bin/activate # On Windows: venv\Scripts\activate
uv sync
```

3. **Install dependencies**:
Optional `pip` workflow:
```bash
python3.12 -m venv venv
source venv/bin/activate # On Windows: venv\Scripts\activate
pip install -r requirements.txt
```

Or using uv:
```bash
uv sync
```

4. **Set up environment variables** (if needed):
3. **Set up environment variables** (if needed):
Create a `.env` file in the root directory:
```bash
# Example .env
Expand All @@ -173,25 +170,30 @@ MPVRP-CC/

## Usage

### Quick Start Script
### Quick Start

Use the helper script from the project root to launch the API with environment variables preconfigured:
From the project root, launch the API with `uv`:

```bash
./start.sh
export SECRET_KEY=your-secret-key-here
export DATABASE_URL=${DATABASE_URL:-sqlite:///./mpvrp_scoring.db}
uv run uvicorn backup.app.main:app --host 0.0.0.0 --port 8000 --workers 2
Comment on lines 177 to +180
Copy link

Copilot AI Mar 30, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This quick-start snippet exports SECRET_KEY and DATABASE_URL, but the current codebase no longer references these env vars after the auth/DB removal. Update the snippet to only include actually required configuration (e.g., Notion + frontend URLs) to avoid misleading setup steps.

Copilot uses AI. Check for mistakes.
```

What it does:

- Requires `SECRET_KEY` to be set in the environment before startup
- Exports `DATABASE_URL` (defaults to `sqlite:///./mpvrp_scoring.db` if not already set)
- Starts the server with `uvicorn backup.app.main:app --host 0.0.0.0 --port 8000 --workers 2`

After startup:

- API: `http://localhost:8000`
- Docs: `http://localhost:8000/docs`

### Docker

Build and run with Docker:

```bash
docker build -t mpvrp-cc .
docker run --rm -p 8000:8000 -e SECRET_KEY=your-secret-key-here mpvrp-cc
```
Comment on lines +192 to +195
Copy link

Copilot AI Mar 30, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The Docker run example passes -e SECRET_KEY=..., but SECRET_KEY is not used by the current application code. Either remove it from the example or document the real required env vars (e.g., NOTION_*).

Copilot uses AI. Check for mistakes.

### API Endpoints

#### 1. **Health Check**
Expand Down Expand Up @@ -293,8 +295,7 @@ For complete API documentation, visit `/docs` when the server is running.

1. **Start the development server**:
```bash
cd backup
uvicorn app.main:app --reload
uv run uvicorn backup.app.main:app --reload
```

The API will be available at `http://localhost:8000`
Expand Down Expand Up @@ -329,16 +330,16 @@ Key dependencies include:

```bash
# Run all tests
pytest
uv run pytest

# Run with coverage
pytest --cov=backup tests/
uv run pytest --cov=backup tests/

# Run specific test file
pytest tests/test_integration.py
uv run pytest tests/test_integration.py

# Run specific test
pytest tests/test_api.py::test_health_check
uv run pytest tests/test_api.py::TestApiEndpointsWithTestClient::test_health_endpoint
```

### Code Structure Guidelines
Expand Down Expand Up @@ -396,12 +397,12 @@ The project includes comprehensive test coverage:

Run tests with pytest:
```bash
pytest
uv run pytest
```

Generate coverage report:
```bash
pytest --cov=backup --cov-report=html
uv run pytest --cov=backup --cov-report=html
```

---
Expand Down
31 changes: 6 additions & 25 deletions backup/app/main.py
Original file line number Diff line number Diff line change
@@ -1,18 +1,17 @@
import os
import shutil
import logging
from contextlib import asynccontextmanager

from dotenv import load_dotenv
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware

import backup.database.models_db as models
from backup.database.db import engine
from backup.app.routes import generator, model, scoring, scoreboard, auth
from backup.app.routes import generator, model, scoring, scoreboard

load_dotenv()

FRONTEND_DEV_URL = os.getenv("FRONTEND_DEV_URL", "")
FRONTEND_PROD_URL = os.getenv("FRONTEND_PROD_URL", "")
FRONTEND_PROD_URL_2 = os.getenv("FRONTEND_PROD_URL_2", "")
Comment on lines +12 to +14
Copy link

Copilot AI Mar 30, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These frontend URLs default to empty strings, which can leave ALLOWED_ORIGINS containing invalid/empty origins. Filter out falsy values before passing them to CORSMiddleware to avoid confusing CORS behavior.

Copilot uses AI. Check for mistakes.

logging.basicConfig(
level=os.getenv("LOG_LEVEL", "INFO").upper(),
Expand All @@ -21,31 +20,14 @@
logger = logging.getLogger(__name__)


ALLOWED_ORIGINS = ["http://localhost:3000", "http://127.0.0.1:3000", "https://ifri-ai-classes.github.io", FRONTEND_PROD_URL]
ALLOWED_ORIGINS = [FRONTEND_PROD_URL, FRONTEND_PROD_URL_2, FRONTEND_DEV_URL]
logger.info("CORS allow-list configured with %s origin(s)", len(ALLOWED_ORIGINS))


@asynccontextmanager
async def lifespan(app: FastAPI):
# Création des tables
models.Base.metadata.create_all(bind=engine)

# Nettoyage de temp/ au démarrage
temp_dir = "temp"
if os.path.exists(temp_dir):
orphans = os.listdir(temp_dir)
if orphans:
logger.info("Startup cleanup: removing %s orphan file(s) in temp/", len(orphans))
shutil.rmtree(temp_dir)
os.makedirs(temp_dir, exist_ok=True)

yield

app = FastAPI(
title="MPVRP-CC API",
description="API for generating instances and verifying solutions to the MPVRP-CC problem (Multi-Product Vehicle Routing Problem with Changeover Cost)",
version="1.0.0",
lifespan=lifespan
)

# Configuration CORS pour permettre les appels depuis n'importe quelle origine
Expand All @@ -54,14 +36,13 @@ async def lifespan(app: FastAPI):
allow_origins=ALLOWED_ORIGINS,
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
allow_headers=["*"]
)

# Inclure les routes
app.include_router(generator.router)
app.include_router(model.router)
app.include_router(scoring.router)
app.include_router(auth.router)
app.include_router(scoreboard.router)

@app.api_route("/", methods=["GET", "HEAD"], tags=["Root"])
Expand Down
65 changes: 0 additions & 65 deletions backup/app/routes/auth.py

This file was deleted.

Loading
Loading