Car*_*ten 1 python bash pylint gitlab-ci
我正在尝试从 Gitlab CI 脚本中的 PyLint 输出生成徽章。最终,如果 PyLint 具有非零退出代码,作业应该会失败。但在此之前,我希望创建徽章。所以我尝试了以下方法:
before_script:
- [...]
- mkdir -p public
script:
- pylint lib --disable R,missing-docstring,wrong-import-order --reports=y | tee public/pylint-report.txt
- export SUCCESS=${PIPESTATUS[0]}
- SCORE=$(tail -n 2 public/pylint-report.txt | grep -o -P "\d\d?\.\d+\/\d*" | head -1)
- echo "PyLint score ${SCORE}"
- python3.6 -m pybadges --left-text=PyLint --right-text=${SCORE} > public/pylint.svg
- exit ${SUCCESS}
artifacts:
when: always
[...]
Run Code Online (Sandbox Code Playgroud)
如果 PyLint 退出代码为 0,这可以正常工作:
$ mkdir -p public
$ pylint lib --disable R,missing-docstring,wrong-import-order --reports=y | tee public/pylint-report.txt; export SUCCESS=${PIPESTATUS[0]}
[Pylint report output]
$ SCORE=$(tail -n 2 public/pylint-report.txt | grep -o -P "\d\d?\.\d+\/\d*" | head -1)
$ echo "PyLint score ${SCORE}"
PyLint score 10.00/10
$ python3.6 -m pybadges --left-text=PyLint --right-text=${SCORE} > public/pylint.svg
$ exit ${SUCCESS}
Uploading artifacts...
public/pylint-report.txt: found 1 matching files
public/pylint.svg: found 1 matching files
Uploading artifacts to coordinator... ok id=XXX responseStatus=201 Created token=XXX
Job succeeded
Run Code Online (Sandbox Code Playgroud)
但是,当 PyLint 以非零值退出时,脚本会在第一行之后中止:
$ mkdir -p public
$ pylint lib --disable R,missing-docstring,wrong-import-order --reports=y | tee public/pylint-report.txt
[Pylint report output]
Uploading artifacts...
public/pylint-report.txt: found 1 matching files
WARNING: public/pylint.svg: no matching files
Uploading artifacts to coordinator... ok id=XXX responseStatus=201 Created token=XXX
ERROR: Job failed: exit code 1
Run Code Online (Sandbox Code Playgroud)
澄清:我希望作业失败,但我想确保脚本始终运行所有行。只有exit最后一行中的命令才能确定作业状态。
它在使用 Bash 的容器中运行。
我希望该tee命令始终以 0 退出,以便第一个脚本行永远不会失败。但情况似乎并非如此。
我试过|| true在第一行附加一个呼叫,但随后的行,SUCCESS=${PIPESTATUS[0]}始终为 0;也许这是指根本原因。
另外,我试图将export调用(现在是第二行)附加到第一行,用分号分隔。同样,即使我也期望export调用总是以 0 退出,也没有区别。
因此,我的问题是:为什么脚本的第一行可以以非零代码退出?我如何防止这种情况?
或者:是否有更简单的方法来实现相同的目标?
Gitlab 设置了一堆您实际上并不想要的“有用”shell 选项。其中包括errexit, aka set -e, and pipefail(这通常是一个好主意,但与 with 结合set -e意味着如果管道的任何组件出现故障,您的脚本将退出)。
要解决这个问题:
{ SUCCESS=0; pylint lib ...args... || SUCCESS=$?; } > >(tee public/pylint-report.txt)
Run Code Online (Sandbox Code Playgroud)
我们SUCCESS直接坐在这里(不需要export),所以你PIPESTATUS以后不需要参考。在命令的返回值上进行分支将该命令标记为“已检查”,因此出于errexit.
顺便说一句,有关背景set -e以及为什么它是您真正不想要的东西,请参阅BashFAQ #105。
另一方面,全大写变量名称用于对 shell 或 POSIX 指定工具有意义的变量,而至少包含一个小写字符的名称保留供应用程序使用并保证不会冲突。请参阅https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap08.html,请记住,设置 shell 变量将覆盖任何预先存在的同名环境变量。