1 | # grunt-githooks
|
2 |
|
3 | [![Build Status](https://travis-ci.org/rhumaric/grunt-githooks.png?branch=master)](https://travis-ci.org/rhumaric/grunt-githooks)
|
4 | [![Code Climate](https://codeclimate.com/github/rhumaric/grunt-githooks.png)](https://codeclimate.com/github/rhumaric/grunt-githooks)
|
5 |
|
6 | > A Grunt plugin to help bind Grunt tasks to Git hooks
|
7 |
|
8 | ## Getting Started
|
9 | This plugin requires Grunt `~0.4.1`
|
10 |
|
11 | If you haven't used [Grunt](http://gruntjs.com/) before, be sure to check out the [Getting Started](http://gruntjs.com/getting-started) guide, as it explains how to create a [Gruntfile](http://gruntjs.com/sample-gruntfile) as well as install and use Grunt plugins. Once you're familiar with that process, you may install this plugin with this command:
|
12 |
|
13 | ```shell
|
14 | npm install grunt-githooks --save-dev
|
15 | ```
|
16 |
|
17 | Once the plugin has been installed, it may be enabled inside your Gruntfile with this line of JavaScript:
|
18 |
|
19 | ```js
|
20 | grunt.loadNpmTasks('grunt-githooks');
|
21 | ```
|
22 |
|
23 | ## The "githooks" task
|
24 |
|
25 | ### Overview
|
26 | In your project's Gruntfile, add a section named `githooks` to the data object passed into `grunt.initConfig()`.
|
27 |
|
28 | ```js
|
29 | grunt.initConfig({
|
30 | githooks: {
|
31 | options: {
|
32 | // Task-specific options go here.
|
33 | },
|
34 | all: {
|
35 | options: {
|
36 | // Target-specific options go here
|
37 | },
|
38 | // Hook definitions go there
|
39 | }
|
40 | },
|
41 | })
|
42 | ```
|
43 |
|
44 | #### Defining a few hooks
|
45 |
|
46 | Hooks are listed as keys of your target configuration.
|
47 | **Any key other than `option`** is considered the name of a hook you want to create.
|
48 | The simplest way to define a hook is to provide a **space-separated list of the tasks you want the hook to run as the value**.
|
49 |
|
50 | For example:
|
51 | ```js
|
52 | grunt.initConfig({
|
53 | githooks: {
|
54 | all: {
|
55 | // Will run the jshint and test:unit tasks at every commit
|
56 | 'pre-commit': 'jshint test:unit',
|
57 | }
|
58 | }
|
59 | });
|
60 | ```
|
61 |
|
62 | The plugin warns you if the name matches one of the [hooks announced in the Git documentation](https://www.kernel.org/pub/software/scm/git/docs/githooks.html).
|
63 | It will still create the hook, though, in case Git introduces new hooks in the future.
|
64 |
|
65 | #### Hook specific options
|
66 |
|
67 | If you need to override a few options for a given hook only, you can *use and Object instead of a String*.
|
68 | The `taskNames` property will then correspond to the tasks you want to run.
|
69 | Any other key will be merged into the options.
|
70 |
|
71 | ```js
|
72 | grunt.initConfig({
|
73 | githooks: {
|
74 | all: {
|
75 | options: {
|
76 | template: 'path/to/a/template'
|
77 | },
|
78 | // Will bind the jshint and test:unit tasks
|
79 | // with the template specified above
|
80 | 'pre-commit': 'jshint test:unit',
|
81 |
|
82 | // Will bind the bower:install task
|
83 | // with a specific template
|
84 | 'post-merge': {
|
85 | taskNames: 'bower:install',
|
86 | template: 'path/to/another/template'
|
87 | }
|
88 | }
|
89 | }
|
90 | })
|
91 | ```
|
92 |
|
93 | #### Working with existing hooks
|
94 |
|
95 | If you happen to have existing hooks in your hook folder, the plugin *appends the code launching Grunt* at the end of your hooks.
|
96 | You can also insert marker comments in your hooks to specify exactly where you want them inserted.
|
97 | Your existing hook would look something like this:
|
98 |
|
99 | ```js
|
100 | // Some code run before Grunt starts
|
101 |
|
102 | // GRUNT-GITHOOKS START // GRUNT-GITHOOKS END
|
103 |
|
104 | // Some code run after Grunt starts
|
105 | ```
|
106 |
|
107 | The markers get automatically inserted when the plugin appends code, so hooks get updated cleanly the next time you run `grunt githooks`.
|
108 |
|
109 | #### Customising hook output
|
110 |
|
111 | By default, the plugin generate NodeJS scripts for the hooks.
|
112 | Reasonning behind this is that creating Shell scripts won't work well for people using Windows.
|
113 | Plus, NodeJS is already installed as Grunt kinda needs it.
|
114 | However, you're not tied to it and you can customise the generated script entirely. In case of a Shell script:
|
115 |
|
116 | ```js
|
117 | grunt.initConfig({
|
118 | githooks: {
|
119 | all: {
|
120 | options: {
|
121 | // Customize the hashbang to say 'Shell script'
|
122 | hashbang: '#!/bin/sh',
|
123 | // Plugin comes in with a sheel script template already. Handy, innit?
|
124 | template: './node_modules/grunt-githooks/templates/shell.hb',
|
125 | // Customize the markers so comments start with #
|
126 | startMarker: '## LET THE FUN BEGIN',
|
127 | endMarker: '## PARTY IS OVER'
|
128 | }
|
129 | }
|
130 | }
|
131 | });
|
132 | ```
|
133 |
|
134 | In the template, you've got access to the following variables:
|
135 |
|
136 | - *command*: `String` with the name of the command to run
|
137 | - *task*: `String` with the name of the tasks to be run
|
138 | - *args*: `String` with the list of arguments to provide to the task
|
139 | - *gruntfileDirectory*: Absolute path to the directory containing the Gruntfile
|
140 | - *preventExit*: Flag telling if the hook should avoid exiting after the grunt task
|
141 | - *options*: The options provided to the grunt-githooks task to create this hook
|
142 |
|
143 | #### Extending the plugin
|
144 |
|
145 | Pretty annoying when you're using a library that's missing the exact extension point you need to tweak its functionalities?
|
146 | `grunt-githooks` is based on a lot of small functions and most of them are exposed so you can override them.
|
147 | If you need feel, free to tinker with the internals (at your own risk though ;)). Could be something along:
|
148 |
|
149 | ```js
|
150 | var gruntGithooks = require('grunt-githooks/tasks/githooks');
|
151 |
|
152 | var originalFunction = gruntGithooks.internals.Hook.prototype.getHookContent;
|
153 | gruntGithooks.internals.Hook.prototype.getHookContent = function () {
|
154 | console.log('Loading content of an existing hook');
|
155 | originalFunction.apply(this, arguments);
|
156 | };
|
157 | ```
|
158 |
|
159 | ### Options
|
160 |
|
161 | #### command
|
162 | Type: `String`
|
163 | Defaults: `grunt`
|
164 |
|
165 | The command that will be run by the hook. This has initally been introduced to
|
166 | allow specifying the full path to Grunt in some specific cases. It can also allow
|
167 | you to run another command than Grunt if you need.
|
168 |
|
169 | #### taskNames
|
170 | Type: `String`
|
171 |
|
172 | A space separated list of tasks that will be run by the hook.
|
173 |
|
174 | #### args
|
175 | Type: `String`
|
176 |
|
177 | Additional CLI arguments to be passed to the command run by the hook.
|
178 |
|
179 | #### hashbang
|
180 | Type: `String`
|
181 | Defaults: `'#!/usr/bin/env node'`
|
182 |
|
183 | The hashbang that will be used at the top of the hook script file. If a hook
|
184 | already exist, the hashbang will be used to check if its ok to append/insert
|
185 | code in it (to avoid inserting Node code in a Python hook for example).
|
186 |
|
187 | #### template
|
188 | Type: `String`
|
189 |
|
190 | Path to the Handlebars template used to generate the code that will run Grunt
|
191 | in the hook. Default template is the `node.js.hb` file located in the `templates` folder of the plugin.
|
192 | It also contains a `shell.hb` file with the template for a shell script hook.
|
193 |
|
194 | > **Note**: Handlebars escapes HTML special characters if you use only two curly braces to insert,
|
195 | > a variable in your template. Make sure you use three `{{{my_var}}}` if you need to insert variable
|
196 | > that containt quotes, chevrons or anything that would be HTML escaped
|
197 |
|
198 | #### startMarker
|
199 | Type: `String`
|
200 | Default: `'// GRUNT-GITHOOKS START'`
|
201 |
|
202 | #### endMarker
|
203 | Type: `String`
|
204 | Default: `'// GRUNT-GITHOOKS END'`
|
205 |
|
206 | `startMarker` and `endMarker` are markers the plugin use to know where to insert code if a hook already exist.
|
207 | If the existing hook doesn't have these markers, the code will simply be appended.
|
208 |
|
209 | #### preventExit
|
210 | Type: `Boolean`
|
211 | Default `false`
|
212 |
|
213 | By default, the inserted code will exit the process after Grunt has run, using a -1 exit code if the task(s) failed.
|
214 | If you're inserting the code running Grunt in the middle of an existing hook,
|
215 | you might want to disable this so any code after what was inserted by the plugin runs.
|
216 |
|
217 | #### dest
|
218 | Type: `String`
|
219 | Default value: `'.git/hooks'`
|
220 |
|
221 | This option allows you to choose in which directory the hooks should be generated.
|
222 | Comes in handy if your Gruntfile is not at the root of your Git project.
|
223 |
|
224 |
|
225 | ## Contributing
|
226 |
|
227 | In lieu of a formal styleguide, take care to maintain the existing coding style. Add unit tests for any new or changed functionality. Lint and test your code using [Grunt](http://gruntjs.com/).
|
228 |
|
229 |
|
230 | ## Release History
|
231 |
|
232 | - 2013-12-17 v0.3.1 [Escaping fix in the hooks templates](https://github.com/rhumaric/grunt-githooks/pull/15) by @gyoshev.
|
233 | - 2013-11-13 v0.3.0 New *command* option to specify which command to run, in case full path to Grunt is needed. NodeJS template now uses new `escapeBackslashes` helper to make sure backslashes ('\') are properly escaped when written in the hook
|
234 | - 2013-10-05 v0.2.0 New *args* option to specify arguments to hooked task. Bugfix to allow running grunt when the Gruntfile is not at the root of the project.
|
235 | - 2013-09-02 v0.1.0 Initial functionnalities
|
236 |
|
237 |
|
238 | [![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/rhumaric/grunt-githooks/trend.png)](https://bitdeli.com/free "Bitdeli Badge")
|
239 |
|