Husky 的简单使用

110 阅读2分钟
项目使用工具版本:
   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 关联起来,在团队之间共享。

关联具体实现步骤

  1. 拷贝 husky.sh 到项目中,其主要工作是添加 debug 开关以及支持 .huskyrc 配置文件,最后将其添加到 .gitignore
  2. 将 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')
}


总结

多多使用自动化工具,可以减少工作中主观原因导致的失误,当然也需要了解工具运行的原理,才能很好的使用。