param( [ValidateSet('apk', 'appbundle', 'windows', 'web', 'ios', 'ipa', 'macos', 'linux')] [string]$Target = 'apk', [string]$FlutterCommand = 'flutter', [string[]]$FlutterArguments = @() ) $ErrorActionPreference = 'Stop' $projectRoot = Split-Path -Parent $PSScriptRoot $pubspecPath = Join-Path $projectRoot 'pubspec.yaml' $lockPath = Join-Path $projectRoot '.release-build.lock' $buildLock = $null $originalBytes = $null $updated = $false $succeeded = $false try { # Hold an exclusive lock; the OS releases it even if PowerShell is closed. $buildLock = [System.IO.File]::Open( $lockPath, [System.IO.FileMode]::OpenOrCreate, [System.IO.FileAccess]::ReadWrite, [System.IO.FileShare]::None ) foreach ($argument in $FlutterArguments) { if ($argument -match '^--(build-name|build-number|debug|profile|config-only)(=|$)') { throw "Argument $argument ist im versionierten Release-Build nicht erlaubt." } } $originalBytes = [System.IO.File]::ReadAllBytes($pubspecPath) $source = [System.Text.Encoding]::UTF8.GetString($originalBytes) $versionMatch = [regex]::Match($source, '(?m)^version:\s*(\d+)\.(\d+)\.(\d+)\+(\d+)[ \t]*\r?$') if (-not $versionMatch.Success) { throw 'In pubspec.yaml wird eine Version wie 1.0.0+1 erwartet.' } $patch = [long]::Parse($versionMatch.Groups[3].Value) + 1 $build = [long]::Parse($versionMatch.Groups[4].Value) + 1 $nextVersion = '{0}.{1}.{2}+{3}' -f $versionMatch.Groups[1].Value, $versionMatch.Groups[2].Value, $patch, $build $replacement = "version: $nextVersion" if ($versionMatch.Value.EndsWith("`r")) { $replacement += "`r" } $nextSource = $source.Remove($versionMatch.Index, $versionMatch.Length).Insert($versionMatch.Index, $replacement) [System.IO.File]::WriteAllText($pubspecPath, $nextSource, [System.Text.UTF8Encoding]::new($false)) $updated = $true Push-Location $projectRoot try { Write-Host "Release $nextVersion ($Target) wird erstellt ..." $global:LASTEXITCODE = 0 & $FlutterCommand build $Target --release @FlutterArguments if ($LASTEXITCODE -ne 0) { throw "Flutter-Build fehlgeschlagen (Exitcode $LASTEXITCODE)." } $succeeded = $true Write-Host "Release $nextVersion erfolgreich. Die Version wurde in pubspec.yaml gespeichert." } finally { Pop-Location } } finally { if ($updated -and -not $succeeded) { [System.IO.File]::WriteAllBytes($pubspecPath, $originalBytes) Write-Host 'Build nicht erfolgreich: Bisherige Version wiederhergestellt.' } if ($null -ne $buildLock) { $buildLock.Dispose() } }