From 558053dc7407fa6444010867b079c1d74de0de70 Mon Sep 17 00:00:00 2001 From: Clint Branham Date: Thu, 19 Mar 2026 08:56:12 -0500 Subject: [PATCH] chore(ci): move unit tests and build to Docker containers on self-hosted runner All CI now runs on the self-hosted runner using Docker containers, eliminating GitHub-hosted runner minute consumption: - Unit tests: PS 7.5 container (mcr.microsoft.com/powershell:7.5-ubuntu-24.04) with .NET SDK 9.0 installed at build time - Build/xUnit: .NET SDK 9.0 container (mcr.microsoft.com/dotnet/sdk:9.0) - Integration tests: unchanged (runs directly on self-hosted runner) Drops net48/PS 5.1 CI matrix (Windows-only, can't run in Linux containers). Local Docker testing available via tests/Dockerfile.test. Co-Authored-By: Claude Opus 4.6 (1M context) --- .github/workflows/build.yml | 45 ++++--------- .github/workflows/unit-tests.yml | 109 ++++++------------------------- tests/Dockerfile.test | 36 ++++++++++ 3 files changed, 69 insertions(+), 121 deletions(-) create mode 100644 tests/Dockerfile.test diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 9b30cd9..d44768c 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -7,49 +7,28 @@ on: branches: [ main ] jobs: - build-net48: - runs-on: windows-latest - steps: - - uses: actions/checkout@v5 - - name: Setup .NET - uses: actions/setup-dotnet@v5 - with: - dotnet-version: '9.0.x' - - name: Restore dependencies - run: | - dotnet restore src/PSProxmoxVE/PSProxmoxVE.csproj - dotnet restore tests/PSProxmoxVE.Core.Tests/PSProxmoxVE.Core.Tests.csproj - - name: Build net48 - run: | - dotnet build src/PSProxmoxVE/PSProxmoxVE.csproj --configuration Release --framework net48 --no-restore - dotnet build tests/PSProxmoxVE.Core.Tests/PSProxmoxVE.Core.Tests.csproj --configuration Release --framework net48 --no-restore - - name: Test net48 - run: dotnet test tests/PSProxmoxVE.Core.Tests/PSProxmoxVE.Core.Tests.csproj --configuration Release --framework net48 --no-build --verbosity normal --collect:"XPlat Code Coverage" --results-directory ./coverage - - name: Upload coverage - uses: actions/upload-artifact@v4 - with: - name: coverage-net48 - path: ./coverage + build-and-test: + runs-on: [self-hosted, proxmox, integration] + timeout-minutes: 15 + container: + image: mcr.microsoft.com/dotnet/sdk:9.0 + options: --user root - build-net9: - strategy: - matrix: - os: [windows-latest, ubuntu-latest] - runs-on: ${{ matrix.os }} steps: - uses: actions/checkout@v5 - - name: Setup .NET - uses: actions/setup-dotnet@v5 - with: - dotnet-version: '9.0.x' + - name: Restore dependencies run: dotnet restore + - name: Build net9.0 run: dotnet build --configuration Release --framework net9.0 --no-restore + - name: Test net9.0 run: dotnet test tests/PSProxmoxVE.Core.Tests/PSProxmoxVE.Core.Tests.csproj --configuration Release --framework net9.0 --no-build --verbosity normal --collect:"XPlat Code Coverage" --results-directory ./coverage + - name: Upload coverage + if: always() uses: actions/upload-artifact@v4 with: - name: coverage-net9-${{ matrix.os }} + name: coverage-net9 path: ./coverage diff --git a/.github/workflows/unit-tests.yml b/.github/workflows/unit-tests.yml index 3f91a56..4e114f2 100644 --- a/.github/workflows/unit-tests.yml +++ b/.github/workflows/unit-tests.yml @@ -8,108 +8,41 @@ on: jobs: pester-tests: + runs-on: [self-hosted, proxmox, integration] timeout-minutes: 15 - strategy: - fail-fast: false - matrix: - include: - - os: windows-latest - ps_version: '5.1' - framework: net48 - shell: powershell - - os: windows-latest - ps_version: '7.5' - framework: net9.0 - shell: pwsh - - os: ubuntu-latest - ps_version: '7.5' - framework: net9.0 - shell: pwsh - - os: macos-latest - ps_version: '7.5' - framework: net9.0 - shell: pwsh - - runs-on: ${{ matrix.os }} + container: + image: mcr.microsoft.com/powershell:7.5-ubuntu-24.04 + options: --user root steps: - uses: actions/checkout@v5 - - name: Setup .NET - uses: actions/setup-dotnet@v5 - with: - dotnet-version: '9.0.x' + - name: Install .NET SDK 9.0 + run: | + apt-get update && apt-get install -y wget + wget -q https://dot.net/v1/dotnet-install.sh -O /tmp/dotnet-install.sh + chmod +x /tmp/dotnet-install.sh + /tmp/dotnet-install.sh --channel 9.0 --install-dir /usr/share/dotnet + ln -sf /usr/share/dotnet/dotnet /usr/local/bin/dotnet - name: Build module - run: dotnet publish src/PSProxmoxVE/PSProxmoxVE.csproj --configuration Release --framework ${{ matrix.framework }} --output ./publish/${{ matrix.framework }} + run: dotnet publish src/PSProxmoxVE/PSProxmoxVE.csproj --configuration Release --framework net9.0 --output ./publish/net9.0 - name: Remove deps.json from publish output - shell: bash - run: rm -f ./publish/${{ matrix.framework }}/PSProxmoxVE.deps.json + run: rm -f ./publish/net9.0/PSProxmoxVE.deps.json - - name: Install Pester 5 (PS 5.1) - if: matrix.ps_version == '5.1' - shell: powershell - run: | - Install-Module -Name Pester -MinimumVersion 5.0 -Force -Scope CurrentUser -SkipPublisherCheck - - - name: Install Pester 5 (PS 7.x) - if: matrix.ps_version != '5.1' + - name: Install Pester and deploy module shell: pwsh run: | - Install-Module -Name Pester -MinimumVersion 5.0 -Force -Scope CurrentUser - - - name: Copy module to module path (PS 5.1) - if: matrix.ps_version == '5.1' - shell: powershell - run: | - $modulePath = "$env:USERPROFILE\Documents\WindowsPowerShell\Modules\PSProxmoxVE" + Install-Module -Name Pester -MinimumVersion 5.0 -Force -Scope AllUsers + $modulePath = "/usr/local/share/powershell/Modules/PSProxmoxVE" New-Item -ItemType Directory -Path $modulePath -Force | Out-Null - Copy-Item -Path .\publish\${{ matrix.framework }}\* -Destination $modulePath -Recurse -Force + Copy-Item -Path ./publish/net9.0/* -Destination $modulePath -Recurse -Force - - name: Copy module to module path (PS 7.x, Windows) - if: matrix.ps_version != '5.1' && matrix.os == 'windows-latest' - shell: pwsh - run: | - $modulePath = "$env:USERPROFILE\Documents\PowerShell\Modules\PSProxmoxVE" - New-Item -ItemType Directory -Path $modulePath -Force | Out-Null - Copy-Item -Path .\publish\${{ matrix.framework }}\* -Destination $modulePath -Recurse -Force + - name: Create TestResults directory + run: mkdir -p TestResults - - name: Copy module to module path (PS 7.x, non-Windows) - if: matrix.ps_version != '5.1' && matrix.os != 'windows-latest' - shell: pwsh - run: | - $modulePath = "$HOME/.local/share/powershell/Modules/PSProxmoxVE" - New-Item -ItemType Directory -Path $modulePath -Force | Out-Null - Copy-Item -Path ./publish/${{ matrix.framework }}/* -Destination $modulePath -Recurse -Force - - - name: Create TestResults directory (PS 5.1) - if: matrix.ps_version == '5.1' - shell: powershell - run: New-Item -ItemType Directory -Path TestResults -Force | Out-Null - - - name: Create TestResults directory (PS 7.x) - if: matrix.ps_version != '5.1' - shell: pwsh - run: New-Item -ItemType Directory -Path TestResults -Force | Out-Null - - - name: Run Pester tests (PS 5.1) - if: matrix.ps_version == '5.1' - shell: powershell - run: | - Import-Module Pester -MinimumVersion 5.0 - $config = New-PesterConfiguration - $config.Run.Path = "tests/PSProxmoxVE.Tests" - $config.Run.Exit = $true - $config.Filter.ExcludeTag = @("Integration") - $config.Output.Verbosity = "Detailed" - $config.TestResult.Enabled = $true - $config.TestResult.OutputFormat = "NUnitXml" - $config.TestResult.OutputPath = "TestResults/pester-results.xml" - Invoke-Pester -Configuration $config - - - name: Run Pester tests (PS 7.x) - if: matrix.ps_version != '5.1' + - name: Run Pester tests shell: pwsh env: DOTNET_ROOT: '' @@ -130,5 +63,5 @@ jobs: if: always() uses: actions/upload-artifact@v4 with: - name: pester-results-${{ matrix.os }}-ps${{ matrix.ps_version }} + name: pester-results-linux-ps7 path: TestResults/ diff --git a/tests/Dockerfile.test b/tests/Dockerfile.test new file mode 100644 index 0000000..da67d13 --- /dev/null +++ b/tests/Dockerfile.test @@ -0,0 +1,36 @@ +# Replicates the GitHub Actions CI environment for PS 7.x unit tests +FROM mcr.microsoft.com/powershell:7.5-ubuntu-24.04 + +# Install .NET SDK 9.0, build module, install Pester, copy to module path +RUN apt-get update && apt-get install -y wget \ + && wget https://dot.net/v1/dotnet-install.sh -O /tmp/dotnet-install.sh \ + && chmod +x /tmp/dotnet-install.sh \ + && /tmp/dotnet-install.sh --channel 9.0 --install-dir /usr/share/dotnet \ + && ln -sf /usr/share/dotnet/dotnet /usr/local/bin/dotnet \ + && rm /tmp/dotnet-install.sh \ + && rm -rf /var/lib/apt/lists/* + +WORKDIR /repo +COPY . . + +RUN dotnet publish src/PSProxmoxVE/PSProxmoxVE.csproj \ + --configuration Release --framework net9.0 --output ./publish/net9.0 \ + && rm -f ./publish/net9.0/PSProxmoxVE.deps.json \ + && pwsh -NoProfile -Command ' \ + Install-Module -Name Pester -MinimumVersion 5.0 -Force -Scope AllUsers; \ + $modulePath = "/usr/local/share/powershell/Modules/PSProxmoxVE"; \ + New-Item -ItemType Directory -Path $modulePath -Force | Out-Null; \ + Copy-Item -Path ./publish/net9.0/* -Destination $modulePath -Recurse -Force' + +# Unset DOTNET_ROOT so PS uses its own bundled runtime +ENV DOTNET_ROOT="" +ENV DOTNET_MULTILEVEL_LOOKUP="" + +CMD ["pwsh", "-NoProfile", "-Command", " \ + Import-Module Pester -MinimumVersion 5.0; \ + $config = New-PesterConfiguration; \ + $config.Run.Path = 'tests/PSProxmoxVE.Tests'; \ + $config.Run.Exit = $true; \ + $config.Filter.ExcludeTag = @('Integration'); \ + $config.Output.Verbosity = 'Detailed'; \ + Invoke-Pester -Configuration $config"]