I'm working on a dev tool based on PowerShell. But it always failed in Ubuntu-Latest CI/CD tests. If interested, please check the GitHub Link of Actions
After a day of trying, I found and minimized the process of reproducing the problem.
- Platform: Both Windows and WSL2 show the same problem
- PSVersion: 7.3.6
Consider a directory ${Home}/test/ with a file test_in_method.ps1 and a file test_out_of_method.ps1 as:
${Home}/test/
|----test_in_method.ps1
|----test_out_of_method.ps1
|----(no other items, i.e., no other dirs or files)
The test_in_method.ps1 is as:
# PowerShell 7.3.6 on Windows Or Linux
# test_in_method.ps1
class FormattedFileSystemPath {
FormattedFileSystemPath([string] $Path) {
$link_target = $this.PreProcess()
}
[string] PreProcess(){
Write-Verbose "PWD is:$PWD" -Verbose
return (Get-ChildItem 'usr'| Where-Object Name -eq 'sbin')
}
}
Write-Verbose ([FormattedFileSystemPath]::new('???')) -Verbose
, and the test_out_of_method.ps1 is as:
# PowerShell 7.3.6 on Windows Or Linux
# test_out_of_method.ps1
class FormattedFileSystemPath {
FormattedFileSystemPath([string] $Path) {
Write-Verbose "PWD is:$PWD" -Verbose
$link_target = (Get-ChildItem 'usr'| Where-Object Name -eq 'sbin')
}
}
Write-Verbose ([FormattedFileSystemPath]::new('???')) -Verbose
First, test test_in_method.ps1 as:
pwsh
cd "${Home}/test/"
./ test_in_method.ps1
The output is:
VERBOSE: PWD is:C:\Users\User\test
VERBOSE: FormattedFileSystemPath
Second, test test_out_of_method.ps1 as:
pwsh
cd "${Home}/test/"
./ test_out_of_method.ps1
The out put is:
VERBOSE: PWD is:C:\Users\User\test
Get-ChildItem: C:\Users\User\test\test_out_of_method.ps1:7
Line |
7 | $link_target = (Get-ChildItem 'usr'| Where-Object Name -eq 's …
| ~~~~~~~~~~~~~~~~~~~
| Cannot find path 'C:\Users\User\test\usr' because it does not exist.
VERBOSE: FormattedFileSystemPath
Expected behavior: both test_in_method.ps1 and test_out_of_method.ps1 throw cannot find path errors
Actual behavior: only test_out_of_method.ps1 throws cannot find path errors but test_in_method.ps1 does not.
I have tested on my local machines, and both Windows 11 (PowerShellv7.3.6) and WSL2(PowerShellv7.3.5) show the above phenomenon.
Even more strangely, when put into a CI/CD environment, see here, either of the above writes (whether put Get-ChildItem into a class function or a constructor function) can both throw errors as expected.
What's the problem? Why? And how can I deal with it? Why Get-ChildItem does not throw a cannot find path error in the class method as expected?
Thanks in advance.
The problem has 2 aspects and can be answered respectively:
Why
Get-ChildItemdoes not throw acannot find patherror in a class method as expected? Because:terminating errorsandnon-terminating errors, see here.cannot find pathis anon-terminating errorbutnon-terminating errorsare not surfaced by class methods, see here and here.Why the phenomenon is different the local machines and CI/CD environments?
$ErrorActionPreferencecan determine how PowerShell responds to a non-terminating error, an error that doesn't stop the cmdlet processing.$ErrorActionPreference= 'stop'that is set by many configuration scripts, see an action example, while local machines usually have$ErrorActionPreference = 'Continue', which is the default state that displays the error message and continues executing.And how to do it?
I think the best way is as @Santiago Squarzon's comments, adding
-ErrorAction StoptoGet-ChildItemin class methods. Because it follows the principle of Occam's Razor, with the minimized scope of changes.Thanks for every above comments and advice.