ps/Modules/build-solution.ps1

190 lines
6.3 KiB
PowerShell
Raw Permalink Normal View History

2023-05-30 22:51:22 -07:00
<#
.SYNOPSIS
Builds the Alkami.PowerShell module system
.EXAMPLE
.\build-solution.ps1
.PARAMETER Configuration
The MSBuild build configuration to use. Typically Release or Debug
.PARAMETER CleanFirst
Should MSBuild clean the project first?
.PARAMETER AsBuildServer
Run the tests on a developer machine as a build server
.PARAMETER WithTests
Run tests after the build
.PARAMETER WithAnalyzer
Run PSScriptAnalyzer on the project
.PARAMETER Fast
Run with the least options possible
.PARAMETER Full
Run with the most options possible
#>
[CmdletBinding()]
Param(
$Configuration = "Release",
[switch]$CleanFirst,
[switch]$AsBuildServer,
[switch]$WithTests,
[switch]$WithAnalyzer,
[switch]$Fast,
[switch]$Full
)
if ($Fast) {
$WithTests = $false
$WithAnalyzer = $false
$Full = $false
}
if ($Full) {
$WithTests = $true
$WithAnalyzer = $true
}
. $PSScriptRoot\.build\Load-Includes.ps1
$AsBuildServer = $AsBuildServer -or (Test-IsTeamCityProcess)
Function Get-ProjectsAndDependencies {
$projectlist = New-Object PsObject @{ }
$projectlist["Carbon"] = New-Object PsObject @{ ProjectId = "Carbon"; ModuleVersion = "2.5.0"; RequiredModules = @(); }
$psdList = Get-ChildItem -Path $PSScriptRoot *.psd1 -recurse
foreach ($file in $psdList) {
$projectId = $file.BaseName
$capturePSDasVariable = Import-PowerShellDataFile -Path $file.FullName
$requiredModules = @($capturePSDasVariable.RequiredModules)
$moduleVersion = $capturePSDasVariable.ModuleVersion
$projectlist[$projectId] = New-Object PsObject @{ ProjectId = $projectId; ModuleVersion = $moduleVersion; RequiredModules = $requiredModules }
}
return $projectlist
}
Function Get-XmlWriterSettings {
$xmlsettings = New-Object System.Xml.XmlWriterSettings
$xmlsettings.Indent = $true
$xmlsettings.IndentChars = "`t"
return $xmlsettings
}
# We don't run this locally.
if ($AsBuildServer) {
## Gather the latest version and required dependencies from all modules.
$projectList = (Get-ProjectsAndDependencies)
$xmlsettings = (Get-XmlWriterSettings)
$nuspeclist = (Get-ChildItem *.nuspec -recurse)
foreach ($file in $nuspeclist) {
## If there is no psd1 in this folder, don't change anything
if (!(Get-ChildItem -Path $file.Parent.FullName *.psd1 -Recurse)) {
Write-Host "No PSD1 found in [$($file.Parent.FullName)]"
continue
}
## Don't muck with the global object
$myProjectList = $projectlist.Clone()
$xml = [Xml](Get-Content $file)
$projectName = $xml.package.metadata.id
if ($null -ne $xml.package.metadata.dependencies) {
foreach ($dependency in $xml.package.metadata.dependencies) {
## If the dependency isn't Alkami centric (example: Carbon) then we will just be keeping it
if (($null -ne $dependency) -and ($null -ne $dependency.id) -and ($dependency.id -notmatch 'Alkami') -and !($myProjectList.ContainsKey($dependency.id))) {
$projectId = $dependency.id
$moduleVersion = $dependency.version
$myProjectlist[$projectId] = New-Object PsObject -Properties @{ ProjectId = $projectId; ModuleVersion = $moduleVersion; RequiredModules = @() }
## Add this item to the tree
$myProjectList[$projectName].RequiredModules += $projectId
}
}
}
$myDependencies = $myProjectList[$projectName].RequiredModules | Sort-Object
if (!!($xml.GetElementsByTagName("dependencies"))[0]) {
($xml.package.metadata.RemoveChild(($xml.GetElementsByTagName("dependencies"))[0])) | Out-Null
}
$dependencyList = $xml.CreateElement("dependencies")
## Write out all of the dependencies of this project
foreach ($dependencyId in $myDependencies) {
$dependency = $myProjectlist[$dependencyId]
## Create required dependencies with the latest version of the module in the current branch
if ($dependency) {
$node = $xml.CreateElement("dependency")
($node.SetAttribute("id", $dependency.ProjectId)) | Out-Null
($node.SetAttribute("version", $dependency.ModuleVersion)) | Out-Null
}
if ($null -ne $node) {
($dependencyList.AppendChild($node)) | Out-Null
}
}
($xml.package.metadata.AppendChild($dependencyList)) | Out-Null
$sb = [System.Text.StringBuilder]::new()
$writer = [System.Xml.XmlWriter]::Create($sb, $xmlSettings)
## Update the actual XML element with the values in the XmlWriter
($xml.Save($writer)) | Out-Null
## Save the content of the XML file back to disk where we found the original one.
(Set-Content -Value $sb.ToString() -Path $file.FullName) | Out-Null
}
}
Function Get-AnalyzerResults {
Param(
$FolderPath
)
process {
$failingResults = @()
$folderTypes = @('Public','Private')
foreach ($folderType in $folderTypes) {
if (Test-Path (Join-Path $FolderPath $folderType)) {
$testFiles = (Get-ChildItem -Path (Join-Path $FolderPath $folderType) "*.ps1" -recurse)
foreach ($file in $testFiles) {
Write-Verbose "Analyzing $file"
$reportSummary = Invoke-ScriptAnalyzer $file.FullName -Severity Error,Warning
if (!!($reportSummary)) {
$failingResults += New-Object PSObject -Property @{ Filename = $file.FullName; TestResult = $null; Analyzer = $reportSummary; }
}
}
}
}
return $failingResults
}
}
$results = @()
(Get-ChildItem $PSScriptRoot -Directory) | ForEach-Object {
$FolderPath = $_.FullName;
& $PSScriptRoot\build-project.ps1 $FolderPath $Configuration -CleanFirst:$CleanFirst -AsBuildServer:$AsBuildServer
if ($WithAnalyzer) {
$results += Get-AnalyzerResults $FolderPath
}
}
## TeamCity does something else here
## This is intended to only run if we're in development
if ($WithTests) {
$results += .\test-solution.ps1 -NoAnalyzer
}
if ($WithAnalyzer -or $WithTests) {
return $results
}