diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 00000000..be8d0507 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,43 @@ +name: CI + +on: + pull_request: + push: + branches: [ main ] + +concurrency: + group: ci-${{ github.ref }} + cancel-in-progress: true + +permissions: + contents: read + +jobs: + test: + name: Pester (${{ matrix.os }}) + runs-on: ${{ matrix.os }} + + # add job-scoped permissions needed for artifact upload + permissions: + contents: read + actions: write + + strategy: + fail-fast: false + matrix: + os: [ubuntu-latest, windows-latest, macos-latest] + + steps: + - uses: actions/checkout@v4 + + - name: Run Pester + shell: pwsh + run: pwsh -NoProfile -File ./tools/run-tests.ps1 -CI + + - name: Upload test results + if: always() + continue-on-error: true + uses: actions/upload-artifact@v4 + with: + name: test-results-${{ matrix.os }} + path: artifacts/test-results.xml diff --git a/.gitignore b/.gitignore index 69ab9fdd..1233d431 100644 --- a/.gitignore +++ b/.gitignore @@ -32,10 +32,11 @@ history/ *.log logs/ -# Coverage +# Coverage & Tests .coverage coverage/ coverage.* +test-results.* # Packages *.7z @@ -58,5 +59,6 @@ dist/ deploy/ build_output/ BuildOutput/ +artifacts/ # End of file \ No newline at end of file diff --git a/README.md b/README.md index 8e9f97a9..76943288 100644 --- a/README.md +++ b/README.md @@ -3,6 +3,7 @@ [![PowerShell](https://img.shields.io/badge/PowerShell-7%2B-blue)](#requirements) [![Pester](https://img.shields.io/badge/Tests-Pester%205-blueviolet)](#testing) [![License](https://img.shields.io/badge/License-See%20LICENSE-lightgrey)](LICENSE.md) +[![CI](https://github.com/blindzero/IdentityLifecycleEngine/actions/workflows/ci.yml/badge.svg)](https://github.com/blindzero/IdentityLifecycleEngine/actions/workflows/ci.yml) **IdLE** is a **generic, headless, configurable Identity or Account Lifecycle / JML (Joiner–Mover–Leaver) orchestration engine** built for **PowerShell**. diff --git a/tools/run-tests.ps1 b/tools/run-tests.ps1 new file mode 100644 index 00000000..0868ee7c --- /dev/null +++ b/tools/run-tests.ps1 @@ -0,0 +1,54 @@ +[CmdletBinding()] +param( + [Parameter()] + [string] $TestPath = 'tests', + + [Parameter()] + [switch] $CI, + + [Parameter()] + [string] $TestResultsPath = 'artifacts/test-results.xml' +) + +Set-StrictMode -Off +$ErrorActionPreference = 'Stop' + +function Ensure-Pester { + [CmdletBinding()] + param( + [Parameter()] + [version] $MinimumVersion = '5.0.0' + ) + + $pester = Get-Module -ListAvailable -Name Pester | + Sort-Object Version -Descending | + Select-Object -First 1 + + if (-not $pester -or $pester.Version -lt $MinimumVersion) { + Write-Host "Installing Pester >= $MinimumVersion (CurrentUser scope)..." + Install-Module -Name Pester -Scope CurrentUser -Force -MinimumVersion $MinimumVersion + } + + Import-Module -Name Pester -MinimumVersion $MinimumVersion -Force +} + +# Ensure output folder exists (for CI artifacts) +$resultsDir = Split-Path -Path $TestResultsPath -Parent +if ($resultsDir -and -not (Test-Path -Path $resultsDir)) { + New-Item -Path $resultsDir -ItemType Directory -Force | Out-Null +} + +Ensure-Pester -MinimumVersion '5.0.0' + +$config = New-PesterConfiguration +$config.Run.Path = $TestPath +$config.Run.Exit = $true +$config.Output.Verbosity = 'Detailed' + +if ($CI) { + $config.TestResult.Enabled = $true + $config.TestResult.OutputFormat = 'NUnitXml' + $config.TestResult.OutputPath = $TestResultsPath +} + +Invoke-Pester -Configuration $config