LeetABit.Build.psm1
#requires -version 6 using namespace System.Collections using namespace System.Collections.Generic using namespace Microsoft.PowerShell.Commands using module LeetABit.Build.Common using module LeetABit.Build.Extensibility Set-StrictMode -Version 3.0 Import-LocalizedData -BindingVariable LocalizedData -FileName LeetABit.Build.Resources.psd1 $MyInvocation.MyCommand.ScriptBlock.Module.OnRemove = { Remove-Module LeetABit.Build.* -Force } ################################################################################################################## # Public Commands ################################################################################################################## function Build-Repository { <# .SYNOPSIS Performs a build operation on all projects located in the specified repository. .DESCRIPTION Build-Repository cmdlet runs project resolution for all registered extensions against specified repository root directory. And then run specified task for all projects and its extensions. .EXAMPLE PS> Build-Repository '~/repository' 'help' Runs a help task for all extensions that supports it using no additional arguments. .EXAMPLE PS> Build-Repository '~/repository' 'build' -ExtensionModule @{ModuleName = "PowerShell"; ModuleVersion = "1.0.0"} Loads "PowerShell" extension and runs a build task for all extensions that supports it using no additional arguments. .EXAMPLE PS> Build-Repository '~/repository' -NamedArguments @{ 'CompilerVersion' = '1.0.0' } -UnknownArguments ("-Debug") Runs a default build task for all extensions that supports it using specified additional arguments. #> [CmdletBinding(PositionalBinding = $False)] param ( # The path to the repository root folder. [Parameter(HelpMessage = "Provide path to the repository's root directory.", Position = 0, Mandatory = $True, ValueFromPipeline = $False, ValueFromPipelineByPropertyName = $True)] [ValidateContainerPathAttribute()] [String] $RepositoryRoot, # Name of the build task to invoke. [Parameter(Position = 1, Mandatory = $True, ValueFromPipeline = $False, ValueFromPipelineByPropertyName = $True)] [ValidateIdentifierOrEmptyAttribute()] [AllowEmptyString()] [AllowEmptyCollection()] [String[]] $TaskName, # Extension modules to import. [Parameter(Mandatory = $False, ValueFromPipeline = $False, ValueFromPipelineByPropertyName = $True)] [AllowNull()] [AllowEmptyCollection()] [ModuleSpecification[]] $ExtensionModule, # Dictionary of buildstrapper arguments (including dynamic ones) that have been successfully bound. [Parameter(Mandatory = $False, ValueFromPipeline = $False, ValueFromPipelineByPropertyName = $True)] [IDictionary] $NamedArguments, # Arguments to be passed to the target. [Parameter(Mandatory = $False, ValueFromPipeline = $False, ValueFromPipelineByPropertyName = $True)] [String[]] $UnknownArguments) begin { LeetABit.Build.Common\Import-CallerPreference -Cmdlet $PSCmdlet -SessionState $ExecutionContext.SessionState } process { LeetABit.Build.Logging\Write-Invocation -Invocation $MyInvocation LeetABit.Build.Arguments\Set-CommandArgumentSet -RepositoryRoot $RepositoryRoot -NamedArguments $NamedArguments -UnknownArguments $UnknownArguments Initialize-WellKnownParameters -RepositoryRoot $RepositoryRoot -ExtensionModule $ExtensionModule $ExtensionModule = LeetABit.Build.Arguments\Find-CommandArgument -ParameterName 'ExtensionModule' if ($ExtensionModule) { $ExtensionModule | ForEach-Object { if (-not (Get-Module -FullyQualifiedName @{ ModuleName="$($_.Name)"; ModuleVersion=$_.RequiredVersion } -ListAvailable)) { Write-Verbose "Installing $($_.Name) v$($_.RequiredVersion) from the available PowerShell repositories..." Install-Module -Name $_.Name -RequiredVersion $_.RequiredVersion -Scope CurrentUser -AllowPrerelease -Force } } Import-Module -FullyQualifiedName $ExtensionModule } Import-RepositoryExtension -RepositoryRoot $RepositoryRoot $TaskName = LeetABit.Build.Arguments\Find-CommandArgument -ParameterName 'TaskName' -DefaultValue $TaskName $SourceRoot = LeetABit.Build.Arguments\Find-CommandArgument -ParameterName 'SourceRoot' $projectPath = $SourceRoot $lastExtension = $Null $aggregatedProjects = @() LeetABit.Build.Extensibility\Resolve-Project $projectPath 'LeetABit.Build.Repository' $TaskName | Select-Object -Unique | ForEach-Object { $projectPath, $extensionName = $_ if ($lastExtension -and $lastExtension -ne $extensionName) { LeetABit.Build.Extensibility\Invoke-BuildTask $lastExtension $TaskName $aggregatedProjects $SourceRoot $aggregatedProjects = @() } $lastExtension = $extensionName $aggregatedProjects += $projectPath } if ($lastExtension) { LeetABit.Build.Extensibility\Invoke-BuildTask $lastExtension $TaskName $aggregatedProjects $SourceRoot } } } ################################################################################################################## # Private Commands ################################################################################################################## function Initialize-WellKnownParameters { <# .SYNOPSIS Initializes a set of well known parameters with its default values. #> [CmdletBinding(PositionalBinding = $False)] param ( # The directory to the repository's root directory path. [Parameter(HelpMessage = "Provide path to the repository's root directory.", Position = 0, Mandatory = $True, ValueFromPipeline = $False, ValueFromPipelineByPropertyName = $False)] [String] $RepositoryRoot, # Collection fo extension modules to import. [Parameter(Mandatory = $False, ValueFromPipeline = $False, ValueFromPipelineByPropertyName = $False)] [AllowNull()] [AllowEmptyCollection()] [ModuleSpecification[]] $ExtensionModule) process { LeetABit.Build.Arguments\Add-CommandArgument 'ArtifactsRoot' (Join-Path $RepositoryRoot 'artifacts') -ErrorAction SilentlyContinue LeetABit.Build.Arguments\Add-CommandArgument 'SourceRoot' (Join-Path $RepositoryRoot 'src') -ErrorAction SilentlyContinue LeetABit.Build.Arguments\Add-CommandArgument 'TestRoot' (Join-Path $RepositoryRoot 'test') -ErrorAction SilentlyContinue LeetABit.Build.Arguments\Add-CommandArgument 'ReferenceDocsRoot' (Join-Path -Path $RepositoryRoot -ChildPath 'docs' -AdditionalChildPath 'Reference') -ErrorAction SilentlyContinue [ModuleSpecification[]]$existingExtensionModule = LeetABit.Build.Arguments\Find-CommandArgument -ParameterName 'ExtensionModule' [ModuleSpecification[]]$uniqueExtensionModule = (($existingExtensionModule + $ExtensionModule) | Select-Object -Unique) LeetABit.Build.Arguments\Add-CommandArgument 'ExtensionModule' $uniqueExtensionModule -ErrorAction SilentlyContinue } } function Import-RepositoryExtension { <# .SYNOPSIS Executes LeetABit.Build.Repository scripts from the specified repository. #> [CmdletBinding(PositionalBinding = $False)] param ( # The directory to the repository's root directory path. [Parameter(HelpMessage = "Provide path to the repository's root directory.", Position = 0, Mandatory = $True, ValueFromPipeline = $False, ValueFromPipelineByPropertyName = $False)] [String] $RepositoryRoot) process { Get-ChildItem -Path $RepositoryRoot -Filter "LeetABit.Build.Repository.ps1" -Recurse | ForEach-Object { . "$_" } } } Export-ModuleMember -Function '*' -Variable '*' -Alias '*' -Cmdlet '*' # SIG # Begin signature block # MIIM3wYJKoZIhvcNAQcCoIIM0DCCDMwCAQExDzANBglghkgBZQMEAgEFADB5Bgor # BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG # KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCBKw+hWNDeHUVzT # MtDLiIfsvxYDmZ/9dL902aec1DGOXqCCCe0wggTeMIIDxqADAgECAhBrMmoPAyjT # eh1TC/0jvUjiMA0GCSqGSIb3DQEBCwUAMH4xCzAJBgNVBAYTAlBMMSIwIAYDVQQK # ExlVbml6ZXRvIFRlY2hub2xvZ2llcyBTLkEuMScwJQYDVQQLEx5DZXJ0dW0gQ2Vy # dGlmaWNhdGlvbiBBdXRob3JpdHkxIjAgBgNVBAMTGUNlcnR1bSBUcnVzdGVkIE5l # dHdvcmsgQ0EwHhcNMTUxMDI5MTEzMDI5WhcNMjcwNjA5MTEzMDI5WjCBgDELMAkG # A1UEBhMCUEwxIjAgBgNVBAoMGVVuaXpldG8gVGVjaG5vbG9naWVzIFMuQS4xJzAl # BgNVBAsMHkNlcnR1bSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTEkMCIGA1UEAwwb # Q2VydHVtIENvZGUgU2lnbmluZyBDQSBTSEEyMIIBIjANBgkqhkiG9w0BAQEFAAOC # AQ8AMIIBCgKCAQEAt9uo2MjjvNrag7q5v9bVV1NBt0C6FwxEldTpZjt/tL6Qo5QJ # pa0hIBeARrRDJj6OSxpk7A5AMkP8gp//Si3qlN1aETaLYe/sFtRJA9jnXcNlW/JO # CyvDwVP6QC3CqzMkBYFwfsiHTJ/RgMIYew4UvU4DQ8soSLAt5jbfGz2Lw4ydN57h # BtclUN95Pdq3X+tGvnYoNrgCAEYD0DQbeLQox1HHyJU/bo2JGNxJ8cIPGvSBgcdt # 1AR3xSGjLlP5d8/cqZvDweXVZy8xvMDCaJxKluUf8fNINQ725LHF74eAOuKADDSd # +hRkceQcoaqyzwCn4zdy+UCtniiVAg3OkONbxQIDAQABo4IBUzCCAU8wDwYDVR0T # AQH/BAUwAwEB/zAdBgNVHQ4EFgQUwHu0yLduVqcJSJr4ck/X1yQsNj4wHwYDVR0j # BBgwFoAUCHbNywf/JPbFze27kLzihDdGdfcwDgYDVR0PAQH/BAQDAgEGMBMGA1Ud # JQQMMAoGCCsGAQUFBwMDMC8GA1UdHwQoMCYwJKAioCCGHmh0dHA6Ly9jcmwuY2Vy # dHVtLnBsL2N0bmNhLmNybDBrBggrBgEFBQcBAQRfMF0wKAYIKwYBBQUHMAGGHGh0 # dHA6Ly9zdWJjYS5vY3NwLWNlcnR1bS5jb20wMQYIKwYBBQUHMAKGJWh0dHA6Ly9y # ZXBvc2l0b3J5LmNlcnR1bS5wbC9jdG5jYS5jZXIwOQYDVR0gBDIwMDAuBgRVHSAA # MCYwJAYIKwYBBQUHAgEWGGh0dHA6Ly93d3cuY2VydHVtLnBsL0NQUzANBgkqhkiG # 9w0BAQsFAAOCAQEAquU/dlQCTHAOKak5lgYPMbcL8aaLUvsQj09CW4y9MSMBZp3o # KaFNw1D69/hFDh2C1/z+pjIEc/1x7MyID6OSCMWBWAL9C2k7zbg/ST3QjRwTFGgu # mw2arbAZ4p7SfDl3iG8j/XuE/ERttbprcJJVbJSx2Df9qVkdtGOy3BPNeI4lNcGa # jzeELtRFzOP1zI1zqOM6beeVlHBXkVC2be9zck8vAodg4uoioe0+/dGLZo0ucm1P # xl017pOomNJnaunaGc0Cg/l0/F96GAQoHt0iMzt2bEcFXdVS/g66dvODEMduMF+n # YMf6dCcxmyiD7SGKG/EjUoTtlbytOqWjQgGdvDCCBQcwggPvoAMCAQICECxWDYHo # gPTFxULdYYZu+b0wDQYJKoZIhvcNAQELBQAwgYAxCzAJBgNVBAYTAlBMMSIwIAYD # VQQKDBlVbml6ZXRvIFRlY2hub2xvZ2llcyBTLkEuMScwJQYDVQQLDB5DZXJ0dW0g # Q2VydGlmaWNhdGlvbiBBdXRob3JpdHkxJDAiBgNVBAMMG0NlcnR1bSBDb2RlIFNp # Z25pbmcgQ0EgU0hBMjAeFw0yMDAzMTgwNjMzMDdaFw0yMTAzMTgwNjMzMDdaMHAx # CzAJBgNVBAYTAlBMMRAwDgYDVQQHDAdLcmFrw7N3MR4wHAYDVQQKDBVPcGVuIFNv # dXJjZSBEZXZlbG9wZXIxLzAtBgNVBAMMJk9wZW4gU291cmNlIERldmVsb3Blciwg # SHViZXJ0IEJ1a293c2tpMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA # 3B0pw0zPe4KG0FR7q4ZrHDWpELuc3KyfaaaDkF6EXpbX5bCByq97QrQ4YJjru9UW # JK+u45hyUpiUXWPfeKHKKz3bLMCmIMaPq+FpfSh2xzB3lFnj/1LlO7htUpfKZ6Ks # FpCkrKk6ZiPs8PxXpfmoiOzxryySbcqVZr7ZEQnRKfl6Op4IKiZQ54lZOy4ORRMu # ghxlxJfK49XQ5gUrV1dRL3blFSIrfOl1K6wB0/5QxxWeO4WxHzD9WtfpSTs2/gML # fj4xe80QjaGGShpN+qtPRaa+2qEdm2Dm+Btto8Gy9eVcxUXAQNZFTZPMd2Sf71yl # whZIsqEChoTawyrnZTMwgwIDAQABo4IBijCCAYYwDAYDVR0TAQH/BAIwADAyBgNV # HR8EKzApMCegJaAjhiFodHRwOi8vY3JsLmNlcnR1bS5wbC9jc2Nhc2hhMi5jcmww # cQYIKwYBBQUHAQEEZTBjMCsGCCsGAQUFBzABhh9odHRwOi8vY3NjYXNoYTIub2Nz # cC1jZXJ0dW0uY29tMDQGCCsGAQUFBzAChihodHRwOi8vcmVwb3NpdG9yeS5jZXJ0 # dW0ucGwvY3NjYXNoYTIuY2VyMB8GA1UdIwQYMBaAFMB7tMi3blanCUia+HJP19ck # LDY+MB0GA1UdDgQWBBSqIB8Yxug7KjAkRKhvS62xLJPR1zAdBgNVHRIEFjAUgRJj # c2Nhc2hhMkBjZXJ0dW0ucGwwDgYDVR0PAQH/BAQDAgeAMEsGA1UdIAREMEIwCAYG # Z4EMAQQBMDYGCyqEaAGG9ncCBQEEMCcwJQYIKwYBBQUHAgEWGWh0dHBzOi8vd3d3 # LmNlcnR1bS5wbC9DUFMwEwYDVR0lBAwwCgYIKwYBBQUHAwMwDQYJKoZIhvcNAQEL # BQADggEBAKkWEKsxeIDC+mcLz+zJgNkK+eXZR1sEueM5LcK7iDzWPG8pPOfrKJMH # v67m3XG1PYy54Qn3AHGIZzXPF+HgIatkEFE931TUTjUFhuTuiEtKft+gsZgEyCXG # Km2e5fYiaBRUAtvQKPpDrocSazIP92x+blTaIKM1Z+Ysx/2YTwkpyMclviK7OisV # JHzbKmxgLxhatMwCPtLbFuAUffDxG8igXstCbQ3Qoa4qj2HldQy4HVCYDfdA3PcV # 9LGXPpCKGeSFCGekSdZW2f61xATc0mCpfECVTUQBJL4taNCeR219IfX20ETo+zH6 # epfSds5WtOnY/9uzFR6jLNtAx3IVrQwxggJIMIICRAIBATCBlTCBgDELMAkGA1UE # BhMCUEwxIjAgBgNVBAoMGVVuaXpldG8gVGVjaG5vbG9naWVzIFMuQS4xJzAlBgNV # BAsMHkNlcnR1bSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTEkMCIGA1UEAwwbQ2Vy # dHVtIENvZGUgU2lnbmluZyBDQSBTSEEyAhAsVg2B6ID0xcVC3WGGbvm9MA0GCWCG # SAFlAwQCAQUAoIGEMBgGCisGAQQBgjcCAQwxCjAIoAKAAKECgAAwGQYJKoZIhvcN # AQkDMQwGCisGAQQBgjcCAQQwHAYKKwYBBAGCNwIBCzEOMAwGCisGAQQBgjcCARUw # LwYJKoZIhvcNAQkEMSIEILDo0o2kPBNplMQon7kI3M/I0QGhXFLwqjjXc+Y21gxT # MA0GCSqGSIb3DQEBAQUABIIBAHMisod/6htEjD4qXu9DK/CvxO1nVg3OGU+Yqo9z # A5uv2fa4qCjOnHeMAxkK3qBgIlwJVJLTSNwpomiiJ51vo856vYPV8NoQUG5jvglI # VngY9nUExt3UFRsQoHPupr9N6sKmK6mnUKfI4DhD+M0/brt+qvwtp16eRd9vWEhd # +e+qq2lUswCggDyKChJXTjmGAEfn13bMRziGWJ0YqPUl+oHCyhJ83xqrPZQXfY6H # exblO7DQAnrnzYkQIUgbWHpyCUMLLKjxSds/L9yuiGE/vnihk6yeSgmZ6kJQm5ip # r6OzpR10CCIbmHbWehFKWOu6XvN7lPgjwLjOcXgSYsYbvmU= # SIG # End signature block |