git commit前利用git-hook搭配husky執行代碼檢測

1、Git-Hook

Git 能在特定的重要動做發生時觸發自定義腳本。 有兩組這樣的鉤子:客戶端的和服務器端的。 客戶端鉤子由諸如提交和合並這樣的操做所調用,而服務器端鉤子做用於諸如接收被推送的提交這樣的聯網操做。
工做流相關的鉤子:css

  • pre-commit鉤子在鍵入提交信息前運行。 它用於檢查即將提交的快照,例如,檢查是否有所遺漏,確保測試運行,以及覈查代碼。 若是該鉤子以非零值退出,Git 將放棄這次提交,不過你能夠用git commit --no-verify來繞過這個環節。 你能夠利用該鉤子,來檢查代碼風格是否一致(運行相似lint的程序)、尾隨空白字符是否存在(自帶的鉤子就是這麼作的),或新方法的文檔是否適當。
  • prepare-commit-msg鉤子在啓動提交信息編輯器以前,默認信息被建立以後運行。 它容許你編輯提交者所看到的默認信息。 該鉤子接收一些選項:存有當前提交信息的文件的路徑、提交類型和修補提交的提交的 SHA-1 校驗。
  • commit-msg鉤子接收一個參數,此參數即上文提到的,存有當前提交信息的臨時文件的路徑。 若是該鉤子腳本以非零值退出,Git 將放棄提交,所以,能夠用來在提交經過前驗證項目狀態或提交信息。 在本章的最後一節,咱們將展現如何使用該鉤子來覈對提交信息是否遵循指定的模板。
  • post-commit鉤子在整個提交過程完成後運行。 它不接收任何參數 該鉤子通常用於通知之類的事情。

下面利用pre-commit鉤子來運行tslint程序。html

2、Husky

husky是一個Git Hook工具,可讓咱們更方便地使用Git的鉤子,並避免一些錯誤代碼或者一些不合規範的代碼提交和推送。node

3、安裝和配置

安裝husky、tslintgit

npm install husky tslint --save-dev

新建tslint.json文件至跟目錄,文件內容以下:npm

{
  "defaultSeverity": "warning",
  "extends": "tslint:recommended",
  "rules": {
    "array-type": false,
    "arrow-parens": false,
    "deprecation": {
      "severity": "warning"
    },
    "component-class-suffix": true,
    "contextual-lifecycle": true,
    "directive-class-suffix": true,
    "directive-selector": [
      true,
      "attribute",
      "app",
      "camelCase"
    ],
    "component-selector": [
      true,
      "element",
      "app",
      "kebab-case"
    ],
    "interface-name": false,
    "max-classes-per-file": false,
    "max-line-length": [
      true,
      140
    ],
    "member-access": false,
    "member-ordering": [
      true,
      {
        "order": [
          "static-field",
          "instance-field",
          "static-method",
          "instance-method"
        ]
      }
    ],
    "no-consecutive-blank-lines": false,
    "no-console": [
      true,
      "debug",
      "info",
      "time",
      "timeEnd",
      "trace"
    ],
    "no-empty": false,
    "no-inferrable-types": [
      true,
      "ignore-params"
    ],
    "no-non-null-assertion": true,
    "no-redundant-jsdoc": true,
    "no-switch-case-fall-through": true,
    "no-var-requires": false,
    "object-literal-key-quotes": [
      true,
      "as-needed"
    ],
    "object-literal-sort-keys": false,
    "ordered-imports": false,
    "quotemark": [
      true,
      "single"
    ],
    "trailing-comma": false,
    "no-conflicting-lifecycle": true,
    "no-host-metadata-property": true,
    "no-input-rename": true,
    "no-inputs-metadata-property": true,
    "no-output-native": true,
    "no-output-on-prefix": true,
    "no-output-rename": true,
    "no-outputs-metadata-property": true,
    "template-banana-in-box": true,
    "template-no-negated-async": true,
    "use-lifecycle-interface": true,
    "use-pipe-transform-interface": true
  },
  "rulesDirectory": [
    "codelyzer"
  ]
}

新建codelint.js腳本至根目錄,內容以下:json

const { exec } = require('child_process');

/**
 * @param  {type}  須要的文件類型:['ts', 'css']
 * @return {files} 返回符合條件的文件列表 ['a.ts b.ts c.ts', 'a.css, b.css']
 * @Description: 獲取暫存區待commit的文件列表
 */
const getChangedFiles = (tyes = []) => {
    return new Promise((resolve, reject) => {
        exec('git diff --cached --name-only', (err, stdout) => {
            if (err) {
                reject('獲取待commit文件列表失敗,錯誤:' + (err.message || err));
            } else {
                const files = tyes.reduce((result, type) => {
                    const filterFiles = stdout.split('\n').filter(f => f.indexOf('.' + type) > -1).join(' ');
                    result.push(filterFiles);
                    return result;
                }, [])

                resolve(files);
            }
        });
    });
}

/**
 * @param   {files}   待檢測的文件: 'a.ts b.ts'
 * @return  {stdout}  檢測結果
 * @Description: 執行代碼檢測
 */
const execLint = (type, files) => {
    return new Promise((resolve, reject) => {
        const cmdObj = {
            'ts': 'node ./node_modules/tslint/bin/tslint -c tslint.json',
            'css': 'node ./node_modules/stylelint/bin/stylelint'
        };

        const cmd = cmdObj[type];
        exec(`${cmd} ${files}`, (err, stdout) => {
            if (err) {
                return reject(err);
            }
            stdout ? reject(stdout) : resolve(null);
        });
    });
}

const start = async () => {
    try {
        const [ tsFiles ] = await getChangedFiles(['ts']);
        if (tsFiles) {
            const execResult = await execLint('ts', tsFiles);
            if (execResult) {
                throw ('代碼存在如下問題:\n' + execResult);
            }
        }
    } catch (error) {
        console.log(error);
        // 退出進程,再也不commit文件
        process.exit(1);
    }
}

start();

修改package.json,添加如下代碼:服務器

"husky": {
    "hooks": {
      "pre-commit": "node ./codelint.js"
    }
}

4、總結

按照以上安裝和配置,每次commit的時候就會執行codelint.js的代碼,這樣能夠阻止錯誤代碼和不符合規範代碼的提交,若是咱們要檢測css代碼和html代碼,能夠安裝htmllint、stylelint再添加相應的配置文件來實現。app

相關文章
相關標籤/搜索