项目使用工具版本:
yarn: 3.2.4
husky: ^8.0.2
为什么要使用 husky ?
该项目使用gitlab-ci自动化工具,在提交代码到远程dev分支后,会触发执行一系列脚本后,自动发布包到gitlab npm registry。发布包的一个必要条件是提升package.json中的version值,但是由于非受迫性失误,导致忘记加版本号后提交到dev分支后,ci自动化执行失败,报如下错误
$ yarn npm publish --tag $DIST_TAG
[21] YN0000: README.md
[22] YN0000: package.json
[23] YN0000: protocols.d.ts
[24] YN0000: protocols.js
[25] YN0035: insufficient_scope
[26] YN0035: Response Code: 403 (Forbidden)
[27] YN0035: Request Method: PUT
[28] YN0035: Request URL: <https://code.apowo.com/api/v4/projects/312/packages/npm/@pixow%2fproto>
[29] YN0000: Failed with errors in 0s 378ms
在一番排查NPM_TOKEN是否有效的操作后,才发现是 version 没变导致的失败,所以痛定思痛,决定使用 git hook 来改变 version ,防止后面再出现失误。
husky 使用
1. Install husky
yarn add husky --dev
2. Enable Git hooks
yarn husky install
3. Create hook
yarn husky add .husky/pre-commit "yarn version patch"
问题1: 在运行 git commit -m "xxxx"
后,发现抱错 # stdin is not a tty
,解决办法查看 github.com/typicode/hu…
问题2: 在hook脚本执行完后,期望的package.json 的 version 值变化了,但是本地仓库多了更改的文件 package.json,所以需要给.husky/pre-commit
再加上 git add package.json
# .husky/pre-commit
#!/usr/bin/env sh
. "$(dirname -- "$0")/_/husky.sh"
. "$(dirname "$0")/common.sh"
yarn version patch
git add package.json
husky 实现原理
本地的 git hook
是保存在本地的 .git
文件夹中的,本地的 git hook
是不会被提交到版本控制中的。这就存在了一个问题,便是如何在项目中管理 Git hooks,这个时候就需要 Husky 登场了。Husky 的原理就是在项目的根目录中使用一个配置文件,然后在安装 Husky 的时候把配置文件和 Git hook 关联起来,在团队之间共享。
关联具体实现步骤
- 拷贝
husky.sh
到项目中,其主要工作是添加 debug 开关以及支持.huskyrc
配置文件,最后将其添加到.gitignore
。 - 将 Git 的 core.hooksPath 修改为项目目录的
.husky
,后续添加的 hooks 都将存放在此目录。
## 关联核心代码
// src/index.ts
export function install(dir = '.husky'): void {
if (process.env.HUSKY === '0') {
l('HUSKY env variable is set to 0, skipping install')
return
}
// Ensure that we're inside a git repository
// If git command is not found, status is null and we should return.
// That's why status value needs to be checked explicitly.
if (git(['rev-parse']).status !== 0) {
return
}
// Custom dir help
const url = 'https://typicode.github.io/husky/#/?id=custom-directory'
// Ensure that we're not trying to install outside of cwd
if (!p.resolve(process.cwd(), dir).startsWith(process.cwd())) {
throw new Error(`.. not allowed (see ${url})`)
}
// Ensure that cwd is git top level
if (!fs.existsSync('.git')) {
throw new Error(`.git can't be found (see ${url})`)
}
try {
// Create .husky/_
fs.mkdirSync(p.join(dir, '_'), { recursive: true })
// Create .husky/_/.gitignore
fs.writeFileSync(p.join(dir, '_/.gitignore'), '*')
// Copy husky.sh to .husky/_/husky.sh
fs.copyFileSync(p.join(__dirname, '../husky.sh'), p.join(dir, '_/husky.sh'))
// Configure repo
const { error } = git(['config', 'core.hooksPath', dir])
if (error) {
throw error
}
} catch (e) {
l('Git hooks failed to install')
throw e
}
l('Git hooks installed')
}
总结
多多使用自动化工具,可以减少工作中主观原因导致的失误,当然也需要了解工具运行的原理,才能很好的使用。