From 405ed02b35243429a2569e621ee15b51e16caf05 Mon Sep 17 00:00:00 2001 From: Mikey Lombardi Date: Wed, 8 Oct 2025 13:04:24 -0500 Subject: [PATCH] (MAINT) Minimally Parallelize pester tests Prior to this change, the pester tests made up the majority of the build time in CI. This change attempts to speed up the pester tests by parallelizing them roughly by folder: - The tests in the `dsc` folder run in their own cell. - The tests in the `adapters` folder run in their own cell. - The tests in the `extensions` folder run in their own cell. - The tests in the `resources` folder run in their own cell. This should substantially reduce the time spent on tests, particularly on Windows, where the CLI tests take much longer. This change makes minor changes to the new build script and helpers to support targeted test execution. --- .github/workflows/rust.new.yml | 158 +++++++++++++++++++++++++-------- build.helpers.psm1 | 30 ++++++- build.new.ps1 | 77 +++++++++++----- 3 files changed, 205 insertions(+), 60 deletions(-) diff --git a/.github/workflows/rust.new.yml b/.github/workflows/rust.new.yml index 316bf09fe..665e8c931 100644 --- a/.github/workflows/rust.new.yml +++ b/.github/workflows/rust.new.yml @@ -14,45 +14,133 @@ on: env: CARGO_TERM_COLOR: always +defaults: + run: + shell: pwsh + jobs: - build-linux-new: + linux-build: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v5 - - name: Install prerequisites - shell: pwsh - run: ./build.new.ps1 -SkipBuild -Clippy -Verbose - - name: Build - shell: pwsh - run: ./build.new.ps1 -Clippy -Verbose - - name: Run tests - shell: pwsh - run: ./build.new.ps1 -Test -Verbose - - build-windows-new: - runs-on: windows-latest + - uses: actions/checkout@v5 + - name: Install prerequisites + run: ./build.new.ps1 -SkipBuild -Clippy -Verbose + - name: Build + run: ./build.new.ps1 -Clippy -Verbose + - name: Run rust tests + run: ./build.new.ps1 -SkipBuild -Test -ExcludePesterTests -Verbose + - name: Prepare build artifact + run: tar -cvf bin.tar bin/ + - name: Upload build artifact + uses: actions/upload-artifact@v4 + with: + name: linux-bin + path: bin.tar + linux-pester: + needs: linux-build + strategy: + matrix: + group: [dsc, adapters, extensions, resources] + runs-on: ubuntu-latest steps: - - uses: actions/checkout@v5 - - name: Install prerequisites - shell: pwsh - run: ./build.new.ps1 -SkipBuild -Clippy -Verbose - - name: Build - shell: pwsh - run: ./build.new.ps1 -Clippy -Verbose - - name: Run tests - shell: pwsh - run: ./build.new.ps1 -Test -Verbose + - uses: actions/checkout@v5 + - name: Download build artifact + uses: actions/download-artifact@v4 + with: + name: linux-bin + - name: Expand build artifact + run: tar -xvf bin.tar + - name: Test ${{matrix.group}} + run: |- + $params = @{ + SkipBuild = $true + Test = $true + ExcludeRustTests = $true + Verbose = $true + } + ./build.new.ps1 @params -PesterTestGroup ${{matrix.group}} - build-macos-new: + macos-build: + runs-on: macos-latest + steps: + - uses: actions/checkout@v5 + - name: Install prerequisites + run: ./build.new.ps1 -SkipBuild -Clippy -Verbose + - name: Build + run: ./build.new.ps1 -Clippy -Verbose + - name: Run rust tests + run: ./build.new.ps1 -SkipBuild -Test -ExcludePesterTests -Verbose + - name: Prepare build artifact + run: tar -cvf bin.tar bin/ + - name: Upload build artifact + uses: actions/upload-artifact@v4 + with: + name: macos-bin + path: bin.tar + macos-pester: + needs: macos-build + strategy: + matrix: + group: [dsc, adapters, extensions, resources] runs-on: macos-latest steps: - - uses: actions/checkout@v5 - - name: Install prerequisites - shell: pwsh - run: ./build.new.ps1 -SkipBuild -Clippy -Verbose - - name: Build - shell: pwsh - run: ./build.new.ps1 -Clippy -Verbose - - name: Run tests - shell: pwsh - run: ./build.new.ps1 -Test -Verbose + - uses: actions/checkout@v5 + - name: Download build artifact + uses: actions/download-artifact@v4 + with: + name: macos-bin + - name: Expand build artifact + run: tar -xvf bin.tar + - name: Test ${{matrix.group}} + run: |- + $params = @{ + SkipBuild = $true + Test = $true + ExcludeRustTests = $true + Verbose = $true + } + ./build.new.ps1 @params -PesterTestGroup ${{matrix.group}} + + # Windows + windows-build: + runs-on: windows-latest + steps: + - uses: actions/checkout@v5 + - name: Install prerequisites + run: ./build.new.ps1 -SkipBuild -Clippy -Verbose + - name: Build + run: ./build.new.ps1 -Clippy -Verbose + - name: Run rust tests + run: ./build.new.ps1 -SkipBuild -Test -ExcludePesterTests -Verbose + - name: List bin folder files + run: Get-ChildItem bin + - name: Prepare build artifact + run: tar -cvf bin.tar bin + - name: Upload build artifact + uses: actions/upload-artifact@v4 + with: + name: windows-bin + path: bin.tar + windows-pester: + needs: windows-build + strategy: + matrix: + group: [dsc, adapters, extensions, resources] + runs-on: windows-latest + steps: + - uses: actions/checkout@v5 + - name: Download build artifact + uses: actions/download-artifact@v4 + with: + name: windows-bin + - name: Expand build artifact + run: tar -xvf bin.tar + - name: Test ${{matrix.group}} + run: |- + $params = @{ + SkipBuild = $true + Test = $true + ExcludeRustTests = $true + Verbose = $true + } + ./build.new.ps1 @params -PesterTestGroup ${{matrix.group}} diff --git a/build.helpers.psm1 b/build.helpers.psm1 index e96dc6834..bbb575915 100644 --- a/build.helpers.psm1 +++ b/build.helpers.psm1 @@ -1274,6 +1274,9 @@ function Test-RustProject { function Test-ProjectWithPester { [cmdletbinding()] param( + [DscProjectDefinition[]]$Project, + [ValidateSet("dsc", "adapters", "extensions", "grammars", "resources")] + [string[]]$Group, [switch]$UsingADO ) @@ -1297,10 +1300,35 @@ function Test-ProjectWithPester { Write-Verbose "Updated Pester module location:`n`t$((Get-Module -Name Pester -ListAvailable).Path)" } + $pesterParams = @{ + Output = 'Detailed' + ErrorAction = 'Stop' + } + if ($Project) { + $pesterParams.ExcludePath = $Project.RelativePath | Where-Object -FilterScript { + $_.Name -notin $Project.Name + } + } + if ($Group) { + $pesterParams.Path = $Group + } } process { - Invoke-Pester -Output Detailed -ErrorAction Stop + if ($Group -and $Project) { + Write-Verbose (@( + "Invoking pester for groups and projects:" + "Groups: [$($Group -join ', ')]" + "Projects: [$($Project.Name -join ', ')]" + ) -join "`n`t") + } elseif ($Group) { + Write-Verbose "Invoking pester for groups: [$($Group -join ', ')]" + } elseif ($Project) { + Write-Verbose "Invoking pester for projects: [$($Project.Name -join ', ')]" + } else { + Write-Verbose "Invoking pester for all groups and projects" + } + Invoke-Pester @pesterParams } } #endregion Test project functions diff --git a/build.new.ps1 b/build.new.ps1 index b50a88050..dd697fe30 100644 --- a/build.new.ps1 +++ b/build.new.ps1 @@ -83,6 +83,11 @@ param( )] $PackageType, [switch]$Test, + [string[]]$Project, + [switch]$ExcludeRustTests, + [switch]$ExcludePesterTests, + [ValidateSet("dsc", "adapters", "extensions", "grammars", "resources")] + [string[]]$PesterTestGroup, [switch]$GetPackageVersion, [switch]$SkipLinkCheck, [switch]$UseX64MakeAppx, @@ -110,7 +115,14 @@ begin { if ($usingADO -or $UseCFSAuth) { $UseCFS = $true } + # Import the build data $BuildData = Import-DscBuildData + # Filter projects if needed. + if ($Project.Count -ge 1) { + $BuildData.Projects = $BuildData.Projects | Where-Object -FilterScript { + $_.Name -in $Project + } + } $VerboseParam = @{} if ($VerbosePreference -eq 'Continue' -and -not $Quiet) { $VerboseParam.Verbose = $true @@ -177,27 +189,29 @@ process { Write-BuildProgress @progressParams -Status 'Ensuring Rust is up-to-date' Update-Rust @VerboseParam } - + if (!$usingADO) { Write-BuildProgress @progressParams -Status 'Setting RustUp to default channel' $rustup, $channel = Get-RustUp @VerboseParam & $rustup default stable } - + if ($Clippy) { Write-BuildProgress @progressParams -Status 'Ensuring Clippy is available and updated' Install-Clippy -UseCFS:$UseCFS -Architecture $Architecture @VerboseParam } + + if (-not ($SkipBuild -and $Test -and $ExcludeRustTests)) { + # Install Node if needed + Write-BuildProgress @progressParams -Status 'Ensuring Node.JS is available' + Install-NodeJS @VerboseParam - # Install Node if needed - Write-BuildProgress @progressParams -Status 'Ensuring Node.JS is available' - Install-NodeJS @VerboseParam - - # Ensure tree-sitter is installed - Write-BuildProgress @progressParams -Status 'Ensuring tree-sitter is available' - Install-TreeSitter -UseCFS:$UseCFS @VerboseParam + # Ensure tree-sitter is installed + Write-BuildProgress @progressParams -Status 'Ensuring tree-sitter is available' + Install-TreeSitter -UseCFS:$UseCFS @VerboseParam + } } - + if (!$SkipBuild -and !$SkipLinkCheck -and $IsWindows) { Write-BuildProgress @progressParams -Status "Ensuring Windows C++ build tools are available" Install-WindowsCPlusPlusBuildTools @VerboseParam @@ -220,29 +234,44 @@ process { Write-BuildProgress @progressParams -Status "Copying build artifacts" Copy-BuildArtifact @buildParams -ExecutableFile $BuildData.PackageFiles.Executable @VerboseParam } - - if (!$Clippy -and !$SkipBuild) { + + # Ensure PATH includes the output artifacts after building and before testing. + if ((!$Clippy -and !$SkipBuild) -or $Test) { $progressParams.Activity = 'Updating environment variables' Write-BuildProgress @progressParams Update-PathEnvironment -Architecture $Architecture -Release:$Release @VerboseParam } - + if ($Test) { $progressParams.Activity = 'Testing projects' Write-BuildProgress @progressParams - Write-BuildProgress @progressParams -Status "Installing PowerShell test prerequisites" - Install-PowerShellTestPrerequisite @VerboseParam -UsingAdo:$usingADO - $testParams = @{ - Project = $BuildData.Projects - Architecture = $Architecture - Release = $Release + + if (-not $ExcludeRustTests) { + $rustTestParams = @{ + Project = $BuildData.Projects + Architecture = $Architecture + Release = $Release + } + Write-BuildProgress @progressParams -Status "Testing Rust projects" + Test-RustProject @rustTestParams @VerboseParam + } + if (-not $ExcludePesterTests) { + $installParams = @{ + UsingADO = $usingADO + } + $pesterParams = @{ + UsingADO = $usingADO + } + if ($null -ne $PesterTestGroup) { + $pesterParams.Group = $PesterTestGroup + } + Write-BuildProgress @progressParams -Status "Installing PowerShell test prerequisites" + Install-PowerShellTestPrerequisite @installParams @VerboseParam + Write-BuildProgress @progressParams -Status "Invoking pester" + Test-ProjectWithPester @pesterParams @VerboseParam } - Write-BuildProgress @progressParams -Status "Testing Rust projects" - Test-RustProject @testParams @VerboseParam - Write-BuildProgress @progressParams -Status "Invoking pester" - Test-ProjectWithPester -UsingADO:$usingADO @VerboseParam } - + if (-not [string]::IsNullOrEmpty($PackageType)) { $progressParams.Activity = "Packaging" $packageParams = @{