#!/usr/bin/env pwsh
# ======================
# Script Init
# ======================
# Ensure we're running in PowerShell Core
if (-not ($PSVersionTable.PSEdition -eq "Core"))
{
Write-Host "This script requires PowerShell Core. Please install it first."
exit 1
}
Set-StrictMode -Version Latest
$ErrorActionPreference = "Stop"
# ======================
# Variables and Constants
# ======================
# Set default log level (DEBUG, INFO, WARNING, ERROR)
$Script:LOG_LEVEL = if ($env:LOG_LEVEL)
{ $env:LOG_LEVEL
} else
{ "INFO"
}
# Required environment variables
$Script:BUILD_MODE = if ($env:BUILD_MODE)
{ $env:BUILD_MODE
} else
{ ""
}
$Script:WORKSPACE_DIR = if ($env:WORKSPACE_DIR)
{ $env:WORKSPACE_DIR
} else
{ ""
}
# Optional environment variables
$Script:CARGO_BUILD_PROFILE = if ($env:CARGO_BUILD_PROFILE)
{ $env:CARGO_BUILD_PROFILE
} else
{ "dev"
}
$Script:CARGO_FEATURES = if ($env:CARGO_FEATURES)
{ $env:CARGO_FEATURES
} else
{ ""
}
$Script:CARGO_TARGET = if ($env:CARGO_TARGET)
{ $env:CARGO_TARGET
} else
{ ""
}
$Script:RUSTDOCFLAGS = if ($env:RUSTDOCFLAGS)
{ $env:RUSTDOCFLAGS
} else
{ ""
}
# Constants
$Script:VALID_BUILD_MODES = @("compile", "release", "doc", "check")
# Log file name for this script
$Script:LOG_FILE_NAME = "entropy_auth_build.log"
# ======================
# Shared Functions
# ======================
. "$PSScriptRoot/common.ps1"
# ======================
# Function Definitions
# ======================
# Ensure all mandatory environment variables are present
function Test-EnvironmentVariables
{
$absent = @()
if ([string]::IsNullOrEmpty($Script:BUILD_MODE))
{ $absent += "BUILD_MODE"
}
if ([string]::IsNullOrEmpty($Script:WORKSPACE_DIR))
{ $absent += "WORKSPACE_DIR"
}
if ($absent.Count -gt 0)
{
Write-Log -LogLevel "ERROR" -LogMessage "Missing required environment variables:"
foreach ($v in $absent)
{
Write-Log -LogLevel "ERROR" -LogMessage " - $v"
}
return $false
}
# Validate build mode is a known value
if ($Script:BUILD_MODE -notin $Script:VALID_BUILD_MODES)
{
Write-Log -LogLevel "ERROR" -LogMessage "BUILD_MODE must be one of: $($Script:VALID_BUILD_MODES -join ', '). Got: '$($Script:BUILD_MODE)'"
return $false
}
Write-Log -LogLevel "INFO" -LogMessage "All required environment variables are present"
return $true
}
# Build common cargo arguments from configuration
function Get-CargoBaseArgs
{
$cargoArgs = @()
if ($Script:CARGO_BUILD_PROFILE -ne "dev")
{
$cargoArgs += "--profile"
$cargoArgs += $Script:CARGO_BUILD_PROFILE
}
if (-not [string]::IsNullOrEmpty($Script:CARGO_FEATURES))
{
$cargoArgs += "--features"
$cargoArgs += $Script:CARGO_FEATURES
}
if (-not [string]::IsNullOrEmpty($Script:CARGO_TARGET))
{
$cargoArgs += "--target"
$cargoArgs += $Script:CARGO_TARGET
}
return $cargoArgs
}
# Run cargo build for development profile compilation
function Invoke-CompileBuild
{
Start-OperationTiming -Operation "compile_build"
Write-Log -LogLevel "INFO" -LogMessage "=== Running Development Compilation ==="
# Build the library and its test targets (the crate ships no examples
# or benchmarks).
$cargoArgs = @("build", "--lib", "--tests") + (Get-CargoBaseArgs)
Write-Log -LogLevel "DEBUG" -LogMessage "Working directory: $($Script:WORKSPACE_DIR)"
Write-Log -LogLevel "DEBUG" -LogMessage "Command: cargo $($cargoArgs -join ' ')"
Push-Location $Script:WORKSPACE_DIR
try
{
Write-Log -LogLevel "INFO" -LogMessage "Running cargo build --lib --tests..."
& cargo @cargoArgs 2>&1 | ForEach-Object {
$line = "$_"
if (-not [string]::IsNullOrWhiteSpace($line))
{
if ($line -match 'error\[|warning:')
{
Write-Log -LogLevel "INFO" -LogMessage "[cargo build] $line"
} else
{
Write-Log -LogLevel "DEBUG" -LogMessage "[cargo build] $line"
}
}
}
if ($LASTEXITCODE -ne 0)
{
Write-Log -LogLevel "ERROR" -LogMessage "Development compilation failed with exit code $LASTEXITCODE"
return $false
}
Write-Log -LogLevel "INFO" -LogMessage "Development compilation succeeded" -OperationName "compile_build"
return $true
} finally
{
Pop-Location
Stop-OperationTiming -Operation "compile_build"
}
}
# Run cargo build with the release profile for optimized compilation
function Invoke-ReleaseBuild
{
Start-OperationTiming -Operation "release_build"
Write-Log -LogLevel "INFO" -LogMessage "=== Running Release Compilation ==="
# Force --release regardless of CARGO_BUILD_PROFILE for this mode.
$cargoArgs = @("build", "--lib", "--tests", "--release")
if (-not [string]::IsNullOrEmpty($Script:CARGO_FEATURES))
{
$cargoArgs += "--features"
$cargoArgs += $Script:CARGO_FEATURES
}
if (-not [string]::IsNullOrEmpty($Script:CARGO_TARGET))
{
$cargoArgs += "--target"
$cargoArgs += $Script:CARGO_TARGET
}
Write-Log -LogLevel "DEBUG" -LogMessage "Working directory: $($Script:WORKSPACE_DIR)"
Write-Log -LogLevel "DEBUG" -LogMessage "Command: cargo $($cargoArgs -join ' ')"
Push-Location $Script:WORKSPACE_DIR
try
{
Write-Log -LogLevel "INFO" -LogMessage "Running cargo build --lib --tests --release..."
& cargo @cargoArgs 2>&1 | ForEach-Object {
$line = "$_"
if (-not [string]::IsNullOrWhiteSpace($line))
{
if ($line -match 'error\[|warning:')
{
Write-Log -LogLevel "INFO" -LogMessage "[cargo build] $line"
} else
{
Write-Log -LogLevel "DEBUG" -LogMessage "[cargo build] $line"
}
}
}
if ($LASTEXITCODE -ne 0)
{
Write-Log -LogLevel "ERROR" -LogMessage "Release compilation failed with exit code $LASTEXITCODE"
return $false
}
Write-Log -LogLevel "INFO" -LogMessage "Release compilation succeeded" -OperationName "release_build"
return $true
} finally
{
Pop-Location
Stop-OperationTiming -Operation "release_build"
}
}
# Run cargo doc to verify documentation builds without errors
function Invoke-DocBuild
{
Start-OperationTiming -Operation "doc_build"
Write-Log -LogLevel "INFO" -LogMessage "=== Running Documentation Build ==="
# Doc defaults (overridable via env): deny rustdoc warnings and document
# every feature so intra-doc links into the optional asym-jwt/oidc/saml/
# ssh-keys modules resolve (matches [package.metadata.docs.rs] all-features).
if ([string]::IsNullOrEmpty($Script:RUSTDOCFLAGS))
{ $Script:RUSTDOCFLAGS = "-D warnings"
}
if ([string]::IsNullOrEmpty($Script:CARGO_FEATURES))
{ $Script:CARGO_FEATURES = "saml,oidc,ssh-keys,asym-jwt"
}
$cargoArgs = @("doc", "--no-deps") + (Get-CargoBaseArgs)
Write-Log -LogLevel "DEBUG" -LogMessage "Working directory: $($Script:WORKSPACE_DIR)"
Write-Log -LogLevel "DEBUG" -LogMessage "Command: cargo $($cargoArgs -join ' ')"
# Set RUSTDOCFLAGS if provided (e.g., "-D warnings" to deny doc warnings)
if (-not [string]::IsNullOrEmpty($Script:RUSTDOCFLAGS))
{
$env:RUSTDOCFLAGS = $Script:RUSTDOCFLAGS
Write-Log -LogLevel "DEBUG" -LogMessage "RUSTDOCFLAGS set to: $($Script:RUSTDOCFLAGS)"
}
Push-Location $Script:WORKSPACE_DIR
try
{
Write-Log -LogLevel "INFO" -LogMessage "Running cargo doc --no-deps..."
& cargo @cargoArgs 2>&1 | ForEach-Object {
$line = "$_"
if (-not [string]::IsNullOrWhiteSpace($line))
{
if ($line -match 'error\[|warning:')
{
Write-Log -LogLevel "INFO" -LogMessage "[cargo doc] $line"
} else
{
Write-Log -LogLevel "DEBUG" -LogMessage "[cargo doc] $line"
}
}
}
if ($LASTEXITCODE -ne 0)
{
Write-Log -LogLevel "ERROR" -LogMessage "Documentation build failed with exit code $LASTEXITCODE"
return $false
}
Write-Log -LogLevel "INFO" -LogMessage "Documentation build succeeded" -OperationName "doc_build"
return $true
} finally
{
Pop-Location
Stop-OperationTiming -Operation "doc_build"
}
}
# Run cargo check for fast type-checking without full compilation
function Invoke-CheckBuild
{
Start-OperationTiming -Operation "check_build"
Write-Log -LogLevel "INFO" -LogMessage "=== Running Type Check ==="
$cargoArgs = @("check", "--lib", "--tests") + (Get-CargoBaseArgs)
Write-Log -LogLevel "DEBUG" -LogMessage "Working directory: $($Script:WORKSPACE_DIR)"
Write-Log -LogLevel "DEBUG" -LogMessage "Command: cargo $($cargoArgs -join ' ')"
Push-Location $Script:WORKSPACE_DIR
try
{
Write-Log -LogLevel "INFO" -LogMessage "Running cargo check --lib --tests..."
& cargo @cargoArgs 2>&1 | ForEach-Object {
$line = "$_"
if (-not [string]::IsNullOrWhiteSpace($line))
{
if ($line -match 'error\[|warning:')
{
Write-Log -LogLevel "INFO" -LogMessage "[cargo check] $line"
} else
{
Write-Log -LogLevel "DEBUG" -LogMessage "[cargo check] $line"
}
}
}
if ($LASTEXITCODE -ne 0)
{
Write-Log -LogLevel "ERROR" -LogMessage "Type check failed with exit code $LASTEXITCODE"
return $false
}
Write-Log -LogLevel "INFO" -LogMessage "Type check succeeded" -OperationName "check_build"
return $true
} finally
{
Pop-Location
Stop-OperationTiming -Operation "check_build"
}
}
# ======================
# Main Script Execution
# ======================
# Display Banner
Write-Host '
##############################################################################################
# #
# Entropy Softworks — entropy-auth Build Automation #
# #
##############################################################################################
=== Overview ===
Verifies Rust compilation for the entropy-auth crate based on the
BUILD_MODE environment variable:
- compile : Development build (cargo build --lib --tests)
- release : Optimized release build (cargo build --lib --tests --release)
- doc : Documentation generation check (cargo doc --no-deps)
- check : Fast type-checking without codegen (cargo check --lib --tests)
=== Environment Variables ===
Required: BUILD_MODE, WORKSPACE_DIR
Optional: CARGO_BUILD_PROFILE, CARGO_FEATURES, CARGO_TARGET,
RUSTDOCFLAGS, LOG_LEVEL
'
Start-OperationTiming -Operation "total_build"
# Validate environment variables
if (-not (Test-EnvironmentVariables))
{
Write-Log -LogLevel "ERROR" -LogMessage "Environment validation failed — aborting"
exit 1
}
# Verify required tooling
if (-not (Test-ToolInstallation -ToolName "cargo"))
{
Write-Log -LogLevel "ERROR" -LogMessage "cargo is required but not available"
exit 1
}
# Log configuration summary
Write-Log -LogLevel "INFO" -LogMessage "Configuration:"
Write-Log -LogLevel "INFO" -LogMessage " Build Mode : $($Script:BUILD_MODE)"
Write-Log -LogLevel "INFO" -LogMessage " Workspace : $($Script:WORKSPACE_DIR)"
Write-Log -LogLevel "INFO" -LogMessage " Build Profile : $($Script:CARGO_BUILD_PROFILE)"
if (-not [string]::IsNullOrEmpty($Script:CARGO_FEATURES))
{
Write-Log -LogLevel "INFO" -LogMessage " Features : $($Script:CARGO_FEATURES)"
}
if (-not [string]::IsNullOrEmpty($Script:CARGO_TARGET))
{
Write-Log -LogLevel "INFO" -LogMessage " Target : $($Script:CARGO_TARGET)"
}
if (-not [string]::IsNullOrEmpty($Script:RUSTDOCFLAGS))
{
Write-Log -LogLevel "INFO" -LogMessage " RUSTDOCFLAGS : $($Script:RUSTDOCFLAGS)"
}
# Run the requested build mode
$buildResult = $false
switch ($Script:BUILD_MODE)
{
"compile"
{
$buildResult = Invoke-CompileBuild
}
"release"
{
$buildResult = Invoke-ReleaseBuild
}
"doc"
{
$buildResult = Invoke-DocBuild
}
"check"
{
$buildResult = Invoke-CheckBuild
}
}
# Done
Stop-OperationTiming -Operation "total_build"
if ($buildResult)
{
Write-Log -LogLevel "INFO" -LogMessage "Build completed successfully" -OperationName "total_build"
Show-TimingSummary
exit 0
} else
{
Write-Log -LogLevel "ERROR" -LogMessage "Build failed"
Show-TimingSummary
exit 1
}