CI 从Git hooks学起

前端工程化

前端工程化是前端的一个重要领域,简单的从代码规范开始,复杂的到团队脚手架搭建。在小团队中大多由开发兼任,在大团队中则可能有专门的基建团队负责。可见工程化的普及度是非常高的,只是不同团队的水平或复杂度参差不齐。

工程化对于前端开发是个必备技能。不说要学的多深多厉害,起码能 hold 住一个普通项目。我们先从 Git 的 hooks 学起,这是很多自动化的关键。

Git hooks

以前可能还会时常遇到使用 SVN 管理的代码仓库,而现在已经很少见到了,绝大多数项目应该都使用或切换到 Git 管理了。其中两个最重要的原因就是 Git 的分布式及便捷的分支管理。关于 Git 的使用就不细说了,而 Git hooks 顾名思义就是 Git 提供的一些钩子,我们可以利用其做一些自动化的事情。

Git 提供的钩子可以在仓库的 .git 文件中可以看到,在 .git/hooks 下有这么一些文件

.
├── applypatch-msg.sample
├── commit-msg.sample
├── fsmonitor-watchman.sample
├── post-update.sample
├── pre-applypatch.sample
├── pre-commit.sample
├── pre-merge-commit.sample
├── pre-push.sample
├── pre-rebase.sample
├── pre-receive.sample
├── prepare-commit-msg.sample
├── push-to-checkout.sample
└── update.sample

他们都是以 .sample 结尾的 bash 文件,其实就是钩子的示例文件了,我们把 .sample 去掉便可让 bash 生效,在特定的时期就会执行这些钩子文件代码,例如 pre-commit 会在我们执行 git commit 的时候执行,如果 pre-commit 的执行结果状态为 0,则 commit 成功,否则 commit 会失败。所以说,通过 Git 提供的各类钩子,我们可以在流程中加入各类校验,或者自动化相关的能力,各种工具包实际也产生于此。

其中最简单常用的应该是 pre-commitcommit-msg 钩子了。pre-commit 多用于规范校验、自动修复,commit-msg 多用于 commit message 规范校验、提示。

看到这里,我想大家可以联想到团队项目在使用 Git 命令时候的一些自动化的原理了吧,很酷但原理实际很简单。

husky

上面说了原理很简单,但是操作起来还是有一些需要思考的点的。例如

  • .git/hooks 的内容是不会被 push 到远程的,pull 的时候自然也无法同步,那团队间该如何同步呢

  • .git 一般在编辑器上默认也是隐藏文件,想要修改其内容需要先设置为显示,修改完再隐藏吗

所以 husky 就来了,其作用在于帮助开发者创建修改 hooks 并同步。husky 在很多文章都有介绍,并且会对比其新旧版本。我们这边仅仅学习下新版本的使用就好了。

新版本的新在于利用了 Git 的新能力,在 .git/config 下可以通过 hooksPath 自定义 hooks 目录

[core]
hooksPath = xxx

简单介绍下使用

安装

npm install husky --save-dev

命令式配置 package.json,作用是以后每次执行完 install 都会执行 husky install,实际就是自动帮你修改 .git 配置文件,修改 hooks 目录,解决一致性问题

npm set-script prepare "husky install"
npm run prepare

添加 hooks

npx husky add .husky/pre-commit "npm run lint"

这时候在项目根目录下会创建 .husky 目录,好奇的你可以看看 ./git/config 的配置中多了 hooksPath = .husky

我们来看看新建的 ./husky/pre-commit 的内容,实际就是个执行 npm run lint 的 bash。当然,其中是通过 husky.sh 执行的,细节不再展开。

#!/usr/bin/env sh
. "$(dirname -- "$0")/_/husky.sh"

npm run lint

我们继续配置 lint,在 package.json 的 script 中添加

{
    "lint": "eslint --ext .js src/"
}

当然安装 eslint 及配置规则必不可少

npm i eslint -D

.eslintrc

module.exports = {
    "env": {
        "browser": true,
        "es2021": true
    },
    "extends": "eslint:recommended",
    "parserOptions": {
        "ecmaVersion": "latest",
        "sourceType": "module"
    },
    "rules": {
        "semi": [2, "never"]
    }
}

好了,现在每次执行 git commit 都会先执行 npm run lint,只有通过 eslint 的检查,才能继续填写 commit message,否则将提交失败。

commitlint

前面了解了常见的 pre-commit 用于配置 lint 的情况。我们再来看看另一常见的钩子 commit-msg。当执行 git commit 提交时,如果 pre-commit 执行通过,则继续触发 commit-msg。如果自己写 bash 研究如何校验 message 格式会比较麻烦,而 commitlint 正是用于提供统一的校验规则并支持自定义配置。即通过配置的方式来校验 message,避免大家陷入不会 bash 的窘局。

我们看看其使用

安装

npm install @commitlint/cli @commitlint/config-conventional -D

生成配置

echo "module.exports = {extends: ['@commitlint/config-conventional']}" > commitlint.config.js

通过 husky 添加 commit-msg

npx husky add .husky/commit-msg "npx commitlint --edit $1"

现在再提交 commit 就会验证提交格式了,正确的 message 格式形如

git commit -m 'fix: 修复配置'

当然,具体格式是支持自定义配置的,感兴趣可以查看其文档。

lint-staged

上面我们执行 eslint 检查的时候是对整个项目进行检查的,有没有办法对增量代码进行检查呢?在单测领域,增量检查,增量覆盖率是个很常见的需求。

借助 lint-staged 可以做到,lint-staged 仅仅作用于通过 git add 提交到暂存区的文件。

我们来看看其使用

安装

npm install --save-dev lint-staged

添加 .lintstagedrc 配置,数组的形式意味着可以添加更多不同的命令,例如单元测试

{
    "src/**/*.js": ["npx eslint --fix", "git add"]
}

顾名思义,对 JS 执行 eslint 检查并自动修复,再执行 git add 添加代码。这边的 git add 只会添加在前面命令中的自动修改的代码,不会提交你原本工作区的修改,实际上是通过 git stash 先缓存了工作区。

总结

本文介绍了 Git hooks 及常见的一些和 hooks 配合使用的 npm 插件 husky、commitlint、lint-staged。提供了自动化校验,提交信息校验的简单思路。

参考

© 版权声明
THE END
喜欢就支持一下吧
点赞7 分享
评论 抢沙发
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

取消
昵称表情代码图片

    暂无评论内容