V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
爱意满满的作品展示区。
SingeeKing
V2EX  ›  分享创造

kitty: git hook 管理工具 + lint-staged + dependency manager

  •  
  •   SingeeKing ·
    ImSingee · 2023-09-18 11:38:13 +08:00 · 2211 次点击
    这是一个创建于 434 天前的主题,其中的信息可能已经有所发展或是发生改变。

    这个工具肯定不完美,未来至少还会经历一个月的时间进行稳定和功能增强,现阶段发出来只是单纯的打算 Build in Public (另外,也确实可以正式使用一些功能了),我其实挺想等等完美了再发的,但是怕时间久了又没有继续去做/去写文档的动力了,所以虽然不完美,但还是提前发下

    https://github.com/ImSingee/kitty

    如果你用过 Node.js 的生态,肯定对 husky 和 lint-staged 不陌生,简单来说,这个工具就是这俩的整合 & 增强,给任何语言增加了 git hook 管理和基于要提交的文件进行 lint 的功能

    实话实说,这个工具写出来主要还是为了解决我自己的痛点的

    痛点一:无法共享 hook

    之前的方案都是通过 Makefile 进行 hook 拷贝或者干脆文档说明要手动安装 hook 的,但是如果 hook 规则更新了那么总归会产生问题

    在撰写 hook 前,可以通过 kitty install --direnv 来生成给 direnv 使用的 sh 文件(并提交),这样只要文档说明下让协作者执行 direnv allow 就可以完成每次进入时自动安装/更新 hook 了

    目前 kitty install 会自动生成一个 .kittyrc 配置文件,这个文件可以删除,如果要保留的话也建议使用 .kittyrc.json (方便直接配置 lint-staged 规则给 json 做格式化)

    痛点二:无法只基于特定文件运行 lint

    例如 gofmt 、golines 等工具,之前想要实现对于只打算提交的文件来执行特定命令只能在 pre-commit 中写一段长长的 git diff 命令,并且难以做到自动化的应用修改、也难以处理某些既被 add 又再次修改的文件

    这一切现在可以简单通过 lint-staged 来实现

    比如对所有 .go 文件执行 gofmt ,之前需要

    changed=$(git diff --cached --name-only --diff-filter=ACM | grep -v vendor | grep '.go$')
    gofmt -s -l $changed
    git add $changed
    

    现在只需要配置 kitty 的配置文件

    {
       "lint-staged": {
         "*.go": "gofmt -s -l"
       }
    }
    

    痛点三:无法基于特定目录运行 lint

    主要是 Go 场景下 golangci-lint ,传递时(如果出现多目录修改)需要指定 go package ,用 shell 来做到会非常的麻烦,但是用 kitty lint-staged 只需要

    {
       "lint-staged": {
         "*.go": "[dir] @golangci-lint run"
       }
    }
    

    这里用的 @golangci-lint 而不是 golangci-lint 证明使用的是 kitty tools ,见👇

    痛点四:难以管理依赖工具的版本

    某些依赖需要锁死版本,例如 protoc-gen-go 生成的文件会带有所使用的工具版本、golangci-lint 升级后可能会产生新的 lint error ,又或者 gci 这个鬼东西平均每两个版本就会有一个 breaking change 🙃

    因此顺便在 kitty 中集成了一个简单的 tools manager ,将依赖工具锁死

    例如使用 golangci-lint 时,只需要

    kitty tools install [email protected]
    

    然后使用 kitty @golangci-lint 执行这个工具,就可以保证始终使用的是 1.54.2 这个版本

    并且这个版本信息会保存在 kitty config 中,协作者也会始终使用最新的版本

    如果配置了 direnv ,kitty 的 PATH 会被自动提高到最高优先级,即在项目目录下直接运行 golangci-lint 而不是 kitty @golangci-lint 也会使用被 kitty 管理的版本

    目前的 tools manager 还有很多优化空间,例如不支持本地 registry 、只支持下载二进制和使用 go install 、没有保存 checksum 、不会自动下载缺失的工具(而是需要手动执行 kitty install )等

    附上一份我自己给 go 项目所配置的 kitty config

    .kitty/pre-commit

    kitty @lint-staged
    

    .kitty/pre-push

    go test -tags test -trimpath -race -timeout=2m -short -failfast ./...
    

    .kittyrc.json

    {
      "lint-staged": {
        "files": {
          "*.go": [
            "gofmt -s -w -l",
            "@gci write --skip-generated --skip-vendor -s Standard -s Default -s 'Prefix(github.com/ImSingee/SOME_PKG)' -s Blank -s Dot",
            "@golines -w --max-len=180 --reformat-tags --shorten-comments --ignore-generated",
            "[dir] @golangci-lint run"
          ],
          "*.json": "@format",
          "go.mod": "go mod edit -fmt"
        }
      },
      "tools": {
        "gci": "0.11.1",
        "golangci-lint": "1.54.2",
        "golines": "0.11.0"
      }
    }
    
    1 条回复    2023-09-18 14:26:32 +08:00
    Jirajine
        1
    Jirajine  
       2023-09-18 14:26:32 +08:00 via Android
    与著名工具命名冲突了
    https://sw.kovidgoyal.net/kitty/
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   5763 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 24ms · UTC 03:42 · PVG 11:42 · LAX 19:42 · JFK 22:42
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.