From 4e2a651feb9d0928ea183accb0f21ac700d5e7ad Mon Sep 17 00:00:00 2001 From: Joel Bennett Date: Thu, 19 Dec 2019 18:23:44 -0500 Subject: [PATCH 01/17] Update tests so they work better in VSCode Addresses #6 by adding coverage.xml when you run test.ps1 --- .vscode/tasks.json | 15 +++---- Tests/Private/ConvertToAst.Tests.ps1 | 2 +- Tests/Private/CopyReadMe.Tests.ps1 | 2 +- Tests/Private/GetBuildInfo.Tests.ps1 | 2 +- Tests/Private/GetCommandAlias.Tests.ps1 | 2 +- Tests/Private/InitializeBuild.Tests.ps1 | 2 +- Tests/Private/ParseLineNumber.Tests.ps1 | 4 +- Tests/Private/ResolveBuildManifest.Tests.ps1 | 2 +- Tests/Private/ResolveOutputFolder.Tests.ps1 | 2 +- Tests/Public/Convert-LineNumber.Tests.ps1 | 2 +- build.ps1 | 6 +-- test.ps1 | 44 ++++++++++++++++++++ 12 files changed, 61 insertions(+), 24 deletions(-) create mode 100644 test.ps1 diff --git a/.vscode/tasks.json b/.vscode/tasks.json index 3eff2c7..34b19b8 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -10,7 +10,10 @@ "isDefault": true }, "type": "shell", - "command": "${workspaceFolder}\\build.ps1", + "command": "${workspaceFolder}/build.ps1", + "options": { + "cwd": "${workspaceFolder}" + }, "presentation": { "echo": true, "reveal": "silent", @@ -27,18 +30,10 @@ "isDefault": true }, "type": "shell", + "command": "${workspaceFolder}/test.ps1", "options": { "cwd": "${workspaceFolder}", - "env": { - "PSModulePath": "${workspaceFolder}\\Output;${env:PSModulePath}" - } }, - "command": "Invoke-Pester", - "args": [ - "${workspaceFolder}\\Tests", - "-PesterOption", "@{ IncludeVSCodeMarker = $True }", - "-CodeCoverage", "${workspaceFolder}\\Output\\*.psm1" - ], "presentation": { "echo": true, "reveal": "always", diff --git a/Tests/Private/ConvertToAst.Tests.ps1 b/Tests/Private/ConvertToAst.Tests.ps1 index 0715b8f..5ccca7e 100644 --- a/Tests/Private/ConvertToAst.Tests.ps1 +++ b/Tests/Private/ConvertToAst.Tests.ps1 @@ -1,5 +1,5 @@ +#requires -Module ModuleBuilder Describe "ConvertToAst" { - Import-Module ModuleBuilder -DisableNameChecking -Verbose:$False Context "It returns a ParseResult for file paths" { $ParseResult = InModuleScope ModuleBuilder { diff --git a/Tests/Private/CopyReadMe.Tests.ps1 b/Tests/Private/CopyReadMe.Tests.ps1 index 35e7c50..b72bc71 100644 --- a/Tests/Private/CopyReadMe.Tests.ps1 +++ b/Tests/Private/CopyReadMe.Tests.ps1 @@ -1,6 +1,6 @@ +#requires -Module ModuleBuilder Describe "Copy ReadMe" { . $PSScriptRoot\..\Convert-FolderSeparator.ps1 - Import-Module ModuleBuilder -DisableNameChecking -Verbose:$False Context "There's no ReadMe" { # It should not even call Test-Path diff --git a/Tests/Private/GetBuildInfo.Tests.ps1 b/Tests/Private/GetBuildInfo.Tests.ps1 index 7df8dde..4ef5ae5 100644 --- a/Tests/Private/GetBuildInfo.Tests.ps1 +++ b/Tests/Private/GetBuildInfo.Tests.ps1 @@ -1,6 +1,6 @@ +#requires -Module ModuleBuilder Describe "GetBuildInfo" { . $PSScriptRoot\..\Convert-FolderSeparator.ps1 - Import-Module ModuleBuilder -DisableNameChecking -Verbose:$False Mock Import-Metadata -ModuleName ModuleBuilder { @{ diff --git a/Tests/Private/GetCommandAlias.Tests.ps1 b/Tests/Private/GetCommandAlias.Tests.ps1 index 422cc97..9e54b55 100644 --- a/Tests/Private/GetCommandAlias.Tests.ps1 +++ b/Tests/Private/GetCommandAlias.Tests.ps1 @@ -1,5 +1,5 @@ +#requires -Module ModuleBuilder Describe "GetCommandAlias" { - Import-Module ModuleBuilder -DisableNameChecking -Verbose:$False Context "Mandatory Parameter" { $CommandInfo = InModuleScope ModuleBuilder { Get-Command GetCommandAlias } diff --git a/Tests/Private/InitializeBuild.Tests.ps1 b/Tests/Private/InitializeBuild.Tests.ps1 index 131ab91..ab5775b 100644 --- a/Tests/Private/InitializeBuild.Tests.ps1 +++ b/Tests/Private/InitializeBuild.Tests.ps1 @@ -1,6 +1,6 @@ +#requires -Module ModuleBuilder Describe "InitializeBuild" { . $PSScriptRoot\..\Convert-FolderSeparator.ps1 - Import-Module ModuleBuilder -DisableNameChecking -Verbose:$False Context "It collects the initial data" { diff --git a/Tests/Private/ParseLineNumber.Tests.ps1 b/Tests/Private/ParseLineNumber.Tests.ps1 index e40c8a7..40fa5f2 100644 --- a/Tests/Private/ParseLineNumber.Tests.ps1 +++ b/Tests/Private/ParseLineNumber.Tests.ps1 @@ -1,5 +1,5 @@ +#requires -Module ModuleBuilder Describe "ParseLineNumber" { - Import-Module ModuleBuilder -DisableNameChecking -Verbose:$False It 'Should get the SourceFile and LineNumber from stack trace messages with modules' { $Source = InModuleScope ModuleBuilder { ParseLineNumber "at Test-Throw, C:\Test\Path\Modules\ErrorMaker\ErrorMaker.psm1: line 27" } @@ -60,4 +60,4 @@ Describe "ParseLineNumber" { $Source.SourceLineNumber | Should -Be 207 $Source.InvocationBlock | Should -Be "ItImpl" } -} \ No newline at end of file +} diff --git a/Tests/Private/ResolveBuildManifest.Tests.ps1 b/Tests/Private/ResolveBuildManifest.Tests.ps1 index 936e005..c797c4d 100644 --- a/Tests/Private/ResolveBuildManifest.Tests.ps1 +++ b/Tests/Private/ResolveBuildManifest.Tests.ps1 @@ -1,5 +1,5 @@ +#requires -Module ModuleBuilder Describe "ResolveBuildManifest" { - Import-Module ModuleBuilder -DisableNameChecking -Verbose:$False [string]${Global:Test Root Path} = Resolve-Path $PSScriptRoot\..\..\Source diff --git a/Tests/Private/ResolveOutputFolder.Tests.ps1 b/Tests/Private/ResolveOutputFolder.Tests.ps1 index 3d9a16e..510185f 100644 --- a/Tests/Private/ResolveOutputFolder.Tests.ps1 +++ b/Tests/Private/ResolveOutputFolder.Tests.ps1 @@ -1,5 +1,5 @@ +#requires -Module ModuleBuilder Describe "ResolveOutputFolder" { - Import-Module ModuleBuilder -DisableNameChecking -Verbose:$False Context "Given an OutputDirectory and ModuleBase" { diff --git a/Tests/Public/Convert-LineNumber.Tests.ps1 b/Tests/Public/Convert-LineNumber.Tests.ps1 index f4b662e..8a9b375 100644 --- a/Tests/Public/Convert-LineNumber.Tests.ps1 +++ b/Tests/Public/Convert-LineNumber.Tests.ps1 @@ -1,5 +1,5 @@ +#requires -Module ModuleBuilder Describe "Convert-LineNumber" { - Import-Module ModuleBuilder -DisableNameChecking -Verbose:$False $ModulePath = Join-Path (Get-Module ModuleBuilder).ModuleBase ModuleBuilder.psm1 $ModuleContent = Get-Content $ModulePath diff --git a/build.ps1 b/build.ps1 index 856fd33..71b03a0 100644 --- a/build.ps1 +++ b/build.ps1 @@ -12,9 +12,10 @@ param( [Alias("ModuleVersion")] [string]$SemVer ) - # Sanitize parameters to pass to Build-Module $null = $PSBoundParameters.Remove('Test') +$ErrorActionPreference = "Stop" +Push-Location $PSScriptRoot -StackName BuildBuildModule if (-not $Semver) { if ($semver = gitversion -showvariable SemVer) { @@ -22,9 +23,6 @@ if (-not $Semver) { } } - -$ErrorActionPreference = "Stop" -Push-Location $PSScriptRoot -StackName BuildBuildModule try { # Build ModuleBuilder with ModuleBuilder: Write-Verbose "Compiling ModuleBuilderBootstrap module" diff --git a/test.ps1 b/test.ps1 new file mode 100644 index 0000000..3b81dc8 --- /dev/null +++ b/test.ps1 @@ -0,0 +1,44 @@ +#requires -Module PowerShellGet, Pester +using namespace Microsoft.PackageManagement.Provider.Utility +param( + [switch]$SkipCodeCoverage, + [switch]$HideSuccess + [switch]$IncludeVSCodeMarker +) +Push-Location $PSScriptRoot +$ModuleUnderTest = Split-Path $PSScriptRoot -Leaf + +# Disable default parameters during testing, just in case +$PSDefaultParameterValues += @{} +$PSDefaultParameterValues["Disabled"] = $true + +# Find a built module as a version-numbered folder: +$FullModulePath = Get-ChildItem [0-9]* -Directory | Sort-Object { $_.Name -as [SemanticVersion[]] } | + Select-Object -Last 1 -Ov Version | + Get-ChildItem -Filter "$($ModuleUnderTest).psd1" + + if(!$FullModulePath) { + throw "Can't find $($ModuleUnderTest).psd1 in $($Version.FullName)" + } + +$Show = if ($HideSuccess) { + "Fails" +} else { + "All" +} + +Remove-Module (Split-Path $ModuleUnderTest -Leaf) -ErrorAction Ignore -Force +$ModuleUnderTest = Import-Module $FullModulePath -PassThru -Force -DisableNameChecking -Verbose:$false +Write-Host "Invoke-Pester for Module $($ModuleUnderTest) version $($ModuleUnderTest.Version)" + +if (-not $SkipCodeCoverage) { + # Get code coverage for the psm1 file to a coverage.xml that we can mess with later + Invoke-Pester (Join-Path $PSScriptRoot Tests) -CodeCoverage $ModuleUnderTest.Path -CodeCoverageOutputFile ./coverage.xml -Show $Show -PesterOption @{ IncludeVSCodeMarker = $IncludeVSCodeMarker } +} else { + Invoke-Pester (Join-Path $PSScriptRoot Tests) -Show $Show -PesterOption @{ IncludeVSCodeMarker = $IncludeVSCodeMarker } +} + +Pop-Location + +# Re-enable default parameters after testing +$PSDefaultParameterValues["Disabled"] = $false From 9c0854599839520cf748f2c2c90a95fff8ccc6a9 Mon Sep 17 00:00:00 2001 From: Joel Bennett Date: Sat, 11 Jan 2020 01:48:42 -0500 Subject: [PATCH 02/17] Whitespace cleanup commit --- Source/Private/InitializeBuild.ps1 | 4 +-- Tests/Integration/Source1.Tests.ps1 | 1 - Tests/Public/Build-Module.Tests.ps1 | 38 ++++++++++++++--------------- 3 files changed, 21 insertions(+), 22 deletions(-) diff --git a/Source/Private/InitializeBuild.ps1 b/Source/Private/InitializeBuild.ps1 index 498411f..4f8bb7a 100644 --- a/Source/Private/InitializeBuild.ps1 +++ b/Source/Private/InitializeBuild.ps1 @@ -39,14 +39,14 @@ function InitializeBuild { $ModuleInfo = Get-Module (Get-Item $BuildInfo.ModuleManifest).FullName -ListAvailable -WarningAction SilentlyContinue -ErrorAction SilentlyContinue -ErrorVariable Problems # If there are any problems that count, fail - if ($Problems = $Problems.Where( {$_.FullyQualifiedErrorId -notmatch $ErrorsWeIgnore})) { + if ($Problems = $Problems.Where({ $_.FullyQualifiedErrorId -notmatch $ErrorsWeIgnore })) { foreach ($problem in $Problems) { Write-Error $problem } throw "Unresolvable problems in module manifest" } - # Update the ModuleManifest with our build configuration + # Update the module manifest with our build configuration $ModuleInfo = Update-Object -InputObject $ModuleInfo -UpdateObject $BuildInfo $ModuleInfo = Update-Object -InputObject $ModuleInfo -UpdateObject @{ DefaultCommandPrefix = $ModuleInfo.Prefix; Prefix = "" } diff --git a/Tests/Integration/Source1.Tests.ps1 b/Tests/Integration/Source1.Tests.ps1 index bf81127..262e9cd 100644 --- a/Tests/Integration/Source1.Tests.ps1 +++ b/Tests/Integration/Source1.Tests.ps1 @@ -80,7 +80,6 @@ Describe "Build-Module With Source1" { Context "Regression test for #84: Multiple Aliases per command will Export" { $Output = Build-Module $PSScriptRoot\Source1\build.psd1 -Passthru - $Module = [IO.Path]::ChangeExtension($Output.Path, "psm1") $Metadata = Import-Metadata $Output.Path diff --git a/Tests/Public/Build-Module.Tests.ps1 b/Tests/Public/Build-Module.Tests.ps1 index bdd5f14..82ba21a 100644 --- a/Tests/Public/Build-Module.Tests.ps1 +++ b/Tests/Public/Build-Module.Tests.ps1 @@ -76,11 +76,11 @@ Describe "Build-Module" { # These are actually all the values that we need [PSCustomObject]@{ OutputDirectory = "TestDrive:\1.0.0" - Name = "MyModule" - ModuleBase = "TestDrive:\MyModule\" + Name = "MyModule" + ModuleBase = "TestDrive:\MyModule\" CopyDirectories = @() - Encoding = "UTF8" - PublicFilter = "Public\*.ps1" + Encoding = "UTF8" + PublicFilter = "Public\*.ps1" } } @@ -162,11 +162,11 @@ Describe "Build-Module" { # These are actually all the values that we need [PSCustomObject]@{ OutputDirectory = "TestDrive:\1.0.0" - Name = "MyModule" - ModuleBase = "TestDrive:\MyModule\" + Name = "MyModule" + ModuleBase = "TestDrive:\MyModule\" CopyDirectories = @() - Encoding = "UTF8" - PublicFilter = "Public\*.ps1" + Encoding = "UTF8" + PublicFilter = "Public\*.ps1" } } @@ -227,11 +227,11 @@ Describe "Build-Module" { # These are actually all the values that we need [PSCustomObject]@{ OutputDirectory = "TestDrive:\$Version" - Name = "MyModule" - ModuleBase = "TestDrive:\MyModule\" + Name = "MyModule" + ModuleBase = "TestDrive:\MyModule\" CopyDirectories = @() - Encoding = "UTF8" - PublicFilter = "Public\*.ps1" + Encoding = "UTF8" + PublicFilter = "Public\*.ps1" } } @@ -326,8 +326,8 @@ Describe "Build-Module" { Context "Setting the version and pre-release" { # $SemVer = "1.0.0-beta03+sha.22c35ffff166f34addc49a3b80e622b543199cc5.Date.2018-10-11" $SemVer = @{ - Version = "1.0.0" - Prerelease = "beta03" + Version = "1.0.0" + Prerelease = "beta03" BuildMetadata = "Sha.22c35ffff166f34addc49a3b80e622b543199cc5.Date.2018-10-11" } $global:ExpectedVersion = "1.0.0" @@ -342,11 +342,11 @@ Describe "Build-Module" { # These are actually all the values that we need [PSCustomObject]@{ OutputDirectory = "TestDrive:\$Version" - Name = "MyModule" - ModuleBase = "TestDrive:\MyModule\" + Name = "MyModule" + ModuleBase = "TestDrive:\MyModule\" CopyDirectories = @() - Encoding = "UTF8" - PublicFilter = "Public\*.ps1" + Encoding = "UTF8" + PublicFilter = "Public\*.ps1" } } @@ -536,7 +536,7 @@ Describe "Build-Module" { Mock GetBuildInfo -ModuleName ModuleBuilder { [PSCustomObject]@{ - ModuleManifest = "TestDrive:\MyModule.psd1" + SourcePath = "TestDrive:\MyModule.psd1" Version = [Version]"1.0.0" OutputDirectory = "./output" Encoding = 'UTF8' From 84658d229d1dd7521a269f2cd0ab88a6ad17b60d Mon Sep 17 00:00:00 2001 From: Joel Bennett Date: Sat, 11 Jan 2020 01:54:11 -0500 Subject: [PATCH 03/17] Fix #87 by switching "ModuleManifest" to "SourcePath" Using two names for the same thing caused #87 --- Source/Private/GetBuildInfo.ps1 | 52 ++++++++++++++++++------- Source/Private/InitializeBuild.ps1 | 2 +- Tests/Private/GetBuildInfo.Tests.ps1 | 4 +- Tests/Private/InitializeBuild.Tests.ps1 | 13 ++++--- 4 files changed, 49 insertions(+), 22 deletions(-) diff --git a/Source/Private/GetBuildInfo.ps1 b/Source/Private/GetBuildInfo.ps1 index 502efc9..e43bc6d 100644 --- a/Source/Private/GetBuildInfo.ps1 +++ b/Source/Private/GetBuildInfo.ps1 @@ -25,6 +25,12 @@ function GetBuildInfo { $CommonParameters = [System.Management.Automation.Cmdlet]::CommonParameters + [System.Management.Automation.Cmdlet]::OptionalCommonParameters $BuildParameters = $BuildCommandInvocation.MyCommand.Parameters + # Make we can always look things up in BoundParameters + $BoundParameters = if ($BuildCommandInvocation.BoundParameters) { + $BuildCommandInvocation.BoundParameters + } else { + @{} + } # Combine the defaults with parameter values $ParameterValues = @{} @@ -32,19 +38,36 @@ function GetBuildInfo { foreach ($parameter in $BuildParameters.GetEnumerator().Where({$_.Key -notin $CommonParameters})) { Write-Debug " Parameter: $($parameter.key)" $key = $parameter.Key - # set if it doesn't exist, overwrite if the value is bound as a parameter - if (!$BuildInfo.ContainsKey($key) -or ($BuildCommandInvocation.BoundParameters -and $BuildCommandInvocation.BoundParameters.ContainsKey($key))) { + + # We want to map the parameter aliases to the parameter name: + foreach ($k in @($parameter.Value.Aliases)) { + if ($null -ne $k -and $BuildInfo.ContainsKey($k)) { + Write-Debug " ... Update BuildInfo[$key] from $k" + $BuildInfo[$key] = $BuildInfo[$k] + $null = $BuildInfo.Remove($k) + } + } + # !$BuildInfo.ContainsKey($key) -or $BoundParameters.ContainsKey($key) + + # The SourcePath is special: we overwrite the parameter value with the Build.psd1 value + # Otherwise, we overwrite build.psd1 values with bound parameters values + if (($key -ne "SourcePath" -or -not $BuildInfo.SourcePath) -and (-not $BuildInfo.ContainsKey($key) -or $BoundParameters.ContainsKey($key))) { if ($null -ne ($value = Get-Variable -Name $key -ValueOnly -ErrorAction Ignore )) { if ($value -ne ($null -as $parameter.Value.ParameterType)) { $ParameterValues[$key] = $value } } - } else { - Write-Debug " From Manifest: $($BuildInfo.$key)" + if ($BoundParameters.ContainsKey($key)) { + Write-Debug " From Parameter: $($ParameterValues[$key] -join ', ')" + } elseif ($ParameterValues[$key]) { + Write-Debug " From Default: $($ParameterValues[$key] -join ', ')" + } + } elseif ($BuildInfo[$key]) { + Write-Debug " From Manifest: $($BuildInfo[$key] -join ', ')" } - Write-Debug " From Parameter: $($ParameterValues.$key)" } } + Write-Debug "Finished parsing Build Manifest $BuildManifest" $BuildInfo = $BuildInfo | Update-Object $ParameterValues @@ -52,7 +75,8 @@ function GetBuildInfo { $BuildManifestParent = (Split-Path -Parent $BuildManifest) # Resolve Module manifest if not defined in Build.psd1 - if (-Not $BuildInfo.ModuleManifest) { + if (-Not $BuildInfo.SourcePath -and $BuildManifestParent) { + # Resolve Build Manifest's parent folder to find the Absolute path $ModuleName = Split-Path -Leaf $BuildManifestParent # If we're in a "well known" source folder, look higher for a name @@ -61,18 +85,20 @@ function GetBuildInfo { } # As the Module Manifest did not specify the Module manifest, we expect the Module manifest in same folder - $ModuleManifest = Join-Path $BuildManifestParent "$ModuleName.psd1" - Write-Debug "Updating BuildInfo path to $ModuleManifest" - $BuildInfo = $BuildInfo | Update-Object @{ModuleManifest = $ModuleManifest } + $SourcePath = Join-Path $BuildManifestParent "$ModuleName.psd1" + Write-Debug "Updating BuildInfo SourcePath to $SourcePath" + $BuildInfo = $BuildInfo | Update-Object @{ SourcePath = $SourcePath } } # Make sure the Path is set and points at the actual manifest, relative to Build.psd1 or absolute - if(!(Split-Path -IsAbsolute $BuildInfo.ModuleManifest)) { - $BuildInfo.ModuleManifest = Join-Path $BuildManifestParent $BuildInfo.ModuleManifest + if (!(Split-Path -IsAbsolute $BuildInfo.SourcePath) -and $BuildManifestParent) { + $BuildInfo.SourcePath = Join-Path $BuildManifestParent $BuildInfo.SourcePath | Convert-Path + } else { + $BuildInfo.SourcePath = Convert-Path $BuildInfo.SourcePath } - if (!(Test-Path $BuildInfo.ModuleManifest)) { - throw "Can't find module manifest at $($BuildInfo.ModuleManifest)" + if (!(Test-Path $BuildInfo.SourcePath)) { + throw "Can't find module manifest at the specified SourcePath: $($BuildInfo.SourcePath)" } $BuildInfo diff --git a/Source/Private/InitializeBuild.ps1 b/Source/Private/InitializeBuild.ps1 index 4f8bb7a..7d0c3bb 100644 --- a/Source/Private/InitializeBuild.ps1 +++ b/Source/Private/InitializeBuild.ps1 @@ -36,7 +36,7 @@ function InitializeBuild { ) -join "|^" # Finally, add all the information in the module manifest to the return object - $ModuleInfo = Get-Module (Get-Item $BuildInfo.ModuleManifest).FullName -ListAvailable -WarningAction SilentlyContinue -ErrorAction SilentlyContinue -ErrorVariable Problems + $ModuleInfo = Get-Module (Get-Item $BuildInfo.SourcePath).FullName -ListAvailable -WarningAction SilentlyContinue -ErrorAction SilentlyContinue -ErrorVariable Problems # If there are any problems that count, fail if ($Problems = $Problems.Where({ $_.FullyQualifiedErrorId -notmatch $ErrorsWeIgnore })) { diff --git a/Tests/Private/GetBuildInfo.Tests.ps1 b/Tests/Private/GetBuildInfo.Tests.ps1 index 4ef5ae5..5afd93a 100644 --- a/Tests/Private/GetBuildInfo.Tests.ps1 +++ b/Tests/Private/GetBuildInfo.Tests.ps1 @@ -47,7 +47,7 @@ Describe "GetBuildInfo" { It "Returns the resolved Module path, SourceDirectories, and overridden OutputDirectory (via Invocation param)" { # if set in build.psd1 it will stay the same (i.e. relative) - (Convert-FolderSeparator $Result.ModuleManifest) | + (Convert-FolderSeparator $Result.SourcePath) | Should -Be (Convert-FolderSeparator "TestDrive:\MyModule\Source\MyModule.psd1") $Result.SourceDirectories | Should -Be @("Classes", "Public") @@ -56,7 +56,7 @@ Describe "GetBuildInfo" { } Context 'Error when calling GetBuildInfo the wrong way' { - It 'Should throw if the ModuleManifestPath does not exist' { + It 'Should throw if the SourcePath does not exist' { {InModuleScope -ModuleName ModuleBuilder { GetBuildInfo -BuildManifest TestDrive:\NOTEXIST\Source\build.psd1 }} | Should -Throw diff --git a/Tests/Private/InitializeBuild.Tests.ps1 b/Tests/Private/InitializeBuild.Tests.ps1 index ab5775b..fb26fee 100644 --- a/Tests/Private/InitializeBuild.Tests.ps1 +++ b/Tests/Private/InitializeBuild.Tests.ps1 @@ -13,20 +13,21 @@ Describe "InitializeBuild" { Version = "1.0.0" }' + # Note that "Path" is an alias for "SourcePath" Set-Content "TestDrive:\build.psd1" '@{ - SourcePath = "TestDrive:\Source" - ModuleManifest = "Source\MyModule.psd1" + Path = ".\Source\MyModule.psd1" SourceDirectories = @("Classes", "Private", "Public") }' $Result = @{} - It "Handles Build-Module parameters and the build.psd1 configuration" { + It "Handles Build-Module parameters, and the build.psd1 configuration" { Push-Location TestDrive:\ $Result.Result = InModuleScope -ModuleName ModuleBuilder { function Test-Build { [CmdletBinding()] param( + [Alias("ModuleManifest", "Path")] $SourcePath = ".\Source", $SourceDirectories = @("Enum", "Classes", "Private", "Public"), $OutputDirectory = ".\Output", @@ -34,7 +35,7 @@ Describe "InitializeBuild" { ) try { Write-Warning $($MyInvocation.MyCommand | Out-String) - InitializeBuild -SourcePath $SourcePath + InitializeBuild -SourcePath $SourcePath -Debug } catch { $_ } @@ -52,7 +53,7 @@ Describe "InitializeBuild" { $Result.Name | Should -Be "MyModule" $result.ModuleType | Should -Be "Manifest" (Convert-FolderSeparator $Result.ModuleBase) | Should -Be (Convert-FolderSeparator "TestDrive:\Source") - (Convert-FolderSeparator $Result.ModuleManifest) | Should -Be (Convert-FolderSeparator "TestDrive:\Source\MyModule.psd1") + (Convert-FolderSeparator $Result.SourcePath) | Should -Be (Convert-FolderSeparator "TestDrive:\Source\MyModule.psd1") } It "Returns default values from the Build Command" { @@ -64,7 +65,7 @@ Describe "InitializeBuild" { } It "Returns overriden values from parameters" { - $Result.SourcePath | Should -Be 'TestDrive:\' + $Result.SourcePath | Should -Be (Convert-Path 'TestDrive:\Source\MyModule.psd1') } } } From 3dc7800c9ec7c3fb7faa7972df93b4c1516e1b06 Mon Sep 17 00:00:00 2001 From: Joel Bennett Date: Sat, 11 Jan 2020 01:56:02 -0500 Subject: [PATCH 04/17] Update documentation about required changes to module manifests --- ReadMe.md | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/ReadMe.md b/ReadMe.md index 15298e9..9e865ca 100644 --- a/ReadMe.md +++ b/ReadMe.md @@ -98,12 +98,15 @@ For best results, you need to organize your module project similarly to how this 1. Create a `source` folder with a `build.psd1` file and your module manifest in it 2. In the `build.psd1` specify the relative **Path** to your module's manifest, e.g. `@{ Path = "ModuleBuilder.psd1" }` -3. In your manifest, make sure the `FunctionsToExport` entry is not commented out. You can leave it empty +3. In your manifest, make sure a few values are not commented out. You can leave them empty, because they'll be overwritten: + - `FunctionsToExport` will be updated with the _file names_ that match the `PublicFilter` + - `AliasesToExport` will be updated with the values from `[Alias()]` attributes on commands + - `Prerelease` and `ReleaseNotes` in the `PSData` hashtable in `PrivateData` Once you start working on the module, you'll create sub-folders in source, and put script files in them with only **one** function in each file. You should name the files with _the same name_ as the function that's in them -- especially in the public folder, where we use the file name (without the extension) to determine the exported functions. 1. By convention, use folders named "Classes" (and/or "Enum"), "Private", and "Public" -2. By convention, the functions in "Public" will be exported from the module +2. By convention, the functions in "Public" will be exported from the module (you can override the `PublicFilter`) 3. To force classes to be in a certain order, you can prefix their file names with numbers, like `01-User.ps1` There are a *lot* of conventions in `Build-Module`, expressed as default values for its parameters. These defaults are documented in the help for Build-Module. You can override any parameter to `Build-Module` by passing it, or by adding keys to the `build.psd1` file with your preferences. From 7d519fa54d7f70a79cf3a7e9636bf1c964961a28 Mon Sep 17 00:00:00 2001 From: Joel Bennett Date: Sat, 11 Jan 2020 01:56:23 -0500 Subject: [PATCH 05/17] Finally make the build.psd1 file optional per #44 --- Source/Private/GetBuildInfo.ps1 | 33 ++++++++++++++----------- Source/Private/ResolveBuildManifest.ps1 | 6 ++--- Tests/Integration/Source1.Tests.ps1 | 33 +++++++++++++++++++++++++ 3 files changed, 53 insertions(+), 19 deletions(-) diff --git a/Source/Private/GetBuildInfo.ps1 b/Source/Private/GetBuildInfo.ps1 index e43bc6d..f444811 100644 --- a/Source/Private/GetBuildInfo.ps1 +++ b/Source/Private/GetBuildInfo.ps1 @@ -2,15 +2,7 @@ function GetBuildInfo { [CmdletBinding()] param( # The path to the Build Manifest Build.psd1 - [Parameter(Mandatory)] - [ValidateScript( { - if ((Test-Path $_) -and (Split-path -Leaf $_) -eq 'build.psd1') { - $true - } - else { - throw "The Module Manifest must point to a valid build.psd1 Data file" - } - })] + [Parameter()][AllowNull()] [string]$BuildManifest, # Pass MyInvocation from the Build-Command so we can read parameter values @@ -19,9 +11,23 @@ function GetBuildInfo { $BuildCommandInvocation ) - # Read the Module Manifest configuration file for default parameter values - Write-Debug "Load Build Manifest $BuildManifest" - $BuildInfo = Import-Metadata -Path $BuildManifest + $BuildInfo = if ($BuildManifest -and (Test-Path $BuildManifest)) { + if ((Split-path -Leaf $BuildManifest) -eq 'build.psd1') { + $BuildManifestParent = if ($BuildManifest) { + Split-Path -Parent $BuildManifest + } else { + Get-Location -PSProvider FileSystem + } + # Read the Module Manifest configuration file for default parameter values + Write-Debug "Load Build Manifest $BuildManifest" + Import-Metadata -Path $BuildManifest + } else { + @{ SourcePath = $BuildManifest } + } + } else { + @{} + } + $CommonParameters = [System.Management.Automation.Cmdlet]::CommonParameters + [System.Management.Automation.Cmdlet]::OptionalCommonParameters $BuildParameters = $BuildCommandInvocation.MyCommand.Parameters @@ -71,9 +77,6 @@ function GetBuildInfo { $BuildInfo = $BuildInfo | Update-Object $ParameterValues - # Resolve Build Manifest's parent folder to find the Absolute path - $BuildManifestParent = (Split-Path -Parent $BuildManifest) - # Resolve Module manifest if not defined in Build.psd1 if (-Not $BuildInfo.SourcePath -and $BuildManifestParent) { # Resolve Build Manifest's parent folder to find the Absolute path diff --git a/Source/Private/ResolveBuildManifest.ps1 b/Source/Private/ResolveBuildManifest.ps1 index c898abb..3e1ab67 100644 --- a/Source/Private/ResolveBuildManifest.ps1 +++ b/Source/Private/ResolveBuildManifest.ps1 @@ -9,7 +9,7 @@ function ResolveBuildManifest { if ((Split-Path $SourcePath -Leaf) -eq 'build.psd1') { $BuildManifest = $SourcePath } elseif (Test-Path $SourcePath -PathType Leaf) { - # When you pass the ModuleManifest as parameter, you must have the Build Manifest in the same folder + # When you pass the SourcePath as parameter, you must have the Build Manifest in the same folder $BuildManifest = Join-Path (Split-Path -Parent $SourcePath) [Bb]uild.psd1 } else { # It's a container, assume the Build Manifest is directly under @@ -19,9 +19,7 @@ function ResolveBuildManifest { # Make sure we are resolving the absolute path to the manifest, and test it exists $ResolvedBuildManifest = (Resolve-Path $BuildManifest -ErrorAction SilentlyContinue).Path - if (-Not ($ResolvedBuildManifest)) { - throw "Couldn't resolve the Build Manifest at $BuildManifest" - } else { + if ($ResolvedBuildManifest) { $ResolvedBuildManifest } diff --git a/Tests/Integration/Source1.Tests.ps1 b/Tests/Integration/Source1.Tests.ps1 index 262e9cd..54b5e3f 100644 --- a/Tests/Integration/Source1.Tests.ps1 +++ b/Tests/Integration/Source1.Tests.ps1 @@ -86,6 +86,39 @@ Describe "Build-Module With Source1" { It "Should update AliasesToExport in the manifest" { $Metadata.AliasesToExport | Should -Be @("GS","GSou", "SS", "SSou") } + } + + Context "Supports building without a build.psd1" { + Copy-Item $PSScriptRoot\Source1 $PSScriptRoot\Copy1 -Recurse + Remove-Item $PSScriptRoot\Copy1\build.psd1 + Rename-Item $PSScriptRoot\Copy1\Source1.psd1 Copy1.psd1 + + $Build = @{ } + + It "No longer fails if there's no build.psd1" { + $BuildParameters = @{ + SourcePath = "$PSScriptRoot\Copy1\Copy1.psd1" + OutputDirectory = "..\Result1" + VersionedOutputDirectory = $true + } + + $Build.Output = Build-Module @BuildParameters -Passthru + } + + Remove-Item -Recurse $PSScriptRoot\Copy1 + + + It "Creates the same module as with a build.psd1" { + $Build.Metadata = Import-Metadata $Build.Output.Path + } + + It "Should update AliasesToExport in the manifest" { + $Build.Metadata.AliasesToExport | Should -Be @("GS", "GSou", "SS", "SSou") + } + + It "Should update FunctionsToExport in the manifest" { + $Build.Metadata.FunctionsToExport | Should -Be @("Get-Source", "Set-Source") + } } } From d28c47de58e4aa108fef1300e6a7cb6c9d8e08e1 Mon Sep 17 00:00:00 2001 From: Joel Bennett Date: Sat, 11 Jan 2020 02:34:22 -0500 Subject: [PATCH 06/17] Add tests to verify prefix works right --- Source/Private/SetModuleContent.ps1 | 1 + Tests/Integration/Source1.Tests.ps1 | 177 +++++++++++++++------------- Tests/Integration/build.psd1 | 3 + Tests/Integration/using.ps1 | 1 + 4 files changed, 98 insertions(+), 84 deletions(-) create mode 100644 Tests/Integration/using.ps1 diff --git a/Source/Private/SetModuleContent.ps1 b/Source/Private/SetModuleContent.ps1 index fdbb0eb..508e630 100644 --- a/Source/Private/SetModuleContent.ps1 +++ b/Source/Private/SetModuleContent.ps1 @@ -31,6 +31,7 @@ function SetModuleContent { [string]$Encoding = $(if($IsCoreCLR) { "UTF8Bom" } else { "UTF8" }) ) begin { + Write-Debug "SetModuleContent WorkingDirectory $WorkingDirectory" Push-Location $WorkingDirectory -StackName SetModuleContent $ContentStarted = $false # There has been no content yet diff --git a/Tests/Integration/Source1.Tests.ps1 b/Tests/Integration/Source1.Tests.ps1 index 54b5e3f..479639d 100644 --- a/Tests/Integration/Source1.Tests.ps1 +++ b/Tests/Integration/Source1.Tests.ps1 @@ -1,124 +1,133 @@ #requires -Module ModuleBuilder -Describe "Build-Module With Source1" { - Context "When we call Build-Module" { - $Output = Build-Module $PSScriptRoot\Source1\build.psd1 -Passthru - $Module = [IO.Path]::ChangeExtension($Output.Path, "psm1") +Describe "When we call Build-Module" -Tag Integration { + $Output = Build-Module $PSScriptRoot\Source1\build.psd1 -Passthru + $Module = [IO.Path]::ChangeExtension($Output.Path, "psm1") - It "Should not put the module's DefaultCommandPrefix into the psm1 as code. Duh!" { - $Module | Should -Not -FileContentMatch '^Source$' - } + It "Should not put the module's DefaultCommandPrefix into the psm1 as code. Duh!" { + $Module | Should -Not -FileContentMatch '^Source$' + } - $Metadata = Import-Metadata $Output.Path + $Metadata = Import-Metadata $Output.Path - It "Should update FunctionsToExport in the manifest" { - $Metadata.FunctionsToExport | Should -Be @("Get-Source", "Set-Source") - } + It "Should update FunctionsToExport in the manifest" { + $Metadata.FunctionsToExport | Should -Be @("Get-Source", "Set-Source") + } - It "Should update AliasesToExport in the manifest" { - $Metadata.AliasesToExport -match "GS" | Should -Not -BeNullOrEmpty - } + It "Should update AliasesToExport in the manifest" { + $Metadata.AliasesToExport -match "GS" | Should -Not -BeNullOrEmpty + } - It "Should de-dupe and move using statements to the top of the file" { - Select-String -Pattern "^using" -Path $Module | ForEach-Object LineNumber | Should -Be 1 - } + It "Should de-dupe and move using statements to the top of the file" { + Select-String -Pattern "^using" -Path $Module | ForEach-Object LineNumber | Should -Be 1 + } - It "Will comment out the original using statements in their original positions" { - (Select-String -Pattern "^#\s*using" -Path $Module).Count | Should -Be 3 - } + It "Will comment out the original using statements in their original positions" { + (Select-String -Pattern "^#\s*using" -Path $Module).Count | Should -Be 3 } +} - Context "Regression test for #55: I can pass SourceDirectories" { - $Output = Build-Module $PSScriptRoot\Source1\build.psd1 -SourceDirectories "Private" -Passthru - $Module = [IO.Path]::ChangeExtension($Output.Path, "psm1") +Describe "Regression test for #55: I can pass SourceDirectories" -Tag Integration, Regression { + $Output = Build-Module $PSScriptRoot\Source1\build.psd1 -SourceDirectories "Private" -Passthru + $Module = [IO.Path]::ChangeExtension($Output.Path, "psm1") - It "Should not put the module's DefaultCommandPrefix into the psm1 as code. Duh!" { - $Module | Should -Not -FileContentMatch '^Source$' - } + It "Should not put the module's DefaultCommandPrefix into the psm1 as code. Duh!" { + $Module | Should -Not -FileContentMatch '^Source$' + } - $Metadata = Import-Metadata $Output.Path + $Metadata = Import-Metadata $Output.Path - It "Should not have any FunctionsToExport if SourceDirectories don't match the PublicFilter" { - $Metadata.FunctionsToExport | Should -Be @() - } + It "Should not have any FunctionsToExport if SourceDirectories don't match the PublicFilter" { + $Metadata.FunctionsToExport | Should -Be @() + } - It "Should de-dupe and move using statements to the top of the file" { - Select-String -Pattern "^using" -Path $Module | ForEach-Object LineNumber | Should -Be 1 - } + It "Should de-dupe and move using statements to the top of the file" { + Select-String -Pattern "^using" -Path $Module | ForEach-Object LineNumber | Should -Be 1 + } - It "Will comment out the original using statement in the original positions" { - (Select-String -Pattern "^#\s*using" -Path $Module).Count | Should -Be 2 - } + It "Will comment out the original using statement in the original positions" { + (Select-String -Pattern "^#\s*using" -Path $Module).Count | Should -Be 2 } +} - Context "Regression test for #55: I can pass SourceDirectories and PublicFilter" { - $Output = Build-Module $PSScriptRoot\Source1\build.psd1 -SourceDirectories "Private" -PublicFilter "P*\*" -Passthru - $Module = [IO.Path]::ChangeExtension($Output.Path, "psm1") +Describe "Regression test for #55: I can pass SourceDirectories and PublicFilter" -Tag Integration, Regression { + $Output = Build-Module $PSScriptRoot\Source1\build.psd1 -SourceDirectories "Private" -PublicFilter "P*\*" -Passthru + $Module = [IO.Path]::ChangeExtension($Output.Path, "psm1") - It "Should not put the module's DefaultCommandPrefix into the psm1 as code. Duh!" { - $Module | Should -Not -FileContentMatch '^Source$' - } + It "Should not put the module's DefaultCommandPrefix into the psm1 as code. Duh!" { + $Module | Should -Not -FileContentMatch '^Source$' + } - $Metadata = Import-Metadata $Output.Path + $Metadata = Import-Metadata $Output.Path - It "Should not have any FunctionsToExport if SourceDirectories don't match the PublicFilter" { - $Metadata.FunctionsToExport | Should -Be @("GetFinale", "GetPreview") - } + It "Should not have any FunctionsToExport if SourceDirectories don't match the PublicFilter" { + $Metadata.FunctionsToExport | Should -Be @("GetFinale", "GetPreview") + } - It "Should update AliasesToExport in the manifest" { - $Metadata.AliasesToExport | Should -Be @("GF", "GP") - } + It "Should update AliasesToExport in the manifest" { + $Metadata.AliasesToExport | Should -Be @("GF", "GP") + } - It "Should de-dupe and move using statements to the top of the file" { - Select-String -Pattern "^using" -Path $Module | ForEach-Object LineNumber | Should -Be 1 - } + It "Should de-dupe and move using statements to the top of the file" { + Select-String -Pattern "^using" -Path $Module | ForEach-Object LineNumber | Should -Be 1 + } - It "Will comment out the original using statement in the original positions" { - (Select-String -Pattern "^#\s*using" -Path $Module).Count | Should -Be 2 - } + It "Will comment out the original using statement in the original positions" { + (Select-String -Pattern "^#\s*using" -Path $Module).Count | Should -Be 2 } +} - Context "Regression test for #84: Multiple Aliases per command will Export" { - $Output = Build-Module $PSScriptRoot\Source1\build.psd1 -Passthru +Describe "Regression test for #84: Multiple Aliases per command will Export" -Tag Integration, Regression { + $Output = Build-Module $PSScriptRoot\Source1\build.psd1 -Passthru - $Metadata = Import-Metadata $Output.Path + $Metadata = Import-Metadata $Output.Path - It "Should update AliasesToExport in the manifest" { - $Metadata.AliasesToExport | Should -Be @("GS","GSou", "SS", "SSou") - } + It "Should update AliasesToExport in the manifest" { + $Metadata.AliasesToExport | Should -Be @("GS","GSou", "SS", "SSou") } +} - Context "Supports building without a build.psd1" { - Copy-Item $PSScriptRoot\Source1 $PSScriptRoot\Copy1 -Recurse - Remove-Item $PSScriptRoot\Copy1\build.psd1 - Rename-Item $PSScriptRoot\Copy1\Source1.psd1 Copy1.psd1 - - $Build = @{ } +Describe "Supports building without a build.psd1" -Tag Integration { + Copy-Item $PSScriptRoot\Source1 $PSScriptRoot\Copy1 -Recurse + Remove-Item $PSScriptRoot\Copy1\build.psd1 + Rename-Item $PSScriptRoot\Copy1\Source1.psd1 Copy1.psd1 - It "No longer fails if there's no build.psd1" { - $BuildParameters = @{ - SourcePath = "$PSScriptRoot\Copy1\Copy1.psd1" - OutputDirectory = "..\Result1" - VersionedOutputDirectory = $true - } + $Build = @{ } - $Build.Output = Build-Module @BuildParameters -Passthru + It "No longer fails if there's no build.psd1" { + $BuildParameters = @{ + SourcePath = "$PSScriptRoot\Copy1\Copy1.psd1" + OutputDirectory = "..\Result1" + VersionedOutputDirectory = $true } - Remove-Item -Recurse $PSScriptRoot\Copy1 + $Build.Output = Build-Module @BuildParameters -Passthru + } + Remove-Item -Recurse $PSScriptRoot\Copy1 - It "Creates the same module as with a build.psd1" { - $Build.Metadata = Import-Metadata $Build.Output.Path - } - It "Should update AliasesToExport in the manifest" { - $Build.Metadata.AliasesToExport | Should -Be @("GS", "GSou", "SS", "SSou") - } + It "Creates the same module as with a build.psd1" { + $Build.Metadata = Import-Metadata $Build.Output.Path + } - It "Should update FunctionsToExport in the manifest" { - $Build.Metadata.FunctionsToExport | Should -Be @("Get-Source", "Set-Source") - } + It "Should update AliasesToExport in the manifest" { + $Build.Metadata.AliasesToExport | Should -Be @("GS", "GSou", "SS", "SSou") + } + It "Should update FunctionsToExport in the manifest" { + $Build.Metadata.FunctionsToExport | Should -Be @("Get-Source", "Set-Source") + } +} + +Describe "Regression test for #88 not copying prefix files" -Tag Integration, Regression { + $Output = Build-Module $PSScriptRoot\build.psd1 -Passthru + + $Metadata = Import-Metadata $Output.Path + + It "Should update AliasesToExport in the manifest" { + $Module = [IO.Path]::ChangeExtension($Output.Path, "psm1") + $ModuleInfo = Get-Content $Module + $ModuleInfo[0] | Should -be "using module Configuration" } } diff --git a/Tests/Integration/build.psd1 b/Tests/Integration/build.psd1 index c47bdfe..2759bc5 100644 --- a/Tests/Integration/build.psd1 +++ b/Tests/Integration/build.psd1 @@ -2,4 +2,7 @@ Path = "Source1\Source1.psd1" OutputDirectory = "..\Result1" VersionedOutputDirectory = $true + + # This file is not in Source1 it's here next to this build + Prefix = "..\using.ps1" } diff --git a/Tests/Integration/using.ps1 b/Tests/Integration/using.ps1 new file mode 100644 index 0000000..90a5b2f --- /dev/null +++ b/Tests/Integration/using.ps1 @@ -0,0 +1 @@ +using module Configuration From cb936ce6fb36ce51585208ec5873382a1a07753e Mon Sep 17 00:00:00 2001 From: Joel Bennett Date: Sat, 11 Jan 2020 02:31:14 -0500 Subject: [PATCH 07/17] Fix #88 by keeping the prefix from build.psd1 --- Source/Private/InitializeBuild.ps1 | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Source/Private/InitializeBuild.ps1 b/Source/Private/InitializeBuild.ps1 index 7d0c3bb..d1f68a9 100644 --- a/Source/Private/InitializeBuild.ps1 +++ b/Source/Private/InitializeBuild.ps1 @@ -46,9 +46,10 @@ function InitializeBuild { throw "Unresolvable problems in module manifest" } + # Workaround the fact that Get-Module returns the DefaultCommandPrefix as Prefix + $ModuleInfo = Update-Object -InputObject $ModuleInfo -UpdateObject @{ DefaultCommandPrefix = $ModuleInfo.Prefix; Prefix = "" } # Update the module manifest with our build configuration $ModuleInfo = Update-Object -InputObject $ModuleInfo -UpdateObject $BuildInfo - $ModuleInfo = Update-Object -InputObject $ModuleInfo -UpdateObject @{ DefaultCommandPrefix = $ModuleInfo.Prefix; Prefix = "" } $ModuleInfo } From e6a894c43d467f8ac9ce55943ce80efb15693518 Mon Sep 17 00:00:00 2001 From: Joel Bennett Date: Sat, 11 Jan 2020 02:45:14 -0500 Subject: [PATCH 08/17] Fix build by working around the bug in 1.5.2 --- Source/build.psd1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/build.psd1 b/Source/build.psd1 index 5946d20..727fbff 100644 --- a/Source/build.psd1 +++ b/Source/build.psd1 @@ -1,7 +1,7 @@ # Use this file to override the default parameter values used by the `Build-Module` # command when building the module (see `Get-Help Build-Module -Full` for details). @{ - Path = "ModuleBuilder.psd1" + ModuleManifest = "ModuleBuilder.psd1" # Subsequent relative paths are to the ModuleManifest OutputDirectory = "../" VersionedOutputDirectory = $true From 4564df7037dc6c2d5c6e9cabc114f443a780330a Mon Sep 17 00:00:00 2001 From: Joel Bennett Date: Tue, 14 Jan 2020 01:08:21 -0500 Subject: [PATCH 09/17] Fix a few tests that will break if we check module manifests better --- Tests/Private/GetBuildInfo.Tests.ps1 | 15 +++++---------- Tests/Private/InitializeBuild.Tests.ps1 | 21 ++++++++------------- Tests/Public/Build-Module.Tests.ps1 | 2 +- azure-pipelines.yml | 2 +- 4 files changed, 15 insertions(+), 25 deletions(-) diff --git a/Tests/Private/GetBuildInfo.Tests.ps1 b/Tests/Private/GetBuildInfo.Tests.ps1 index 5afd93a..ab0ba09 100644 --- a/Tests/Private/GetBuildInfo.Tests.ps1 +++ b/Tests/Private/GetBuildInfo.Tests.ps1 @@ -11,8 +11,9 @@ Describe "GetBuildInfo" { Context "It collects the initial data" { - New-Item "TestDrive:\MyModule\Source\build.psd1" -Type File -Force - New-Item "TestDrive:\MyModule\Source\MyModule.psd1" -Type File -Force + # use -Force to create the subdirectories + New-Item -Force "TestDrive:\MyModule\Source\build.psd1" -Type File -Value "@{ Path = 'MyModule.psd1' }" + New-ModuleManifest "TestDrive:\MyModule\Source\MyModule.psd1" -Author Tester $Result = InModuleScope -ModuleName ModuleBuilder { @@ -68,18 +69,12 @@ Describe "GetBuildInfo" { }} | Should -Throw } - It 'Should throw if the Module manifest does not exists' { + It 'Should throw if the Module manifest does not exist' { + # use -Force to create the subdirectories New-Item -Force TestDrive:\NoModuleManifest\Source\build.psd1 -ItemType File {InModuleScope -ModuleName ModuleBuilder { GetBuildInfo -BuildManifest TestDrive:\NoModuleManifest\Source\build.psd1 }} | Should -Throw } } - - Context "Invalid module manifest" { - # In the current PowerShell 5.1 and 6.1 - # I can't make Get-Module -ListAvailable throw on a manifest - # So I can't test the if($Problems = ... code - } - } diff --git a/Tests/Private/InitializeBuild.Tests.ps1 b/Tests/Private/InitializeBuild.Tests.ps1 index fb26fee..bc36276 100644 --- a/Tests/Private/InitializeBuild.Tests.ps1 +++ b/Tests/Private/InitializeBuild.Tests.ps1 @@ -4,21 +4,16 @@ Describe "InitializeBuild" { Context "It collects the initial data" { - New-Item "TestDrive:\Source\build.psd1" -Type File -Force - New-Item "TestDrive:\Source\MyModule.psd1" -Type File -Force - - Set-Content "TestDrive:\Source\MyModule.psd1" '@{ - RootModule = "MyModule.psm1" - Author = "Test Manager" - Version = "1.0.0" - }' - # Note that "Path" is an alias for "SourcePath" - Set-Content "TestDrive:\build.psd1" '@{ + New-Item "TestDrive:\build.psd1" -Type File -Force -Value '@{ Path = ".\Source\MyModule.psd1" SourceDirectories = @("Classes", "Private", "Public") }' + New-Item "TestDrive:\Source\" -Type Directory + + New-ModuleManifest "TestDrive:\Source\MyModule.psd1" -RootModule "MyModule.psm1" -Author "Test Manager" -ModuleVersion "1.0.0" + $Result = @{} It "Handles Build-Module parameters, and the build.psd1 configuration" { @@ -35,7 +30,7 @@ Describe "InitializeBuild" { ) try { Write-Warning $($MyInvocation.MyCommand | Out-String) - InitializeBuild -SourcePath $SourcePath -Debug + InitializeBuild -SourcePath $SourcePath } catch { $_ } @@ -51,8 +46,8 @@ Describe "InitializeBuild" { It "Returns the ModuleInfo combined with the BuildInfo" { $Result.Name | Should -Be "MyModule" - $result.ModuleType | Should -Be "Manifest" - (Convert-FolderSeparator $Result.ModuleBase) | Should -Be (Convert-FolderSeparator "TestDrive:\Source") + $Result.SourceDirectories | Should -Be @("Classes", "Private", "Public") + (Convert-FolderSeparator $Result.ModuleBase) | Should -Be (Convert-FolderSeparator "TestDrive:\Source") (Convert-FolderSeparator $Result.SourcePath) | Should -Be (Convert-FolderSeparator "TestDrive:\Source\MyModule.psd1") } diff --git a/Tests/Public/Build-Module.Tests.ps1 b/Tests/Public/Build-Module.Tests.ps1 index 82ba21a..e4d932f 100644 --- a/Tests/Public/Build-Module.Tests.ps1 +++ b/Tests/Public/Build-Module.Tests.ps1 @@ -531,7 +531,7 @@ Describe "Build-Module" { Context "Does not fall over if you build from the drive root" { $null = New-Item "TestDrive:\build.psd1" -Type File -Force -Value "@{}" - $null = New-Item "TestDrive:\MyModule.psd1" -Type File -Force -value '@{ModuleVersion="1.0.0";Author="TEST"}' + $null = New-ModuleManifest "TestDrive:\MyModule.psd1" -ModuleVersion "1.0.0" -Author "Tester" $null = New-Item "TestDrive:\Public\Test.ps1" -Type File -Value 'MATCHING TEST CONTENT' -Force Mock GetBuildInfo -ModuleName ModuleBuilder { diff --git a/azure-pipelines.yml b/azure-pipelines.yml index eb6a09a..938c5ba 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -10,7 +10,7 @@ resources: endpoint: PoshCode type: github name: PoshCode/Azure-Pipelines - ref: refs/tags/3.2.0 + ref: refs/tags/3.2.1 stages: - stage: Build From 0d78ae5bdb453819bce2913b07c99ed81d139393 Mon Sep 17 00:00:00 2001 From: Joel Bennett Date: Tue, 14 Jan 2020 01:21:01 -0500 Subject: [PATCH 10/17] Fix ResolveBuildManifest Tests (it no longer throws) in this branch --- Tests/Private/ResolveBuildManifest.Tests.ps1 | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/Tests/Private/ResolveBuildManifest.Tests.ps1 b/Tests/Private/ResolveBuildManifest.Tests.ps1 index c797c4d..3fe0ad0 100644 --- a/Tests/Private/ResolveBuildManifest.Tests.ps1 +++ b/Tests/Private/ResolveBuildManifest.Tests.ps1 @@ -25,16 +25,22 @@ Describe "ResolveBuildManifest" { $Expected | Should -Be (Join-Path ${Global:Test Root Path} "build.psd1") } - It "Should throw when passed a wrong absolute module manifest" { - {InModuleScope ModuleBuilder { ResolveBuildManifest (Join-Path (Join-Path ${Global:Test Root Path} ERROR) ModuleBuilder.psd1) }} | Should -Throw + It "Returns nothing when passed a wrong absolute module manifest" { + InModuleScope ModuleBuilder { + ResolveBuildManifest (Join-Path (Join-Path ${Global:Test Root Path} ERROR) ModuleBuilder.psd1) | Should -BeNullOrEmpty + } } - It "Should throw when passed the wrong folder path" { - {InModuleScope ModuleBuilder { ResolveBuildManifest (Join-Path ${Global:Test Root Path} "..") }} | Should -Throw + It "Returns nothing when passed the wrong folder path" { + InModuleScope ModuleBuilder { + ResolveBuildManifest (Join-Path ${Global:Test Root Path} "..") | Should -BeNullOrEmpty + } } - It "Should throw when passed the wrong folder relative path" { - {InModuleScope ModuleBuilder { ResolveBuildManifest (Join-Path . ..) }} | Should -Throw + It "Returns nothing when passed the wrong folder relative path" { + InModuleScope ModuleBuilder { + ResolveBuildManifest (Join-Path . ..) | Should -BeNullOrEmpty + } } } From 59dd957da0153c42b9bc0c5626b05481c08c9edb Mon Sep 17 00:00:00 2001 From: Joel Bennett Date: Tue, 14 Jan 2020 01:23:47 -0500 Subject: [PATCH 11/17] Add ImportModuleManifest to wrap Get-Module I thought Get-Module would error if it could not parse the manifest. Instead it returns an empty ModuleInfo object. This wrapper will correct that while preserving the old error handling... --- Source/Private/ImportModuleManifest.ps1 | 36 ++++++++++++ Tests/Private/ImportModuleManifest.Tests.ps1 | 59 ++++++++++++++++++++ 2 files changed, 95 insertions(+) create mode 100644 Source/Private/ImportModuleManifest.ps1 create mode 100644 Tests/Private/ImportModuleManifest.Tests.ps1 diff --git a/Source/Private/ImportModuleManifest.ps1 b/Source/Private/ImportModuleManifest.ps1 new file mode 100644 index 0000000..e8f0a9b --- /dev/null +++ b/Source/Private/ImportModuleManifest.ps1 @@ -0,0 +1,36 @@ +function ImportModuleManifest { + [CmdletBinding()] + param( + [Alias("PSPath")] + [Parameter(Mandatory, ValueFromPipelineByPropertyName)] + [string]$Path + ) + process { + # Get all the information in the module manifest + $ModuleInfo = Get-Module $Path -ListAvailable -WarningAction SilentlyContinue -ErrorAction SilentlyContinue -ErrorVariable Problems + + # Some versions fails silently. If the GUID is empty, we didn't get anything at all + if ($ModuleInfo.Guid -eq [Guid]::Empty) { + Write-Error "Cannot parse '$Path' as a module manifest, try Test-ModuleManifest for details" + return + } + + # Some versions show errors are when the psm1 doesn't exist (yet), but we don't care + $ErrorsWeIgnore = "^" + (@( + "Modules_InvalidRequiredModulesinModuleManifest" + "Modules_InvalidRootModuleInModuleManifest" + ) -join "|^") + + # If there are any OTHER problems we'll fail + if ($Problems = $Problems.Where({ $_.FullyQualifiedErrorId -notmatch $ErrorsWeIgnore })) { + foreach ($problem in $Problems) { + Write-Error $problem + } + # Short circuit - don't output the ModuleInfo if there were errors + return + } + + # Workaround the fact that Get-Module returns the DefaultCommandPrefix as Prefix + Update-Object -InputObject $ModuleInfo -UpdateObject @{ DefaultCommandPrefix = $ModuleInfo.Prefix; Prefix = "" } + } +} diff --git a/Tests/Private/ImportModuleManifest.Tests.ps1 b/Tests/Private/ImportModuleManifest.Tests.ps1 new file mode 100644 index 0000000..7c7dbf1 --- /dev/null +++ b/Tests/Private/ImportModuleManifest.Tests.ps1 @@ -0,0 +1,59 @@ +#requires -Module ModuleBuilder +Describe "ImportModuleManifest" { + + Context "Mandatory Parameter" { + $CommandInfo = InModuleScope ModuleBuilder { Get-Command ImportModuleManifest } + + It 'has a mandatory Path parameter for the PSPath by pipeline' { + $Path = $CommandInfo.Parameters['Path'] + $Path | Should -Not -BeNullOrEmpty + $Path.ParameterType | Should -Be ([string]) + $Path.Aliases | Should -Be ("PSPath") + $Path.Attributes.Where{ $_ -is [Parameter] }.Mandatory | Should -Be $true + $Path.Attributes.Where{ $_ -is [Parameter] }.ValueFromPipelineByPropertyName | Should -Be $true + } + + } + + Context "Parsing Manifests" { + It "Does not cause errors for non-existent root modules" { + New-ModuleManifest -Path TestDrive:\BadRoot.psd1 -Author TestName -RootModule NoSuchFile + + InModuleScope ModuleBuilder { + ImportModuleManifest -Path TestDrive:\BadRoot.psd1 -ErrorAction Stop + } + } + + It "Returns the ModuleInfo with DefaultCommandPrefix instead of Prefix" { + New-ModuleManifest -Path TestDrive:\TestPrefix.psd1 -Author TestName -DefaultCommandPrefix PrePre + + $Prefix = InModuleScope ModuleBuilder { + $DebugPreference = "Continue" + Get-ChildItem TestDrive:\TestPrefix.psd1 | ImportModuleManifest + $DebugPreference = "SilentlyContinue" + } + + $Prefix.Prefix | Should -BeNullOrEmpty + $Prefix.DefaultCommandPrefix | Should -Be "PrePre" + } + + It "Does cause errors for manifests that are invalid" { + New-ModuleManifest -Path TestDrive:\Invalid.psd1 -Author TestName -ModuleVersion "1.0.0" + Set-Content TestDrive:\Invalid.psd1 ( + (Get-Content -Path TestDrive:\Invalid.psd1 -Raw) -replace "1.0.0" + ) + + { + InModuleScope ModuleBuilder { + ImportModuleManifest -Path TestDrive:\Invalid.psd1 -ErrorAction Stop -WarningAction Stop + } + } | Should -Throw + } + } + + Context "Invalid module manifest" { + # In the current PowerShell 5.1 and 6.1 + # We can't make Get-Module -ListAvailable throw on a manifest + # So I can't test the if($Problems = ... code + } +} From d8736230cf58c7e0ccb0f137445ef8bfb846562d Mon Sep 17 00:00:00 2001 From: Joel Bennett Date: Tue, 14 Jan 2020 01:28:56 -0500 Subject: [PATCH 12/17] Switch to searching for module manifests After discussion on #89 it seems this will "just work" in more scenarios, without breaking things that already work. --- Source/Private/GetBuildInfo.ps1 | 43 ++++++++++++++++++------------ Source/Private/InitializeBuild.ps1 | 26 ++++-------------- 2 files changed, 31 insertions(+), 38 deletions(-) diff --git a/Source/Private/GetBuildInfo.ps1 b/Source/Private/GetBuildInfo.ps1 index f444811..0180092 100644 --- a/Source/Private/GetBuildInfo.ps1 +++ b/Source/Private/GetBuildInfo.ps1 @@ -13,11 +13,6 @@ function GetBuildInfo { $BuildInfo = if ($BuildManifest -and (Test-Path $BuildManifest)) { if ((Split-path -Leaf $BuildManifest) -eq 'build.psd1') { - $BuildManifestParent = if ($BuildManifest) { - Split-Path -Parent $BuildManifest - } else { - Get-Location -PSProvider FileSystem - } # Read the Module Manifest configuration file for default parameter values Write-Debug "Load Build Manifest $BuildManifest" Import-Metadata -Path $BuildManifest @@ -77,20 +72,34 @@ function GetBuildInfo { $BuildInfo = $BuildInfo | Update-Object $ParameterValues - # Resolve Module manifest if not defined in Build.psd1 - if (-Not $BuildInfo.SourcePath -and $BuildManifestParent) { - # Resolve Build Manifest's parent folder to find the Absolute path - $ModuleName = Split-Path -Leaf $BuildManifestParent + $BuildManifestParent = if ($BuildManifest) { + Split-Path -Parent $BuildManifest + } else { + Get-Location -PSProvider FileSystem + } - # If we're in a "well known" source folder, look higher for a name - if ($ModuleName -in 'Source', 'src') { - $ModuleName = Split-Path (Split-Path -Parent $BuildManifestParent) -Leaf + # Resolve Module manifest if not defined in Build.psd1 or there's no Build.psd1 + if (-Not $BuildInfo.SourcePath) { + # Find a module manifest (or maybe several) + $ModuleInfo = Get-ChildItem $BuildManifestParent -Recurse -Filter *.psd1 -ErrorAction SilentlyContinue | + ImportModuleManifest -ErrorAction SilentlyContinue + # If we found more than one module info, the only way we have of picking just one is if it matches a folder name + if (@($ModuleInfo).Count -gt 1) { + # Resolve Build Manifest's parent folder to find the Absolute path + $ModuleName = Split-Path -Leaf $BuildManifestParent + # If we're in a "well known" source folder, look higher for a name + if ($ModuleName -in 'Source', 'src') { + $ModuleName = Split-Path (Split-Path -Parent $BuildManifestParent) -Leaf + } + $ModuleInfo = @($ModuleInfo).Where{ $_.Name -eq $ModuleName } + } + if (@($ModuleInfo).Count -eq 1) { + Write-Debug "Updating BuildInfo SourcePath to $SourcePath" + $BuildInfo = $BuildInfo | Update-Object @{ SourcePath = $ModuleInfo.Path } + } + if (-Not $BuildInfo.SourcePath) { + throw "Can't find a module manifest in $BuildManifestParent" } - - # As the Module Manifest did not specify the Module manifest, we expect the Module manifest in same folder - $SourcePath = Join-Path $BuildManifestParent "$ModuleName.psd1" - Write-Debug "Updating BuildInfo SourcePath to $SourcePath" - $BuildInfo = $BuildInfo | Update-Object @{ SourcePath = $SourcePath } } # Make sure the Path is set and points at the actual manifest, relative to Build.psd1 or absolute diff --git a/Source/Private/InitializeBuild.ps1 b/Source/Private/InitializeBuild.ps1 index d1f68a9..7461cd0 100644 --- a/Source/Private/InitializeBuild.ps1 +++ b/Source/Private/InitializeBuild.ps1 @@ -29,27 +29,11 @@ function InitializeBuild { Write-Debug "BuildCommand: $($BuildCommandInvocation.MyCommand | Out-String)" $BuildInfo = GetBuildInfo -BuildManifest $BuildManifest -BuildCommandInvocation $BuildCommandInvocation - # These errors are caused by trying to parse valid module manifests without compiling the module first - $ErrorsWeIgnore = "^" + @( - "Modules_InvalidRequiredModulesinModuleManifest" - "Modules_InvalidRootModuleInModuleManifest" - ) -join "|^" - # Finally, add all the information in the module manifest to the return object - $ModuleInfo = Get-Module (Get-Item $BuildInfo.SourcePath).FullName -ListAvailable -WarningAction SilentlyContinue -ErrorAction SilentlyContinue -ErrorVariable Problems - - # If there are any problems that count, fail - if ($Problems = $Problems.Where({ $_.FullyQualifiedErrorId -notmatch $ErrorsWeIgnore })) { - foreach ($problem in $Problems) { - Write-Error $problem - } - throw "Unresolvable problems in module manifest" + if ($ModuleInfo = ImportModuleManifest $BuildInfo.SourcePath) { + # Update the module manifest with our build configuration and output it + Update-Object -InputObject $ModuleInfo -UpdateObject $BuildInfo + } else { + throw "Unresolvable problems in module manifest: '$($BuildInfo.SourcePath)'" } - - # Workaround the fact that Get-Module returns the DefaultCommandPrefix as Prefix - $ModuleInfo = Update-Object -InputObject $ModuleInfo -UpdateObject @{ DefaultCommandPrefix = $ModuleInfo.Prefix; Prefix = "" } - # Update the module manifest with our build configuration - $ModuleInfo = Update-Object -InputObject $ModuleInfo -UpdateObject $BuildInfo - - $ModuleInfo } From 55ce9c82d9d5b27f54b4c5d55abd2f58a5b44ab3 Mon Sep 17 00:00:00 2001 From: Joel Bennett Date: Tue, 14 Jan 2020 02:20:36 -0500 Subject: [PATCH 13/17] Update to fixed azure-pipeline This one handles ModuleManifest and SourcePath as well as Path --- azure-pipelines.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 938c5ba..d258803 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -10,7 +10,7 @@ resources: endpoint: PoshCode type: github name: PoshCode/Azure-Pipelines - ref: refs/tags/3.2.1 + ref: refs/tags/3.2.2 stages: - stage: Build From 12d5fd9ce9c7513972d12c218a496349b62ebfb5 Mon Sep 17 00:00:00 2001 From: Joel Bennett Date: Wed, 15 Jan 2020 00:55:56 -0500 Subject: [PATCH 14/17] Clean up capitalization --- Source/Private/MoveUsingStatements.ps1 | 9 ++++----- Tests/Private/MoveUsingStatements.Tests.ps1 | 15 +++++++-------- 2 files changed, 11 insertions(+), 13 deletions(-) diff --git a/Source/Private/MoveUsingStatements.ps1 b/Source/Private/MoveUsingStatements.ps1 index 1648ecf..504a21a 100644 --- a/Source/Private/MoveUsingStatements.ps1 +++ b/Source/Private/MoveUsingStatements.ps1 @@ -32,12 +32,12 @@ function MoveUsingStatements { # Avoid modifying the file if there's no Parsing Error caused by Using Statements or other errors if (!$ParseErrors.Where{$_.ErrorId -eq 'UsingMustBeAtStartOfScript'}) { - Write-Debug "No Using Statement Error found." + Write-Debug "No using statement errors found." return } # Avoid modifying the file if there's other parsing errors than Using Statements misplaced if ($ParseErrors.Where{$_.ErrorId -ne 'UsingMustBeAtStartOfScript'}) { - Write-Warning "Parsing errors found. Skipping Moving Using statements." + Write-Warning "Parsing errors found. Skipping moving using statements." return } @@ -71,9 +71,8 @@ function MoveUsingStatements { ) if ($ParseErrors) { - Write-Warning "Oops, it seems that we introduced parsing error(s) while moving the Using Statements. Cancelling changes." - } - else { + Write-Warning "We introduced parsing error(s) while attempting to move using statements. Cancelling changes." + } else { $null = Set-Content -Value $ScriptText -Path $RootModule -Encoding $Encoding } } diff --git a/Tests/Private/MoveUsingStatements.Tests.ps1 b/Tests/Private/MoveUsingStatements.Tests.ps1 index 4513e83..165cea1 100644 --- a/Tests/Private/MoveUsingStatements.Tests.ps1 +++ b/Tests/Private/MoveUsingStatements.Tests.ps1 @@ -1,5 +1,5 @@ +#requires -Module ModuleBuilder Describe "MoveUsingStatements" { - Context "Necessary Parameters" { $CommandInfo = InModuleScope ModuleBuilder { Get-Command MoveUsingStatements } @@ -96,7 +96,7 @@ Describe "MoveUsingStatements" { $MoveUsingStatementsCmd = InModuleScope ModuleBuilder { $null = Mock Write-Warning {} $null = Mock Set-Content {} - $null = Mock Write-Debug {} -ParameterFilter {$Message -eq "No Using Statement Error found." } + $null = Mock Write-Debug {} -ParameterFilter { $Message -eq "No using statement errors found." } { param($RootModule) ConvertToAst $RootModule | MoveUsingStatements @@ -113,18 +113,17 @@ Describe "MoveUsingStatements" { Assert-MockCalled -CommandName Set-Content -Times 0 -ModuleName ModuleBuilder } - It 'Should not do anything when there are no Using Statements Errors' { - + It 'Should not do anything when there are no using statement errors' { $testModuleFile = "$TestDrive\MyModule.psm1" - $PSM1File = "Using namespace System.IO; function x {}" + $PSM1File = "using namespace System.IO; function x {}" Set-Content $testModuleFile -value $PSM1File -Encoding UTF8 - &$MoveUsingStatementsCmd -RootModule $testModuleFile + &$MoveUsingStatementsCmd -RootModule $testModuleFile -Debug - Assert-MockCalled -CommandName Write-Debug -Times 1 -ModuleName ModuleBuilder - Assert-MockCalled -CommandName Set-Content -Times 0 -ModuleName ModuleBuilder (Get-Content -Raw $testModuleFile).Trim() | Should -Be $PSM1File + Assert-MockCalled -CommandName Set-Content -Times 0 -ModuleName ModuleBuilder + Assert-MockCalled -CommandName Write-Debug -Times 1 -ModuleName ModuleBuilder } From c128593b0175421ddbd6194f265fa046e6ac6a3b Mon Sep 17 00:00:00 2001 From: Joel Bennett Date: Wed, 15 Jan 2020 00:59:51 -0500 Subject: [PATCH 15/17] Fix integration test and test.ps1 --- Tests/Integration/Source1.Tests.ps1 | 12 ++++-------- test.ps1 | 16 ++++++++-------- 2 files changed, 12 insertions(+), 16 deletions(-) diff --git a/Tests/Integration/Source1.Tests.ps1 b/Tests/Integration/Source1.Tests.ps1 index 479639d..fab20ad 100644 --- a/Tests/Integration/Source1.Tests.ps1 +++ b/Tests/Integration/Source1.Tests.ps1 @@ -88,25 +88,21 @@ Describe "Regression test for #84: Multiple Aliases per command will Export" -Ta } Describe "Supports building without a build.psd1" -Tag Integration { - Copy-Item $PSScriptRoot\Source1 $PSScriptRoot\Copy1 -Recurse - Remove-Item $PSScriptRoot\Copy1\build.psd1 - Rename-Item $PSScriptRoot\Copy1\Source1.psd1 Copy1.psd1 + Copy-Item $PSScriptRoot\Source1 TestDrive:\Source1 -Recurse + Remove-Item TestDrive:\Source1\build.psd1 $Build = @{ } It "No longer fails if there's no build.psd1" { $BuildParameters = @{ - SourcePath = "$PSScriptRoot\Copy1\Copy1.psd1" - OutputDirectory = "..\Result1" + SourcePath = "TestDrive:\Source1\Source1.psd1" + OutputDirectory = "TestDrive:\Result1" VersionedOutputDirectory = $true } $Build.Output = Build-Module @BuildParameters -Passthru } - Remove-Item -Recurse $PSScriptRoot\Copy1 - - It "Creates the same module as with a build.psd1" { $Build.Metadata = Import-Metadata $Build.Output.Path } diff --git a/test.ps1 b/test.ps1 index 3b81dc8..7b8b33b 100644 --- a/test.ps1 +++ b/test.ps1 @@ -2,11 +2,11 @@ using namespace Microsoft.PackageManagement.Provider.Utility param( [switch]$SkipCodeCoverage, - [switch]$HideSuccess + [switch]$HideSuccess, [switch]$IncludeVSCodeMarker ) Push-Location $PSScriptRoot -$ModuleUnderTest = Split-Path $PSScriptRoot -Leaf +$ModuleName = "ModuleBuilder" # Disable default parameters during testing, just in case $PSDefaultParameterValues += @{} @@ -15,10 +15,10 @@ $PSDefaultParameterValues["Disabled"] = $true # Find a built module as a version-numbered folder: $FullModulePath = Get-ChildItem [0-9]* -Directory | Sort-Object { $_.Name -as [SemanticVersion[]] } | Select-Object -Last 1 -Ov Version | - Get-ChildItem -Filter "$($ModuleUnderTest).psd1" + Get-ChildItem -Filter "$($ModuleName).psd1" - if(!$FullModulePath) { - throw "Can't find $($ModuleUnderTest).psd1 in $($Version.FullName)" + if (!$FullModulePath) { + throw "Can't find $($ModuleName).psd1 in $($Version.FullName)" } $Show = if ($HideSuccess) { @@ -27,15 +27,15 @@ $Show = if ($HideSuccess) { "All" } -Remove-Module (Split-Path $ModuleUnderTest -Leaf) -ErrorAction Ignore -Force +Remove-Module (Split-Path $ModuleName -Leaf) -ErrorAction Ignore -Force $ModuleUnderTest = Import-Module $FullModulePath -PassThru -Force -DisableNameChecking -Verbose:$false Write-Host "Invoke-Pester for Module $($ModuleUnderTest) version $($ModuleUnderTest.Version)" if (-not $SkipCodeCoverage) { # Get code coverage for the psm1 file to a coverage.xml that we can mess with later - Invoke-Pester (Join-Path $PSScriptRoot Tests) -CodeCoverage $ModuleUnderTest.Path -CodeCoverageOutputFile ./coverage.xml -Show $Show -PesterOption @{ IncludeVSCodeMarker = $IncludeVSCodeMarker } + Invoke-Pester ./Tests -CodeCoverage $ModuleUnderTest.Path -CodeCoverageOutputFile ./coverage.xml -Show $Show -PesterOption @{ IncludeVSCodeMarker = $IncludeVSCodeMarker } } else { - Invoke-Pester (Join-Path $PSScriptRoot Tests) -Show $Show -PesterOption @{ IncludeVSCodeMarker = $IncludeVSCodeMarker } + Invoke-Pester ./Tests -Show $Show -PesterOption @{ IncludeVSCodeMarker = $IncludeVSCodeMarker } } Pop-Location From 2aa4c4f87d9f2c8c8e7c22802fff8b6bb4d70fdb Mon Sep 17 00:00:00 2001 From: Joel Bennett Date: Wed, 15 Jan 2020 01:00:29 -0500 Subject: [PATCH 16/17] Clean up debug output --- Source/Private/InitializeBuild.ps1 | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Source/Private/InitializeBuild.ps1 b/Source/Private/InitializeBuild.ps1 index 7461cd0..a8908c9 100644 --- a/Source/Private/InitializeBuild.ps1 +++ b/Source/Private/InitializeBuild.ps1 @@ -26,7 +26,11 @@ function InitializeBuild { # GetBuildInfo reads the parameter values from the Build-Module command and combines them with the Manifest values $BuildManifest = ResolveBuildManifest $SourcePath - Write-Debug "BuildCommand: $($BuildCommandInvocation.MyCommand | Out-String)" + Write-Debug "BuildCommand: $( + @( + @($BuildCommandInvocation.MyCommand.Name) + @($BuildCommandInvocation.BoundParameters.GetEnumerator().ForEach{ "-{0} '{1}'" -f $_.Key, $_.Value }) + ) -join ' ')" $BuildInfo = GetBuildInfo -BuildManifest $BuildManifest -BuildCommandInvocation $BuildCommandInvocation # Finally, add all the information in the module manifest to the return object From 0a8a42f3ffb5693b4e06f0523443043365a9af45 Mon Sep 17 00:00:00 2001 From: Joel Bennett Date: Wed, 15 Jan 2020 01:01:28 -0500 Subject: [PATCH 17/17] Fix the normalization / guessing of SourcePath --- Source/Private/GetBuildInfo.ps1 | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/Source/Private/GetBuildInfo.ps1 b/Source/Private/GetBuildInfo.ps1 index 0180092..458e6e3 100644 --- a/Source/Private/GetBuildInfo.ps1 +++ b/Source/Private/GetBuildInfo.ps1 @@ -17,6 +17,7 @@ function GetBuildInfo { Write-Debug "Load Build Manifest $BuildManifest" Import-Metadata -Path $BuildManifest } else { + Write-Debug "Use SourcePath $BuildManifest" @{ SourcePath = $BuildManifest } } } else { @@ -48,11 +49,9 @@ function GetBuildInfo { $null = $BuildInfo.Remove($k) } } - # !$BuildInfo.ContainsKey($key) -or $BoundParameters.ContainsKey($key) - - # The SourcePath is special: we overwrite the parameter value with the Build.psd1 value - # Otherwise, we overwrite build.psd1 values with bound parameters values - if (($key -ne "SourcePath" -or -not $BuildInfo.SourcePath) -and (-not $BuildInfo.ContainsKey($key) -or $BoundParameters.ContainsKey($key))) { + # Bound parameter values > build.psd1 values > default parameters values + if (-not $BuildInfo.ContainsKey($key) -or $BoundParameters.ContainsKey($key)) { + # Reading the current value of the $key variable returns either the bound parameter or the default if ($null -ne ($value = Get-Variable -Name $key -ValueOnly -ErrorAction Ignore )) { if ($value -ne ($null -as $parameter.Value.ParameterType)) { $ParameterValues[$key] = $value @@ -68,9 +67,18 @@ function GetBuildInfo { } } } + # BuildInfo.SourcePath should point to a module manifest + if ($BuildInfo.SourcePath -and $BuildInfo.SourcePath -ne $BuildManifest) { + $ParameterValues["SourcePath"] = $BuildInfo.SourcePath + } + # If SourcePath point to build.psd1, we should clear it + if ($ParameterValues["SourcePath"] -eq $BuildManifest) { + $ParameterValues.Remove("SourcePath") + } Write-Debug "Finished parsing Build Manifest $BuildManifest" $BuildInfo = $BuildInfo | Update-Object $ParameterValues + Write-Debug "Using Module Manifest $($BuildInfo.SourcePath)" $BuildManifestParent = if ($BuildManifest) { Split-Path -Parent $BuildManifest @@ -78,7 +86,6 @@ function GetBuildInfo { Get-Location -PSProvider FileSystem } - # Resolve Module manifest if not defined in Build.psd1 or there's no Build.psd1 if (-Not $BuildInfo.SourcePath) { # Find a module manifest (or maybe several) $ModuleInfo = Get-ChildItem $BuildManifestParent -Recurse -Filter *.psd1 -ErrorAction SilentlyContinue | @@ -94,7 +101,7 @@ function GetBuildInfo { $ModuleInfo = @($ModuleInfo).Where{ $_.Name -eq $ModuleName } } if (@($ModuleInfo).Count -eq 1) { - Write-Debug "Updating BuildInfo SourcePath to $SourcePath" + Write-Debug "Updating BuildInfo SourcePath to $($ModuleInfo.Path)" $BuildInfo = $BuildInfo | Update-Object @{ SourcePath = $ModuleInfo.Path } } if (-Not $BuildInfo.SourcePath) { @@ -102,13 +109,12 @@ function GetBuildInfo { } } - # Make sure the Path is set and points at the actual manifest, relative to Build.psd1 or absolute + # Make sure the SourcePath is absolute and points at an actual file if (!(Split-Path -IsAbsolute $BuildInfo.SourcePath) -and $BuildManifestParent) { $BuildInfo.SourcePath = Join-Path $BuildManifestParent $BuildInfo.SourcePath | Convert-Path } else { $BuildInfo.SourcePath = Convert-Path $BuildInfo.SourcePath } - if (!(Test-Path $BuildInfo.SourcePath)) { throw "Can't find module manifest at the specified SourcePath: $($BuildInfo.SourcePath)" }