diff --git a/.travis.yml b/.travis.yml index 7c857a0cb..e9e057fa4 100644 --- a/.travis.yml +++ b/.travis.yml @@ -17,6 +17,10 @@ script: - cat .git/hooks/post-checkout - time git checkout - node scripts/ci-post-checkout-check + # Test HUSKY_SKIP_HOOKS + - cat .git/hooks/post-checkout + - HUSKY_SKIP_HOOKS=1 time git checkout + - node scripts/ci-husky-skip-hooks # Should not fail due to missing script - node scripts/ci-break-path.js - cat .git/hooks/post-checkout diff --git a/DOCS.md b/DOCS.md index 0b52ea866..e905fd98f 100644 --- a/DOCS.md +++ b/DOCS.md @@ -28,6 +28,14 @@ If you don't want `husky` to automatically install Git hooks, simply set `HUSKY_ HUSKY_SKIP_INSTALL=1 npm install ``` +## Skip running hooks + +If you don't want `husky` to run your hooks, simply set `HUSKY_SKIP_HOOKS` environment variable to `1`. + +```sh +HUSKY_SKIP_HOOKS=1 git checkout +``` + ## Multi-package repository (monorepo) If you have a multi-package repository, it's __recommended__ to use tools like [lerna](https://github.com/lerna/lerna) and have `husky` installed ONLY in the root `package.json` to act as the source of truth. diff --git a/package-lock.json b/package-lock.json index 5a833ba8c..25c6d8b7c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2359,8 +2359,7 @@ "ansi-regex": { "version": "2.1.1", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "aproba": { "version": "1.2.0", @@ -2381,14 +2380,12 @@ "balanced-match": { "version": "1.0.0", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "brace-expansion": { "version": "1.1.11", "bundled": true, "dev": true, - "optional": true, "requires": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -2403,20 +2400,17 @@ "code-point-at": { "version": "1.1.0", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "concat-map": { "version": "0.0.1", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "console-control-strings": { "version": "1.1.0", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "core-util-is": { "version": "1.0.2", @@ -2533,8 +2527,7 @@ "inherits": { "version": "2.0.3", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "ini": { "version": "1.3.5", @@ -2546,7 +2539,6 @@ "version": "1.0.0", "bundled": true, "dev": true, - "optional": true, "requires": { "number-is-nan": "^1.0.0" } @@ -2561,7 +2553,6 @@ "version": "3.0.4", "bundled": true, "dev": true, - "optional": true, "requires": { "brace-expansion": "^1.1.7" } @@ -2569,14 +2560,12 @@ "minimist": { "version": "0.0.8", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "minipass": { "version": "2.3.5", "bundled": true, "dev": true, - "optional": true, "requires": { "safe-buffer": "^5.1.2", "yallist": "^3.0.0" @@ -2595,7 +2584,6 @@ "version": "0.5.1", "bundled": true, "dev": true, - "optional": true, "requires": { "minimist": "0.0.8" } @@ -2676,8 +2664,7 @@ "number-is-nan": { "version": "1.0.1", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "object-assign": { "version": "4.1.1", @@ -2689,7 +2676,6 @@ "version": "1.4.0", "bundled": true, "dev": true, - "optional": true, "requires": { "wrappy": "1" } @@ -2775,8 +2761,7 @@ "safe-buffer": { "version": "5.1.2", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "safer-buffer": { "version": "2.1.2", @@ -2812,7 +2797,6 @@ "version": "1.0.2", "bundled": true, "dev": true, - "optional": true, "requires": { "code-point-at": "^1.0.0", "is-fullwidth-code-point": "^1.0.0", @@ -2832,7 +2816,6 @@ "version": "3.0.1", "bundled": true, "dev": true, - "optional": true, "requires": { "ansi-regex": "^2.0.0" } @@ -2876,14 +2859,12 @@ "wrappy": { "version": "1.0.2", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "yallist": { "version": "3.0.3", "bundled": true, - "dev": true, - "optional": true + "dev": true } } }, diff --git a/scripts/ci-husky-skip-hooks.js b/scripts/ci-husky-skip-hooks.js new file mode 100644 index 000000000..60f4f32c9 --- /dev/null +++ b/scripts/ci-husky-skip-hooks.js @@ -0,0 +1,25 @@ +/* eslint-disable @typescript-eslint/no-var-requires */ +const fs = require('fs') +const path = require('path') + +const filename = path.join(__dirname, '../ci-post-checkout') + +if (fs.existsSync(filename)) { + const data = fs.readFileSync(filename, 'utf-8') + + if (data.split(' ').length !== 3) { + console.log('Not all params were set in HUSKY_GIT_PARAMS') + console.log('Got', data) + process.exit(1) + } + + fs.unlinkSync(filename) + console.log( + '.git/hooks/post-checkout script has run, hooks were not skipped.' + ) + process.exit(1) +} else { + console.log( + '.git/hooks/post-checkout script has not run, hooks were successfully skipped.' + ) +} diff --git a/src/runner/index.ts b/src/runner/index.ts index 7e7bbbfa2..0befb7f84 100644 --- a/src/runner/index.ts +++ b/src/runner/index.ts @@ -7,6 +7,7 @@ import getConf from '../getConf' export interface Env extends NodeJS.ProcessEnv { HUSKY_GIT_STDIN?: string HUSKY_GIT_PARAMS?: string + HUSKY_SKIP_HOOKS?: string } /** @@ -17,6 +18,17 @@ export default async function run( [, scriptPath, hookName = '', HUSKY_GIT_PARAMS]: string[], getStdinFn: () => Promise = getStdin ): Promise { + if ( + process.env.HUSKY_SKIP_HOOKS === 'true' || + process.env.HUSKY_SKIP_HOOKS === '1' + ) { + console.log( + "HUSKY_SKIP_HOOKS environment variable is set to 'true',", + 'skipping running Git hooks.' + ) + return 0 + } + const cwd = path.resolve(scriptPath.split('node_modules')[0]) // In some cases, package.json may not exist // For example, when switching to gh-page branch