ci: dockerise l'API + connexion DB et CORS configurables par env
- config.py: connexion SQL via DB_* (driver 18, auth SQL), fallback Windows local - main.py: origines CORS via CORS_ORIGINS - Dockerfile (python 3.12 + msodbcsql18) + workflow Gitea Actions (build/push image)
This commit is contained in:
@@ -0,0 +1,37 @@
|
|||||||
|
name: Build & Deploy
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: [main]
|
||||||
|
workflow_dispatch: {}
|
||||||
|
|
||||||
|
env:
|
||||||
|
IMAGE: git.nfteam.ovh/neckfire/datasentinel-api
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Build & push image
|
||||||
|
run: |
|
||||||
|
set -e
|
||||||
|
echo "${{ secrets.REGISTRY_PASSWORD }}" | docker login git.nfteam.ovh -u "${{ secrets.REGISTRY_USER }}" --password-stdin
|
||||||
|
docker build -t "${IMAGE}:latest" -t "${IMAGE}:${GITHUB_SHA::12}" .
|
||||||
|
docker push --all-tags "${IMAGE}"
|
||||||
|
echo "pushed ${IMAGE}"
|
||||||
|
|
||||||
|
- name: Notify ntfy (success/failure)
|
||||||
|
if: always()
|
||||||
|
run: |
|
||||||
|
if [ "${{ job.status }}" = "success" ]; then EMOJI="white_check_mark"; PRIO="default"; else EMOJI="rotating_light"; PRIO="high"; fi
|
||||||
|
curl -s \
|
||||||
|
-H "Authorization: Bearer ${{ secrets.NTFY_TOKEN }}" \
|
||||||
|
-H "Title: ${GITHUB_REPOSITORY} — ${{ job.status }}" \
|
||||||
|
-H "Priority: ${PRIO}" \
|
||||||
|
-H "Tags: ${EMOJI}" \
|
||||||
|
-H "Click: ${GITHUB_SERVER_URL}/${GITHUB_REPOSITORY}/actions" \
|
||||||
|
-d "${GITHUB_WORKFLOW} sur ${GITHUB_REF_NAME} (run #${GITHUB_RUN_NUMBER}) : ${{ job.status }}" \
|
||||||
|
"${{ secrets.NTFY_URL }}/${{ secrets.NTFY_TOPIC }}" || true
|
||||||
+21
@@ -0,0 +1,21 @@
|
|||||||
|
# API Data Sentinel — FastAPI + pyodbc (ODBC Driver 18 pour SQL Server).
|
||||||
|
FROM python:3.12-slim
|
||||||
|
|
||||||
|
# Pilote Microsoft ODBC 18 (le 17 n'est plus packagé sur Debian 12 / bookworm).
|
||||||
|
RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||||
|
curl gnupg ca-certificates apt-transport-https \
|
||||||
|
&& curl -sSL https://packages.microsoft.com/keys/microsoft.asc \
|
||||||
|
| gpg --dearmor -o /usr/share/keyrings/microsoft-prod.gpg \
|
||||||
|
&& echo "deb [arch=amd64,arm64 signed-by=/usr/share/keyrings/microsoft-prod.gpg] https://packages.microsoft.com/debian/12/prod bookworm main" \
|
||||||
|
> /etc/apt/sources.list.d/mssql-release.list \
|
||||||
|
&& apt-get update \
|
||||||
|
&& ACCEPT_EULA=Y apt-get install -y msodbcsql18 unixodbc-dev \
|
||||||
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
|
WORKDIR /app
|
||||||
|
COPY requirements.txt .
|
||||||
|
RUN pip install --no-cache-dir -r requirements.txt
|
||||||
|
COPY . .
|
||||||
|
|
||||||
|
EXPOSE 8000
|
||||||
|
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]
|
||||||
@@ -3,28 +3,50 @@
|
|||||||
# Data Sentinel | COYAUD Anthony | 2026
|
# Data Sentinel | COYAUD Anthony | 2026
|
||||||
# ============================================================
|
# ============================================================
|
||||||
|
|
||||||
|
import os
|
||||||
import pyodbc
|
import pyodbc
|
||||||
from contextlib import contextmanager
|
from contextlib import contextmanager
|
||||||
|
|
||||||
|
|
||||||
class Config:
|
def _build_connection_string() -> str:
|
||||||
# Chaîne de connexion SQL Server
|
"""
|
||||||
DB_CONNECTION_STRING = (
|
En déploiement (variables d'environnement présentes), on se connecte en
|
||||||
|
authentification SQL. Sinon, on garde la connexion Windows locale par défaut
|
||||||
|
(poste de dev).
|
||||||
|
"""
|
||||||
|
server = os.getenv("DB_SERVER")
|
||||||
|
if server:
|
||||||
|
driver = os.getenv("DB_DRIVER", "ODBC Driver 18 for SQL Server")
|
||||||
|
port = os.getenv("DB_PORT", "1433")
|
||||||
|
return (
|
||||||
|
f"Driver={{{driver}}};"
|
||||||
|
f"Server={server},{port};"
|
||||||
|
f"Database={os.getenv('DB_NAME', 'DataSentinel')};"
|
||||||
|
f"UID={os.getenv('DB_USER')};"
|
||||||
|
f"PWD={os.getenv('DB_PASSWORD')};"
|
||||||
|
"Encrypt=yes;TrustServerCertificate=yes;"
|
||||||
|
)
|
||||||
|
return (
|
||||||
"Driver={ODBC Driver 17 for SQL Server};"
|
"Driver={ODBC Driver 17 for SQL Server};"
|
||||||
"Server=LaptopCA\\SQLEXPRESS;"
|
"Server=LaptopCA\\SQLEXPRESS;"
|
||||||
"Database=DataSentinel;"
|
"Database=DataSentinel;"
|
||||||
"Trusted_Connection=yes;"
|
"Trusted_Connection=yes;"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class Config:
|
||||||
|
# Chaîne de connexion SQL Server (env en prod, Windows en local)
|
||||||
|
DB_CONNECTION_STRING = _build_connection_string()
|
||||||
|
|
||||||
# Paramètres API
|
# Paramètres API
|
||||||
API_TITLE = "Data Sentinel API"
|
API_TITLE = "Data Sentinel API"
|
||||||
API_VERSION = "1.0.0"
|
API_VERSION = "1.0.0"
|
||||||
API_DESCRIPTION = "API de monitoring de la qualité des données — XEFI"
|
API_DESCRIPTION = "API de monitoring de la qualité des données — XEFI"
|
||||||
|
|
||||||
# Sécurité JWT
|
# Sécurité JWT
|
||||||
SECRET_KEY = "data-sentinel-secret-change-in-prod"
|
SECRET_KEY = os.getenv("JWT_SECRET", "data-sentinel-secret-change-in-prod")
|
||||||
ALGORITHM = "HS256"
|
ALGORITHM = os.getenv("JWT_ALGORITHM", "HS256")
|
||||||
TOKEN_EXPIRE_MINUTES = 60
|
TOKEN_EXPIRE_MINUTES = int(os.getenv("JWT_EXPIRE_MINUTES", "60"))
|
||||||
|
|
||||||
|
|
||||||
# ----------------------------------------------------------------
|
# ----------------------------------------------------------------
|
||||||
|
|||||||
@@ -7,6 +7,8 @@
|
|||||||
# Swagger : http://localhost:8000/docs
|
# Swagger : http://localhost:8000/docs
|
||||||
# ============================================================
|
# ============================================================
|
||||||
|
|
||||||
|
import os
|
||||||
|
|
||||||
from fastapi import FastAPI, HTTPException, Query
|
from fastapi import FastAPI, HTTPException, Query
|
||||||
from fastapi.middleware.cors import CORSMiddleware
|
from fastapi.middleware.cors import CORSMiddleware
|
||||||
from typing import Optional
|
from typing import Optional
|
||||||
@@ -14,6 +16,14 @@ from datetime import date
|
|||||||
|
|
||||||
from config import Config, get_cursor
|
from config import Config, get_cursor
|
||||||
|
|
||||||
|
# Origines autorisées : depuis CORS_ORIGINS (séparées par des virgules) en prod,
|
||||||
|
# localhost par défaut en dev.
|
||||||
|
CORS_ORIGINS = [
|
||||||
|
o.strip()
|
||||||
|
for o in os.getenv("CORS_ORIGINS", "http://localhost:5173,http://localhost:3000").split(",")
|
||||||
|
if o.strip()
|
||||||
|
]
|
||||||
|
|
||||||
# ============================================================
|
# ============================================================
|
||||||
# Initialisation
|
# Initialisation
|
||||||
# ============================================================
|
# ============================================================
|
||||||
@@ -26,7 +36,7 @@ app = FastAPI(
|
|||||||
|
|
||||||
app.add_middleware(
|
app.add_middleware(
|
||||||
CORSMiddleware,
|
CORSMiddleware,
|
||||||
allow_origins = ["http://localhost:5173", "http://localhost:3000"],
|
allow_origins = CORS_ORIGINS,
|
||||||
allow_methods = ["GET"],
|
allow_methods = ["GET"],
|
||||||
allow_headers = ["*"],
|
allow_headers = ["*"],
|
||||||
)
|
)
|
||||||
|
|||||||
Reference in New Issue
Block a user