diff --git a/Tests/Engine/InvokeScriptAnalyzer.tests.ps1 b/Tests/Engine/InvokeScriptAnalyzer.tests.ps1 index 414e24ff9..fc149b95c 100644 --- a/Tests/Engine/InvokeScriptAnalyzer.tests.ps1 +++ b/Tests/Engine/InvokeScriptAnalyzer.tests.ps1 @@ -523,18 +523,35 @@ Describe "Test -Fix Switch" { Describe "Test -EnableExit Switch" { It "Returns exit code equivalent to number of warnings" { - powershell -Command 'Import-Module PSScriptAnalyzer; Invoke-ScriptAnalyzer -ScriptDefinition gci -EnableExit' + if ($IsCoreCLR) { + pwsh -command 'Import-Module PSScriptAnalyzer; Invoke-ScriptAnalyzer -ScriptDefinition gci -EnableExit' + } + else { + powershell -command 'Invoke-ScriptAnalyzer -ScriptDefinition gci -EnableExit' + } $LASTEXITCODE | Should -Be 1 } Describe "-ReportSummary switch" { $reportSummaryFor1Warning = '*1 rule violation found. Severity distribution: Error = 0, Warning = 1, Information = 0*' It "prints the correct report summary using the -NoReportSummary switch" { - $result = powershell -command 'Invoke-Scriptanalyzer -ScriptDefinition gci -ReportSummary' + if ($IsCoreCLR) { + $result = pwsh -command 'Import-Module PSScriptAnalyzer; Invoke-Scriptanalyzer -ScriptDefinition gci -ReportSummary' + } + else { + $result = powershell -command 'Invoke-Scriptanalyzer -ScriptDefinition gci -ReportSummary' + } + "$result" | Should -BeLike $reportSummaryFor1Warning } It "does not print the report summary when not using -NoReportSummary switch" { - $result = powershell -command 'Invoke-Scriptanalyzer -ScriptDefinition gci' + if ($IsCoreCLR) { + $result = pwsh -command 'Import-Module PSScriptAnalyzer; Invoke-Scriptanalyzer -ScriptDefinition gci' + } + else { + $result = powershell -command 'Invoke-Scriptanalyzer -ScriptDefinition gci' + } + "$result" | Should -Not -BeLike $reportSummaryFor1Warning } } diff --git a/Tests/Rules/UseToExportFieldsInManifest.tests.ps1 b/Tests/Rules/UseToExportFieldsInManifest.tests.ps1 index e8556ef11..667a5f98f 100644 --- a/Tests/Rules/UseToExportFieldsInManifest.tests.ps1 +++ b/Tests/Rules/UseToExportFieldsInManifest.tests.ps1 @@ -83,7 +83,7 @@ Describe "UseManifestExportFields" { $results[0].Extent.Text | Should -Be "'*'" } - It "suggests corrections for AliasesToExport with wildcard" -pending:($IsLinux -or $IsMacOS) { + It "suggests corrections for AliasesToExport with wildcard" -pending:($IsCoreClr) { $violations = Run-PSScriptAnalyzerRule $testManifestBadAliasesWildcardPath $violationFilepath = Join-path $testManifestPath $testManifestBadAliasesWildcardPath Test-CorrectionExtent $violationFilepath $violations[0] 1 "'*'" "@('gbar', 'gfoo')" diff --git a/appveyor.yml b/appveyor.yml index 9e5302718..ad54f9771 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,91 +1,63 @@ environment: matrix: - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017 - PowerShellEdition: Desktop + PowerShellEdition: PowerShellCore + BuildConfiguration: Release + - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017 + PowerShellEdition: WindowsPowerShell BuildConfiguration: Release - APPVEYOR_BUILD_WORKER_IMAGE: WMF 4 - PowerShellEdition: Desktop + PowerShellEdition: WindowsPowerShell BuildConfiguration: PSv3Release -# clone directory -clone_folder: c:\projects\psscriptanalyzer - # cache Nuget packages and dotnet CLI cache cache: - '%USERPROFILE%\.nuget\packages -> appveyor.yml' - '%LocalAppData%\Microsoft\dotnet -> appveyor.yml' -# Install Pester install: - - ps: nuget install platyPS -Version 0.9.0 -source https://www.powershellgallery.com/api/v2 -outputDirectory "$Env:ProgramFiles\WindowsPowerShell\Modules\." -ExcludeVersion - - ps: | - $requiredPesterVersion = '4.3.1' - $pester = Get-Module Pester -ListAvailable | Where-Object { $_.Version -eq $requiredPesterVersion } - $pester - if ($null -eq $pester) - { - if ($null -eq (Get-Module -ListAvailable PowershellGet)) - { - # WMF 4 image build - nuget install Pester -Version $requiredPesterVersion -source https://www.powershellgallery.com/api/v2 -outputDirectory "$Env:ProgramFiles\WindowsPowerShell\Modules\." -ExcludeVersion - } - else - { - # Visual Studio 2017 build (has already Pester v3, therefore a different installation mechanism is needed to make it also use the new version 4) - Install-Module -Name Pester -Force -SkipPublisherCheck -Scope CurrentUser - } - } - - ps: | - # the legacy WMF4 image only has the old preview SDKs of dotnet - $globalDotJson = Get-Content .\global.json -Raw | ConvertFrom-Json - $dotNetCoreSDKVersion = $globalDotJson.sdk.version - if (-not ((dotnet --version).StartsWith($dotNetCoreSDKVersion))) - { - Invoke-WebRequest 'https://dot.net/v1/dotnet-install.ps1' -OutFile dotnet-install.ps1 - .\dotnet-install.ps1 -Version $dotNetCoreSDKVersion - } + - ps: Import-Module .\tools\appveyor.psm1 + - ps: if ($env:PowerShellEdition -eq 'WindowsPowerShell') { Invoke-AppveyorInstall } + - pwsh: if ($env:PowerShellEdition -eq 'PowerShellCore') { Import-Module .\tools\appveyor.psm1; Invoke-AppveyorInstall } build_script: - - ps: | - $PSVersionTable - Write-Verbose "Pester version: $((Get-Command Invoke-Pester).Version)" -Verbose - Write-Verbose ".NET SDK version: $(dotnet --version)" -Verbose - Push-Location C:\projects\psscriptanalyzer - # Test build using netstandard to test whether APIs are being called that are not available in .Net Core. Remove output afterwards. - .\buildCoreClr.ps1 -Framework netstandard1.6 -Configuration Release -Build - git clean -dfx - C:\projects\psscriptanalyzer\buildCoreClr.ps1 -Framework net451 -Configuration $env:BuildConfiguration -Build - C:\projects\psscriptanalyzer\build.ps1 -BuildDocs - Pop-Location - -# branches to build -branches: - # whitelist - only: - - master - - development + - ps: | + if ($env:PowerShellEdition -eq 'WindowsPowerShell') { + Invoke-AppveyorBuild -CheckoutPath $env:APPVEYOR_BUILD_FOLDER -BuildConfiguration $env:BuildConfiguration -BuildType 'FullCLR' + } + - pwsh: | + if ($env:PowerShellEdition -eq 'PowerShellCore') { + Import-Module .\tools\appveyor.psm1 # Appveyor does not persist pwsh sessions like it does for ps + Invoke-AppveyorBuild -CheckoutPath $env:APPVEYOR_BUILD_FOLDER -BuildConfiguration $env:BuildConfiguration -BuildType 'NetStandard' + } -# Run Pester tests and store the results +# Test scripts are not in a module function because the tests behave differently for unknown reasons in AppVeyor test_script: - - SET PATH=c:\Program Files\WindowsPowerShell\Modules\;%PATH%; - - ps: | - copy-item "C:\projects\psscriptanalyzer\out\PSScriptAnalyzer" "$Env:ProgramFiles\WindowsPowerShell\Modules\" -Recurse -Force - $testResultsFile = ".\TestResults.xml" - $testScripts = "C:\projects\psscriptanalyzer\Tests\Engine","C:\projects\psscriptanalyzer\Tests\Rules" - $testResults = Invoke-Pester -Script $testScripts -OutputFormat NUnitXml -OutputFile $testResultsFile -PassThru - (New-Object 'System.Net.WebClient').UploadFile("https://ci.appveyor.com/api/testresults/nunit/$($env:APPVEYOR_JOB_ID)", (Resolve-Path $testResultsFile)) - if ($testResults.FailedCount -gt 0) { - throw "$($testResults.FailedCount) tests failed." - } + - ps: | + if ($env:PowerShellEdition -eq 'WindowsPowerShell') { + $modulePath = $env:PSModulePath.Split([System.IO.Path]::PathSeparator) | Where-Object { Test-Path $_} | Select-Object -First 1 + Copy-Item "${env:APPVEYOR_BUILD_FOLDER}\out\PSScriptAnalyzer" "$modulePath\" -Recurse -Force + $testResultsFile = ".\TestResults.xml" + $testScripts = "${env:APPVEYOR_BUILD_FOLDER}\Tests\Engine","${env:APPVEYOR_BUILD_FOLDER}\Tests\Rules" + $testResults = Invoke-Pester -Script $testScripts -OutputFormat NUnitXml -OutputFile $testResultsFile -PassThru + (New-Object 'System.Net.WebClient').UploadFile("https://ci.appveyor.com/api/testresults/nunit/${env:APPVEYOR_JOB_ID}", (Resolve-Path $testResultsFile)) + if ($testResults.FailedCount -gt 0) { + throw "$($testResults.FailedCount) tests failed." + } + } + - pwsh: | + if ($env:PowerShellEdition -eq 'PowerShellCore') { + $modulePath = $env:PSModulePath.Split(';') | Where-Object { Test-Path $_} | Select-Object -First 1 + Copy-Item "${env:APPVEYOR_BUILD_FOLDER}\out\PSScriptAnalyzer" "$modulePath\" -Recurse -Force + $testResultsFile = ".\TestResults.xml" + $testScripts = "${env:APPVEYOR_BUILD_FOLDER}\Tests\Engine","${env:APPVEYOR_BUILD_FOLDER}\Tests\Rules" + $testResults = Invoke-Pester -Script $testScripts -OutputFormat NUnitXml -OutputFile $testResultsFile -PassThru + (New-Object 'System.Net.WebClient').UploadFile("https://ci.appveyor.com/api/testresults/nunit/${env:APPVEYOR_JOB_ID}", (Resolve-Path $testResultsFile)) + if ($testResults.FailedCount -gt 0) { + throw "$($testResults.FailedCount) tests failed." + } + } -# Upload the project along with TestResults as a zip archive +# Upload the project along with test results as a zip archive on_finish: - - ps: | - $stagingDirectory = (Resolve-Path ..).Path - $zipFile = Join-Path $stagingDirectory "$(Split-Path $pwd -Leaf).zip" - Add-Type -assemblyname System.IO.Compression.FileSystem - [System.IO.Compression.ZipFile]::CreateFromDirectory($pwd, $zipFile) - @( - # You can add other artifacts here - (ls $zipFile) - ) | % { Push-AppveyorArtifact $_.FullName } + - ps: Invoke-AppveyorFinish diff --git a/tools/appveyor.psm1 b/tools/appveyor.psm1 new file mode 100644 index 000000000..bbac9a0a2 --- /dev/null +++ b/tools/appveyor.psm1 @@ -0,0 +1,80 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. + +$ErrorActionPreference = 'Stop' + +# Implements the AppVeyor 'install' step and installs the required versions of Pester, platyPS and the .Net Core SDK if needed. +function Invoke-AppVeyorInstall { + $requiredPesterVersion = '4.3.1' + $pester = Get-Module Pester -ListAvailable | Where-Object { $_.Version -eq $requiredPesterVersion } + if ($null -eq $pester) { + if ($null -eq (Get-Module -ListAvailable PowershellGet)) { + # WMF 4 image build + nuget install Pester -Version $requiredPesterVersion -source https://www.powershellgallery.com/api/v2 -outputDirectory "$env:ProgramFiles\WindowsPowerShell\Modules\." -ExcludeVersion + } + else { + # Visual Studio 2017 build (has already Pester v3, therefore a different installation mechanism is needed to make it also use the new version 4) + Install-Module -Name Pester -Force -SkipPublisherCheck -Scope CurrentUser + } + } + + if ($null -eq (Get-Module -ListAvailable PowershellGet)) { + # WMF 4 image build + nuget install platyPS -Version 0.9.0 -source https://www.powershellgallery.com/api/v2 -outputDirectory "$Env:ProgramFiles\WindowsPowerShell\Modules\." -ExcludeVersion + } + else { + Install-Module -Name platyPS -Force -Scope CurrentUser -RequiredVersion '0.9.0' + } + + # the legacy WMF4 image only has the old preview SDKs of dotnet + $globalDotJson = Get-Content (Join-Path $PSScriptRoot '..\global.json') -Raw | ConvertFrom-Json + $dotNetCoreSDKVersion = $globalDotJson.sdk.version + if (-not ((dotnet --version).StartsWith($dotNetCoreSDKVersion))) { + Invoke-WebRequest 'https://dot.net/v1/dotnet-install.ps1' -OutFile dotnet-install.ps1 + .\dotnet-install.ps1 -Version $dotNetCoreSDKVersion + Remove-Item .\dotnet-install.ps1 + } +} + +# Implements the AppVeyor 'build_script' step +function Invoke-AppVeyorBuild { + Param( + [Parameter(Mandatory)] + [ValidateSet('FullCLR', 'NetStandard')] + $BuildType, + + [Parameter(Mandatory)] + [ValidateSet('Release', 'PSv3Release')] + $BuildConfiguration, + + [Parameter(Mandatory)] + [ValidateScript( {Test-Path $_})] + $CheckoutPath + ) + + $PSVersionTable + Write-Verbose "Pester version: $((Get-Command Invoke-Pester).Version)" -Verbose + Write-Verbose ".NET SDK version: $(dotnet --version)" -Verbose + Push-Location $CheckoutPath + [Environment]::SetEnvironmentVariable("DOTNET_SKIP_FIRST_TIME_EXPERIENCE", 1) # avoid unneccessary initialization in CI + if ($BuildType -eq 'FullCLR') { + .\buildCoreClr.ps1 -Framework net451 -Configuration $BuildConfiguration -Build + } + elseif ($BuildType -eq 'NetStandard') { + .\buildCoreClr.ps1 -Framework netstandard1.6 -Configuration Release -Build + } + .\build.ps1 -BuildDocs + Pop-Location +} + +# Implements AppVeyor 'on_finish' step +function Invoke-AppveyorFinish { + $stagingDirectory = (Resolve-Path ..).Path + $zipFile = Join-Path $stagingDirectory "$(Split-Path $pwd -Leaf).zip" + Add-Type -AssemblyName 'System.IO.Compression.FileSystem' + [System.IO.Compression.ZipFile]::CreateFromDirectory($pwd, $zipFile) + @( + # You can add other artifacts here + (Get-ChildItem $zipFile) + ) | ForEach-Object { Push-AppveyorArtifact $_.FullName } +} \ No newline at end of file