mirror of
https://gitlab.com/MaddoScientisto/cirnogodot.git
synced 2026-06-01 08:55:35 +00:00
401 lines
14 KiB
PowerShell
401 lines
14 KiB
PowerShell
# CirnoBuild.psm1
|
|
# Common functions for building and publishing Cirno No Reason
|
|
|
|
# Configuration
|
|
$script:gitVersionPath = "dotnet-gitversion.exe"
|
|
$script:configFile = "export_presets.cfg"
|
|
$script:fileName = "Cirno_No_Reason"
|
|
|
|
# Platform configurations
|
|
$script:platforms = @{
|
|
"win" = @{
|
|
ExportName = "Windows Desktop"
|
|
Extension = ".exe"
|
|
OutputSubDir = "win"
|
|
}
|
|
"linux" = @{
|
|
ExportName = "Linux"
|
|
Extension = ".x86_64"
|
|
OutputSubDir = "linux"
|
|
}
|
|
}
|
|
|
|
function Test-Prerequisites {
|
|
<#
|
|
.SYNOPSIS
|
|
Validates that required tools are available
|
|
|
|
.PARAMETER GodotPath
|
|
Path to Godot executable
|
|
|
|
.PARAMETER SkipButler
|
|
Skip Butler validation (not needed for build-only operations)
|
|
#>
|
|
param(
|
|
[string]$GodotPath,
|
|
[string]$ButlerPath,
|
|
[switch]$SkipButler
|
|
)
|
|
|
|
$errors = @()
|
|
|
|
if ([string]::IsNullOrWhiteSpace($GodotPath)) {
|
|
$errors += "GODOT environment variable is not set. Please set it to your Godot executable path."
|
|
$errors += "Example: `$env:GODOT = 'C:\Godot\Godot_v4.x.exe'"
|
|
} elseif (-not (Test-Path $GodotPath)) {
|
|
# Try to resolve from PATH if it's just an executable name
|
|
$resolvedPath = Get-Command $GodotPath -ErrorAction SilentlyContinue | Select-Object -ExpandProperty Source
|
|
if ($resolvedPath) {
|
|
Write-Host " Resolved Godot path: $resolvedPath" -ForegroundColor Gray
|
|
# Update the caller's variable
|
|
return @{
|
|
Valid = $true
|
|
ResolvedGodotPath = $resolvedPath
|
|
}
|
|
} else {
|
|
$errors += "Godot executable not found at: $GodotPath"
|
|
$errors += "Please update the GODOT environment variable or add Godot to PATH."
|
|
}
|
|
}
|
|
|
|
if (-not (Test-Path $script:gitVersionPath) -and -not (Get-Command $script:gitVersionPath -ErrorAction SilentlyContinue)) {
|
|
$errors += "GitVersion not found. Please install dotnet-gitversion or add it to PATH."
|
|
}
|
|
|
|
if (-not $SkipButler) {
|
|
if ([string]::IsNullOrWhiteSpace($ButlerPath)) {
|
|
$errors += "Butler path is not configured."
|
|
} elseif (-not (Test-Path $ButlerPath)) {
|
|
$errors += "Butler executable not found at: $ButlerPath"
|
|
}
|
|
}
|
|
|
|
if ($errors.Count -gt 0) {
|
|
Write-Host ""
|
|
Write-Host "ERROR: Missing Prerequisites" -ForegroundColor Red
|
|
Write-Host "=====================================" -ForegroundColor Red
|
|
foreach ($error in $errors) {
|
|
Write-Host " $error" -ForegroundColor Yellow
|
|
}
|
|
Write-Host ""
|
|
return @{
|
|
Valid = $false
|
|
}
|
|
}
|
|
|
|
return @{
|
|
Valid = $true
|
|
ResolvedGodotPath = $GodotPath
|
|
}
|
|
}
|
|
|
|
function Get-VersionInfo {
|
|
<#
|
|
.SYNOPSIS
|
|
Gets version information from GitVersion
|
|
#>
|
|
Write-Host "Getting version information..." -ForegroundColor Cyan
|
|
$gitVersionOutput = & $script:gitVersionPath | ConvertFrom-Json
|
|
|
|
$versionInfo = @{
|
|
AssemblySemFileVer = $gitVersionOutput.AssemblySemFileVer
|
|
AssemblySemVer = $gitVersionOutput.AssemblySemVer
|
|
FullSemVer = $gitVersionOutput.FullSemVer
|
|
PreReleaseLabel = $gitVersionOutput.PreReleaseLabelWithDash
|
|
}
|
|
|
|
[System.Environment]::SetEnvironmentVariable("GIT_ASSEMBLY_SEM_FILE_VER", $versionInfo.AssemblySemFileVer, [System.EnvironmentVariableTarget]::Process)
|
|
[System.Environment]::SetEnvironmentVariable("GIT_ASSEMBLY_SEM_VER", $versionInfo.AssemblySemVer, [System.EnvironmentVariableTarget]::Process)
|
|
|
|
Write-Host " Version: $($versionInfo.FullSemVer)" -ForegroundColor Green
|
|
Write-Host " File Version: $($versionInfo.AssemblySemFileVer)" -ForegroundColor Green
|
|
|
|
return $versionInfo
|
|
}
|
|
|
|
function Initialize-BuildDirectories {
|
|
<#
|
|
.SYNOPSIS
|
|
Creates and clears build directories for specified platforms
|
|
#>
|
|
param(
|
|
[string[]]$PlatformsToBuild,
|
|
[string]$BuildDir
|
|
)
|
|
|
|
Write-Host "Initializing build directories..." -ForegroundColor Cyan
|
|
|
|
# Ensure the root build directory exists but DO NOT delete its contents (preserve logs and zips)
|
|
if (-not (Test-Path $BuildDir)) {
|
|
New-Item -ItemType Directory -Path $BuildDir | Out-Null
|
|
}
|
|
|
|
foreach ($platform in $PlatformsToBuild) {
|
|
$platformDir = Join-Path $BuildDir $script:platforms[$platform].OutputSubDir
|
|
if (Test-Path $platformDir) {
|
|
# Clear only the platform directory contents
|
|
Remove-Item "$platformDir\*" -Recurse -Force -ErrorAction SilentlyContinue
|
|
} else {
|
|
New-Item -ItemType Directory -Path $platformDir -Force | Out-Null
|
|
}
|
|
Write-Host " Prepared: $platformDir" -ForegroundColor Gray
|
|
}
|
|
}
|
|
|
|
function Update-ExportConfig {
|
|
<#
|
|
.SYNOPSIS
|
|
Updates export_presets.cfg with version information
|
|
#>
|
|
param($VersionInfo)
|
|
|
|
Write-Host "Updating export configuration..." -ForegroundColor Cyan
|
|
|
|
if (Test-Path $script:configFile) {
|
|
(Get-Content $script:configFile) `
|
|
-replace 'application/file_version="[^"]*"', "application/file_version=`"$($VersionInfo.AssemblySemFileVer)`"" `
|
|
-replace 'application/product_version="[^"]*"', "application/product_version=`"$($VersionInfo.AssemblySemVer)`"" `
|
|
| Set-Content $script:configFile
|
|
Write-Host " Export config updated successfully" -ForegroundColor Green
|
|
} else {
|
|
Write-Host " WARNING: $script:configFile not found!" -ForegroundColor Red
|
|
}
|
|
}
|
|
|
|
function Wait-ForExportCompletion {
|
|
<#
|
|
.SYNOPSIS
|
|
Monitors export output file until it's complete
|
|
#>
|
|
param(
|
|
[string]$OutputPath,
|
|
[int]$TimeoutSeconds = 300
|
|
)
|
|
|
|
$startTime = Get-Date
|
|
$checkInterval = 2
|
|
$lastSize = -1
|
|
$stableCount = 0
|
|
$requiredStableChecks = 3
|
|
|
|
Write-Host " Waiting for export to complete: $OutputPath" -ForegroundColor Gray
|
|
|
|
while (((Get-Date) - $startTime).TotalSeconds -lt $TimeoutSeconds) {
|
|
Start-Sleep -Seconds $checkInterval
|
|
|
|
if (Test-Path $OutputPath) {
|
|
$currentSize = (Get-Item $OutputPath).Length
|
|
|
|
if ($currentSize -eq $lastSize -and $currentSize -gt 0) {
|
|
$stableCount++
|
|
if ($stableCount -ge $requiredStableChecks) {
|
|
Write-Host " Export completed: $OutputPath ($currentSize bytes)" -ForegroundColor Green
|
|
return $true
|
|
}
|
|
} else {
|
|
$stableCount = 0
|
|
}
|
|
|
|
$lastSize = $currentSize
|
|
}
|
|
}
|
|
|
|
Write-Host " WARNING: Export timeout reached for $OutputPath" -ForegroundColor Yellow
|
|
return (Test-Path $OutputPath)
|
|
}
|
|
|
|
function Create-PlatformZip {
|
|
<#
|
|
.SYNOPSIS
|
|
Creates a zip archive for a platform build
|
|
|
|
.PARAMETER Platform
|
|
Platform identifier (win, linux)
|
|
|
|
.PARAMETER BuildDir
|
|
Build directory path
|
|
|
|
.PARAMETER VersionInfo
|
|
Optional version information hashtable (if provided, includes version in filename)
|
|
|
|
.PARAMETER Force
|
|
Force recreate zip even if it exists
|
|
|
|
.RETURNS
|
|
Path to the created zip file, or $null if failed
|
|
#>
|
|
param(
|
|
[string]$Platform,
|
|
[string]$BuildDir,
|
|
[hashtable]$VersionInfo = $null,
|
|
[switch]$Force
|
|
)
|
|
|
|
$platformConfig = $script:platforms[$Platform]
|
|
$platformDir = Join-Path $BuildDir $platformConfig.OutputSubDir
|
|
|
|
# Determine zip filename (with or without version)
|
|
if ($VersionInfo) {
|
|
$zipFileName = "$script:fileName.$($VersionInfo.FullSemVer).$Platform.zip"
|
|
} else {
|
|
$zipFileName = "$script:fileName.$Platform.zip"
|
|
}
|
|
$zipFilePath = Join-Path $BuildDir $zipFileName
|
|
|
|
# Check if zip already exists and force not specified
|
|
if ((Test-Path $zipFilePath) -and -not $Force) {
|
|
Write-Host " Using existing zip: $zipFilePath" -ForegroundColor Gray
|
|
return $zipFilePath
|
|
}
|
|
|
|
# Validate source files exist
|
|
$files = Get-ChildItem -Path $platformDir -Recurse -File -ErrorAction SilentlyContinue
|
|
if (-not $files) {
|
|
Write-Host " ERROR: No files found in $platformDir" -ForegroundColor Red
|
|
return $null
|
|
}
|
|
|
|
# Create zip
|
|
Write-Host " Creating zip archive: $zipFileName" -ForegroundColor Cyan
|
|
try {
|
|
# Do not explicitly delete existing zip to avoid losing historical artifacts; Compress-Archive -Force will overwrite
|
|
Compress-Archive -Path "$platformDir\*" -DestinationPath $zipFilePath -Force
|
|
Write-Host " Zip created: $zipFilePath" -ForegroundColor Green
|
|
return $zipFilePath
|
|
} catch {
|
|
Write-Host " ERROR: Failed to create zip: $($_.Exception.Message)" -ForegroundColor Red
|
|
return $null
|
|
}
|
|
}
|
|
|
|
function Export-GodotPlatform {
|
|
<#
|
|
.SYNOPSIS
|
|
Exports a single platform build using Godot - simple and direct
|
|
#>
|
|
param(
|
|
[string]$Platform,
|
|
[string]$GodotPath,
|
|
[string]$BuildDir,
|
|
[hashtable]$VersionInfo = $null
|
|
)
|
|
|
|
$platformConfig = $script:platforms[$Platform]
|
|
$outputPath = Join-Path $BuildDir "$($platformConfig.OutputSubDir)\$script:fileName$($platformConfig.Extension)"
|
|
|
|
Write-Host "Exporting $Platform build..." -ForegroundColor Cyan
|
|
Write-Host " Export Name: $($platformConfig.ExportName)" -ForegroundColor Gray
|
|
Write-Host " Output: $outputPath" -ForegroundColor Gray
|
|
Write-Host ""
|
|
|
|
if (Test-Path $outputPath) { Remove-Item $outputPath -Force }
|
|
|
|
$timeStamp = (Get-Date).ToString('yyyyMMdd-HHmmss')
|
|
# Put log in parent build folder, not in platform subfolder (avoid including in zip)
|
|
$logPath = Join-Path $BuildDir "godot-export-$Platform-$timeStamp.log"
|
|
|
|
$exportName = $platformConfig.ExportName
|
|
|
|
Write-Host "--- Godot Export Output ---" -ForegroundColor DarkGray
|
|
Write-Host "Logging to: $logPath" -ForegroundColor DarkGray
|
|
Write-Host ""
|
|
|
|
# Save current encoding and set to UTF8 to handle Godot's Unicode output
|
|
$previousEncoding = [Console]::OutputEncoding
|
|
try {
|
|
[Console]::OutputEncoding = [System.Text.Encoding]::UTF8
|
|
|
|
# Run Godot directly - output streams to console and gets logged
|
|
& $GodotPath --headless --export-release $exportName $outputPath 2>&1 | Tee-Object -FilePath $logPath | ForEach-Object { Write-Host $_ }
|
|
} catch {
|
|
Write-Host " ERROR: Failed to execute Godot: $($_.Exception.Message)" -ForegroundColor Red
|
|
return $false
|
|
} finally {
|
|
# Restore previous encoding
|
|
[Console]::OutputEncoding = $previousEncoding
|
|
}
|
|
|
|
Write-Host ""
|
|
Write-Host "--- Export command completed ---" -ForegroundColor DarkGray
|
|
Write-Host ""
|
|
|
|
# Wait for the file to be created and stabilize
|
|
$success = Wait-ForExportCompletion -OutputPath $outputPath -TimeoutSeconds 30
|
|
|
|
if ($success) {
|
|
Write-Host " $Platform export completed successfully!" -ForegroundColor Green
|
|
|
|
# Create zip file after successful export (with version if provided)
|
|
$zipPath = Create-PlatformZip -Platform $Platform -BuildDir $BuildDir -VersionInfo $VersionInfo -Force
|
|
if (-not $zipPath) {
|
|
Write-Host " WARNING: Export succeeded but zip creation failed" -ForegroundColor Yellow
|
|
}
|
|
} else {
|
|
Write-Host " ERROR: $Platform export may have failed!" -ForegroundColor Red
|
|
Write-Host " Check log: $logPath" -ForegroundColor Yellow
|
|
}
|
|
|
|
return $success
|
|
}
|
|
|
|
function Publish-PlatformBuild {
|
|
<#
|
|
.SYNOPSIS
|
|
Publishes a platform build to itch.io
|
|
#>
|
|
param(
|
|
[string]$Platform,
|
|
[hashtable]$VersionInfo,
|
|
[string]$BuildDir,
|
|
[string]$ReleaseDir,
|
|
[string]$ButlerPath
|
|
)
|
|
|
|
$platformConfig = $script:platforms[$Platform]
|
|
$butlerTarget = "maddoscientisto/cirno-no-reason:$Platform$($VersionInfo.PreReleaseLabel)"
|
|
|
|
Write-Host "Publishing $Platform build..." -ForegroundColor Cyan
|
|
|
|
# Ensure zip exists with version number (create if missing)
|
|
$zipFilePath = Create-PlatformZip -Platform $Platform -BuildDir $BuildDir -VersionInfo $VersionInfo
|
|
if (-not $zipFilePath) {
|
|
Write-Host " ERROR: Failed to get or create zip file" -ForegroundColor Red
|
|
return $false
|
|
}
|
|
|
|
# Ensure release directory exists
|
|
if (!(Test-Path $ReleaseDir)) {
|
|
New-Item -ItemType Directory -Path $ReleaseDir | Out-Null
|
|
}
|
|
|
|
# Copy versioned zip to release directory
|
|
$zipFileName = Split-Path $zipFilePath -Leaf
|
|
$releaseZipPath = Join-Path $ReleaseDir $zipFileName
|
|
Copy-Item -Path $zipFilePath -Destination $releaseZipPath -Force
|
|
Write-Host " Copied to release: $zipFileName" -ForegroundColor Gray
|
|
|
|
# Push to itch.io
|
|
Write-Host " Pushing to itch.io: $butlerTarget" -ForegroundColor Gray
|
|
& $ButlerPath push $releaseZipPath $butlerTarget --userversion $VersionInfo.FullSemVer
|
|
|
|
if ($LASTEXITCODE -eq 0) {
|
|
Write-Host " $Platform published successfully!" -ForegroundColor Green
|
|
return $true
|
|
} else {
|
|
Write-Host " ERROR: Failed to publish $Platform build" -ForegroundColor Red
|
|
return $false
|
|
}
|
|
}
|
|
|
|
function Get-PlatformConfigurations {
|
|
<#
|
|
.SYNOPSIS
|
|
Returns platform configuration hashtable
|
|
#>
|
|
return $script:platforms
|
|
}
|
|
|
|
# Export functions
|
|
Export-ModuleMember -Function Test-Prerequisites, Get-VersionInfo, Initialize-BuildDirectories, `
|
|
Update-ExportConfig, Wait-ForExportCompletion, Create-PlatformZip, Export-GodotPlatform, `
|
|
Publish-PlatformBuild, Get-PlatformConfigurations
|