`mypy` 以退出状态 0 返回,即使代码在 gitlab CI/CD 管道中没有正确类型提示

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

我有以下 .gitlab-ci.yml 文件:

stages:
  - check-code

before_script:
  - C:\Users79\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 $_}

check-code 阶段按预期运行。然而 type_checker 阶段在 GitLab 管道中通过,即使我当前目录中的许多 python 脚本实际上没有通过类型检查。

我怀疑这可能是因为 (ls -recurse *.py).fullname | foreach-object {echo "n$_n";mypy --strict $_} 以某种方式 returns 为零退出代码。这个对吗?当代码输入不正确时,如何确保我的管道失败?

编辑

我认为退出代码可能终究不是零。我用以下内容创建了一个临时脚本,运行 它在相同条件下:

(ls -recurse *.py).fullname | foreach-object {echo "`n$_`n";mypy --strict $_}

exit $LASTEXITCODE

当我回显 $LASTEXITCODE 时,它包含一个值 1。所以现在我很困惑....

默认情况下,Powershell 脚本不会因错误而停止。要更改此行为,请设置 CI/CD 变量 ErrorActionPreference: STOP(对于 commandlet 失败)and/or 检查 $LASTEXITCODE 然后 throw 如果它非零。

如果您的脚本是一个简单的单一命令,则没有必要:

script: # will succeed/fail depending on exit code of the command
  - some-command-or-executable  

但是,如果您在 powershell 脚本中调用多个 commands/executables 并且您需要脚本在任何失败时立即 退出,您必须检查 $LastExitCode每次并手动终止脚本(使用 throwexit$host.SetShouldExit 等)

some-command
if ($LastExitCode -ne 0) { $host.SetShouldExit($LastExitCode)  }
another-command
if ($LastExitCode -ne 0) { $host.SetShouldExit($LastExitCode)  }
# ...

如果没有 if 条件,两个 命令都将是 运行,无论退出代码如何第一个命令(some-command)。作业的总体成功将取决于最后一个命令的退出代码 运行.

据推测,问题的出现是因为 GitLab CI/CD 管道通过 PowerShell CLI (powershell.exe 对于 Windows PowerShell,pwsh 对于 PowerShell(核心)7+:

  • 决定 CLI 调用退出代码的是最后执行的语句

  • 在您的情况下,这转换为对包含 $falseGet-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 的调用 - 报告为 1 退出代码;否则,它是 0.

换句话说:在传递给ForEach-Object的脚本块中对mypy等外部程序的调用没有 对整体退出代码的影响。

要改变这一点,请跟踪失败的外部程序调用并使用明确的 exit 语句作为最后一条语句(代码分布在多行中以提高可读性 - 只有在以下情况下才需要 ;你重新格式化为一行):

$overallExitCode = 0;
(ls -recurse *.py).fullname | foreach-object { 
  echo "`n$_`n"; mypy --strict $_;
  if ($LASTEXITCODE -ne 0) { $overallExitCode = $LASTEXITCODE }
};
exit $overallExitCode

如果您只关心 第一个 失败:

(ls -recurse *.py).fullname | foreach-object { 
  echo "`n$_`n"; mypy --strict $_;
  if ($LASTEXITCODE -ne 0) { break }
};
exit $LASTEXITCODE

如果您不关心转发 mypy 报告的 特定 非零退出代码,并且想要发出信号 any 整体退出代码失败 1,您可以使用以下简化的公式(您自己想出的),它依赖于调用外部程序也报告非零退出代码这一事实结果 $? 反映了 $false:

(ls -recurse *.py).fullname | foreach-object {mypy --strict $_; if (-not $?) {exit 1}}

有关 PowerShell 中退出代码的详细信息,请参阅