I have the following .gitlab-ci.yml
file":
stages:
- check-code
before_script:
- C:\Users\9279\Documents\WindowsPowerShell\profile.ps1
- conda activate temp
run_tests:
stage: check-code
script:
- pytest test.py
type_checker:
stage: check-code
script:
- (ls -recurse *.py).fullname | foreach-object {echo "`n$_`n";mypy --strict $_}
The check-code
stage runs as expected. However the type_checker
stage passes in GitLab pipelines even though many of the python scripts in my current directory actually fail the type check.
I suspect this might be because the (ls -recurse *.py).fullname | foreach-object {echo "
n$_n";mypy --strict $_}
somehow returns a zero exit code. Is this correct? How can I make sure my pipeline fails when the code is improperly typed?
Thanks
EDIT
I think the exit code might not be zero after all. I created a temporary script with the following and ran it under the same conditions:
(ls -recurse *.py).fullname | foreach-object {echo "`n$_`n";mypy --strict $_}
exit $LASTEXITCODE
When I echoed the $LASTEXITCODE
it contained a value of 1. So now I am quite confused....
CodePudding user response:
Presumably, the problem arises because the GitLab CI/CD pipeline executes your PowerShell code via the -Command
(-c
) parameter of the PowerShell CLI (powershell.exe
for Windows PowerShell, pwsh
for PowerShell (Core) 7 ):
It is the last statement executed that determines the CLI invocation's exit code.
In your case, that translates to the calls to
Get-ChildItem
andForEach-Object
(%
): Only if one or both calls as a whole are considered to have encountered errors - as reflected in the automatic$?
variable containing$false
- is1
reported as the exit code; otherwise, it is0
.
In other words: the calls to external programs such as mypy
inside the script block passed to ForEach-Object
have no impact on the overall exit code.
To change that, keep track of failing external-program calls and use an explicit exit
statement as the last statement (code spread across multiple lines for readability - the ;
are only needed if you reformat to a single line):
$overallExitCode = 0;
(ls -recurse *.py).fullname | foreach-object {
echo "`n$_`n"; mypy --strict $_;
if ($LASTEXITCODE -ne 0) { $overallExitCode = $LASTEXITCODE }
};
exit $overallExitCode
If you only care about the first failure:
(ls -recurse *.py).fullname | foreach-object {
echo "`n$_`n"; mypy --strict $_;
if ($LASTEXITCODE -ne 0) { break }
};
exit $LASTEXITCODE
For more information about exit codes in PowerShell, see this answer.
CodePudding user response:
By default Powershell scripts do not stop on errors. To change this behavior, set the CI/CD variable ErrorActionPreference: STOP
(for commandlet failures) and/or check $LASTEXITCODE
and then throw
if it is nonzero.