Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
  • Loading branch information
mdaneri committed Mar 7, 2025
1 parent 67505f5 commit 440e00c
Show file tree
Hide file tree
Showing 19 changed files with 4,303 additions and 3,921 deletions.
154 changes: 147 additions & 7 deletions pode.build.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,14 @@
.PARAMETER Version
Specifies the project version for stamping, packaging, and documentation. Defaults to '0.0.0'.
.PARAMETER Prerelease
Specifies the prerelease label to append to the module version, following semantic versioning conventions.
Examples include 'alpha.1', 'alpha.2', 'beta.1', etc. This label indicates the stability and iteration of the prerelease version.
.PARAMETER PersistVersion
If specified, the provided version and prerelease label will be saved to `Version.json`.
This ensures future builds use the same versioning information unless explicitly overridden.
.PARAMETER PesterVerbosity
Sets the verbosity level for Pester tests. Options: None, Normal, Detailed, Diagnostic.
Expand Down Expand Up @@ -76,6 +84,9 @@
Invoke-Build -Task Docs
# Builds and serves the documentation locally.
Invoke-Build -Task Build -Version '2.13.0' -Prerelease 'beta.1' -PersistVersion
# Saves "2.13.0-beta.1" to Version.json for future builds.
.LINK
For more information, visit https://github.com/Badgerati/Pode
#>
Expand All @@ -88,7 +99,13 @@
[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUSeDeclaredVarsMoreThanAssignments', '')]
param(
[string]
$Version = '0.0.0',
$Version,

[string]
$Prerelease,

[switch]
$PersistVersion,

[string]
[ValidateSet('None', 'Normal' , 'Detailed', 'Diagnostic')]
Expand Down Expand Up @@ -486,18 +503,27 @@ function Invoke-PodeBuildDotnetBuild {

# Optionally set assembly version
if ($Version) {
Write-Output "Assembly Version: $Version"
$AssemblyVersion = "-p:Version=$Version"
if ($Prerelease) {
Write-Output "Assembly Version: $Version-$Prerelease"
$AssemblyVersion = "-p:VersionPrefix=$Version"
$AssemblyPrerelease = "-p:VersionSuffix=$Prerelease"
}
else {
Write-Output "Assembly Version: $Version"
$AssemblyVersion = "-p:Version=$Version"
$AssemblyPrerelease = ''
}
}
else {
$AssemblyVersion = ''
$AssemblyPrerelease = ''
}

# restore dependencies
dotnet restore

# Use dotnet publish for .NET Core and .NET 5+
dotnet publish --configuration Release --self-contained --framework $target $AssemblyVersion --output ../Libs/$target
dotnet publish --configuration Release --self-contained --framework $target $AssemblyVersion $AssemblyPrerelease --output ../Libs/$target

if (!$?) {
throw "Build failed for target framework '$target'."
Expand Down Expand Up @@ -889,6 +915,55 @@ if (($null -eq $PSCmdlet.MyInvocation) -or ($PSCmdlet.MyInvocation.BoundParamete
return
}

# Import Version File if needed
if ([string]::IsNullOrEmpty($Version)) {
if (Test-Path './Version.json' -PathType Leaf) {
$importedVersion = Get-Content -Path './Version.json' | ConvertFrom-Json
if ($importedVersion.Version) {
$Version = $importedVersion.Version
}
if ($importedVersion.Prerelease) {
$Prerelease = $importedVersion.Prerelease
}
}
else {
$Version = '0.0.0'
if ($PersistVersion) {
Write-Error 'The -PersistVersion parameter requires the -Version parameter to be specified.'
return
}
}
}
elseif ($PersistVersion) {
if ($Prerelease) {
[ordered]@{Version = $Version; Prerelease = $Prerelease } | ConvertTo-Json | Out-File './Version.json'
}
else {
[ordered]@{Version = $Version } | ConvertTo-Json | Out-File './Version.json'
}
}

Write-Host '---------------------------------------------------' -ForegroundColor DarkCyan

# Display the Pode build version
if ($Prerelease) {
Write-Host "Pode Build: v$Version-$Prerelease (Pre-release)" -ForegroundColor DarkCyan
}
else {
if ($Version -eq '0.0.0') {
Write-Host 'Pode Build: [Development Version]' -ForegroundColor DarkCyan
}
else {
Write-Host "Pode Build: v$Version" -ForegroundColor DarkCyan
}
}

# Display the current UTC time in a readable format
$utcTime = (Get-Date).ToUniversalTime().ToString("yyyy-MM-dd HH:mm:ss 'UTC'")
Write-Host "Start Time: $utcTime" -ForegroundColor DarkCyan

Write-Host '---------------------------------------------------' -ForegroundColor DarkCyan


Add-BuildTask Default {
Write-Host 'Tasks in the Build Script:' -ForegroundColor DarkMagenta
Expand Down Expand Up @@ -940,7 +1015,13 @@ Add-BuildTask Default {
# Synopsis: Stamps the version onto the Module
Add-BuildTask StampVersion {
$pwshVersions = Get-PodeBuildPwshEOL
(Get-Content ./pkg/Pode.psd1) | ForEach-Object { $_ -replace '\$version\$', $Version -replace '\$versionsUntested\$', $pwshVersions.eol -replace '\$versionsSupported\$', $pwshVersions.supported -replace '\$buildyear\$', ((get-date).Year) } | Set-Content ./pkg/Pode.psd1
$prereleaseValue = if ($Prerelease) {
"Prerelease = '$Prerelease'"
}
else {
''
}
(Get-Content ./pkg/Pode.psd1) | ForEach-Object { $_ -replace '\$version\$', $Version -replace '\$versionsUntested\$', $pwshVersions.eol -replace '\$versionsSupported\$', $pwshVersions.supported -replace '\$buildyear\$', ((get-date).Year) -replace '#\$Prerelease-Here\$', $prereleaseValue } | Set-Content ./pkg/Pode.psd1
(Get-Content ./pkg/Pode.Internal.psd1) | ForEach-Object { $_ -replace '\$version\$', $Version } | Set-Content ./pkg/Pode.Internal.psd1
(Get-Content ./packers/choco/pode_template.nuspec) | ForEach-Object { $_ -replace '\$version\$', $Version } | Set-Content ./packers/choco/pode.nuspec
(Get-Content ./packers/choco/tools/ChocolateyInstall_template.ps1) | ForEach-Object { $_ -replace '\$version\$', $Version } | Set-Content ./packers/choco/tools/ChocolateyInstall.ps1
Expand Down Expand Up @@ -1234,9 +1315,10 @@ Add-BuildTask TestNoBuild TestDeps, {
$configuration = [PesterConfiguration]::Default
$configuration.run.path = @('./tests/unit', './tests/integration')
$configuration.run.PassThru = $true
$configuration.TestResult.OutputFormat = 'NUnitXml'
$configuration.Output.Verbosity = $PesterVerbosity
$configuration.TestResult.OutputPath = $Script:TestResultFile
$configuration.TestResult.OutputFormat = 'NUnitXml'
$configuration.TestResult.Enabled = $true

# if run code coverage if enabled
if (Test-PodeBuildCanCodeCoverage) {
Expand Down Expand Up @@ -1592,7 +1674,7 @@ Add-BuildTask SetupPowerShell {
#>

# Synopsis: Build the Release Notes
task ReleaseNotes {
Add-BuildTask ReleaseNotes {
if ([string]::IsNullOrWhiteSpace($ReleaseNoteVersion)) {
Write-Host 'Please provide a ReleaseNoteVersion' -ForegroundColor Red
return
Expand Down Expand Up @@ -1713,3 +1795,61 @@ task ReleaseNotes {
Write-Host ''
}
}

Add-BuildTask Sort-LanguageFiles {
$localePath = './src/Locales'
$files = Get-ChildItem -Path $localePath -Filter 'Pode.psd1' -Recurse

foreach ($file in $files) {
Write-Host "Processing file: $($file.FullName)"

$messages = Import-PowerShellDataFile -Path $file.FullName

$sortedKeys = $messages.Keys | Sort-Object

$exceptionMessages = [ordered]@{}
$generalMessages = [ordered]@{}

foreach ($key in $sortedKeys) {
if ($key -match 'ExceptionMessage$') {
$exceptionMessages[$key] = $messages[$key]
}
else {
$generalMessages[$key] = $messages[$key]
}
}

$maxLength = ($sortedKeys | Measure-Object -Property Length -Maximum).Maximum + 1

$lines = @()
$lines += '@{'
$lines += ' # -------------------------------'
$lines += ' # Exception Messages'
$lines += ' # -------------------------------'

foreach ($key in $exceptionMessages.Keys) {
$padding = ' ' * ($maxLength - $key.Length)
$escapedValue = $exceptionMessages[$key].Replace("'", "''")
$lines += " $key$padding= '$escapedValue'"
}

$lines += ''
$lines += ' # -------------------------------'
$lines += ' # General Messages'
$lines += ' # -------------------------------'

foreach ($key in $generalMessages.Keys) {
$padding = ' ' * ($maxLength - $key.Length)
$escapedValue = $generalMessages[$key].Replace("'", "''")
$lines += " $key$padding= '$escapedValue'"
}

$lines += '}'

# Explicitly write CRLF endings
[System.IO.File]::WriteAllText($file.FullName, ($lines -join "`r`n") + "`r`n", [System.Text.UTF8Encoding]::new($false))

Write-Host "Updated file: $($file.FullName)"
}
}

154 changes: 154 additions & 0 deletions prerelease.build.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSAvoidUsingWriteHost', '')]
param (
[Parameter(Mandatory)]
[string]$PodeVersion,

[Parameter(Mandatory)]
[string]$PreReleaseType,

[Parameter()]
[int[]]$ExcludePRs,

[Parameter()]
[switch]$Force
)


Add-BuildTask UpdateDevelop {
git fetch upstream
git checkout develop

if (-not $Force) {
$confirmation = Read-Host "⚠️ WARNING: This action will reset and force push 'develop' to match upstream. This is irreversible! Type 'y' to proceed or 'n' to cancel."
}

if ($confirmation -eq 'y' -or $Force) {
git reset --hard upstream/develop
git push origin develop --force
}
else {
Write-Warning 'Skipping reset and force push.'
}
}


Add-BuildTask CleanBranch Delete-ExistingBranch, Create-NewBranch, Create-VersionJson, Commit-VersionJson, {}


Add-BuildTask Delete-ExistingBranch UpdateDevelop, {
if (git branch --list $PreReleaseType) {
git branch -D $PreReleaseType
}
}

Add-BuildTask Create-NewBranch Delete-ExistingBranch, {
git checkout -b $PreReleaseType origin/develop
}

Add-BuildTask Create-VersionJson Create-NewBranch, {
$VersionData = @{
Version = $PodeVersion
Prerelease = $PreReleaseType
} | ConvertTo-Json -Depth 2

$VersionFilePath = "$PSScriptRoot\Version.json"
Set-Content -Path $VersionFilePath -Value $VersionData
}

Add-BuildTask Commit-VersionJson Create-VersionJson, {
git add $VersionFilePath
git commit -m "Set Pode version to $PodeVersion-$PreReleaseType"
}

Add-BuildTask ProcessPRs Commit-VersionJson, {
$prs = gh pr list --repo Badgerati/Pode --search 'draft:false' --json 'number,title,url,mergeStateStatus' | ConvertFrom-Json

if ($ExcludePRs) {
$prs = $prs | Where-Object { $_.number -notin $ExcludePRs }
}

foreach ($pr in $prs) {
if ($pr.mergeStateStatus -ne 'CLEAN') {
Write-Output "Skipping PR #$($pr.number): Merge state $($pr.mergeStateStatus)"
continue
}

git fetch upstream pull/$($pr.number)/head:pr-$($pr.number)

do {
$mergeResult = git merge --squash pr-$($pr.number) 2>&1
Write-Output $mergeResult
$mergeExitCode = $LASTEXITCODE
if ($mergeExitCode -ne 0) {
Write-Output "❌ Merge failed for PR #$($pr.number). Choose an option: (R)etry after fixing, (M)anually resolve, or (Q)uit the process."
do {
$choice = Read-Host
if ($choice -eq 'q') { exit 1 }
if ($choice -eq 'm') { Read-Host "🛠️ Resolve the issue manually, then press Enter to retry the merge."; $mergeExitCode = 0 }
} until ('q', 'm', 'r' -contains $choice)
}
}
while ($mergeExitCode -ne 0)

# Run tests
$testResultsPath = "$PSScriptRoot\testResults.xml"
if (Test-Path $testResultsPath) { Remove-Item $testResultsPath }

$testArgs = @(#'-NoExit',
'-NoProfile',
'-ExecutionPolicy', 'Bypass',
'-Command', "`$Host.UI.RawUI.WindowTitle = '$customTitle'; Invoke-Build test"
)

do {
$testProcess = Start-Process -FilePath 'pwsh.exe' -ArgumentList $testArgs -PassThru -WindowStyle Normal
Write-Output "⏳ Running Pester tests for PR #$($pr.number)... Please wait."

# Display a progress indicator while waiting for tests to complete
while (!$testProcess.HasExited) {
Start-Sleep -Seconds 10
Write-Host '.' -NoNewline
}
Write-Host '' # Move to a new line after completion

# Abort if tests fail
if ($testProcess.ExitCode -ne 0) {
Write-Output "❌ Pester tests failed for PR #$prNumber (Exit Code: $($testProcess.ExitCode)). (R)etry running tests or (Q)uit the process?"
do {
$choice = Read-Host
if ($choice -eq 'q') { exit 1 }
if ($choice -eq 'r') { Read-Host "🔄 Tests failed. Resolve the issue and press Enter to retry." }
} until ('q' , 'r' -contains $choice)
}
} until ($testProcess.ExitCode -eq 0)

# Verify test results
[xml]$testResults = Get-Content $testResultsPath
if ([int]$testResults.'test-results'.failures -gt 0) {
Write-Output "Tests failed for PR #$($pr.number). Aborting."
exit 1
}

# Commit the PR merge with a formatted message and check for errors
Write-Output "Committing merge for PR #$prNumber..."
do {
git commit -m "PR $prNumber $prTitle $prUrl"
$commitExitCode = $LASTEXITCODE
if ($commitExitCode -ne 0) {
Write-Output "Commit failed for PR #$($pr.number). (R)etry/(Q)uit?"
$choice = Read-Host
if ($choice -eq 'q') { exit 1 }
else { Read-Host "🛠️ Fix the commit issue manually, then press Enter to retry the commit." }
}
else {
Write-Output "✅ Commit successful for PR #$prNumber"
}
}
while ($commitExitCode -ne 0)
}

Write-Output '✅ All PRs processed successfully!'
}

# Default task
Add-BuildTask Default ProcessPRs
Loading

0 comments on commit 440e00c

Please sign in to comment.