mirror of
https://github.com/GoodOlClint/PSProxmoxVE.git
synced 2026-09-03 18:55:33 +00:00
122e79407c
Two filed issues in one rewrite of preflight-cleanup.sh's ISO block, because they are the same twenty lines. #111 — ISO_FILENAME was interpolated into python3 -c PROGRAM TEXT inside a single-quoted literal, so a quote in the value escaped it and executed arbitrary Python in a container holding PVE_API_TOKEN, PVE_PASSWORD, the Terraform state and the storage VM's SSH key. It now arrives through the environment and is read with os.environ. The volid is passed to urllib's quote() via argv for the same reason, and an empty encode result now skips the volume instead of issuing a DELETE against the bare collection URL. #105 — generated ISOs embed a hash of first-boot.sh, so every change to that script mints a new filename. Deleting only the exact current name orphaned each earlier ISO on the storage permanently, because force-cleanup wipes the Terraform state that could otherwise reclaim it. The family is now swept by rebuilding the full generated shape: the captured prefix plus twelve hex characters plus .iso. A prefix test alone would also have matched a longer FQDN's family and any hand-uploaded "-manual-backup.iso" sibling, which in a script whose job is deletion is worse than the leak it fixes. Multi-delete applies only to that family. A name that is not generated — the storage VM's cloud image — keeps the original one-shot behaviour, since a basename can repeat across content namespaces and a plain name carries nothing that identifies a family. Adds preflight-cleanup.test.sh, wired into shell-selfchecks. The script had no coverage at all. It stubs curl and sleep, then asserts on the DELETEs issued: the family goes, the pinned base ISO and unrelated uploads stay, a non-hash sibling stays, the cloud image takes only itself, a quoted payload is data rather than code, and unset storage skips only the ISO branch. Every case also asserts the script ran to completion and removed the Terraform state, so a path that dies early cannot pass by having issued the right DELETEs first.
183 lines
6.5 KiB
YAML
183 lines
6.5 KiB
YAML
name: Unit Tests
|
|
|
|
on:
|
|
push:
|
|
branches: [ main ]
|
|
pull_request:
|
|
branches: [ main ]
|
|
|
|
jobs:
|
|
# ── Build module artifacts (only job that needs .NET SDK) ──────────
|
|
build:
|
|
runs-on: ${{ matrix.os }}
|
|
timeout-minutes: 10
|
|
strategy:
|
|
fail-fast: false
|
|
matrix:
|
|
include:
|
|
- os: windows-latest
|
|
framework: netstandard2.0
|
|
- os: ubuntu-latest
|
|
framework: netstandard2.0
|
|
|
|
steps:
|
|
- uses: actions/checkout@v7
|
|
|
|
- name: Setup .NET
|
|
uses: actions/setup-dotnet@v6
|
|
with:
|
|
dotnet-version: '10.0.x'
|
|
|
|
- name: Build module
|
|
run: dotnet publish src/PSProxmoxVE/PSProxmoxVE.csproj --configuration Release --framework ${{ matrix.framework }} --output ./publish/${{ matrix.framework }}
|
|
|
|
- name: Clean publish output for PS module loading
|
|
shell: bash
|
|
run: rm -f ./publish/${{ matrix.framework }}/*.deps.json ./publish/${{ matrix.framework }}/*.runtimeconfig.json
|
|
|
|
- name: Upload module artifact
|
|
uses: actions/upload-artifact@v7
|
|
with:
|
|
name: module-${{ matrix.framework }}-${{ matrix.os }}
|
|
path: ./publish/${{ matrix.framework }}/
|
|
|
|
# ── Pester tests (no .NET SDK — just PowerShell + Pester) ─────────
|
|
pester-tests:
|
|
needs: build
|
|
timeout-minutes: 15
|
|
strategy:
|
|
fail-fast: false
|
|
matrix:
|
|
include:
|
|
- os: windows-latest
|
|
ps_version: '5.1'
|
|
framework: netstandard2.0
|
|
artifact_os: windows-latest
|
|
shell: powershell
|
|
- os: windows-latest
|
|
ps_version: '7.5'
|
|
framework: netstandard2.0
|
|
artifact_os: windows-latest
|
|
shell: pwsh
|
|
- os: ubuntu-latest
|
|
ps_version: '7.5'
|
|
framework: netstandard2.0
|
|
artifact_os: ubuntu-latest
|
|
shell: pwsh
|
|
- os: macos-latest
|
|
ps_version: '7.5'
|
|
framework: netstandard2.0
|
|
artifact_os: ubuntu-latest
|
|
shell: pwsh
|
|
|
|
runs-on: ${{ matrix.os }}
|
|
|
|
steps:
|
|
- uses: actions/checkout@v7
|
|
|
|
- name: Download module artifact
|
|
uses: actions/download-artifact@v8
|
|
with:
|
|
name: module-${{ matrix.framework }}-${{ matrix.artifact_os }}
|
|
path: ./publish/${{ matrix.framework }}/
|
|
|
|
- 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'
|
|
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"
|
|
New-Item -ItemType Directory -Path $modulePath -Force | Out-Null
|
|
Copy-Item -Path .\publish\${{ matrix.framework }}\* -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: 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: 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'
|
|
shell: pwsh
|
|
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: Upload test results
|
|
if: always()
|
|
uses: actions/upload-artifact@v7
|
|
with:
|
|
name: pester-results-${{ matrix.os }}-ps${{ matrix.ps_version }}
|
|
path: TestResults/
|
|
|
|
# ── CI infrastructure shell self-checks ─────────────────────────────
|
|
# These guard the provisioning and reporting scripts, whose real exercise is
|
|
# a ~45-minute nested-PVE run. They stub ssh/gh/git and finish in seconds, so
|
|
# a regression in them is caught on the PR rather than a week later.
|
|
shell-selfchecks:
|
|
runs-on: ubuntu-latest
|
|
timeout-minutes: 5
|
|
steps:
|
|
- uses: actions/checkout@v7
|
|
with:
|
|
persist-credentials: false
|
|
|
|
- name: prepare-test-environment self-check
|
|
run: bash tests/infrastructure/scripts/prepare-test-environment.test.sh
|
|
|
|
- name: report-package-currency self-check
|
|
run: bash tests/infrastructure/scripts/report-package-currency.test.sh
|
|
|
|
- name: preflight-cleanup self-check
|
|
run: bash tests/infrastructure/scripts/preflight-cleanup.test.sh
|
|
|
|
- name: Shell syntax check
|
|
run: |
|
|
for f in tests/infrastructure/scripts/*.sh; do
|
|
bash -n "$f" || exit 1
|
|
done
|