【问题标题】:Run a pre-commit hook only if all other hooks are successful仅当所有其他钩子都成功时才运行预提交钩子
【发布时间】:2023-03-11 03:35:01
【问题描述】:

我有一个预提交设置,其中包含几个非常标准的存储库(无论如何对于 Python 项目),以及一个非常神奇的项目特定操作。

类似这样的:

repos:
  - repo: https://github.com/timothycrosley/isort
    ...
  - repo: https://github.com/psf/black
    ...
  - repo: https://gitlab.com/pycqa/flake8
    ...

  - repo: local
    hooks:
      - id: local_project_specific_magic
        name: local-magic-script
        entry: magic_script.sh
        language: script

当所有检查都成功时,这一切运行良好。

我需要实现的是让最终的local_project_specific_magic 挂钩不执行,如果之前的任何挂钩失败。这可行吗?


我尝试添加fail_fast: true,这似乎有效,但如果其中任何一个钩子失败,它也会阻止其他钩子运行。例如,即使 isort 修复了一些导入,我仍然希望 black 做它的事情。

【问题讨论】:

    标签: pre-commit.com


    【解决方案1】:

    fail_fast: true 与没有重大手术的情况一样接近


    你可以想象每个其他的钩子都会做类似的事情:

    entry: bash -c 'black "$@" || touch .fail' --
    

    然后你的脚本会做类似if [ -f .fail ]; then echo 'some other hook failed' && exit 1; fi

    您还需要在开头添加一个 always_run: true 挂钩,以确保 .fail 也不存在 (rm -f .fail)

    但这一切听起来像是一个大的、无法维护的 hack。我怀疑你有一个 XY 问题,因为你的要求似乎非常奇怪——也许详细说明你为什么想要这个设置?


    免责声明:我创建了预提交

    【讨论】:

      【解决方案2】:

      我有一个非常相似的任务,@Anthony Sottile 的回答给了我一个新的想法。

      我对这个问题的解决方案是使用log_file 关键字来生成pre-commit.log。这些文件仅在blackisort(或两者)pre-commits 失败时才存在。

      我的.pre-commit-config.yaml 最后看起来像这样:

      repos:
      -   repo: local
          hooks:
          - id: cleaner
            name: cleaner
            entry: bash clean_logfiles.sh
            language: system
      -   repo: https://github.com/ambv/black
          hooks:
          - id: black
            log_file: pre-commit.log
      -   repo: https://gitlab.com/pycqa/flake8
          hooks:
          - id: flake8
            log_file: pre-commit.log
        - repo: local
          hooks:
            - id: local_project_specific_magic
              name: local-magic-script
              entry: bash magic_script.sh
              language: system
      

      在我本地的magic_script.sh上面我加了

      if [ -f "pre-commit.log" ]; then
          echo "Error in earlier pre-commit! We skip magic_script.sh."
          exit 1
      else
         # some more magic_script.sh
      fi
      

      通过这种方式,我可以选择哪些预提交对我很重要。

      为避免下一次运行因旧日志文件而失败,我添加了清理程序预提交,它只是删除了这些旧日志文件。

      代码非常基本,如下所示:

      if [ -f "pre-commit.log" ]; then
         echo "delete pre-commit.log"
         rm "pre-commit.log"
      fi
      

      【讨论】:

        猜你喜欢
        • 2013-12-15
        • 2017-02-08
        • 2016-09-02
        • 2018-07-22
        • 1970-01-01
        • 2015-03-30
        • 1970-01-01
        • 2019-07-12
        相关资源
        最近更新 更多