如果执行 shell 失败,不要让 Jenkins build 失败

作为构建过程的一部分,我将 git 提交作为执行 shell 步骤运行。但是,如果工作区中没有任何更改,Jenkins 的构建就会失败。这是因为 git 在没有要提交的更改时返回错误代码。我想要么中止构建,要么只是标记为不稳定,如果是这种情况。有什么想法吗?

215217 次浏览

你可以使用 文本查找插件。它将允许您检查输出控制台以获得您选择的表达式,然后将构建标记为 Unstable

Jenkins 通过步骤的返回值来确定步骤的成功/失败。对于 shell,它应该是最后一个值的返回值。对于 WindowsCMD 和(POSIX) Bash shell,您应该能够通过使用 exit 0作为最后一个命令手动设置返回值。

我可以用这里找到的答案来解决这个问题:

如何在没有错误的情况下不提交任何东西?

git diff --quiet --exit-code --cached || git commit -m 'bla'

下面的方法只有在发生更改时才能对 反复无常起作用。所以构建只有在提交失败时才会失败。

hg id | grep "+" || exit 0
hg commit -m "scheduled commit"

如果没有什么可以推动 git 返回退出状态1。执行 shell 生成步骤分别标记为失败。可以使用 OR 语句 | | (双管道)。

git commit -m 'some messasge' || echo 'Commit failed. There is probably nothing to commit.'

这意味着,如果第一个参数失败,则执行第二个参数(返回的退出状态 > 0)。第二个命令总是返回0。当没有什么可推(退出状态1-> 执行第二条命令)时,echo 将返回0并继续构建步骤。

要标记构建为不稳定,可以使用构建后步骤 Jenkins 文本查找器。它可以通过控制台输出,匹配模式(您的回声)并将 build 标记为不稳定。

关于标题中的(更一般的)问题——为了防止詹金斯失败,你可以防止它看到退出代码1。例如 ping:

bash -c "ping 1.2.3.9999 -c 1; exit 0"

现在你可以得到 ping 的输出:

output=`bash -c "ping 1.2.3.9999 -c 1; exit 0"`

当然,你可以使用任何命令而不是 ping ...-包括 git commit

还有一个更好的办法告诉詹金斯不要失败。 您可以在构建步骤中隔离您的提交,并将 shell 设置为不会失败:

set +e
git commit -m "Bla."
set -e

指挥官失败时停止进一步执行:

command || exit 0

指挥官失败时继续执行:

command || true

Jenkins 默认使用 /bin/sh -xe执行 shell 构建步骤。-x表示打印执行的每个命令。-e意味着如果脚本中的任何命令失败,则退出。

因此,我认为在您的例子中发生的情况是 git 命令 exit 为1,并且由于缺省的 -e参数,shell 拾取非0的退出代码,忽略脚本的其余部分,并将步骤标记为失败。我们可以证实这一点,如果你可以张贴你的构建步骤脚本在这里。

如果是这种情况,您可以尝试放置 #!/bin/sh,这样脚本将不带选项地执行; 或者在构建步骤的顶部执行 set +e或类似的操作,以覆盖此行为。


编辑: 另一件需要注意的事情是,如果您的 shell 脚本 返回非0代码中的 最后一道命令,即使使用这种设置,整个构建步骤仍将被标记为失败。在这种情况下,您可以简单地将 true命令放在末尾以避免这种情况。

另一个相关的问题

如果将这些命令放入 shell 块:

false
true

您的构建将被标记为失败(至少有1个非零退出代码) ,因此您可以添加(set + e)来忽略它:

set +e
false
true

但是,即使(set + e)已经到位,这也不会失败:

set +e
false

因为最后一个 shell 命令必须以0退出。

Https://jenkins.io/doc/pipeline/steps/workflow-durable-task-step/#sh-shell-script

如果您包含 returStatus: true 属性,则将忽略 shell 返回。

对于多个 shell 命令,我通过添加以下内容来忽略失败:

设置 + e 命令 真实

enter image description here

另一个带有一些提示的答案可能对某些人有帮助:

记住分开你的命令 遵循以下规则:

Command1 & & command2-意味着,只有在 command1成功的情况下,才会执行 command2

Command1 ; command2-意思是,尽管命令1的结果是执行命令2

例如:

String run_tests = sh(script: "set +e && cd ~/development/tests/ && gmake test ;set -e;echo 0 ", returnStdout: true).trim()
println run_tests

如果 gmake test失败(测试失败) ,将使用 set -eecho 0命令成功执行,同时剪切以下代码:

String run_tests = sh(script: "set +e && cd ~/development/tests/ && gmake test && set -e && echo 0 ", returnStdout: true).trim()
println run_tests

有一点错误,命令 set -eecho 0 in&& gmake test && set -e && echo 0将被跳过,使用 println run_tests语句,因为失败的 gmake test将中止 jenkins 构建。作为解决方案,您可以切换到 returnStatus:true,但是这样就会错过命令的输出。

这个答案 是正确的,但是它没有指定 || exit 0或者 || true在 shell 命令中。这里有一个更完整的例子:

sh "adb uninstall com.example.app || true"

上述措施将会奏效,但下列措施将会失败:

sh "adb uninstall com.example.app" || true

也许对别人来说是显而易见的,但在我意识到这一点之前,我浪费了很多时间。