# Sistema di Versioning Automatizzato ## Panoramica Data-Coupler implementa un sistema di versioning automatizzato che integra le Gitea Actions con l'applicazione Blazor per mostrare dinamicamente la versione corrente nel NavMenu. ## Architettura del Sistema ### Componenti 1. **version.json**: File JSON generato automaticamente durante il build 2. **VersionInfo.cs**: Modello dati per le informazioni di versione 3. **VersionService.cs**: Servizio per leggere e gestire le informazioni di versione 4. **NavMenu.razor**: UI che mostra la versione corrente ### Flusso di Versioning ```mermaid graph LR A[Git Push] --> B[Gitea Actions] B --> C[Generate version.json] C --> D[Docker Build] D --> E[Deploy] E --> F[VersionService carica version.json] F --> G[NavMenu mostra versione] ``` ## Gitea Actions Workflow ### Generazione version.json - Linux Durante il build Linux, il workflow **legge dinamicamente** la versione dal `.csproj`: ```bash # Extract version from Data_Coupler.csproj or use default VERSION=$(grep '' Data_Coupler/Data_Coupler.csproj | sed 's/.*\(.*\)<\/Version>.*/\1/' || echo "2.1.0") # If version tag not found, use default if [ -z "$VERSION" ]; then VERSION="2.1.0" fi # Create version.json cat > Data_Coupler/wwwroot/version.json <` nel `.csproj` 2. Estrae il valore con `sed` 3. Se non trova nulla, usa fallback "2.1.0" 4. Genera `version.json` con tutti i metadati ### Generazione version.json - Windows Durante il build Windows, il workflow **legge dinamicamente** la versione dal `.csproj` usando PowerShell: ```powershell # Extract version from Data_Coupler.csproj or use default $csprojPath = "Data_Coupler\Data_Coupler.csproj" $VERSION = "2.1.0" if (Test-Path $csprojPath) { $csprojContent = Get-Content $csprojPath -Raw if ($csprojContent -match '(.*?)<\/Version>') { $VERSION = $matches[1] Write-Host "Version extracted from csproj: $VERSION" } else { Write-Host "Version tag not found in csproj, using default: $VERSION" } } else { Write-Host "csproj not found, using default version: $VERSION" } $COMMIT_SHA = "${{ github.sha }}" $SHORT_SHA = $COMMIT_SHA.Substring(0, 7) $BRANCH = "${{ github.ref_name }}" $BUILD_DATE = (Get-Date).ToUniversalTime().ToString("yyyy-MM-dd HH:mm:ss UTC") # Create version.json $versionJson = @{ version = $VERSION commitSha = $SHORT_SHA branch = $BRANCH buildDate = $BUILD_DATE buildEnvironment = "Gitea Actions" } | ConvertTo-Json $versionJson | Out-File -FilePath "Data_Coupler\wwwroot\version.json" -Encoding UTF8 ``` **Logica**: 1. Legge contenuto del file `.csproj` 2. Usa regex per estrarre `` tag 3. Se non trova, usa fallback "2.1.0" 4. Genera `version.json` usando `ConvertTo-Json` per formato corretto 5. Data in formato UTC consistente con Linux **✅ Consistenza**: Entrambi i workflow (Linux e Windows) ora leggono la versione dalla **stessa fonte** (`.csproj`) ## Modello Dati ### VersionInfo.cs ```csharp public class VersionInfo { public string Version { get; set; } = "0.0.0"; public string CommitSha { get; set; } = "unknown"; public string Branch { get; set; } = "unknown"; public string BuildDate { get; set; } = "unknown"; public string BuildEnvironment { get; set; } = "Local"; // Formati di output public string GetFullVersion() // "v2.1.0 (main-abc1234)" public string GetShortVersion() // "v2.1.0" } ``` ## Servizio di Versioning ### VersionService.cs Il servizio: 1. Viene registrato come **Singleton** in `Program.cs` 2. Carica `version.json` all'avvio dell'applicazione 3. Fornisce fallback a valori di default se il file non esiste 4. Log dettagliato delle operazioni ```csharp public class VersionService : IVersionService { public VersionInfo GetVersion() // Info complete public string GetDisplayVersion() // Solo versione per UI } ``` ### Registrazione del Servizio In `Program.cs`: ```csharp builder.Services.AddSingleton(); ``` ## Integrazione UI ### NavMenu.razor ```razor @inject Data_Coupler.Services.IVersionService VersionService Data_Coupler @_version @code { private string _version = ""; protected override void OnInitialized() { _version = VersionService.GetDisplayVersion(); } } ``` Risultato: **"Data_Coupler v2.1.0"** ## Gestione Versioni ### ⚠️ Importante: Incremento Manuale **Il sistema NON incrementa automaticamente la versione**. Il versioning segue questo flusso: 1. **Developer** aggiorna manualmente `` in `Data_Coupler.csproj` 2. **Gitea Actions** legge la versione dal file `.csproj` 3. **Workflow** genera `version.json` con la versione letta 4. **Applicazione** carica e mostra la versione ### Come Incrementare la Versione **NON** modificare `version.json` direttamente. Segui questi passi: 1. **File csproj**: Aggiorna `2.1.0` in `Data_Coupler.csproj` 2. **Commit e Push**: Le Gitea Actions genereranno automaticamente il nuovo `version.json` 3. **Deploy**: La nuova versione sarà visibile nell'applicazione ### Semantic Versioning Seguiamo il pattern **MAJOR.MINOR.PATCH**: - **MAJOR**: Breaking changes (incompatibilità con versione precedente) - **MINOR**: Nuove feature backward-compatible (non rompe codice esistente) - **PATCH**: Bug fixes (solo correzioni, nessuna nuova funzionalità) Esempio progressione: - `2.1.0` → `2.1.1` (bug fix - aggiornamento PATCH) - `2.1.1` → `2.2.0` (nuova feature - aggiornamento MINOR) - `2.2.0` → `3.0.0` (breaking change - aggiornamento MAJOR) ### Pattern di Incremento: Logica e Consistenza #### 🎯 Fonte Unica della Verità (Single Source of Truth) Il file **`Data_Coupler.csproj`** è l'**unica fonte** della versione: ```xml 2.1.0 2.1.0.0 2.1.0.0 ``` #### 📋 Flusso di Versioning ``` ┌───────────────────────────────────────────────────────────────┐ │ 1. Developer aggiorna in Data_Coupler.csproj │ │ - MANUALE: Developer sceglie il numero (2.1.0 → 2.2.0) │ │ - Segue Semantic Versioning │ └────────────────────────┬──────────────────────────────────────┘ ↓ ┌───────────────────────────────────────────────────────────────┐ │ 2. Git Commit & Push │ │ - git commit -am "Bump version to 2.2.0" │ │ - git push origin main │ └────────────────────────┬──────────────────────────────────────┘ ↓ ┌───────────────────────────────────────────────────────────────┐ │ 3. Gitea Actions Triggered │ │ - Workflow avvia automaticamente │ └────────────────────────┬──────────────────────────────────────┘ ↓ ┌───────────────────────────────────────────────────────────────┐ │ 4. Build Linux: Legge versione da .csproj │ │ - grep '' Data_Coupler.csproj │ │ - Estrae: "2.2.0" │ └────────────────────────┬──────────────────────────────────────┘ ↓ ┌───────────────────────────────────────────────────────────────┐ │ 5. Build Windows: Legge versione da .csproj │ │ - PowerShell regex: '(.*?)<\/Version>' │ │ - Estrae: "2.2.0" │ └────────────────────────┬──────────────────────────────────────┘ ↓ ┌───────────────────────────────────────────────────────────────┐ │ 6. Genera version.json (identico su Linux e Windows) │ │ { │ │ "version": "2.2.0", │ │ "commitSha": "abc1234", │ │ "branch": "main", │ │ "buildDate": "2026-02-02 10:30:45 UTC", │ │ "buildEnvironment": "Gitea Actions" │ │ } │ └────────────────────────┬──────────────────────────────────────┘ ↓ ┌───────────────────────────────────────────────────────────────┐ │ 7. Docker Build include version.json │ │ - File copiato in container │ └────────────────────────┬──────────────────────────────────────┘ ↓ ┌───────────────────────────────────────────────────────────────┐ │ 8. Deploy & Runtime │ │ - VersionService carica version.json │ │ - NavMenu mostra: "Data_Coupler v2.2.0" │ └───────────────────────────────────────────────────────────────┘ ``` #### ✅ Garanzie di Consistenza | Aspetto | Linux | Windows | Consistenza | |---------|-------|---------|-------------| | **Fonte versione** | `.csproj` | `.csproj` | ✅ Identica | | **Metodo estrazione** | `grep + sed` | `PowerShell regex` | ✅ Equivalente | | **Fallback default** | "2.1.0" | "2.1.0" | ✅ Identico | | **Formato date** | UTC | UTC | ✅ Identico | | **Formato JSON** | Manuale | `ConvertTo-Json` | ✅ Valido | | **Posizione file** | `wwwroot/version.json` | `wwwroot\version.json` | ✅ Stessa | #### 🚫 Cosa NON Viene Fatto - ❌ **Auto-incremento**: Non esiste logica di auto-bump (nessun +1 automatico) - ❌ **Parsing Git Tags**: Non legge versioni da git tags - ❌ **Calcolo automatico**: Non calcola MAJOR/MINOR/PATCH basandosi su commit - ❌ **Versionamento per branch**: Tutti i branch usano la stessa versione dal `.csproj` #### ✅ Cosa Viene Fatto - ✅ **Lettura semplice**: Estrae valore esistente da `.csproj` - ✅ **Propagazione**: Copia versione in `version.json` - ✅ **Metadata arricchito**: Aggiunge commit SHA, branch, data - ✅ **Consistenza multi-platform**: Stessa logica su Linux e Windows ### Decisioni di Design **Perché incremento manuale?** - **Controllo esplicito**: Developer decide consapevolmente quando incrementare - **Semantic Versioning corretto**: Umano determina se MAJOR/MINOR/PATCH - **Semplicità**: Nessuna logica complessa di parsing commit messages - **Chiarezza**: Una singola fonte di verità (`.csproj`) **Perché non auto-incremento basato su commit?** - Richiederebbe parsing di commit messages (Conventional Commits) - Complessità aggiunta senza reale beneficio - Rischio di errori nell'interpretazione dei commit - Preferibile controllo umano per decisioni di versioning ## File version.json ### Formato ```json { "version": "2.1.0", "commitSha": "abc1234", "branch": "main", "buildDate": "2026-02-02 10:30:45 UTC", "buildEnvironment": "Gitea Actions" } ``` ### Posizione - **Sviluppo Locale**: `Data_Coupler/wwwroot/version.json` - **Docker Container**: `/app/wwwroot/version.json` ### Fallback Se `version.json` non esiste o c'è un errore, il servizio usa: ```json { "version": "2.1.0", "commitSha": "local", "branch": "dev", "buildDate": "2026-02-02 HH:mm:ss", "buildEnvironment": "Local" } ``` ## Testing ### Test Locale 1. Creare manualmente `Data_Coupler/wwwroot/version.json`: ```json { "version": "2.1.0-dev", "commitSha": "local", "branch": "dev", "buildDate": "2026-02-02", "buildEnvironment": "Local" } ``` 2. Eseguire l'applicazione: ```bash dotnet run --project Data_Coupler/Data_Coupler.csproj ``` 3. Verificare nel NavMenu la versione "Data_Coupler v2.1.0-dev" ### Test Docker Dopo il build e push tramite Gitea Actions: ```bash docker pull gitea.home-nas-ds.org/alessio/data-coupler:latest docker run -p 7550:8080 gitea.home-nas-ds.org/alessio/data-coupler:latest ``` Verificare: - NavMenu mostra la versione corretta - Logs mostrano: `Version loaded: v2.1.0 (main-abc1234)` ## Troubleshooting ### Problema: Versione non aggiornata **Sintomo**: NavMenu mostra sempre "v2.1.0" anche dopo aggiornamento **Soluzione**: 1. Verificare che `version.json` sia stato generato nel workflow 2. Controllare i logs del workflow Gitea 3. Verificare che il file sia incluso nel Docker image: ```bash docker run --rm gitea.home-nas-ds.org/alessio/data-coupler:latest cat /app/wwwroot/version.json ``` ### Problema: VersionService non trovato **Sintomo**: Errore `Cannot provide a value for property 'VersionService'` **Soluzione**: Verificare la registrazione in `Program.cs`: ```csharp builder.Services.AddSingleton(); ``` ### Problema: version.json non caricato **Sintomo**: Logs mostrano "version.json not found" **Soluzione**: 1. Verificare che il file esista in `wwwroot/version.json` 2. Controllare i permessi del file 3. Verificare il path in `VersionService.cs`: ```csharp var versionFilePath = Path.Combine(_env.ContentRootPath, "wwwroot", "version.json"); ``` ## Best Practices ### 1. Aggiornamento Versione - Aggiornare sempre `` in `Data_Coupler.csproj` - Seguire Semantic Versioning - Documentare le modifiche nel changelog ### 2. Build e Deploy - Testare localmente prima del push - Verificare che i workflow Gitea completino con successo - Controllare i logs del container dopo il deploy ### 3. Monitoraggio - Verificare periodicamente che la versione sia corretta - Controllare i logs per errori di caricamento `version.json` - Mantenere sincronizzati i tag Docker con la versione applicazione ## Integrazione Futura ### Potenziali Miglioramenti 1. **Health Check Endpoint**: ```csharp app.MapGet("/version", (IVersionService versionService) => Results.Ok(versionService.GetVersion())); ``` 2. **Footer con Versione Dettagliata**: ```razor ``` 3. **About Page**: Creare una pagina dedicata con tutte le informazioni di versione 4. **Notifiche di Aggiornamento**: Sistema per notificare agli utenti quando è disponibile una nuova versione ## Riferimenti - **File Sorgenti**: - `Data_Coupler/Models/VersionInfo.cs` - `Data_Coupler/Services/VersionService.cs` - `Data_Coupler/Shared/NavMenu.razor` - `Data_Coupler/Program.cs` - `.gitea/workflows/docker-build.yml` - **Documentazione Correlata**: - `GITHUB_ACTIONS_SETUP.md` - `DOCKER_DEPLOYMENT.md` - `.gitea/workflows/README.md` --- **Versione Documento**: 1.0 **Data Creazione**: 2 Febbraio 2026 **Autore**: Alessio Dalsanto **Ultima Revisione**: 2 Febbraio 2026