v0.12.0 — Report tool auto-deploy from PROSERVE ZIP

Each PROSERVE ZIP can ship a _report/ subfolder alongside _migrations/.
After install + DB migration, the launcher copies _report/ to the local
XAMPP htdocs (default C:\xampp\htdocs\ProserveReport\) so the Reports
tab in the sidebar always serves the matching version.

Service (PSLauncher.Core/ReportTool)
- IReportToolDeployer + ReportToolDeployer.
- Atomic deploy: copy to {target}.new/ → rename current to .old/ →
  rename .new → final → cleanup .old. Apache never sees a half-state.
- Skip silencieux si _report/ absent du ZIP (PROSERVE release qui ne
  touche pas au Report).
- DeployStatus enum (SkippedNoSourceFolder, XamppNotFound, Failed,
  Deployed) renvoyé pour gestion UI claire.

Config (LocalConfig)
- ReportToolConfig (HtdocsRoot, FolderName, AutoDeploy). Defaults
  matchent l'install standard ASTERION (C:\xampp\htdocs\ProserveReport).

Install pipeline (MainViewModel)
- Étape 6 après extraction + migrations. Progress reporté via le footer
  Library : « 📂 Déploiement Report : 47/120 — assets/main.js ».
  XAMPP introuvable → dialog avec lien vers Settings → Avancés.

Settings UI (SettingsDialog → Avancés)
- Nouveau bloc « OUTIL REPORT (XAMPP htdocs) » : 2 champs path + checkbox
  AutoDeploy + bouton « 📂 Re-déployer maintenant » qui rejoue le deploy
  sur la dernière version installée. Utile après changement de chemin
  htdocs ou si l'auto-deploy avait foiré (XAMPP éteint).

Versions bumped to 0.12.0 (App + Updater + installer .iss).

Côté release : tu ajoutes _report/ dans le source de PROSERVE, tu zippes,
tu uploades. Les clients récupèrent ZIP + migrations + Report en une
seule install.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-03 09:05:40 +02:00
parent a2e67d5405
commit 67f422539d
11 changed files with 396 additions and 5 deletions

View File

@@ -16,6 +16,7 @@ using PSLauncher.Core.Localization;
using PSLauncher.Core.Manifests;
using PSLauncher.Core.Migrations;
using PSLauncher.Core.Process;
using PSLauncher.Core.ReportTool;
using PSLauncher.Core.Updates;
using PSLauncher.Models;
@@ -41,6 +42,7 @@ public sealed partial class MainViewModel : ObservableObject
private readonly ILauncherSelfUpdater _selfUpdater;
private readonly IToastService _toastService;
private readonly IDatabaseMigrationService _migrationService;
private readonly IReportToolDeployer _reportDeployer;
private readonly IServiceProvider _serviceProvider;
private readonly ILogger<MainViewModel> _logger;
@@ -223,6 +225,7 @@ public sealed partial class MainViewModel : ObservableObject
ILauncherSelfUpdater selfUpdater,
IToastService toastService,
IDatabaseMigrationService migrationService,
IReportToolDeployer reportDeployer,
IServiceProvider serviceProvider,
ILogger<MainViewModel> logger)
{
@@ -238,6 +241,7 @@ public sealed partial class MainViewModel : ObservableObject
_selfUpdater = selfUpdater;
_toastService = toastService;
_migrationService = migrationService;
_reportDeployer = reportDeployer;
_serviceProvider = serviceProvider;
_logger = logger;
@@ -745,6 +749,50 @@ public sealed partial class MainViewModel : ObservableObject
}
}
// 6) Déploiement de l'outil Report (page web XAMPP).
// Cherche _report/ dans le ZIP extrait et copie vers htdocs en
// atomic rename. Skip silencieux si _report/ absent du ZIP.
if (_config.ReportTool.AutoDeploy)
{
StatusMessage = Strings.StatusDeployingReport(row.Version);
ProgressDetail = null;
ProgressPercent = 0;
var rdProgress = new Progress<DeployProgress>(dp =>
{
if (dp.FilesTotal > 0)
{
var pct = (double)dp.FilesDone / dp.FilesTotal * 100.0;
ProgressPercent = pct;
row.ProgressPercent = pct;
}
var label = Strings.ProgressReportDeploy(dp.FilesDone, dp.FilesTotal, dp.CurrentFilename);
ProgressDetail = label;
row.ProgressDetail = label;
});
var rdResult = await _reportDeployer.DeployAsync(target, rdProgress, ct);
switch (rdResult.Status)
{
case DeployStatus.Deployed:
_logger.LogInformation("Report tool deployed ({N} files) for v{Version}", rdResult.FilesDeployed, row.Version);
break;
case DeployStatus.SkippedNoSourceFolder:
_logger.LogInformation("No _report/ in v{Version} ZIP, report tool unchanged", row.Version);
break;
case DeployStatus.XamppNotFound:
MessageBox.Show(
Strings.MsgReportXamppNotFound(_config.ReportTool.HtdocsRoot),
Strings.MsgBoxReportDeployFailed,
MessageBoxButton.OK, MessageBoxImage.Warning);
break;
case DeployStatus.Failed:
MessageBox.Show(
Strings.MsgReportDeployFailed(rdResult.ErrorMessage ?? "?"),
Strings.MsgBoxReportDeployFailed,
MessageBoxButton.OK, MessageBoxImage.Warning);
break;
}
}
StatusMessage = Strings.StatusInstalledSuccess(row.Version);
ProgressDetail = null;
ProgressPercent = 0;