From 8aafc8476367950a17112e7bc84ff74457570681 Mon Sep 17 00:00:00 2001 From: "James Truher [MSFT]" Date: Fri, 9 Aug 2024 14:22:28 -0700 Subject: [PATCH] Add CI as github action. (#47) * Add CI as github action. Required small adjustments in build.ps1. Also created a cron job for weekly builds. * fix name of upload test results. * Add skip publisher check to pester install. * Change tests to not use PS7 commands for path combination. Also mock PSStyle variable. * Drop support for Windows PowerShell. It's not possible with the use of System.Text.Json. Add another test result file to gitignore. * Remove mock of PSStyle variable. --- .github/workflows/ci-test.yml | 46 ++++++++++++++++++ .gitignore | 1 + .pipelines/TextUtility-Official.yml | 15 ++++++ build.ps1 | 59 +++++++++++++++-------- src/Microsoft.PowerShell.TextUtility.psd1 | 2 +- test/TextTableParser.Tests.ps1 | 6 +-- 6 files changed, 104 insertions(+), 25 deletions(-) create mode 100644 .github/workflows/ci-test.yml diff --git a/.github/workflows/ci-test.yml b/.github/workflows/ci-test.yml new file mode 100644 index 0000000..ccc6caa --- /dev/null +++ b/.github/workflows/ci-test.yml @@ -0,0 +1,46 @@ +name: TextUtility CI Tests + +on: + push: + branches: [ main ] + pull_request: + branches: [ main ] + +jobs: + ci: + name: Build and Test + strategy: + matrix: + os: [ windows-latest, macos-latest, ubuntu-latest ] + runs-on: ${{ matrix.os }} + env: + DOTNET_NOLOGO: true + DOTNET_GENERATE_ASPNET_CERTIFICATE: false + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Install dotnet + uses: actions/setup-dotnet@v4 + with: + cache: true + cache-dependency-path: '**/*.csproj' + + - name: Install PSResources + run: ./build.ps1 -Bootstrap + shell: pwsh + + - name: Build + run: ./build.ps1 -Configuration Release + shell: pwsh + + - name: Test + run: ./build.ps1 -Test -NoBuild + shell: pwsh + + - name: Upload test results + uses: actions/upload-artifact@v4 + if: always() + with: + name: TextUtility-tests-${{ matrix.os }} + path: testResults.xml diff --git a/.gitignore b/.gitignore index e97d30b..84fb4fd 100644 --- a/.gitignore +++ b/.gitignore @@ -6,5 +6,6 @@ out/ project.lock.json .DS_Store Microsoft.PowerShell.TextUtility.xml +testResults.xml # VSCode directories that are not at the repository root /**/.vscode/ diff --git a/.pipelines/TextUtility-Official.yml b/.pipelines/TextUtility-Official.yml index ccb3b9d..778ad3b 100644 --- a/.pipelines/TextUtility-Official.yml +++ b/.pipelines/TextUtility-Official.yml @@ -2,6 +2,20 @@ name: TextUtility-ModuleBuild-$(Build.BuildId) trigger: none pr: none +schedules: +- cron: '0 3 * * 1' + displayName: Weekly Build + branches: + include: + - master + always: true + +parameters: + - name: 'publishToPowerShellGallery' + displayName: 'Publish module to PowerShell gallery' + type: boolean + default: false + variables: BuildConfiguration: Release DOTNET_NOLOGO: true @@ -106,6 +120,7 @@ extends: files_to_sign: "**/*.nupkg" - stage: release dependsOn: build + condition: ${{ parameters.publishToPowerShellGallery }} variables: version: $[ stageDependencies.build.main.outputs['package.version'] ] drop: $(Pipeline.Workspace)/drop_build_main diff --git a/build.ps1 b/build.ps1 index bbcd7da..9e710eb 100644 --- a/build.ps1 +++ b/build.ps1 @@ -30,7 +30,11 @@ param ( [Parameter()] [switch] - $GetPackageVersion + $GetPackageVersion, + + [Parameter(ParameterSetName="bootstrap")] + [switch] + $Bootstrap ) @@ -89,22 +93,43 @@ function Export-Module function Test-Module { try { $PSVersionTable | Out-String -Stream | Write-Verbose -Verbose - $pesterInstallations = Get-Module -ListAvailable -Name Pester - if ($pesterInstallations.Version -notcontains "4.10.1") { - Install-Module -Name Pester -RequiredVersion 4.10.1 -Force -Scope CurrentUser - } $importTarget = "Import-Module ${PSScriptRoot}/out/${ModuleName}" $importPester = "Import-Module Pester -Max 4.10.1" - $invokePester = "Invoke-Pester -OutputFormat NUnitXml -EnableExit -OutputFile ../Microsoft.PowerShell.TextUtility.xml" - $command = "${importTarget}; ${importPester}; ${invokePester}" + $invokePester = "Invoke-Pester -OutputFormat NUnitXml -EnableExit -OutputFile ../testResults.xml" + $sb = [scriptblock]::Create("${importTarget}; ${importPester}; ${invokePester}") Push-Location $testRoot - pwsh -noprofile -command $command + # calculate the shell to run rather than hardcoding it. + $PSEXE = (Get-Process -id $PID).MainModule.FileName + & $PSEXE -noprofile -command $sb } finally { Pop-Location } } +function Invoke-Bootstrap +{ + $neededPesterModule = Get-Module -Name Pester -ListAvailable | Where-Object { $_.Version -eq "4.10.1" } + $neededPesterVersion = [version]"4.10.1" + if ($neededPesterModule.Version -eq $neededPesterVersion) + { + Write-Verbose -Verbose -Message "Required pester version $neededPesterVersion is available." + return + } + + Write-Verbose -Verbose -Message "Attempting install of Pester version ${neededPesterVersion}." + Install-Module -Name Pester -Scope CurrentUser -RequiredVersion 4.10.1 -Force -SkipPublisherCheck + $neededPesterModule = Get-Module -Name Pester -ListAvailable | Where-Object { $_.Version -eq $neededPesterVersion } + if ($neededPesterModule.Version -ne $neededPesterVersion) + { + throw "Pester install failed" + } + + Write-Verbose -Verbose -Message "Pester version $neededPesterVersion installed." + return +} + + try { Push-Location "$PSScriptRoot/src/code" $script:moduleInfo = Get-ModuleInfo @@ -112,6 +137,11 @@ try { return $moduleInfo.ModuleVersion } + if ($Bootstrap) { + Invoke-Bootstrap + return + } + $outPath = "$PSScriptRoot/out/${moduleName}" if ($Clean) { if (Test-Path $outPath) { @@ -132,19 +162,6 @@ try { if ($Test) { Test-Module - - <# - $script = [ScriptBlock]::Create("try { - Import-Module '${repoRoot}/out/${moduleName}/' - Import-Module -Name Pester -Max 4.99 - Push-Location '${repoRoot}/test' - Invoke-Pester - } - finally { - Pop-Location - }") - pwsh -c $script - #> return } diff --git a/src/Microsoft.PowerShell.TextUtility.psd1 b/src/Microsoft.PowerShell.TextUtility.psd1 index ddb5209..35ce7e1 100644 --- a/src/Microsoft.PowerShell.TextUtility.psd1 +++ b/src/Microsoft.PowerShell.TextUtility.psd1 @@ -10,7 +10,7 @@ CompanyName = 'Microsoft Corporation' Copyright = '(c) Microsoft Corporation. All rights reserved.' Description = "This module contains cmdlets to help with manipulating or reading text." - PowerShellVersion = '5.1' + PowerShellVersion = '7.0' FormatsToProcess = @('Microsoft.PowerShell.TextUtility.format.ps1xml') CmdletsToExport = @( 'Compare-Text','ConvertFrom-Base64','ConvertTo-Base64',"ConvertFrom-TextTable" diff --git a/test/TextTableParser.Tests.ps1 b/test/TextTableParser.Tests.ps1 index fc2643b..c128447 100644 --- a/test/TextTableParser.Tests.ps1 +++ b/test/TextTableParser.Tests.ps1 @@ -138,7 +138,7 @@ Describe "Test text table parser" { It "Should create proper json from '' " -testCases $testCases { param ($FileName, $convertArgs, $rows, $Results) - $Path = Join-Path $PSScriptRoot assets $FileName + $Path = [io.path]::Combine($PSScriptRoot, "assets", $FileName) # do not alter convertArgs directly as it is a reference rather than a copy $localArgs = $convertArgs.Clone() $localArgs['AsJson'] = $true @@ -158,7 +158,7 @@ Describe "Test text table parser" { Context "Test PSObject output" { It "Should create proper psobject from '' " -testCases $testCases { param ($FileName, $convertArgs, $rows, $Results ) - $Path = Join-Path $PSScriptRoot assets $FileName + $Path = [io.path]::Combine($PSScriptRoot, "assets", $FileName) $result = Get-Content $Path | ConvertFrom-TextTable @convertArgs $result | Should -BeOfType System.Management.Automation.PSObject $result.Count | Should -Be $Rows @@ -180,7 +180,7 @@ Describe "Test text table parser" { @{ Name = "Property_04"; Value = "34567890123456789" } @{ Name = "Property_05"; Value = "012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789" } ) - $testFile = Join-Path $PSScriptRoot assets "columns.01.txt" + $testFile = [io.path]::Combine($PSScriptRoot, "assets", "columns.01.txt") $result = Get-Content $testFile | ConvertFrom-TextTable -ColumnOffset 0,5,13,23,40 -noheader $line = 0 $testCases = $result.ForEach({@{Result = $_; Line = $line++}})