feat(deploy): install silencieuse (dashboard) + MAJ GPO clients Léa + procédure Julien — 2026-07-06
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:
181
deploy/gpo/Deploy-LeaUpdate.ps1
Normal file
181
deploy/gpo/Deploy-LeaUpdate.ps1
Normal 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
5
deploy/installer/releases/.gitignore
vendored
Normal 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
|
||||||
17
deploy/installer/releases/LISEZMOI.txt
Normal file
17
deploy/installer/releases/LISEZMOI.txt
Normal 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).
|
||||||
|
============================================================
|
||||||
40
deploy/installer/silent/LISEZMOI_SILENCIEUX.txt
Normal file
40
deploy/installer/silent/LISEZMOI_SILENCIEUX.txt
Normal 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.
|
||||||
|
============================================================
|
||||||
31
deploy/installer/silent/enroll.txt
Normal file
31
deploy/installer/silent/enroll.txt
Normal 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
|
||||||
73
deploy/installer/silent/install_silencieux.bat
Normal file
73
deploy/installer/silent/install_silencieux.bat
Normal 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
|
||||||
75
docs/PROCEDURE_DEPLOIEMENT_LEA_JULIEN.md
Normal file
75
docs/PROCEDURE_DEPLOIEMENT_LEA_JULIEN.md
Normal 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**.
|
||||||
@@ -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
|
||||||
# =============================================================================
|
# =============================================================================
|
||||||
|
|||||||
Reference in New Issue
Block a user