我的开发机器上有一个干净的分支工作树。如果我运行
pre-commit run --all-files
我的格式化程序挂钩失败,会重新格式化一些文件。我的 CI 服务器(Atlassian Bamboo)也在同一个分支上运行 pre-commit run --all-files
,但钩子通过了,这是意外的。我可以检查什么来找出原因?
作为示例,我将以下行添加到 Python 文件中:
unused = 1+1
我有一个用于格式化的黑色钩子和一个用于掉毛的皱褶钩子。本地输出为:
black....................................................................Failed
- hook id: black
- files were modified by this hook
reformatted tasks/tool.py
All done! ✨ 🍰 ✨
1 file reformatted, 1878 files left unchanged.
ruff.....................................................................Failed
- hook id: ruff
- exit code: 1
tasks/tool.py:76:5: F841 [*] Local variable `unused` is assigned to but never used
Found 1 error.
[*] 1 potentially fixable with the --fix option.
这正如预期的那样——黑色会将行重新格式化为
unused = 1 + 1
(加号运算符周围的空格),并且 ruff 正确地识别出 unused
未使用。
但是,在 CI 服务器上,输出是:
black....................................................................Passed
ruff.....................................................................Failed
- hook id: ruff
- exit code: 1
tasks/tool.py:76:5: F841 [*] Local variable `unused` is assigned to but never used
Found 1 error.
[*] 1 potentially fixable with the --fix option.
意想不到的传球并不是黑色独有的。我还有 mdformat 和 clang-format 的钩子,它们也在本地失败并在 CI 服务器上意外通过。
我尝试过的事情:
pre-commit --version
的调用,以确保它们相同 (3.3.3)pre-commit clean
的调用,以确保钩子不会出现一些奇怪的缓存问题我还可以采取哪些其他措施来追踪此情况?
这是我的(经过精简但希望仍然有效/具有代表性)预提交-config.yaml:
default_language_version:
python: python3.10
exclude: >
(?x)^(
acceptance/.*|
build/.*|
deploy/.*
)$
repos:
- repo: https://github.com/PyCQA/docformatter
rev: v1.1
hooks:
- id: docformatter
alias: reformat-docs
types: [python]
args:
- --in-place
- repo: https://github.com/psf/black
rev: "23.3.0"
hooks:
- id: black
alias: reformat
types: [python]
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.0.292
hooks:
- id: ruff
alias: lint
types: [python]
- repo: https://github.com/executablebooks/mdformat
rev: "0.7.16"
hooks:
- id: mdformat
description: Auto-format Markdown files.
args: [--wrap=88, --number]
additional_dependencies:
- mdformat-gfm==0.3.5
- mdformat-tables==0.4.1
- mdformat-black==0.1.1
- linkify-it-py==2.0.2
- repo: https://github.com/adrienverge/yamllint.git
rev: v1.29.0
hooks:
- id: yamllint
description: This hook runs yamllint.
entry: yamllint
language: python
types: [file, yaml]
args:
- -c
- yamllint-config.yml
- --no-warnings
- repo: https://github.com/pre-commit/mirrors-clang-format
rev: v16.0.6
hooks:
- id: clang-format
types_or: [c++, c]
- repo: meta
hooks:
- id: identity
types: [python]
根据文档,预提交挂钩“必须在失败或修改文件时退出非零”。如果一个钩子意外通过,它应该与这两件事之一有关。
以 black 为例,除非通过 --check 标志,否则即使重新格式化文件,它也会以 0 退出。因此,预提交必须依赖于检测文件已更改以使挂钩失败。
预提交如何知道文件是否更改?它在前后使用 git diff
git diff
命令添加到我的构建脚本中,我发现它在 CI 服务器上失败并打印错误消息。据推测,预提交也出现了错误,但前后消息相同,导致未检测到更改而“通过”。看起来预提交并没有检查
git diff
的退出代码。在我的例子中,由于 Bamboo 的链接存储库功能和 Docker 容器未挂载 Bamboo 的缓存目录的组合,
git diff
失败了。错误看起来像:
error: object directory /opt/bamboo-home/alpha/xml-data/build-dir/_git-repositories-cache/fdae2edae02caea8ea6d761ec2587a93d46f063d/.git/objects does not exist; check .git/objects/info/alternates.
error: unable to find e6ce93b6af518f7e3efd767aa7124aed5d036734
fatal: unable to read e6ce93b6af518f7e3efd767aa7124aed5d036734