Skip to content

Change build script to install into a versioned directory #1247

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 7 commits into from
Jun 3, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 14 additions & 9 deletions Tests/Engine/ModuleDependencyHandler.tests.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ Describe "Resolve DSC Resource Dependency" {
$skipTest = $true
return
}
$SavedPSModulePath = $env:PSModulePath
$savedPSModulePath = $env:PSModulePath
$violationFileName = 'MissingDSCResource.ps1'
$violationFilePath = Join-Path $directory $violationFileName
$testRootDirectory = Split-Path -Parent $directory
Expand All @@ -27,15 +27,19 @@ Describe "Resolve DSC Resource Dependency" {
}
AfterAll {
if ( $skipTest ) { return }
$env:PSModulePath = $SavedPSModulePath
$env:PSModulePath = $savedPSModulePath
}

Context "Module handler class" {
BeforeAll {
if ( $skipTest ) { return }
$moduleHandlerType = [Microsoft.Windows.PowerShell.ScriptAnalyzer.Generic.ModuleDependencyHandler]
$oldEnvVars = Get-Item Env:\* | Sort-Object -Property Key
$oldPSModulePath = $env:PSModulePath
$savedPSModulePath = $env:PSModulePath
}
AfterAll {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just a note, there is a Pester issue here whereby using BeforeAll or AfterAll inside a Context block results in unpredictable behaviour. Technically they should be only under a Describe block. We should address this in another PR as refactoring this test suite is hard.

Copy link
Contributor Author

@JamesWTruher JamesWTruher Jun 3, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yah - I agree - the missing AfterAll was the reason that the analyzer needed to be installed into a specific location. with this change, that is no longer needed! The test altered $env:PSModulePath permanently!

if ( $skipTest ) { return }
$env:PSModulePath = $savedPSModulePath
}
It "Sets defaults correctly" -skip:$skipTest {
$rsp = [runspacefactory]::CreateRunspace()
Expand All @@ -54,7 +58,7 @@ Describe "Resolve DSC Resource Dependency" {
$expectedPssaAppDataPath = Join-Path $depHandler.LocalAppDataPath "PSScriptAnalyzer"
$depHandler.PSSAAppDataPath | Should -Be $expectedPssaAppDataPath

$expectedPSModulePath = $oldPSModulePath + [System.IO.Path]::PathSeparator + $depHandler.TempModulePath
$expectedPSModulePath = $savedPSModulePath + [System.IO.Path]::PathSeparator + $depHandler.TempModulePath
$env:PSModulePath | Should -Be $expectedPSModulePath

$depHandler.Dispose()
Expand Down Expand Up @@ -174,7 +178,7 @@ Describe "Resolve DSC Resource Dependency" {
# Save the current environment variables
$oldLocalAppDataPath = $env:LOCALAPPDATA
$oldTempPath = $env:TEMP
$oldPSModulePath = $env:PSModulePath
$savedPSModulePath = $env:PSModulePath

# set the environment variables
$tempPath = Join-Path $oldTempPath ([guid]::NewGUID()).ToString()
Expand All @@ -184,8 +188,8 @@ Describe "Resolve DSC Resource Dependency" {
$env:TEMP = $newTempPath

# create the temporary directories
New-Item -Type Directory -Path $newLocalAppDataPath
New-Item -Type Directory -Path $newTempPath
New-Item -Type Directory -Path $newLocalAppDataPath -force
New-Item -Type Directory -Path $newTempPath -force

# create and dispose module dependency handler object
# to setup the temporary module
Expand All @@ -203,7 +207,8 @@ Describe "Resolve DSC Resource Dependency" {
}

AfterAll {
$env:PSModulePath = $oldPSModulePath
if ( $skipTest ) { return }
$env:PSModulePath = $savedPSModulePath
}

It "has a single parse error" -skip:$skipTest {
Expand All @@ -217,7 +222,7 @@ Describe "Resolve DSC Resource Dependency" {

It "Keeps PSModulePath unchanged before and after invocation" -skip:$skipTest {
$dr = Invoke-ScriptAnalyzer -Path $violationFilePath -ErrorVariable parseErrors -ErrorAction SilentlyContinue
$env:PSModulePath | Should -Be $oldPSModulePath
$env:PSModulePath | Should -Be $savedPSModulePath
}

if (!$skipTest)
Expand Down
8 changes: 4 additions & 4 deletions Tests/Rules/DscExamplesPresent.tests.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@ if ($PSVersionTable.PSVersion -ge [Version]'5.0.0') {
}

Context "When examples present" {
New-Item -Path $examplesPath -ItemType Directory
New-Item -Path "$examplesPath\FileResource_Example.psm1" -ItemType File
New-Item -Path $examplesPath -ItemType Directory -force
New-Item -Path "$examplesPath\FileResource_Example.psm1" -ItemType File -force

$noViolations = Invoke-ScriptAnalyzer -ErrorAction SilentlyContinue $classResourcePath | Where-Object {$_.RuleName -eq $ruleName}

Expand Down Expand Up @@ -57,8 +57,8 @@ Describe "DscExamplesPresent rule in regular (non-class) based resource" {
}

Context "When examples present" {
New-Item -Path $examplesPath -ItemType Directory
New-Item -Path "$examplesPath\MSFT_WaitForAll_Example.psm1" -ItemType File
New-Item -Path $examplesPath -ItemType Directory -force
New-Item -Path "$examplesPath\MSFT_WaitForAll_Example.psm1" -ItemType File -force

$noViolations = Invoke-ScriptAnalyzer -ErrorAction SilentlyContinue $resourcePath | Where-Object {$_.RuleName -eq $ruleName}

Expand Down
8 changes: 4 additions & 4 deletions Tests/Rules/DscTestsPresent.tests.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@ if ($PSVersionTable.PSVersion -ge [Version]'5.0.0') {
}

Context "When tests present" {
New-Item -Path $testsPath -ItemType Directory
New-Item -Path "$testsPath\FileResource_Test.psm1" -ItemType File
New-Item -Path $testsPath -ItemType Directory -force
New-Item -Path "$testsPath\FileResource_Test.psm1" -ItemType File -force

$noViolations = Invoke-ScriptAnalyzer -ErrorAction SilentlyContinue $classResourcePath | Where-Object {$_.RuleName -eq $ruleName}

Expand Down Expand Up @@ -57,8 +57,8 @@ Describe "DscTestsPresent rule in regular (non-class) based resource" {
}

Context "When tests present" {
New-Item -Path $testsPath -ItemType Directory
New-Item -Path "$testsPath\MSFT_WaitForAll_Test.psm1" -ItemType File
New-Item -Path $testsPath -ItemType Directory -force
New-Item -Path "$testsPath\MSFT_WaitForAll_Test.psm1" -ItemType File -force

$noViolations = Invoke-ScriptAnalyzer -ErrorAction SilentlyContinue $resourcePath | Where-Object {$_.RuleName -eq $ruleName}

Expand Down
4 changes: 2 additions & 2 deletions Tests/Rules/UseIdenticalMandatoryParametersForDSC.tests.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ Describe "UseIdenticalMandatoryParametersForDSC" {
}
"@
# and under it a directory called dscresources\something
New-Item -ItemType Directory -Path $noParentClassDir
New-Item -ItemType Directory -Path $noParentClassDir -force
$noparentClassFilepath = Join-Path -Path $noParentClassDir -ChildPath 'ClassWithNoParent.psm1'
$noparentClassMofFilepath = Join-Path -Path $noParentClassDir -ChildPath 'ClassWithNoParent.schema.mof'

Expand Down Expand Up @@ -102,7 +102,7 @@ class ClassWithNoParent
}
"@
# and under it a directory called dscresources\something
New-Item -ItemType Directory -Path $noParentClassDir
New-Item -ItemType Directory -Path $noParentClassDir -force
$noparentClassFilepath = Join-Path -Path $noParentClassDir -ChildPath 'MSFT_ClassWithNoParent.psm1'
$noparentClassMofFilepath = Join-Path -Path $noParentClassDir -ChildPath 'MSFT_ClassWithNoParent.schema.mof'

Expand Down
86 changes: 62 additions & 24 deletions build.psm1
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,18 @@

# Build module for PowerShell ScriptAnalyzer
$projectRoot = $PSScriptRoot
$destinationDir = Join-Path -Path $projectRoot -ChildPath (Join-Path -Path "out" -ChildPath "PSScriptAnalyzer")
$analyzerName = "PSScriptAnalyzer"

function Get-AnalyzerVersion
{
$csprojPath = [io.path]::Combine($projectRoot,"Engine","Engine.csproj")
$xml = [xml](Get-Content "${csprojPath}")
$xml.SelectSingleNode(".//VersionPrefix")."#text"
}

$analyzerVersion = Get-AnalyzerVersion
# location where analyzer goes
$script:destinationDir = [io.path]::Combine($projectRoot,"out","${analyzerName}", $analyzerVersion)

function Publish-File
{
Expand Down Expand Up @@ -40,7 +51,7 @@ function Get-UserModulePath
function Uninstall-ScriptAnalyzer
{
[CmdletBinding(SupportsShouldProcess)]
param ( $ModulePath = $(Join-Path -Path (Get-UserModulePath) -ChildPath PSScriptAnalyzer) )
param ( $ModulePath = $(Join-Path -Path (Get-UserModulePath) -ChildPath ${analyzerName}) )
END {
if ( $PSCmdlet.ShouldProcess("$modulePath") ) {
Remove-Item -Recurse -Path "$ModulePath" -Force
Expand All @@ -52,10 +63,10 @@ function Uninstall-ScriptAnalyzer
function Install-ScriptAnalyzer
{
[CmdletBinding(SupportsShouldProcess)]
param ( $ModulePath = $(Join-Path -Path (Get-UserModulePath) -ChildPath PSScriptAnalyzer) )
param ( $ModulePath = $(Join-Path -Path (Get-UserModulePath) -ChildPath ${analyzerName}) )
END {
if ( $PSCmdlet.ShouldProcess("$modulePath") ) {
Copy-Item -Recurse -Path "$destinationDir" -Destination "$ModulePath\." -Force
Copy-Item -Recurse -Path "$script:destinationDir" -Destination "$ModulePath\." -Force
}
}
}
Expand All @@ -64,7 +75,7 @@ function Install-ScriptAnalyzer
function Uninstall-ScriptAnalyzer
{
[CmdletBinding(SupportsShouldProcess)]
param ( $ModulePath = $(Join-Path -Path (Get-UserModulePath) -ChildPath PSScriptAnalyzer) )
param ( $ModulePath = $(Join-Path -Path (Get-UserModulePath) -ChildPath ${analyzerName}) )
END {
if ((Test-Path $ModulePath) -and (Get-Item $ModulePath).PSIsContainer )
{
Expand All @@ -79,9 +90,9 @@ function Remove-Build
[CmdletBinding(SupportsShouldProcess=$true)]
param ()
END {
if ( $PSCmdlet.ShouldProcess("${destinationDir}")) {
if ( Test-Path ${destinationDir} ) {
Remove-Item -Force -Recurse ${destinationDir}
if ( $PSCmdlet.ShouldProcess("${script:destinationDir}")) {
if ( Test-Path ${script:destinationDir} ) {
Remove-Item -Force -Recurse ${script:destinationDir}
}
}
}
Expand All @@ -92,7 +103,7 @@ function Start-DocumentationBuild
{
$docsPath = Join-Path $projectRoot docs
$markdownDocsPath = Join-Path $docsPath markdown
$outputDocsPath = Join-Path $destinationDir en-US
$outputDocsPath = Join-Path $script:destinationDir en-US
$platyPS = Get-Module -ListAvailable platyPS
if ($null -eq $platyPS -or ($platyPS | Sort-Object Version -Descending | Select-Object -First 1).Version -lt [version]0.12)
{
Expand All @@ -118,12 +129,12 @@ function Copy-CompatibilityProfiles
}

$profileDir = [System.IO.Path]::Combine($PSScriptRoot, 'PSCompatibilityCollector', 'profiles')
$destinationDir = [System.IO.Path]::Combine($PSScriptRoot, 'out', 'PSScriptAnalyzer', "compatibility_profiles")
if ( -not (Test-Path $destinationDir) ) {
$null = New-Item -Type Directory $destinationDir
$targetProfileDir = [io.path]::Combine($script:destinationDir,"compatibility_profiles")
if ( -not (Test-Path $targetProfileDir) ) {
$null = New-Item -Type Directory $targetProfileDir
}

Copy-Item -Force $profileDir/* $destinationDir
Copy-Item -Force $profileDir/* $targetProfileDir
}

# build script analyzer (and optionally build everything with -All)
Expand Down Expand Up @@ -162,9 +173,6 @@ function Start-ScriptAnalyzerBuild
Start-DocumentationBuild
}

# Destination for the composed module when built
$destinationDir = "$projectRoot\out\PSScriptAnalyzer"

if ( $All )
{
# Build all the versions of the analyzer
Expand Down Expand Up @@ -205,24 +213,23 @@ function Start-ScriptAnalyzerBuild
"$projectRoot\Engine\ScriptAnalyzer.format.ps1xml", "$projectRoot\Engine\ScriptAnalyzer.types.ps1xml"
)

$destinationDir = "$projectRoot\out\PSScriptAnalyzer"
switch ($PSVersion)
{
3
{
$destinationDirBinaries = "$destinationDir\PSv3"
$destinationDirBinaries = "$script:destinationDir\PSv3"
}
4
{
$destinationDirBinaries = "$destinationDir\PSv4"
$destinationDirBinaries = "$script:destinationDir\PSv4"
}
5
{
$destinationDirBinaries = "$destinationDir"
$destinationDirBinaries = "$script:destinationDir"
}
6
{
$destinationDirBinaries = "$destinationDir\coreclr"
$destinationDirBinaries = "$script:destinationDir\coreclr"
}
default
{
Expand Down Expand Up @@ -252,7 +259,7 @@ function Start-ScriptAnalyzerBuild
Pop-Location
}

Publish-File $itemsToCopyCommon $destinationDir
Publish-File $itemsToCopyCommon $script:destinationDir

$itemsToCopyBinaries = @(
"$projectRoot\Engine\bin\${config}\${Framework}\Microsoft.Windows.PowerShell.ScriptAnalyzer.dll",
Expand All @@ -262,7 +269,7 @@ function Start-ScriptAnalyzerBuild
Publish-File $itemsToCopyBinaries $destinationDirBinaries

$settingsFiles = Get-Childitem "$projectRoot\Engine\Settings" | ForEach-Object -MemberName FullName
Publish-File $settingsFiles (Join-Path -Path $destinationDir -ChildPath Settings)
Publish-File $settingsFiles (Join-Path -Path $script:destinationDir -ChildPath Settings)

if ($framework -eq 'net452') {
Copy-Item -path "$projectRoot\Rules\bin\${config}\${framework}\Newtonsoft.Json.dll" -Destination $destinationDirBinaries
Expand All @@ -280,10 +287,38 @@ function Test-ScriptAnalyzer
param ( [Parameter()][switch]$InProcess, [switch]$ShowAll )

END {
$testModulePath = Join-Path "${projectRoot}" -ChildPath out
# versions 3 and 4 don't understand versioned module paths, so we need to rename the directory of the version to
# the module name, and then set the ModulePath to that
#
# the layout of the build location is
# .../out
# /PSScriptAnalyzer
# /1.18.0
# /<modulefiles live here>
# and ".../out" is added to env:PSModulePath
# on v3 and v4, it will be
# .../out
# /PSScriptAnalyzer
# /PSScriptAnalyzer
# /<modulefiles live here>
# and ".../out/PSScriptAnalyzer" is added to env:PSModulePath
#
#
$major = $PSVersionTable.PSVersion.Major
if ( $major -lt 5 ) {
# get the directory name of the destination, we need to change it
$versionDirectoryRoot = Split-Path $script:destinationDir
$testModulePath = Join-Path $versionDirectoryRoot $analyzerName
}
else {
$testModulePath = Join-Path "${projectRoot}" -ChildPath out
}
$testResultsFile = "'$(Join-Path ${projectRoot} -childPath TestResults.xml)'"
$testScripts = "'${projectRoot}\Tests\Engine','${projectRoot}\Tests\Rules','${projectRoot}\Tests\Documentation'"
try {
if ( $major -lt 5 ) {
Rename-Item $script:destinationDir ${testModulePath}
}
$savedModulePath = $env:PSModulePath
$env:PSModulePath = "${testModulePath}{0}${env:PSModulePath}" -f [System.IO.Path]::PathSeparator
if ($ShowAll)
Expand All @@ -304,6 +339,9 @@ function Test-ScriptAnalyzer
}
finally {
$env:PSModulePath = $savedModulePath
if ( $major -lt 5 ) {
Rename-Item ${testModulePath} ${script:destinationDir}
}
}
}
}
Expand Down
21 changes: 17 additions & 4 deletions tools/appveyor.psm1
Original file line number Diff line number Diff line change
Expand Up @@ -51,10 +51,23 @@ function Invoke-AppveyorTest {
Write-Verbose -Verbose ("Running tests on PowerShell version " + $PSVersionTable.PSVersion)
Write-Verbose -Verbose "Language set to '${env:LANG}'"

# Copy the generated modules into the out directory
$modulePath = $env:PSModulePath.Split([System.IO.Path]::PathSeparator) | Where-Object { Test-Path $_} | Select-Object -First 1
Copy-Item "${CheckoutPath}\out\PSScriptAnalyzer" "$modulePath\" -Recurse -Force
Copy-Item "${CheckoutPath}\PSCompatibilityCollector\out\PSCompatibilityCollector" "$modulePath\" -Recurse -Force
# set up env:PSModulePath to the build location, don't copy it to the "normal place"
$analyzerVersion = ([xml](Get-Content "${CheckoutPath}\Engine\Engine.csproj")).SelectSingleNode(".//VersionPrefix")."#text".Trim()
$majorVersion = ([System.Version]$analyzerVersion).Major
$psMajorVersion = $PSVersionTable.PSVersion.Major

if ( $psMajorVersion -lt 5 ) {
$versionModuleDir = "${CheckoutPath}\out\PSScriptAnalyzer\${analyzerVersion}"
$renameTarget = "${CheckoutPath}\out\PSScriptAnalyzer\PSScriptAnalyzer"
Rename-Item "${versionModuleDir}" "${renameTarget}"
$moduleDir = "${CheckoutPath}\out\PSScriptAnalyzer"
}
else{
$moduleDir = "${CheckoutPath}\out"
}

$env:PSModulePath = "${moduleDir}","${env:PSModulePath}" -join [System.IO.Path]::PathSeparator
Write-Verbose -Verbose "module path: ${env:PSModulePath}"

# Set up testing assets
$testResultsPath = Join-Path ${CheckoutPath} TestResults.xml
Expand Down