Skip to content

Commit 5dfa6c6

Browse files
🪲 [Fix]: Fix test and container loading function to also process tests root folder (#35)
## Description This pull request includes several improvements and new features to enhance the robustness and functionality of the PowerShell scripts. The key changes involve adding retry mechanisms for module installations, introducing a new function to process test directories, and updating existing scripts to use these new functionalities. ### Enhancements to module installation: * [`.github/workflows/Action-Test.yml`](diffhunk://#diff-a12ae5c885b0673c0ff6f70c2670886907590d624626e07da4c52e01aeaf56a4L232-R251): Added a retry mechanism for installing the `Markdown` module to handle potential installation failures more gracefully. * [`scripts/exec.ps1`](diffhunk://#diff-9565c9ed6189efecf687222ac63d0ec9702c9708f75a02f7d9d9de9f86ae37a0L7-R8): Replaced direct module installations with the new `Install-PSResourceWithRetry` function to ensure reliable installations. [[1]](diffhunk://#diff-9565c9ed6189efecf687222ac63d0ec9702c9708f75a02f7d9d9de9f86ae37a0L7-R8) [[2]](diffhunk://#diff-9565c9ed6189efecf687222ac63d0ec9702c9708f75a02f7d9d9de9f86ae37a0L61-R58) * [`scripts/init.ps1`](diffhunk://#diff-f47ceebe9ade2bb55cede031de8267e9c87b09336a93fcd557c02c1f488554b6L5-R6): Updated to use `Install-PSResourceWithRetry` for installing required modules, ensuring retries on failure. ### New function for processing test directories: * [`scripts/Helpers.psm1`](diffhunk://#diff-acb1351e3ba396afa6a397b0bd44b5d8ed3ffeb97a3f3ef3633e9cfd6cacf11aR1113-R1318): Introduced `Invoke-ProcessTestDirectory` to scan directories for container and test files, process them accordingly, and support recursive processing. ### Directory and path handling improvements: * [`scripts/exec.ps1`](diffhunk://#diff-9565c9ed6189efecf687222ac63d0ec9702c9708f75a02f7d9d9de9f86ae37a0L24-R21): Changed the temporary directory name from 'temp' to '.temp' for better organization. * [`scripts/init.ps1`](diffhunk://#diff-f47ceebe9ade2bb55cede031de8267e9c87b09336a93fcd557c02c1f488554b6L184-R198): Updated the script to create a '.temp' directory for container output and utilize `Invoke-ProcessTestDirectory` for processing test directories. ### Additional changes: * [`tests/1-Simple-Failure/data/Test.Data.ps1`](diffhunk://#diff-170528ba3d6e6898a263b83dd935f3bc4954ed8f98435b8e66f23df7772fd20fR1): Added a mock test data file. ## Type of change <!-- Use the check-boxes [x] on the options that are relevant. --> - [ ] 📖 [Docs] - [x] 🪲 [Fix] - [ ] 🩹 [Patch] - [ ] ⚠️ [Security fix] - [ ] 🚀 [Feature] - [ ] 🌟 [Breaking change] ## Checklist <!-- Use the check-boxes [x] on the options that are relevant. --> - [x] I have performed a self-review of my own code - [x] I have commented my code, particularly in hard-to-understand areas
1 parent 993d539 commit 5dfa6c6

5 files changed

Lines changed: 243 additions & 64 deletions

File tree

.github/workflows/Action-Test.yml

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -229,7 +229,26 @@ jobs:
229229
uses: PSModule/Github-Script@v1
230230
with:
231231
Script: |
232-
Install-PSResource -Name Markdown -Repository PSGallery -TrustRepository
232+
'Markdown' | ForEach-Object {
233+
$name = $_
234+
Write-Output "Installing module: $name"
235+
$retryCount = 5
236+
$retryDelay = 10
237+
for ($i = 0; $i -lt $retryCount; $i++) {
238+
try {
239+
Install-PSResource -Name $name -WarningAction SilentlyContinue -TrustRepository -Repository PSGallery
240+
break
241+
} catch {
242+
Write-Warning "Installation of $name failed with error: $_"
243+
if ($i -eq $retryCount - 1) {
244+
throw
245+
}
246+
Write-Warning "Retrying in $retryDelay seconds..."
247+
Start-Sleep -Seconds $retryDelay
248+
}
249+
}
250+
Import-Module -Name $name
251+
}
233252
234253
# Build an array of objects for each job
235254
$ActionTest1SimpleOutcome = '${{ needs.ActionTest1Simple.outputs.outcome }}'

scripts/Helpers.psm1

Lines changed: 206 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1110,3 +1110,209 @@ filter Show-Input {
11101110
}
11111111
[pscustomobject]$new | Format-List | Out-String
11121112
}
1113+
1114+
function Invoke-ProcessTestDirectory {
1115+
<#
1116+
.SYNOPSIS
1117+
Processes a directory to find and handle test and container files.
1118+
1119+
.DESCRIPTION
1120+
This function scans a given directory for container and test files, processing them accordingly.
1121+
If container files are found, they are imported and exported to the specified output path.
1122+
If no container files exist, test files are used to generate new container files.
1123+
The function supports recursive processing of subdirectories.
1124+
1125+
.EXAMPLE
1126+
Invoke-ProcessTestDirectory -Directory 'C:\Tests' -OutputPath 'C:\Output'
1127+
1128+
Output:
1129+
```powershell
1130+
=== Examining directory: [C:\Tests] (Level: 0) ===
1131+
Looking for container files in current directory (non-recursive)...
1132+
Container files found in [C:\Tests]: [2]
1133+
Processing container file: [Test1.Container.ps1]
1134+
Processing container file: [Test2.Container.ps1]
1135+
Exporting container [C:\Output\Test1.Container.ps1]
1136+
Exporting container [C:\Output\Test2.Container.ps1]
1137+
=== Completed processing directory: [C:\Tests] ===
1138+
```
1139+
1140+
Processes test container files in 'C:\Tests' and exports them to 'C:\Output'.
1141+
1142+
.EXAMPLE
1143+
Invoke-ProcessTestDirectory -Directory 'C:\Tests' -OutputPath 'C:\Output' -RecursionLevel 1
1144+
1145+
Output:
1146+
```powershell
1147+
=== Examining directory: [C:\Tests] (Level: 1) ===
1148+
Looking for container files in current directory (non-recursive)...
1149+
No container files found - looking for test files...
1150+
Test files found in [C:\Tests]: [3]
1151+
Creating container for test file: [TestA.Tests.ps1]
1152+
Creating container for test file: [TestB.Tests.ps1]
1153+
Exporting container [C:\Output\TestA.Container.ps1]
1154+
Exporting container [C:\Output\TestB.Container.ps1]
1155+
=== Completed processing directory: [C:\Tests] ===
1156+
```
1157+
1158+
Generates and exports container files for test scripts found in 'C:\Tests' at recursion level 1.
1159+
1160+
.OUTPUTS
1161+
array
1162+
1163+
.NOTES
1164+
A list of processed container hashtables.
1165+
Each container represents a test file or an imported container configuration.
1166+
#>
1167+
[Diagnostics.CodeAnalysis.SuppressMessageAttribute(
1168+
'PSAvoidUsingWriteHost', '',
1169+
Justification = 'Log to the GitHub Action runner'
1170+
)]
1171+
[CmdletBinding()]
1172+
param(
1173+
# The directory to process for container and test files.
1174+
[Parameter(Mandatory)]
1175+
[string]$Directory,
1176+
1177+
# The path where container files should be exported.
1178+
[Parameter(Mandatory)]
1179+
[string]$OutputPath,
1180+
1181+
# A collection of processed containers, used for recursive directory processing.
1182+
[Parameter()]
1183+
[array]$Containers = @(),
1184+
1185+
# The current recursion level, used for logging indentation.
1186+
[Parameter()]
1187+
[int]$RecursionLevel = 0
1188+
)
1189+
1190+
# Create indent for better log readability based on recursion level
1191+
$indent = ' ' * $RecursionLevel
1192+
Write-Host "${indent}=== Examining directory: [$Directory] (Level: $RecursionLevel) ==="
1193+
1194+
# First check for container files in this directory (non-recursive)
1195+
Write-Host "${indent}Looking for container files in current directory (non-recursive)..."
1196+
$containerFiles = Get-ChildItem -Path $Directory -Filter *.Container.* -File
1197+
$containerFilesFound = $containerFiles.Count -gt 0
1198+
1199+
Write-Host "${indent}Container files found in [$Directory]: [$($containerFiles.Count)]"
1200+
if ($containerFilesFound) {
1201+
Write-Host "${indent}Container files detected - will process them directly"
1202+
}
1203+
1204+
if ($containerFilesFound) {
1205+
# If container files exist, use those for this directory
1206+
foreach ($containerFile in $containerFiles) {
1207+
Write-Host "${indent}Processing container file: [$($containerFile.Name)]"
1208+
$container = Import-Hashtable $containerFile
1209+
$containerFileName = $containerFile | Split-Path -Leaf
1210+
Write-Host "${indent}Init - Export containers - $containerFileName"
1211+
Write-Host "${indent}Container configuration:"
1212+
Write-Host (Format-Hashtable -Hashtable $container)
1213+
Write-Host "${indent}Exporting container [$OutputPath/$containerFileName]"
1214+
Export-Hashtable -Hashtable $container -Path "$OutputPath/$containerFileName"
1215+
Write-Host "${indent}Added container from $containerFileName to collection"
1216+
$Containers += $container
1217+
}
1218+
} else {
1219+
# If no container files, look for test files in this directory only (non-recursive)
1220+
Write-Host "${indent}No container files found - looking for test files..."
1221+
$testFiles = Get-ChildItem -Path $Directory -Filter *.Tests.ps1 -File
1222+
Write-Host "${indent}Test files found in [$Directory]: [$($testFiles.Count)]"
1223+
1224+
if ($testFiles.Count -gt 0) {
1225+
Write-Host "${indent}Will generate containers for each test file"
1226+
} else {
1227+
Write-Host "${indent}No test files found in this directory"
1228+
}
1229+
1230+
# Create containers for test files in this directory
1231+
foreach ($testFile in $testFiles) {
1232+
Write-Host "${indent}Creating container for test file: [$($testFile.Name)]"
1233+
$container = @{
1234+
Path = $testFile.FullName
1235+
}
1236+
$containerFileName = ($testFile | Split-Path -Leaf).Replace('.Tests.ps1', '.Container.ps1')
1237+
Write-Host "${indent}Init - Export containers - Generated - $containerFileName"
1238+
Write-Host "${indent}Container configuration:"
1239+
Write-Host (Format-Hashtable -Hashtable $container)
1240+
Write-Host "${indent}Exporting container [$OutputPath/$containerFileName]"
1241+
Export-Hashtable -Hashtable $container -Path "$OutputPath/$containerFileName"
1242+
Write-Host "${indent}Added generated container for $($testFile.Name) to collection"
1243+
$Containers += $container
1244+
}
1245+
}
1246+
1247+
# Now process subdirectories recursively
1248+
Write-Host "${indent}Checking for subdirectories in [$Directory]..."
1249+
$subdirectories = Get-ChildItem -Path $Directory -Directory
1250+
$subdirCount = $subdirectories.Count
1251+
Write-Host "${indent}Found $subdirCount subdirectories to process"
1252+
1253+
if ($subdirCount -gt 0) {
1254+
Write-Host "${indent}Beginning recursive processing of $subdirCount subdirectories..."
1255+
}
1256+
1257+
foreach ($subdir in $subdirectories) {
1258+
Write-Host "${indent}Processing subdirectory - [$($subdir.Name)]"
1259+
$params = @{
1260+
Directory = $subdir.FullName
1261+
OutputPath = $OutputPath
1262+
Containers = $Containers
1263+
RecursionLevel = ($RecursionLevel + 1)
1264+
}
1265+
$Containers = Invoke-ProcessTestDirectory @params
1266+
}
1267+
1268+
Write-Host "${indent}=== Completed processing directory: [$Directory] ==="
1269+
Write-Host "${indent}Total containers after processing [$Directory]: [$($Containers.Count)]"
1270+
1271+
$Containers
1272+
}
1273+
1274+
function Install-PSResourceWithRetry {
1275+
<#
1276+
.SYNOPSIS
1277+
Installs a PowerShell module with retry mechanism
1278+
1279+
.DESCRIPTION
1280+
Attempts to install a PowerShell module multiple times in case of failure
1281+
#>
1282+
[CmdletBinding()]
1283+
param (
1284+
# Name of the module to install
1285+
[Parameter(
1286+
Mandatory,
1287+
Position = 0,
1288+
ValueFromPipeline
1289+
)]
1290+
[string] $Name,
1291+
1292+
# Number of times to retry installation, default is 5
1293+
[Parameter()]
1294+
[int] $RetryCount = 5,
1295+
1296+
# Delay in seconds between retries, default is 10
1297+
[Parameter()]
1298+
[int] $RetryDelay = 10
1299+
)
1300+
1301+
process {
1302+
Write-Output "Installing module: $Name"
1303+
for ($i = 0; $i -lt $RetryCount; $i++) {
1304+
try {
1305+
Install-PSResource -Name $Name -WarningAction SilentlyContinue -TrustRepository -Repository PSGallery
1306+
break
1307+
} catch {
1308+
Write-Warning "Installation of $Name failed with error: $_"
1309+
if ($i -eq $RetryCount - 1) {
1310+
throw
1311+
}
1312+
Write-Warning "Retrying in $RetryDelay seconds..."
1313+
Start-Sleep -Seconds $RetryDelay
1314+
}
1315+
}
1316+
Import-Module -Name $Name
1317+
}
1318+
}

scripts/exec.ps1

Lines changed: 3 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,8 @@ param()
44
$PSStyle.OutputRendering = 'Ansi'
55

66
'::group::Exec - Setup prerequisites'
7-
'Pester' | ForEach-Object {
8-
Install-PSResource -Name $_ -WarningAction SilentlyContinue -TrustRepository -Repository PSGallery
9-
Import-Module -Name $_
10-
}
117
Import-Module "$PSScriptRoot/Helpers.psm1"
8+
'Pester' | Install-PSResourceWithRetry
129
'::endgroup::'
1310

1411
'::group::Exec - Get test kit versions'
@@ -21,7 +18,7 @@ $pesterModule = Get-PSResource -Name Pester -Verbose:$false | Sort-Object Versio
2118
'::endgroup::'
2219

2320
'::group::Exec - Info about environment'
24-
$path = Join-Path -Path $pwd.Path -ChildPath 'temp'
21+
$path = Join-Path -Path $pwd.Path -ChildPath '.temp'
2522
Test-Path -Path $path
2623
Get-ChildItem -Path $path -Recurse | Sort-Object FullName | Format-Table -AutoSize | Out-String
2724

@@ -58,11 +55,7 @@ $configuration = New-PesterConfiguration -Hashtable $configuration
5855
$testResults = Invoke-Pester -Configuration $configuration
5956

6057
LogGroup 'Eval - Setup prerequisites' {
61-
'Pester', 'Hashtable', 'TimeSpan', 'Markdown' | ForEach-Object {
62-
Install-PSResource -Name $_ -Verbose:$false -WarningAction SilentlyContinue -TrustRepository -Repository PSGallery
63-
Import-Module -Name $_ -Verbose:$false
64-
}
65-
Import-Module "$PSScriptRoot/Helpers.psm1"
58+
'Pester', 'Hashtable', 'TimeSpan', 'Markdown' | Install-PSResourceWithRetry
6659
}
6760

6861
LogGroup 'Eval - Get test kit versions' {

scripts/init.ps1

Lines changed: 13 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,8 @@
22
param()
33

44
LogGroup 'Init - Setup prerequisites' {
5-
'Pester', 'Hashtable', 'TimeSpan', 'Markdown' | ForEach-Object {
6-
Install-PSResource -Name $_ -WarningAction SilentlyContinue -TrustRepository -Repository PSGallery
7-
Import-Module -Name $_
8-
}
95
Import-Module "$PSScriptRoot/Helpers.psm1"
6+
'Pester', 'Hashtable', 'TimeSpan', 'Markdown' | Install-PSResourceWithRetry
107
}
118

129
LogGroup 'Init - Get test kit versions' {
@@ -181,61 +178,24 @@ LogGroup 'Init - Export containers' {
181178
}
182179
}
183180
Write-Output "Containers from configuration: [$($containers.Count)]"
184-
# Search for "*.Container.*" files in each Run.Path directory
185-
Write-Output 'Searching for containers in same location as config.'
186-
$path = New-Item -Path . -ItemType Directory -Name 'temp' -Force
181+
182+
# Create temp directory for container output
183+
$path = New-Item -Path . -ItemType Directory -Name '.temp' -Force
184+
185+
# Process each input path
187186
foreach ($testDir in $inputs.Path) {
188-
#If testDir is a file, get the directory
187+
# If testDir is a file, get the directory
189188
$testItem = Get-Item -Path $testDir
190189
if ($testItem.PSIsContainer -eq $false) {
191190
$testDir = $testItem.DirectoryName
192191
}
193192

194-
$containerFiles = Get-ChildItem -Path $testDir -Filter *.Container.* -Recurse
195-
Write-Output "Containers found in [$testDir]: [$($containerFiles.Count)]"
196-
if ($containerFiles.Count -eq 0) {
197-
# First, look for test files directly in the test directory (non-recursive)
198-
$rootTestFiles = Get-ChildItem -Path $testDir -Filter *.Tests.ps1 -File
199-
Write-Output "Root level test files found in [$testDir]: [$($rootTestFiles.Count)]"
200-
201-
# Then, look for test files in subdirectories
202-
$subfolderTestFiles = Get-ChildItem -Path $testDir -Filter *.Tests.ps1 -Recurse -File |
203-
Where-Object { $_.DirectoryName -ne $testDir }
204-
Write-Output "Subfolder test files found in [$testDir]: [$($subfolderTestFiles.Count)]"
205-
206-
# Combine all test files using a generic List
207-
$testFiles = [System.Collections.Generic.List[System.IO.FileInfo]]::new()
208-
if ($rootTestFiles) {
209-
$rootTestFiles | ForEach-Object { $testFiles.Add($_) }
210-
}
211-
if ($subfolderTestFiles) {
212-
$subfolderTestFiles | ForEach-Object { $testFiles.Add($_) }
213-
}
214-
Write-Output "Total test files found in [$testDir]: [$($testFiles.Count)]"
215-
216-
foreach ($testFile in $testFiles) {
217-
$container = @{
218-
Path = $testFile.FullName
219-
}
220-
$containerFileName = ($testFile | Split-Path -Leaf).Replace('.Tests.ps1', '.Container.ps1')
221-
LogGroup "Init - Export containers - Generated - $containerFileName" {
222-
Write-Output "Exporting container [$path/$containerFileName]"
223-
Export-Hashtable -Hashtable $container -Path "$path/$containerFileName"
224-
}
225-
$containers += $container
226-
}
227-
Write-Output "Containers created from test files: [$($containers.Count)]"
228-
}
229-
foreach ($containerFile in $containerFiles) {
230-
$container = Import-Hashtable $containerFile
231-
$containerFileName = $containerFile | Split-Path -Leaf
232-
LogGroup "Init - Export containers - $containerFileName" {
233-
Format-Hashtable -Hashtable $container
234-
Write-Output "Exporting container [$path/$containerFileName]"
235-
Export-Hashtable -Hashtable $container -Path "$path/$containerFileName"
236-
}
237-
$containers += $container
238-
}
193+
Write-Output "Processing test directory: [$testDir]"
194+
195+
# Process the root directory and all subdirectories recursively
196+
$containers += Invoke-ProcessTestDirectory -Directory $testDir -OutputPath $path
197+
198+
Write-Output "Total containers after processing [$testDir]: [$($containers.Count)]"
239199
}
240200
$configuration.Run.Container = @()
241201
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
"This is some mock test data"

0 commit comments

Comments
 (0)