feat(deploy): install silencieuse (dashboard) + MAJ GPO clients Léa + procédure Julien — 2026-07-06
Some checks failed
tests / Lint (ruff + black) (push) Failing after 1m58s
tests / Tests unitaires (sans GPU) (push) Failing after 2m8s
tests / Tests sécurité (critique) (push) Has been skipped

Deux canaux de déploiement des clients Léa, en s'appuyant sur l'installeur EXE
v1.0.2 existant (per-user, upgrade-safe, mode /VERYSILENT /CONFIG=).

- Route dashboard `GET /api/fleet/installer` (web_dashboard/app.py, insertion pure,
  125 lignes, 0 suppression) : sert un ZIP {EXE + install_silencieux.bat + enroll.txt
  (SERVER_URL/token injectés via _resolve_public_server_url) + LISEZMOI} pour un poste
  NEUF. L'EXE génère lui-même le machine_id → pas de pré-enregistrement (distinct de
  la voie ZIP download_agent_package). Tri EXE en semver (1.0.10 > 1.0.2). Testée e2e.
- deploy/installer/silent/ : lanceur d'install silencieuse + gabarit enroll + notice.
- deploy/gpo/Deploy-LeaUpdate.ps1 : MAJ upgrade-safe via GPO **logon script user-context**
  (install per-user invisible au contexte SYSTEM). Détection version = **DisplayVersion
  du registre HKCU** (primaire pour install EXE ; le config.txt EXE ne porte PAS la
  version — vérifié sur poste réel), fallback RPA_AGENT_VERSION (installs ZIP).
  Comparaison semver, idempotent, journalisation best-effort silencieuse, non bloquant
  à l'ouverture de session. Options -DryRun / -TargetVersionOverride / -LogShareOverride.
  **Validé sur poste réel .11 (Windows PowerShell 5.1)** : branche « déjà à jour » et
  branche « MAJ requise » (DryRun, 0 install), détection = 1.0.2.
- docs/PROCEDURE_DEPLOIEMENT_LEA_JULIEN.md : procédure (poste neuf / MAJ manuelle / GPO / rollback).
- EXE binaire jamais versionné (deploy/installer/releases/.gitignore).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Dom
2026-07-06 10:22:34 +02:00
parent f4bef1de37
commit 48b1fc2800
8 changed files with 547 additions and 0 deletions

View File

@@ -0,0 +1,181 @@
<#
.SYNOPSIS
Met a jour l'agent Lea (installe per-user) via un script d'OUVERTURE DE SESSION GPO.
.DESCRIPTION
============================================================================
A DEPLOYER EN : User Configuration > Policies > Windows Settings >
Scripts (Logon/Logoff) > Logon.
ET PAS EN "Computer > Startup".
============================================================================
RAISON (non negociable) : l'installeur Lea est PER-USER
(%LOCALAPPDATA%\Programs\Lea, cle de desinstallation sous HKCU). Un script de
DEMARRAGE MACHINE tourne en contexte SYSTEM : il ne verrait NI l'installation
NI HKCU du collaborateur -> il ne mettrait jamais rien a jour. Le contexte
UTILISATEUR est donc obligatoire.
Le script, a chaque ouverture de session :
1. Detecte la version installee (DisplayVersion de la cle de desinstallation
Inno dans HKCU — primaire pour un install EXE ; fallback RPA_AGENT_VERSION
du config.txt, present uniquement sur les installs via ZIP).
2. La compare a la version cible (comparaison semver correcte :
1.0.2 < 1.0.10, contrairement a une comparaison de chaines).
3. Si plus ancienne : lance l'installeur en mode SILENCIEUX + UPGRADE-SAFE
(SANS /CONFIG -> machine_id, serveur et token du poste PRESERVES).
4. Journalise le resultat. IDEMPOTENT : ne refait rien si deja a jour.
Ne leve JAMAIS d'exception bloquant l'ouverture de session (tout en try/catch,
sortie 0 sur erreur non geree).
.NOTES
Execution : configurer la GPO pour lancer
powershell.exe -NoProfile -ExecutionPolicy Bypass -File Deploy-LeaUpdate.ps1
Test sur un poste (lecture seule, ne telecharge/installe RIEN) :
powershell.exe -NoProfile -ExecutionPolicy Bypass -File Deploy-LeaUpdate.ps1 -DryRun
#>
param(
# -DryRun : teste la DECISION (version installee vs cible) et journalise ce
# qui SERAIT fait, sans rien telecharger ni installer. Pour valider un poste.
[switch]$DryRun,
# Overrides optionnels (sinon = valeurs du bloc PARAMETRES ci-dessous).
# Utiles pour tester un poste (cible bumpee, journal local) sans editer le script.
[string]$TargetVersionOverride,
[string]$LogShareOverride
)
# ============================================================================
# PARAMETRES A ADAPTER PAR LE DSI / Julien (les 3 seules lignes a toucher)
# ============================================================================
# Source de l'installeur : chemin UNC du domaine (recommande) OU URL http(s).
# UNC : \\SRV-FICHIERS\Deploiement$\Lea\Lea-Setup-v1.0.2.exe
# HTTPS : https://lea.labs.laurinebazin.design/api/fleet/installer/exe
$ExeSource = '\\SRV-FICHIERS\Deploiement$\Lea\Lea-Setup-v1.0.2.exe'
# Version cible : DOIT correspondre a l'EXE ci-dessus.
$TargetVersion = '1.0.2'
# Dossier de journalisation partage (audit Julien). Vide => journal local %TEMP%.
$LogShare = '\\SRV-FICHIERS\Deploiement$\Lea\logs'
# ============================================================================
# Ne rien modifier en dessous de cette ligne.
# ============================================================================
# Overrides de ligne de commande (prioritaires sur le bloc PARAMETRES).
if ($TargetVersionOverride) { $TargetVersion = $TargetVersionOverride }
if ($PSBoundParameters.ContainsKey('LogShareOverride')) { $LogShare = $LogShareOverride }
$InstallDir = Join-Path $env:LOCALAPPDATA 'Programs\Lea'
$ConfigTxt = Join-Path $InstallDir 'config.txt'
$AppUninst = 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Uninstall\{B3F9A1E2-5C4D-4E7F-9A1B-2C3D4E5F6789}_is1'
function Write-Log([string]$msg) {
$line = '{0} {1}\{2} {3}' -f (Get-Date -Format 'yyyy-MM-dd HH:mm:ss'), $env:COMPUTERNAME, $env:USERNAME, $msg
Write-Output $line
# Journalisation best-effort : ne DOIT jamais perturber l'ouverture de session.
# -ErrorAction SilentlyContinue car un partage injoignable produit une erreur
# NON-terminante (non capturee par try/catch) — verifie sur poste reel .11.
try {
$dir = if ($LogShare) { $LogShare } else { Join-Path $env:TEMP 'Lea-update-logs' }
if (-not (Test-Path $dir -ErrorAction SilentlyContinue)) {
New-Item -ItemType Directory -Path $dir -Force -ErrorAction SilentlyContinue | Out-Null
}
$file = Join-Path $dir ('{0}_{1}.log' -f $env:COMPUTERNAME, $env:USERNAME)
Add-Content -Path $file -Value $line -Encoding UTF8 -ErrorAction SilentlyContinue
} catch { }
}
function Get-InstalledVersion {
# 1. Source de verite pour un install EXE (Inno) : DisplayVersion dans HKCU
# (install per-user). Toujours ecrite par l'installeur -> methode primaire.
# Verifie sur poste reel .11 : le config.txt genere par l'EXE ne contient
# PAS de ligne de version, seul le registre fait foi.
if (Test-Path $AppUninst) {
$dv = (Get-ItemProperty -Path $AppUninst -Name DisplayVersion -ErrorAction SilentlyContinue).DisplayVersion
if ($dv) { return $dv }
}
# 2. Fallback : RPA_AGENT_VERSION dans config.txt (present sur les installs
# via ZIP/Python ; absent des installs via EXE).
if (Test-Path $ConfigTxt) {
$m = Select-String -Path $ConfigTxt -Pattern '^\s*RPA_AGENT_VERSION\s*=\s*(.+?)\s*$' -ErrorAction SilentlyContinue
if ($m) { return $m.Matches[0].Groups[1].Value.Trim() }
}
return $null
}
function ConvertTo-VersionParts([string]$v) {
$clean = ($v -replace '^[vV]', '').Trim()
$parts = New-Object System.Collections.Generic.List[int]
foreach ($p in ($clean -split '\.')) {
$n = 0
if ([int]::TryParse($p, [ref]$n)) { $parts.Add($n) } else { $parts.Add(0) }
}
while ($parts.Count -lt 3) { $parts.Add(0) }
return $parts
}
function Compare-Semver([string]$a, [string]$b) {
# -1 si a<b, 0 si egal, 1 si a>b. Tolerant (piege 1.0.2 < 1.0.10).
$pa = ConvertTo-VersionParts $a
$pb = ConvertTo-VersionParts $b
$max = [Math]::Max($pa.Count, $pb.Count)
for ($i = 0; $i -lt $max; $i++) {
$va = if ($i -lt $pa.Count) { $pa[$i] } else { 0 }
$vb = if ($i -lt $pb.Count) { $pb[$i] } else { 0 }
if ($va -lt $vb) { return -1 }
if ($va -gt $vb) { return 1 }
}
return 0
}
try {
$installed = Get-InstalledVersion
if (-not $installed) {
Write-Log 'Lea non installe sur ce profil -> ignore (les nouveaux postes passent par le dashboard).'
exit 0
}
if ((Compare-Semver $installed $TargetVersion) -ge 0) {
Write-Log ('Deja a jour (installe={0}, cible={1}) -> rien a faire.' -f $installed, $TargetVersion)
exit 0
}
if ($DryRun) {
Write-Log ('[DryRun] MAJ qui SERAIT appliquee : {0} -> {1}. Aucune action (ni telechargement ni installation).' -f $installed, $TargetVersion)
exit 0
}
Write-Log ('MAJ requise : installe={0} < cible={1}. Recuperation de l''installeur...' -f $installed, $TargetVersion)
# Recuperer l'EXE (UNC ou URL) vers un fichier temporaire local.
$localExe = Join-Path $env:TEMP ('Lea-Setup-{0}.exe' -f $TargetVersion)
if ($ExeSource -match '^(?i)https?://') {
Invoke-WebRequest -Uri $ExeSource -OutFile $localExe -UseBasicParsing
} else {
Copy-Item -Path $ExeSource -Destination $localExe -Force
}
if (-not (Test-Path $localExe)) {
Write-Log ('ECHEC : installeur introuvable apres recuperation ({0}).' -f $ExeSource)
exit 1
}
# Installation SILENCIEUSE + UPGRADE-SAFE (sans /CONFIG : identite du poste preservee).
# L'installeur arrete Lea (via lock), sauvegarde <app>_backup, puis met a jour.
$logInstall = Join-Path $env:TEMP ('Lea-upgrade-{0}.log' -f (Get-Date -Format 'yyyyMMdd_HHmmss'))
$installArgs = @('/VERYSILENT', '/SUPPRESSMSGBOXES', '/NORESTART', ('/LOG={0}' -f $logInstall))
$proc = Start-Process -FilePath $localExe -ArgumentList $installArgs -Wait -PassThru
$rc = $proc.ExitCode
if ($rc -eq 0) {
$now = Get-InstalledVersion
Write-Log ('MAJ OK : {0} -> {1} (code 0).' -f $installed, $now)
} else {
Write-Log ('ECHEC MAJ : code {0}. Journal installeur : {1}.' -f $rc, $logInstall)
}
exit $rc
} catch {
Write-Log ('ERREUR non geree : ' + $_.Exception.Message)
exit 0 # ne JAMAIS bloquer l'ouverture de session
}

5
deploy/installer/releases/.gitignore vendored Normal file
View File

@@ -0,0 +1,5 @@
# L'installeur EXE (~33 Mo binaire) est déposé ici mais JAMAIS versionné.
# On garde le dossier + son LISEZMOI, on ignore tout le reste.
*
!.gitignore
!LISEZMOI.txt

View File

@@ -0,0 +1,17 @@
============================================================
deploy/installer/releases/ — Depot des installeurs EXE
============================================================
DEPOSER ICI l'installeur "Lea-Setup-vX.Y.Z.exe" (buildé sur .11).
Le dashboard sert le plus RECENT via la route :
GET /api/fleet/installer
-> paquet ZIP "Lea-Install-Silencieux-vX.Y.Z.zip"
(EXE + install_silencieux.bat + enroll.txt pré-rempli + LISEZMOI)
L'EXE (~33 Mo binaire) n'est VOLONTAIREMENT pas versionné dans git.
Pour pointer ailleurs : variable d'environnement RPA_LEA_RELEASES_DIR.
Ce fichier LISEZMOI.txt sert uniquement à garder le dossier présent
dans le dépôt (l'EXE, lui, est déposé à la main / par script de release).
============================================================

View File

@@ -0,0 +1,40 @@
============================================================
Lea - Installation silencieuse (nouveau poste)
============================================================
CE DOSSIER CONTIENT :
- Lea-Setup-vX.Y.Z.exe : l'installeur Lea
- install_silencieux.bat : le lanceur d'installation
- enroll.txt : les parametres d'enrolement a remplir
- LISEZMOI_SILENCIEUX.txt : ce fichier
------------------------------------------------------------
QUAND UTILISER CETTE VOIE ?
------------------------------------------------------------
Pour installer Lea sur un poste qui NE l'a PAS encore.
(Pour METTRE A JOUR un poste deja installe : voir la voie GPO,
ou relancer simplement l'installeur qui detecte l'existant.)
------------------------------------------------------------
PROCEDURE (3 etapes, ~2 min, sans droits administrateur)
------------------------------------------------------------
1. Ouvrir "enroll.txt" avec le Bloc-notes.
Renseigner : USER_NAME, USER_EMAIL, SERVER_URL, API_TOKEN.
(Remplacer les valeurs "CONFIGURE_ME".) Enregistrer.
2. Double-cliquer sur "install_silencieux.bat".
L'installation se deroule sans fenetre d'installation.
Ne pas fermer la fenetre noire avant le message "OK".
3. Verifier que Lea demarre (icone dans la barre des taches,
pres de l'horloge). C'est termine.
------------------------------------------------------------
EN CAS DE PROBLEME
------------------------------------------------------------
- Message "valeurs CONFIGURE_ME" : enroll.txt n'est pas rempli.
- Message "aucun Lea-Setup trouve" : l'EXE n'est pas dans ce dossier.
- Autre erreur : le journal detaille est indique a l'ecran
(dossier %TEMP%, fichier Lea-install-silencieux.log).
Le transmettre a l'administrateur AIVANOV.
============================================================

View File

@@ -0,0 +1,31 @@
# ============================================================
# enroll.txt — Enrolement pour installation SILENCIEUSE
# ------------------------------------------------------------
# Utilise par install_silencieux.bat :
# Lea-Setup-vX.Y.Z.exe /VERYSILENT /CONFIG=enroll.txt
#
# L'installeur lit ce fichier au demarrage et remplit les
# informations d'enrolement SANS interface graphique.
#
# A FAIRE : renseigner les valeurs ci-dessous (remplacer les
# CONFIGURE_ME), enregistrer, puis lancer install_silencieux.bat.
#
# Format : CLE=valeur, une ligne par parametre, # = commentaire.
# NOTE : ce fichier sert l'INSTALL NEUVE. Sur une mise a jour,
# l'installeur preserve tout seul l'identite du poste et
# IGNORE ce fichier (voir la voie GPO).
# ============================================================
# --- Identite du collaborateur ---
USER_NAME=Prenom Nom
USER_EMAIL=prenom.nom@clinique-wallerstein.fr
USER_ID=
# --- Connexion au serveur Lea ---
# Exemples de SERVER_URL :
# LAN clinique (DGX) : http://192.168.1.178:5005/api/v1
# Internet : https://lea.labs.laurinebazin.design/api/v1
SERVER_URL=CONFIGURE_ME
# Token d'authentification (fourni par l'administrateur AIVANOV)
API_TOKEN=CONFIGURE_ME

View File

@@ -0,0 +1,73 @@
@echo off
chcp 65001 >nul 2>&1
setlocal enabledelayedexpansion
title Lea - Installation silencieuse (nouveau poste)
:: ============================================================
:: install_silencieux.bat
:: Installe Lea sur un NOUVEAU poste, sans interface graphique.
::
:: Pre-requis : ce script, l'installeur "Lea-Setup-v*.exe" et
:: "enroll.txt" (rempli) doivent etre dans le MEME dossier.
::
:: Installation PER-USER : aucun droit administrateur requis.
:: ============================================================
set "HERE=%~dp0"
set "ENROLL=%HERE%enroll.txt"
set "LOG=%TEMP%\Lea-install-silencieux.log"
echo.
echo ============================================================
echo Lea - Installation silencieuse (nouveau poste)
echo ============================================================
echo.
:: --- 1. Localiser l'installeur (Lea-Setup-v*.exe, version la plus recente) ---
set "EXE="
for /f "delims=" %%f in ('dir /b /o-n "%HERE%Lea-Setup-v*.exe" 2^>nul') do (
if not defined EXE set "EXE=%HERE%%%f"
)
if not defined EXE (
echo ERREUR : aucun "Lea-Setup-v*.exe" trouve dans ce dossier.
echo Placez ce script a cote de l'installeur Lea.
echo.
pause
exit /b 1
)
echo Installeur detecte : !EXE!
:: --- 2. Verifier enroll.txt ---
if not exist "%ENROLL%" (
echo ERREUR : "enroll.txt" introuvable a cote de ce script.
echo.
pause
exit /b 1
)
findstr /C:"CONFIGURE_ME" "%ENROLL%" >nul 2>&1
if not errorlevel 1 (
echo.
echo ATTENTION : "enroll.txt" contient encore des valeurs CONFIGURE_ME.
echo Ouvrez enroll.txt, renseignez SERVER_URL / API_TOKEN / USER_*,
echo enregistrez, puis relancez ce script.
echo.
pause
exit /b 1
)
:: --- 3. Installation silencieuse (per-user, pas d'admin) ---
echo Installation en cours (silencieuse, ~1-2 min)... ne fermez pas cette fenetre.
"!EXE!" /VERYSILENT /SUPPRESSMSGBOXES /NORESTART /CONFIG="%ENROLL%" /LOG="%LOG%"
set "RC=!errorlevel!"
echo.
if "!RC!"=="0" (
echo Installation terminee - OK.
echo Lea est enrolle et pret. Journal : %LOG%
) else (
echo ERREUR : l'installation a echoue ^(code !RC!^).
echo Consultez le journal : %LOG%
)
echo.
pause
endlocal

View File

@@ -0,0 +1,75 @@
# Procédure de déploiement Léa — pour Julien (informaticien clinique)
> Version agent cible : **1.0.2** · Installeur : `Lea-Setup-v1.0.2.exe` (per-user, aucun droit admin requis).
> Rédigé le 2026-07-06. Poste pilote validé : **Émilie**.
Trois cas. Le n°1 pour un poste **neuf**, le n°2/3 pour **mettre à jour** un poste déjà installé.
---
## 1. Installer Léa sur un NOUVEAU poste (install silencieuse)
1. Depuis un navigateur (dashboard Léa), télécharger le paquet :
**`GET /api/fleet/installer`** → `Lea-Install-Silencieux-vX.Y.Z.zip`.
*(Le ZIP contient l'EXE + `install_silencieux.bat` + `enroll.txt` déjà pré-rempli avec l'URL serveur et le token.)*
2. Sur le poste cible : dézipper le paquet dans un dossier.
3. Ouvrir **`enroll.txt`** (Bloc-notes), compléter **`USER_NAME`** et **`USER_EMAIL`** (l'URL et le token sont déjà remplis). Enregistrer.
4. Double-cliquer **`install_silencieux.bat`**. Attendre le message **« Installation terminée - OK »**.
5. Vérifier : icône Léa près de l'horloge (barre des tâches).
> L'installeur génère un **`machine_id` unique** pour ce poste : rien à pré-enregistrer.
---
## 2. Mettre à jour un poste déjà installé — voie MANUELLE (immédiate)
C'est la voie utilisée pour Émilie, à rejouer poste par poste **en attendant l'autorisation AD/GPO**.
1. Récupérer **`Lea-Setup-v1.0.2.exe`** (le même EXE, aucune régénération).
2. Sur le poste, le lancer par **double-clic** (mode interactif).
3. Le wizard doit s'afficher **pré-rempli** avec la config du poste (serveur/token/utilisateur).
⚠️ **S'il est vide** → l'installeur n'a pas détecté l'install existante : **ne pas continuer**, prévenir AIVANOV (risque de créer un nouveau poste au lieu de mettre à jour).
4. Valider. L'installeur **arrête Léa**, sauvegarde l'ancienne version (`<dossier>_backup`), met à jour en **préservant l'identité** du poste, purge les captures accumulées.
5. Vérifier après MAJ (mêmes points qu'Émilie) : Léa relancée en **v1.0.2**, icône présente, capture d'écran OK, comportement RDP OK.
> **Rollback** si besoin : restaurer le dossier `<install>_backup` (le dossier d'install est `%LOCALAPPDATA%\Programs\Lea`).
---
## 3. Mettre à jour la flotte via AD/GPO (quand l'autorisation est en place)
Script fourni : **`deploy/gpo/Deploy-LeaUpdate.ps1`**.
### ⚠️ Point crucial : script d'OUVERTURE DE SESSION (contexte utilisateur)
Léa est installée **par utilisateur** (`%LOCALAPPDATA%`). Un script de **démarrage machine** (contexte SYSTEM) **ne verrait pas** l'installation et ne mettrait rien à jour. Le script doit donc être en :
**`User Configuration → Policies → Windows Settings → Scripts (Logon/Logoff) → Logon`.**
### Étapes
1. Déposer `Lea-Setup-v1.0.2.exe` sur un partage du domaine accessible aux postes (ex. `\\SRV-FICHIERS\Deploiement$\Lea\`).
2. Éditer les **3 lignes de paramètres** en tête de `Deploy-LeaUpdate.ps1` :
- `$ExeSource` = chemin UNC (ou URL) de l'EXE ;
- `$TargetVersion` = `1.0.2` (doit correspondre à l'EXE) ;
- `$LogShare` = dossier partagé pour les journaux d'audit (ou vide → journal local).
3. Ajouter le script en **Logon script** (commande : `powershell.exe -NoProfile -ExecutionPolicy Bypass -File Deploy-LeaUpdate.ps1`).
4. À l'ouverture de session, le script : détecte la version installée, compare à la cible, met à jour **seulement si plus ancienne** (idempotent, silencieux, upgrade-safe), puis journalise.
### Comportement (garanti par le script)
- Poste **déjà à jour** → ne fait rien.
- Poste **sans Léa** → ignoré (les postes neufs passent par le cas 1).
- Erreur (partage indisponible, etc.) → journalisée, **n'empêche jamais l'ouverture de session**.
### Audit
Un journal par poste/utilisateur dans `$LogShare` : `<POSTE>_<UTILISATEUR>.log` (ligne datée : version installée → version après MAJ, ou motif d'échec).
---
## Aide-mémoire
| Besoin | Voie | Artefact |
|---|---|---|
| Poste neuf | Install silencieuse | Dashboard `GET /api/fleet/installer` |
| MAJ immédiate d'un poste | Manuelle (double-clic) | `Lea-Setup-v1.0.2.exe` |
| MAJ de toute la flotte | AD/GPO (logon script) | `deploy/gpo/Deploy-LeaUpdate.ps1` |
| Revenir en arrière | Rollback | dossier `<install>_backup` |
En cas de doute ou de wizard **non** pré-rempli lors d'une MAJ : **s'arrêter et contacter AIVANOV**.

View File

@@ -2481,6 +2481,131 @@ def download_agent_package(machine_id):
) )
# =============================================================================
# Fleet — Téléchargement de l'installeur SILENCIEUX (EXE, nouveaux postes)
# =============================================================================
#
# Voie EXE (python-embedded, upgrade-safe) DISTINCTE de la voie ZIP/Python
# ci-dessus (download_agent_package). Sert un paquet d'installation silencieuse
# pour un NOUVEAU poste : l'EXE génère lui-même un machine_id unique → pas de
# pré-enregistrement requis (contrairement à la voie ZIP, qui bake un
# machine_id assigné). L'EXE lourd (~33 Mo binaire) n'est PAS versionné : il est
# déposé sur l'hôte dans RPA_LEA_RELEASES_DIR (défaut deploy/installer/releases/)
# après build sur .11.
_LEA_RELEASES_DIR = Path(
os.getenv("RPA_LEA_RELEASES_DIR", str(BASE_PATH / "deploy" / "installer" / "releases"))
)
_LEA_SILENT_DIR = BASE_PATH / "deploy" / "installer" / "silent"
def _silent_exe_version(name: str) -> str:
"""Extrait la version d'un nom "Lea-Setup-v1.0.2.exe""1.0.2" (sans regex)."""
stem = name[:-4] if name.lower().endswith(".exe") else name
prefix = "Lea-Setup-v"
return stem[len(prefix):] if stem.startswith(prefix) else "0.0.0"
def _resolve_silent_installer_exe(releases_dir: "Path | None" = None) -> "Path | None":
"""Retourne l'EXE Lea-Setup-v*.exe le plus récent du dossier releases, ou None.
Tri par version sémantique décroissante (pas lexicographique : 1.0.10 > 1.0.2).
Paramètre injectable pour les tests (évite de démarrer Flask — DETTE-013).
"""
d = releases_dir or _LEA_RELEASES_DIR
try:
exes = list(d.glob("Lea-Setup-v*.exe"))
except Exception:
return None
if not exes:
return None
def _ver_key(p: Path):
parts = []
for tok in _silent_exe_version(p.name).split("."):
parts.append(int(tok) if tok.isdigit() else 0)
return parts
return sorted(exes, key=_ver_key, reverse=True)[0]
def _build_silent_enroll(token: str) -> str:
"""Génère enroll.txt (clés /CONFIG de l'installeur EXE) avec SERVER_URL et
token injectés. USER_* laissés en placeholder : remplis par poste avant le
lancement de install_silencieux.bat.
"""
server_url = _resolve_public_server_url()
return f"""\
# ============================================================
# enroll.txt — Enrolement pour installation SILENCIEUSE
# Genere par le dashboard Fleet. SERVER_URL et API_TOKEN sont
# deja renseignes. A COMPLETER : USER_NAME / USER_EMAIL.
# Puis lancer install_silencieux.bat.
# ============================================================
# --- Identite du collaborateur (a remplir) ---
USER_NAME=Prenom Nom
USER_EMAIL=prenom.nom@clinique-wallerstein.fr
USER_ID=
# --- Connexion serveur (pre-renseignee, ne pas modifier) ---
SERVER_URL={server_url}
API_TOKEN={token}
"""
@app.route('/api/fleet/installer')
def download_silent_installer():
"""Sert un paquet ZIP d'installation SILENCIEUSE pour un nouveau poste.
Contenu : Lea-Setup-v*.exe + install_silencieux.bat + enroll.txt
(SERVER_URL/token pré-injectés) + LISEZMOI. L'auth Basic est gérée par
before_request.
"""
exe = _resolve_silent_installer_exe()
if exe is None:
api_logger.error(
"download_silent_installer — aucun Lea-Setup-v*.exe dans %s.",
_LEA_RELEASES_DIR,
)
return jsonify({
'error': 'Installeur EXE introuvable',
'detail': (
f'Aucun Lea-Setup-v*.exe dans {_LEA_RELEASES_DIR}. '
'Déposer l\'EXE (buildé sur .11) dans ce dossier, ou définir '
'la variable d\'environnement RPA_LEA_RELEASES_DIR.'
),
}), 404
version = _silent_exe_version(exe.name)
token = os.environ.get('RPA_API_TOKEN', 'CONFIGURE_ME')
enroll_txt = _build_silent_enroll(token)
# Artefacts d'accompagnement — source de vérité = deploy/installer/silent/.
bat_path = _LEA_SILENT_DIR / "install_silencieux.bat"
readme_path = _LEA_SILENT_DIR / "LISEZMOI_SILENCIEUX.txt"
output_buffer = io.BytesIO()
with zipfile.ZipFile(output_buffer, 'w', zipfile.ZIP_DEFLATED) as z:
z.write(exe, arcname=exe.name)
if bat_path.exists():
z.write(bat_path, arcname="install_silencieux.bat")
if readme_path.exists():
z.write(readme_path, arcname="LISEZMOI_SILENCIEUX.txt")
z.writestr("enroll.txt", enroll_txt.encode('utf-8'))
output_buffer.seek(0)
api_logger.info(
"download_silent_installer — paquet servi (EXE %s, v%s).", exe.name, version
)
return send_file(
output_buffer,
as_attachment=True,
download_name=f"Lea-Install-Silencieux-v{version}.zip",
mimetype='application/zip',
)
# ============================================================================= # =============================================================================
# Cartographie des processus — Process Mining # Cartographie des processus — Process Mining
# ============================================================================= # =============================================================================