- Aggiunto MinVer per calcolo automatico versione da git tags - Creato modello VersionInfo e servizio VersionService - Integrato display versione nel NavMenu (Data_Coupler v2.1.0) - Aggiornato workflow Gitea Actions (Linux e Windows) per generare version.json - Risolto problema inconsistenza versioning tra container Linux e Windows - Documentazione completa: VERSIONING_SYSTEM.md e MINVER_SETUP.md - Versione ora calcolata automaticamente da git tags (Semantic Versioning)
17 KiB
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
- version.json: File JSON generato automaticamente durante il build
- VersionInfo.cs: Modello dati per le informazioni di versione
- VersionService.cs: Servizio per leggere e gestire le informazioni di versione
- NavMenu.razor: UI che mostra la versione corrente
Flusso di Versioning
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:
# Extract version from Data_Coupler.csproj or use default
VERSION=$(grep '<Version>' Data_Coupler/Data_Coupler.csproj | sed 's/.*<Version>\(.*\)<\/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 <<EOF
{
"version": "${VERSION}",
"commitSha": "${GITHUB_SHA:0:7}",
"branch": "${GITHUB_REF_NAME}",
"buildDate": "$(date -u +"%Y-%m-%d %H:%M:%S UTC")",
"buildEnvironment": "Gitea Actions"
}
EOF
Logica:
- Usa
grepper cercare tag<Version>nel.csproj - Estrae il valore con
sed - Se non trova nulla, usa fallback "2.1.0"
- Genera
version.jsoncon tutti i metadati
Generazione version.json - Windows
Durante il build Windows, il workflow legge dinamicamente la versione dal .csproj usando 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>') {
$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:
- Legge contenuto del file
.csproj - Usa regex per estrarre
<Version>tag - Se non trova, usa fallback "2.1.0"
- Genera
version.jsonusandoConvertTo-Jsonper formato corretto - 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
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:
- Viene registrato come Singleton in
Program.cs - Carica
version.jsonall'avvio dell'applicazione - Fornisce fallback a valori di default se il file non esiste
- Log dettagliato delle operazioni
public class VersionService : IVersionService
{
public VersionInfo GetVersion() // Info complete
public string GetDisplayVersion() // Solo versione per UI
}
Registrazione del Servizio
In Program.cs:
builder.Services.AddSingleton<Data_Coupler.Services.IVersionService, Data_Coupler.Services.VersionService>();
Integrazione UI
NavMenu.razor
@inject Data_Coupler.Services.IVersionService VersionService
<a class="navbar-brand" href="">Data_Coupler @_version</a>
@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:
- Developer aggiorna manualmente
<Version>inData_Coupler.csproj - Gitea Actions legge la versione dal file
.csproj - Workflow genera
version.jsoncon la versione letta - Applicazione carica e mostra la versione
Come Incrementare la Versione
NON modificare version.json direttamente. Segui questi passi:
- File csproj: Aggiorna
<Version>2.1.0</Version>inData_Coupler.csproj - Commit e Push: Le Gitea Actions genereranno automaticamente il nuovo
version.json - 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:
<PropertyGroup>
<Version>2.1.0</Version>
<AssemblyVersion>2.1.0.0</AssemblyVersion>
<FileVersion>2.1.0.0</FileVersion>
</PropertyGroup>
📋 Flusso di Versioning
┌───────────────────────────────────────────────────────────────┐
│ 1. Developer aggiorna <Version> 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 '<Version>' Data_Coupler.csproj │
│ - Estrae: "2.2.0" │
└────────────────────────┬──────────────────────────────────────┘
↓
┌───────────────────────────────────────────────────────────────┐
│ 5. Build Windows: Legge versione da .csproj │
│ - PowerShell regex: '<Version>(.*?)<\/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
{
"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:
{
"version": "2.1.0",
"commitSha": "local",
"branch": "dev",
"buildDate": "2026-02-02 HH:mm:ss",
"buildEnvironment": "Local"
}
Testing
Test Locale
- Creare manualmente
Data_Coupler/wwwroot/version.json:
{
"version": "2.1.0-dev",
"commitSha": "local",
"branch": "dev",
"buildDate": "2026-02-02",
"buildEnvironment": "Local"
}
- Eseguire l'applicazione:
dotnet run --project Data_Coupler/Data_Coupler.csproj
- Verificare nel NavMenu la versione "Data_Coupler v2.1.0-dev"
Test Docker
Dopo il build e push tramite Gitea Actions:
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:
- Verificare che
version.jsonsia stato generato nel workflow - Controllare i logs del workflow Gitea
- Verificare che il file sia incluso nel Docker image:
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:
builder.Services.AddSingleton<Data_Coupler.Services.IVersionService, Data_Coupler.Services.VersionService>();
Problema: version.json non caricato
Sintomo: Logs mostrano "version.json not found"
Soluzione:
- Verificare che il file esista in
wwwroot/version.json - Controllare i permessi del file
- Verificare il path in
VersionService.cs:
var versionFilePath = Path.Combine(_env.ContentRootPath, "wwwroot", "version.json");
Best Practices
1. Aggiornamento Versione
- Aggiornare sempre
<Version>inData_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
- Health Check Endpoint:
app.MapGet("/version", (IVersionService versionService) =>
Results.Ok(versionService.GetVersion()));
- Footer con Versione Dettagliata:
<footer>
Build: @_versionInfo.CommitSha | Branch: @_versionInfo.Branch | @_versionInfo.BuildDate
</footer>
-
About Page: Creare una pagina dedicata con tutte le informazioni di versione
-
Notifiche di Aggiornamento: Sistema per notificare agli utenti quando è disponibile una nuova versione
Riferimenti
-
File Sorgenti:
Data_Coupler/Models/VersionInfo.csData_Coupler/Services/VersionService.csData_Coupler/Shared/NavMenu.razorData_Coupler/Program.cs.gitea/workflows/docker-build.yml
-
Documentazione Correlata:
GITHUB_ACTIONS_SETUP.mdDOCKER_DEPLOYMENT.md.gitea/workflows/README.md
Versione Documento: 1.0
Data Creazione: 2 Febbraio 2026
Autore: Alessio Dalsanto
Ultima Revisione: 2 Febbraio 2026