Files
ObsiGate/Dockerfile
T
bruno 634ba8a272
CI / lint (push) Successful in 2m43s
CI / security (push) Successful in 1m33s
CI / test (push) Canceled after 0s
CI / build (push) Canceled after 0s
CI / e2e (push) Canceled after 0s
feat: éditeur tableur — grille A → Z par blocs, barre de menus Sheets, panneau de couleurs, création .xlsx (#180 → #186)
Restaure et termine le lot tableur resté non committé. Il n'existait que dans un
`git stash` (24 fichiers suivis) et en fichiers non suivis (menus.js, formula.js,
color-picker.js, tests, fiches) : la 2.53.3 livrée ne le contenait donc pas. Le
stash, créé avant le commit BUG-108, n'a jamais été restauré.

#180 Redimensionnement au curseur (en-tête de bord miroité + classe de repaint),
grille thémée sur les 15 thèmes et les modes contraste élevé / sépia, menu
Fichier au niveau des onglets, barre épinglée pleine largeur.

#181 Modèle de saisie Google Sheets : sélection ≠ édition (caret masqué sans
quitter contenteditable, double-clic / F2 / première frappe qui remplace,
Entrée contextuelle, Échap qui restaure) + inventaire priorisé des écarts.

#182 Désélection fiable (clic simple sans dépendre du focus), contours de plage
non empilés (sélecteur de classes sans point), couleurs texte/fond sur une
plage, clic droit qui préserve la sélection multiple.

#183 Panneau de couleurs façon Google Sheets : palette 8 × 10, STANDARD,
PERSONNALISÉ, coche selon la luminance, sortie `#rrggbb` (une valeur HSL était
rejetée par normHex).

#184 Peinture de format complète (toutes propriétés, source sans format =
réinitialisation), sélection multi-lignes/colonnes depuis les marges, grille
étendue : colonnes A → Z d'emblée, lignes ajoutées PAR BLOCS DE 100 au
défilement jusqu'à 1000 — matérialiser 1000 lignes d'un coup = ~26 000 cellules
câblées par feuille, ce qui épuisait le tas de la suite JSDOM ; index de
cellules `ref → td`, court-circuits formule/styles, marqueur data-wired.

#185 Barre de menus : les 10 menus Google Sheets (161 entrées, 125 câblées, 36
annoncées indisponibles), ruban façon Sheets, grille unie 1 px dérivée du thème.

#186 « Créer un fichier » propose .xlsx et construit un vrai classeur OPC
(openpyxl) au lieu d'une charge utile texte illisible.

Corrections trouvées en restaurant et en exerçant le lot :
- fuite mémoire : écouteur `click` anonyme posé sur #content-area à chaque
  rendu, jamais retiré — sa fermeture retenait la grille précédente en entier ;
- sorties Markdown / HTML / Imprimer de la barre de menus inertes
  (`data-xlsx-export` jamais réparti, seul `data-xlsx-action` l'était) ;
- collision de classe `.xlsx-structure-menu` entre la barre de menus et le menu
  Structure de la barre d'outils (toute requête tombait sur un nœud masqué) ;
- curseur col/row-resize absent quand le pointeur est sur la table elle-même ;
- l'export emportait les lignes et colonnes vides du quadrillage (CSV, Markdown,
  HTML, impression) ;
- clic extérieur avalé par la grâce de 250 ms du menu contextuel (destinée au
  seul appui long tactile) ;
- une entrée indisponible laissait la barre de menus ouverte.

Tests : pytest 1595 passés / 2 ignorés ; ruff et mypy 0 erreur ; bandit 0 ;
33 suites frontend vertes (xlsx-viewer 163/163, xlsx-menus 19/19,
xlsx-formula 14/14) ; E2E complet 132 passés / 12 ignorés ; E2E xlsx-viewer
19/19.
2026-10-08 12:00:15 -04:00

54 lines
1.9 KiB
Docker

# ObsiGate — Multi-platform Docker image
# Stage 1: Install Python dependencies (with build tools)
FROM python:3.11-slim AS builder
RUN apt-get update \
&& apt-get install -y --no-install-recommends gcc libffi-dev libc6-dev \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/*
WORKDIR /build
COPY backend/requirements.txt .
RUN pip install --no-cache-dir --prefix=/install -r requirements.txt
# Stage 2: Final lightweight image (no build tools)
FROM python:3.11-slim
LABEL maintainer="Bruno Beloeil" \
description="ObsiGate — lightweight web interface for Obsidian vaults"
WORKDIR /app
# Copy installed packages from builder stage
COPY --from=builder /install /usr/local
# WeasyPrint runtime dependencies
RUN apt-get update \
&& apt-get install -y --no-install-recommends libpango-1.0-0 libpangocairo-1.0-0 shared-mime-info fonts-noto-color-emoji \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/*
# Copy application code
COPY backend/ ./backend/
COPY frontend/ ./frontend/
# Version livrée : `VERSION` (racine du dépôt) est la source unique de vérité —
# copié dans l'image, jamais un numéro codé en dur. `backend/version.py` le lit
# et /api/health l'expose (header + boîte À propos).
COPY VERSION ./VERSION
# Create non-root user for security + data directory for auth persistence
# Using explicit UID/GID 1000 to match common host user and docker-compose settings
RUN groupadd -g 1000 obsigate && useradd -u 1000 -g obsigate -d /app -s /sbin/nologin obsigate \
&& mkdir -p /app/data \
&& chmod 777 /app/data \
&& chown -R obsigate:obsigate /app
USER obsigate
EXPOSE 8080
HEALTHCHECK --interval=30s --timeout=5s --start-period=10s --retries=3 \
CMD python -c "import urllib.request; urllib.request.urlopen('http://localhost:8080/api/health')" || exit 1
CMD ["uvicorn", "backend.main:app", "--host", "0.0.0.0", "--port", "8080"]