From d3b3c24d65fb63a042da84a8396a15b85f904451 Mon Sep 17 00:00:00 2001 From: mdaneri Date: Wed, 13 Nov 2024 09:59:58 -0800 Subject: [PATCH 01/25] Changes to Pode.build to support net9 --- pode.build.ps1 | 1619 ++++++++++++++++++++------------------ src/Listener/Pode.csproj | 2 +- 2 files changed, 867 insertions(+), 754 deletions(-) diff --git a/pode.build.ps1 b/pode.build.ps1 index d82731d5c..eea1b6799 100644 --- a/pode.build.ps1 +++ b/pode.build.ps1 @@ -22,997 +22,1110 @@ param( $UICulture = 'en-US' ) -# Fix for PS7.5 Preview - https://github.com/PowerShell/PowerShell/issues/23868 -$ProgressPreference = 'SilentlyContinue' -<# -# Dependency Versions -#> -$Versions = @{ - Pester = '5.6.1' - MkDocs = '1.6.0' - PSCoveralls = '1.0.0' - SevenZip = '18.5.0.20180730' - DotNet = '8.0' - MkDocsTheme = '9.5.23' - PlatyPS = '0.14.2' -} +# Check if the script is running under Invoke-Build +if (($null -ne $PSCmdlet.MyInvocation) -and ($PSCmdlet.MyInvocation.BoundParameters.ContainsKey('BuildRoot') -or $null -ne $BuildRoot)) { -<# -# Helper Functions -#> -function Test-PodeBuildIsWindows { - $v = $PSVersionTable - return ($v.Platform -ilike '*win*' -or ($null -eq $v.Platform -and $v.PSEdition -ieq 'desktop')) -} + # Dependency Versions + $Versions = @{ + Pester = '5.6.1' + MkDocs = '1.6.1' + PSCoveralls = '1.0.0' + SevenZip = '18.5.0.20180730' + DotNet = '9.0' + MkDocsTheme = '9.5.44' + PlatyPS = '0.14.2' + } -function Test-PodeBuildIsGitHub { - return (![string]::IsNullOrWhiteSpace($env:GITHUB_REF)) -} -function Test-PodeBuildCanCodeCoverage { - return (@('1', 'true') -icontains $env:PODE_RUN_CODE_COVERAGE) -} + $NetVersions = 'netstandard2.0', 'netstandard2.1', 'netcoreapp3.1', 'net5.0', 'net6.0', 'net7.0', 'net8.0', 'net9.0' + #Unsupported .NET Framework version 'net4.0', 'net4.5', 'net4.5.1', 'net4.5.2', 'net4.6', 'net4.6.1', 'net4.6.2', 'net4.7', 'net4.7.1', 'net4.7.2', 'net4.8' -function Get-PodeBuildService { - return 'github-actions' -} + # Helper Functions + function Test-PodeBuildIsWindows { + $v = $PSVersionTable + return ($v.Platform -ilike '*win*' -or ($null -eq $v.Platform -and $v.PSEdition -ieq 'desktop')) + } -function Test-PodeBuildCommand($cmd) { - $path = $null + function Test-PodeBuildIsGitHub { + return (![string]::IsNullOrWhiteSpace($env:GITHUB_REF)) + } - if (Test-PodeBuildIsWindows) { - $path = (Get-Command $cmd -ErrorAction Ignore) + function Test-PodeBuildCanCodeCoverage { + return (@('1', 'true') -icontains $env:PODE_RUN_CODE_COVERAGE) } - else { - $path = (which $cmd) + + function Get-PodeBuildService { + return 'github-actions' } - return (![string]::IsNullOrWhiteSpace($path)) -} + function Test-PodeBuildCommand($cmd) { + $path = $null -function Get-PodeBuildBranch { - return ($env:GITHUB_REF -ireplace 'refs\/heads\/', '') -} + if (Test-PodeBuildIsWindows) { + $path = (Get-Command $cmd -ErrorAction Ignore) + } + else { + $path = (which $cmd) + } -function Invoke-PodeBuildInstall($name, $version) { - [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 + return (![string]::IsNullOrWhiteSpace($path)) + } - if (Test-PodeBuildIsWindows) { - if (Test-PodeBuildCommand 'choco') { - choco install $name --version $version -y --no-progress - } + function Get-PodeBuildBranch { + return ($env:GITHUB_REF -ireplace 'refs\/heads\/', '') } - else { - if (Test-PodeBuildCommand 'brew') { - brew install $name - } - elseif (Test-PodeBuildCommand 'apt-get') { - sudo apt-get install $name -y + + function Invoke-PodeBuildInstall($name, $version) { + [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 + + if (Test-PodeBuildIsWindows) { + if (Test-PodeBuildCommand 'choco') { + choco install $name --version $version -y --no-progress + } } - elseif (Test-PodeBuildCommand 'yum') { - sudo yum install $name -y + else { + if (Test-PodeBuildCommand 'brew') { + brew install $name + } + elseif (Test-PodeBuildCommand 'apt-get') { + sudo apt-get install $name -y + } + elseif (Test-PodeBuildCommand 'yum') { + sudo yum install $name -y + } } } -} -function Install-PodeBuildModule($name) { - if ($null -ne ((Get-Module -ListAvailable $name) | Where-Object { $_.Version -ieq $Versions[$name] })) { - return + function Install-PodeBuildModule($name) { + if ($null -ne ((Get-Module -ListAvailable $name) | Where-Object { $_.Version -ieq $Versions[$name] })) { + return + } + + Write-Host "Installing $($name) v$($Versions[$name])" + [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 + Install-Module -Name "$($name)" -Scope CurrentUser -RequiredVersion "$($Versions[$name])" -Force -SkipPublisherCheck } - Write-Host "Installing $($name) v$($Versions[$name])" - [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 - Install-Module -Name "$($name)" -Scope CurrentUser -RequiredVersion "$($Versions[$name])" -Force -SkipPublisherCheck -} + function Invoke-PodeBuildDotnetBuild { + param ( + [string]$target + ) -function Invoke-PodeBuildDotnetBuild($target) { - # Retrieve the highest installed SDK version - $majorVersion = ([version](dotnet --version)).Major + # Verify if the target is a known .NET version + if ($target -notin $NetVersions) { + Write-Host "Unknown target framework '$target'. Please specify a valid .NET framework." + return + } - # Determine if the target framework is compatible - $isCompatible = $False - switch ($majorVersion) { - 8 { if ($target -in @('net6.0', 'netstandard2.0', 'net8.0')) { $isCompatible = $True } } - 7 { if ($target -in @('net6.0', 'netstandard2.0')) { $isCompatible = $True } } - 6 { if ($target -in @('net6.0', 'netstandard2.0')) { $isCompatible = $True } } - } + # Retrieve the installed SDK versions + $sdkVersions = dotnet --list-sdks | ForEach-Object { $_.Split('[')[0].Trim() } + $majorVersions = $sdkVersions | ForEach-Object { ([version]$_).Major } | Sort-Object -Descending | Select-Object -Unique + + # Map target frameworks to minimum SDK versions + $targetSdkMap = @{ + 'netstandard2.0' = 2 + 'netstandard2.1' = 3 + 'netcoreapp3.1' = 3 + 'net5.0' = 5 + 'net6.0' = 6 + 'net7.0' = 7 + 'net8.0' = 8 + 'net9.0' = 9 + } - # Skip build if not compatible - if ($isCompatible) { - Write-Host "SDK for target framework $target is compatible with the installed SDKs" - } - else { - Write-Host "SDK for target framework $target is not compatible with the installed SDKs. Skipping build." - return - } - if ($Version) { - Write-Host "Assembly Version $Version" - $AssemblyVersion = "-p:Version=$Version" - } - else { - $AssemblyVersion = '' - } + # Determine if the target framework is compatible + $isCompatible = $False - dotnet publish --configuration Release --self-contained --framework $target $AssemblyVersion --output ../Libs/$target - if (!$?) { - throw "dotnet publish failed for $($target)" - } + if ($targetSdkMap.ContainsKey($target)) { + $requiredSdkVersion = $targetSdkMap[$target] -} + foreach ($sdkVersion in $sdkVersions) { + $sdkMajor = ([version]$sdkVersion).Major + if ($sdkMajor -ge $requiredSdkVersion) { + $isCompatible = $True + break + } + } + } + elseif ($target -like 'net4*') { + # .NET Framework targets require MSBuild, typically available with Visual Studio + $msbuildPath = Get-Command msbuild -ErrorAction SilentlyContinue + if ($msbuildPath) { + $isCompatible = $True + } + else { + Write-Host 'MSBuild is not available. Cannot build .NET Framework targets.' + return + } + } -function Get-PodeBuildPwshEOL { - $eol = Invoke-RestMethod -Uri 'https://endoflife.date/api/powershell.json' -Headers @{ Accept = 'application/json' } - return @{ - eol = ($eol | Where-Object { [datetime]$_.eol -lt [datetime]::Now }).cycle -join ',' - supported = ($eol | Where-Object { [datetime]$_.eol -ge [datetime]::Now }).cycle -join ',' - } -} + if ($isCompatible) { + Write-Host "SDK for target framework '$target' is compatible with the installed SDKs." + } + else { + Write-Host "SDK for target framework '$target' is not compatible with the installed SDKs. Skipping build." + return + } -function Test-PodeBuildOSWindows { - return ($IsWindows -or - ![string]::IsNullOrEmpty($env:ProgramFiles) -or - (($PSVersionTable.Keys -contains 'PSEdition') -and ($PSVersionTable.PSEdition -eq 'Desktop'))) -} + # Optionally set assembly version + if ($Version) { + Write-Host "Assembly Version: $Version" + $AssemblyVersion = "-p:Version=$Version" + } + else { + $AssemblyVersion = '' + } -function Get-PodeBuildOSPwshName { - if (Test-PodeBuildOSWindows) { - return 'win' - } + # Execute dotnet publish or MSBuild depending on the target + if ($target -like 'net4*') { + # Use MSBuild for .NET Framework targets + $projectFile = 'YourProject.csproj' # Replace with your actual project file + & msbuild $projectFile /p:Configuration=Release /p:TargetFramework=$target $AssemblyVersion /p:OutputPath="../Libs/$target" + } + else { + # Use dotnet publish for .NET Core and .NET 5+ + dotnet publish --configuration Release --self-contained --framework $target $AssemblyVersion --output ../Libs/$target + } - if ($IsLinux) { - return 'linux' + if (!$?) { + throw "Build failed for target framework '$target'." + } } - if ($IsMacOS) { - return 'osx' + function Get-PodeBuildPwshEOL { + $uri = 'https://endoflife.date/api/powershell.json' + try { + $eol = Invoke-RestMethod -Uri $uri -Headers @{ Accept = 'application/json' } + return @{ + eol = ($eol | Where-Object { [datetime]$_.eol -lt [datetime]::Now }).cycle -join ',' + supported = ($eol | Where-Object { [datetime]$_.eol -ge [datetime]::Now }).cycle -join ',' + } + } + catch { + Write-Warning "Invoke-RestMethod to $uri failed: $($_.ErrorDetails.Message)" + return @{ + eol = '' + supported = '' + } + } } -} -function Get-PodeBuildOSPwshArchitecture { - $arch = [string]::Empty - # windows - if (Test-PodeBuildOSWindows) { - $arch = $env:PROCESSOR_ARCHITECTURE + function Get-PodeBuildDotNetEOL { + $uri = 'https://endoflife.date/api/dotnet.json' + try { + $eol = Invoke-RestMethod -Uri $uri -Headers @{ Accept = 'application/json' } + return @{ + eol = ($eol | Where-Object { [datetime]$_.eol -lt [datetime]::Now }).cycle -join ',' + supported = ($eol | Where-Object { [datetime]$_.eol -ge [datetime]::Now }).cycle -join ',' + } + } + catch { + Write-Warning "Invoke-RestMethod to $uri failed: $($_.ErrorDetails.Message)" + return @{ + eol = '' + supported = '' + } + } } - - # unix - if ($IsLinux -or $IsMacOS) { - $arch = uname -m + function Test-PodeBuildOSWindows { + return ($IsWindows -or + ![string]::IsNullOrEmpty($env:ProgramFiles) -or + (($PSVersionTable.Keys -contains 'PSEdition') -and ($PSVersionTable.PSEdition -eq 'Desktop'))) } - Write-Host "OS Architecture: $($arch)" + function Get-PodeBuildOSPwshName { + if (Test-PodeBuildOSWindows) { + return 'win' + } + + if ($IsLinux) { + return 'linux' + } - # convert to pwsh arch - switch ($arch.ToLowerInvariant()) { - 'amd64' { return 'x64' } - 'x86' { return 'x86' } - 'x86_64' { return 'x64' } - 'armv7*' { return 'arm32' } - 'aarch64*' { return 'arm64' } - 'arm64' { return 'arm64' } - 'arm64*' { return 'arm64' } - 'armv8*' { return 'arm64' } - default { throw "Unsupported architecture: $($arch)" } + if ($IsMacOS) { + return 'osx' + } } -} -function Convert-PodeBuildOSPwshTagToVersion { - $result = Invoke-RestMethod -Uri "https://aka.ms/pwsh-buildinfo-$($PowerShellVersion)" - return $result.ReleaseTag -ireplace '^v' -} + function Get-PodeBuildOSPwshArchitecture { + $arch = [string]::Empty -function Install-PodeBuildPwshWindows($target) { - $installFolder = "$($env:ProgramFiles)\PowerShell\7" + # windows + if (Test-PodeBuildOSWindows) { + $arch = $env:PROCESSOR_ARCHITECTURE + } - if (Test-Path $installFolder) { - Remove-Item $installFolder -Recurse -Force -ErrorAction Stop + # unix + if ($IsLinux -or $IsMacOS) { + $arch = uname -m + } + + Write-Host "OS Architecture: $($arch)" + + # convert to pwsh arch + switch ($arch.ToLowerInvariant()) { + 'amd64' { return 'x64' } + 'x86' { return 'x86' } + 'x86_64' { return 'x64' } + 'armv7*' { return 'arm32' } + 'aarch64*' { return 'arm64' } + 'arm64' { return 'arm64' } + 'arm64*' { return 'arm64' } + 'armv8*' { return 'arm64' } + default { throw "Unsupported architecture: $($arch)" } + } } - Copy-Item -Path "$($target)\" -Destination "$($installFolder)\" -Recurse -ErrorAction Stop -} + function Convert-PodeBuildOSPwshTagToVersion { + $result = Invoke-RestMethod -Uri "https://aka.ms/pwsh-buildinfo-$($PowerShellVersion)" + return $result.ReleaseTag -ireplace '^v' + } -function Install-PodeBuildPwshUnix($target) { - $targetFullPath = Join-Path -Path $target -ChildPath 'pwsh' - $null = chmod 755 $targetFullPath + function Install-PodeBuildPwshWindows($target) { + $installFolder = "$($env:ProgramFiles)\PowerShell\7" - $symlink = $null - if ($IsMacOS) { - $symlink = '/usr/local/bin/pwsh' - } - else { - $symlink = '/usr/bin/pwsh' - } + if (Test-Path $installFolder) { + Remove-Item $installFolder -Recurse -Force -ErrorAction Stop + } - $uid = id -u - if ($uid -ne '0') { - $sudo = 'sudo' - } - else { - $sudo = '' + Copy-Item -Path "$($target)\" -Destination "$($installFolder)\" -Recurse -ErrorAction Stop } - # Make symbolic link point to installed path - & $sudo ln -fs $targetFullPath $symlink -} + function Install-PodeBuildPwshUnix($target) { + $targetFullPath = Join-Path -Path $target -ChildPath 'pwsh' + $null = chmod 755 $targetFullPath -function Get-PodeBuildCurrentPwshVersion { - return ("$(pwsh -v)" -split ' ')[1].Trim() -} + $symlink = $null + if ($IsMacOS) { + $symlink = '/usr/local/bin/pwsh' + } + else { + $symlink = '/usr/bin/pwsh' + } + + $uid = id -u + if ($uid -ne '0') { + $sudo = 'sudo' + } + else { + $sudo = '' + } -function Invoke-PodeBuildDockerBuild($tag, $file) { - docker build -t badgerati/pode:$tag -f $file . - if (!$?) { - throw "docker build failed for $($tag)" + # Make symbolic link point to installed path + & $sudo ln -fs $targetFullPath $symlink } - docker tag badgerati/pode:$tag docker.pkg.github.com/badgerati/pode/pode:$tag - if (!$?) { - throw "docker tag failed for $($tag)" + function Get-PodeBuildCurrentPwshVersion { + return ("$(pwsh -v)" -split ' ')[1].Trim() } -} -function Split-PodeBuildPwshPath { - if (Test-PodeBuildOSWindows) { - return $env:PSModulePath -split ';' + function Invoke-PodeBuildDockerBuild($tag, $file) { + docker build -t badgerati/pode:$tag -f $file . + if (!$?) { + throw "docker build failed for $($tag)" + } + + docker tag badgerati/pode:$tag docker.pkg.github.com/badgerati/pode/pode:$tag + if (!$?) { + throw "docker tag failed for $($tag)" + } } - else { - return $env:PSModulePath -split ':' + + function Split-PodeBuildPwshPath { + if (Test-PodeBuildOSWindows) { + return $env:PSModulePath -split ';' + } + else { + return $env:PSModulePath -split ':' + } } -} -<# + <# # Helper Tasks #> -# Synopsis: Stamps the version onto the Module -Task StampVersion { - $pwshVersions = Get-PodeBuildPwshEOL + # Synopsis: Stamps the version onto the Module + Task 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 (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 -} + } -# Synopsis: Generating a Checksum of the Zip -Task PrintChecksum { - $Script:Checksum = (Get-FileHash "./deliverable/$Version-Binaries.zip" -Algorithm SHA256).Hash - Write-Host "Checksum: $($Checksum)" -} + # Synopsis: Generating a Checksum of the Zip + Task PrintChecksum { + $Script:Checksum = (Get-FileHash "./deliverable/$Version-Binaries.zip" -Algorithm SHA256).Hash + Write-Host "Checksum: $($Checksum)" + } -<# + <# # Dependencies #> -# Synopsis: Installs Chocolatey -Task ChocoDeps -If (Test-PodeBuildIsWindows) { - if (!(Test-PodeBuildCommand 'choco')) { - Set-ExecutionPolicy Bypass -Scope Process -Force - Invoke-Expression ([System.Net.WebClient]::new().DownloadString('https://chocolatey.org/install.ps1')) + # Synopsis: Installs Chocolatey + Task ChocoDeps -If (Test-PodeBuildIsWindows) { + if (!(Test-PodeBuildCommand 'choco')) { + Set-ExecutionPolicy Bypass -Scope Process -Force + Invoke-Expression ([System.Net.WebClient]::new().DownloadString('https://chocolatey.org/install.ps1')) + } } -} -# Synopsis: Install dependencies for packaging -Task PackDeps -If (Test-PodeBuildIsWindows) ChocoDeps, { - if (!(Test-PodeBuildCommand '7z')) { - Invoke-PodeBuildInstall '7zip' $Versions.SevenZip + # Synopsis: Install dependencies for packaging + Task PackDeps -If (Test-PodeBuildIsWindows) ChocoDeps, { + if (!(Test-PodeBuildCommand '7z')) { + Invoke-PodeBuildInstall '7zip' $Versions.SevenZip + } } -} -# Synopsis: Install dependencies for compiling/building -Task BuildDeps { - # install dotnet - if (Test-PodeBuildIsWindows) { - $dotnet = 'dotnet' - } - else { - $dotnet = "dotnet-sdk-$($Versions.DotNet)" - } + # Synopsis: Install dependencies for compiling/building + Task BuildDeps { + # install dotnet + if (Test-PodeBuildIsWindows) { + $dotnet = 'dotnet' + } + else { + $dotnet = "dotnet-sdk-$($Versions.DotNet)" + } - if (!(Test-PodeBuildCommand 'dotnet')) { - Invoke-PodeBuildInstall $dotnet $Versions.DotNet + if (!(Test-PodeBuildCommand 'dotnet')) { + Invoke-PodeBuildInstall $dotnet $Versions.DotNet + } } -} -# Synopsis: Install dependencies for running tests -Task TestDeps { - # install pester - Install-PodeBuildModule Pester + # Synopsis: Install dependencies for running tests + Task TestDeps { + # install pester + Install-PodeBuildModule Pester - # install PSCoveralls - if (Test-PodeBuildCanCodeCoverage) { - Install-PodeBuildModule PSCoveralls + # install PSCoveralls + if (Test-PodeBuildCanCodeCoverage) { + Install-PodeBuildModule PSCoveralls + } } -} -# Synopsis: Install dependencies for documentation -Task DocsDeps ChocoDeps, { - # install mkdocs - if (!(Test-PodeBuildCommand 'mkdocs')) { - Invoke-PodeBuildInstall 'mkdocs' $Versions.MkDocs - } + # Synopsis: Install dependencies for documentation + Task DocsDeps ChocoDeps, { + # install mkdocs + if (!(Test-PodeBuildCommand 'mkdocs')) { + Invoke-PodeBuildInstall 'mkdocs' $Versions.MkDocs + } + + $_installed = (pip list --format json --disable-pip-version-check | ConvertFrom-Json) + if (($_installed | Where-Object { $_.name -ieq 'mkdocs-material' -and $_.version -ieq $Versions.MkDocsTheme } | Measure-Object).Count -eq 0) { + pip install "mkdocs-material==$($Versions.MkDocsTheme)" --force-reinstall --disable-pip-version-check --quiet + } - $_installed = (pip list --format json --disable-pip-version-check | ConvertFrom-Json) - if (($_installed | Where-Object { $_.name -ieq 'mkdocs-material' -and $_.version -ieq $Versions.MkDocsTheme } | Measure-Object).Count -eq 0) { - pip install "mkdocs-material==$($Versions.MkDocsTheme)" --force-reinstall --disable-pip-version-check --quiet + # install platyps + Install-PodeBuildModule PlatyPS } - # install platyps - Install-PodeBuildModule PlatyPS -} + Task IndexSamples { + $examplesPath = './examples' + if (!(Test-Path -PathType Container -Path $examplesPath)) { + return + } -Task IndexSamples { - $examplesPath = './examples' - if (!(Test-Path -PathType Container -Path $examplesPath)) { - return + # List of directories to exclude + $sampleMarkDownPath = './docs/Getting-Started/Samples.md' + $excludeDirs = @('scripts', 'views', 'static', 'public', 'assets', 'timers', 'modules', + 'Authentication', 'certs', 'logs', 'relative', 'routes', 'issues') + + # Convert exlusion list into single regex pattern for directory matching + $dirSeparator = [IO.Path]::DirectorySeparatorChar + $excludeDirs = "\$($dirSeparator)($($excludeDirs -join '|'))\$($dirSeparator)" + + # build the page content + Get-ChildItem -Path $examplesPath -Filter *.ps1 -Recurse -File -Force | + Where-Object { + $_.FullName -inotmatch $excludeDirs + } | + Sort-Object -Property FullName | + ForEach-Object { + Write-Verbose "Processing Sample: $($_.FullName)" + + # get the script help + $help = Get-Help -Name $_.FullName -ErrorAction Stop + + # add help content + $urlFileName = ($_.FullName -isplit 'examples')[1].Trim('\/') -replace '[\\/]', '/' + $markdownContent += "## [$($_.BaseName)](https://github.com/Badgerati/Pode/blob/develop/examples/$($urlFileName))`n`n" + $markdownContent += "**Synopsis**`n`n$($help.Synopsis)`n`n" + $markdownContent += "**Description**`n`n$($help.Description.Text)`n`n" + } + + Write-Output "Write Markdown document for the sample files to $($sampleMarkDownPath)" + Set-Content -Path $sampleMarkDownPath -Value "# Sample Scripts`n`n$($markdownContent)" -Force } - # List of directories to exclude - $sampleMarkDownPath = './docs/Getting-Started/Samples.md' - $excludeDirs = @('scripts', 'views', 'static', 'public', 'assets', 'timers', 'modules', - 'Authentication', 'certs', 'logs', 'relative', 'routes', 'issues') + <# +# Building +#> + + # Synopsis: Build the .NET Listener + Task Build BuildDeps, { + if (Test-Path ./src/Libs) { + Remove-Item -Path ./src/Libs -Recurse -Force | Out-Null + } - # Convert exlusion list into single regex pattern for directory matching - $dirSeparator = [IO.Path]::DirectorySeparatorChar - $excludeDirs = "\$($dirSeparator)($($excludeDirs -join '|'))\$($dirSeparator)" + # Retrieve supported .NET versions + $eol = Get-PodeBuildDotNetEOL - # build the page content - Get-ChildItem -Path $examplesPath -Filter *.ps1 -Recurse -File -Force | - Where-Object { - $_.FullName -inotmatch $excludeDirs - } | - Sort-Object -Property FullName | - ForEach-Object { - Write-Verbose "Processing Sample: $($_.FullName)" + $targetFrameworks = @() - # get the script help - $help = Get-Help -Name $_.FullName -ErrorAction Stop + if (![string]::IsNullOrEmpty($eol.supported)) { - # add help content - $urlFileName = ($_.FullName -isplit 'examples')[1].Trim('\/') -replace '[\\/]', '/' - $markdownContent += "## [$($_.BaseName)](https://github.com/Badgerati/Pode/blob/develop/examples/$($urlFileName))`n`n" - $markdownContent += "**Synopsis**`n`n$($help.Synopsis)`n`n" - $markdownContent += "**Description**`n`n$($help.Description.Text)`n`n" + # Parse supported versions into an array + $supportedVersions = $eol['supported'] -split ',' + + # Construct target framework monikers + $targetFrameworks += ($supportedVersions | ForEach-Object { "net$_.0" }) } - Write-Output "Write Markdown document for the sample files to $($sampleMarkDownPath)" - Set-Content -Path $sampleMarkDownPath -Value "# Sample Scripts`n`n$($markdownContent)" -Force -} + # Optionally include netstandard2.0 + $targetFrameworks += 'netstandard2.0' -<# -# Building -#> -# Synopsis: Build the .NET Listener -Task Build BuildDeps, { - if (Test-Path ./src/Libs) { - Remove-Item -Path ./src/Libs -Recurse -Force | Out-Null - } + # Retrieve the SDK version being used + $sdkVersion = dotnet --version + + # Display the SDK version + Write-Output "Building target framework '$($targetFrameworks -join "','")' using .NET SDK version '$sdkVersion'" + + # Build for supported target frameworks + try { + Push-Location ./src/Listener + foreach ($target in $targetFrameworks) { + Invoke-PodeBuildDotnetBuild -target $target + Write-Host + Write-Host "***********************" -ForegroundColor DarkMagenta + + } + } + finally { + Pop-Location + } - try { - Push-Location ./src/Listener - Invoke-PodeBuildDotnetBuild -target 'netstandard2.0' - Invoke-PodeBuildDotnetBuild -target 'net6.0' - Invoke-PodeBuildDotnetBuild -target 'net8.0' - } - finally { - Pop-Location } -} -<# + <# # Packaging #> -# Synopsis: Creates a Zip of the Module -Task 7Zip -If (Test-PodeBuildIsWindows) PackDeps, StampVersion, { - exec { & 7z -tzip a $Version-Binaries.zip ./pkg/* } -}, PrintChecksum - -#Synopsis: Create the Deliverable folder -Task DeliverableFolder { - $path = './deliverable' - if (Test-Path $path) { - Remove-Item -Path $path -Recurse -Force | Out-Null - } + # Synopsis: Creates a Zip of the Module + Task 7Zip -If (Test-PodeBuildIsWindows) PackDeps, StampVersion, { + exec { & 7z -tzip a $Version-Binaries.zip ./pkg/* } + }, PrintChecksum - # create the deliverable dir - New-Item -Path $path -ItemType Directory -Force | Out-Null -} - -# Synopsis: Creates a Zip of the Module -Task Compress PackageFolder, StampVersion, DeliverableFolder, { - $path = './deliverable' - if (Test-Path $path) { - Remove-Item -Path $path -Recurse -Force | Out-Null - } - # create the pkg dir - New-Item -Path $path -ItemType Directory -Force | Out-Null - Compress-Archive -Path './pkg/*' -DestinationPath "$path/$Version-Binaries.zip" -}, PrintChecksum - -# Synopsis: Creates a Chocolately package of the Module -Task ChocoPack -If (Test-PodeBuildIsWindows) PackDeps, PackageFolder, StampVersion, DeliverableFolder, { - exec { choco pack ./packers/choco/pode.nuspec } - Move-Item -Path "pode.$Version.nupkg" -Destination './deliverable' -} + #Synopsis: Create the Deliverable folder + Task DeliverableFolder { + $path = './deliverable' + if (Test-Path $path) { + Remove-Item -Path $path -Recurse -Force | Out-Null + } -# Synopsis: Create docker tags -Task DockerPack PackageFolder, StampVersion, { - # check if github and windows, and output warning - if ((Test-PodeBuildIsGitHub) -and (Test-PodeBuildIsWindows)) { - Write-Warning 'Docker images are not built on GitHub Windows runners, and Docker is in Windows container only mode. Exiting task.' - return + # create the deliverable dir + New-Item -Path $path -ItemType Directory -Force | Out-Null } - try { - # Try to get the Docker version to check if Docker is installed - docker --version - } - catch { - # If Docker is not available, exit the task - Write-Warning 'Docker is not installed or not available in the PATH. Exiting task.' - return - } + # Synopsis: Creates a Zip of the Module + Task Compress PackageFolder, StampVersion, DeliverableFolder, { + $path = './deliverable' + if (Test-Path $path) { + Remove-Item -Path $path -Recurse -Force | Out-Null + } + # create the pkg dir + New-Item -Path $path -ItemType Directory -Force | Out-Null + Compress-Archive -Path './pkg/*' -DestinationPath "$path/$Version-Binaries.zip" + }, PrintChecksum + + # Synopsis: Creates a Chocolately package of the Module + Task ChocoPack -If (Test-PodeBuildIsWindows) PackDeps, PackageFolder, StampVersion, DeliverableFolder, { + exec { choco pack ./packers/choco/pode.nuspec } + Move-Item -Path "pode.$Version.nupkg" -Destination './deliverable' + } + + # Synopsis: Create docker tags + Task DockerPack PackageFolder, StampVersion, { + # check if github and windows, and output warning + if ((Test-PodeBuildIsGitHub) -and (Test-PodeBuildIsWindows)) { + Write-Warning 'Docker images are not built on GitHub Windows runners, and Docker is in Windows container only mode. Exiting task.' + return + } + + try { + # Try to get the Docker version to check if Docker is installed + docker --version + } + catch { + # If Docker is not available, exit the task + Write-Warning 'Docker is not installed or not available in the PATH. Exiting task.' + return + } - Invoke-PodeBuildDockerBuild -Tag $Version -File './Dockerfile' - Invoke-PodeBuildDockerBuild -Tag 'latest' -File './Dockerfile' - Invoke-PodeBuildDockerBuild -Tag "$Version-alpine" -File './alpine.dockerfile' - Invoke-PodeBuildDockerBuild -Tag 'latest-alpine' -File './alpine.dockerfile' + Invoke-PodeBuildDockerBuild -Tag $Version -File './Dockerfile' + Invoke-PodeBuildDockerBuild -Tag 'latest' -File './Dockerfile' + Invoke-PodeBuildDockerBuild -Tag "$Version-alpine" -File './alpine.dockerfile' + Invoke-PodeBuildDockerBuild -Tag 'latest-alpine' -File './alpine.dockerfile' - if (!(Test-PodeBuildIsGitHub)) { - Invoke-PodeBuildDockerBuild -Tag "$Version-arm32" -File './arm32.dockerfile' - Invoke-PodeBuildDockerBuild -Tag 'latest-arm32' -File './arm32.dockerfile' - } - else { - Write-Warning 'Docker images for ARM32 are not built on GitHub runners due to having the wrong OS architecture. Skipping.' + if (!(Test-PodeBuildIsGitHub)) { + Invoke-PodeBuildDockerBuild -Tag "$Version-arm32" -File './arm32.dockerfile' + Invoke-PodeBuildDockerBuild -Tag 'latest-arm32' -File './arm32.dockerfile' + } + else { + Write-Warning 'Docker images for ARM32 are not built on GitHub runners due to having the wrong OS architecture. Skipping.' + } } -} -# Synopsis: Package up the Module -Task Pack Compress, ChocoPack, DockerPack + # Synopsis: Package up the Module + Task Pack Compress, ChocoPack, DockerPack -# Synopsis: Package up the Module into a /pkg folder -Task PackageFolder Build, { - $path = './pkg' - if (Test-Path $path) { - Remove-Item -Path $path -Recurse -Force | Out-Null - } + # Synopsis: Package up the Module into a /pkg folder + Task PackageFolder Build, { + $path = './pkg' + if (Test-Path $path) { + Remove-Item -Path $path -Recurse -Force | Out-Null + } - # create the pkg dir - New-Item -Path $path -ItemType Directory -Force | Out-Null + # create the pkg dir + New-Item -Path $path -ItemType Directory -Force | Out-Null - # which source folders do we need? create them and copy their contents - $folders = @('Private', 'Public', 'Misc', 'Libs', 'Locales') - $folders | ForEach-Object { - New-Item -ItemType Directory -Path (Join-Path $path $_) -Force | Out-Null - Copy-Item -Path "./src/$($_)/*" -Destination (Join-Path $path $_) -Force -Recurse | Out-Null - } + # which source folders do we need? create them and copy their contents + $folders = @('Private', 'Public', 'Misc', 'Libs', 'Locales') + $folders | ForEach-Object { + New-Item -ItemType Directory -Path (Join-Path $path $_) -Force | Out-Null + Copy-Item -Path "./src/$($_)/*" -Destination (Join-Path $path $_) -Force -Recurse | Out-Null + } - # which route folders to we need? create them and copy their contents - $folders = @('licenses') - $folders | ForEach-Object { - New-Item -ItemType Directory -Path (Join-Path $path $_) -Force | Out-Null - Copy-Item -Path "./$($_)/*" -Destination (Join-Path $path $_) -Force -Recurse | Out-Null - } + # which route folders to we need? create them and copy their contents + $folders = @('licenses') + $folders | ForEach-Object { + New-Item -ItemType Directory -Path (Join-Path $path $_) -Force | Out-Null + Copy-Item -Path "./$($_)/*" -Destination (Join-Path $path $_) -Force -Recurse | Out-Null + } - # copy general files - $files = @('src/Pode.psm1', 'src/Pode.psd1', 'src/Pode.Internal.psm1', 'src/Pode.Internal.psd1', 'LICENSE.txt') - $files | ForEach-Object { - Copy-Item -Path "./$($_)" -Destination $path -Force | Out-Null + # copy general files + $files = @('src/Pode.psm1', 'src/Pode.psd1', 'src/Pode.Internal.psm1', 'src/Pode.Internal.psd1', 'LICENSE.txt') + $files | ForEach-Object { + Copy-Item -Path "./$($_)" -Destination $path -Force | Out-Null + } } -} -<# + <# # Testing #> -# Synopsis: Run the tests -Task TestNoBuild TestDeps, { - $p = (Get-Command Invoke-Pester) - if ($null -eq $p -or $p.Version -ine $Versions.Pester) { - Remove-Module Pester -Force -ErrorAction Ignore - Import-Module Pester -Force -RequiredVersion $Versions.Pester - } - - # for windows, output current netsh excluded ports - if (Test-PodeBuildIsWindows) { - netsh int ipv4 show excludedportrange protocol=tcp | Out-Default - } - if ($UICulture -ne ([System.Threading.Thread]::CurrentThread.CurrentUICulture) ) { - $originalUICulture = [System.Threading.Thread]::CurrentThread.CurrentUICulture - Write-Output "Original UICulture is $originalUICulture" - Write-Output "Set UICulture to $UICulture" - # set new UICulture - [System.Threading.Thread]::CurrentThread.CurrentUICulture = $UICulture - } - $Script:TestResultFile = "$($pwd)/TestResults.xml" - - # get default from static property - $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 + # Synopsis: Run the tests + Task TestNoBuild TestDeps, { + $p = (Get-Command Invoke-Pester) + if ($null -eq $p -or $p.Version -ine $Versions.Pester) { + Remove-Module Pester -Force -ErrorAction Ignore + Import-Module Pester -Force -RequiredVersion $Versions.Pester + } - # if run code coverage if enabled - if (Test-PodeBuildCanCodeCoverage) { - $srcFiles = (Get-ChildItem "$($pwd)/src/*.ps1" -Recurse -Force).FullName - $configuration.CodeCoverage.Enabled = $true - $configuration.CodeCoverage.Path = $srcFiles - $Script:TestStatus = Invoke-Pester -Configuration $configuration - } - else { - $Script:TestStatus = Invoke-Pester -Configuration $configuration - } - if ($originalUICulture) { - Write-Output "Restore UICulture to $originalUICulture" - # restore original UICulture - [System.Threading.Thread]::CurrentThread.CurrentUICulture = $originalUICulture - } -}, PushCodeCoverage, CheckFailedTests + # for windows, output current netsh excluded ports + if (Test-PodeBuildIsWindows) { + netsh int ipv4 show excludedportrange protocol=tcp | Out-Default + } + if ($UICulture -ne ([System.Threading.Thread]::CurrentThread.CurrentUICulture) ) { + $originalUICulture = [System.Threading.Thread]::CurrentThread.CurrentUICulture + Write-Output "Original UICulture is $originalUICulture" + Write-Output "Set UICulture to $UICulture" + # set new UICulture + [System.Threading.Thread]::CurrentThread.CurrentUICulture = $UICulture + } + $Script:TestResultFile = "$($pwd)/TestResults.xml" + + # get default from static property + $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 + + # if run code coverage if enabled + if (Test-PodeBuildCanCodeCoverage) { + $srcFiles = (Get-ChildItem "$($pwd)/src/*.ps1" -Recurse -Force).FullName + $configuration.CodeCoverage.Enabled = $true + $configuration.CodeCoverage.Path = $srcFiles + $Script:TestStatus = Invoke-Pester -Configuration $configuration + } + else { + $Script:TestStatus = Invoke-Pester -Configuration $configuration + } + if ($originalUICulture) { + Write-Output "Restore UICulture to $originalUICulture" + # restore original UICulture + [System.Threading.Thread]::CurrentThread.CurrentUICulture = $originalUICulture + } + }, PushCodeCoverage, CheckFailedTests -# Synopsis: Run tests after a build -Task Test Build, TestNoBuild + # Synopsis: Run tests after a build + Task Test Build, TestNoBuild -# Synopsis: Check if any of the tests failed -Task CheckFailedTests { - if ($TestStatus.FailedCount -gt 0) { - throw "$($TestStatus.FailedCount) tests failed" + # Synopsis: Check if any of the tests failed + Task CheckFailedTests { + if ($TestStatus.FailedCount -gt 0) { + throw "$($TestStatus.FailedCount) tests failed" + } } -} -# Synopsis: If AppyVeyor or GitHub, push code coverage stats -Task PushCodeCoverage -If (Test-PodeBuildCanCodeCoverage) { - try { - $service = Get-PodeBuildService - $branch = Get-PodeBuildBranch + # Synopsis: If AppyVeyor or GitHub, push code coverage stats + Task PushCodeCoverage -If (Test-PodeBuildCanCodeCoverage) { + try { + $service = Get-PodeBuildService + $branch = Get-PodeBuildBranch - Write-Host "Pushing coverage for $($branch) from $($service)" - $coverage = New-CoverallsReport -Coverage $Script:TestStatus.CodeCoverage -ServiceName $service -BranchName $branch - Publish-CoverallsReport -Report $coverage -ApiToken $env:PODE_COVERALLS_TOKEN - } - catch { - $_.Exception | Out-Default + Write-Host "Pushing coverage for $($branch) from $($service)" + $coverage = New-CoverallsReport -Coverage $Script:TestStatus.CodeCoverage -ServiceName $service -BranchName $branch + Publish-CoverallsReport -Report $coverage -ApiToken $env:PODE_COVERALLS_TOKEN + } + catch { + $_.Exception | Out-Default + } } -} -<# + <# # Docs #> -# Synopsis: Run the documentation locally -Task Docs DocsDeps, DocsHelpBuild, { - mkdocs serve --open -} + # Synopsis: Run the documentation locally + Task Docs DocsDeps, DocsHelpBuild, { + mkdocs serve --open + } -# Synopsis: Build the function help documentation -Task DocsHelpBuild IndexSamples, DocsDeps, Build, { - # import the local module - Remove-Module Pode -Force -ErrorAction Ignore | Out-Null - Import-Module ./src/Pode.psm1 -Force | Out-Null + # Synopsis: Build the function help documentation + Task DocsHelpBuild IndexSamples, DocsDeps, Build, { + # import the local module + Remove-Module Pode -Force -ErrorAction Ignore | Out-Null + Import-Module ./src/Pode.psm1 -Force | Out-Null - # build the function docs - $path = './docs/Functions' - $map = @{} + # build the function docs + $path = './docs/Functions' + $map = @{} (Get-Module Pode).ExportedFunctions.Keys | ForEach-Object { - $type = [System.IO.Path]::GetFileNameWithoutExtension((Split-Path -Leaf -Path (Get-Command $_ -Module Pode).ScriptBlock.File)) - New-MarkdownHelp -Command $_ -OutputFolder (Join-Path $path $type) -Force -Metadata @{ PodeType = $type } -AlphabeticParamsOrder | Out-Null - $map[$_] = $type - } + $type = [System.IO.Path]::GetFileNameWithoutExtension((Split-Path -Leaf -Path (Get-Command $_ -Module Pode).ScriptBlock.File)) + New-MarkdownHelp -Command $_ -OutputFolder (Join-Path $path $type) -Force -Metadata @{ PodeType = $type } -AlphabeticParamsOrder | Out-Null + $map[$_] = $type + } - # update docs to bind links to unlinked functions - $path = Join-Path $pwd 'docs' - Get-ChildItem -Path $path -Recurse -Filter '*.md' | ForEach-Object { - $depth = ($_.FullName.Replace($path, [string]::Empty).trim('\/') -split '[\\/]').Length - $updated = $false + # update docs to bind links to unlinked functions + $path = Join-Path $pwd 'docs' + Get-ChildItem -Path $path -Recurse -Filter '*.md' | ForEach-Object { + $depth = ($_.FullName.Replace($path, [string]::Empty).trim('\/') -split '[\\/]').Length + $updated = $false - $content = (Get-Content -Path $_.FullName | ForEach-Object { - $line = $_ + $content = (Get-Content -Path $_.FullName | ForEach-Object { + $line = $_ - while ($line -imatch '\[`(?[a-z]+\-pode[a-z]+)`\](?([^(]|$))') { - $updated = $true - $name = $Matches['name'] - $char = $Matches['char'] - $line = ($line -ireplace "\[``$($name)``\]([^(]|$)", "[``$($name)``]($('../' * $depth)Functions/$($map[$name])/$($name))$($char)") - } + while ($line -imatch '\[`(?[a-z]+\-pode[a-z]+)`\](?([^(]|$))') { + $updated = $true + $name = $Matches['name'] + $char = $Matches['char'] + $line = ($line -ireplace "\[``$($name)``\]([^(]|$)", "[``$($name)``]($('../' * $depth)Functions/$($map[$name])/$($name))$($char)") + } - $line - }) + $line + }) - if ($updated) { - $content | Out-File -FilePath $_.FullName -Force -Encoding ascii + if ($updated) { + $content | Out-File -FilePath $_.FullName -Force -Encoding ascii + } } - } - # remove the module - Remove-Module Pode -Force -ErrorAction Ignore | Out-Null -} + # remove the module + Remove-Module Pode -Force -ErrorAction Ignore | Out-Null + } -# Synopsis: Build the documentation -Task DocsBuild DocsDeps, DocsHelpBuild, { - mkdocs build --quiet -} + # Synopsis: Build the documentation + Task DocsBuild DocsDeps, DocsHelpBuild, { + mkdocs build --quiet + } -<# + <# # Clean-up #> -# Synopsis: Clean the build enviroment -Task Clean CleanPkg, CleanDeliverable, CleanLibs, CleanListener, CleanDocs + # Synopsis: Clean the build enviroment + Task Clean CleanPkg, CleanDeliverable, CleanLibs, CleanListener, CleanDocs -# Synopsis: Clean the Deliverable folder -Task CleanDeliverable { - $path = './deliverable' - if (Test-Path -Path $path -PathType Container) { - Write-Host 'Removing ./deliverable folder' - Remove-Item -Path $path -Recurse -Force | Out-Null + # Synopsis: Clean the Deliverable folder + Task CleanDeliverable { + $path = './deliverable' + if (Test-Path -Path $path -PathType Container) { + Write-Host 'Removing ./deliverable folder' + Remove-Item -Path $path -Recurse -Force | Out-Null + } + Write-Host "Cleanup $path done" } - Write-Host "Cleanup $path done" -} -# Synopsis: Clean the pkg directory -Task CleanPkg { - $path = './pkg' - if ((Test-Path -Path $path -PathType Container )) { - Write-Host 'Removing ./pkg folder' - Remove-Item -Path $path -Recurse -Force | Out-Null - } + # Synopsis: Clean the pkg directory + Task CleanPkg { + $path = './pkg' + if ((Test-Path -Path $path -PathType Container )) { + Write-Host 'Removing ./pkg folder' + Remove-Item -Path $path -Recurse -Force | Out-Null + } - if ((Test-Path -Path .\packers\choco\tools\ChocolateyInstall.ps1 -PathType Leaf )) { - Write-Host 'Removing .\packers\choco\tools\ChocolateyInstall.ps1' - Remove-Item -Path .\packers\choco\tools\ChocolateyInstall.ps1 - } + if ((Test-Path -Path .\packers\choco\tools\ChocolateyInstall.ps1 -PathType Leaf )) { + Write-Host 'Removing .\packers\choco\tools\ChocolateyInstall.ps1' + Remove-Item -Path .\packers\choco\tools\ChocolateyInstall.ps1 + } - if ((Test-Path -Path .\packers\choco\pode.nuspec -PathType Leaf )) { - Write-Host 'Removing .\packers\choco\pode.nuspec' - Remove-Item -Path .\packers\choco\pode.nuspec + if ((Test-Path -Path .\packers\choco\pode.nuspec -PathType Leaf )) { + Write-Host 'Removing .\packers\choco\pode.nuspec' + Remove-Item -Path .\packers\choco\pode.nuspec + } + + Write-Host "Cleanup $path done" } - Write-Host "Cleanup $path done" -} + # Synopsis: Clean the libs folder + Task CleanLibs { + $path = './src/Libs' + if (Test-Path -Path $path -PathType Container) { + Write-Host "Removing $path contents" + Remove-Item -Path $path -Recurse -Force | Out-Null + } -# Synopsis: Clean the libs folder -Task CleanLibs { - $path = './src/Libs' - if (Test-Path -Path $path -PathType Container) { - Write-Host "Removing $path contents" - Remove-Item -Path $path -Recurse -Force | Out-Null + Write-Host "Cleanup $path done" } - Write-Host "Cleanup $path done" -} + # Synopsis: Clean the Listener folder + Task CleanListener { + $path = './src/Listener/bin' + if (Test-Path -Path $path -PathType Container) { + Write-Host "Removing $path contents" + Remove-Item -Path $path -Recurse -Force | Out-Null + } -# Synopsis: Clean the Listener folder -Task CleanListener { - $path = './src/Listener/bin' - if (Test-Path -Path $path -PathType Container) { - Write-Host "Removing $path contents" - Remove-Item -Path $path -Recurse -Force | Out-Null + Write-Host "Cleanup $path done" } - Write-Host "Cleanup $path done" -} - -Task CleanDocs { - $path = './docs/Getting-Started/Samples.md' - if (Test-Path -Path $path -PathType Leaf) { - Write-Host "Removing $path" - Remove-Item -Path $path -Force | Out-Null + Task CleanDocs { + $path = './docs/Getting-Started/Samples.md' + if (Test-Path -Path $path -PathType Leaf) { + Write-Host "Removing $path" + Remove-Item -Path $path -Force | Out-Null + } } -} -<# + <# # Local module management #> -# Synopsis: Install Pode Module locally -Task Install-Module -If ($Version) Pack, { - $PSPaths = Split-PodeBuildPwshPath + # Synopsis: Install Pode Module locally + Task Install-Module -If ($Version) Pack, { + $PSPaths = Split-PodeBuildPwshPath - $dest = Join-Path -Path $PSPaths[0] -ChildPath 'Pode' -AdditionalChildPath "$Version" - if (Test-Path $dest) { - Remove-Item -Path $dest -Recurse -Force | Out-Null - } + $dest = Join-Path -Path $PSPaths[0] -ChildPath 'Pode' -AdditionalChildPath "$Version" + if (Test-Path $dest) { + Remove-Item -Path $dest -Recurse -Force | Out-Null + } - # create the dest dir - New-Item -Path $dest -ItemType Directory -Force | Out-Null - $path = './pkg' + # create the dest dir + New-Item -Path $dest -ItemType Directory -Force | Out-Null + $path = './pkg' - # copy over folders - $folders = @('Private', 'Public', 'Misc', 'Libs', 'licenses', 'Locales') - $folders | ForEach-Object { - Copy-Item -Path (Join-Path -Path $path -ChildPath $_) -Destination $dest -Force -Recurse | Out-Null - } + # copy over folders + $folders = @('Private', 'Public', 'Misc', 'Libs', 'licenses', 'Locales') + $folders | ForEach-Object { + Copy-Item -Path (Join-Path -Path $path -ChildPath $_) -Destination $dest -Force -Recurse | Out-Null + } - # copy over general files - $files = @('Pode.psm1', 'Pode.psd1', 'Pode.Internal.psm1', 'Pode.Internal.psd1', 'LICENSE.txt') - $files | ForEach-Object { - Copy-Item -Path (Join-Path -Path $path -ChildPath $_) -Destination $dest -Force | Out-Null + # copy over general files + $files = @('Pode.psm1', 'Pode.psd1', 'Pode.Internal.psm1', 'Pode.Internal.psd1', 'LICENSE.txt') + $files | ForEach-Object { + Copy-Item -Path (Join-Path -Path $path -ChildPath $_) -Destination $dest -Force | Out-Null + } + + Write-Host "Deployed to $dest" } - Write-Host "Deployed to $dest" -} + # Synopsis: Remove the Pode Module from the local registry + Task Remove-Module { + if (!$Version) { + throw 'Parameter -Version is required' + } -# Synopsis: Remove the Pode Module from the local registry -Task Remove-Module { - if (!$Version) { - throw 'Parameter -Version is required' - } + $PSPaths = Split-PodeBuildPwshPath - $PSPaths = Split-PodeBuildPwshPath + $dest = Join-Path -Path $PSPaths[0] -ChildPath 'Pode' -AdditionalChildPath "$Version" + if (!(Test-Path $dest)) { + Write-Warning "Directory $dest doesn't exist" + } - $dest = Join-Path -Path $PSPaths[0] -ChildPath 'Pode' -AdditionalChildPath "$Version" - if (!(Test-Path $dest)) { - Write-Warning "Directory $dest doesn't exist" + Write-Host "Deleting module from $dest" + Remove-Item -Path $dest -Recurse -Force | Out-Null } - Write-Host "Deleting module from $dest" - Remove-Item -Path $dest -Recurse -Force | Out-Null -} - -<# + <# # PowerShell setup #> -# Synopsis: Setup the PowerShell environment -Task SetupPowerShell { - # code for this step is altered versions of the code found here: - # - https://github.com/bjompen/UpdatePWSHAction/blob/main/UpgradePwsh.ps1 - # - https://raw.githubusercontent.com/PowerShell/PowerShell/master/tools/install-powershell.ps1 + # Synopsis: Setup the PowerShell environment + Task SetupPowerShell { + # code for this step is altered versions of the code found here: + # - https://github.com/bjompen/UpdatePWSHAction/blob/main/UpgradePwsh.ps1 + # - https://raw.githubusercontent.com/PowerShell/PowerShell/master/tools/install-powershell.ps1 - # fail if no version supplied - if ([string]::IsNullOrWhiteSpace($PowerShellVersion)) { - throw 'No PowerShell version supplied to set up' - } + # fail if no version supplied + if ([string]::IsNullOrWhiteSpace($PowerShellVersion)) { + throw 'No PowerShell version supplied to set up' + } - # is the version valid? - $tags = @('preview', 'lts', 'daily', 'stable') - if (($PowerShellVersion -inotin $tags) -and ($PowerShellVersion -inotmatch '^\d+\.\d+\.\d+(-\w+(\.\d+)?)?$')) { - throw "Invalid PowerShell version supplied: $($PowerShellVersion)" - } + # is the version valid? + $tags = @('preview', 'lts', 'daily', 'stable') + if (($PowerShellVersion -inotin $tags) -and ($PowerShellVersion -inotmatch '^\d+\.\d+\.\d+(-\w+(\.\d+)?)?$')) { + throw "Invalid PowerShell version supplied: $($PowerShellVersion)" + } - # tag version or literal version? - $isTagVersion = $PowerShellVersion -iin $tags - if ($isTagVersion) { - Write-Host "Release tag: $($PowerShellVersion)" - $PowerShellVersion = Convert-PodeBuildOSPwshTagToVersion - } - Write-Host "Release version: $($PowerShellVersion)" + # tag version or literal version? + $isTagVersion = $PowerShellVersion -iin $tags + if ($isTagVersion) { + Write-Host "Release tag: $($PowerShellVersion)" + $PowerShellVersion = Convert-PodeBuildOSPwshTagToVersion + } + Write-Host "Release version: $($PowerShellVersion)" - # base/prefix versions - $atoms = $PowerShellVersion -split '\-' - $baseVersion = $atoms[0] + # base/prefix versions + $atoms = $PowerShellVersion -split '\-' + $baseVersion = $atoms[0] - # do nothing if the current version is the version we're trying to set up - $currentVersion = Get-PodeBuildCurrentPwshVersion - Write-Host "Current PowerShell version: $($currentVersion)" + # do nothing if the current version is the version we're trying to set up + $currentVersion = Get-PodeBuildCurrentPwshVersion + Write-Host "Current PowerShell version: $($currentVersion)" - if ($baseVersion -ieq $currentVersion) { - Write-Host "PowerShell version $($PowerShellVersion) is already installed" - return - } + if ($baseVersion -ieq $currentVersion) { + Write-Host "PowerShell version $($PowerShellVersion) is already installed" + return + } - # build the package name - $arch = Get-PodeBuildOSPwshArchitecture - $os = Get-PodeBuildOSPwshName + # build the package name + $arch = Get-PodeBuildOSPwshArchitecture + $os = Get-PodeBuildOSPwshName - $packageName = (@{ - win = "PowerShell-$($PowerShellVersion)-$($os)-$($arch).zip" - linux = "powershell-$($PowerShellVersion)-$($os)-$($arch).tar.gz" - osx = "powershell-$($PowerShellVersion)-$($os)-$($arch).tar.gz" - })[$os] + $packageName = (@{ + win = "PowerShell-$($PowerShellVersion)-$($os)-$($arch).zip" + linux = "powershell-$($PowerShellVersion)-$($os)-$($arch).tar.gz" + osx = "powershell-$($PowerShellVersion)-$($os)-$($arch).tar.gz" + })[$os] - # build the URL - $urls = @{ - Old = "https://pscoretestdata.blob.core.windows.net/v$($PowerShellVersion -replace '\.', '-')/$($packageName)" - New = "https://powershellinfraartifacts-gkhedzdeaghdezhr.z01.azurefd.net/install/v$($PowerShellVersion)/$($packageName)" - } + # build the URL + $urls = @{ + Old = "https://pscoretestdata.blob.core.windows.net/v$($PowerShellVersion -replace '\.', '-')/$($packageName)" + New = "https://powershellinfraartifacts-gkhedzdeaghdezhr.z01.azurefd.net/install/v$($PowerShellVersion)/$($packageName)" + } - # download the package to a temp location - $outputFile = Join-Path -Path ([System.IO.Path]::GetTempPath()) -ChildPath $packageName - $downloadParams = @{ - Uri = $urls.New - OutFile = $outputFile - ErrorAction = 'Stop' - } + # download the package to a temp location + $outputFile = Join-Path -Path ([System.IO.Path]::GetTempPath()) -ChildPath $packageName + $downloadParams = @{ + Uri = $urls.New + OutFile = $outputFile + ErrorAction = 'Stop' + } - Write-Host "Output file: $($outputFile)" + Write-Host "Output file: $($outputFile)" - # retry the download 6 times, with a sleep of 10s between each attempt, and altering between old and new URLs - $counter = 0 - $success = $false + # retry the download 6 times, with a sleep of 10s between each attempt, and altering between old and new URLs + $counter = 0 + $success = $false - do { - try { - $counter++ - Write-Host "Attempt $($counter) of 6" + do { + try { + $counter++ + Write-Host "Attempt $($counter) of 6" - # use new URL for odd attempts, and old URL for even attempts - if ($counter % 2 -eq 0) { - $downloadParams.Uri = $urls.Old - } - else { - $downloadParams.Uri = $urls.New - } + # use new URL for odd attempts, and old URL for even attempts + if ($counter % 2 -eq 0) { + $downloadParams.Uri = $urls.Old + } + else { + $downloadParams.Uri = $urls.New + } - # download the package - Write-Host "Attempting download of $($packageName) from $($downloadParams.Uri)" - Invoke-WebRequest @downloadParams + # download the package + Write-Host "Attempting download of $($packageName) from $($downloadParams.Uri)" + Invoke-WebRequest @downloadParams - $success = $true - Write-Host "Downloaded $($packageName) successfully" - } - catch { - $success = $false - if ($counter -ge 6) { - throw "Failed to download PowerShell package after 6 attempts. Error: $($_.Exception.Message)" + $success = $true + Write-Host "Downloaded $($packageName) successfully" + } + catch { + $success = $false + if ($counter -ge 6) { + throw "Failed to download PowerShell package after 6 attempts. Error: $($_.Exception.Message)" + } + + Start-Sleep -Seconds 5 } + } while (!$success) - Start-Sleep -Seconds 5 + # create target folder for package + $targetFolder = Join-Path -Path (Resolve-Path ~).Path -ChildPath ($packageName -ireplace '\.tar$') + if (!(Test-Path $targetFolder)) { + $null = New-Item -Path $targetFolder -ItemType Directory -Force } - } while (!$success) - # create target folder for package - $targetFolder = Join-Path -Path (Resolve-Path ~).Path -ChildPath ($packageName -ireplace '\.tar$') - if (!(Test-Path $targetFolder)) { - $null = New-Item -Path $targetFolder -ItemType Directory -Force - } + # extract the package + switch ($os) { + 'win' { + Expand-Archive -Path $outputFile -DestinationPath $targetFolder -Force + } - # extract the package - switch ($os) { - 'win' { - Expand-Archive -Path $outputFile -DestinationPath $targetFolder -Force + { $_ -iin 'linux', 'osx' } { + $null = tar -xzf $outputFile -C $targetFolder + } } - { $_ -iin 'linux', 'osx' } { - $null = tar -xzf $outputFile -C $targetFolder + # install the package + Write-Host "Installing PowerShell $($PowerShellVersion) to $($targetFolder)" + if (Test-PodeBuildOSWindows) { + Install-PodeBuildPwshWindows -Target $targetFolder + } + else { + Install-PodeBuildPwshUnix -Target $targetFolder } } - # install the package - Write-Host "Installing PowerShell $($PowerShellVersion) to $($targetFolder)" - if (Test-PodeBuildOSWindows) { - Install-PodeBuildPwshWindows -Target $targetFolder - } - else { - Install-PodeBuildPwshUnix -Target $targetFolder - } -} - -<# + <# # Release Notes #> -# Synopsis: Build the Release Notes -task ReleaseNotes { - if ([string]::IsNullOrWhiteSpace($ReleaseNoteVersion)) { - Write-Host 'Please provide a ReleaseNoteVersion' -ForegroundColor Red - return - } + # Synopsis: Build the Release Notes + task ReleaseNotes { + if ([string]::IsNullOrWhiteSpace($ReleaseNoteVersion)) { + Write-Host 'Please provide a ReleaseNoteVersion' -ForegroundColor Red + return + } - # get the PRs for the ReleaseNoteVersion - $prs = gh search prs --milestone $ReleaseNoteVersion --repo badgerati/pode --merged --limit 200 --json 'number,title,labels,author' | ConvertFrom-Json + # get the PRs for the ReleaseNoteVersion + $prs = gh search prs --milestone $ReleaseNoteVersion --repo badgerati/pode --merged --limit 200 --json 'number,title,labels,author' | ConvertFrom-Json - # group PRs into categories, filtering out some internal PRs - $categories = [ordered]@{ - Features = @() - Enhancements = @() - Bugs = @() - Documentation = @() - } + # group PRs into categories, filtering out some internal PRs + $categories = [ordered]@{ + Features = @() + Enhancements = @() + Bugs = @() + Documentation = @() + } - $dependabot = @{} + $dependabot = @{} - foreach ($pr in $prs) { - if ($pr.labels.name -icontains 'superseded') { - continue - } + foreach ($pr in $prs) { + if ($pr.labels.name -icontains 'superseded') { + continue + } - $label = ($pr.labels[0].name -split ' ')[0] - if ($label -iin @('new-release', 'internal-code')) { - continue - } + $label = ($pr.labels[0].name -split ' ')[0] + if ($label -iin @('new-release', 'internal-code')) { + continue + } - if ([string]::IsNullOrWhiteSpace($label)) { - $label = 'misc' - } + if ([string]::IsNullOrWhiteSpace($label)) { + $label = 'misc' + } - switch ($label.ToLowerInvariant()) { - 'feature' { $label = 'Features' } - 'enhancement' { $label = 'Enhancements' } - 'bug' { $label = 'Bugs' } - } + switch ($label.ToLowerInvariant()) { + 'feature' { $label = 'Features' } + 'enhancement' { $label = 'Enhancements' } + 'bug' { $label = 'Bugs' } + } - if (!$categories.Contains($label)) { - $categories[$label] = @() - } + if (!$categories.Contains($label)) { + $categories[$label] = @() + } - if ($pr.author.login -ilike '*dependabot*') { - if ($pr.title -imatch 'Bump (?\S+) from (?[0-9\.]+) to (?[0-9\.]+)') { - if (!$dependabot.ContainsKey($Matches['name'])) { - $dependabot[$Matches['name']] = @{ - Name = $Matches['name'] - Number = $pr.number - From = [version]$Matches['from'] - To = [version]$Matches['to'] - } - } - else { - $item = $dependabot[$Matches['name']] - if ([int]$pr.number -gt [int]$item.Number) { - $item.Number = $pr.number - } - if ([version]$Matches['from'] -lt $item.From) { - $item.From = [version]$Matches['from'] + if ($pr.author.login -ilike '*dependabot*') { + if ($pr.title -imatch 'Bump (?\S+) from (?[0-9\.]+) to (?[0-9\.]+)') { + if (!$dependabot.ContainsKey($Matches['name'])) { + $dependabot[$Matches['name']] = @{ + Name = $Matches['name'] + Number = $pr.number + From = [version]$Matches['from'] + To = [version]$Matches['to'] + } } - if ([version]$Matches['to'] -gt $item.To) { - $item.To = [version]$Matches['to'] + else { + $item = $dependabot[$Matches['name']] + if ([int]$pr.number -gt [int]$item.Number) { + $item.Number = $pr.number + } + if ([version]$Matches['from'] -lt $item.From) { + $item.From = [version]$Matches['from'] + } + if ([version]$Matches['to'] -gt $item.To) { + $item.To = [version]$Matches['to'] + } } + + continue } + } - continue + $titles = @($pr.title).Trim() + if ($pr.title.Contains(';')) { + $titles = ($pr.title -split ';').Trim() } - } - $titles = @($pr.title).Trim() - if ($pr.title.Contains(';')) { - $titles = ($pr.title -split ';').Trim() - } + $author = $null + if (($pr.author.login -ine 'badgerati') -and ($pr.author.login -inotlike '*dependabot*')) { + $author = $pr.author.login + } - $author = $null - if (($pr.author.login -ine 'badgerati') -and ($pr.author.login -inotlike '*dependabot*')) { - $author = $pr.author.login - } + foreach ($title in $titles) { + $str = "* #$($pr.number): $($title -replace '`', "'")" + if (![string]::IsNullOrWhiteSpace($author)) { + $str += " (thanks @$($author)!)" + } - foreach ($title in $titles) { - $str = "* #$($pr.number): $($title -replace '`', "'")" - if (![string]::IsNullOrWhiteSpace($author)) { - $str += " (thanks @$($author)!)" + if ($str -imatch '\s+(docs|documentation)\s+') { + $categories['Documentation'] += $str + } + else { + $categories[$label] += $str + } } + } - if ($str -imatch '\s+(docs|documentation)\s+') { - $categories['Documentation'] += $str - } - else { - $categories[$label] += $str + # add dependabot aggregated PRs + if ($dependabot.Count -gt 0) { + $label = 'dependencies' + if (!$categories.Contains($label)) { + $categories[$label] = @() } - } - } - # add dependabot aggregated PRs - if ($dependabot.Count -gt 0) { - $label = 'dependencies' - if (!$categories.Contains($label)) { - $categories[$label] = @() + foreach ($dep in $dependabot.Values) { + $categories[$label] += "* #$($dep.Number): Bump $($dep.Name) from $($dep.From) to $($dep.To)" + } } - foreach ($dep in $dependabot.Values) { - $categories[$label] += "* #$($dep.Number): Bump $($dep.Name) from $($dep.From) to $($dep.To)" - } - } + # output the release notes + Write-Host "# v$($ReleaseNoteVersion)`n" - # output the release notes - Write-Host "# v$($ReleaseNoteVersion)`n" + $culture = (Get-Culture).TextInfo + foreach ($category in $categories.Keys) { + if ($categories[$category].Length -eq 0) { + continue + } - $culture = (Get-Culture).TextInfo - foreach ($category in $categories.Keys) { - if ($categories[$category].Length -eq 0) { - continue + Write-Host "### $($culture.ToTitleCase($category))" + $categories[$category] | Sort-Object | ForEach-Object { Write-Host $_ } + Write-Host '' } - - Write-Host "### $($culture.ToTitleCase($category))" - $categories[$category] | Sort-Object | ForEach-Object { Write-Host $_ } - Write-Host '' } +} +else { + Write-Host 'This script is intended to be run with Invoke-Build. Please use Invoke-Build to execute the tasks defined in this script.' -ForegroundColor Yellow } \ No newline at end of file diff --git a/src/Listener/Pode.csproj b/src/Listener/Pode.csproj index 3932c1dc7..45760ac6e 100644 --- a/src/Listener/Pode.csproj +++ b/src/Listener/Pode.csproj @@ -1,6 +1,6 @@ - netstandard2.0;net6.0;net8.0 + netstandard2.0;netstandard2.1;netcoreapp3.1;net5.0;net6.0;net7.0;net8.0;net9.0; $(NoWarn);SYSLIB0001 7.3 From e60e93d2d1bf92a4db19776da285fba4866ca7ee Mon Sep 17 00:00:00 2001 From: mdaneri Date: Wed, 13 Nov 2024 10:09:44 -0800 Subject: [PATCH 02/25] fix github issue --- .github/workflows/ci-powershell.yml | 2 +- .github/workflows/ci-pwsh7_2.yml | 2 +- .github/workflows/ci-pwsh_lts.yml | 2 +- .github/workflows/ci-pwsh_preview.yml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci-powershell.yml b/.github/workflows/ci-powershell.yml index c3cf4b313..d02acd9aa 100644 --- a/.github/workflows/ci-powershell.yml +++ b/.github/workflows/ci-powershell.yml @@ -40,7 +40,7 @@ jobs: - name: Setup .NET uses: actions/setup-dotnet@v4 with: - dotnet-version: 8.0.x + dotnet-version: 'latest' # Automatically picks the latest available .NET SDK - name: Install Invoke-Build shell: powershell diff --git a/.github/workflows/ci-pwsh7_2.yml b/.github/workflows/ci-pwsh7_2.yml index 468043c36..c5c0cb357 100644 --- a/.github/workflows/ci-pwsh7_2.yml +++ b/.github/workflows/ci-pwsh7_2.yml @@ -42,7 +42,7 @@ jobs: - name: Setup .NET uses: actions/setup-dotnet@v4 with: - dotnet-version: 8.0.x + dotnet-version: 'latest' # Automatically picks the latest available .NET SDK - name: Setup Powershell - Unix shell: pwsh diff --git a/.github/workflows/ci-pwsh_lts.yml b/.github/workflows/ci-pwsh_lts.yml index c0fa8a682..0cb4336d9 100644 --- a/.github/workflows/ci-pwsh_lts.yml +++ b/.github/workflows/ci-pwsh_lts.yml @@ -42,7 +42,7 @@ jobs: - name: Setup .NET uses: actions/setup-dotnet@v4 with: - dotnet-version: 8.0.x + dotnet-version: 'latest' # Automatically picks the latest available .NET SDK - name: Setup Powershell - Unix shell: pwsh diff --git a/.github/workflows/ci-pwsh_preview.yml b/.github/workflows/ci-pwsh_preview.yml index 81bb80c3d..977c19c57 100644 --- a/.github/workflows/ci-pwsh_preview.yml +++ b/.github/workflows/ci-pwsh_preview.yml @@ -42,7 +42,7 @@ jobs: - name: Setup .NET uses: actions/setup-dotnet@v4 with: - dotnet-version: 8.0.x + dotnet-version: 'latest' # Automatically picks the latest available .NET SDK - name: Setup Powershell - Unix shell: pwsh From 359c408224187d8bdb1a29495b19260528f7f526 Mon Sep 17 00:00:00 2001 From: mdaneri Date: Wed, 13 Nov 2024 10:12:34 -0800 Subject: [PATCH 03/25] latest is not supported rollback to 9.x --- .github/workflows/ci-powershell.yml | 2 +- .github/workflows/ci-pwsh7_2.yml | 2 +- .github/workflows/ci-pwsh_lts.yml | 2 +- .github/workflows/ci-pwsh_preview.yml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci-powershell.yml b/.github/workflows/ci-powershell.yml index d02acd9aa..1b071fe4a 100644 --- a/.github/workflows/ci-powershell.yml +++ b/.github/workflows/ci-powershell.yml @@ -40,7 +40,7 @@ jobs: - name: Setup .NET uses: actions/setup-dotnet@v4 with: - dotnet-version: 'latest' # Automatically picks the latest available .NET SDK + dotnet-version: 9.x - name: Install Invoke-Build shell: powershell diff --git a/.github/workflows/ci-pwsh7_2.yml b/.github/workflows/ci-pwsh7_2.yml index c5c0cb357..8d37e5af5 100644 --- a/.github/workflows/ci-pwsh7_2.yml +++ b/.github/workflows/ci-pwsh7_2.yml @@ -42,7 +42,7 @@ jobs: - name: Setup .NET uses: actions/setup-dotnet@v4 with: - dotnet-version: 'latest' # Automatically picks the latest available .NET SDK + dotnet-version: 9.x - name: Setup Powershell - Unix shell: pwsh diff --git a/.github/workflows/ci-pwsh_lts.yml b/.github/workflows/ci-pwsh_lts.yml index 0cb4336d9..29a74a2df 100644 --- a/.github/workflows/ci-pwsh_lts.yml +++ b/.github/workflows/ci-pwsh_lts.yml @@ -42,7 +42,7 @@ jobs: - name: Setup .NET uses: actions/setup-dotnet@v4 with: - dotnet-version: 'latest' # Automatically picks the latest available .NET SDK + dotnet-version: 9.x - name: Setup Powershell - Unix shell: pwsh diff --git a/.github/workflows/ci-pwsh_preview.yml b/.github/workflows/ci-pwsh_preview.yml index 977c19c57..6abca6cde 100644 --- a/.github/workflows/ci-pwsh_preview.yml +++ b/.github/workflows/ci-pwsh_preview.yml @@ -42,7 +42,7 @@ jobs: - name: Setup .NET uses: actions/setup-dotnet@v4 with: - dotnet-version: 'latest' # Automatically picks the latest available .NET SDK + dotnet-version: 9.x - name: Setup Powershell - Unix shell: pwsh From 02c5731308d81e2ea387a02c41336afd69fe32e1 Mon Sep 17 00:00:00 2001 From: mdaneri Date: Wed, 13 Nov 2024 10:15:42 -0800 Subject: [PATCH 04/25] Update ci-coverage.yml --- .github/workflows/ci-coverage.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci-coverage.yml b/.github/workflows/ci-coverage.yml index 0841de82c..8847cfab6 100644 --- a/.github/workflows/ci-coverage.yml +++ b/.github/workflows/ci-coverage.yml @@ -37,7 +37,7 @@ jobs: - name: Setup .NET uses: actions/setup-dotnet@v4 with: - dotnet-version: 8.0.x + dotnet-version: 9.x - name: Install Invoke-Build shell: pwsh From 7790c7d664c88a467e126a0ca31d0afb67554ca4 Mon Sep 17 00:00:00 2001 From: mdaneri Date: Wed, 13 Nov 2024 10:32:22 -0800 Subject: [PATCH 05/25] Update pode.build.ps1 --- pode.build.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pode.build.ps1 b/pode.build.ps1 index eea1b6799..187612895 100644 --- a/pode.build.ps1 +++ b/pode.build.ps1 @@ -703,7 +703,7 @@ if (($null -ne $PSCmdlet.MyInvocation) -and ($PSCmdlet.MyInvocation.BoundParamet } # Synopsis: Build the function help documentation - Task DocsHelpBuild IndexSamples, DocsDeps, Build, { + Task DocsHelpBuild IndexSamples, DocsDeps, { # import the local module Remove-Module Pode -Force -ErrorAction Ignore | Out-Null Import-Module ./src/Pode.psm1 -Force | Out-Null From 0377351a1240f38228fd158c40cb0f6ad79774c7 Mon Sep 17 00:00:00 2001 From: mdaneri Date: Wed, 13 Nov 2024 10:38:52 -0800 Subject: [PATCH 06/25] fix doc build --- .github/workflows/ci-docs.yml | 5 +++++ pode.build.ps1 | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci-docs.yml b/.github/workflows/ci-docs.yml index d88abaa84..dc2aaf2b1 100644 --- a/.github/workflows/ci-docs.yml +++ b/.github/workflows/ci-docs.yml @@ -36,6 +36,11 @@ jobs: steps: - uses: actions/checkout@v4 + - name: Setup .NET + uses: actions/setup-dotnet@v4 + with: + dotnet-version: 9.x + - name: Install Invoke-Build shell: pwsh run: | diff --git a/pode.build.ps1 b/pode.build.ps1 index 187612895..eea1b6799 100644 --- a/pode.build.ps1 +++ b/pode.build.ps1 @@ -703,7 +703,7 @@ if (($null -ne $PSCmdlet.MyInvocation) -and ($PSCmdlet.MyInvocation.BoundParamet } # Synopsis: Build the function help documentation - Task DocsHelpBuild IndexSamples, DocsDeps, { + Task DocsHelpBuild IndexSamples, DocsDeps, Build, { # import the local module Remove-Module Pode -Force -ErrorAction Ignore | Out-Null Import-Module ./src/Pode.psm1 -Force | Out-Null From 9a4615fe07869bd1ed2e03d7bab8e0fe9933a9d1 Mon Sep 17 00:00:00 2001 From: mdaneri Date: Wed, 13 Nov 2024 15:16:19 -0800 Subject: [PATCH 07/25] improvements --- pode.build.ps1 | 23 ++++++++++++++++++----- src/Listener/Pode.csproj | 30 +++++++++++++++++++++++++++++- 2 files changed, 47 insertions(+), 6 deletions(-) diff --git a/pode.build.ps1 b/pode.build.ps1 index eea1b6799..459dd6cb6 100644 --- a/pode.build.ps1 +++ b/pode.build.ps1 @@ -32,7 +32,7 @@ if (($null -ne $PSCmdlet.MyInvocation) -and ($PSCmdlet.MyInvocation.BoundParamet MkDocs = '1.6.1' PSCoveralls = '1.0.0' SevenZip = '18.5.0.20180730' - DotNet = '9.0' + DotNet = 'auto' MkDocsTheme = '9.5.44' PlatyPS = '0.14.2' } @@ -213,12 +213,21 @@ if (($null -ne $PSCmdlet.MyInvocation) -and ($PSCmdlet.MyInvocation.BoundParamet function Get-PodeBuildDotNetEOL { + param( + [switch] + $LastVersion + ) $uri = 'https://endoflife.date/api/dotnet.json' try { $eol = Invoke-RestMethod -Uri $uri -Headers @{ Accept = 'application/json' } - return @{ - eol = ($eol | Where-Object { [datetime]$_.eol -lt [datetime]::Now }).cycle -join ',' - supported = ($eol | Where-Object { [datetime]$_.eol -ge [datetime]::Now }).cycle -join ',' + if ($LastVersion) { + return (($eol | Where-Object { [datetime]$_.eol -ge [datetime]::Now }).cycle)[0] + } + else { + return @{ + eol = ($eol | Where-Object { [datetime]$_.eol -lt [datetime]::Now }).cycle -join ',' + supported = ($eol | Where-Object { [datetime]$_.eol -ge [datetime]::Now }).cycle -join ',' + } } } catch { @@ -384,6 +393,10 @@ if (($null -ne $PSCmdlet.MyInvocation) -and ($PSCmdlet.MyInvocation.BoundParamet # Synopsis: Install dependencies for compiling/building Task BuildDeps { + if ($Versions.DotNet -eq 'auto') { + $Versions.DotNet = Get-PodeBuildDotNetEOL -LastVersion + } + # install dotnet if (Test-PodeBuildIsWindows) { $dotnet = 'dotnet' @@ -502,7 +515,7 @@ if (($null -ne $PSCmdlet.MyInvocation) -and ($PSCmdlet.MyInvocation.BoundParamet foreach ($target in $targetFrameworks) { Invoke-PodeBuildDotnetBuild -target $target Write-Host - Write-Host "***********************" -ForegroundColor DarkMagenta + Write-Host '***********************' -ForegroundColor DarkMagenta } } diff --git a/src/Listener/Pode.csproj b/src/Listener/Pode.csproj index 45760ac6e..0505565c6 100644 --- a/src/Listener/Pode.csproj +++ b/src/Listener/Pode.csproj @@ -1,7 +1,35 @@ - netstandard2.0;netstandard2.1;netcoreapp3.1;net5.0;net6.0;net7.0;net8.0;net9.0; + netstandard2.0;netstandard2.1 $(NoWarn);SYSLIB0001 7.3 + + + $(TargetFrameworks);netcoreapp3.1 + + + + $(TargetFrameworks);net5.0 + + + + $(TargetFrameworks);net6.0 + + + + $(TargetFrameworks);net7.0 + + + + $(TargetFrameworks);net8.0 + + + + $(TargetFrameworks);net9.0 + + + + $(TargetFrameworks);net10.0 + From d0d8687a1fc450fc18bfa34e5dc8ad48512e42b5 Mon Sep 17 00:00:00 2001 From: mdaneri Date: Thu, 14 Nov 2024 08:08:37 -0800 Subject: [PATCH 08/25] Update pode.build.ps1 --- pode.build.ps1 | 259 ++++++++++++++++++++++++++++--------------------- 1 file changed, 150 insertions(+), 109 deletions(-) diff --git a/pode.build.ps1 b/pode.build.ps1 index 459dd6cb6..b1c9915a1 100644 --- a/pode.build.ps1 +++ b/pode.build.ps1 @@ -19,7 +19,15 @@ param( $ReleaseNoteVersion, [string] - $UICulture = 'en-US' + $UICulture = 'en-US', + + [string[]] + [ValidateSet('netstandard2.0', 'netstandard2.1', 'netcoreapp3.0', 'netcoreapp3.1', 'net5.0', 'net6.0', 'net7.0', 'net8.0', 'net9.0', 'net10.0')] + $TargetFrameworks, + + [string] + [ValidateSet('netstandard2.0', 'netstandard2.1', 'netcoreapp3.0', 'netcoreapp3.1', 'net5.0', 'net6.0', 'net7.0', 'net8.0', 'net9.0', 'net10.0')] + $SdkVersion ) @@ -32,15 +40,12 @@ if (($null -ne $PSCmdlet.MyInvocation) -and ($PSCmdlet.MyInvocation.BoundParamet MkDocs = '1.6.1' PSCoveralls = '1.0.0' SevenZip = '18.5.0.20180730' - DotNet = 'auto' + DotNet = @($(if ($null -eq $TargetFrameworks) { 'auto' } else { $TargetFrameworks })) MkDocsTheme = '9.5.44' PlatyPS = '0.14.2' } - $NetVersions = 'netstandard2.0', 'netstandard2.1', 'netcoreapp3.1', 'net5.0', 'net6.0', 'net7.0', 'net8.0', 'net9.0' - #Unsupported .NET Framework version 'net4.0', 'net4.5', 'net4.5.1', 'net4.5.2', 'net4.6', 'net4.6.1', 'net4.6.2', 'net4.7', 'net4.7.1', 'net4.7.2', 'net4.8' - # Helper Functions function Test-PodeBuildIsWindows { $v = $PSVersionTable @@ -107,86 +112,92 @@ if (($null -ne $PSCmdlet.MyInvocation) -and ($PSCmdlet.MyInvocation.BoundParamet Install-Module -Name "$($name)" -Scope CurrentUser -RequiredVersion "$($Versions[$name])" -Force -SkipPublisherCheck } + function Get-TargetFramework { + param( + [string] + $TargetFrameworks + ) + + switch ($TargetFrameworks) { + 'netstandard2.0' { return 2 } + 'netstandard2.1' { return 3 } + 'netcoreapp3.0' { return 3 } + 'net5.0' { return 5 } + 'net6.0' { return 6 } + 'net7.0' { return 7 } + 'net8.0' { return 8 } + 'net9.0' { return 9 } + default { + Write-Warning "$TargetFrameworks is not a valid Framework. Rollback to netstandard2.0" + return 2 + } + } + } + + + function Get-TargetFrameworkName { + param( + $Version + ) + + switch ( $Version) { + '2' { return 'netstandard2.0' } + '3' { return 'netstandard2.1' } + '5' { return 'net5.0' } + '6' { return 'net6.0' } + '7' { return 'net7.0' } + '8' { return 'net8.0' } + '9' { return 'net9.0' } + default { + Write-Warning "$Version is not a valid Framework. Rollback to netstandard2.0" + return 'netstandard2.0' + } + } + } + function Invoke-PodeBuildDotnetBuild { param ( [string]$target ) - # Verify if the target is a known .NET version - if ($target -notin $NetVersions) { - Write-Host "Unknown target framework '$target'. Please specify a valid .NET framework." - return - } - # Retrieve the installed SDK versions $sdkVersions = dotnet --list-sdks | ForEach-Object { $_.Split('[')[0].Trim() } - $majorVersions = $sdkVersions | ForEach-Object { ([version]$_).Major } | Sort-Object -Descending | Select-Object -Unique - + if ([string]::IsNullOrEmpty($AvailableSdkVersion)) { + $majorVersions = $sdkVersions | ForEach-Object { ([version]$_).Major } | Sort-Object -Descending | Select-Object -Unique + } + else { + $majorVersions = $sdkVersions.Where( { ([version]$_).Major -ge (Get-TargetFramework -TargetFrameworks $AvailableSdkVersion) } ) | Sort-Object -Descending | Select-Object -Unique + } # Map target frameworks to minimum SDK versions - $targetSdkMap = @{ - 'netstandard2.0' = 2 - 'netstandard2.1' = 3 - 'netcoreapp3.1' = 3 - 'net5.0' = 5 - 'net6.0' = 6 - 'net7.0' = 7 - 'net8.0' = 8 - 'net9.0' = 9 + + if ($null -eq $majorVersions) { + Write-Error "The requested '$AvailableSdkVersion' framework is not available." + return } + $requiredSdkVersion = Get-TargetFramework -TargetFrameworks $target # Determine if the target framework is compatible - $isCompatible = $False - - if ($targetSdkMap.ContainsKey($target)) { - $requiredSdkVersion = $targetSdkMap[$target] - - foreach ($sdkVersion in $sdkVersions) { - $sdkMajor = ([version]$sdkVersion).Major - if ($sdkMajor -ge $requiredSdkVersion) { - $isCompatible = $True - break - } - } - } - elseif ($target -like 'net4*') { - # .NET Framework targets require MSBuild, typically available with Visual Studio - $msbuildPath = Get-Command msbuild -ErrorAction SilentlyContinue - if ($msbuildPath) { - $isCompatible = $True - } - else { - Write-Host 'MSBuild is not available. Cannot build .NET Framework targets.' - return - } - } + $isCompatible = $majorVersions -ge $requiredSdkVersion if ($isCompatible) { - Write-Host "SDK for target framework '$target' is compatible with the installed SDKs." + Write-Output "SDK for target framework '$target' is compatible with the '$AvailableSdkVersion' framework." } else { - Write-Host "SDK for target framework '$target' is not compatible with the installed SDKs. Skipping build." + Write-Warning "SDK for target framework '$target' is not compatible with the '$AvailableSdkVersion' framework. Skipping build." return } # Optionally set assembly version if ($Version) { - Write-Host "Assembly Version: $Version" + Write-Output "Assembly Version: $Version" $AssemblyVersion = "-p:Version=$Version" } else { $AssemblyVersion = '' } - # Execute dotnet publish or MSBuild depending on the target - if ($target -like 'net4*') { - # Use MSBuild for .NET Framework targets - $projectFile = 'YourProject.csproj' # Replace with your actual project file - & msbuild $projectFile /p:Configuration=Release /p:TargetFramework=$target $AssemblyVersion /p:OutputPath="../Libs/$target" - } - else { - # Use dotnet publish for .NET Core and .NET 5+ - dotnet publish --configuration Release --self-contained --framework $target $AssemblyVersion --output ../Libs/$target - } + # Use dotnet publish for .NET Core and .NET 5+ + dotnet publish --configuration Release --self-contained --framework $target $AssemblyVersion --output ../Libs/$target if (!$?) { throw "Build failed for target framework '$target'." @@ -215,12 +226,12 @@ if (($null -ne $PSCmdlet.MyInvocation) -and ($PSCmdlet.MyInvocation.BoundParamet function Get-PodeBuildDotNetEOL { param( [switch] - $LastVersion + $LatestVersion ) $uri = 'https://endoflife.date/api/dotnet.json' try { $eol = Invoke-RestMethod -Uri $uri -Headers @{ Accept = 'application/json' } - if ($LastVersion) { + if ($LatestVersion) { return (($eol | Where-Object { [datetime]$_.eol -ge [datetime]::Now }).cycle)[0] } else { @@ -357,7 +368,7 @@ if (($null -ne $PSCmdlet.MyInvocation) -and ($PSCmdlet.MyInvocation.BoundParamet #> # Synopsis: Stamps the version onto the Module - Task StampVersion { + 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 (Get-Content ./pkg/Pode.Internal.psd1) | ForEach-Object { $_ -replace '\$version\$', $Version } | Set-Content ./pkg/Pode.Internal.psd1 @@ -366,7 +377,7 @@ if (($null -ne $PSCmdlet.MyInvocation) -and ($PSCmdlet.MyInvocation.BoundParamet } # Synopsis: Generating a Checksum of the Zip - Task PrintChecksum { + Add-BuildTask PrintChecksum { $Script:Checksum = (Get-FileHash "./deliverable/$Version-Binaries.zip" -Algorithm SHA256).Hash Write-Host "Checksum: $($Checksum)" } @@ -377,7 +388,7 @@ if (($null -ne $PSCmdlet.MyInvocation) -and ($PSCmdlet.MyInvocation.BoundParamet #> # Synopsis: Installs Chocolatey - Task ChocoDeps -If (Test-PodeBuildIsWindows) { + Add-BuildTask ChocoDeps -If (Test-PodeBuildIsWindows) { if (!(Test-PodeBuildCommand 'choco')) { Set-ExecutionPolicy Bypass -Scope Process -Force Invoke-Expression ([System.Net.WebClient]::new().DownloadString('https://chocolatey.org/install.ps1')) @@ -385,33 +396,60 @@ if (($null -ne $PSCmdlet.MyInvocation) -and ($PSCmdlet.MyInvocation.BoundParamet } # Synopsis: Install dependencies for packaging - Task PackDeps -If (Test-PodeBuildIsWindows) ChocoDeps, { + Add-BuildTask PackDeps -If (Test-PodeBuildIsWindows) ChocoDeps, { if (!(Test-PodeBuildCommand '7z')) { Invoke-PodeBuildInstall '7zip' $Versions.SevenZip } } # Synopsis: Install dependencies for compiling/building - Task BuildDeps { - if ($Versions.DotNet -eq 'auto') { - $Versions.DotNet = Get-PodeBuildDotNetEOL -LastVersion + Add-BuildTask BuildDeps { + if ([string]::IsNullOrEmpty($SdkVersion)) { + $_sdkVersion = Get-PodeBuildDotNetEOL -LatestVersion + } + else { + $_sdkVersion = $SdkVersion } # install dotnet if (Test-PodeBuildIsWindows) { $dotnet = 'dotnet' } + elseif (Test-PodeBuildCommand 'brew') { + $dotnet = 'dotnet-sdk' + } else { - $dotnet = "dotnet-sdk-$($Versions.DotNet)" + $dotnet = "dotnet-sdk-$_sdkVersion" } if (!(Test-PodeBuildCommand 'dotnet')) { - Invoke-PodeBuildInstall $dotnet $Versions.DotNet + Invoke-PodeBuildInstall $dotnet $_sdkVersion + } + elseif (![string]::IsNullOrEmpty($SdkVersion)) { + $sdkVersions = dotnet --list-sdks | ForEach-Object { $_.Split('[')[0].Trim() } + $majorVersions = $sdkVersions | ForEach-Object { ([version]$_).Major } | Sort-Object -Descending | Select-Object -Unique + if ($majorVersions -lt (Get-TargetFramework -TargetFrameworks $SdkVersion)) { + Invoke-PodeBuildInstall $dotnet $SdkVersion + $sdkVersions = dotnet --list-sdks | ForEach-Object { $_.Split('[')[0].Trim() } + $majorVersions = $sdkVersions | ForEach-Object { ([version]$_).Major } | Sort-Object -Descending | Select-Object -Unique + if ($majorVersions -lt (Get-TargetFramework -TargetFrameworks $SdkVersion)) { + Write-Error "The requested framework '$SdkVersion' is not available." + return + } + + } + else { + $script:AvailableSdkVersion = Get-TargetFrameworkName -Version $majorVersions + Write-Warning "The requested SDK version '$SdkVersion' is superseded by the installed '$($script:AvailableSdkVersion)' framework." + return + } } + $script:AvailableSdkVersion = Get-TargetFrameworkName -Version $_sdkVersion + } # Synopsis: Install dependencies for running tests - Task TestDeps { + Add-BuildTask TestDeps { # install pester Install-PodeBuildModule Pester @@ -422,7 +460,7 @@ if (($null -ne $PSCmdlet.MyInvocation) -and ($PSCmdlet.MyInvocation.BoundParamet } # Synopsis: Install dependencies for documentation - Task DocsDeps ChocoDeps, { + Add-BuildTask DocsDeps ChocoDeps, { # install mkdocs if (!(Test-PodeBuildCommand 'mkdocs')) { Invoke-PodeBuildInstall 'mkdocs' $Versions.MkDocs @@ -437,7 +475,7 @@ if (($null -ne $PSCmdlet.MyInvocation) -and ($PSCmdlet.MyInvocation.BoundParamet Install-PodeBuildModule PlatyPS } - Task IndexSamples { + Add-BuildTask IndexSamples { $examplesPath = './examples' if (!(Test-Path -PathType Container -Path $examplesPath)) { return @@ -480,34 +518,37 @@ if (($null -ne $PSCmdlet.MyInvocation) -and ($PSCmdlet.MyInvocation.BoundParamet #> # Synopsis: Build the .NET Listener - Task Build BuildDeps, { + Add-BuildTask Build BuildDeps, { if (Test-Path ./src/Libs) { Remove-Item -Path ./src/Libs -Recurse -Force | Out-Null } + if ($Versions.DotNet -eq 'auto') { + # Retrieve supported .NET versions + $eol = Get-PodeBuildDotNetEOL - # Retrieve supported .NET versions - $eol = Get-PodeBuildDotNetEOL - - $targetFrameworks = @() + $targetFrameworks = @() - if (![string]::IsNullOrEmpty($eol.supported)) { + if (![string]::IsNullOrEmpty($eol.supported)) { - # Parse supported versions into an array - $supportedVersions = $eol['supported'] -split ',' + # Parse supported versions into an array + $supportedVersions = $eol['supported'] -split ',' - # Construct target framework monikers - $targetFrameworks += ($supportedVersions | ForEach-Object { "net$_.0" }) + # Construct target framework monikers + $targetFrameworks += ($supportedVersions | ForEach-Object { "net$_.0" }) + } + } + else { + $targetFrameworks = $Versions.DotNet } - # Optionally include netstandard2.0 $targetFrameworks += 'netstandard2.0' # Retrieve the SDK version being used - $sdkVersion = dotnet --version + # $dotnetVersion = dotnet --version # Display the SDK version - Write-Output "Building target framework '$($targetFrameworks -join "','")' using .NET SDK version '$sdkVersion'" + Write-Output "Building targets '$($targetFrameworks -join "','")' using .NET '$AvailableSdkVersion' framework." # Build for supported target frameworks try { @@ -531,12 +572,12 @@ if (($null -ne $PSCmdlet.MyInvocation) -and ($PSCmdlet.MyInvocation.BoundParamet #> # Synopsis: Creates a Zip of the Module - Task 7Zip -If (Test-PodeBuildIsWindows) PackDeps, StampVersion, { + Add-BuildTask 7Zip -If (Test-PodeBuildIsWindows) PackDeps, StampVersion, { exec { & 7z -tzip a $Version-Binaries.zip ./pkg/* } }, PrintChecksum #Synopsis: Create the Deliverable folder - Task DeliverableFolder { + Add-BuildTask DeliverableFolder { $path = './deliverable' if (Test-Path $path) { Remove-Item -Path $path -Recurse -Force | Out-Null @@ -547,7 +588,7 @@ if (($null -ne $PSCmdlet.MyInvocation) -and ($PSCmdlet.MyInvocation.BoundParamet } # Synopsis: Creates a Zip of the Module - Task Compress PackageFolder, StampVersion, DeliverableFolder, { + Add-BuildTask Compress PackageFolder, StampVersion, DeliverableFolder, { $path = './deliverable' if (Test-Path $path) { Remove-Item -Path $path -Recurse -Force | Out-Null @@ -558,13 +599,13 @@ if (($null -ne $PSCmdlet.MyInvocation) -and ($PSCmdlet.MyInvocation.BoundParamet }, PrintChecksum # Synopsis: Creates a Chocolately package of the Module - Task ChocoPack -If (Test-PodeBuildIsWindows) PackDeps, PackageFolder, StampVersion, DeliverableFolder, { + Add-BuildTask ChocoPack -If (Test-PodeBuildIsWindows) PackDeps, PackageFolder, StampVersion, DeliverableFolder, { exec { choco pack ./packers/choco/pode.nuspec } Move-Item -Path "pode.$Version.nupkg" -Destination './deliverable' } # Synopsis: Create docker tags - Task DockerPack PackageFolder, StampVersion, { + Add-BuildTask DockerPack PackageFolder, StampVersion, { # check if github and windows, and output warning if ((Test-PodeBuildIsGitHub) -and (Test-PodeBuildIsWindows)) { Write-Warning 'Docker images are not built on GitHub Windows runners, and Docker is in Windows container only mode. Exiting task.' @@ -596,10 +637,10 @@ if (($null -ne $PSCmdlet.MyInvocation) -and ($PSCmdlet.MyInvocation.BoundParamet } # Synopsis: Package up the Module - Task Pack Compress, ChocoPack, DockerPack + Add-BuildTask Pack Compress, ChocoPack, DockerPack # Synopsis: Package up the Module into a /pkg folder - Task PackageFolder Build, { + Add-BuildTask PackageFolder Build, { $path = './pkg' if (Test-Path $path) { Remove-Item -Path $path -Recurse -Force | Out-Null @@ -635,7 +676,7 @@ if (($null -ne $PSCmdlet.MyInvocation) -and ($PSCmdlet.MyInvocation.BoundParamet #> # Synopsis: Run the tests - Task TestNoBuild TestDeps, { + Add-BuildTask TestNoBuild TestDeps, { $p = (Get-Command Invoke-Pester) if ($null -eq $p -or $p.Version -ine $Versions.Pester) { Remove-Module Pester -Force -ErrorAction Ignore @@ -681,17 +722,17 @@ if (($null -ne $PSCmdlet.MyInvocation) -and ($PSCmdlet.MyInvocation.BoundParamet }, PushCodeCoverage, CheckFailedTests # Synopsis: Run tests after a build - Task Test Build, TestNoBuild + Add-BuildTask Test Build, TestNoBuild # Synopsis: Check if any of the tests failed - Task CheckFailedTests { + Add-BuildTask CheckFailedTests { if ($TestStatus.FailedCount -gt 0) { throw "$($TestStatus.FailedCount) tests failed" } } # Synopsis: If AppyVeyor or GitHub, push code coverage stats - Task PushCodeCoverage -If (Test-PodeBuildCanCodeCoverage) { + Add-BuildTask PushCodeCoverage -If (Test-PodeBuildCanCodeCoverage) { try { $service = Get-PodeBuildService $branch = Get-PodeBuildBranch @@ -711,12 +752,12 @@ if (($null -ne $PSCmdlet.MyInvocation) -and ($PSCmdlet.MyInvocation.BoundParamet #> # Synopsis: Run the documentation locally - Task Docs DocsDeps, DocsHelpBuild, { + Add-BuildTask Docs DocsDeps, DocsHelpBuild, { mkdocs serve --open } # Synopsis: Build the function help documentation - Task DocsHelpBuild IndexSamples, DocsDeps, Build, { + Add-BuildTask DocsHelpBuild IndexSamples, DocsDeps, Build, { # import the local module Remove-Module Pode -Force -ErrorAction Ignore | Out-Null Import-Module ./src/Pode.psm1 -Force | Out-Null @@ -760,7 +801,7 @@ if (($null -ne $PSCmdlet.MyInvocation) -and ($PSCmdlet.MyInvocation.BoundParamet } # Synopsis: Build the documentation - Task DocsBuild DocsDeps, DocsHelpBuild, { + Add-BuildTask DocsBuild DocsDeps, DocsHelpBuild, { mkdocs build --quiet } @@ -770,10 +811,10 @@ if (($null -ne $PSCmdlet.MyInvocation) -and ($PSCmdlet.MyInvocation.BoundParamet #> # Synopsis: Clean the build enviroment - Task Clean CleanPkg, CleanDeliverable, CleanLibs, CleanListener, CleanDocs + Add-BuildTask Clean CleanPkg, CleanDeliverable, CleanLibs, CleanListener, CleanDocs # Synopsis: Clean the Deliverable folder - Task CleanDeliverable { + Add-BuildTask CleanDeliverable { $path = './deliverable' if (Test-Path -Path $path -PathType Container) { Write-Host 'Removing ./deliverable folder' @@ -783,7 +824,7 @@ if (($null -ne $PSCmdlet.MyInvocation) -and ($PSCmdlet.MyInvocation.BoundParamet } # Synopsis: Clean the pkg directory - Task CleanPkg { + Add-BuildTask CleanPkg { $path = './pkg' if ((Test-Path -Path $path -PathType Container )) { Write-Host 'Removing ./pkg folder' @@ -804,7 +845,7 @@ if (($null -ne $PSCmdlet.MyInvocation) -and ($PSCmdlet.MyInvocation.BoundParamet } # Synopsis: Clean the libs folder - Task CleanLibs { + Add-BuildTask CleanLibs { $path = './src/Libs' if (Test-Path -Path $path -PathType Container) { Write-Host "Removing $path contents" @@ -815,7 +856,7 @@ if (($null -ne $PSCmdlet.MyInvocation) -and ($PSCmdlet.MyInvocation.BoundParamet } # Synopsis: Clean the Listener folder - Task CleanListener { + Add-BuildTask CleanListener { $path = './src/Listener/bin' if (Test-Path -Path $path -PathType Container) { Write-Host "Removing $path contents" @@ -825,7 +866,7 @@ if (($null -ne $PSCmdlet.MyInvocation) -and ($PSCmdlet.MyInvocation.BoundParamet Write-Host "Cleanup $path done" } - Task CleanDocs { + Add-BuildTask CleanDocs { $path = './docs/Getting-Started/Samples.md' if (Test-Path -Path $path -PathType Leaf) { Write-Host "Removing $path" @@ -837,7 +878,7 @@ if (($null -ne $PSCmdlet.MyInvocation) -and ($PSCmdlet.MyInvocation.BoundParamet #> # Synopsis: Install Pode Module locally - Task Install-Module -If ($Version) Pack, { + Add-BuildTask Install-Module -If ($Version) Pack, { $PSPaths = Split-PodeBuildPwshPath $dest = Join-Path -Path $PSPaths[0] -ChildPath 'Pode' -AdditionalChildPath "$Version" @@ -865,7 +906,7 @@ if (($null -ne $PSCmdlet.MyInvocation) -and ($PSCmdlet.MyInvocation.BoundParamet } # Synopsis: Remove the Pode Module from the local registry - Task Remove-Module { + Add-BuildTask Remove-Module { if (!$Version) { throw 'Parameter -Version is required' } @@ -887,7 +928,7 @@ if (($null -ne $PSCmdlet.MyInvocation) -and ($PSCmdlet.MyInvocation.BoundParamet #> # Synopsis: Setup the PowerShell environment - Task SetupPowerShell { + Add-BuildTask SetupPowerShell { # code for this step is altered versions of the code found here: # - https://github.com/bjompen/UpdatePWSHAction/blob/main/UpgradePwsh.ps1 # - https://raw.githubusercontent.com/PowerShell/PowerShell/master/tools/install-powershell.ps1 From 09c192eddbb3fb4a0688f9d2337156e5b5e088b8 Mon Sep 17 00:00:00 2001 From: mdaneri Date: Thu, 14 Nov 2024 18:31:45 -0800 Subject: [PATCH 09/25] Update pode.build.ps1 --- pode.build.ps1 | 776 ++++++++++++++++++++++++++++++------------------- 1 file changed, 474 insertions(+), 302 deletions(-) diff --git a/pode.build.ps1 b/pode.build.ps1 index b1c9915a1..26ba5a630 100644 --- a/pode.build.ps1 +++ b/pode.build.ps1 @@ -1,3 +1,87 @@ +<# +.SYNOPSIS + Build script for the Pode project, defining tasks for compilation, testing, packaging, and deployment. + +.DESCRIPTION + This script uses Invoke-Build to automate the Pode project build process across different environments (Windows, macOS, Linux). + It includes tasks for setting up dependencies, compiling .NET targets, running tests, generating documentation, and packaging. + +.PARAMETER Version + Specifies the project version for stamping, packaging, and documentation. Defaults to '0.0.0'. + +.PARAMETER PesterVerbosity + Sets the verbosity level for Pester tests. Options: None, Normal, Detailed, Diagnostic. + +.PARAMETER PowerShellVersion + Defines the target PowerShell version for installation, e.g., 'lts' or a specific version. + +.PARAMETER ReleaseNoteVersion + Specifies the release version for generating release notes. + +.PARAMETER UICulture + Sets the culture for running tests, defaulting to 'en-US'. + +.PARAMETER TargetFrameworks + Specifies the target .NET frameworks for building the project, e.g., netstandard2.0, net8.0. + +.PARAMETER SdkVersion + Sets the SDK version used for building .NET projects, defaulting to net8.0. + +.NOTES + This build script requires Invoke-Build. Below is a list of all available tasks: + + - Default: Lists all available tasks. + - StampVersion: Stamps the specified version onto the module. + - PrintChecksum: Generates and displays a checksum of the ZIP archive. + - ChocoDeps: Installs Chocolatey (for Windows). + - PackDeps: Installs dependencies required for packaging. + - BuildDeps: Installs dependencies required for building/compiling. + - TestDeps: Installs dependencies required for testing. + - DocsDeps: Installs dependencies required for documentation generation. + - IndexSamples: Indexes sample files for documentation. + - Build: Builds the .NET Listener for specified frameworks. + - 7Zip: Creates a ZIP archive of the module (Windows only). + - DeliverableFolder: Creates a folder for deliverables. + - Compress: Compresses the module into a ZIP format for distribution. + - ChocoPack: Creates a Chocolatey package of the module (Windows only). + - DockerPack: Builds Docker images for the module. + - Pack: Packages the module, including ZIP, Chocolatey, and Docker. + - PackageFolder: Creates the `pkg` folder for module packaging. + - TestNoBuild: Runs tests without building, including Pester tests. + - Test: Runs tests after building the project. + - CheckFailedTests: Checks if any tests failed and throws an error if so. + - PushCodeCoverage: Pushes code coverage results to a coverage service. + - Docs: Serves the documentation locally for review. + - DocsHelpBuild: Builds function help documentation. + - DocsBuild: Builds the documentation for distribution. + - Clean: Cleans the build environment, removing all generated files. + - CleanDeliverable: Removes the `deliverable` folder. + - CleanPkg: Removes the `pkg` folder. + - CleanLibs: Removes the `Libs` folder under `src`. + - CleanListener: Removes the Listener folder. + - CleanDocs: Cleans up generated documentation files. + - Install-Module: Installs the Pode module locally. + - Remove-Module: Removes the Pode module from the local registry. + - SetupPowerShell: Sets up the PowerShell environment for the build. + - ReleaseNotes: Generates release notes based on merged pull requests. + +.EXAMPLE + Invoke-Build -Task Default + # Displays a list of all available tasks. + + Invoke-Build -Task Build -Version '1.2.3' + # Compiles the project for the specified version. + + Invoke-Build -Task Test + # Runs tests on the project, including Pester tests. + + Invoke-Build -Task Docs + # Builds and serves the documentation locally. + +.LINK + For more information, visit https://github.com/Badgerati/Pode +#> + [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSReviewUnusedParameter', '')] [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseSingularNouns', '')] [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSAvoidUsingWriteHost', '')] @@ -23,343 +107,462 @@ param( [string[]] [ValidateSet('netstandard2.0', 'netstandard2.1', 'netcoreapp3.0', 'netcoreapp3.1', 'net5.0', 'net6.0', 'net7.0', 'net8.0', 'net9.0', 'net10.0')] - $TargetFrameworks, + $TargetFrameworks = @('netstandard2.0', 'net8.0' ), [string] [ValidateSet('netstandard2.0', 'netstandard2.1', 'netcoreapp3.0', 'netcoreapp3.1', 'net5.0', 'net6.0', 'net7.0', 'net8.0', 'net9.0', 'net10.0')] - $SdkVersion + $SdkVersion = 'net8.0' ) +# Dependency Versions +$Versions = @{ + Pester = '5.6.1' + MkDocs = '1.6.1' + PSCoveralls = '1.0.0' + SevenZip = '18.5.0.20180730' + DotNet = $SdkVersion + MkDocsTheme = '9.5.44' + PlatyPS = '0.14.2' +} -# Check if the script is running under Invoke-Build -if (($null -ne $PSCmdlet.MyInvocation) -and ($PSCmdlet.MyInvocation.BoundParameters.ContainsKey('BuildRoot') -or $null -ne $BuildRoot)) { - # Dependency Versions - $Versions = @{ - Pester = '5.6.1' - MkDocs = '1.6.1' - PSCoveralls = '1.0.0' - SevenZip = '18.5.0.20180730' - DotNet = @($(if ($null -eq $TargetFrameworks) { 'auto' } else { $TargetFrameworks })) - MkDocsTheme = '9.5.44' - PlatyPS = '0.14.2' - } +# Helper Functions +function Test-PodeBuildIsWindows { + $v = $PSVersionTable + return ($v.Platform -ilike '*win*' -or ($null -eq $v.Platform -and $v.PSEdition -ieq 'desktop')) +} +function Test-PodeBuildIsGitHub { + return (![string]::IsNullOrWhiteSpace($env:GITHUB_REF)) +} - # Helper Functions - function Test-PodeBuildIsWindows { - $v = $PSVersionTable - return ($v.Platform -ilike '*win*' -or ($null -eq $v.Platform -and $v.PSEdition -ieq 'desktop')) - } +function Test-PodeBuildCanCodeCoverage { + return (@('1', 'true') -icontains $env:PODE_RUN_CODE_COVERAGE) +} - function Test-PodeBuildIsGitHub { - return (![string]::IsNullOrWhiteSpace($env:GITHUB_REF)) - } +function Get-PodeBuildService { + return 'github-actions' +} - function Test-PodeBuildCanCodeCoverage { - return (@('1', 'true') -icontains $env:PODE_RUN_CODE_COVERAGE) - } +function Test-PodeBuildCommand($cmd) { + $path = $null - function Get-PodeBuildService { - return 'github-actions' + if (Test-PodeBuildIsWindows) { + $path = (Get-Command $cmd -ErrorAction Ignore) + } + else { + $path = (which $cmd) } - function Test-PodeBuildCommand($cmd) { - $path = $null + return (![string]::IsNullOrWhiteSpace($path)) +} - if (Test-PodeBuildIsWindows) { - $path = (Get-Command $cmd -ErrorAction Ignore) +function Get-PodeBuildBranch { + return ($env:GITHUB_REF -ireplace 'refs\/heads\/', '') +} + +function Invoke-PodeBuildInstall($name, $version) { + [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 + + if (Test-PodeBuildIsWindows) { + if (Test-PodeBuildCommand 'choco') { + choco install $name --version $version -y --no-progress } - else { - $path = (which $cmd) + } + else { + if (Test-PodeBuildCommand 'brew') { + brew install $name + } + elseif (Test-PodeBuildCommand 'apt-get') { + sudo apt-get install $name -y + } + elseif (Test-PodeBuildCommand 'yum') { + sudo yum install $name -y } - - return (![string]::IsNullOrWhiteSpace($path)) } +} - function Get-PodeBuildBranch { - return ($env:GITHUB_REF -ireplace 'refs\/heads\/', '') +function Install-PodeBuildModule($name) { + if ($null -ne ((Get-Module -ListAvailable $name) | Where-Object { $_.Version -ieq $Versions[$name] })) { + return } - function Invoke-PodeBuildInstall($name, $version) { - [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 + Write-Host "Installing $($name) v$($Versions[$name])" + [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 + Install-Module -Name "$($name)" -Scope CurrentUser -RequiredVersion "$($Versions[$name])" -Force -SkipPublisherCheck +} - if (Test-PodeBuildIsWindows) { - if (Test-PodeBuildCommand 'choco') { - choco install $name --version $version -y --no-progress - } - } - else { - if (Test-PodeBuildCommand 'brew') { - brew install $name - } - elseif (Test-PodeBuildCommand 'apt-get') { - sudo apt-get install $name -y - } - elseif (Test-PodeBuildCommand 'yum') { - sudo yum install $name -y - } +function Get-TargetFramework { + param( + [string] + $TargetFrameworks + ) + + switch ($TargetFrameworks) { + 'netstandard2.0' { return 2 } + 'netstandard2.1' { return 3 } + 'netcoreapp3.0' { return 3 } + 'net5.0' { return 5 } + 'net6.0' { return 6 } + 'net7.0' { return 7 } + 'net8.0' { return 8 } + 'net9.0' { return 9 } + default { + Write-Warning "$TargetFrameworks is not a valid Framework. Rollback to netstandard2.0" + return 2 } } +} - function Install-PodeBuildModule($name) { - if ($null -ne ((Get-Module -ListAvailable $name) | Where-Object { $_.Version -ieq $Versions[$name] })) { - return - } - Write-Host "Installing $($name) v$($Versions[$name])" - [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 - Install-Module -Name "$($name)" -Scope CurrentUser -RequiredVersion "$($Versions[$name])" -Force -SkipPublisherCheck - } +function Get-TargetFrameworkName { + param( + $Version + ) - function Get-TargetFramework { - param( - [string] - $TargetFrameworks - ) - - switch ($TargetFrameworks) { - 'netstandard2.0' { return 2 } - 'netstandard2.1' { return 3 } - 'netcoreapp3.0' { return 3 } - 'net5.0' { return 5 } - 'net6.0' { return 6 } - 'net7.0' { return 7 } - 'net8.0' { return 8 } - 'net9.0' { return 9 } - default { - Write-Warning "$TargetFrameworks is not a valid Framework. Rollback to netstandard2.0" - return 2 - } + switch ( $Version) { + '2' { return 'netstandard2.0' } + '3' { return 'netstandard2.1' } + '5' { return 'net5.0' } + '6' { return 'net6.0' } + '7' { return 'net7.0' } + '8' { return 'net8.0' } + '9' { return 'net9.0' } + default { + Write-Warning "$Version is not a valid Framework. Rollback to netstandard2.0" + return 'netstandard2.0' } } +} +function Invoke-PodeBuildDotnetBuild { + param ( + [string]$target + ) - function Get-TargetFrameworkName { - param( - $Version - ) - - switch ( $Version) { - '2' { return 'netstandard2.0' } - '3' { return 'netstandard2.1' } - '5' { return 'net5.0' } - '6' { return 'net6.0' } - '7' { return 'net7.0' } - '8' { return 'net8.0' } - '9' { return 'net9.0' } - default { - Write-Warning "$Version is not a valid Framework. Rollback to netstandard2.0" - return 'netstandard2.0' - } - } + # Retrieve the installed SDK versions + $sdkVersions = dotnet --list-sdks | ForEach-Object { $_.Split('[')[0].Trim() } + if ([string]::IsNullOrEmpty($AvailableSdkVersion)) { + $majorVersions = $sdkVersions | ForEach-Object { ([version]$_).Major } | Sort-Object -Descending | Select-Object -Unique } + else { + $majorVersions = $sdkVersions.Where( { ([version]$_).Major -ge (Get-TargetFramework -TargetFrameworks $AvailableSdkVersion) } ) | Sort-Object -Descending | Select-Object -Unique + } + # Map target frameworks to minimum SDK versions - function Invoke-PodeBuildDotnetBuild { - param ( - [string]$target - ) + if ($null -eq $majorVersions) { + Write-Error "The requested '$AvailableSdkVersion' framework is not available." + return + } + $requiredSdkVersion = Get-TargetFramework -TargetFrameworks $target - # Retrieve the installed SDK versions - $sdkVersions = dotnet --list-sdks | ForEach-Object { $_.Split('[')[0].Trim() } - if ([string]::IsNullOrEmpty($AvailableSdkVersion)) { - $majorVersions = $sdkVersions | ForEach-Object { ([version]$_).Major } | Sort-Object -Descending | Select-Object -Unique - } - else { - $majorVersions = $sdkVersions.Where( { ([version]$_).Major -ge (Get-TargetFramework -TargetFrameworks $AvailableSdkVersion) } ) | Sort-Object -Descending | Select-Object -Unique - } - # Map target frameworks to minimum SDK versions + # Determine if the target framework is compatible + $isCompatible = $majorVersions -ge $requiredSdkVersion - if ($null -eq $majorVersions) { - Write-Error "The requested '$AvailableSdkVersion' framework is not available." - return - } - $requiredSdkVersion = Get-TargetFramework -TargetFrameworks $target + if ($isCompatible) { + Write-Output "SDK for target framework '$target' is compatible with the '$AvailableSdkVersion' framework." + } + else { + Write-Warning "SDK for target framework '$target' is not compatible with the '$AvailableSdkVersion' framework. Skipping build." + return + } - # Determine if the target framework is compatible - $isCompatible = $majorVersions -ge $requiredSdkVersion + # Optionally set assembly version + if ($Version) { + Write-Output "Assembly Version: $Version" + $AssemblyVersion = "-p:Version=$Version" + } + else { + $AssemblyVersion = '' + } - if ($isCompatible) { - Write-Output "SDK for target framework '$target' is compatible with the '$AvailableSdkVersion' framework." - } - else { - Write-Warning "SDK for target framework '$target' is not compatible with the '$AvailableSdkVersion' framework. Skipping build." - return - } + # Use dotnet publish for .NET Core and .NET 5+ + dotnet publish --configuration Release --self-contained --framework $target $AssemblyVersion --output ../Libs/$target - # Optionally set assembly version - if ($Version) { - Write-Output "Assembly Version: $Version" - $AssemblyVersion = "-p:Version=$Version" + if (!$?) { + throw "Build failed for target framework '$target'." + } +} + +function Get-PodeBuildPwshEOL { + $uri = 'https://endoflife.date/api/powershell.json' + try { + $eol = Invoke-RestMethod -Uri $uri -Headers @{ Accept = 'application/json' } + return @{ + eol = ($eol | Where-Object { [datetime]$_.eol -lt [datetime]::Now }).cycle -join ',' + supported = ($eol | Where-Object { [datetime]$_.eol -ge [datetime]::Now }).cycle -join ',' } - else { - $AssemblyVersion = '' + } + catch { + Write-Warning "Invoke-RestMethod to $uri failed: $($_.ErrorDetails.Message)" + return @{ + eol = '' + supported = '' } + } +} - # Use dotnet publish for .NET Core and .NET 5+ - dotnet publish --configuration Release --self-contained --framework $target $AssemblyVersion --output ../Libs/$target - if (!$?) { - throw "Build failed for target framework '$target'." +function Get-PodeBuildDotNetEOL { + param( + [switch] + $LatestVersion + ) + $uri = 'https://endoflife.date/api/dotnet.json' + try { + $eol = Invoke-RestMethod -Uri $uri -Headers @{ Accept = 'application/json' } + if ($LatestVersion) { + return (($eol | Where-Object { [datetime]$_.eol -ge [datetime]::Now }).cycle)[0] } - } - - function Get-PodeBuildPwshEOL { - $uri = 'https://endoflife.date/api/powershell.json' - try { - $eol = Invoke-RestMethod -Uri $uri -Headers @{ Accept = 'application/json' } + else { return @{ eol = ($eol | Where-Object { [datetime]$_.eol -lt [datetime]::Now }).cycle -join ',' supported = ($eol | Where-Object { [datetime]$_.eol -ge [datetime]::Now }).cycle -join ',' } } - catch { - Write-Warning "Invoke-RestMethod to $uri failed: $($_.ErrorDetails.Message)" - return @{ - eol = '' - supported = '' - } + } + catch { + Write-Warning "Invoke-RestMethod to $uri failed: $($_.ErrorDetails.Message)" + return @{ + eol = '' + supported = '' } } +} - function Get-PodeBuildDotNetEOL { - param( - [switch] - $LatestVersion - ) - $uri = 'https://endoflife.date/api/dotnet.json' - try { - $eol = Invoke-RestMethod -Uri $uri -Headers @{ Accept = 'application/json' } - if ($LatestVersion) { - return (($eol | Where-Object { [datetime]$_.eol -ge [datetime]::Now }).cycle)[0] - } - else { - return @{ - eol = ($eol | Where-Object { [datetime]$_.eol -lt [datetime]::Now }).cycle -join ',' - supported = ($eol | Where-Object { [datetime]$_.eol -ge [datetime]::Now }).cycle -join ',' - } - } - } - catch { - Write-Warning "Invoke-RestMethod to $uri failed: $($_.ErrorDetails.Message)" - return @{ - eol = '' - supported = '' - } - } - } - function Test-PodeBuildOSWindows { - return ($IsWindows -or - ![string]::IsNullOrEmpty($env:ProgramFiles) -or +function Test-PodeBuildOSWindows { + return ($IsWindows -or + ![string]::IsNullOrEmpty($env:ProgramFiles) -or (($PSVersionTable.Keys -contains 'PSEdition') -and ($PSVersionTable.PSEdition -eq 'Desktop'))) +} + +function Get-PodeBuildOSPwshName { + if (Test-PodeBuildOSWindows) { + return 'win' } - function Get-PodeBuildOSPwshName { - if (Test-PodeBuildOSWindows) { - return 'win' - } + if ($IsLinux) { + return 'linux' + } - if ($IsLinux) { - return 'linux' - } + if ($IsMacOS) { + return 'osx' + } +} - if ($IsMacOS) { - return 'osx' - } +function Get-PodeBuildOSPwshArchitecture { + $arch = [string]::Empty + + # windows + if (Test-PodeBuildOSWindows) { + $arch = $env:PROCESSOR_ARCHITECTURE } - function Get-PodeBuildOSPwshArchitecture { - $arch = [string]::Empty + # unix + if ($IsLinux -or $IsMacOS) { + $arch = uname -m + } - # windows - if (Test-PodeBuildOSWindows) { - $arch = $env:PROCESSOR_ARCHITECTURE - } + Write-Host "OS Architecture: $($arch)" + + # convert to pwsh arch + switch ($arch.ToLowerInvariant()) { + 'amd64' { return 'x64' } + 'x86' { return 'x86' } + 'x86_64' { return 'x64' } + 'armv7*' { return 'arm32' } + 'aarch64*' { return 'arm64' } + 'arm64' { return 'arm64' } + 'arm64*' { return 'arm64' } + 'armv8*' { return 'arm64' } + default { throw "Unsupported architecture: $($arch)" } + } +} - # unix - if ($IsLinux -or $IsMacOS) { - $arch = uname -m - } +function Convert-PodeBuildOSPwshTagToVersion { + $result = Invoke-RestMethod -Uri "https://aka.ms/pwsh-buildinfo-$($PowerShellVersion)" + return $result.ReleaseTag -ireplace '^v' +} - Write-Host "OS Architecture: $($arch)" +function Install-PodeBuildPwshWindows($target) { + $installFolder = "$($env:ProgramFiles)\PowerShell\7" - # convert to pwsh arch - switch ($arch.ToLowerInvariant()) { - 'amd64' { return 'x64' } - 'x86' { return 'x86' } - 'x86_64' { return 'x64' } - 'armv7*' { return 'arm32' } - 'aarch64*' { return 'arm64' } - 'arm64' { return 'arm64' } - 'arm64*' { return 'arm64' } - 'armv8*' { return 'arm64' } - default { throw "Unsupported architecture: $($arch)" } - } + if (Test-Path $installFolder) { + Remove-Item $installFolder -Recurse -Force -ErrorAction Stop } - function Convert-PodeBuildOSPwshTagToVersion { - $result = Invoke-RestMethod -Uri "https://aka.ms/pwsh-buildinfo-$($PowerShellVersion)" - return $result.ReleaseTag -ireplace '^v' - } + Copy-Item -Path "$($target)\" -Destination "$($installFolder)\" -Recurse -ErrorAction Stop +} - function Install-PodeBuildPwshWindows($target) { - $installFolder = "$($env:ProgramFiles)\PowerShell\7" +function Install-PodeBuildPwshUnix($target) { + $targetFullPath = Join-Path -Path $target -ChildPath 'pwsh' + $null = chmod 755 $targetFullPath - if (Test-Path $installFolder) { - Remove-Item $installFolder -Recurse -Force -ErrorAction Stop - } + $symlink = $null + if ($IsMacOS) { + $symlink = '/usr/local/bin/pwsh' + } + else { + $symlink = '/usr/bin/pwsh' + } - Copy-Item -Path "$($target)\" -Destination "$($installFolder)\" -Recurse -ErrorAction Stop + $uid = id -u + if ($uid -ne '0') { + $sudo = 'sudo' + } + else { + $sudo = '' } - function Install-PodeBuildPwshUnix($target) { - $targetFullPath = Join-Path -Path $target -ChildPath 'pwsh' - $null = chmod 755 $targetFullPath + # Make symbolic link point to installed path + & $sudo ln -fs $targetFullPath $symlink +} - $symlink = $null - if ($IsMacOS) { - $symlink = '/usr/local/bin/pwsh' - } - else { - $symlink = '/usr/bin/pwsh' - } +<# +.SYNOPSIS + Retrieves the currently installed PowerShell version. - $uid = id -u - if ($uid -ne '0') { - $sudo = 'sudo' - } - else { - $sudo = '' - } +.DESCRIPTION + This function runs the `pwsh -v` command and parses the output to return only the version number. + This is useful for verifying the PowerShell version in the build environment. + +.OUTPUTS + [string] - The current PowerShell version. + +.EXAMPLE + $version = Get-PodeBuildCurrentPwshVersion + Write-Host "Current PowerShell version: $version" + +.NOTES + This function assumes that `pwsh` is available in the system PATH. +#> +function Get-PodeBuildCurrentPwshVersion { + # Run pwsh command, split by spaces, and return the version component + return ("$(pwsh -v)" -split ' ')[1].Trim() +} + +<# +.SYNOPSIS + Builds a Docker image and tags it for the Pode project. + +.DESCRIPTION + This function uses the Docker CLI to build an image for Pode, then tags it for GitHub Packages. + The function takes a tag and a Dockerfile path as parameters to build and tag the Docker image. + +.PARAMETER Tag + The Docker image tag, typically a version number or label (e.g., 'latest'). + +.PARAMETER File + The path to the Dockerfile to use for building the image. + +.EXAMPLE + Invoke-PodeBuildDockerBuild -Tag '1.0.0' -File './Dockerfile' + # Builds a Docker image using './Dockerfile' and tags it as 'badgerati/pode:1.0.0'. - # Make symbolic link point to installed path - & $sudo ln -fs $targetFullPath $symlink +.NOTES + Requires Docker to be installed and available in the system PATH. +#> +function Invoke-PodeBuildDockerBuild { + param ( + [string] + $Tag, + [string] + $File + ) + + # Build the Docker image with the specified tag and Dockerfile + docker build -t badgerati/pode:$tTag -f $File . + if (!$?) { + throw "docker build failed for $($Tag)" } - function Get-PodeBuildCurrentPwshVersion { - return ("$(pwsh -v)" -split ' ')[1].Trim() + # Tag the image for GitHub Packages + docker tag badgerati/pode:$Tag docker.pkg.github.com/badgerati/pode/pode:$Tag + if (!$?) { + throw "docker tag failed for $($Tag)" } +} - function Invoke-PodeBuildDockerBuild($tag, $file) { - docker build -t badgerati/pode:$tag -f $file . - if (!$?) { - throw "docker build failed for $($tag)" - } - docker tag badgerati/pode:$tag docker.pkg.github.com/badgerati/pode/pode:$tag - if (!$?) { - throw "docker tag failed for $($tag)" - } +<# +.SYNOPSIS + Splits the PSModulePath environment variable into an array of paths. + +.DESCRIPTION + This function checks the operating system and splits the PSModulePath variable based on the appropriate separator: + ';' for Windows and ':' for Unix-based systems. + +.OUTPUTS + [string[]] - An array of paths from the PSModulePath variable. + +.EXAMPLE + $paths = Split-PodeBuildPwshPath + foreach ($path in $paths) { + Write-Host $path } - function Split-PodeBuildPwshPath { - if (Test-PodeBuildOSWindows) { - return $env:PSModulePath -split ';' - } - else { - return $env:PSModulePath -split ':' - } +.NOTES + This function enables cross-platform support by handling path separators for Windows and Unix-like systems. +#> +function Split-PodeBuildPwshPath { + # Check if OS is Windows, then split PSModulePath by ';', otherwise use ':' + if (Test-PodeBuildOSWindows) { + return $env:PSModulePath -split ';' + } + else { + return $env:PSModulePath -split ':' + } +} + + + +# Check if the script is running under Invoke-Build +if (($null -ne $PSCmdlet.MyInvocation) -and ($PSCmdlet.MyInvocation.BoundParameters.ContainsKey('BuildRoot') -or $null -ne $BuildRoot)) { + + + Add-BuildTask Default { + Write-Host 'Tasks in the Build Script:' -ForegroundColor DarkMagenta + Write-Host + Write-Host 'Primary Tasks:' -ForegroundColor Green + Write-Host '- Default: Lists all available tasks.' + Write-Host '- Build: Builds the .NET Listener for specified frameworks.' + Write-Host '- Pack: Packages the module, including ZIP, Chocolatey, and Docker.' + Write-Host '- Test: Runs tests after building the project.' + Write-Host '- Clean: Cleans the build environment, removing all generated files.' + Write-Host '- Install-Module: Installs the Pode module locally.' + Write-Host '- Remove-Module: Removes the Pode module from the local registry.' + Write-Host '- DocsBuild: Builds the documentation for distribution.' + Write-Host '- TestNoBuild: Runs tests without building, including Pester tests.' + + + Write-Host + Write-Host 'Other Tasks:' -ForegroundColor Green + Write-Host '- StampVersion: Stamps the specified version onto the module.' + Write-Host '- PrintChecksum: Generates and displays a checksum of the ZIP archive.' + Write-Host '- ChocoDeps: Installs Chocolatey (for Windows).' + Write-Host '- PackDeps: Installs dependencies required for packaging.' + Write-Host '- BuildDeps: Installs dependencies required for building/compiling.' + Write-Host '- TestDeps: Installs dependencies required for testing.' + Write-Host '- DocsDeps: Installs dependencies required for documentation generation.' + Write-Host '- IndexSamples: Indexes sample files for documentation.' + Write-Host '- 7Zip: Creates a ZIP archive of the module (Windows only).' + Write-Host '- DeliverableFolder: Creates a folder for deliverables.' + Write-Host '- Compress: Compresses the module into a ZIP format for distribution.' + Write-Host '- ChocoPack: Creates a Chocolatey package of the module (Windows only).' + Write-Host '- DockerPack: Builds Docker images for the module.' + Write-Host "- PackageFolder: Creates the `pkg` folder for module packaging." + Write-Host '- CheckFailedTests: Checks if any tests failed and throws an error if so.' + Write-Host '- PushCodeCoverage: Pushes code coverage results to a coverage service.' + Write-Host '- Docs: Serves the documentation locally for review.' + Write-Host '- DocsHelpBuild: Builds function help documentation.' + Write-Host "- CleanDeliverable: Removes the `deliverable` folder." + Write-Host "- CleanPkg: Removes the `pkg` folder." + Write-Host "- CleanLibs: Removes the `Libs` folder under `src`." + Write-Host '- CleanListener: Removes the Listener folder.' + Write-Host '- CleanDocs: Cleans up generated documentation files.' + Write-Host '- SetupPowerShell: Sets up the PowerShell environment for the build.' + Write-Host '- ReleaseNotes: Generates release notes based on merged pull requests.' } @@ -404,12 +607,7 @@ if (($null -ne $PSCmdlet.MyInvocation) -and ($PSCmdlet.MyInvocation.BoundParamet # Synopsis: Install dependencies for compiling/building Add-BuildTask BuildDeps { - if ([string]::IsNullOrEmpty($SdkVersion)) { - $_sdkVersion = Get-PodeBuildDotNetEOL -LatestVersion - } - else { - $_sdkVersion = $SdkVersion - } + # install dotnet if (Test-PodeBuildIsWindows) { @@ -419,32 +617,24 @@ if (($null -ne $PSCmdlet.MyInvocation) -and ($PSCmdlet.MyInvocation.BoundParamet $dotnet = 'dotnet-sdk' } else { - $dotnet = "dotnet-sdk-$_sdkVersion" + $dotnet = "dotnet-sdk-$SdkVersion" } if (!(Test-PodeBuildCommand 'dotnet')) { - Invoke-PodeBuildInstall $dotnet $_sdkVersion - } - elseif (![string]::IsNullOrEmpty($SdkVersion)) { - $sdkVersions = dotnet --list-sdks | ForEach-Object { $_.Split('[')[0].Trim() } - $majorVersions = $sdkVersions | ForEach-Object { ([version]$_).Major } | Sort-Object -Descending | Select-Object -Unique - if ($majorVersions -lt (Get-TargetFramework -TargetFrameworks $SdkVersion)) { - Invoke-PodeBuildInstall $dotnet $SdkVersion - $sdkVersions = dotnet --list-sdks | ForEach-Object { $_.Split('[')[0].Trim() } - $majorVersions = $sdkVersions | ForEach-Object { ([version]$_).Major } | Sort-Object -Descending | Select-Object -Unique - if ($majorVersions -lt (Get-TargetFramework -TargetFrameworks $SdkVersion)) { - Write-Error "The requested framework '$SdkVersion' is not available." - return - } + Invoke-PodeBuildInstall $dotnet $SdkVersion + } - } - else { - $script:AvailableSdkVersion = Get-TargetFrameworkName -Version $majorVersions - Write-Warning "The requested SDK version '$SdkVersion' is superseded by the installed '$($script:AvailableSdkVersion)' framework." - return - } + $sdkVersions = dotnet --list-sdks | ForEach-Object { $_.Split('[')[0].Trim() } + $majorVersions = $sdkVersions | ForEach-Object { ([version]$_).Major } | Sort-Object -Descending | Select-Object -Unique + $script:AvailableSdkVersion = Get-TargetFrameworkName -Version $majorVersions + + if ($majorVersions -lt (Get-TargetFramework -TargetFrameworks $SdkVersion)) { + Write-Error "The requested framework '$SdkVersion' is not available." + return + } + elseif ($majorVersions -gt (Get-TargetFramework -TargetFrameworks $SdkVersion)) { + Write-Warning "The requested SDK version '$SdkVersion' is superseded by the installed '$($script:AvailableSdkVersion)' framework." } - $script:AvailableSdkVersion = Get-TargetFrameworkName -Version $_sdkVersion } @@ -522,26 +712,8 @@ if (($null -ne $PSCmdlet.MyInvocation) -and ($PSCmdlet.MyInvocation.BoundParamet if (Test-Path ./src/Libs) { Remove-Item -Path ./src/Libs -Recurse -Force | Out-Null } - if ($Versions.DotNet -eq 'auto') { - # Retrieve supported .NET versions - $eol = Get-PodeBuildDotNetEOL - - $targetFrameworks = @() - if (![string]::IsNullOrEmpty($eol.supported)) { - # Parse supported versions into an array - $supportedVersions = $eol['supported'] -split ',' - - # Construct target framework monikers - $targetFrameworks += ($supportedVersions | ForEach-Object { "net$_.0" }) - } - } - else { - $targetFrameworks = $Versions.DotNet - } - # Optionally include netstandard2.0 - $targetFrameworks += 'netstandard2.0' # Retrieve the SDK version being used From a5deebe58e2aa90cc7d3ea880302803d92cd8121 Mon Sep 17 00:00:00 2001 From: mdaneri Date: Thu, 14 Nov 2024 18:58:46 -0800 Subject: [PATCH 10/25] fixes --- pode.build.ps1 | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/pode.build.ps1 b/pode.build.ps1 index 26ba5a630..6d213de1c 100644 --- a/pode.build.ps1 +++ b/pode.build.ps1 @@ -111,7 +111,7 @@ param( [string] [ValidateSet('netstandard2.0', 'netstandard2.1', 'netcoreapp3.0', 'netcoreapp3.1', 'net5.0', 'net6.0', 'net7.0', 'net8.0', 'net9.0', 'net10.0')] - $SdkVersion = 'net8.0' + $SdkVersion = 'net9.0' ) # Dependency Versions @@ -607,8 +607,6 @@ if (($null -ne $PSCmdlet.MyInvocation) -and ($PSCmdlet.MyInvocation.BoundParamet # Synopsis: Install dependencies for compiling/building Add-BuildTask BuildDeps { - - # install dotnet if (Test-PodeBuildIsWindows) { $dotnet = 'dotnet' @@ -629,8 +627,15 @@ if (($null -ne $PSCmdlet.MyInvocation) -and ($PSCmdlet.MyInvocation.BoundParamet $script:AvailableSdkVersion = Get-TargetFrameworkName -Version $majorVersions if ($majorVersions -lt (Get-TargetFramework -TargetFrameworks $SdkVersion)) { - Write-Error "The requested framework '$SdkVersion' is not available." - return + Invoke-PodeBuildInstall $dotnet $SdkVersion + $sdkVersions = dotnet --list-sdks | ForEach-Object { $_.Split('[')[0].Trim() } + $majorVersions = $sdkVersions | ForEach-Object { ([version]$_).Major } | Sort-Object -Descending | Select-Object -Unique + $script:AvailableSdkVersion = Get-TargetFrameworkName -Version $majorVersions + + if ($majorVersions -lt (Get-TargetFramework -TargetFrameworks $SdkVersion)) { + Write-Error "The requested framework '$SdkVersion' is not available." + return + } } elseif ($majorVersions -gt (Get-TargetFramework -TargetFrameworks $SdkVersion)) { Write-Warning "The requested SDK version '$SdkVersion' is superseded by the installed '$($script:AvailableSdkVersion)' framework." From 114b9cb95798e28ade73dff4d427f91c45bca530 Mon Sep 17 00:00:00 2001 From: mdaneri Date: Thu, 14 Nov 2024 19:20:02 -0800 Subject: [PATCH 11/25] more comments --- pode.build.ps1 | 168 ++++++++++++++++++++++++++++++++++++------------- 1 file changed, 123 insertions(+), 45 deletions(-) diff --git a/pode.build.ps1 b/pode.build.ps1 index 6d213de1c..d49d65c7f 100644 --- a/pode.build.ps1 +++ b/pode.build.ps1 @@ -302,34 +302,7 @@ function Get-PodeBuildPwshEOL { } } - -function Get-PodeBuildDotNetEOL { - param( - [switch] - $LatestVersion - ) - $uri = 'https://endoflife.date/api/dotnet.json' - try { - $eol = Invoke-RestMethod -Uri $uri -Headers @{ Accept = 'application/json' } - if ($LatestVersion) { - return (($eol | Where-Object { [datetime]$_.eol -ge [datetime]::Now }).cycle)[0] - } - else { - return @{ - eol = ($eol | Where-Object { [datetime]$_.eol -lt [datetime]::Now }).cycle -join ',' - supported = ($eol | Where-Object { [datetime]$_.eol -ge [datetime]::Now }).cycle -join ',' - } - } - } - catch { - Write-Warning "Invoke-RestMethod to $uri failed: $($_.ErrorDetails.Message)" - return @{ - eol = '' - supported = '' - } - } -} - + function Test-PodeBuildOSWindows { return ($IsWindows -or @@ -351,54 +324,158 @@ function Get-PodeBuildOSPwshName { } } +<# +.SYNOPSIS + Determines the OS architecture for the current system. + +.DESCRIPTION + This function detects the operating system's architecture and converts it into a format + compatible with PowerShell installation requirements. It handles both Windows and Unix-based + systems and maps various architecture identifiers to PowerShell-supported names (e.g., 'x64', 'arm64'). + +.OUTPUTS + [string] - The architecture string, such as 'x64', 'x86', 'arm64', or 'arm32'. + +.EXAMPLE + $arch = Get-PodeBuildOSPwshArchitecture + Write-Host "Current architecture: $arch" + +.NOTES + - For Windows, the architecture is derived from the `PROCESSOR_ARCHITECTURE` environment variable. + - For Unix-based systems, the architecture is determined using the `uname -m` command. + - If the architecture is not supported, the function throws an exception. +#> function Get-PodeBuildOSPwshArchitecture { + # Initialize architecture variable $arch = [string]::Empty - # windows + # Detect architecture on Windows if (Test-PodeBuildOSWindows) { $arch = $env:PROCESSOR_ARCHITECTURE } - # unix + # Detect architecture on Unix-based systems (Linux/macOS) if ($IsLinux -or $IsMacOS) { $arch = uname -m } + # Output detected architecture for debugging Write-Host "OS Architecture: $($arch)" - # convert to pwsh arch + # Convert detected architecture to a PowerShell-compatible format switch ($arch.ToLowerInvariant()) { - 'amd64' { return 'x64' } - 'x86' { return 'x86' } - 'x86_64' { return 'x64' } - 'armv7*' { return 'arm32' } - 'aarch64*' { return 'arm64' } - 'arm64' { return 'arm64' } - 'arm64*' { return 'arm64' } - 'armv8*' { return 'arm64' } - default { throw "Unsupported architecture: $($arch)" } + 'amd64' { return 'x64' } # 64-bit architecture (AMD64) + 'x86' { return 'x86' } # 32-bit architecture + 'x86_64' { return 'x64' } # 64-bit architecture (x86_64) + 'armv7*' { return 'arm32' } # 32-bit ARM architecture + 'aarch64*' { return 'arm64' } # 64-bit ARM architecture + 'arm64' { return 'arm64' } # Explicit ARM64 + 'arm64*' { return 'arm64' } # Pattern matching for ARM64 + 'armv8*' { return 'arm64' } # ARM v8 series + default { throw "Unsupported architecture: $($arch)" } # Throw exception for unsupported architectures } } + +<# +.SYNOPSIS + Converts a PowerShell tag to a version number. + +.DESCRIPTION + This function retrieves PowerShell build information for a specified tag by querying + an online API. It then extracts and returns the release version associated with the tag. + +.PARAMETER PowerShellVersion + The PowerShell version tag to retrieve build information for (e.g., 'lts', 'stable', or a specific version). + +.OUTPUTS + [string] - The extracted version number corresponding to the provided tag. + +.EXAMPLE + $version = Convert-PodeBuildOSPwshTagToVersion + Write-Host "Resolved PowerShell version: $version" + +.NOTES + This function depends on internet connectivity to query the build information API. +#> function Convert-PodeBuildOSPwshTagToVersion { + # Query PowerShell build info API with the specified tag $result = Invoke-RestMethod -Uri "https://aka.ms/pwsh-buildinfo-$($PowerShellVersion)" + + # Extract and return the release tag without the leading 'v' return $result.ReleaseTag -ireplace '^v' } -function Install-PodeBuildPwshWindows($target) { +<# +.SYNOPSIS + Installs PowerShell on a Windows system. + +.DESCRIPTION + This function installs PowerShell by copying files from a specified target directory + to the standard installation folder on a Windows system. It first removes any existing + installation in the Target directory. + +.PARAMETER Target + The directory containing the PowerShell installation files. + +.EXAMPLE + Install-PodeBuildPwshWindows -Target 'C:\Temp\PowerShell' + # Installs PowerShell from the 'C:\Temp\PowerShell' directory. + +.NOTES + This function requires administrative privileges to modify the Program Files directory. +#> +function Install-PodeBuildPwshWindows { + param ( + [string] + $Target + ) + + # Define the installation folder path $installFolder = "$($env:ProgramFiles)\PowerShell\7" + # Remove the existing installation, if any if (Test-Path $installFolder) { Remove-Item $installFolder -Recurse -Force -ErrorAction Stop } - Copy-Item -Path "$($target)\" -Destination "$($installFolder)\" -Recurse -ErrorAction Stop + # Copy the new PowerShell files to the installation folder + Copy-Item -Path "$($Target)\" -Destination "$($installFolder)\" -Recurse -ErrorAction Stop } -function Install-PodeBuildPwshUnix($target) { - $targetFullPath = Join-Path -Path $target -ChildPath 'pwsh' + +<# +.SYNOPSIS + Installs PowerShell on a Unix-based system. + +.DESCRIPTION + This function installs PowerShell on Unix-based systems by copying files from a specified Target directory, + setting appropriate permissions, and creating a symbolic link to the PowerShell binary. + +.PARAMETER Target + The directory containing the PowerShell installation files. + +.EXAMPLE + Install-PodeBuildPwshUnix -Target '/tmp/powershell' + # Installs PowerShell from the '/tmp/powershell' directory. + +.NOTES + - This function requires administrative privileges to create symbolic links in system directories. + - The `sudo` command is used if the script is not run as root. +#> +function Install-PodeBuildPwshUnix { + param ( + [string] + $Target + ) + + # Define the full path to the PowerShell binary + $targetFullPath = Join-Path -Path $Target -ChildPath 'pwsh' + + # Set executable permissions on the PowerShell binary $null = chmod 755 $targetFullPath + # Determine the symbolic link location based on the operating system $symlink = $null if ($IsMacOS) { $symlink = '/usr/local/bin/pwsh' @@ -407,6 +484,7 @@ function Install-PodeBuildPwshUnix($target) { $symlink = '/usr/bin/pwsh' } + # Check if the script is run as root $uid = id -u if ($uid -ne '0') { $sudo = 'sudo' @@ -415,7 +493,7 @@ function Install-PodeBuildPwshUnix($target) { $sudo = '' } - # Make symbolic link point to installed path + # Create a symbolic link to the PowerShell binary & $sudo ln -fs $targetFullPath $symlink } From 3bbb732c735f5ffdada18118a600f6ff381fd0bb Mon Sep 17 00:00:00 2001 From: mdaneri Date: Thu, 14 Nov 2024 19:24:25 -0800 Subject: [PATCH 12/25] Update pode.build.ps1 --- pode.build.ps1 | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/pode.build.ps1 b/pode.build.ps1 index d49d65c7f..b82996d8c 100644 --- a/pode.build.ps1 +++ b/pode.build.ps1 @@ -302,7 +302,7 @@ function Get-PodeBuildPwshEOL { } } - + function Test-PodeBuildOSWindows { return ($IsWindows -or @@ -696,11 +696,16 @@ if (($null -ne $PSCmdlet.MyInvocation) -and ($PSCmdlet.MyInvocation.BoundParamet $dotnet = "dotnet-sdk-$SdkVersion" } - if (!(Test-PodeBuildCommand 'dotnet')) { + # if (!(Test-PodeBuildCommand 'dotnet')) { + # Invoke-PodeBuildInstall $dotnet $SdkVersion + # } + try { + $sdkVersions = dotnet --list-sdks | ForEach-Object { $_.Split('[')[0].Trim() } + } + catch { Invoke-PodeBuildInstall $dotnet $SdkVersion + $sdkVersions = dotnet --list-sdks | ForEach-Object { $_.Split('[')[0].Trim() } } - - $sdkVersions = dotnet --list-sdks | ForEach-Object { $_.Split('[')[0].Trim() } $majorVersions = $sdkVersions | ForEach-Object { ([version]$_).Major } | Sort-Object -Descending | Select-Object -Unique $script:AvailableSdkVersion = Get-TargetFrameworkName -Version $majorVersions From 170bc4a4831fb7ee0e21211206931b2294cb44c9 Mon Sep 17 00:00:00 2001 From: mdaneri Date: Thu, 14 Nov 2024 19:50:08 -0800 Subject: [PATCH 13/25] Update pode.build.ps1 --- pode.build.ps1 | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/pode.build.ps1 b/pode.build.ps1 index b82996d8c..e9589c393 100644 --- a/pode.build.ps1 +++ b/pode.build.ps1 @@ -699,6 +699,19 @@ if (($null -ne $PSCmdlet.MyInvocation) -and ($PSCmdlet.MyInvocation.BoundParamet # if (!(Test-PodeBuildCommand 'dotnet')) { # Invoke-PodeBuildInstall $dotnet $SdkVersion # } + + if (Test-PodeBuildIsGitHub){ + $sdkVersions = dotnet --list-sdks | ForEach-Object { $_.Split('[')[0].Trim() } + $majorVersions = $sdkVersions | ForEach-Object { ([version]$_).Major } | Sort-Object -Descending | Select-Object -Unique + $script:AvailableSdkVersion = Get-TargetFrameworkName -Version $majorVersions + + if ($majorVersions -lt (Get-TargetFramework -TargetFrameworks $SdkVersion)) { + Write-Error "The requested framework '$SdkVersion' is not available." + return + } + return + } + try { $sdkVersions = dotnet --list-sdks | ForEach-Object { $_.Split('[')[0].Trim() } } From c46e295f994728bada9a401533c76f097895e57c Mon Sep 17 00:00:00 2001 From: mdaneri Date: Thu, 14 Nov 2024 19:54:08 -0800 Subject: [PATCH 14/25] Update pode.build.ps1 --- pode.build.ps1 | 1 + 1 file changed, 1 insertion(+) diff --git a/pode.build.ps1 b/pode.build.ps1 index e9589c393..5fae53506 100644 --- a/pode.build.ps1 +++ b/pode.build.ps1 @@ -702,6 +702,7 @@ if (($null -ne $PSCmdlet.MyInvocation) -and ($PSCmdlet.MyInvocation.BoundParamet if (Test-PodeBuildIsGitHub){ $sdkVersions = dotnet --list-sdks | ForEach-Object { $_.Split('[')[0].Trim() } + Write-Warning $sdkVersions $majorVersions = $sdkVersions | ForEach-Object { ([version]$_).Major } | Sort-Object -Descending | Select-Object -Unique $script:AvailableSdkVersion = Get-TargetFrameworkName -Version $majorVersions From 65344081c188f283b3b8770de4288fe7d91aa8ae Mon Sep 17 00:00:00 2001 From: mdaneri Date: Thu, 14 Nov 2024 19:56:22 -0800 Subject: [PATCH 15/25] Update pode.build.ps1 --- pode.build.ps1 | 1 + 1 file changed, 1 insertion(+) diff --git a/pode.build.ps1 b/pode.build.ps1 index 5fae53506..0d5cd3cff 100644 --- a/pode.build.ps1 +++ b/pode.build.ps1 @@ -702,6 +702,7 @@ if (($null -ne $PSCmdlet.MyInvocation) -and ($PSCmdlet.MyInvocation.BoundParamet if (Test-PodeBuildIsGitHub){ $sdkVersions = dotnet --list-sdks | ForEach-Object { $_.Split('[')[0].Trim() } + dotnet --list-sdks Write-Warning $sdkVersions $majorVersions = $sdkVersions | ForEach-Object { ([version]$_).Major } | Sort-Object -Descending | Select-Object -Unique $script:AvailableSdkVersion = Get-TargetFrameworkName -Version $majorVersions From 5447d5e8b62b93426e469cf061a10b5cfdadb598 Mon Sep 17 00:00:00 2001 From: mdaneri Date: Thu, 14 Nov 2024 20:01:07 -0800 Subject: [PATCH 16/25] Update pode.build.ps1 --- pode.build.ps1 | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/pode.build.ps1 b/pode.build.ps1 index 0d5cd3cff..b9c7b69ca 100644 --- a/pode.build.ps1 +++ b/pode.build.ps1 @@ -702,11 +702,12 @@ if (($null -ne $PSCmdlet.MyInvocation) -and ($PSCmdlet.MyInvocation.BoundParamet if (Test-PodeBuildIsGitHub){ $sdkVersions = dotnet --list-sdks | ForEach-Object { $_.Split('[')[0].Trim() } - dotnet --list-sdks + dotnet --list-sdks Write-Warning $sdkVersions $majorVersions = $sdkVersions | ForEach-Object { ([version]$_).Major } | Sort-Object -Descending | Select-Object -Unique + Write-Warning "Majorversion=$majorVersions" $script:AvailableSdkVersion = Get-TargetFrameworkName -Version $majorVersions - + Write-Warning "AvailableSdkVersion=$AvailableSdkVersion" if ($majorVersions -lt (Get-TargetFramework -TargetFrameworks $SdkVersion)) { Write-Error "The requested framework '$SdkVersion' is not available." return From b27548473da017422f8c27005d432a1b64a613f4 Mon Sep 17 00:00:00 2001 From: mdaneri Date: Thu, 14 Nov 2024 20:04:35 -0800 Subject: [PATCH 17/25] Update pode.build.ps1 --- pode.build.ps1 | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pode.build.ps1 b/pode.build.ps1 index b9c7b69ca..9fe535d33 100644 --- a/pode.build.ps1 +++ b/pode.build.ps1 @@ -704,7 +704,7 @@ if (($null -ne $PSCmdlet.MyInvocation) -and ($PSCmdlet.MyInvocation.BoundParamet $sdkVersions = dotnet --list-sdks | ForEach-Object { $_.Split('[')[0].Trim() } dotnet --list-sdks Write-Warning $sdkVersions - $majorVersions = $sdkVersions | ForEach-Object { ([version]$_).Major } | Sort-Object -Descending | Select-Object -Unique + $majorVersions = ($sdkVersions | ForEach-Object { ([version]$_).Major } | Sort-Object -Descending | Select-Object -Unique)[0] Write-Warning "Majorversion=$majorVersions" $script:AvailableSdkVersion = Get-TargetFrameworkName -Version $majorVersions Write-Warning "AvailableSdkVersion=$AvailableSdkVersion" @@ -722,13 +722,13 @@ if (($null -ne $PSCmdlet.MyInvocation) -and ($PSCmdlet.MyInvocation.BoundParamet Invoke-PodeBuildInstall $dotnet $SdkVersion $sdkVersions = dotnet --list-sdks | ForEach-Object { $_.Split('[')[0].Trim() } } - $majorVersions = $sdkVersions | ForEach-Object { ([version]$_).Major } | Sort-Object -Descending | Select-Object -Unique + $majorVersions = ($sdkVersions | ForEach-Object { ([version]$_).Major } | Sort-Object -Descending | Select-Object -Unique)[0] $script:AvailableSdkVersion = Get-TargetFrameworkName -Version $majorVersions if ($majorVersions -lt (Get-TargetFramework -TargetFrameworks $SdkVersion)) { Invoke-PodeBuildInstall $dotnet $SdkVersion $sdkVersions = dotnet --list-sdks | ForEach-Object { $_.Split('[')[0].Trim() } - $majorVersions = $sdkVersions | ForEach-Object { ([version]$_).Major } | Sort-Object -Descending | Select-Object -Unique + $majorVersions = ($sdkVersions | ForEach-Object { ([version]$_).Major } | Sort-Object -Descending | Select-Object -Unique)[0] $script:AvailableSdkVersion = Get-TargetFrameworkName -Version $majorVersions if ($majorVersions -lt (Get-TargetFramework -TargetFrameworks $SdkVersion)) { From 307f4667a541f4937a37f869d2826eb5215783cf Mon Sep 17 00:00:00 2001 From: mdaneri Date: Thu, 14 Nov 2024 20:07:21 -0800 Subject: [PATCH 18/25] Update pode.build.ps1 --- pode.build.ps1 | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/pode.build.ps1 b/pode.build.ps1 index 9fe535d33..9e567edf1 100644 --- a/pode.build.ps1 +++ b/pode.build.ps1 @@ -700,21 +700,17 @@ if (($null -ne $PSCmdlet.MyInvocation) -and ($PSCmdlet.MyInvocation.BoundParamet # Invoke-PodeBuildInstall $dotnet $SdkVersion # } - if (Test-PodeBuildIsGitHub){ + <# if (Test-PodeBuildIsGitHub){ $sdkVersions = dotnet --list-sdks | ForEach-Object { $_.Split('[')[0].Trim() } - dotnet --list-sdks - Write-Warning $sdkVersions $majorVersions = ($sdkVersions | ForEach-Object { ([version]$_).Major } | Sort-Object -Descending | Select-Object -Unique)[0] - Write-Warning "Majorversion=$majorVersions" $script:AvailableSdkVersion = Get-TargetFrameworkName -Version $majorVersions - Write-Warning "AvailableSdkVersion=$AvailableSdkVersion" if ($majorVersions -lt (Get-TargetFramework -TargetFrameworks $SdkVersion)) { Write-Error "The requested framework '$SdkVersion' is not available." return } return } - +#> try { $sdkVersions = dotnet --list-sdks | ForEach-Object { $_.Split('[')[0].Trim() } } From e9e4ec6f181a09f97148b046ae89d3a663bd2e06 Mon Sep 17 00:00:00 2001 From: mdaneri Date: Thu, 14 Nov 2024 20:24:59 -0800 Subject: [PATCH 19/25] Update pode.build.ps1 --- pode.build.ps1 | 312 ++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 296 insertions(+), 16 deletions(-) diff --git a/pode.build.ps1 b/pode.build.ps1 index 9e567edf1..2fbde429a 100644 --- a/pode.build.ps1 +++ b/pode.build.ps1 @@ -107,7 +107,7 @@ param( [string[]] [ValidateSet('netstandard2.0', 'netstandard2.1', 'netcoreapp3.0', 'netcoreapp3.1', 'net5.0', 'net6.0', 'net7.0', 'net8.0', 'net9.0', 'net10.0')] - $TargetFrameworks = @('netstandard2.0', 'net8.0' ), + $TargetFrameworks = @('netstandard2.0', 'net8.0','net9.0'), [string] [ValidateSet('netstandard2.0', 'netstandard2.1', 'netcoreapp3.0', 'netcoreapp3.1', 'net5.0', 'net6.0', 'net7.0', 'net8.0', 'net9.0', 'net10.0')] @@ -127,23 +127,132 @@ $Versions = @{ # Helper Functions + +<# +.SYNOPSIS + Checks if the current environment is running on Windows. + +.DESCRIPTION + This function determines if the current PowerShell session is running on Windows. + It inspects `$PSVersionTable.Platform` and `$PSVersionTable.PSEdition` to verify the OS, + returning `$true` for Windows and `$false` for other platforms. + +.OUTPUTS + [bool] - Returns `$true` if the current environment is Windows, otherwise `$false`. + +.EXAMPLE + if (Test-PodeBuildIsWindows) { + Write-Host "This script is running on Windows." + } + +.NOTES + - Useful for cross-platform scripts to conditionally execute Windows-specific commands. + - The `$PSVersionTable.Platform` variable may be `$null` in certain cases, so `$PSEdition` is used as an additional check. +#> function Test-PodeBuildIsWindows { $v = $PSVersionTable return ($v.Platform -ilike '*win*' -or ($null -eq $v.Platform -and $v.PSEdition -ieq 'desktop')) } +<# +.SYNOPSIS + Checks if the script is running in a GitHub Actions environment. + +.DESCRIPTION + This function verifies if the script is running in a GitHub Actions environment + by checking if the `GITHUB_REF` environment variable is defined and not empty. + It returns `$true` if the variable is present, indicating a GitHub Actions environment. + +.OUTPUTS + [bool] - Returns `$true` if the script is running on GitHub Actions, otherwise `$false`. + +.EXAMPLE + if (Test-PodeBuildIsGitHub) { + Write-Host "Running in GitHub Actions." + } + +.NOTES + - This function is useful for CI/CD pipelines to identify if the script is running in GitHub Actions. + - Assumes that `GITHUB_REF` is always set in a GitHub Actions environment. +#> function Test-PodeBuildIsGitHub { return (![string]::IsNullOrWhiteSpace($env:GITHUB_REF)) } +<# +.SYNOPSIS + Checks if code coverage is enabled for the build. + +.DESCRIPTION + This function checks if code coverage is enabled by evaluating the `PODE_RUN_CODE_COVERAGE` + environment variable. If the variable contains '1' or 'true' (case-insensitive), it returns `$true`; + otherwise, it returns `$false`. + +.OUTPUTS + [bool] - Returns `$true` if code coverage is enabled, otherwise `$false`. + +.EXAMPLE + if (Test-PodeBuildCanCodeCoverage) { + Write-Host "Code coverage is enabled for this build." + } + +.NOTES + - Useful for conditional logic in build scripts that should only execute code coverage-related tasks if enabled. + - The `PODE_RUN_CODE_COVERAGE` variable is typically set by the CI/CD environment or the user. +#> function Test-PodeBuildCanCodeCoverage { return (@('1', 'true') -icontains $env:PODE_RUN_CODE_COVERAGE) } +<# +.SYNOPSIS + Returns the name of the CI/CD service being used for the build. + +.DESCRIPTION + This function returns a string representing the CI/CD service in use. + Currently, it always returns 'github-actions', indicating that the build + is running in GitHub Actions. + +.OUTPUTS + [string] - The name of the CI/CD service, which is 'github-actions'. + +.EXAMPLE + $service = Get-PodeBuildService + Write-Host "The build service is: $service" + # Output: The build service is: github-actions + +.NOTES + - This function is useful for identifying the CI/CD service in logs or reporting. + - Future modifications could extend this function to detect other CI/CD services. +#> function Get-PodeBuildService { return 'github-actions' } +<# +.SYNOPSIS + Checks if a specified command is available on the system. + +.DESCRIPTION + This function checks if a given command is available in the system's PATH. + On Windows, it uses `Get-Command`, and on Unix-based systems, it uses `which`. + It returns `$true` if the command exists and `$false` if it does not. + +.PARAMETER cmd + The name of the command to check for availability (e.g., 'choco', 'brew'). + +.OUTPUTS + [bool] - Returns `$true` if the command is found, otherwise `$false`. + +.EXAMPLE + if (Test-PodeBuildCommand -Cmd 'git') { + Write-Host "Git is available." + } + +.NOTES + - This function supports both Windows and Unix-based platforms. + - Requires `Test-PodeBuildIsWindows` to detect the OS type. +#> function Test-PodeBuildCommand($cmd) { $path = $null @@ -157,10 +266,59 @@ function Test-PodeBuildCommand($cmd) { return (![string]::IsNullOrWhiteSpace($path)) } +<# +.SYNOPSIS + Retrieves the branch name from the GitHub Actions environment variable. + +.DESCRIPTION + This function extracts the branch name from the `GITHUB_REF` environment variable, + which is commonly set in GitHub Actions workflows. It removes the 'refs/heads/' prefix + from the branch reference, leaving only the branch name. + +.OUTPUTS + [string] - The name of the GitHub branch. + +.EXAMPLE + $branch = Get-PodeBuildBranch + Write-Host "Current branch: $branch" + # Output example: Current branch: main + +.NOTES + - Only relevant in environments where `GITHUB_REF` is defined (e.g., GitHub Actions). + - Returns an empty string if `GITHUB_REF` is not set. +#> function Get-PodeBuildBranch { return ($env:GITHUB_REF -ireplace 'refs\/heads\/', '') } +<# +.SYNOPSIS + Installs a specified package using the appropriate package manager for the OS. + +.DESCRIPTION + This function installs a specified package at a given version using platform-specific + package managers. For Windows, it uses Chocolatey (`choco`). On Unix-based systems, + it checks for `brew`, `apt-get`, and `yum` to handle installations. The function sets + the security protocol to TLS 1.2 to ensure secure connections during the installation. + +.PARAMETER name + The name of the package to install (e.g., 'git'). + +.PARAMETER version + The version of the package to install, required only for Chocolatey on Windows. + +.OUTPUTS + None. + +.EXAMPLE + Invoke-PodeBuildInstall -Name 'git' -Version '2.30.0' + # Installs version 2.30.0 of Git on Windows if Chocolatey is available. + +.NOTES + - Requires administrator or sudo privileges on Unix-based systems. + - This function supports package installation on both Windows and Unix-based systems. + - If `choco` is available, it will use `choco` for Windows, and `brew`, `apt-get`, or `yum` for Unix-based systems. +#> function Invoke-PodeBuildInstall($name, $version) { [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 @@ -182,6 +340,30 @@ function Invoke-PodeBuildInstall($name, $version) { } } +<# +.SYNOPSIS + Installs a specified PowerShell module if it is not already installed at the required version. + +.DESCRIPTION + This function checks if the specified PowerShell module is available in the current session + at the specified version. If not, it installs the module using the PowerShell Gallery, setting + the security protocol to TLS 1.2. The module is installed in the current user's scope. + +.PARAMETER name + The name of the PowerShell module to check and install. + +.OUTPUTS + None. + +.EXAMPLE + Install-PodeBuildModule -Name 'Pester' + # Installs the 'Pester' module if the specified version is not already installed. + +.NOTES + - Uses `$Versions` hashtable to look up the required version for the module. + - Requires internet access to download modules from the PowerShell Gallery. + - The `-SkipPublisherCheck` parameter bypasses publisher verification; use with caution. +#> function Install-PodeBuildModule($name) { if ($null -ne ((Get-Module -ListAvailable $name) | Where-Object { $_.Version -ieq $Versions[$name] })) { return @@ -192,6 +374,29 @@ function Install-PodeBuildModule($name) { Install-Module -Name "$($name)" -Scope CurrentUser -RequiredVersion "$($Versions[$name])" -Force -SkipPublisherCheck } +<# +.SYNOPSIS + Converts a .NET target framework identifier to a numeric version. + +.DESCRIPTION + This function maps common .NET target framework identifiers (e.g., 'netstandard2.0', 'net6.0') to their + numeric equivalents. It is used to ensure compatibility by returning the framework version number as an integer. + +.PARAMETER TargetFrameworks + The target framework identifier (e.g., 'netstandard2.0', 'net6.0'). + +.OUTPUTS + [int] - The numeric version of the target framework. Defaults to 2 if an unrecognized framework is provided. + +.EXAMPLE + $version = Get-TargetFramework -TargetFrameworks 'net6.0' + Write-Host "Target framework version: $version" + # Output: Target framework version: 6 + +.NOTES + - Returns 2 (netstandard2.0) by default if the input framework is not recognized. + - This function is useful in build scripts that require target framework versioning. +#> function Get-TargetFramework { param( [string] @@ -214,7 +419,29 @@ function Get-TargetFramework { } } +<# +.SYNOPSIS + Converts a .NET target framework version number to a framework identifier. +.DESCRIPTION + This function maps a numeric version to a .NET target framework identifier (e.g., '2' to 'netstandard2.0'). + If the version number is not recognized, it defaults to 'netstandard2.0'. + +.PARAMETER Version + The numeric version of the .NET target framework (e.g., 2, 6, 8). + +.OUTPUTS + [string] - The target framework identifier (e.g., 'netstandard2.0'). + +.EXAMPLE + $frameworkName = Get-TargetFrameworkName -Version 6 + Write-Host "Target framework name: $frameworkName" + # Output: Target framework name: net6.0 + +.NOTES + - Returns 'netstandard2.0' by default if an unrecognized version is provided. + - Useful for converting numeric framework versions to identifier strings in build processes. +#> function Get-TargetFrameworkName { param( $Version @@ -284,6 +511,30 @@ function Invoke-PodeBuildDotnetBuild { } } +<# +.SYNOPSIS + Retrieves the end-of-life (EOL) and supported versions of PowerShell. + +.DESCRIPTION + This function queries an online API to retrieve the EOL and supported versions of PowerShell. + It uses the `Invoke-RestMethod` cmdlet to access data from endoflife.date and returns an object + with comma-separated lists of supported and EOL PowerShell versions based on the current date. + +.OUTPUTS + [hashtable] - A hashtable containing: + - `eol`: Comma-separated string of EOL PowerShell versions. + - `supported`: Comma-separated string of supported PowerShell versions. + +.EXAMPLE + $pwshEOLInfo = Get-PodeBuildPwshEOL + Write-Host "Supported PowerShell versions: $($pwshEOLInfo.supported)" + Write-Host "EOL PowerShell versions: $($pwshEOLInfo.eol)" + +.NOTES + - Requires internet access to query the endoflife.date API. + - If the request fails, the function returns an empty string for both `eol` and `supported`. + - API URL: https://endoflife.date/api/powershell.json +#> function Get-PodeBuildPwshEOL { $uri = 'https://endoflife.date/api/powershell.json' try { @@ -302,14 +553,58 @@ function Get-PodeBuildPwshEOL { } } +<# +.SYNOPSIS + Checks if the current OS is Windows. +.DESCRIPTION + This function detects whether the current operating system is Windows by checking + the `$IsWindows` automatic variable, the presence of the `$env:ProgramFiles` variable, + and the PowerShell Edition in `$PSVersionTable`. This function returns `$true` if + any of these indicate Windows. +.OUTPUTS + [bool] - Returns `$true` if the OS is Windows, otherwise `$false`. + +.EXAMPLE + if (Test-PodeBuildOSWindows) { + Write-Host "Running on Windows" + } + +.NOTES + - Useful for distinguishing between Windows and Unix-based systems for conditional logic. + - May return `$true` in environments where Windows-related environment variables are present. +#> function Test-PodeBuildOSWindows { return ($IsWindows -or ![string]::IsNullOrEmpty($env:ProgramFiles) -or (($PSVersionTable.Keys -contains 'PSEdition') -and ($PSVersionTable.PSEdition -eq 'Desktop'))) } +<# +.SYNOPSIS + Retrieves the current OS name in a PowerShell-compatible format. + +.DESCRIPTION + This function identifies the current operating system and returns a standardized string + representing the OS name ('win' for Windows, 'linux' for Linux, and 'osx' for macOS). + It relies on the `Test-PodeBuildOSWindows` function for Windows detection and `$IsLinux` + and `$IsMacOS` for Linux and macOS, respectively. + +.OUTPUTS + [string] - A string representing the OS name: + - 'win' for Windows + - 'linux' for Linux + - 'osx' for macOS + +.EXAMPLE + $osName = Get-PodeBuildOSPwshName + Write-Host "Operating system name: $osName" + +.NOTES + - This function enables cross-platform compatibility by standardizing OS name detection. + - For accurate results, ensure `$IsLinux` and `$IsMacOS` variables are defined for Unix-like systems. +#> function Get-PodeBuildOSPwshName { if (Test-PodeBuildOSWindows) { return 'win' @@ -696,21 +991,6 @@ if (($null -ne $PSCmdlet.MyInvocation) -and ($PSCmdlet.MyInvocation.BoundParamet $dotnet = "dotnet-sdk-$SdkVersion" } - # if (!(Test-PodeBuildCommand 'dotnet')) { - # Invoke-PodeBuildInstall $dotnet $SdkVersion - # } - - <# if (Test-PodeBuildIsGitHub){ - $sdkVersions = dotnet --list-sdks | ForEach-Object { $_.Split('[')[0].Trim() } - $majorVersions = ($sdkVersions | ForEach-Object { ([version]$_).Major } | Sort-Object -Descending | Select-Object -Unique)[0] - $script:AvailableSdkVersion = Get-TargetFrameworkName -Version $majorVersions - if ($majorVersions -lt (Get-TargetFramework -TargetFrameworks $SdkVersion)) { - Write-Error "The requested framework '$SdkVersion' is not available." - return - } - return - } -#> try { $sdkVersions = dotnet --list-sdks | ForEach-Object { $_.Split('[')[0].Trim() } } From 8cdc7c82742ab6765ebb7a4bd04acfff58016f36 Mon Sep 17 00:00:00 2001 From: mdaneri Date: Thu, 14 Nov 2024 20:28:23 -0800 Subject: [PATCH 20/25] Update pode.build.ps1 --- pode.build.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pode.build.ps1 b/pode.build.ps1 index 2fbde429a..4077c7cbe 100644 --- a/pode.build.ps1 +++ b/pode.build.ps1 @@ -845,7 +845,7 @@ function Invoke-PodeBuildDockerBuild { ) # Build the Docker image with the specified tag and Dockerfile - docker build -t badgerati/pode:$tTag -f $File . + docker build -t badgerati/pode:$Tag -f $File . if (!$?) { throw "docker build failed for $($Tag)" } From 613ebbf1f2d25c0aa06cfb98a05ce569953b5773 Mon Sep 17 00:00:00 2001 From: mdaneri Date: Fri, 22 Nov 2024 14:16:52 -0800 Subject: [PATCH 21/25] improvements --- .github/workflows/VirusTotal-Releases.yml | 10 + .github/workflows/VirusTotal.yml | 15 +- .github/workflows/ci-coverage.yml | 2 +- .github/workflows/ci-docs.yml | 2 +- .github/workflows/ci-powershell.yml | 2 +- .github/workflows/ci-pwsh7_2.yml | 4 +- .github/workflows/ci-pwsh7_5.yml | 79 ++ .github/workflows/ci-pwsh_lts.yml | 2 +- .github/workflows/ci-pwsh_preview.yml | 2 +- pode.build.ps1 | 1335 ++++++++++----------- 10 files changed, 774 insertions(+), 679 deletions(-) create mode 100644 .github/workflows/ci-pwsh7_5.yml diff --git a/.github/workflows/VirusTotal-Releases.yml b/.github/workflows/VirusTotal-Releases.yml index 44d331890..4e7ffd046 100644 --- a/.github/workflows/VirusTotal-Releases.yml +++ b/.github/workflows/VirusTotal-Releases.yml @@ -9,6 +9,16 @@ jobs: runs-on: ubuntu-latest steps: + - name: Check VIRUSTOTAL_API_KEY + env: + VIRUSTOTAL_API_KEY: ${{ secrets.VIRUSTOTAL_API_KEY }} + run: | + if [ -z "$VIRUSTOTAL_API_KEY" ]; then + echo "VIRUSTOTAL_API_KEY is not set. Exiting workflow." + exit 1 + fi + echo "VIRUSTOTAL_API_KEY is set. Proceeding with the workflow. + - name: Run VirusTotal Scan uses: crazy-max/ghaction-virustotal@v4 with: diff --git a/.github/workflows/VirusTotal.yml b/.github/workflows/VirusTotal.yml index 8faaad8d4..2e1ddc290 100644 --- a/.github/workflows/VirusTotal.yml +++ b/.github/workflows/VirusTotal.yml @@ -19,14 +19,25 @@ on: - cron: '0 12 * * *' env: - INVOKE_BUILD_VERSION: '5.11.1' + INVOKE_BUILD_VERSION: '5.12.0' POWERSHELL_VERSION: 'lts' jobs: build: runs-on: ubuntu-latest - steps: + + + - name: Check VIRUSTOTAL_API_KEY + env: + VIRUSTOTAL_API_KEY: ${{ secrets.VIRUSTOTAL_API_KEY }} + run: | + if [ -z "$VIRUSTOTAL_API_KEY" ]; then + echo "VIRUSTOTAL_API_KEY is not set. Exiting workflow." + exit 1 + fi + echo "VIRUSTOTAL_API_KEY is set. Proceeding with the workflow. + - uses: actions/checkout@v4 - name: Setup .NET diff --git a/.github/workflows/ci-coverage.yml b/.github/workflows/ci-coverage.yml index 8847cfab6..c64594877 100644 --- a/.github/workflows/ci-coverage.yml +++ b/.github/workflows/ci-coverage.yml @@ -20,7 +20,7 @@ on: - '.github/workflows/ci-coverage.yml' env: - INVOKE_BUILD_VERSION: '5.11.1' + INVOKE_BUILD_VERSION: '5.12.0' jobs: build: diff --git a/.github/workflows/ci-docs.yml b/.github/workflows/ci-docs.yml index dc2aaf2b1..02ad1c82f 100644 --- a/.github/workflows/ci-docs.yml +++ b/.github/workflows/ci-docs.yml @@ -24,7 +24,7 @@ on: - 'src/Pode.psd1' env: - INVOKE_BUILD_VERSION: '5.11.1' + INVOKE_BUILD_VERSION: '5.12.0' jobs: build: diff --git a/.github/workflows/ci-powershell.yml b/.github/workflows/ci-powershell.yml index 1b071fe4a..adc4cd1f2 100644 --- a/.github/workflows/ci-powershell.yml +++ b/.github/workflows/ci-powershell.yml @@ -20,7 +20,7 @@ on: - '.github/workflows/ci-powershell.yml' env: - INVOKE_BUILD_VERSION: '5.11.1' + INVOKE_BUILD_VERSION: '5.12.0' jobs: build: diff --git a/.github/workflows/ci-pwsh7_2.yml b/.github/workflows/ci-pwsh7_2.yml index 8d37e5af5..67602bb8b 100644 --- a/.github/workflows/ci-pwsh7_2.yml +++ b/.github/workflows/ci-pwsh7_2.yml @@ -24,8 +24,8 @@ on: - '*.dockerfile' env: - INVOKE_BUILD_VERSION: '5.11.1' - POWERSHELL_VERSION: '7.2.24' + INVOKE_BUILD_VERSION: '5.12.0' + POWERSHELL_VERSION: '7.5.0' jobs: build: diff --git a/.github/workflows/ci-pwsh7_5.yml b/.github/workflows/ci-pwsh7_5.yml new file mode 100644 index 000000000..b5faba8cd --- /dev/null +++ b/.github/workflows/ci-pwsh7_5.yml @@ -0,0 +1,79 @@ +name: Pode CI - pwsh 7.5 + +on: + push: + branches: + - '*' + - '!gh-pages' + paths: + - 'src/**' + - 'tests/**' + - 'pode.build.ps1' + - '.github/workflows/ci-pwsh7_5.yml' + - 'Dockerfile' + - '*.dockerfile' + pull_request: + branches: + - '*' + paths: + - 'src/**' + - 'tests/**' + - 'pode.build.ps1' + - '.github/workflows/ci-pwsh7_5.yml' + - 'Dockerfile' + - '*.dockerfile' + +env: + INVOKE_BUILD_VERSION: '5.12.1' + POWERSHELL_VERSION: '7.2.24' + +jobs: + build: + runs-on: ${{ matrix.os }} + + strategy: + fail-fast: false + matrix: + os: [ubuntu-latest, windows-latest, macOS-latest] + + steps: + - uses: actions/checkout@v4 + + - name: Setup .NET + uses: actions/setup-dotnet@v4 + with: + dotnet-version: 9.x + + - name: Setup Powershell - Unix + shell: pwsh + if: runner.os == 'Linux' || runner.os == 'macOS' + run: | + Install-Module -Name InvokeBuild -RequiredVersion $env:INVOKE_BUILD_VERSION -Force + Invoke-Build SetupPowerShell -PowerShellVersion $env:POWERSHELL_VERSION + + - name: Setup Powershell - Windows + shell: PowerShell + if: runner.os == 'Windows' + run: | + Install-Module -Name InvokeBuild -RequiredVersion $env:INVOKE_BUILD_VERSION -Force + Invoke-Build SetupPowerShell -PowerShellVersion $env:POWERSHELL_VERSION + + - name: Output PowerShell version + shell: pwsh + run: | + $PSVersionTable.PSVersion + + - name: Install Invoke-Build + shell: pwsh + run: | + Install-Module -Name InvokeBuild -RequiredVersion $env:INVOKE_BUILD_VERSION -Force + + - name: Run Pester Tests + shell: pwsh + run: | + Invoke-Build Test + + - name: Build Packages + shell: pwsh + run: | + Invoke-Build Pack \ No newline at end of file diff --git a/.github/workflows/ci-pwsh_lts.yml b/.github/workflows/ci-pwsh_lts.yml index 29a74a2df..70ab3d0d3 100644 --- a/.github/workflows/ci-pwsh_lts.yml +++ b/.github/workflows/ci-pwsh_lts.yml @@ -24,7 +24,7 @@ on: - '*.dockerfile' env: - INVOKE_BUILD_VERSION: '5.11.1' + INVOKE_BUILD_VERSION: '5.12.0' POWERSHELL_VERSION: 'lts' jobs: diff --git a/.github/workflows/ci-pwsh_preview.yml b/.github/workflows/ci-pwsh_preview.yml index 6abca6cde..d9dcee85c 100644 --- a/.github/workflows/ci-pwsh_preview.yml +++ b/.github/workflows/ci-pwsh_preview.yml @@ -24,7 +24,7 @@ on: - '*.dockerfile' env: - INVOKE_BUILD_VERSION: '5.11.1' + INVOKE_BUILD_VERSION: '5.12.1' POWERSHELL_VERSION: 'Preview' jobs: diff --git a/pode.build.ps1 b/pode.build.ps1 index 4077c7cbe..e2b67f2bd 100644 --- a/pode.build.ps1 +++ b/pode.build.ps1 @@ -106,11 +106,11 @@ param( $UICulture = 'en-US', [string[]] - [ValidateSet('netstandard2.0', 'netstandard2.1', 'netcoreapp3.0', 'netcoreapp3.1', 'net5.0', 'net6.0', 'net7.0', 'net8.0', 'net9.0', 'net10.0')] - $TargetFrameworks = @('netstandard2.0', 'net8.0','net9.0'), + [ValidateSet('netstandard2.0', 'net8.0', 'net9.0', 'net10.0')] + $TargetFrameworks = @('netstandard2.0', 'net8.0', 'net9.0'), [string] - [ValidateSet('netstandard2.0', 'netstandard2.1', 'netcoreapp3.0', 'netcoreapp3.1', 'net5.0', 'net6.0', 'net7.0', 'net8.0', 'net9.0', 'net10.0')] + [ValidateSet('netstandard2.0', 'net8.0', 'net9.0', 'net10.0')] $SdkVersion = 'net9.0' ) @@ -389,7 +389,7 @@ function Install-PodeBuildModule($name) { [int] - The numeric version of the target framework. Defaults to 2 if an unrecognized framework is provided. .EXAMPLE - $version = Get-TargetFramework -TargetFrameworks 'net6.0' + $version = Get-PodeTargetFramework -TargetFrameworks 'net6.0' Write-Host "Target framework version: $version" # Output: Target framework version: 6 @@ -397,7 +397,7 @@ function Install-PodeBuildModule($name) { - Returns 2 (netstandard2.0) by default if the input framework is not recognized. - This function is useful in build scripts that require target framework versioning. #> -function Get-TargetFramework { +function Get-PodeTargetFramework { param( [string] $TargetFrameworks @@ -405,13 +405,9 @@ function Get-TargetFramework { switch ($TargetFrameworks) { 'netstandard2.0' { return 2 } - 'netstandard2.1' { return 3 } - 'netcoreapp3.0' { return 3 } - 'net5.0' { return 5 } - 'net6.0' { return 6 } - 'net7.0' { return 7 } 'net8.0' { return 8 } 'net9.0' { return 9 } + 'net10.0' { return 10 } default { Write-Warning "$TargetFrameworks is not a valid Framework. Rollback to netstandard2.0" return 2 @@ -434,7 +430,7 @@ function Get-TargetFramework { [string] - The target framework identifier (e.g., 'netstandard2.0'). .EXAMPLE - $frameworkName = Get-TargetFrameworkName -Version 6 + $frameworkName = Get-PodeTargetFrameworkName -Version 6 Write-Host "Target framework name: $frameworkName" # Output: Target framework name: net6.0 @@ -442,7 +438,7 @@ function Get-TargetFramework { - Returns 'netstandard2.0' by default if an unrecognized version is provided. - Useful for converting numeric framework versions to identifier strings in build processes. #> -function Get-TargetFrameworkName { +function Get-PodeTargetFrameworkName { param( $Version ) @@ -473,7 +469,7 @@ function Invoke-PodeBuildDotnetBuild { $majorVersions = $sdkVersions | ForEach-Object { ([version]$_).Major } | Sort-Object -Descending | Select-Object -Unique } else { - $majorVersions = $sdkVersions.Where( { ([version]$_).Major -ge (Get-TargetFramework -TargetFrameworks $AvailableSdkVersion) } ) | Sort-Object -Descending | Select-Object -Unique + $majorVersions = $sdkVersions.Where( { ([version]$_).Major -ge (Get-PodeTargetFramework -TargetFrameworks $AvailableSdkVersion) } ) | Sort-Object -Descending | Select-Object -Unique } # Map target frameworks to minimum SDK versions @@ -481,7 +477,7 @@ function Invoke-PodeBuildDotnetBuild { Write-Error "The requested '$AvailableSdkVersion' framework is not available." return } - $requiredSdkVersion = Get-TargetFramework -TargetFrameworks $target + $requiredSdkVersion = Get-PodeTargetFramework -TargetFrameworks $target # Determine if the target framework is compatible $isCompatible = $majorVersions -ge $requiredSdkVersion @@ -891,847 +887,846 @@ function Split-PodeBuildPwshPath { # Check if the script is running under Invoke-Build -if (($null -ne $PSCmdlet.MyInvocation) -and ($PSCmdlet.MyInvocation.BoundParameters.ContainsKey('BuildRoot') -or $null -ne $BuildRoot)) { - - - Add-BuildTask Default { - Write-Host 'Tasks in the Build Script:' -ForegroundColor DarkMagenta - Write-Host - Write-Host 'Primary Tasks:' -ForegroundColor Green - Write-Host '- Default: Lists all available tasks.' - Write-Host '- Build: Builds the .NET Listener for specified frameworks.' - Write-Host '- Pack: Packages the module, including ZIP, Chocolatey, and Docker.' - Write-Host '- Test: Runs tests after building the project.' - Write-Host '- Clean: Cleans the build environment, removing all generated files.' - Write-Host '- Install-Module: Installs the Pode module locally.' - Write-Host '- Remove-Module: Removes the Pode module from the local registry.' - Write-Host '- DocsBuild: Builds the documentation for distribution.' - Write-Host '- TestNoBuild: Runs tests without building, including Pester tests.' - - - Write-Host - Write-Host 'Other Tasks:' -ForegroundColor Green - Write-Host '- StampVersion: Stamps the specified version onto the module.' - Write-Host '- PrintChecksum: Generates and displays a checksum of the ZIP archive.' - Write-Host '- ChocoDeps: Installs Chocolatey (for Windows).' - Write-Host '- PackDeps: Installs dependencies required for packaging.' - Write-Host '- BuildDeps: Installs dependencies required for building/compiling.' - Write-Host '- TestDeps: Installs dependencies required for testing.' - Write-Host '- DocsDeps: Installs dependencies required for documentation generation.' - Write-Host '- IndexSamples: Indexes sample files for documentation.' - Write-Host '- 7Zip: Creates a ZIP archive of the module (Windows only).' - Write-Host '- DeliverableFolder: Creates a folder for deliverables.' - Write-Host '- Compress: Compresses the module into a ZIP format for distribution.' - Write-Host '- ChocoPack: Creates a Chocolatey package of the module (Windows only).' - Write-Host '- DockerPack: Builds Docker images for the module.' - Write-Host "- PackageFolder: Creates the `pkg` folder for module packaging." - Write-Host '- CheckFailedTests: Checks if any tests failed and throws an error if so.' - Write-Host '- PushCodeCoverage: Pushes code coverage results to a coverage service.' - Write-Host '- Docs: Serves the documentation locally for review.' - Write-Host '- DocsHelpBuild: Builds function help documentation.' - Write-Host "- CleanDeliverable: Removes the `deliverable` folder." - Write-Host "- CleanPkg: Removes the `pkg` folder." - Write-Host "- CleanLibs: Removes the `Libs` folder under `src`." - Write-Host '- CleanListener: Removes the Listener folder.' - Write-Host '- CleanDocs: Cleans up generated documentation files.' - Write-Host '- SetupPowerShell: Sets up the PowerShell environment for the build.' - Write-Host '- ReleaseNotes: Generates release notes based on merged pull requests.' - } - - - <# +if (($null -eq $PSCmdlet.MyInvocation) -or ($PSCmdlet.MyInvocation.BoundParameters.ContainsKey('BuildRoot') -and ($null -eq $BuildRoot))) { + Write-Host 'This script is intended to be run with Invoke-Build. Please use Invoke-Build to execute the tasks defined in this script.' -ForegroundColor Yellow + return +} + + +Add-BuildTask Default { + Write-Host 'Tasks in the Build Script:' -ForegroundColor DarkMagenta + Write-Host + Write-Host 'Primary Tasks:' -ForegroundColor Green + Write-Host '- Default: Lists all available tasks.' + Write-Host '- Build: Builds the .NET Listener for specified frameworks.' + Write-Host '- Pack: Packages the module, including ZIP, Chocolatey, and Docker.' + Write-Host '- Test: Runs tests after building the project.' + Write-Host '- Clean: Cleans the build environment, removing all generated files.' + Write-Host '- Install-Module: Installs the Pode module locally.' + Write-Host '- Remove-Module: Removes the Pode module from the local registry.' + Write-Host '- DocsBuild: Builds the documentation for distribution.' + Write-Host '- TestNoBuild: Runs tests without building, including Pester tests.' + + + Write-Host + Write-Host 'Other Tasks:' -ForegroundColor Green + Write-Host '- StampVersion: Stamps the specified version onto the module.' + Write-Host '- PrintChecksum: Generates and displays a checksum of the ZIP archive.' + Write-Host '- ChocoDeps: Installs Chocolatey (for Windows).' + Write-Host '- PackDeps: Installs dependencies required for packaging.' + Write-Host '- BuildDeps: Installs dependencies required for building/compiling.' + Write-Host '- TestDeps: Installs dependencies required for testing.' + Write-Host '- DocsDeps: Installs dependencies required for documentation generation.' + Write-Host '- IndexSamples: Indexes sample files for documentation.' + Write-Host '- 7Zip: Creates a ZIP archive of the module (Windows only).' + Write-Host '- DeliverableFolder: Creates a folder for deliverables.' + Write-Host '- Compress: Compresses the module into a ZIP format for distribution.' + Write-Host '- ChocoPack: Creates a Chocolatey package of the module (Windows only).' + Write-Host '- DockerPack: Builds Docker images for the module.' + Write-Host "- PackageFolder: Creates the `pkg` folder for module packaging." + Write-Host '- CheckFailedTests: Checks if any tests failed and throws an error if so.' + Write-Host '- PushCodeCoverage: Pushes code coverage results to a coverage service.' + Write-Host '- Docs: Serves the documentation locally for review.' + Write-Host '- DocsHelpBuild: Builds function help documentation.' + Write-Host "- CleanDeliverable: Removes the `deliverable` folder." + Write-Host "- CleanPkg: Removes the `pkg` folder." + Write-Host "- CleanLibs: Removes the `Libs` folder under `src`." + Write-Host '- CleanListener: Removes the Listener folder.' + Write-Host '- CleanDocs: Cleans up generated documentation files.' + Write-Host '- SetupPowerShell: Sets up the PowerShell environment for the build.' + Write-Host '- ReleaseNotes: Generates release notes based on merged pull requests.' +} + + +<# # Helper Tasks #> - # Synopsis: Stamps the version onto the Module - Add-BuildTask StampVersion { - $pwshVersions = Get-PodeBuildPwshEOL +# 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 (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 - } +} - # Synopsis: Generating a Checksum of the Zip - Add-BuildTask PrintChecksum { - $Script:Checksum = (Get-FileHash "./deliverable/$Version-Binaries.zip" -Algorithm SHA256).Hash - Write-Host "Checksum: $($Checksum)" - } +# Synopsis: Generating a Checksum of the Zip +Add-BuildTask PrintChecksum { + $Script:Checksum = (Get-FileHash "./deliverable/$Version-Binaries.zip" -Algorithm SHA256).Hash + Write-Host "Checksum: $($Checksum)" +} - <# +<# # Dependencies #> - # Synopsis: Installs Chocolatey - Add-BuildTask ChocoDeps -If (Test-PodeBuildIsWindows) { - if (!(Test-PodeBuildCommand 'choco')) { - Set-ExecutionPolicy Bypass -Scope Process -Force - Invoke-Expression ([System.Net.WebClient]::new().DownloadString('https://chocolatey.org/install.ps1')) - } +# Synopsis: Installs Chocolatey +Add-BuildTask ChocoDeps -If (Test-PodeBuildIsWindows) { + if (!(Test-PodeBuildCommand 'choco')) { + Set-ExecutionPolicy Bypass -Scope Process -Force + Invoke-Expression ([System.Net.WebClient]::new().DownloadString('https://chocolatey.org/install.ps1')) } +} - # Synopsis: Install dependencies for packaging - Add-BuildTask PackDeps -If (Test-PodeBuildIsWindows) ChocoDeps, { - if (!(Test-PodeBuildCommand '7z')) { - Invoke-PodeBuildInstall '7zip' $Versions.SevenZip - } +# Synopsis: Install dependencies for packaging +Add-BuildTask PackDeps -If (Test-PodeBuildIsWindows) ChocoDeps, { + if (!(Test-PodeBuildCommand '7z')) { + Invoke-PodeBuildInstall '7zip' $Versions.SevenZip } +} - # Synopsis: Install dependencies for compiling/building - Add-BuildTask BuildDeps { - # install dotnet - if (Test-PodeBuildIsWindows) { - $dotnet = 'dotnet' - } - elseif (Test-PodeBuildCommand 'brew') { - $dotnet = 'dotnet-sdk' - } - else { - $dotnet = "dotnet-sdk-$SdkVersion" - } +# Synopsis: Install dependencies for compiling/building +Add-BuildTask BuildDeps { + # install dotnet + if (Test-PodeBuildIsWindows) { + $dotnet = 'dotnet' + } + elseif (Test-PodeBuildCommand 'brew') { + $dotnet = 'dotnet-sdk' + } + else { + $dotnet = "dotnet-sdk-$SdkVersion" + } - try { - $sdkVersions = dotnet --list-sdks | ForEach-Object { $_.Split('[')[0].Trim() } - } - catch { - Invoke-PodeBuildInstall $dotnet $SdkVersion - $sdkVersions = dotnet --list-sdks | ForEach-Object { $_.Split('[')[0].Trim() } - } - $majorVersions = ($sdkVersions | ForEach-Object { ([version]$_).Major } | Sort-Object -Descending | Select-Object -Unique)[0] - $script:AvailableSdkVersion = Get-TargetFrameworkName -Version $majorVersions + try { + $sdkVersions = dotnet --list-sdks | ForEach-Object { $_.Split('[')[0].Trim() } + } + catch { + Invoke-PodeBuildInstall $dotnet $SdkVersion + $sdkVersions = dotnet --list-sdks | ForEach-Object { $_.Split('[')[0].Trim() } + } + $majorVersions = ($sdkVersions | ForEach-Object { ([version]$_).Major } | Sort-Object -Descending | Select-Object -Unique)[0] + $script:AvailableSdkVersion = Get-PodeTargetFrameworkName -Version $majorVersions - if ($majorVersions -lt (Get-TargetFramework -TargetFrameworks $SdkVersion)) { - Invoke-PodeBuildInstall $dotnet $SdkVersion - $sdkVersions = dotnet --list-sdks | ForEach-Object { $_.Split('[')[0].Trim() } - $majorVersions = ($sdkVersions | ForEach-Object { ([version]$_).Major } | Sort-Object -Descending | Select-Object -Unique)[0] - $script:AvailableSdkVersion = Get-TargetFrameworkName -Version $majorVersions + if ($majorVersions -lt (Get-PodeTargetFramework -TargetFrameworks $SdkVersion)) { + Invoke-PodeBuildInstall $dotnet $SdkVersion + $sdkVersions = dotnet --list-sdks | ForEach-Object { $_.Split('[')[0].Trim() } + $majorVersions = ($sdkVersions | ForEach-Object { ([version]$_).Major } | Sort-Object -Descending | Select-Object -Unique)[0] + $script:AvailableSdkVersion = Get-PodeTargetFrameworkName -Version $majorVersions - if ($majorVersions -lt (Get-TargetFramework -TargetFrameworks $SdkVersion)) { - Write-Error "The requested framework '$SdkVersion' is not available." - return - } - } - elseif ($majorVersions -gt (Get-TargetFramework -TargetFrameworks $SdkVersion)) { - Write-Warning "The requested SDK version '$SdkVersion' is superseded by the installed '$($script:AvailableSdkVersion)' framework." + if ($majorVersions -lt (Get-PodeTargetFramework -TargetFrameworks $SdkVersion)) { + Write-Error "The requested framework '$SdkVersion' is not available." + return } - } + elseif ($majorVersions -gt (Get-PodeTargetFramework -TargetFrameworks $SdkVersion)) { + Write-Warning "The requested SDK version '$SdkVersion' is superseded by the installed '$($script:AvailableSdkVersion)' framework." + } + +} - # Synopsis: Install dependencies for running tests - Add-BuildTask TestDeps { - # install pester - Install-PodeBuildModule Pester +# Synopsis: Install dependencies for running tests +Add-BuildTask TestDeps { + # install pester + Install-PodeBuildModule Pester - # install PSCoveralls - if (Test-PodeBuildCanCodeCoverage) { - Install-PodeBuildModule PSCoveralls - } + # install PSCoveralls + if (Test-PodeBuildCanCodeCoverage) { + Install-PodeBuildModule PSCoveralls } +} - # Synopsis: Install dependencies for documentation - Add-BuildTask DocsDeps ChocoDeps, { - # install mkdocs - if (!(Test-PodeBuildCommand 'mkdocs')) { - Invoke-PodeBuildInstall 'mkdocs' $Versions.MkDocs - } +# Synopsis: Install dependencies for documentation +Add-BuildTask DocsDeps ChocoDeps, { + # install mkdocs + if (!(Test-PodeBuildCommand 'mkdocs')) { + Invoke-PodeBuildInstall 'mkdocs' $Versions.MkDocs + } - $_installed = (pip list --format json --disable-pip-version-check | ConvertFrom-Json) - if (($_installed | Where-Object { $_.name -ieq 'mkdocs-material' -and $_.version -ieq $Versions.MkDocsTheme } | Measure-Object).Count -eq 0) { - pip install "mkdocs-material==$($Versions.MkDocsTheme)" --force-reinstall --disable-pip-version-check --quiet - } + $_installed = (pip list --format json --disable-pip-version-check | ConvertFrom-Json) + if (($_installed | Where-Object { $_.name -ieq 'mkdocs-material' -and $_.version -ieq $Versions.MkDocsTheme } | Measure-Object).Count -eq 0) { + pip install "mkdocs-material==$($Versions.MkDocsTheme)" --force-reinstall --disable-pip-version-check --quiet + } - # install platyps - Install-PodeBuildModule PlatyPS + # install platyps + Install-PodeBuildModule PlatyPS +} + +Add-BuildTask IndexSamples { + $examplesPath = './examples' + if (!(Test-Path -PathType Container -Path $examplesPath)) { + return } - Add-BuildTask IndexSamples { - $examplesPath = './examples' - if (!(Test-Path -PathType Container -Path $examplesPath)) { - return - } + # List of directories to exclude + $sampleMarkDownPath = './docs/Getting-Started/Samples.md' + $excludeDirs = @('scripts', 'views', 'static', 'public', 'assets', 'timers', 'modules', + 'Authentication', 'certs', 'logs', 'relative', 'routes', 'issues') - # List of directories to exclude - $sampleMarkDownPath = './docs/Getting-Started/Samples.md' - $excludeDirs = @('scripts', 'views', 'static', 'public', 'assets', 'timers', 'modules', - 'Authentication', 'certs', 'logs', 'relative', 'routes', 'issues') - - # Convert exlusion list into single regex pattern for directory matching - $dirSeparator = [IO.Path]::DirectorySeparatorChar - $excludeDirs = "\$($dirSeparator)($($excludeDirs -join '|'))\$($dirSeparator)" - - # build the page content - Get-ChildItem -Path $examplesPath -Filter *.ps1 -Recurse -File -Force | - Where-Object { - $_.FullName -inotmatch $excludeDirs - } | - Sort-Object -Property FullName | - ForEach-Object { - Write-Verbose "Processing Sample: $($_.FullName)" - - # get the script help - $help = Get-Help -Name $_.FullName -ErrorAction Stop - - # add help content - $urlFileName = ($_.FullName -isplit 'examples')[1].Trim('\/') -replace '[\\/]', '/' - $markdownContent += "## [$($_.BaseName)](https://github.com/Badgerati/Pode/blob/develop/examples/$($urlFileName))`n`n" - $markdownContent += "**Synopsis**`n`n$($help.Synopsis)`n`n" - $markdownContent += "**Description**`n`n$($help.Description.Text)`n`n" - } + # Convert exlusion list into single regex pattern for directory matching + $dirSeparator = [IO.Path]::DirectorySeparatorChar + $excludeDirs = "\$($dirSeparator)($($excludeDirs -join '|'))\$($dirSeparator)" - Write-Output "Write Markdown document for the sample files to $($sampleMarkDownPath)" - Set-Content -Path $sampleMarkDownPath -Value "# Sample Scripts`n`n$($markdownContent)" -Force - } + # build the page content + Get-ChildItem -Path $examplesPath -Filter *.ps1 -Recurse -File -Force | + Where-Object { + $_.FullName -inotmatch $excludeDirs + } | + Sort-Object -Property FullName | + ForEach-Object { + Write-Verbose "Processing Sample: $($_.FullName)" + + # get the script help + $help = Get-Help -Name $_.FullName -ErrorAction Stop - <# + # add help content + $urlFileName = ($_.FullName -isplit 'examples')[1].Trim('\/') -replace '[\\/]', '/' + $markdownContent += "## [$($_.BaseName)](https://github.com/Badgerati/Pode/blob/develop/examples/$($urlFileName))`n`n" + $markdownContent += "**Synopsis**`n`n$($help.Synopsis)`n`n" + $markdownContent += "**Description**`n`n$($help.Description.Text)`n`n" + } + + Write-Output "Write Markdown document for the sample files to $($sampleMarkDownPath)" + Set-Content -Path $sampleMarkDownPath -Value "# Sample Scripts`n`n$($markdownContent)" -Force +} + +<# # Building #> - # Synopsis: Build the .NET Listener - Add-BuildTask Build BuildDeps, { - if (Test-Path ./src/Libs) { - Remove-Item -Path ./src/Libs -Recurse -Force | Out-Null - } +# Synopsis: Build the .NET Listener +Add-BuildTask Build BuildDeps, { + if (Test-Path ./src/Libs) { + Remove-Item -Path ./src/Libs -Recurse -Force | Out-Null + } - # Retrieve the SDK version being used - # $dotnetVersion = dotnet --version + # Retrieve the SDK version being used + # $dotnetVersion = dotnet --version - # Display the SDK version - Write-Output "Building targets '$($targetFrameworks -join "','")' using .NET '$AvailableSdkVersion' framework." + # Display the SDK version + Write-Output "Building targets '$($targetFrameworks -join "','")' using .NET '$AvailableSdkVersion' framework." - # Build for supported target frameworks - try { - Push-Location ./src/Listener - foreach ($target in $targetFrameworks) { - Invoke-PodeBuildDotnetBuild -target $target - Write-Host - Write-Host '***********************' -ForegroundColor DarkMagenta + # Build for supported target frameworks + try { + Push-Location ./src/Listener + foreach ($target in $targetFrameworks) { + Invoke-PodeBuildDotnetBuild -target $target + Write-Host + Write-Host '***********************' -ForegroundColor DarkMagenta - } } - finally { - Pop-Location - } - } + finally { + Pop-Location + } + +} - <# +<# # Packaging #> - # Synopsis: Creates a Zip of the Module - Add-BuildTask 7Zip -If (Test-PodeBuildIsWindows) PackDeps, StampVersion, { - exec { & 7z -tzip a $Version-Binaries.zip ./pkg/* } - }, PrintChecksum +# Synopsis: Creates a Zip of the Module +Add-BuildTask 7Zip -If (Test-PodeBuildIsWindows) PackDeps, StampVersion, { + exec { & 7z -tzip a $Version-Binaries.zip ./pkg/* } +}, PrintChecksum - #Synopsis: Create the Deliverable folder - Add-BuildTask DeliverableFolder { - $path = './deliverable' - if (Test-Path $path) { - Remove-Item -Path $path -Recurse -Force | Out-Null - } - - # create the deliverable dir - New-Item -Path $path -ItemType Directory -Force | Out-Null +#Synopsis: Create the Deliverable folder +Add-BuildTask DeliverableFolder { + $path = './deliverable' + if (Test-Path $path) { + Remove-Item -Path $path -Recurse -Force | Out-Null } - # Synopsis: Creates a Zip of the Module - Add-BuildTask Compress PackageFolder, StampVersion, DeliverableFolder, { - $path = './deliverable' - if (Test-Path $path) { - Remove-Item -Path $path -Recurse -Force | Out-Null - } - # create the pkg dir - New-Item -Path $path -ItemType Directory -Force | Out-Null - Compress-Archive -Path './pkg/*' -DestinationPath "$path/$Version-Binaries.zip" - }, PrintChecksum - - # Synopsis: Creates a Chocolately package of the Module - Add-BuildTask ChocoPack -If (Test-PodeBuildIsWindows) PackDeps, PackageFolder, StampVersion, DeliverableFolder, { - exec { choco pack ./packers/choco/pode.nuspec } - Move-Item -Path "pode.$Version.nupkg" -Destination './deliverable' - } - - # Synopsis: Create docker tags - Add-BuildTask DockerPack PackageFolder, StampVersion, { - # check if github and windows, and output warning - if ((Test-PodeBuildIsGitHub) -and (Test-PodeBuildIsWindows)) { - Write-Warning 'Docker images are not built on GitHub Windows runners, and Docker is in Windows container only mode. Exiting task.' - return - } + # create the deliverable dir + New-Item -Path $path -ItemType Directory -Force | Out-Null +} - try { - # Try to get the Docker version to check if Docker is installed - docker --version - } - catch { - # If Docker is not available, exit the task - Write-Warning 'Docker is not installed or not available in the PATH. Exiting task.' - return - } +# Synopsis: Creates a Zip of the Module +Add-BuildTask Compress PackageFolder, StampVersion, DeliverableFolder, { + $path = './deliverable' + if (Test-Path $path) { + Remove-Item -Path $path -Recurse -Force | Out-Null + } + # create the pkg dir + New-Item -Path $path -ItemType Directory -Force | Out-Null + Compress-Archive -Path './pkg/*' -DestinationPath "$path/$Version-Binaries.zip" +}, PrintChecksum + +# Synopsis: Creates a Chocolately package of the Module +Add-BuildTask ChocoPack -If (Test-PodeBuildIsWindows) PackDeps, PackageFolder, StampVersion, DeliverableFolder, { + exec { choco pack ./packers/choco/pode.nuspec } + Move-Item -Path "pode.$Version.nupkg" -Destination './deliverable' +} - Invoke-PodeBuildDockerBuild -Tag $Version -File './Dockerfile' - Invoke-PodeBuildDockerBuild -Tag 'latest' -File './Dockerfile' - Invoke-PodeBuildDockerBuild -Tag "$Version-alpine" -File './alpine.dockerfile' - Invoke-PodeBuildDockerBuild -Tag 'latest-alpine' -File './alpine.dockerfile' +# Synopsis: Create docker tags +Add-BuildTask DockerPack PackageFolder, StampVersion, { + # check if github and windows, and output warning + if ((Test-PodeBuildIsGitHub) -and (Test-PodeBuildIsWindows)) { + Write-Warning 'Docker images are not built on GitHub Windows runners, and Docker is in Windows container only mode. Exiting task.' + return + } - if (!(Test-PodeBuildIsGitHub)) { - Invoke-PodeBuildDockerBuild -Tag "$Version-arm32" -File './arm32.dockerfile' - Invoke-PodeBuildDockerBuild -Tag 'latest-arm32' -File './arm32.dockerfile' - } - else { - Write-Warning 'Docker images for ARM32 are not built on GitHub runners due to having the wrong OS architecture. Skipping.' - } + try { + # Try to get the Docker version to check if Docker is installed + docker --version + } + catch { + # If Docker is not available, exit the task + Write-Warning 'Docker is not installed or not available in the PATH. Exiting task.' + return } - # Synopsis: Package up the Module - Add-BuildTask Pack Compress, ChocoPack, DockerPack + Invoke-PodeBuildDockerBuild -Tag $Version -File './Dockerfile' + Invoke-PodeBuildDockerBuild -Tag 'latest' -File './Dockerfile' + Invoke-PodeBuildDockerBuild -Tag "$Version-alpine" -File './alpine.dockerfile' + Invoke-PodeBuildDockerBuild -Tag 'latest-alpine' -File './alpine.dockerfile' - # Synopsis: Package up the Module into a /pkg folder - Add-BuildTask PackageFolder Build, { - $path = './pkg' - if (Test-Path $path) { - Remove-Item -Path $path -Recurse -Force | Out-Null - } + if (!(Test-PodeBuildIsGitHub)) { + Invoke-PodeBuildDockerBuild -Tag "$Version-arm32" -File './arm32.dockerfile' + Invoke-PodeBuildDockerBuild -Tag 'latest-arm32' -File './arm32.dockerfile' + } + else { + Write-Warning 'Docker images for ARM32 are not built on GitHub runners due to having the wrong OS architecture. Skipping.' + } +} - # create the pkg dir - New-Item -Path $path -ItemType Directory -Force | Out-Null +# Synopsis: Package up the Module +Add-BuildTask Pack Compress, ChocoPack, DockerPack - # which source folders do we need? create them and copy their contents - $folders = @('Private', 'Public', 'Misc', 'Libs', 'Locales') - $folders | ForEach-Object { - New-Item -ItemType Directory -Path (Join-Path $path $_) -Force | Out-Null - Copy-Item -Path "./src/$($_)/*" -Destination (Join-Path $path $_) -Force -Recurse | Out-Null - } +# Synopsis: Package up the Module into a /pkg folder +Add-BuildTask PackageFolder Build, { + $path = './pkg' + if (Test-Path $path) { + Remove-Item -Path $path -Recurse -Force | Out-Null + } - # which route folders to we need? create them and copy their contents - $folders = @('licenses') - $folders | ForEach-Object { - New-Item -ItemType Directory -Path (Join-Path $path $_) -Force | Out-Null - Copy-Item -Path "./$($_)/*" -Destination (Join-Path $path $_) -Force -Recurse | Out-Null - } + # create the pkg dir + New-Item -Path $path -ItemType Directory -Force | Out-Null - # copy general files - $files = @('src/Pode.psm1', 'src/Pode.psd1', 'src/Pode.Internal.psm1', 'src/Pode.Internal.psd1', 'LICENSE.txt') - $files | ForEach-Object { - Copy-Item -Path "./$($_)" -Destination $path -Force | Out-Null - } + # which source folders do we need? create them and copy their contents + $folders = @('Private', 'Public', 'Misc', 'Libs', 'Locales') + $folders | ForEach-Object { + New-Item -ItemType Directory -Path (Join-Path $path $_) -Force | Out-Null + Copy-Item -Path "./src/$($_)/*" -Destination (Join-Path $path $_) -Force -Recurse | Out-Null + } + + # which route folders to we need? create them and copy their contents + $folders = @('licenses') + $folders | ForEach-Object { + New-Item -ItemType Directory -Path (Join-Path $path $_) -Force | Out-Null + Copy-Item -Path "./$($_)/*" -Destination (Join-Path $path $_) -Force -Recurse | Out-Null + } + + # copy general files + $files = @('src/Pode.psm1', 'src/Pode.psd1', 'src/Pode.Internal.psm1', 'src/Pode.Internal.psd1', 'LICENSE.txt') + $files | ForEach-Object { + Copy-Item -Path "./$($_)" -Destination $path -Force | Out-Null } +} - <# +<# # Testing #> - # Synopsis: Run the tests - Add-BuildTask TestNoBuild TestDeps, { - $p = (Get-Command Invoke-Pester) - if ($null -eq $p -or $p.Version -ine $Versions.Pester) { - Remove-Module Pester -Force -ErrorAction Ignore - Import-Module Pester -Force -RequiredVersion $Versions.Pester - } +# Synopsis: Run the tests +Add-BuildTask TestNoBuild TestDeps, { + $p = (Get-Command Invoke-Pester) + if ($null -eq $p -or $p.Version -ine $Versions.Pester) { + Remove-Module Pester -Force -ErrorAction Ignore + Import-Module Pester -Force -RequiredVersion $Versions.Pester + } - # for windows, output current netsh excluded ports - if (Test-PodeBuildIsWindows) { - netsh int ipv4 show excludedportrange protocol=tcp | Out-Default - } - if ($UICulture -ne ([System.Threading.Thread]::CurrentThread.CurrentUICulture) ) { - $originalUICulture = [System.Threading.Thread]::CurrentThread.CurrentUICulture - Write-Output "Original UICulture is $originalUICulture" - Write-Output "Set UICulture to $UICulture" - # set new UICulture - [System.Threading.Thread]::CurrentThread.CurrentUICulture = $UICulture - } - $Script:TestResultFile = "$($pwd)/TestResults.xml" - - # get default from static property - $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 - - # if run code coverage if enabled - if (Test-PodeBuildCanCodeCoverage) { - $srcFiles = (Get-ChildItem "$($pwd)/src/*.ps1" -Recurse -Force).FullName - $configuration.CodeCoverage.Enabled = $true - $configuration.CodeCoverage.Path = $srcFiles - $Script:TestStatus = Invoke-Pester -Configuration $configuration - } - else { - $Script:TestStatus = Invoke-Pester -Configuration $configuration - } - if ($originalUICulture) { - Write-Output "Restore UICulture to $originalUICulture" - # restore original UICulture - [System.Threading.Thread]::CurrentThread.CurrentUICulture = $originalUICulture - } - }, PushCodeCoverage, CheckFailedTests + # for windows, output current netsh excluded ports + if (Test-PodeBuildIsWindows) { + netsh int ipv4 show excludedportrange protocol=tcp | Out-Default + } + if ($UICulture -ne ([System.Threading.Thread]::CurrentThread.CurrentUICulture) ) { + $originalUICulture = [System.Threading.Thread]::CurrentThread.CurrentUICulture + Write-Output "Original UICulture is $originalUICulture" + Write-Output "Set UICulture to $UICulture" + # set new UICulture + [System.Threading.Thread]::CurrentThread.CurrentUICulture = $UICulture + } + $Script:TestResultFile = "$($pwd)/TestResults.xml" + + # get default from static property + $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 + + # if run code coverage if enabled + if (Test-PodeBuildCanCodeCoverage) { + $srcFiles = (Get-ChildItem "$($pwd)/src/*.ps1" -Recurse -Force).FullName + $configuration.CodeCoverage.Enabled = $true + $configuration.CodeCoverage.Path = $srcFiles + $Script:TestStatus = Invoke-Pester -Configuration $configuration + } + else { + $Script:TestStatus = Invoke-Pester -Configuration $configuration + } + if ($originalUICulture) { + Write-Output "Restore UICulture to $originalUICulture" + # restore original UICulture + [System.Threading.Thread]::CurrentThread.CurrentUICulture = $originalUICulture + } +}, PushCodeCoverage, CheckFailedTests - # Synopsis: Run tests after a build - Add-BuildTask Test Build, TestNoBuild +# Synopsis: Run tests after a build +Add-BuildTask Test Build, TestNoBuild - # Synopsis: Check if any of the tests failed - Add-BuildTask CheckFailedTests { - if ($TestStatus.FailedCount -gt 0) { - throw "$($TestStatus.FailedCount) tests failed" - } +# Synopsis: Check if any of the tests failed +Add-BuildTask CheckFailedTests { + if ($TestStatus.FailedCount -gt 0) { + throw "$($TestStatus.FailedCount) tests failed" } +} - # Synopsis: If AppyVeyor or GitHub, push code coverage stats - Add-BuildTask PushCodeCoverage -If (Test-PodeBuildCanCodeCoverage) { - try { - $service = Get-PodeBuildService - $branch = Get-PodeBuildBranch +# Synopsis: If AppyVeyor or GitHub, push code coverage stats +Add-BuildTask PushCodeCoverage -If (Test-PodeBuildCanCodeCoverage) { + try { + $service = Get-PodeBuildService + $branch = Get-PodeBuildBranch - Write-Host "Pushing coverage for $($branch) from $($service)" - $coverage = New-CoverallsReport -Coverage $Script:TestStatus.CodeCoverage -ServiceName $service -BranchName $branch - Publish-CoverallsReport -Report $coverage -ApiToken $env:PODE_COVERALLS_TOKEN - } - catch { - $_.Exception | Out-Default - } + Write-Host "Pushing coverage for $($branch) from $($service)" + $coverage = New-CoverallsReport -Coverage $Script:TestStatus.CodeCoverage -ServiceName $service -BranchName $branch + Publish-CoverallsReport -Report $coverage -ApiToken $env:PODE_COVERALLS_TOKEN + } + catch { + $_.Exception | Out-Default } +} - <# +<# # Docs #> - # Synopsis: Run the documentation locally - Add-BuildTask Docs DocsDeps, DocsHelpBuild, { - mkdocs serve --open - } +# Synopsis: Run the documentation locally +Add-BuildTask Docs DocsDeps, DocsHelpBuild, { + mkdocs serve --open +} - # Synopsis: Build the function help documentation - Add-BuildTask DocsHelpBuild IndexSamples, DocsDeps, Build, { - # import the local module - Remove-Module Pode -Force -ErrorAction Ignore | Out-Null - Import-Module ./src/Pode.psm1 -Force | Out-Null +# Synopsis: Build the function help documentation +Add-BuildTask DocsHelpBuild IndexSamples, DocsDeps, Build, { + # import the local module + Remove-Module Pode -Force -ErrorAction Ignore | Out-Null + Import-Module ./src/Pode.psm1 -Force | Out-Null - # build the function docs - $path = './docs/Functions' - $map = @{} + # build the function docs + $path = './docs/Functions' + $map = @{} (Get-Module Pode).ExportedFunctions.Keys | ForEach-Object { - $type = [System.IO.Path]::GetFileNameWithoutExtension((Split-Path -Leaf -Path (Get-Command $_ -Module Pode).ScriptBlock.File)) - New-MarkdownHelp -Command $_ -OutputFolder (Join-Path $path $type) -Force -Metadata @{ PodeType = $type } -AlphabeticParamsOrder | Out-Null - $map[$_] = $type - } + $type = [System.IO.Path]::GetFileNameWithoutExtension((Split-Path -Leaf -Path (Get-Command $_ -Module Pode).ScriptBlock.File)) + New-MarkdownHelp -Command $_ -OutputFolder (Join-Path $path $type) -Force -Metadata @{ PodeType = $type } -AlphabeticParamsOrder | Out-Null + $map[$_] = $type + } - # update docs to bind links to unlinked functions - $path = Join-Path $pwd 'docs' - Get-ChildItem -Path $path -Recurse -Filter '*.md' | ForEach-Object { - $depth = ($_.FullName.Replace($path, [string]::Empty).trim('\/') -split '[\\/]').Length - $updated = $false + # update docs to bind links to unlinked functions + $path = Join-Path $pwd 'docs' + Get-ChildItem -Path $path -Recurse -Filter '*.md' | ForEach-Object { + $depth = ($_.FullName.Replace($path, [string]::Empty).trim('\/') -split '[\\/]').Length + $updated = $false - $content = (Get-Content -Path $_.FullName | ForEach-Object { - $line = $_ + $content = (Get-Content -Path $_.FullName | ForEach-Object { + $line = $_ - while ($line -imatch '\[`(?[a-z]+\-pode[a-z]+)`\](?([^(]|$))') { - $updated = $true - $name = $Matches['name'] - $char = $Matches['char'] - $line = ($line -ireplace "\[``$($name)``\]([^(]|$)", "[``$($name)``]($('../' * $depth)Functions/$($map[$name])/$($name))$($char)") - } + while ($line -imatch '\[`(?[a-z]+\-pode[a-z]+)`\](?([^(]|$))') { + $updated = $true + $name = $Matches['name'] + $char = $Matches['char'] + $line = ($line -ireplace "\[``$($name)``\]([^(]|$)", "[``$($name)``]($('../' * $depth)Functions/$($map[$name])/$($name))$($char)") + } - $line - }) + $line + }) - if ($updated) { - $content | Out-File -FilePath $_.FullName -Force -Encoding ascii - } + if ($updated) { + $content | Out-File -FilePath $_.FullName -Force -Encoding ascii } - - # remove the module - Remove-Module Pode -Force -ErrorAction Ignore | Out-Null } - # Synopsis: Build the documentation - Add-BuildTask DocsBuild DocsDeps, DocsHelpBuild, { - mkdocs build --quiet - } + # remove the module + Remove-Module Pode -Force -ErrorAction Ignore | Out-Null +} + +# Synopsis: Build the documentation +Add-BuildTask DocsBuild DocsDeps, DocsHelpBuild, { + mkdocs build --quiet +} - <# +<# # Clean-up #> - # Synopsis: Clean the build enviroment - Add-BuildTask Clean CleanPkg, CleanDeliverable, CleanLibs, CleanListener, CleanDocs +# Synopsis: Clean the build enviroment +Add-BuildTask Clean CleanPkg, CleanDeliverable, CleanLibs, CleanListener, CleanDocs - # Synopsis: Clean the Deliverable folder - Add-BuildTask CleanDeliverable { - $path = './deliverable' - if (Test-Path -Path $path -PathType Container) { - Write-Host 'Removing ./deliverable folder' - Remove-Item -Path $path -Recurse -Force | Out-Null - } - Write-Host "Cleanup $path done" +# Synopsis: Clean the Deliverable folder +Add-BuildTask CleanDeliverable { + $path = './deliverable' + if (Test-Path -Path $path -PathType Container) { + Write-Host 'Removing ./deliverable folder' + Remove-Item -Path $path -Recurse -Force | Out-Null } + Write-Host "Cleanup $path done" +} - # Synopsis: Clean the pkg directory - Add-BuildTask CleanPkg { - $path = './pkg' - if ((Test-Path -Path $path -PathType Container )) { - Write-Host 'Removing ./pkg folder' - Remove-Item -Path $path -Recurse -Force | Out-Null - } - - if ((Test-Path -Path .\packers\choco\tools\ChocolateyInstall.ps1 -PathType Leaf )) { - Write-Host 'Removing .\packers\choco\tools\ChocolateyInstall.ps1' - Remove-Item -Path .\packers\choco\tools\ChocolateyInstall.ps1 - } +# Synopsis: Clean the pkg directory +Add-BuildTask CleanPkg { + $path = './pkg' + if ((Test-Path -Path $path -PathType Container )) { + Write-Host 'Removing ./pkg folder' + Remove-Item -Path $path -Recurse -Force | Out-Null + } - if ((Test-Path -Path .\packers\choco\pode.nuspec -PathType Leaf )) { - Write-Host 'Removing .\packers\choco\pode.nuspec' - Remove-Item -Path .\packers\choco\pode.nuspec - } + if ((Test-Path -Path .\packers\choco\tools\ChocolateyInstall.ps1 -PathType Leaf )) { + Write-Host 'Removing .\packers\choco\tools\ChocolateyInstall.ps1' + Remove-Item -Path .\packers\choco\tools\ChocolateyInstall.ps1 + } - Write-Host "Cleanup $path done" + if ((Test-Path -Path .\packers\choco\pode.nuspec -PathType Leaf )) { + Write-Host 'Removing .\packers\choco\pode.nuspec' + Remove-Item -Path .\packers\choco\pode.nuspec } - # Synopsis: Clean the libs folder - Add-BuildTask CleanLibs { - $path = './src/Libs' - if (Test-Path -Path $path -PathType Container) { - Write-Host "Removing $path contents" - Remove-Item -Path $path -Recurse -Force | Out-Null - } + Write-Host "Cleanup $path done" +} - Write-Host "Cleanup $path done" +# Synopsis: Clean the libs folder +Add-BuildTask CleanLibs { + $path = './src/Libs' + if (Test-Path -Path $path -PathType Container) { + Write-Host "Removing $path contents" + Remove-Item -Path $path -Recurse -Force | Out-Null } - # Synopsis: Clean the Listener folder - Add-BuildTask CleanListener { - $path = './src/Listener/bin' - if (Test-Path -Path $path -PathType Container) { - Write-Host "Removing $path contents" - Remove-Item -Path $path -Recurse -Force | Out-Null - } + Write-Host "Cleanup $path done" +} - Write-Host "Cleanup $path done" +# Synopsis: Clean the Listener folder +Add-BuildTask CleanListener { + $path = './src/Listener/bin' + if (Test-Path -Path $path -PathType Container) { + Write-Host "Removing $path contents" + Remove-Item -Path $path -Recurse -Force | Out-Null } - Add-BuildTask CleanDocs { - $path = './docs/Getting-Started/Samples.md' - if (Test-Path -Path $path -PathType Leaf) { - Write-Host "Removing $path" - Remove-Item -Path $path -Force | Out-Null - } + Write-Host "Cleanup $path done" +} + +Add-BuildTask CleanDocs { + $path = './docs/Getting-Started/Samples.md' + if (Test-Path -Path $path -PathType Leaf) { + Write-Host "Removing $path" + Remove-Item -Path $path -Force | Out-Null } - <# +} +<# # Local module management #> - # Synopsis: Install Pode Module locally - Add-BuildTask Install-Module -If ($Version) Pack, { - $PSPaths = Split-PodeBuildPwshPath +# Synopsis: Install Pode Module locally +Add-BuildTask Install-Module -If ($Version) Pack, { + $PSPaths = Split-PodeBuildPwshPath - $dest = Join-Path -Path $PSPaths[0] -ChildPath 'Pode' -AdditionalChildPath "$Version" - if (Test-Path $dest) { - Remove-Item -Path $dest -Recurse -Force | Out-Null - } - - # create the dest dir - New-Item -Path $dest -ItemType Directory -Force | Out-Null - $path = './pkg' + $dest = Join-Path -Path $PSPaths[0] -ChildPath 'Pode' -AdditionalChildPath "$Version" + if (Test-Path $dest) { + Remove-Item -Path $dest -Recurse -Force | Out-Null + } - # copy over folders - $folders = @('Private', 'Public', 'Misc', 'Libs', 'licenses', 'Locales') - $folders | ForEach-Object { - Copy-Item -Path (Join-Path -Path $path -ChildPath $_) -Destination $dest -Force -Recurse | Out-Null - } + # create the dest dir + New-Item -Path $dest -ItemType Directory -Force | Out-Null + $path = './pkg' - # copy over general files - $files = @('Pode.psm1', 'Pode.psd1', 'Pode.Internal.psm1', 'Pode.Internal.psd1', 'LICENSE.txt') - $files | ForEach-Object { - Copy-Item -Path (Join-Path -Path $path -ChildPath $_) -Destination $dest -Force | Out-Null - } + # copy over folders + $folders = @('Private', 'Public', 'Misc', 'Libs', 'licenses', 'Locales') + $folders | ForEach-Object { + Copy-Item -Path (Join-Path -Path $path -ChildPath $_) -Destination $dest -Force -Recurse | Out-Null + } - Write-Host "Deployed to $dest" + # copy over general files + $files = @('Pode.psm1', 'Pode.psd1', 'Pode.Internal.psm1', 'Pode.Internal.psd1', 'LICENSE.txt') + $files | ForEach-Object { + Copy-Item -Path (Join-Path -Path $path -ChildPath $_) -Destination $dest -Force | Out-Null } - # Synopsis: Remove the Pode Module from the local registry - Add-BuildTask Remove-Module { - if (!$Version) { - throw 'Parameter -Version is required' - } + Write-Host "Deployed to $dest" +} - $PSPaths = Split-PodeBuildPwshPath +# Synopsis: Remove the Pode Module from the local registry +Add-BuildTask Remove-Module { + if (!$Version) { + throw 'Parameter -Version is required' + } - $dest = Join-Path -Path $PSPaths[0] -ChildPath 'Pode' -AdditionalChildPath "$Version" - if (!(Test-Path $dest)) { - Write-Warning "Directory $dest doesn't exist" - } + $PSPaths = Split-PodeBuildPwshPath - Write-Host "Deleting module from $dest" - Remove-Item -Path $dest -Recurse -Force | Out-Null + $dest = Join-Path -Path $PSPaths[0] -ChildPath 'Pode' -AdditionalChildPath "$Version" + if (!(Test-Path $dest)) { + Write-Warning "Directory $dest doesn't exist" } + Write-Host "Deleting module from $dest" + Remove-Item -Path $dest -Recurse -Force | Out-Null +} + - <# +<# # PowerShell setup #> - # Synopsis: Setup the PowerShell environment - Add-BuildTask SetupPowerShell { - # code for this step is altered versions of the code found here: - # - https://github.com/bjompen/UpdatePWSHAction/blob/main/UpgradePwsh.ps1 - # - https://raw.githubusercontent.com/PowerShell/PowerShell/master/tools/install-powershell.ps1 - - # fail if no version supplied - if ([string]::IsNullOrWhiteSpace($PowerShellVersion)) { - throw 'No PowerShell version supplied to set up' - } +# Synopsis: Setup the PowerShell environment +Add-BuildTask SetupPowerShell { + # code for this step is altered versions of the code found here: + # - https://github.com/bjompen/UpdatePWSHAction/blob/main/UpgradePwsh.ps1 + # - https://raw.githubusercontent.com/PowerShell/PowerShell/master/tools/install-powershell.ps1 - # is the version valid? - $tags = @('preview', 'lts', 'daily', 'stable') - if (($PowerShellVersion -inotin $tags) -and ($PowerShellVersion -inotmatch '^\d+\.\d+\.\d+(-\w+(\.\d+)?)?$')) { - throw "Invalid PowerShell version supplied: $($PowerShellVersion)" - } + # fail if no version supplied + if ([string]::IsNullOrWhiteSpace($PowerShellVersion)) { + throw 'No PowerShell version supplied to set up' + } - # tag version or literal version? - $isTagVersion = $PowerShellVersion -iin $tags - if ($isTagVersion) { - Write-Host "Release tag: $($PowerShellVersion)" - $PowerShellVersion = Convert-PodeBuildOSPwshTagToVersion - } - Write-Host "Release version: $($PowerShellVersion)" + # is the version valid? + $tags = @('preview', 'lts', 'daily', 'stable') + if (($PowerShellVersion -inotin $tags) -and ($PowerShellVersion -inotmatch '^\d+\.\d+\.\d+(-\w+(\.\d+)?)?$')) { + throw "Invalid PowerShell version supplied: $($PowerShellVersion)" + } - # base/prefix versions - $atoms = $PowerShellVersion -split '\-' - $baseVersion = $atoms[0] + # tag version or literal version? + $isTagVersion = $PowerShellVersion -iin $tags + if ($isTagVersion) { + Write-Host "Release tag: $($PowerShellVersion)" + $PowerShellVersion = Convert-PodeBuildOSPwshTagToVersion + } + Write-Host "Release version: $($PowerShellVersion)" - # do nothing if the current version is the version we're trying to set up - $currentVersion = Get-PodeBuildCurrentPwshVersion - Write-Host "Current PowerShell version: $($currentVersion)" + # base/prefix versions + $atoms = $PowerShellVersion -split '\-' + $baseVersion = $atoms[0] - if ($baseVersion -ieq $currentVersion) { - Write-Host "PowerShell version $($PowerShellVersion) is already installed" - return - } + # do nothing if the current version is the version we're trying to set up + $currentVersion = Get-PodeBuildCurrentPwshVersion + Write-Host "Current PowerShell version: $($currentVersion)" - # build the package name - $arch = Get-PodeBuildOSPwshArchitecture - $os = Get-PodeBuildOSPwshName + if ($baseVersion -ieq $currentVersion) { + Write-Host "PowerShell version $($PowerShellVersion) is already installed" + return + } - $packageName = (@{ - win = "PowerShell-$($PowerShellVersion)-$($os)-$($arch).zip" - linux = "powershell-$($PowerShellVersion)-$($os)-$($arch).tar.gz" - osx = "powershell-$($PowerShellVersion)-$($os)-$($arch).tar.gz" - })[$os] + # build the package name + $arch = Get-PodeBuildOSPwshArchitecture + $os = Get-PodeBuildOSPwshName - # build the URL - $urls = @{ - Old = "https://pscoretestdata.blob.core.windows.net/v$($PowerShellVersion -replace '\.', '-')/$($packageName)" - New = "https://powershellinfraartifacts-gkhedzdeaghdezhr.z01.azurefd.net/install/v$($PowerShellVersion)/$($packageName)" - } + $packageName = (@{ + win = "PowerShell-$($PowerShellVersion)-$($os)-$($arch).zip" + linux = "powershell-$($PowerShellVersion)-$($os)-$($arch).tar.gz" + osx = "powershell-$($PowerShellVersion)-$($os)-$($arch).tar.gz" + })[$os] - # download the package to a temp location - $outputFile = Join-Path -Path ([System.IO.Path]::GetTempPath()) -ChildPath $packageName - $downloadParams = @{ - Uri = $urls.New - OutFile = $outputFile - ErrorAction = 'Stop' - } + # build the URL + $urls = @{ + Old = "https://pscoretestdata.blob.core.windows.net/v$($PowerShellVersion -replace '\.', '-')/$($packageName)" + New = "https://powershellinfraartifacts-gkhedzdeaghdezhr.z01.azurefd.net/install/v$($PowerShellVersion)/$($packageName)" + } - Write-Host "Output file: $($outputFile)" + # download the package to a temp location + $outputFile = Join-Path -Path ([System.IO.Path]::GetTempPath()) -ChildPath $packageName + $downloadParams = @{ + Uri = $urls.New + OutFile = $outputFile + ErrorAction = 'Stop' + } - # retry the download 6 times, with a sleep of 10s between each attempt, and altering between old and new URLs - $counter = 0 - $success = $false + Write-Host "Output file: $($outputFile)" - do { - try { - $counter++ - Write-Host "Attempt $($counter) of 6" + # retry the download 6 times, with a sleep of 10s between each attempt, and altering between old and new URLs + $counter = 0 + $success = $false - # use new URL for odd attempts, and old URL for even attempts - if ($counter % 2 -eq 0) { - $downloadParams.Uri = $urls.Old - } - else { - $downloadParams.Uri = $urls.New - } - - # download the package - Write-Host "Attempting download of $($packageName) from $($downloadParams.Uri)" - Invoke-WebRequest @downloadParams + do { + try { + $counter++ + Write-Host "Attempt $($counter) of 6" - $success = $true - Write-Host "Downloaded $($packageName) successfully" + # use new URL for odd attempts, and old URL for even attempts + if ($counter % 2 -eq 0) { + $downloadParams.Uri = $urls.Old } - catch { - $success = $false - if ($counter -ge 6) { - throw "Failed to download PowerShell package after 6 attempts. Error: $($_.Exception.Message)" - } - - Start-Sleep -Seconds 5 + else { + $downloadParams.Uri = $urls.New } - } while (!$success) - # create target folder for package - $targetFolder = Join-Path -Path (Resolve-Path ~).Path -ChildPath ($packageName -ireplace '\.tar$') - if (!(Test-Path $targetFolder)) { - $null = New-Item -Path $targetFolder -ItemType Directory -Force - } + # download the package + Write-Host "Attempting download of $($packageName) from $($downloadParams.Uri)" + Invoke-WebRequest @downloadParams - # extract the package - switch ($os) { - 'win' { - Expand-Archive -Path $outputFile -DestinationPath $targetFolder -Force + $success = $true + Write-Host "Downloaded $($packageName) successfully" + } + catch { + $success = $false + if ($counter -ge 6) { + throw "Failed to download PowerShell package after 6 attempts. Error: $($_.Exception.Message)" } - { $_ -iin 'linux', 'osx' } { - $null = tar -xzf $outputFile -C $targetFolder - } + Start-Sleep -Seconds 5 } + } while (!$success) + + # create target folder for package + $targetFolder = Join-Path -Path (Resolve-Path ~).Path -ChildPath ($packageName -ireplace '\.tar$') + if (!(Test-Path $targetFolder)) { + $null = New-Item -Path $targetFolder -ItemType Directory -Force + } - # install the package - Write-Host "Installing PowerShell $($PowerShellVersion) to $($targetFolder)" - if (Test-PodeBuildOSWindows) { - Install-PodeBuildPwshWindows -Target $targetFolder + # extract the package + switch ($os) { + 'win' { + Expand-Archive -Path $outputFile -DestinationPath $targetFolder -Force } - else { - Install-PodeBuildPwshUnix -Target $targetFolder + + { $_ -iin 'linux', 'osx' } { + $null = tar -xzf $outputFile -C $targetFolder } } + # install the package + Write-Host "Installing PowerShell $($PowerShellVersion) to $($targetFolder)" + if (Test-PodeBuildOSWindows) { + Install-PodeBuildPwshWindows -Target $targetFolder + } + else { + Install-PodeBuildPwshUnix -Target $targetFolder + } +} + - <# +<# # Release Notes #> - # Synopsis: Build the Release Notes - task ReleaseNotes { - if ([string]::IsNullOrWhiteSpace($ReleaseNoteVersion)) { - Write-Host 'Please provide a ReleaseNoteVersion' -ForegroundColor Red - return - } +# Synopsis: Build the Release Notes +task ReleaseNotes { + if ([string]::IsNullOrWhiteSpace($ReleaseNoteVersion)) { + Write-Host 'Please provide a ReleaseNoteVersion' -ForegroundColor Red + return + } - # get the PRs for the ReleaseNoteVersion - $prs = gh search prs --milestone $ReleaseNoteVersion --repo badgerati/pode --merged --limit 200 --json 'number,title,labels,author' | ConvertFrom-Json + # get the PRs for the ReleaseNoteVersion + $prs = gh search prs --milestone $ReleaseNoteVersion --repo badgerati/pode --merged --limit 200 --json 'number,title,labels,author' | ConvertFrom-Json - # group PRs into categories, filtering out some internal PRs - $categories = [ordered]@{ - Features = @() - Enhancements = @() - Bugs = @() - Documentation = @() - } + # group PRs into categories, filtering out some internal PRs + $categories = [ordered]@{ + Features = @() + Enhancements = @() + Bugs = @() + Documentation = @() + } - $dependabot = @{} + $dependabot = @{} - foreach ($pr in $prs) { - if ($pr.labels.name -icontains 'superseded') { - continue - } + foreach ($pr in $prs) { + if ($pr.labels.name -icontains 'superseded') { + continue + } - $label = ($pr.labels[0].name -split ' ')[0] - if ($label -iin @('new-release', 'internal-code')) { - continue - } + $label = ($pr.labels[0].name -split ' ')[0] + if ($label -iin @('new-release', 'internal-code')) { + continue + } - if ([string]::IsNullOrWhiteSpace($label)) { - $label = 'misc' - } + if ([string]::IsNullOrWhiteSpace($label)) { + $label = 'misc' + } - switch ($label.ToLowerInvariant()) { - 'feature' { $label = 'Features' } - 'enhancement' { $label = 'Enhancements' } - 'bug' { $label = 'Bugs' } - } + switch ($label.ToLowerInvariant()) { + 'feature' { $label = 'Features' } + 'enhancement' { $label = 'Enhancements' } + 'bug' { $label = 'Bugs' } + } - if (!$categories.Contains($label)) { - $categories[$label] = @() - } + if (!$categories.Contains($label)) { + $categories[$label] = @() + } - if ($pr.author.login -ilike '*dependabot*') { - if ($pr.title -imatch 'Bump (?\S+) from (?[0-9\.]+) to (?[0-9\.]+)') { - if (!$dependabot.ContainsKey($Matches['name'])) { - $dependabot[$Matches['name']] = @{ - Name = $Matches['name'] - Number = $pr.number - From = [version]$Matches['from'] - To = [version]$Matches['to'] - } + if ($pr.author.login -ilike '*dependabot*') { + if ($pr.title -imatch 'Bump (?\S+) from (?[0-9\.]+) to (?[0-9\.]+)') { + if (!$dependabot.ContainsKey($Matches['name'])) { + $dependabot[$Matches['name']] = @{ + Name = $Matches['name'] + Number = $pr.number + From = [version]$Matches['from'] + To = [version]$Matches['to'] + } + } + else { + $item = $dependabot[$Matches['name']] + if ([int]$pr.number -gt [int]$item.Number) { + $item.Number = $pr.number } - else { - $item = $dependabot[$Matches['name']] - if ([int]$pr.number -gt [int]$item.Number) { - $item.Number = $pr.number - } - if ([version]$Matches['from'] -lt $item.From) { - $item.From = [version]$Matches['from'] - } - if ([version]$Matches['to'] -gt $item.To) { - $item.To = [version]$Matches['to'] - } + if ([version]$Matches['from'] -lt $item.From) { + $item.From = [version]$Matches['from'] + } + if ([version]$Matches['to'] -gt $item.To) { + $item.To = [version]$Matches['to'] } - - continue } - } - $titles = @($pr.title).Trim() - if ($pr.title.Contains(';')) { - $titles = ($pr.title -split ';').Trim() - } - - $author = $null - if (($pr.author.login -ine 'badgerati') -and ($pr.author.login -inotlike '*dependabot*')) { - $author = $pr.author.login + continue } + } - foreach ($title in $titles) { - $str = "* #$($pr.number): $($title -replace '`', "'")" - if (![string]::IsNullOrWhiteSpace($author)) { - $str += " (thanks @$($author)!)" - } + $titles = @($pr.title).Trim() + if ($pr.title.Contains(';')) { + $titles = ($pr.title -split ';').Trim() + } - if ($str -imatch '\s+(docs|documentation)\s+') { - $categories['Documentation'] += $str - } - else { - $categories[$label] += $str - } - } + $author = $null + if (($pr.author.login -ine 'badgerati') -and ($pr.author.login -inotlike '*dependabot*')) { + $author = $pr.author.login } - # add dependabot aggregated PRs - if ($dependabot.Count -gt 0) { - $label = 'dependencies' - if (!$categories.Contains($label)) { - $categories[$label] = @() + foreach ($title in $titles) { + $str = "* #$($pr.number): $($title -replace '`', "'")" + if (![string]::IsNullOrWhiteSpace($author)) { + $str += " (thanks @$($author)!)" } - foreach ($dep in $dependabot.Values) { - $categories[$label] += "* #$($dep.Number): Bump $($dep.Name) from $($dep.From) to $($dep.To)" + if ($str -imatch '\s+(docs|documentation)\s+') { + $categories['Documentation'] += $str } + else { + $categories[$label] += $str + } + } + } + + # add dependabot aggregated PRs + if ($dependabot.Count -gt 0) { + $label = 'dependencies' + if (!$categories.Contains($label)) { + $categories[$label] = @() } - # output the release notes - Write-Host "# v$($ReleaseNoteVersion)`n" + foreach ($dep in $dependabot.Values) { + $categories[$label] += "* #$($dep.Number): Bump $($dep.Name) from $($dep.From) to $($dep.To)" + } + } - $culture = (Get-Culture).TextInfo - foreach ($category in $categories.Keys) { - if ($categories[$category].Length -eq 0) { - continue - } + # output the release notes + Write-Host "# v$($ReleaseNoteVersion)`n" - Write-Host "### $($culture.ToTitleCase($category))" - $categories[$category] | Sort-Object | ForEach-Object { Write-Host $_ } - Write-Host '' + $culture = (Get-Culture).TextInfo + foreach ($category in $categories.Keys) { + if ($categories[$category].Length -eq 0) { + continue } + + Write-Host "### $($culture.ToTitleCase($category))" + $categories[$category] | Sort-Object | ForEach-Object { Write-Host $_ } + Write-Host '' } } -else { - Write-Host 'This script is intended to be run with Invoke-Build. Please use Invoke-Build to execute the tasks defined in this script.' -ForegroundColor Yellow -} \ No newline at end of file From cb683fe6f5512b524772acf87ba16fc4acc5ae2c Mon Sep 17 00:00:00 2001 From: mdaneri Date: Fri, 22 Nov 2024 14:25:30 -0800 Subject: [PATCH 22/25] fix workflow --- .github/workflows/ci-pwsh7_2.yml | 2 +- .github/workflows/ci-pwsh7_5.yml | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci-pwsh7_2.yml b/.github/workflows/ci-pwsh7_2.yml index 67602bb8b..2c8a2b3af 100644 --- a/.github/workflows/ci-pwsh7_2.yml +++ b/.github/workflows/ci-pwsh7_2.yml @@ -25,7 +25,7 @@ on: env: INVOKE_BUILD_VERSION: '5.12.0' - POWERSHELL_VERSION: '7.5.0' + POWERSHELL_VERSION: '7.2.24' jobs: build: diff --git a/.github/workflows/ci-pwsh7_5.yml b/.github/workflows/ci-pwsh7_5.yml index b5faba8cd..8af886f21 100644 --- a/.github/workflows/ci-pwsh7_5.yml +++ b/.github/workflows/ci-pwsh7_5.yml @@ -25,7 +25,8 @@ on: env: INVOKE_BUILD_VERSION: '5.12.1' - POWERSHELL_VERSION: '7.2.24' + POWERSHELL_VERSION: '7.5.0-rc.1' + jobs: build: From 64536e3e95158ac32aed3fee6226cc94069ad025 Mon Sep 17 00:00:00 2001 From: mdaneri Date: Fri, 22 Nov 2024 14:29:15 -0800 Subject: [PATCH 23/25] fix invoke-build version --- .github/workflows/ci-pwsh7_5.yml | 2 +- .github/workflows/ci-pwsh_preview.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci-pwsh7_5.yml b/.github/workflows/ci-pwsh7_5.yml index 8af886f21..1b0c51cce 100644 --- a/.github/workflows/ci-pwsh7_5.yml +++ b/.github/workflows/ci-pwsh7_5.yml @@ -24,7 +24,7 @@ on: - '*.dockerfile' env: - INVOKE_BUILD_VERSION: '5.12.1' + INVOKE_BUILD_VERSION: '5.12.0' POWERSHELL_VERSION: '7.5.0-rc.1' diff --git a/.github/workflows/ci-pwsh_preview.yml b/.github/workflows/ci-pwsh_preview.yml index d9dcee85c..43198540f 100644 --- a/.github/workflows/ci-pwsh_preview.yml +++ b/.github/workflows/ci-pwsh_preview.yml @@ -24,7 +24,7 @@ on: - '*.dockerfile' env: - INVOKE_BUILD_VERSION: '5.12.1' + INVOKE_BUILD_VERSION: '5.12.0' POWERSHELL_VERSION: 'Preview' jobs: From c8dac4e33957c6d19fb204d7dd8376d9e21a3b47 Mon Sep 17 00:00:00 2001 From: Matthew Kelly Date: Sat, 23 Nov 2024 12:54:11 +0000 Subject: [PATCH 24/25] Bump docker alpine version, remove PS7.2 and older NET frameworks, fix VirusTotal, remove 7zip build task --- .github/workflows/VirusTotal-Releases.yml | 4 +- .github/workflows/VirusTotal.yml | 2 +- .github/workflows/ci-pwsh7_2.yml | 79 ----------------------- alpine.dockerfile | 2 +- pode.build.ps1 | 56 ++++++---------- src/Listener/Pode.csproj | 22 +------ 6 files changed, 23 insertions(+), 142 deletions(-) delete mode 100644 .github/workflows/ci-pwsh7_2.yml diff --git a/.github/workflows/VirusTotal-Releases.yml b/.github/workflows/VirusTotal-Releases.yml index 4e7ffd046..5a08a71c6 100644 --- a/.github/workflows/VirusTotal-Releases.yml +++ b/.github/workflows/VirusTotal-Releases.yml @@ -17,8 +17,8 @@ jobs: echo "VIRUSTOTAL_API_KEY is not set. Exiting workflow." exit 1 fi - echo "VIRUSTOTAL_API_KEY is set. Proceeding with the workflow. - + echo "VIRUSTOTAL_API_KEY is set. Proceeding with the workflow." + - name: Run VirusTotal Scan uses: crazy-max/ghaction-virustotal@v4 with: diff --git a/.github/workflows/VirusTotal.yml b/.github/workflows/VirusTotal.yml index 2e1ddc290..997dd7f39 100644 --- a/.github/workflows/VirusTotal.yml +++ b/.github/workflows/VirusTotal.yml @@ -36,7 +36,7 @@ jobs: echo "VIRUSTOTAL_API_KEY is not set. Exiting workflow." exit 1 fi - echo "VIRUSTOTAL_API_KEY is set. Proceeding with the workflow. + echo "VIRUSTOTAL_API_KEY is set. Proceeding with the workflow." - uses: actions/checkout@v4 diff --git a/.github/workflows/ci-pwsh7_2.yml b/.github/workflows/ci-pwsh7_2.yml deleted file mode 100644 index 2c8a2b3af..000000000 --- a/.github/workflows/ci-pwsh7_2.yml +++ /dev/null @@ -1,79 +0,0 @@ -name: Pode CI - pwsh 7.2 - -on: - push: - branches: - - '*' - - '!gh-pages' - paths: - - 'src/**' - - 'tests/**' - - 'pode.build.ps1' - - '.github/workflows/ci-pwsh7_2.yml' - - 'Dockerfile' - - '*.dockerfile' - pull_request: - branches: - - '*' - paths: - - 'src/**' - - 'tests/**' - - 'pode.build.ps1' - - '.github/workflows/ci-pwsh7_2.yml' - - 'Dockerfile' - - '*.dockerfile' - -env: - INVOKE_BUILD_VERSION: '5.12.0' - POWERSHELL_VERSION: '7.2.24' - -jobs: - build: - runs-on: ${{ matrix.os }} - - strategy: - fail-fast: false - matrix: - os: [ubuntu-latest, windows-latest, macOS-latest] - - steps: - - uses: actions/checkout@v4 - - - name: Setup .NET - uses: actions/setup-dotnet@v4 - with: - dotnet-version: 9.x - - - name: Setup Powershell - Unix - shell: pwsh - if: runner.os == 'Linux' || runner.os == 'macOS' - run: | - Install-Module -Name InvokeBuild -RequiredVersion $env:INVOKE_BUILD_VERSION -Force - Invoke-Build SetupPowerShell -PowerShellVersion $env:POWERSHELL_VERSION - - - name: Setup Powershell - Windows - shell: PowerShell - if: runner.os == 'Windows' - run: | - Install-Module -Name InvokeBuild -RequiredVersion $env:INVOKE_BUILD_VERSION -Force - Invoke-Build SetupPowerShell -PowerShellVersion $env:POWERSHELL_VERSION - - - name: Output PowerShell version - shell: pwsh - run: | - $PSVersionTable.PSVersion - - - name: Install Invoke-Build - shell: pwsh - run: | - Install-Module -Name InvokeBuild -RequiredVersion $env:INVOKE_BUILD_VERSION -Force - - - name: Run Pester Tests - shell: pwsh - run: | - Invoke-Build Test - - - name: Build Packages - shell: pwsh - run: | - Invoke-Build Pack \ No newline at end of file diff --git a/alpine.dockerfile b/alpine.dockerfile index dd0af2ba8..0e218ee43 100644 --- a/alpine.dockerfile +++ b/alpine.dockerfile @@ -1,4 +1,4 @@ -FROM mcr.microsoft.com/powershell:7.4-alpine-3.17 +FROM mcr.microsoft.com/powershell:7.4-alpine-3.20 LABEL maintainer="Matthew Kelly (Badgerati)" RUN mkdir -p /usr/local/share/powershell/Modules/Pode COPY ./pkg/ /usr/local/share/powershell/Modules/Pode \ No newline at end of file diff --git a/pode.build.ps1 b/pode.build.ps1 index e2b67f2bd..bcbed0ed9 100644 --- a/pode.build.ps1 +++ b/pode.build.ps1 @@ -34,13 +34,11 @@ - StampVersion: Stamps the specified version onto the module. - PrintChecksum: Generates and displays a checksum of the ZIP archive. - ChocoDeps: Installs Chocolatey (for Windows). - - PackDeps: Installs dependencies required for packaging. - BuildDeps: Installs dependencies required for building/compiling. - TestDeps: Installs dependencies required for testing. - DocsDeps: Installs dependencies required for documentation generation. - IndexSamples: Indexes sample files for documentation. - Build: Builds the .NET Listener for specified frameworks. - - 7Zip: Creates a ZIP archive of the module (Windows only). - DeliverableFolder: Creates a folder for deliverables. - Compress: Compresses the module into a ZIP format for distribution. - ChocoPack: Creates a Chocolatey package of the module (Windows only). @@ -119,7 +117,6 @@ $Versions = @{ Pester = '5.6.1' MkDocs = '1.6.1' PSCoveralls = '1.0.0' - SevenZip = '18.5.0.20180730' DotNet = $SdkVersion MkDocsTheme = '9.5.44' PlatyPS = '0.14.2' @@ -379,17 +376,17 @@ function Install-PodeBuildModule($name) { Converts a .NET target framework identifier to a numeric version. .DESCRIPTION - This function maps common .NET target framework identifiers (e.g., 'netstandard2.0', 'net6.0') to their + This function maps common .NET target framework identifiers (e.g., 'netstandard2.0', 'net9.0') to their numeric equivalents. It is used to ensure compatibility by returning the framework version number as an integer. .PARAMETER TargetFrameworks - The target framework identifier (e.g., 'netstandard2.0', 'net6.0'). + The target framework identifier (e.g., 'netstandard2.0', 'net9.0'). .OUTPUTS [int] - The numeric version of the target framework. Defaults to 2 if an unrecognized framework is provided. .EXAMPLE - $version = Get-PodeTargetFramework -TargetFrameworks 'net6.0' + $version = Get-PodeBuildTargetFramework -TargetFrameworks 'net9.0' Write-Host "Target framework version: $version" # Output: Target framework version: 6 @@ -397,7 +394,7 @@ function Install-PodeBuildModule($name) { - Returns 2 (netstandard2.0) by default if the input framework is not recognized. - This function is useful in build scripts that require target framework versioning. #> -function Get-PodeTargetFramework { +function Get-PodeBuildTargetFramework { param( [string] $TargetFrameworks @@ -409,7 +406,7 @@ function Get-PodeTargetFramework { 'net9.0' { return 9 } 'net10.0' { return 10 } default { - Write-Warning "$TargetFrameworks is not a valid Framework. Rollback to netstandard2.0" + Write-Warning "$TargetFrameworks is not a valid Framework. Rollback to netstandard2.0" return 2 } } @@ -430,29 +427,26 @@ function Get-PodeTargetFramework { [string] - The target framework identifier (e.g., 'netstandard2.0'). .EXAMPLE - $frameworkName = Get-PodeTargetFrameworkName -Version 6 + $frameworkName = Get-PodeBuildTargetFrameworkName -Version 9 Write-Host "Target framework name: $frameworkName" - # Output: Target framework name: net6.0 + # Output: Target framework name: net9.0 .NOTES - Returns 'netstandard2.0' by default if an unrecognized version is provided. - Useful for converting numeric framework versions to identifier strings in build processes. #> -function Get-PodeTargetFrameworkName { +function Get-PodeBuildTargetFrameworkName { param( $Version ) switch ( $Version) { '2' { return 'netstandard2.0' } - '3' { return 'netstandard2.1' } - '5' { return 'net5.0' } - '6' { return 'net6.0' } - '7' { return 'net7.0' } '8' { return 'net8.0' } '9' { return 'net9.0' } + '10' { return 'net10.0' } default { - Write-Warning "$Version is not a valid Framework. Rollback to netstandard2.0" + Write-Warning "$Version is not a valid Framework. Rollback to netstandard2.0" return 'netstandard2.0' } } @@ -469,7 +463,7 @@ function Invoke-PodeBuildDotnetBuild { $majorVersions = $sdkVersions | ForEach-Object { ([version]$_).Major } | Sort-Object -Descending | Select-Object -Unique } else { - $majorVersions = $sdkVersions.Where( { ([version]$_).Major -ge (Get-PodeTargetFramework -TargetFrameworks $AvailableSdkVersion) } ) | Sort-Object -Descending | Select-Object -Unique + $majorVersions = $sdkVersions.Where( { ([version]$_).Major -ge (Get-PodeBuildTargetFramework -TargetFrameworks $AvailableSdkVersion) } ) | Sort-Object -Descending | Select-Object -Unique } # Map target frameworks to minimum SDK versions @@ -477,7 +471,7 @@ function Invoke-PodeBuildDotnetBuild { Write-Error "The requested '$AvailableSdkVersion' framework is not available." return } - $requiredSdkVersion = Get-PodeTargetFramework -TargetFrameworks $target + $requiredSdkVersion = Get-PodeBuildTargetFramework -TargetFrameworks $target # Determine if the target framework is compatible $isCompatible = $majorVersions -ge $requiredSdkVersion @@ -913,12 +907,10 @@ Add-BuildTask Default { Write-Host '- StampVersion: Stamps the specified version onto the module.' Write-Host '- PrintChecksum: Generates and displays a checksum of the ZIP archive.' Write-Host '- ChocoDeps: Installs Chocolatey (for Windows).' - Write-Host '- PackDeps: Installs dependencies required for packaging.' Write-Host '- BuildDeps: Installs dependencies required for building/compiling.' Write-Host '- TestDeps: Installs dependencies required for testing.' Write-Host '- DocsDeps: Installs dependencies required for documentation generation.' Write-Host '- IndexSamples: Indexes sample files for documentation.' - Write-Host '- 7Zip: Creates a ZIP archive of the module (Windows only).' Write-Host '- DeliverableFolder: Creates a folder for deliverables.' Write-Host '- Compress: Compresses the module into a ZIP format for distribution.' Write-Host '- ChocoPack: Creates a Chocolatey package of the module (Windows only).' @@ -970,13 +962,6 @@ Add-BuildTask ChocoDeps -If (Test-PodeBuildIsWindows) { } } -# Synopsis: Install dependencies for packaging -Add-BuildTask PackDeps -If (Test-PodeBuildIsWindows) ChocoDeps, { - if (!(Test-PodeBuildCommand '7z')) { - Invoke-PodeBuildInstall '7zip' $Versions.SevenZip - } -} - # Synopsis: Install dependencies for compiling/building Add-BuildTask BuildDeps { # install dotnet @@ -998,20 +983,20 @@ Add-BuildTask BuildDeps { $sdkVersions = dotnet --list-sdks | ForEach-Object { $_.Split('[')[0].Trim() } } $majorVersions = ($sdkVersions | ForEach-Object { ([version]$_).Major } | Sort-Object -Descending | Select-Object -Unique)[0] - $script:AvailableSdkVersion = Get-PodeTargetFrameworkName -Version $majorVersions + $script:AvailableSdkVersion = Get-PodeBuildTargetFrameworkName -Version $majorVersions - if ($majorVersions -lt (Get-PodeTargetFramework -TargetFrameworks $SdkVersion)) { + if ($majorVersions -lt (Get-PodeBuildTargetFramework -TargetFrameworks $SdkVersion)) { Invoke-PodeBuildInstall $dotnet $SdkVersion $sdkVersions = dotnet --list-sdks | ForEach-Object { $_.Split('[')[0].Trim() } $majorVersions = ($sdkVersions | ForEach-Object { ([version]$_).Major } | Sort-Object -Descending | Select-Object -Unique)[0] - $script:AvailableSdkVersion = Get-PodeTargetFrameworkName -Version $majorVersions + $script:AvailableSdkVersion = Get-PodeBuildTargetFrameworkName -Version $majorVersions - if ($majorVersions -lt (Get-PodeTargetFramework -TargetFrameworks $SdkVersion)) { + if ($majorVersions -lt (Get-PodeBuildTargetFramework -TargetFrameworks $SdkVersion)) { Write-Error "The requested framework '$SdkVersion' is not available." return } } - elseif ($majorVersions -gt (Get-PodeTargetFramework -TargetFrameworks $SdkVersion)) { + elseif ($majorVersions -gt (Get-PodeBuildTargetFramework -TargetFrameworks $SdkVersion)) { Write-Warning "The requested SDK version '$SdkVersion' is superseded by the installed '$($script:AvailableSdkVersion)' framework." } @@ -1122,11 +1107,6 @@ Add-BuildTask Build BuildDeps, { # Packaging #> -# Synopsis: Creates a Zip of the Module -Add-BuildTask 7Zip -If (Test-PodeBuildIsWindows) PackDeps, StampVersion, { - exec { & 7z -tzip a $Version-Binaries.zip ./pkg/* } -}, PrintChecksum - #Synopsis: Create the Deliverable folder Add-BuildTask DeliverableFolder { $path = './deliverable' @@ -1150,7 +1130,7 @@ Add-BuildTask Compress PackageFolder, StampVersion, DeliverableFolder, { }, PrintChecksum # Synopsis: Creates a Chocolately package of the Module -Add-BuildTask ChocoPack -If (Test-PodeBuildIsWindows) PackDeps, PackageFolder, StampVersion, DeliverableFolder, { +Add-BuildTask ChocoPack -If (Test-PodeBuildIsWindows) ChocoDeps, PackageFolder, StampVersion, DeliverableFolder, { exec { choco pack ./packers/choco/pode.nuspec } Move-Item -Path "pode.$Version.nupkg" -Destination './deliverable' } diff --git a/src/Listener/Pode.csproj b/src/Listener/Pode.csproj index 0505565c6..b5fa8da40 100644 --- a/src/Listener/Pode.csproj +++ b/src/Listener/Pode.csproj @@ -1,30 +1,10 @@ - netstandard2.0;netstandard2.1 + netstandard2.0 $(NoWarn);SYSLIB0001 7.3 - - $(TargetFrameworks);netcoreapp3.1 - - - - $(TargetFrameworks);net5.0 - - - - $(TargetFrameworks);net6.0 - - - - $(TargetFrameworks);net7.0 - - - - $(TargetFrameworks);net8.0 - - $(TargetFrameworks);net9.0 From 0de7cd23f0988a16f1f2d29c9af143ae83887cfc Mon Sep 17 00:00:00 2001 From: Matthew Kelly Date: Sat, 23 Nov 2024 12:56:32 +0000 Subject: [PATCH 25/25] didnt mean to remove net8 --- src/Listener/Pode.csproj | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/Listener/Pode.csproj b/src/Listener/Pode.csproj index b5fa8da40..782ad8b1b 100644 --- a/src/Listener/Pode.csproj +++ b/src/Listener/Pode.csproj @@ -5,6 +5,10 @@ 7.3 + + $(TargetFrameworks);net8.0 + + $(TargetFrameworks);net9.0