`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
每次并手动终止脚本(使用 throw
、exit
或 $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 调用退出代码的是最后执行的语句。
在您的情况下,这转换为对包含 $false
的 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 的调用 - 报告为 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 中退出代码的详细信息,请参阅 。
我有以下 .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
每次并手动终止脚本(使用 throw
、exit
或 $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 调用退出代码的是最后执行的语句。
在您的情况下,这转换为对包含
$false
的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 的调用 - 报告为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 中退出代码的详细信息,请参阅