Home > other >  `mypy` returning with exit status of 0 even though code is not properly type hinted in gitlab CI/CD
`mypy` returning with exit status of 0 even though code is not properly type hinted in gitlab CI/CD

Time:01-01

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 and ForEach-Object (%): Only if one or both calls as a whole are considered to have encountered errors - as reflected in the automatic $? variable containing $false - is 1 reported as the exit code; otherwise, it is 0.

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.

  • Related