pre-commit本地检查失败但CI服务器通过的排查咨询
问题描述
本地开发机分支工作树状态干净,执行pre-commit run --all-files时,格式化类钩子(如black、mdformat、clang-format)会失败并重新格式化文件,但Atlassian Bamboo CI服务器在同一分支执行相同命令时,这些钩子却意外通过。
以Python文件为例:添加代码行unused = 1+1,本地black钩子会将其格式化为unused = 1 + 1并返回失败,ruff钩子也会因未使用变量报错失败;但CI上black钩子显示通过,仅ruff钩子失败。
已完成的排查步骤:
- 确认本地与CI的pre-commit版本一致(均为3.3.3)
- 执行
pre-commit clean清理本地缓存 - 添加identity钩子验证文件过滤规则无差异
附精简后的.pre-commit-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]
可排查的方向
- 检查工具实际运行版本:pre-commit版本一致不代表钩子依赖的工具版本相同。分别在本地和CI执行以下命令,比对版本是否完全一致:
black --versionmdformat --versionclang-format --version
注意mdformat的额外依赖(如mdformat-black)也需要核对版本,避免因版本差异导致格式化规则不同。
- 验证文件行尾格式:本地与CI的换行符(LF/CRLF)设置可能不同,部分格式化工具会因行尾变化触发重新格式化,但CI拉取代码时可能自动转换了行尾格式。可以通过
git config core.autocrlf查看双方配置,或用file命令检查文件的行尾类型。 - 确认CI的文件状态:CI拉取代码后,可能存在文件未正确检出(如未跟踪、权限问题导致钩子无法修改),但通常会有报错。在CI的pre-commit命令前添加
git status和ls -l,确认文件状态与本地一致。 - 比对钩子执行参数:即使配置文件一致,CI环境可能通过环境变量、pre-commit全局配置覆盖参数。在本地和CI分别执行
pre-commit run --all-files --verbose,查看每个钩子的实际执行命令和参数,确认是否存在差异。 - 检查Python环境细节:即使指定了python3.10,本地与CI的Python环境可能有差异(如虚拟环境不同、额外包干扰)。执行
python3.10 -m pip list,比对双方依赖包版本,尤其是格式化工具相关的依赖。 - 验证CI代码完整性:CI可能使用浅克隆或只拉取部分文件,导致需要格式化的文件未被处理。在CI命令前添加
git fetch --unshallow和git diff origin/[你的分支名],确认代码与本地完全一致。 - 核对工具配置文件:black、clang-format等工具会读取本地配置文件(如
pyproject.toml、.clang-format),如果CI环境中这些文件缺失或内容不同,会导致格式化行为不一致。确认CI环境中的配置文件与本地完全相同。
内容的提问来源于stack exchange,提问作者Eric Smith
相关产品推荐
相关产品推荐

