Skip to content

Commit afe54a6

Browse files
committed
Add gemfile option for setting Bundler Gemfile
There is a real need for specifying which versions of a gem Overcommit hooks should use during the hook run, especially when those versions are not yet released or older versions that what is currently on the machine (since Ruby will always load the latest version by default). Add support for a `gemfile` option which allows the developer to specify the explicit list of gems and their respective versions to use during hook runs.
1 parent 168fa9e commit afe54a6

File tree

4 files changed

+94
-4
lines changed

4 files changed

+94
-4
lines changed

CHANGELOG.md

+2
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@
1414
lists and the operating system command length limit
1515
* Add `modified_files` helper to `PostCheckout` hooks
1616
* Add `rewritten_commits` helper to `PostRewrite` hooks
17+
* Add `gemfile` option to configuration file which allows a `Gemfile` to be
18+
loaded by Bundler to enforce particular gem versions during hook runs
1719

1820
## 0.26.0
1921

README.md

+43
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ repository (but unlike regular Git hooks, are stored in source control).
2525
* [Configuration](#configuration)
2626
* [Hooks](#hooks)
2727
* [Hook Categories](#hook-categories)
28+
* [Gemfile](#gemfile)
2829
* [Plugin Directory](#plugin-directory)
2930
* [Signature Verification](#signature-verification)
3031
* [Built-In Hooks](#built-in-hooks)
@@ -61,6 +62,10 @@ Depending on the hooks you enable/disable for your repository, you'll need to
6162
ensure your development environment already has those dependencies installed.
6263
Most hooks will display a warning if a required executable isn't available.
6364

65+
If you are using Bundler to manage your Ruby gem dependencies, you'll likely
66+
want to use the [`gemfile`](#gemfile) option to control which gem versions are
67+
available during your hook runs.
68+
6469
## Installation
6570

6671
`overcommit` is installed via [RubyGems](https://rubygems.org/):
@@ -239,6 +244,44 @@ hooks.
239244
Again, you can consult the [default configuration](config/default.yml) for
240245
detailed examples of how the `ALL` hook can be used.
241246

247+
### Gemfile
248+
249+
You may want to enforce the version of Overcommit or other gems that you use in
250+
your git hooks. This can be done by specifying the `gemfile` option in your
251+
`.overcommit.yml`.
252+
253+
The `gemfile` option tells Overcommit to load the specified file with
254+
[Bundler](http://bundler.io/), the standard gem dependency manager for Ruby.
255+
This is useful if you would like to:
256+
257+
- Enforce a specific version of Overcommit to use for all hook runs
258+
(or to use a version from the master branch that has not been released yet)
259+
- Enforce a specific version or unreleased branch is used for a gem you want
260+
to use in your git hooks
261+
262+
Loading a Bundler context necessarily adds a startup delay to your hook runs
263+
as Bundler parses the specified `Gemfile` and checks that the dependencies are
264+
satisfied. Thus for projects with many gems this can introduce a noticeable
265+
delay.
266+
267+
The recommended workaround is to create a separate `Gemfile` in the root of
268+
your repository (call it `.overcommit_gems.rb`), and include only the gems that
269+
your Overcommit hooks need in order to run. Generate the associated lock file
270+
by running:
271+
272+
```bash
273+
bundle install --gemfile=.overcommit_gems.rb
274+
```
275+
276+
...and commit `.overcommit_gems.rb` and the resulting
277+
`.overcommit_gems.rb.lock` file to your repository. Set your `gemfile` option
278+
to `.overcommit_gems.rb`, and you're all set.
279+
280+
Using a smaller Gemfile containing only the gems used by your Overcommit hooks
281+
significantly reduces the startup delay in your hook runs. It is thus the
282+
recommended approach unless your project has a relatively small number of gems
283+
in your `Gemfile`.
284+
242285
### Plugin Directory
243286

244287
You can change the directory that project-specific hooks are loaded from via

config/default.yml

+31
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,37 @@
22
#
33
# This is an opinionated list of which hooks are valuable to run and what their
44
# out-of-the-box settings should be.
5+
#-------------------------------------------------------------------------------
6+
7+
# Loads Bundler context from a Gemfile. If false, does nothing (default).
8+
#
9+
# Specifying a Gemfile for Bundler to load allows you to control which gems are
10+
# available in the load path (i.e. loadable via `require`) within your hook
11+
# runs. Note that having a Gemfile requires you to include `overcommit` itself
12+
# in your Gemfile (otherwise Overcommit can't load itself!).
13+
#
14+
# This is useful if you want to:
15+
#
16+
# - Enforce a specific version of Overcommit to use for all hook runs
17+
# (or to use a version from the master branch that has not been released yet)
18+
# - Enforce a specific version or unreleased branch is used for a gem you want
19+
# to use in your git hooks
20+
#
21+
# WARNING: This makes your hook runs slower, but you can work around this!
22+
#
23+
# Loading a Bundler context necessarily adds a startup delay to your hook runs
24+
# as Bundler parses the Gemfile and checks that the dependencies are satisfied.
25+
# Thus for projects with many gems this can introduce a noticeable delay.
26+
#
27+
# The recommended workaround is to create a separate Gemfile in the root of your
28+
# repository (call it `.overcommit_gems.rb`), and include only the gems that
29+
# your Overcommit hooks need in order to run. This significantly reduces the
30+
# startup delay in your hook runs. Make sure to commit both
31+
# `.overcommit_gems.rb` and the resulting `.overcommit_gems.rb.lock` file to
32+
# your repository, and then set the `gemfile` option below to the name you gave
33+
# the file.
34+
# (Generate lock file by running `bundle install --gemfile=.overcommit_gems.rb`)
35+
gemfile: false
536

637
# Where to store hook plugins specific to a repository. These are loaded in
738
# addition to the default hooks Overcommit comes with. The location is relative

template-dir/hooks/overcommit-hook

+18-4
Original file line numberDiff line numberDiff line change
@@ -25,13 +25,27 @@ if hook_type == 'overcommit-hook'
2525
exit 64 # EX_USAGE
2626
end
2727

28+
# Check if Overcommit should invoke a Bundler context for loading gems
29+
require 'yaml'
30+
if gemfile = YAML.load_file('.overcommit.yml')['gemfile'] rescue nil
31+
ENV['BUNDLE_GEMFILE'] = gemfile
32+
require 'bundler/setup'
33+
end
34+
2835
begin
2936
require 'overcommit'
3037
rescue LoadError
31-
puts 'This repository contains hooks installed by Overcommit, but the ' \
32-
"overcommit gem is not installed.\n" \
33-
'Install it with `gem install overcommit`.'
34-
exit
38+
if gemfile
39+
puts 'You have specified the `gemfile` option in your Overcommit ' \
40+
'configuration but have not added the `overcommit` gem to ' \
41+
"#{gemfile}."
42+
else
43+
puts 'This repository contains hooks installed by Overcommit, but the ' \
44+
"`overcommit` gem is not installed.\n" \
45+
'Install it with `gem install overcommit`.'
46+
end
47+
48+
exit 64 # EX_USAGE
3549
end
3650

3751
begin

0 commit comments

Comments
 (0)