diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 0db4b5d..141229e 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -10,11 +10,11 @@ jobs: build-net48: runs-on: windows-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - name: Setup .NET - uses: actions/setup-dotnet@v4 + uses: actions/setup-dotnet@v5 with: - dotnet-version: '8.0.x' + dotnet-version: '9.0.x' - name: Restore dependencies run: dotnet restore - name: Build net48 @@ -27,25 +27,25 @@ jobs: name: coverage-net48 path: ./coverage - build-net8: + build-net9: strategy: matrix: os: [windows-latest, ubuntu-latest] runs-on: ${{ matrix.os }} steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - name: Setup .NET - uses: actions/setup-dotnet@v4 + uses: actions/setup-dotnet@v5 with: - dotnet-version: '8.0.x' + dotnet-version: '9.0.x' - name: Restore dependencies run: dotnet restore - - name: Build net8.0 - run: dotnet build --configuration Release --framework net8.0 --no-restore - - name: Test net8.0 - run: dotnet test tests/PSProxmoxVE.Core.Tests/PSProxmoxVE.Core.Tests.csproj --configuration Release --framework net8.0 --no-build --verbosity normal --collect:"XPlat Code Coverage" --results-directory ./coverage + - 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 uses: actions/upload-artifact@v4 with: - name: coverage-net8-${{ matrix.os }} + name: coverage-net9-${{ matrix.os }} path: ./coverage diff --git a/.github/workflows/integration-tests.yml b/.github/workflows/integration-tests.yml index 7f1e3a8..ecbc783 100644 --- a/.github/workflows/integration-tests.yml +++ b/.github/workflows/integration-tests.yml @@ -48,7 +48,7 @@ jobs: timeout-minutes: 45 steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 # ── Pre-flight cleanup ───────────────────────────────────────────── @@ -217,7 +217,7 @@ jobs: - name: Upload test results if: always() - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v5 with: name: integration-test-results path: TestResults/ diff --git a/.github/workflows/mock-integration-tests.yml b/.github/workflows/mock-integration-tests.yml index e924e0c..c465fcc 100644 --- a/.github/workflows/mock-integration-tests.yml +++ b/.github/workflows/mock-integration-tests.yml @@ -18,27 +18,27 @@ jobs: matrix: include: - os: ubuntu-latest - framework: net10.0 + framework: net9.0 shell: pwsh - os: windows-latest - framework: net10.0 + framework: net9.0 shell: pwsh runs-on: ${{ matrix.os }} steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - name: Setup .NET - uses: actions/setup-dotnet@v4 + uses: actions/setup-dotnet@v5 with: - dotnet-version: '10.0.x' + dotnet-version: '9.0.x' - name: Build mock server run: dotnet build tests/PSProxmoxVE.MockServer/PSProxmoxVE.MockServer.csproj --configuration Release - name: Build module - run: dotnet publish src/PSProxmoxVE/PSProxmoxVE.csproj --configuration Release --framework net10.0 --output ./publish/net10.0 + run: dotnet publish src/PSProxmoxVE/PSProxmoxVE.csproj --configuration Release --framework net9.0 --output ./publish/net9.0 - name: Install Pester 5 shell: pwsh @@ -50,7 +50,7 @@ jobs: run: | $modulePath = "$env:USERPROFILE\Documents\PowerShell\Modules\PSProxmoxVE" New-Item -ItemType Directory -Path $modulePath -Force | Out-Null - Copy-Item -Path .\publish\net10.0\* -Destination $modulePath -Recurse -Force + Copy-Item -Path .\publish\net9.0\* -Destination $modulePath -Recurse -Force - name: Copy module to module path (Linux) if: matrix.os != 'windows-latest' @@ -58,7 +58,7 @@ jobs: run: | $modulePath = "$HOME/.local/share/powershell/Modules/PSProxmoxVE" New-Item -ItemType Directory -Path $modulePath -Force | Out-Null - Copy-Item -Path ./publish/net10.0/* -Destination $modulePath -Recurse -Force + Copy-Item -Path ./publish/net9.0/* -Destination $modulePath -Recurse -Force - name: Run mock integration tests shell: pwsh diff --git a/.github/workflows/unit-tests.yml b/.github/workflows/unit-tests.yml index 7ba379c..cf10e5d 100644 --- a/.github/workflows/unit-tests.yml +++ b/.github/workflows/unit-tests.yml @@ -16,50 +16,28 @@ jobs: ps_version: '5.1' framework: net48 shell: powershell - - os: windows-latest - ps_version: '7.2' - framework: net8.0 - shell: pwsh - os: windows-latest ps_version: '7.5' - framework: net8.0 - shell: pwsh - - os: ubuntu-latest - ps_version: '7.2' - framework: net8.0 + framework: net9.0 shell: pwsh - os: ubuntu-latest ps_version: '7.5' - framework: net8.0 + framework: net9.0 shell: pwsh - os: macos-latest ps_version: '7.5' - framework: net8.0 + framework: net9.0 shell: pwsh runs-on: ${{ matrix.os }} steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - name: Setup .NET - uses: actions/setup-dotnet@v4 + uses: actions/setup-dotnet@v5 with: - dotnet-version: '8.0.x' - - - name: Install PowerShell 7.2 (Windows) - if: matrix.ps_version == '7.2' && matrix.os == 'windows-latest' - shell: pwsh - run: | - winget install --id Microsoft.PowerShell --version 7.2 --accept-source-agreements --accept-package-agreements --silent - continue-on-error: true - - - name: Install PowerShell 7.2 (Linux) - if: matrix.ps_version == '7.2' && matrix.os == 'ubuntu-latest' - run: | - wget -q https://github.com/PowerShell/PowerShell/releases/download/v7.2.24/powershell_7.2.24-1.deb_amd64.deb - sudo dpkg -i powershell_7.2.24-1.deb_amd64.deb - sudo apt-get install -f -y + dotnet-version: '9.0.x' - name: Build module run: dotnet publish src/PSProxmoxVE/PSProxmoxVE.csproj --configuration Release --framework ${{ matrix.framework }} --output ./publish/${{ matrix.framework }} diff --git a/tests/PSProxmoxVE.Core.Tests/PSProxmoxVE.Core.Tests.csproj b/tests/PSProxmoxVE.Core.Tests/PSProxmoxVE.Core.Tests.csproj index 3b9383c..a83780d 100644 --- a/tests/PSProxmoxVE.Core.Tests/PSProxmoxVE.Core.Tests.csproj +++ b/tests/PSProxmoxVE.Core.Tests/PSProxmoxVE.Core.Tests.csproj @@ -1,7 +1,7 @@ - net10.0;net48 + net9.0;net48 10.0 enable false diff --git a/tests/PSProxmoxVE.MockServer/PSProxmoxVE.MockServer.csproj b/tests/PSProxmoxVE.MockServer/PSProxmoxVE.MockServer.csproj index a3a34b6..6568b3d 100644 --- a/tests/PSProxmoxVE.MockServer/PSProxmoxVE.MockServer.csproj +++ b/tests/PSProxmoxVE.MockServer/PSProxmoxVE.MockServer.csproj @@ -1,7 +1,7 @@ - net10.0 + net9.0 enable enable diff --git a/tests/PSProxmoxVE.Tests/Integration/Integration.Tests.ps1 b/tests/PSProxmoxVE.Tests/Integration/Integration.Tests.ps1 index 1b97964..4603e48 100644 --- a/tests/PSProxmoxVE.Tests/Integration/Integration.Tests.ps1 +++ b/tests/PSProxmoxVE.Tests/Integration/Integration.Tests.ps1 @@ -77,7 +77,7 @@ BeforeAll { # Track resources created during the run so AfterAll can clean up. $script:CreatedVmIds = [System.Collections.Generic.List[int]]::new() - $script:CreatedVmSnaps = [System.Collections.Generic.List[hashtable]]::new() + $script:TestVmId = $null } AfterAll { @@ -85,6 +85,8 @@ AfterAll { if ($null -eq $script:SkipReason -and $script:CreatedVmIds.Count -gt 0) { foreach ($vmId in $script:CreatedVmIds) { try { + Stop-PveVm -Node $script:Node -VmId $vmId -ErrorAction SilentlyContinue | Out-Null + Start-Sleep -Seconds 3 Remove-PveVm -Node $script:Node -VmId $vmId -Force -Purge -Confirm:$false -ErrorAction SilentlyContinue } catch { <# non-fatal #> } @@ -153,7 +155,7 @@ Describe 'Integration Tests' -Tag 'Integration' { { Get-PveVm -Node $script:Node -ErrorAction Stop } | Should -Not -Throw } - It 'Should create and remove a test VM' { + It 'Should create a test VM' { if ($script:SkipReason) { Set-ItResult -Skipped -Because $script:SkipReason; return } $task = New-PveVm ` @@ -170,34 +172,22 @@ Describe 'Integration Tests' -Tag 'Integration' { Select-Object -First 1 $vm | Should -Not -BeNullOrEmpty + $script:TestVmId = $vm.VmId $script:CreatedVmIds.Add($vm.VmId) - - $removeTask = Remove-PveVm ` - -Node $script:Node ` - -VmId $vm.VmId ` - -Confirm:$false ` - -Wait - - $removeTask | Should -Not -BeNullOrEmpty - $script:CreatedVmIds.Remove($vm.VmId) | Out-Null } It 'Should start and stop a VM' { if ($script:SkipReason) { Set-ItResult -Skipped -Because $script:SkipReason; return } - # Requires at least one VM on the test node; skip if none found. - $vm = Get-PveVm -Node $script:Node | Where-Object { $_.Status -eq 'stopped' } | - Select-Object -First 1 - - if ($null -eq $vm) { - Set-ItResult -Skipped -Because 'No stopped VM available on the test node' + if ($null -eq $script:TestVmId) { + Set-ItResult -Skipped -Because 'No test VM was created' return } - $startTask = Start-PveVm -Node $script:Node -VmId $vm.VmId -Wait + $startTask = Start-PveVm -Node $script:Node -VmId $script:TestVmId -Wait $startTask | Should -Not -BeNullOrEmpty - $stopTask = Stop-PveVm -Node $script:Node -VmId $vm.VmId -Wait + $stopTask = Stop-PveVm -Node $script:Node -VmId $script:TestVmId -Wait $stopTask | Should -Not -BeNullOrEmpty } @@ -260,31 +250,34 @@ Describe 'Integration Tests' -Tag 'Integration' { It 'Should create and remove a snapshot' { if ($script:SkipReason) { Set-ItResult -Skipped -Because $script:SkipReason; return } - $vm = Get-PveVm -Node $script:Node | Where-Object { $_.Status -eq 'stopped' } | - Select-Object -First 1 - - if ($null -eq $vm) { - Set-ItResult -Skipped -Because 'No stopped VM available for snapshot test' + if ($null -eq $script:TestVmId) { + Set-ItResult -Skipped -Because 'No test VM was created' return } + # Ensure the VM is stopped for snapshot + $vm = Get-PveVm -Node $script:Node | Where-Object { $_.VmId -eq $script:TestVmId } + if ($vm.Status -eq 'running') { + Stop-PveVm -Node $script:Node -VmId $script:TestVmId -Wait | Out-Null + } + $snapName = 'pester-snap' $createTask = New-PveSnapshot ` -Node $script:Node ` - -VmId $vm.VmId ` + -VmId $script:TestVmId ` -Name $snapName ` -Description 'Created by Pester integration test' ` -Wait $createTask | Should -Not -BeNullOrEmpty - $snapshots = Get-PveSnapshot -Node $script:Node -VmId $vm.VmId + $snapshots = Get-PveSnapshot -Node $script:Node -VmId $script:TestVmId $snapshots | Where-Object { $_.Name -eq $snapName } | Should -Not -BeNullOrEmpty $removeTask = Remove-PveSnapshot ` -Node $script:Node ` - -VmId $vm.VmId ` + -VmId $script:TestVmId ` -Name $snapName ` -Confirm:$false ` -Wait @@ -330,16 +323,13 @@ Describe 'Integration Tests' -Tag 'Integration' { It 'Should get cloud-init config' { if ($script:SkipReason) { Set-ItResult -Skipped -Because $script:SkipReason; return } - $ciVm = Get-PveVm -Node $script:Node | Where-Object { $_.Status -eq 'stopped' } | - Select-Object -First 1 - - if ($null -eq $ciVm) { - Set-ItResult -Skipped -Because 'No stopped VM available for cloud-init test' + if ($null -eq $script:TestVmId) { + Set-ItResult -Skipped -Because 'No test VM available for cloud-init test' return } # Get-PveCloudInitConfig should not throw even if the VM has no cloud-init drive. - { Get-PveCloudInitConfig -Node $script:Node -VmId $ciVm.VmId -ErrorAction Stop } | + { Get-PveCloudInitConfig -Node $script:Node -VmId $script:TestVmId -ErrorAction Stop } | Should -Not -Throw } }