diff --git a/.ci/ci.yml b/.ci/ci.yml new file mode 100644 index 00000000..f23ccc4e --- /dev/null +++ b/.ci/ci.yml @@ -0,0 +1,92 @@ +name: Build-$(System.PullRequest.PullRequestNumber)-$(Date:yyyyMMdd)$(Rev:.rr) +trigger: + # Batch merge builds together while a merge build is running + batch: true + branches: + include: + - master + - release/* +pr: + branches: + include: + - master + - release/* + +resources: + repositories: + - repository: ComplianceRepo + type: github + endpoint: ComplianceGHRepo + name: PowerShell/Compliance + +stages: +- stage: Build + displayName: Build PowerShell Package + jobs: + - job: BuildPkg + displayName: Build Package + pool: + vmImage: windows-latest + steps: + - pwsh: | + $(Build.SourcesDirectory)/build.ps1 -Clean + displayName: Build + + - pwsh: | + $files = (Get-ChildItem -Recurse '$(Build.SourcesDirectory)/out/platyPS' -File).FullName + + $files | ForEach-Object { + Write-Host "##vso[artifact.upload containerfolder=platyPS;artifactname=platyPS]$_" + } + displayName: Publish build artifact + timeoutInMinutes: 10 + + - pwsh: | + Register-PSRepository -Name local -SourceLocation '$(System.ArtifactsDirectory)' -Verbose -ErrorAction Ignore + Publish-Module -Repository local -Path '$(Build.SourcesDirectory)/out/platyPS' -Verbose + $nupkgFile = Get-ChildItem -Path '$(System.ArtifactsDirectory)/platyPS*.nupkg' + + Write-Verbose -Verbose "Uploading: $nupkgFile" + Write-Host "##vso[artifact.upload containerfolder=nupkg;artifactname=nupkg]$nupkgFile" + + displayName: Create module .nupkg and upload + +- stage: Test + displayName: Test Package + jobs: + - template: test.yml + parameters: + jobName: TestPkgWin + displayName: PowerShell Core on Windows + imageName: windows-2019 + + - template: test.yml + parameters: + jobName: TestPkgWinPS + displayName: Windows PowerShell on Windows + imageName: windows-2019 + powershellExecutable: powershell + + - template: test.yml + parameters: + jobName: TestPkgUbuntu16 + displayName: PowerShell Core on Ubuntu 16.04 + imageName: ubuntu-16.04 + + - template: test.yml + parameters: + jobName: TestPkgWinMacOS + displayName: PowerShell Core on macOS + imageName: macOS-10.14 + +- stage: compliance + displayName: Compliance + dependsOn: Build + jobs: + - job: Compliance_Job + pool: + name: windows-latest + steps: + - checkout: self + - checkout: ComplianceRepo + - template: ci-compliance.yml@ComplianceRepo diff --git a/.ci/test.yml b/.ci/test.yml new file mode 100644 index 00000000..380aa7c9 --- /dev/null +++ b/.ci/test.yml @@ -0,0 +1,87 @@ +parameters: + jobName: TestPkgWin + imageName: windows-latest + displayName: PowerShell Core on Windows + powershellExecutable: pwsh + +jobs: +- job: ${{ parameters.jobName }} + pool: + vmImage: ${{ parameters.imageName }} + displayName: ${{ parameters.displayName }} + steps: + - ${{ parameters.powershellExecutable }}: | + Get-InstalledModule -Name pester -AllowPrerelease -MinimumVersion 5.0.0 -ErrorAction SilentlyContinue | Uninstall-Module -Force -Verbose -ErrorAction SilentlyContinue + displayName: Remove >= 5.0.0 Pester + timeoutInMinutes: 10 + + - ${{ parameters.powershellExecutable }}: | + Install-module Pester -Force -MaximumVersion 4.99 + displayName: Install dependencies - Pester + timeoutInMinutes: 10 + + - task: DownloadBuildArtifacts@0 + displayName: 'Download artifacts' + inputs: + buildType: current + downloadType: specific + itemPattern: '**/*.nupkg' + downloadPath: '$(System.ArtifactsDirectory)' + artifactName: 'nupkg' + + - task: DotNetCoreCLI@2 + displayName: dotnet restore + inputs: + command: restore + projects: '$(Build.SourcesDirectory)/**/*.csproj' + includeNuGetOrg: true + + - ${{ parameters.powershellExecutable }}: | + $sourceName = 'pspackageproject-local-repo' + Register-PSRepository -Name $sourceName -SourceLocation '$(System.ArtifactsDirectory)/nupkg' -ErrorAction Ignore -Verbose + $null = New-Item -Path '$(System.ArtifactsDirectory)/saved' -ItemType Directory + Save-Module -Repository $sourceName -Name platyPS -Path '$(System.ArtifactsDirectory)/saved' -Verbose + displayName: Extract product artifact + timeoutInMinutes: 10 + + - ${{ parameters.powershellExecutable }}: | + $(Build.SourcesDirectory)/build.ps1 -OutputDir '$(System.ArtifactsDirectory)/saved' -Test + + $pesterResult = '$(Build.SourcesDirectory)/pester.tests.xml' + + if (-not (Test-Path $pesterResult)) + { + throw 'Pester test results not found' + } + + Write-Host "##vso[results.publish type=NUnit;mergeResults=true;runTitle=Pester;publishRunAttachments=true;resultFiles=$pesterResult;]" + + if ($IsWindows) + { + $xunitResult = '$(Build.SourcesDirectory)/xunit.tests.xml' + + if (-not (Test-Path $xunitResult)) + { + throw 'xUnit test results not found' + } + } + displayName: Execute functional tests + errorActionPreference: continue + + - task: PublishTestResults@2 + inputs: + testResultsFormat: 'NUnit' + testResultsFiles: '**/pester.tests.xml' + testRunTitle: '${{ parameters.jobName }}-Pester' + + - task: PublishTestResults@2 + inputs: + testResultsFormat: 'xUnit' + testResultsFiles: '**/xunit.tests.xml' + testRunTitle: '${{ parameters.jobName }}-xUnit' + + - ${{ parameters.powershellExecutable }}: | + Unregister-PSRepository -Name 'pspackageproject-local-repo' -ErrorAction Ignore + displayName: Unregister temporary PSRepository + condition: always() + timeoutInMinutes: 10 diff --git a/build.ps1 b/build.ps1 index b3011180..7c1b28d2 100644 --- a/build.ps1 +++ b/build.ps1 @@ -7,7 +7,6 @@ param( [ValidateSet("Debug", "Release")] [string] $Configuration = "Debug", - [Parameter(ParameterSetName = "Build")] [string] $OutputDir = "$PSScriptRoot/out", [Parameter(ParameterSetName = "Test", Mandatory)] @@ -48,8 +47,7 @@ if ($PSCmdlet.ParameterSetName -eq 'Build') { $expectedBuildPath = "./bin/$Configuration/net461/" $expectedDllPath = "$expectedBuildPath/Microsoft.PowerShell.PlatyPS.dll" - if (-not (Test-Path $expectedDllPath)) - { + if (-not (Test-Path $expectedDllPath)) { throw "Build did not succeed." } @@ -73,30 +71,27 @@ if ($PSCmdlet.ParameterSetName -eq 'Build') { elseif ($PSCmdlet.ParameterSetName -eq 'Test') { Import-Module -Name "$OutputDir/platyPS" -Force - $xunitTestRoot = "$PSScriptRoot/test/Microsoft.PowerShell.PlatyPS.Tests" - Write-Verbose "Executing XUnit tests under $xunitTestRoot" -Verbose - - $xunitTestFailed = $true - - try { - Push-Location $xunitTestRoot - dotnet test --test-adapter-path:. "--logger:xunit;LogFilePath=$XUnitLogPath" - - if ($LASTEXITCODE -eq 0) { - $xunitTestFailed = $false + if ($IsWindows) { + try { + $xunitTestRoot = "$PSScriptRoot/test/Microsoft.PowerShell.PlatyPS.Tests" + Write-Verbose "Executing XUnit tests under $xunitTestRoot" -Verbose + Push-Location $xunitTestRoot + dotnet test --test-adapter-path:. "--logger:xunit;LogFilePath=$XUnitLogPath" + if ($LASTEXITCODE -ne 0) { + throw "XUnit test failed" + } + } + finally { + Pop-Location } - } - finally { - Pop-Location } $pesterTestRoot = "$PSScriptRoot/test/Pester" - Write-Verbose "Executing Pester tests under $pesterTestRoot" + Write-Verbose "Executing Pester tests under $pesterTestRoot" -Verbose $results = Invoke-Pester -Script $pesterTestRoot -PassThru -Outputformat nunitxml -outputfile $PesterLogPath - if ($results.FailedCount -ne 0 -or $xunitTestFailed) - { - throw "Tests failed." + if ($results.FailedCount -ne 0) { + throw "Pester Tests failed." } } diff --git a/src/MarkdownWriter/ModulePageWriter.cs b/src/MarkdownWriter/ModulePageWriter.cs index 211c39c1..1a637564 100644 --- a/src/MarkdownWriter/ModulePageWriter.cs +++ b/src/MarkdownWriter/ModulePageWriter.cs @@ -47,7 +47,7 @@ internal FileInfo Write(Collection helpItems) if (!string.Equals(modulePage.Extension, ".md", StringComparison.OrdinalIgnoreCase)) { - _modulePagePath = $"{_modulePagePath}\\{moduleName}.md"; + _modulePagePath = $"{_modulePagePath}{Constants.DirectorySeparator}{moduleName}.md"; } else { diff --git a/test/Microsoft.PowerShell.PlatyPS.Tests/nuget.config b/test/Microsoft.PowerShell.PlatyPS.Tests/nuget.config new file mode 100644 index 00000000..9ebb819a --- /dev/null +++ b/test/Microsoft.PowerShell.PlatyPS.Tests/nuget.config @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/test/Pester/PlatyPs.Tests.ps1 b/test/Pester/PlatyPs.Tests.ps1 index 25defe03..a651323d 100644 --- a/test/Pester/PlatyPs.Tests.ps1 +++ b/test/Pester/PlatyPs.Tests.ps1 @@ -20,8 +20,8 @@ Describe 'New-MarkdownHelp' { } It 'throw when cannot find maml file' { - $null = New-Item -ItemType File -Path "$TestDrive\somefile.txt" - { New-MarkdownHelp -Command 'New-MarkdownHelp' -OutputFolder "$TestDrive\somefile.txt" } | + $null = New-Item -ItemType File -Path "$TestDrive/somefile.txt" + { New-MarkdownHelp -Command 'New-MarkdownHelp' -OutputFolder "$TestDrive/somefile.txt" } | Should -Throw -ErrorId 'PathIsNotFolder,Microsoft.PowerShell.PlatyPS.NewMarkdownHelpCommand' } } @@ -100,7 +100,7 @@ Describe 'New-MarkdownHelp' { } | Import-Module -Force - $files = New-MarkdownHelp -Module PlatyPSTestModule -OutputFolder "$TestDrive\PlatyPSTestModule" -Force + $files = New-MarkdownHelp -Module PlatyPSTestModule -OutputFolder "$TestDrive/PlatyPSTestModule" -Force } AfterAll { @@ -145,8 +145,8 @@ Describe 'New-MarkdownHelp' { #> Write-Host 'Hello World!' "@ - Set-Content -Value $SeedData -Path "$TestDrive\Invoke-HelloWorld.ps1" -NoNewline - $files = New-MarkdownHelp -Command "$TestDrive\Invoke-HelloWorld.ps1" -OutputFolder "$TestDrive\output" -Force + Set-Content -Value $SeedData -Path "$TestDrive/Invoke-HelloWorld.ps1" -NoNewline + $files = New-MarkdownHelp -Command "$TestDrive/Invoke-HelloWorld.ps1" -OutputFolder "$TestDrive/output" -Force $files | Should -HaveCount 1 } @@ -166,10 +166,10 @@ Write-Host 'Hello World!' #> Write-Host 'Hello World!' "@ - Set-Content -Value $SeedData -Path "$TestDrive\Invoke-HelloWorld.ps1" -NoNewline + Set-Content -Value $SeedData -Path "$TestDrive/Invoke-HelloWorld.ps1" -NoNewline $Location = Get-Location Set-Location $TestDrive - $files = New-MarkdownHelp -Command "$TestDrive\Invoke-HelloWorld.ps1" -OutputFolder "$TestDrive\output" -Force + $files = New-MarkdownHelp -Command "$TestDrive/Invoke-HelloWorld.ps1" -OutputFolder "$TestDrive/output" -Force Set-Location $Location $files | Should -HaveCount 1 } @@ -216,7 +216,7 @@ Write-Host 'Hello World!' ### -WhatIf '@ - $files = New-MarkdownHelp -Command Get-Alpha -OutputFolder "$TestDrive\alpha" -Force -AlphabeticParamsOrder + $files = New-MarkdownHelp -Command Get-Alpha -OutputFolder "$TestDrive/alpha" -Force -AlphabeticParamsOrder $files | Should -HaveCount 1 normalizeEnds (Get-Content $files | Where-Object {$_.StartsWith('### -')} | Out-String) | Should -Be $expectedOrder } @@ -258,7 +258,7 @@ Write-Host 'Hello World!' ) } - $file = New-MarkdownHelp -Command Test-PlatyPSFunction -OutputFolder "$TestDrive\testAll1" -Force + $file = New-MarkdownHelp -Command Test-PlatyPSFunction -OutputFolder "$TestDrive/testAll1" -Force $content = Get-Content $file It 'generates markdown with correct parameter set names' { @@ -299,7 +299,7 @@ Write-Host 'Hello World!' ) } - $file = New-MarkdownHelp -Command Test-PlatyPSFunction -OutputFolder "$TestDrive\testAll2" -Force + $file = New-MarkdownHelp -Command Test-PlatyPSFunction -OutputFolder "$TestDrive/testAll2" -Force $content = Get-Content $file It 'generates markdown with correct synopsis placeholder' { @@ -369,19 +369,18 @@ Write-Host 'Hello World!' Context 'Module Landing Page'{ BeforeAll { - $OutputFolder = "$TestDrive\LandingPageMD\" - $OutputFolderReadme = "$TestDrive\LandingPageMD-ReadMe\Readme.md" + $OutputFolder = "$TestDrive/LandingPageMD" + $OutputFolderReadme = "$TestDrive/LandingPageMD-ReadMe/Readme.md" $null = New-Item -ItemType Directory $OutputFolder } - It "generates a landing page from Module"{ + It "generates a landing page from Module" -Pending:$IsMacOS { New-MarkdownHelp -Module PlatyPS -OutputFolder $OutputFolder -WithModulePage -Force - $LandingPage = Get-ChildItem (Join-Path $OutputFolder PlatyPS.md) - $LandingPage | Should -Exist + "$OutputFolder/platyPS.md" | Should -Exist } It "generates a landing page from MAML" -Pending { - New-MarkdownHelp -MamlFile (Get-ChildItem "$outFolder\platyPS\en-US\platy*xml") ` + New-MarkdownHelp -MamlFile (Get-ChildItem "$outFolder/platyPS/en-US/platy*xml") ` -OutputFolder $OutputFolder ` -WithModulePage ` -ModuleName "PlatyPS" ` @@ -425,7 +424,7 @@ Get-Alpha [-WhatIf] [[-CCC] ] [[-ddd] ] [] '@ - $files = New-MarkdownHelp -Command Get-Alpha -OutputFolder "$TestDrive\alpha" -Force -AlphabeticParamsOrder -UseFullTypeName + $files = New-MarkdownHelp -Command Get-Alpha -OutputFolder "$TestDrive/alpha" -Force -AlphabeticParamsOrder -UseFullTypeName $files | Should -HaveCount 1 normalizeEnds(Get-Content $files | Where-Object {$_.StartsWith('Type: ')} | Out-String) | Should -Be $expectedParameters normalizeEnds(Get-Content $files | Where-Object {$_.StartsWith('Get-Alpha')} | Out-String) | Should -Be $expectedSyntax @@ -443,7 +442,7 @@ Get-Alpha [-WhatIf] [[-CCC] ] [[-ddd] ] [] '@ - $files = New-MarkdownHelp -Command Get-Alpha -OutputFolder "$TestDrive\alpha" -Force -AlphabeticParamsOrder + $files = New-MarkdownHelp -Command Get-Alpha -OutputFolder "$TestDrive/alpha" -Force -AlphabeticParamsOrder $files | Should -HaveCount 1 normalizeEnds(Get-Content $files | Where-Object {$_.StartsWith('Type: ')} | Out-String) | Should Be $expectedParameters normalizeEnds(Get-Content $files | Where-Object {$_.StartsWith('Get-Alpha')} | Out-String) | Should Be $expectedSyntax @@ -463,7 +462,7 @@ Get-Alpha [-WhatIf] [[-CCC] ] [[-ddd] ] [] ) } - $file = New-MarkdownHelp -Command 'Test-WildCardsAttribute' -OutputFolder "$TestDrive\NewMarkDownHelp" + $file = New-MarkdownHelp -Command 'Test-WildCardsAttribute' -OutputFolder "$TestDrive/NewMarkDownHelp" } It 'sets accepts wildcards property on parameters as expected' { @@ -475,7 +474,7 @@ Get-Alpha [-WhatIf] [[-CCC] ] [[-ddd] ] [] Describe 'Get-MarkdownMetadata' { Context 'Simple markdown file' { BeforeAll { - Set-Content -Path "$TestDrive\foo.md" -Value @' + Set-Content -Path "$TestDrive/foo.md" -Value @' --- external help file: Microsoft.PowerShell.Archive-help.xml keywords: powershell,cmdlet @@ -501,7 +500,7 @@ title: Compress-Archive } It 'can parse out yaml snippet' { - $d = Get-MarkdownMetadata "$TestDrive\foo.md" + $d = Get-MarkdownMetadata "$TestDrive/foo.md" $d.Keys | Should -HaveCount 8 $d.Keys | Should -BeIn "external help file", "keywords", "Locale", "Module Name", "ms.date", "online version", "schema", "title" $d["Locale"] | Should -Be 'en-US'