From 469059bb8bc50771ca3da3e526181c55c5b95a6c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Siemer?= Date: Wed, 5 Nov 2025 16:33:36 +0100 Subject: [PATCH 1/5] Transform PowerShell script to a module --- CheckMate.ps1 | 76 ---------------------------------------------- CheckMate.psd1 | 8 +++++ CheckMate.psm1 | 81 ++++++++++++++++++++++++++++++++++++++++++++++++++ README.md | 16 ++++++++-- 4 files changed, 103 insertions(+), 78 deletions(-) delete mode 100644 CheckMate.ps1 create mode 100644 CheckMate.psd1 create mode 100644 CheckMate.psm1 diff --git a/CheckMate.ps1 b/CheckMate.ps1 deleted file mode 100644 index 5384e54..0000000 --- a/CheckMate.ps1 +++ /dev/null @@ -1,76 +0,0 @@ -<# - .SYNOPSIS - This is CheckMate. He will run everything you give him inside a "checks/" folder. - - .DESCRIPTION - CheckMate is intended to run automated checks for a software projects repository. Its also meant to be easily extended by just adding PowerShell scripts to its checks/-folder. - - .PARAMETER RepoRoot - The root folder to run the checks from. - - .PARAMETER ReportPath - (optional) Specifies the output path for the report - will be generated inside the repoPath otherwise. - - .EXAMPLE - Run only the checks from the `checks/Sanity` directory on the `./MySolution/MyProject` path and generate a `ChecksResult.md` file with the results: - - ./CheckMate.ps1 -RepoRoot "./MySolution/ProjectDirectory" -ReportPath "CheckResults.md" -ChecksBasePath "checks/Sanity" - - #> - -param( - # Root directory to run the checks for - [string]$RepoRoot = ".", - - # Base directory for the checks to run (relative to this script) - [string]$ChecksBasePath = "checks", - - # name of the report file to be created - [string]$ReportPath = "$(get-date -f yyyy-MM-dd-HH-mm-ss)_autoreview-report.md" - - # -) - -Import-Module "$PSScriptRoot/common/MarkdownReport.psd1" - -# Absolute Pfade berechnen -$RepoRoot = (Resolve-Path $RepoRoot).Path -$checkFolder = Join-Path $PSScriptRoot $ChecksBasePath -$reportFile = if ([System.IO.Path]::IsPathRooted($ReportPath)) { - $ReportPath -} else { - Join-Path $RepoRoot $ReportPath -} - -$results = @{} - -Write-Host ">>> Repository Root: $RepoRoot" -Write-Host ">>> Report file being generated: $reportFile" - -# Alle Checks rekursiv einsammeln -Get-ChildItem -Path $checkFolder -Filter *.ps1 -Recurse | ForEach-Object { - $scriptPath = $_.FullName - - try - { - $simplifiedCheckPath = [System.IO.Path]::GetRelativePath($checkFolder, $scriptPath) - Write-Host "Executing => " $simplifiedCheckPath - $result = & $scriptPath -RepoRoot $RepoRoot - $checkSuccess = $LASTEXITCODE - $results[$simplifiedCheckPath] = @($checkSuccess, $result) - } - catch - { - Write-Error "Exception while running `n$_" - $results[$scriptPath] = @(1, "Threw Exception: $_") - } -} - -$markdownReport = New-MarkdownReport -results $results - -Write-Host "`n$markdownReport" - -Set-Content -Value $markdownReport -Encoding UTF8 $reportFile -Write-Host "`n See report file: $reportFile" - -exit 0 \ No newline at end of file diff --git a/CheckMate.psd1 b/CheckMate.psd1 new file mode 100644 index 0000000..c5d0007 --- /dev/null +++ b/CheckMate.psd1 @@ -0,0 +1,8 @@ +@{ + RootModule = 'CheckMate.psm1' + ModuleVersion = '0.2' + GUID = '014c80b0-082f-4b4c-833a-55852f1a2303' + Author = 'renao' + Description = 'CheckMate - Runs checks, mate.' + FunctionsToExport = @('Invoke-CheckMate') +} \ No newline at end of file diff --git a/CheckMate.psm1 b/CheckMate.psm1 new file mode 100644 index 0000000..6693457 --- /dev/null +++ b/CheckMate.psm1 @@ -0,0 +1,81 @@ +function Invoke-CheckMate { + <# + .SYNOPSIS + This is CheckMate. He will run everything inside a checks folder. + + .DESCRIPTION + CheckMate is intended to run automated checks for a software projects repository. Its also meant to be easily extended by just adding PowerShell scripts to its checks/-folder. + + .PARAMETER RepoRoot + The root folder to run the checks from. + + .PARAMETER ReportPath + (optional) Specifies the output path for the report - will be generated inside the repoPath otherwise. + + .PARAMETER ChecksBasePath + (optional) Specifies the output path for the report - will be generated inside the repoPath otherwise. + + .EXAMPLE + Run only the checks from the `checks/Sanity` directory on the `./MySolution/MyProject` path and generate a `ChecksResult.md` file with the results: + + ./CheckMate.ps1 -RepoRoot "./MySolution/ProjectDirectory" -ReportPath "CheckResults.md" -ChecksBasePath "checks/Sanity" + + #> + + param( + # Root directory to run the checks for + [string]$RepoRoot = ".", + + # Base directory for the checks to run (relative to this script) + [string]$ChecksBasePath = "checks", + + # name of the report file to be created + [string]$ReportPath = "$(get-date -f yyyy-MM-dd-HH-mm-ss)_autoreview-report.md" + + # + ) + + Import-Module "$PSScriptRoot/common/MarkdownReport.psd1" + + # Absolute Pfade berechnen + $RepoRoot = (Resolve-Path $RepoRoot).Path + $checkFolder = Join-Path $PSScriptRoot $ChecksBasePath + $reportFile = if ([System.IO.Path]::IsPathRooted($ReportPath)) { + $ReportPath + } else { + Join-Path $RepoRoot $ReportPath + } + + $results = @{} + + Write-Host ">>> Repository Root: $RepoRoot" + Write-Host ">>> Report file being generated: $reportFile" + + # Alle Checks rekursiv einsammeln + Get-ChildItem -Path $checkFolder -Filter *.ps1 -Recurse | ForEach-Object { + $scriptPath = $_.FullName + + try + { + $simplifiedCheckPath = [System.IO.Path]::GetRelativePath($checkFolder, $scriptPath) + Write-Host "Executing => " $simplifiedCheckPath + $result = & $scriptPath -RepoRoot $RepoRoot + $checkSuccess = $LASTEXITCODE + $results[$simplifiedCheckPath] = @($checkSuccess, $result) + } + catch + { + Write-Error "Exception while running `n$_" + $results[$scriptPath] = @(1, "Threw Exception: $_") + + return 1 + } + } + + $markdownReport = New-MarkdownReport -results $results + + Write-Host "`n$markdownReport" + + Set-Content -Value $markdownReport -Encoding UTF8 $reportFile + Write-Host "`n See report file: $reportFile" +} \ No newline at end of file diff --git a/README.md b/README.md index 4d0a2f0..b7ed04e 100644 --- a/README.md +++ b/README.md @@ -30,7 +30,19 @@ So CheckMate only needs to be run in a **PowerShell Core 7+**. ## Usage -You can run `CheckMate.ps1` without adding any additional parameter: +1. Import CheckMate + +Go and import the CheckMade Module in your current PowerShell session, e.g.: + +```powershell +Import-Module CheckMate.psd1 +``` + +2. Invoke CheckMate to run its tests + +```powershell +Invoke-CheckMate +``` ```powershell ./CheckMate.ps1 @@ -41,7 +53,7 @@ CheckMate will fall back to its current directory a test object, use the `checks Anyhow, you can alter these default configuration by using the corresponding parameters: ```powershell -./CheckMate.ps1 -repoPath "." -ChecksBasePath "./checks/Sanity" -ReportPath "CheckResults.md" +./Invoke-CheckMate -repoPath "." -ChecksBasePath "./checks/Sanity" -ReportPath "CheckResults.md" ``` ## License From 4bce2a1acd77815d9f450b10c7040443e7e70713 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Siemer?= Date: Wed, 5 Nov 2025 16:34:41 +0100 Subject: [PATCH 2/5] Remove double entry in documentation --- README.md | 4 ---- 1 file changed, 4 deletions(-) diff --git a/README.md b/README.md index b7ed04e..4b75caa 100644 --- a/README.md +++ b/README.md @@ -44,10 +44,6 @@ Import-Module CheckMate.psd1 Invoke-CheckMate ``` -```powershell -./CheckMate.ps1 -``` - CheckMate will fall back to its current directory a test object, use the `checks` directory for the tests to run and generate a report file by itself. Anyhow, you can alter these default configuration by using the corresponding parameters: From 474a5aaba3e993d6948cc684dbeb8d6ad5357220 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Siemer?= Date: Wed, 5 Nov 2025 18:13:04 +0100 Subject: [PATCH 3/5] Handle RepoRoot --- CheckMate.psm1 | 58 +++++++++++++++++++++++++-------------- tests/CheckMate.Tests.ps1 | 25 ++++++++--------- 2 files changed, 49 insertions(+), 34 deletions(-) diff --git a/CheckMate.psm1 b/CheckMate.psm1 index 6693457..2447da7 100644 --- a/CheckMate.psm1 +++ b/CheckMate.psm1 @@ -18,7 +18,7 @@ function Invoke-CheckMate { .EXAMPLE Run only the checks from the `checks/Sanity` directory on the `./MySolution/MyProject` path and generate a `ChecksResult.md` file with the results: - ./CheckMate.ps1 -RepoRoot "./MySolution/ProjectDirectory" -ReportPath "CheckResults.md" -ChecksBasePath "checks/Sanity" + Invoke-CheckMate -RepoRoot "./MySolution/ProjectDirectory" -ReportPath "CheckResults.md" -ChecksBasePath "checks/Sanity" #> @@ -31,26 +31,18 @@ function Invoke-CheckMate { # name of the report file to be created [string]$ReportPath = "$(get-date -f yyyy-MM-dd-HH-mm-ss)_autoreview-report.md" - - # ) + + $workingDirectory = Resolve-RepoRoot -RepoRoot $RepoRoot - Import-Module "$PSScriptRoot/common/MarkdownReport.psd1" - - # Absolute Pfade berechnen - $RepoRoot = (Resolve-Path $RepoRoot).Path - $checkFolder = Join-Path $PSScriptRoot $ChecksBasePath - $reportFile = if ([System.IO.Path]::IsPathRooted($ReportPath)) { - $ReportPath - } else { - Join-Path $RepoRoot $ReportPath + if ($null -eq $workingDirectory) { + Write-Error "RepoRoot is not valid or does not exist: $RepoRoot" + return 1 } - + + $checkFolder = Join-Path $PSScriptRoot $ChecksBasePath $results = @{} - Write-Host ">>> Repository Root: $RepoRoot" - Write-Host ">>> Report file being generated: $reportFile" - # Alle Checks rekursiv einsammeln Get-ChildItem -Path $checkFolder -Filter *.ps1 -Recurse | ForEach-Object { $scriptPath = $_.FullName @@ -58,8 +50,7 @@ function Invoke-CheckMate { try { $simplifiedCheckPath = [System.IO.Path]::GetRelativePath($checkFolder, $scriptPath) - Write-Host "Executing => " $simplifiedCheckPath - $result = & $scriptPath -RepoRoot $RepoRoot + $result = & $scriptPath -RepoRoot $workingDirectory $checkSuccess = $LASTEXITCODE $results[$simplifiedCheckPath] = @($checkSuccess, $result) } @@ -72,10 +63,37 @@ function Invoke-CheckMate { } } + Import-Module "$PSScriptRoot/common/MarkdownReport.psd1" $markdownReport = New-MarkdownReport -results $results - Write-Host "`n$markdownReport" + Write-Output "`n$markdownReport" + + + $reportFile = if ([System.IO.Path]::IsPathRooted($ReportPath)) { + $ReportPath + } else { + Join-Path $workingDirectory $ReportPath + } Set-Content -Value $markdownReport -Encoding UTF8 $reportFile - Write-Host "`n See report file: $reportFile" + Write-Output "`n See report file: $reportFile" + + return 0 +} + +function Resolve-RepoRoot { + param( + [string] $repoRoot + ) + + $resolvedPath = Resolve-Path $repoRoot -ErrorAction SilentlyContinue + + if ( + (-not $resolvedPath) -or + (-not $(Test-Path -Path $resolvedPath -PathType Container))) + { + return $null + } + + return $resolvedPath.Path } \ No newline at end of file diff --git a/tests/CheckMate.Tests.ps1 b/tests/CheckMate.Tests.ps1 index 003e480..8d8b93d 100644 --- a/tests/CheckMate.Tests.ps1 +++ b/tests/CheckMate.Tests.ps1 @@ -1,16 +1,13 @@ -Describe "CheckMate.ps1 - Pfadauflösung" { - It "RepoRoot sollte als absoluter Pfad aufgelöst werden" { - $testRepoRoot = "." - $resolvedPath = (Resolve-Path $testRepoRoot).Path - $resolvedPath | Should -Not -BeNullOrEmpty - $resolvedPath | Should -Match '^([A-Za-z]:\\|\\\\\\\\|/)' # Windows/Unix-Pfad - } +BeforeAll { + $modulePath = Join-Path $PSScriptRoot '..\CheckMate.psd1' + Import-Module $modulePath -Force +} - It "ReportPath sollte relativ zu RepoRoot aufgelöst werden, falls nicht absolut" { - $testRepoRoot = (Get-Location).Path - $testReportPath = "report.md" - $expectedReportPath = Join-Path $testRepoRoot $testReportPath - $actualReportPath = if ([System.IO.Path]::IsPathRooted($testReportPath)) { $testReportPath } else { Join-Path $testRepoRoot $testReportPath } - $actualReportPath | Should -Be $expectedReportPath +Describe "Invoke-CheckMate" { + Context "Validating parameters" { + It "Exits FAILED when repository path does not exist" { + $result = Invoke-CheckMate -RepoRoot "C:\nonexistant" + $result | Should -Be 1 + } } -} \ No newline at end of file +} From a1d94404063efddc297625797ace52a542666fbd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Siemer?= Date: Wed, 5 Nov 2025 18:15:38 +0100 Subject: [PATCH 4/5] Use Write-Output for handled RepoRoot error --- CheckMate.psm1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CheckMate.psm1 b/CheckMate.psm1 index 2447da7..8704917 100644 --- a/CheckMate.psm1 +++ b/CheckMate.psm1 @@ -36,7 +36,7 @@ function Invoke-CheckMate { $workingDirectory = Resolve-RepoRoot -RepoRoot $RepoRoot if ($null -eq $workingDirectory) { - Write-Error "RepoRoot is not valid or does not exist: $RepoRoot" + Write-Output "RepoRoot is not valid or does not exist: $RepoRoot" return 1 } From 7c796ff6634f4113366922eeba2ac3631581fb30 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Siemer?= Date: Wed, 5 Nov 2025 18:24:53 +0100 Subject: [PATCH 5/5] Throw exception instead of writing error --- CheckMate.psm1 | 3 +-- tests/CheckMate.Tests.ps1 | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/CheckMate.psm1 b/CheckMate.psm1 index 8704917..de11dfc 100644 --- a/CheckMate.psm1 +++ b/CheckMate.psm1 @@ -36,8 +36,7 @@ function Invoke-CheckMate { $workingDirectory = Resolve-RepoRoot -RepoRoot $RepoRoot if ($null -eq $workingDirectory) { - Write-Output "RepoRoot is not valid or does not exist: $RepoRoot" - return 1 + throw "RepoRoot is not valid or does not exist: $RepoRoot" } $checkFolder = Join-Path $PSScriptRoot $ChecksBasePath diff --git a/tests/CheckMate.Tests.ps1 b/tests/CheckMate.Tests.ps1 index 8d8b93d..d831086 100644 --- a/tests/CheckMate.Tests.ps1 +++ b/tests/CheckMate.Tests.ps1 @@ -6,8 +6,7 @@ BeforeAll { Describe "Invoke-CheckMate" { Context "Validating parameters" { It "Exits FAILED when repository path does not exist" { - $result = Invoke-CheckMate -RepoRoot "C:\nonexistant" - $result | Should -Be 1 + { Invoke-CheckMate -RepoRoot "C:\nonexistant" } | Should -Throw } } }