Jenkins结合pylint导致构建失败

12

我添加了一个构建步骤来执行一个Python脚本。
在这个脚本中,使用lint.Run(..args)调用pylint来检查代码。
脚本可以正常运行,但最终构建失败,并显示唯一的错误消息:

构建步骤“执行Python脚本”将构建标记为失败

有人知道为什么会出现这种情况吗?

9个回答

24
你也可以在shell命令行中输入以下代码,即可轻松实现:

pylint || exit 0

Pylint插件将通过检查pylint的结果,无论如何都会使构建失败。


3
问题在于,如果pylint无法运行,则由于其仍具有0退出代码,您将错过错误。 - Adam Parkin
使用管道是可行的,但以下是由sherylpinto和floern提供的更清晰的解决方案:https://dev59.com/kGs05IYBdhLWcg3wQvuq#54934402 - Dominik Sajovic

16

14

Pylint的不良行为是即使只发现一个小警告问题,也会返回非零退出代码。只有当一切正常时,才会返回0(请参阅man页面)。

通常情况下,非零代码表示错误,Jenkins构建失败。

我看到两种方法可以克服这个问题:

  • 在pylint周围使用一个小脚本,始终返回0。然后jenkins将不会因为pylint而失败。我使用一个小的Python脚本,在os.system()中调用pylint,然后在sys.exit(0)之后退出。您可以将其视为覆盖pylint的错误代码。
  • 修补pylint。例如,在我的Linux系统上,sys.exit()调用在文件/usr/lib/pymodules/python2.6/pylint/lint.py中。

我将输出通过管道传输给cat,现在似乎已经成功构建了。例如:pylint -f html code.py | cat > report.html - zyxue

3

看起来您的pylint执行以非零状态退出(缺少脚本,错误选项...),可能是因为您退出脚本时引发了异常或使用了sys.exit(something_else_than_zero)


1
确实如此。我调试了lint.py并发现一个sys.exit(self.linter.msgstatus)的调用,其中msgstatus在上下文中找不到。将其替换为0就可以了,现在构建成功了。 - Gobliins

2
最近的 rylint 已经有了不调用 sys exit 的选项。
lint.Run(args, exit=False, **kwargs)

1
Pylint希望分析的代码是百分之百完美的。 即使是代码警告也可能导致退出非零状态码。 尝试按照Pylint建议修复您的代码并获得10/10的评分。
希望这可以帮助您。

1
今天遇到了这个问题(虽然没有使用Jenkins)。
在我的情况下,是因为Pylint如何在其退出代码中编码致命错误、警告、重构、约定和用法信息:https://docs.pylint.org/en/1.6.0/run.html#exit-codes
我的解决方法:
#!/usr/bin/env sh

# Wraps Pylint invocation to produce shell-friendly exit codes
# Because Pylint exit codes are weird:
# https://docs.pylint.org/en/1.6.0/run.html#exit-codes

PYTHON_EXECUTABLE=python
if [ ! -z $PYTHON_ENV ]; then
    PYTHON_EXECUTABLE="$PYTHON_ENV/bin/python"
fi

${PYTHON_EXECUTABLE} -m pylint $@

PYLINT_EXIT_CODE=$?

exit $(($PYLINT_EXIT_CODE % 4))

(简述:https://gist.github.com/nkashy1/ae59d06d4bf81fb72047fcd390d08903)


注意:我不想使用 --exit-zero,因为它不允许我在出现合法错误时失败构建(例如,在 Pylint 的 undefined-variable 错误上)。 - Neeraj Kashyap

0

我同意@dmeister的观点,但是对于管道代码(Jenkinsfile),我建议采用try/catch并解析错误。这样您就可以确定是否只是从pylint获取状态位(请参阅Pylint文档),是否pylint报告了用法错误,或者是否出现了灾难性失败:

try {       
    sh 'pylint --output-format=parseable my_module'
} catch ( pylint_rc ) {
    // pylint_rc will be of the form
    // "hudson.AbortException: script returned exit code NN"
    // where NN is 1-63 and represents bit field;
    // bits 0-4 indicate lint-ish issues in analyzed code,
    // bit 5 indicates pylint usage error
    echo "pylint_rc= \'$pylint_rc\'"
    String rc = "$pylint_rc"
    String code = rc.split()[5]
    echo "Isolated return code string value $code"
    int value = code.toInteger()

    // catastrophic/crash error returns a 1; else there is a pylint return code
    int error_bits_code = value & 0x20
    int lint_bits_code = value & 0x1f
    echo "pylint error_bits_code=$error_bits_code ; lint_bits_code=$lint_bits_code"
    if ( (value == 1) || (error_bits_code != 0) ) {
        currentBuild.result = "FAILURE"
        throw pylint_rc
    }
}

向 Groovy 纯粹主义者道歉 - Groovy 不是我的强项,所以我相信这可以改进 - 让我知道。已知有一个漏洞:如果 pylint 仅检测到“致命”类型的错误(位 0),而没有任何其他问题(位 1-4 未设置),则此代码将不正确地抛出异常。但我的代码标记了大量问题,所以对我来说这不是问题。修复(?解析错误消息?)可能对具有 Groovy 技能的人来说很简单。


0

在编程语境下,pylint 可能会出现非零退出,但却没有明显的错误信息。你可能需要追踪代码,看看哪个文件导致了 pylint 的失败,并检查该文件。

对于我来说,我添加了一个空目录,在里面放置了一个 init.py 文件,然后 pylint 给出了相同的错误提示。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接