Functions/Build-Workflow.ps1

# Build Workflow Functions
# Complete build, copy, and attach workflow for releases

function Start-BuildWorkflow {
    <#
    .SYNOPSIS
    Executes a complete build workflow including building, copying files, and preparing for release.
     
    .DESCRIPTION
    This function provides a complete build workflow that:
    1. Builds the project in specified configuration
    2. Finds all built files (DLL, EXE, etc.)
    3. Copies files to release locations
    4. Optionally creates archives
    5. Prepares files for GitHub release attachment
     
    .PARAMETER ProjectPath
    Path to the project file or directory.
     
    .PARAMETER Configuration
    Build configuration (Release, Debug, etc.). Default: Release
     
    .PARAMETER Architecture
    Target architecture (win-x64, win-x86, etc.). Default: win-x64
     
    .PARAMETER Framework
    Target framework (net8.0, net6.0, etc.). Default: net8.0
     
    .PARAMETER AssemblyName
    Name of the main assembly. If not specified, will be extracted from project file.
     
    .PARAMETER OutputDirectory
    Directory to copy built files to. Default: ./dist/
     
    .PARAMETER CreateArchive
    Whether to create ZIP archives of the built files.
     
    .PARAMETER ArchiveName
    Name for the archive file (without extension).
     
    .PARAMETER IncludeDebugFiles
    Whether to include debug files (.pdb) in the output.
     
    .PARAMETER CleanOutput
    Whether to clean the output directory before copying files.
     
    .PARAMETER PublishMode
    Whether to use publish mode instead of regular build.
     
    .EXAMPLE
    Start-BuildWorkflow -ProjectPath "MyApp.csproj" -Configuration "Release" -Architecture "win-x64"
     
    .EXAMPLE
    Start-BuildWorkflow -ProjectPath "MyApp.csproj" -CreateArchive -ArchiveName "MyApp-v1.0" -PublishMode
    #>

    [CmdletBinding()]
    param(
        [Parameter(Mandatory = $true)]
        [string]$ProjectPath,
        
        [Parameter(Mandatory = $false)]
        [string]$Configuration = "Release",
        
        [Parameter(Mandatory = $false)]
        [string]$Architecture = "win-x64",
        
        [Parameter(Mandatory = $false)]
        [string]$Framework = "net8.0",
        
        [Parameter(Mandatory = $false)]
        [string]$AssemblyName,
        
        [Parameter(Mandatory = $false)]
        [string]$OutputDirectory = "./dist/",
        
        [Parameter(Mandatory = $false)]
        [switch]$CreateArchive,
        
        [Parameter(Mandatory = $false)]
        [string]$ArchiveName,
        
        [Parameter(Mandatory = $false)]
        [switch]$IncludeDebugFiles,
        
        [Parameter(Mandatory = $false)]
        [switch]$CleanOutput,
        
        [Parameter(Mandatory = $false)]
        [switch]$PublishMode
    )
    
    Write-Host "🚀 Starting Build Workflow" -ForegroundColor Cyan
    Write-Host "Project: $ProjectPath" -ForegroundColor Gray
    Write-Host "Configuration: $Configuration" -ForegroundColor Gray
    Write-Host "Architecture: $Architecture" -ForegroundColor Gray
    Write-Host "Framework: $Framework" -ForegroundColor Gray
    Write-Host ""
    
    # Step 1: Extract project information
    $projectInfo = Get-ProjectInfo -ProjectPath $ProjectPath
    if (-not $AssemblyName) {
        $AssemblyName = $projectInfo.AssemblyName
    }
    
    Write-Host "📋 Project Information:" -ForegroundColor Green
    Write-Host " Assembly Name: $AssemblyName" -ForegroundColor Gray
    Write-Host " Project Directory: $($projectInfo.ProjectDir)" -ForegroundColor Gray
    Write-Host ""
    
    # Step 2: Build the project
    Write-Host "🔨 Building project..." -ForegroundColor Green
    
    if ($PublishMode) {
        if (-not (Get-Command Dotnet-Publish -ErrorAction SilentlyContinue)) {
            throw "Dotnet-Publish command not found in Bluscream-BuildTools module"
        }
        
        $buildResult = Dotnet-Publish -ProjectPath $ProjectPath -Configuration $Configuration -Architecture $Architecture -Framework $Framework
        if (-not $buildResult) {
            throw "Publish build failed"
        }
    }
    else {
        if (-not (Get-Command Dotnet-Build -ErrorAction SilentlyContinue)) {
            throw "Dotnet-Build command not found in Bluscream-BuildTools module"
        }
        
        $buildResult = Dotnet-Build -ProjectPath $ProjectPath -Configuration $Configuration -Architecture $Architecture -Framework $Framework
        if (-not $buildResult) {
            throw "Build failed"
        }
    }
    
    Write-Host "✓ Build completed successfully" -ForegroundColor Green
    Write-Host ""
    
    # Step 3: Find all built files
    Write-Host "🔍 Finding built files..." -ForegroundColor Green
    
    $builtFiles = @()
    $fileTypes = @(
        @{ Extension = ".exe"; Type = "executable" },
        @{ Extension = ".dll"; Type = "library" },
        @{ Extension = ".pdb"; Type = "debug symbols" }
    )
    
    foreach ($fileType in $fileTypes) {
        if ($fileType.Extension -eq ".pdb" -and -not $IncludeDebugFiles) {
            continue
        }
        
        $foundFile = Find-BuiltFile -Config $Configuration -Arch $Architecture -ProjectFramework $Framework -AssemblyName $AssemblyName -FileExtension $fileType.Extension -FileType $fileType.Type -IsPublish:$PublishMode -ProjectDir $projectInfo.ProjectDir
        
        if ($foundFile) {
            $builtFiles += $foundFile
        }
    }
    
    if ($builtFiles.Count -eq 0) {
        throw "No built files found"
    }
    
    Write-Host "✓ Found $($builtFiles.Count) built files" -ForegroundColor Green
    Write-Host ""
    
    # Step 4: Prepare output directory
    if ($CleanOutput -and (Test-Path $OutputDirectory)) {
        Write-Host "🧹 Cleaning output directory..." -ForegroundColor Yellow
        Remove-Item $OutputDirectory -Recurse -Force
    }
    
    if (-not (Test-Path $OutputDirectory)) {
        New-Item -ItemType Directory -Path $OutputDirectory -Force | Out-Null
        Write-Host "✓ Created output directory: $OutputDirectory" -ForegroundColor Green
    }
    
    # Step 5: Copy files to output directory
    Write-Host "📋 Copying files to output directory..." -ForegroundColor Green
    
    $copiedFiles = @()
    foreach ($file in $builtFiles) {
        $destinationPath = Join-Path $OutputDirectory $file.Name
        Copy-Item $file.FullName $destinationPath -Force
        $copiedFiles += $destinationPath
        Write-Host " ✓ Copied: $($file.Name)" -ForegroundColor Gray
    }
    
    Write-Host "✓ Copied $($copiedFiles.Count) files to $OutputDirectory" -ForegroundColor Green
    Write-Host ""
    
    # Step 6: Create archive if requested
    $archivePath = $null
    if ($CreateArchive) {
        Write-Host "📦 Creating archive..." -ForegroundColor Green
        
        if (-not $ArchiveName) {
            $ArchiveName = "$AssemblyName-$Configuration-$Architecture"
        }
        
        $archivePath = "$OutputDirectory$ArchiveName.zip"
        
        if (Test-Path $archivePath) {
            Remove-Item $archivePath -Force
        }
        
        Compress-Archive -Path $copiedFiles -DestinationPath $archivePath -Force
        Write-Host "✓ Created archive: $archivePath" -ForegroundColor Green
        Write-Host ""
    }
    
    # Step 7: Prepare release information
    $releaseInfo = @{
        ProjectPath     = $ProjectPath
        Configuration   = $Configuration
        Architecture    = $Architecture
        Framework       = $Framework
        AssemblyName    = $AssemblyName
        OutputDirectory = $OutputDirectory
        BuiltFiles      = $builtFiles
        CopiedFiles     = $copiedFiles
        ArchivePath     = $archivePath
        Success         = $true
    }
    
    Write-Host "🎉 Build Workflow Completed Successfully!" -ForegroundColor Green
    Write-Host "Output Directory: $OutputDirectory" -ForegroundColor Cyan
    Write-Host "Files: $($copiedFiles.Count)" -ForegroundColor Cyan
    if ($archivePath) {
        Write-Host "Archive: $archivePath" -ForegroundColor Cyan
    }
    Write-Host ""
    
    return $releaseInfo
}

function Get-ProjectInfo {
    <#
    .SYNOPSIS
    Extracts project information from a .NET project file.
     
    .DESCRIPTION
    Parses a .NET project file to extract assembly name, project directory, and other relevant information.
     
    .PARAMETER ProjectPath
    Path to the project file.
     
    .EXAMPLE
    Get-ProjectInfo -ProjectPath "MyApp.csproj"
    #>

    [CmdletBinding()]
    param(
        [Parameter(Mandatory = $true)]
        [string]$ProjectPath
    )
    
    if (-not (Test-Path $ProjectPath)) {
        throw "Project file not found: $ProjectPath"
    }
    
    $projectDir = Split-Path $ProjectPath -Parent
    $projectContent = Get-Content $ProjectPath -Raw
    
    # Extract assembly name
    $assemblyName = $null
    if ($projectContent -match '<AssemblyName>([^<]+)</AssemblyName>') {
        $assemblyName = $Matches[1]
    }
    elseif ($projectContent -match '<AssemblyName>([^<]+)</AssemblyName>') {
        $assemblyName = $Matches[1]
    }
    else {
        # Fallback to project file name without extension
        $assemblyName = [System.IO.Path]::GetFileNameWithoutExtension($ProjectPath)
    }
    
    # Extract target framework
    $targetFramework = $null
    if ($projectContent -match '<TargetFramework>([^<]+)</TargetFramework>') {
        $targetFramework = $Matches[1]
    }
    elseif ($projectContent -match '<TargetFrameworks>([^<]+)</TargetFrameworks>') {
        $targetFramework = ($Matches[1] -split ';')[0]  # Take first framework
    }
    
    return @{
        ProjectPath     = $ProjectPath
        ProjectDir      = $projectDir
        AssemblyName    = $assemblyName
        TargetFramework = $targetFramework
    }
}

function New-ReleasePackage {
    <#
    .SYNOPSIS
    Creates a complete release package with all necessary files and metadata.
     
    .DESCRIPTION
    Creates a release package that includes built files, metadata, and optionally archives for distribution.
     
    .PARAMETER ReleaseInfo
    Release information object from Start-BuildWorkflow.
     
    .PARAMETER Version
    Version number for the release.
     
    .PARAMETER ReleaseNotes
    Release notes for the release.
     
    .PARAMETER CreateArchives
    Whether to create ZIP archives for different architectures.
     
    .EXAMPLE
    New-ReleasePackage -ReleaseInfo $releaseInfo -Version "1.0.0" -CreateArchives
    #>

    [CmdletBinding()]
    param(
        [Parameter(Mandatory = $true)]
        [hashtable]$ReleaseInfo,
        
        [Parameter(Mandatory = $false)]
        [string]$Version = "1.0.0",
        
        [Parameter(Mandatory = $false)]
        [string]$ReleaseNotes = "",
        
        [Parameter(Mandatory = $false)]
        [switch]$CreateArchives
    )
    
    Write-Host "📦 Creating Release Package" -ForegroundColor Cyan
    Write-Host "Version: $Version" -ForegroundColor Gray
    Write-Host ""
    
    $packageDir = Join-Path $ReleaseInfo.OutputDirectory "package"
    if (Test-Path $packageDir) {
        Remove-Item $packageDir -Recurse -Force
    }
    New-Item -ItemType Directory -Path $packageDir -Force | Out-Null
    
    # Copy all files to package directory
    foreach ($file in $ReleaseInfo.CopiedFiles) {
        $fileName = Split-Path $file -Leaf
        Copy-Item $file (Join-Path $packageDir $fileName) -Force
    }
    
    # Create metadata file
    $metadata = @{
        Version       = $Version
        AssemblyName  = $ReleaseInfo.AssemblyName
        Configuration = $ReleaseInfo.Configuration
        Architecture  = $ReleaseInfo.Architecture
        Framework     = $ReleaseInfo.Framework
        BuildDate     = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
        ReleaseNotes  = $ReleaseNotes
    }
    
    $metadataPath = Join-Path $packageDir "release-metadata.json"
    $metadata | ConvertTo-Json -Depth 3 | Set-Content $metadataPath -Encoding UTF8
    
    # Create README for the release
    $readmeContent = @"
# $($ReleaseInfo.AssemblyName) v$Version
 
## Release Information
- **Version:** $Version
- **Configuration:** $($ReleaseInfo.Configuration)
- **Architecture:** $($ReleaseInfo.Architecture)
- **Framework:** $($ReleaseInfo.Framework)
- **Build Date:** $(Get-Date -Format "yyyy-MM-dd HH:mm:ss")
 
## Files Included
$($ReleaseInfo.CopiedFiles | ForEach-Object { "- $(Split-Path $_ -Leaf)" } | Out-String)
 
## Installation
1. Extract all files to your desired location
2. Run the executable file
3. Ensure all dependencies are installed
 
## Release Notes
$ReleaseNotes
"@

    
    $readmePath = Join-Path $packageDir "README.md"
    $readmeContent | Set-Content $readmePath -Encoding UTF8
    
    Write-Host "✓ Created release package in: $packageDir" -ForegroundColor Green
    
    if ($CreateArchives) {
        $archiveName = "$($ReleaseInfo.AssemblyName)-v$Version-$($ReleaseInfo.Architecture)"
        $archivePath = "$($ReleaseInfo.OutputDirectory)$archiveName.zip"
        
        if (Test-Path $archivePath) {
            Remove-Item $archivePath -Force
        }
        
        Compress-Archive -Path "$packageDir\*" -DestinationPath $archivePath -Force
        Write-Host "✓ Created archive: $archivePath" -ForegroundColor Green
    }
    
    return @{
        PackageDirectory = $packageDir
        MetadataPath     = $metadataPath
        ReadmePath       = $readmePath
        ArchivePath      = if ($CreateArchives) { $archivePath } else { $null }
        Success          = $true
    }
}