Initial SyncVito release with installer updater
This commit is contained in:
commit
b9e4c09f49
41 files changed
+4331
No files matched your search
@@ -0,0 +1,175 @@
|
||||
param(
|
||||
[switch]$NoVersionBump,
|
||||
[switch]$SkipPublish,
|
||||
[switch]$SkipGit,
|
||||
[string]$TargetVersion = ""
|
||||
)
|
||||
|
||||
$ErrorActionPreference = "Stop"
|
||||
$Root = Split-Path -Parent $MyInvocation.MyCommand.Path
|
||||
Set-Location -LiteralPath $Root
|
||||
|
||||
function Find-Python {
|
||||
foreach ($candidate in @("python", "py")) {
|
||||
try {
|
||||
& $candidate --version 2>$null | Out-Null
|
||||
if ($LASTEXITCODE -eq 0) { return $candidate }
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
throw "Python wurde nicht gefunden."
|
||||
}
|
||||
|
||||
function Find-InnoCompiler {
|
||||
$candidates = @(
|
||||
"$env:LOCALAPPDATA\Programs\Inno Setup 7\ISCC.exe",
|
||||
"$env:LOCALAPPDATA\Programs\Inno Setup 6\ISCC.exe",
|
||||
"$env:ProgramFiles\Inno Setup 7\ISCC.exe",
|
||||
"${env:ProgramFiles(x86)}\Inno Setup 7\ISCC.exe",
|
||||
"${env:ProgramFiles(x86)}\Inno Setup 6\ISCC.exe",
|
||||
"$env:ProgramFiles\Inno Setup 6\ISCC.exe"
|
||||
)
|
||||
foreach ($candidate in $candidates) {
|
||||
if (Test-Path -LiteralPath $candidate -PathType Leaf) { return $candidate }
|
||||
}
|
||||
throw "Inno Setup 6 oder 7 wurde nicht gefunden."
|
||||
}
|
||||
|
||||
function Write-Utf8NoBom {
|
||||
param([string]$LiteralPath, [string]$Content)
|
||||
[System.IO.File]::WriteAllText($LiteralPath, $Content, [System.Text.UTF8Encoding]::new($false))
|
||||
}
|
||||
|
||||
function Get-Sha256Hex {
|
||||
param([string]$LiteralPath)
|
||||
return (Get-FileHash -LiteralPath $LiteralPath -Algorithm SHA256).Hash.ToLowerInvariant()
|
||||
}
|
||||
|
||||
$VersionPath = Join-Path $Root "version.txt"
|
||||
$PyprojectPath = Join-Path $Root "pyproject.toml"
|
||||
$ChangelogPath = Join-Path $Root "CHANGELOG.md"
|
||||
$originalVersion = [System.IO.File]::ReadAllText($VersionPath, [System.Text.Encoding]::UTF8)
|
||||
$originalPyproject = [System.IO.File]::ReadAllText($PyprojectPath, [System.Text.Encoding]::UTF8)
|
||||
$currentVersion = $originalVersion.Trim()
|
||||
if ($currentVersion -notmatch '^\d+\.\d+\.\d+$') {
|
||||
throw "Ungültige Version in version.txt: $currentVersion"
|
||||
}
|
||||
|
||||
$appVersion = $currentVersion
|
||||
if (-not [string]::IsNullOrWhiteSpace($TargetVersion)) {
|
||||
if ($NoVersionBump) { throw "TargetVersion und NoVersionBump dürfen nicht gemeinsam verwendet werden." }
|
||||
if ($TargetVersion -notmatch '^\d+\.\d+\.\d+$') { throw "Ungültige Zielversion: $TargetVersion" }
|
||||
if ([version]$TargetVersion -le [version]$currentVersion) {
|
||||
throw "Die Zielversion $TargetVersion muss neuer als $currentVersion sein."
|
||||
}
|
||||
$appVersion = $TargetVersion
|
||||
}
|
||||
elseif (-not $NoVersionBump) {
|
||||
$parts = @($currentVersion.Split('.') | ForEach-Object { [int]$_ })
|
||||
$parts[2] += 1
|
||||
$appVersion = "$($parts[0]).$($parts[1]).$($parts[2])"
|
||||
}
|
||||
|
||||
$changelog = [System.IO.File]::ReadAllText($ChangelogPath, [System.Text.Encoding]::UTF8)
|
||||
$sectionPattern = '(?ms)^##\s+' + [regex]::Escape($appVersion) + '\s+.*?(?=^##\s+\d+\.\d+\.\d+\s+|\z)'
|
||||
$sectionMatch = [regex]::Match($changelog, $sectionPattern)
|
||||
if (-not $sectionMatch.Success) {
|
||||
throw "CHANGELOG.md enthält keinen Abschnitt für Version $appVersion."
|
||||
}
|
||||
$releaseNotes = "# SyncVito – Änderungsprotokoll`r`n`r`n$($sectionMatch.Value.Trim())`r`n"
|
||||
|
||||
$versionParts = @($appVersion.Split('.') | ForEach-Object { [int]$_ })
|
||||
$fileVersion = "$($versionParts[0]).$($versionParts[1]).$($versionParts[2]).0"
|
||||
$python = Find-Python
|
||||
$iscc = Find-InnoCompiler
|
||||
$sourceCommitted = $false
|
||||
|
||||
try {
|
||||
Write-Utf8NoBom -LiteralPath $VersionPath -Content "$appVersion`n"
|
||||
$versionRegex = [regex]::new('(?m)^(version\s*=\s*")[^"]+("\s*)$')
|
||||
$updatedPyproject = $versionRegex.Replace($originalPyproject, "`${1}$appVersion`${2}", 1)
|
||||
if ($updatedPyproject -eq $originalPyproject -and $appVersion -ne $currentVersion) {
|
||||
throw "Die Projektversion in pyproject.toml konnte nicht aktualisiert werden."
|
||||
}
|
||||
Write-Utf8NoBom -LiteralPath $PyprojectPath -Content $updatedPyproject
|
||||
|
||||
$buildRoot = Join-Path $Root "build"
|
||||
$appDist = Join-Path $buildRoot "app"
|
||||
$workPath = Join-Path $buildRoot "pyinstaller"
|
||||
New-Item -ItemType Directory -Force -Path $buildRoot, $appDist | Out-Null
|
||||
|
||||
$versionInfoPath = Join-Path $buildRoot "version_info.txt"
|
||||
$versionInfo = @"
|
||||
VSVersionInfo(
|
||||
ffi=FixedFileInfo(filevers=($($versionParts[0]), $($versionParts[1]), $($versionParts[2]), 0), prodvers=($($versionParts[0]), $($versionParts[1]), $($versionParts[2]), 0), mask=0x3f, flags=0x0, OS=0x40004, fileType=0x1, subtype=0x0, date=(0, 0)),
|
||||
kids=[StringFileInfo([StringTable('040704B0', [StringStruct('CompanyName', 'Davito'), StringStruct('FileDescription', 'SyncVito'), StringStruct('FileVersion', '$fileVersion'), StringStruct('InternalName', 'SyncVito'), StringStruct('OriginalFilename', 'SyncVito.exe'), StringStruct('ProductName', 'SyncVito'), StringStruct('ProductVersion', '$appVersion')])]), VarFileInfo([VarStruct('Translation', [1031, 1200])])]
|
||||
)
|
||||
"@
|
||||
Write-Utf8NoBom -LiteralPath $versionInfoPath -Content $versionInfo
|
||||
|
||||
Write-Host "Tests werden ausgeführt …"
|
||||
& $python -m pytest
|
||||
if ($LASTEXITCODE -ne 0) { throw "Die Tests sind fehlgeschlagen." }
|
||||
& $python -m ruff check .
|
||||
if ($LASTEXITCODE -ne 0) { throw "Ruff hat Fehler gefunden." }
|
||||
|
||||
Write-Host "Programmsymbol wird erzeugt …"
|
||||
& $python tools\generate_icon.py
|
||||
if ($LASTEXITCODE -ne 0) { throw "Das Programmsymbol konnte nicht erzeugt werden." }
|
||||
|
||||
Write-Host "Baue SyncVito.exe mit PyInstaller …"
|
||||
& $python -m PyInstaller --noconfirm --clean --distpath $appDist --workpath $workPath SyncVito.spec
|
||||
if ($LASTEXITCODE -ne 0) { throw "Der PyInstaller-Build ist fehlgeschlagen." }
|
||||
$appExe = Join-Path $appDist "SyncVito.exe"
|
||||
if (-not (Test-Path -LiteralPath $appExe -PathType Leaf)) { throw "SyncVito.exe wurde nicht erzeugt." }
|
||||
|
||||
Write-Host "Prüfe den gebauten Programmstart …"
|
||||
$smoke = Start-Process -FilePath $appExe -ArgumentList "--smoke-test" -PassThru -Wait -WindowStyle Hidden
|
||||
if ($smoke.ExitCode -ne 0) { throw "Der EXE-Smoke-Test ist fehlgeschlagen (Exitcode $($smoke.ExitCode))." }
|
||||
|
||||
New-Item -ItemType Directory -Force -Path (Join-Path $Root "release") | Out-Null
|
||||
Write-Host "Baue Windows-Installer …"
|
||||
& $iscc "/DMyAppVersion=$appVersion" "/DMyAppFileVersion=$fileVersion" "/DMyAppExeSource=$appExe" (Join-Path $Root "installer\SyncVito.iss")
|
||||
if ($LASTEXITCODE -ne 0) { throw "Der Inno-Setup-Build ist fehlgeschlagen." }
|
||||
|
||||
$installerName = "SyncVitoSetup-$appVersion.exe"
|
||||
$installerPath = Join-Path $Root "release\$installerName"
|
||||
if (-not (Test-Path -LiteralPath $installerPath -PathType Leaf)) { throw "Installer wurde nicht gefunden: $installerPath" }
|
||||
$hash = Get-Sha256Hex -LiteralPath $installerPath
|
||||
$checksumPath = "$installerPath.sha256"
|
||||
Write-Utf8NoBom -LiteralPath $checksumPath -Content "$hash *$installerName`n"
|
||||
$releaseChangelogPath = Join-Path $Root "release\CHANGELOG-$appVersion.md"
|
||||
Write-Utf8NoBom -LiteralPath $releaseChangelogPath -Content $releaseNotes
|
||||
|
||||
if (-not $SkipGit) {
|
||||
git add --all
|
||||
if ($LASTEXITCODE -ne 0) { throw "Git konnte die Release-Änderungen nicht vormerken." }
|
||||
git diff --cached --quiet
|
||||
if ($LASTEXITCODE -ne 0) {
|
||||
git commit -m "Release SyncVito $appVersion"
|
||||
if ($LASTEXITCODE -ne 0) { throw "Der Release-Commit ist fehlgeschlagen." }
|
||||
}
|
||||
$sourceCommitted = $true
|
||||
git push origin main
|
||||
if ($LASTEXITCODE -ne 0) { throw "Der Quellstand konnte nicht nach Gitea gepusht werden." }
|
||||
}
|
||||
|
||||
if (-not $SkipPublish) {
|
||||
& (Join-Path $Root "publish_gitea_release.ps1") -Version $appVersion
|
||||
if ($LASTEXITCODE -ne 0) { throw "Der Gitea-Release ist fehlgeschlagen." }
|
||||
}
|
||||
|
||||
Write-Host ""
|
||||
Write-Host "Release-Workflow abgeschlossen:"
|
||||
Write-Host " Installer: $installerPath"
|
||||
Write-Host " Prüfsumme: $checksumPath"
|
||||
Write-Host " SHA256: $hash"
|
||||
}
|
||||
catch {
|
||||
if (-not $sourceCommitted) {
|
||||
Write-Utf8NoBom -LiteralPath $VersionPath -Content $originalVersion
|
||||
Write-Utf8NoBom -LiteralPath $PyprojectPath -Content $originalPyproject
|
||||
Write-Warning "Build fehlgeschlagen; Versionsdateien wurden zurückgesetzt."
|
||||
}
|
||||
throw
|
||||
}
|
||||
Reference in new issue
Block a user